feat: Enhance reservation functionality
This commit is contained in:
47
CLAUDE.md
47
CLAUDE.md
@@ -31,6 +31,26 @@ You work with Patrick, a Solutions Architect, on the OYS Borrow a Boat app (oysq
|
||||
- `app/middleware/auth.ts` — global auth guard via useSupabaseUser()
|
||||
- Auth pages use `definePageMeta({ layout: false })` (effectively a no-op with IonRouterOutlet, but documents intent)
|
||||
|
||||
### Ionic + Nuxt Watch-outs
|
||||
Source: https://ionic.nuxtjs.org/get-started/watch-outs
|
||||
|
||||
**Never use Nuxt navigation components** — `<NuxtPage>`, `<NuxtLayout>`, `<NuxtLink>` are not integrated with this module. Use `<IonRouterOutlet>` and `useIonRouter()` / `router-link` prop on Ionic components instead.
|
||||
|
||||
**Every page must have `<IonPage>` as its root element** — required for Ionic page transitions and stack navigation.
|
||||
|
||||
**Route params: always import `useRoute` from `vue-router` directly** — Nuxt's auto-imported `useRoute()` always returns `params: {}` when used with IonRouterOutlet. This is a known bug with no upstream fix yet.
|
||||
```typescript
|
||||
import { useRoute, useRouter } from 'vue-router' // NOT Nuxt auto-import
|
||||
```
|
||||
|
||||
**`onMounted` / `onBeforeMount` are unreliable** — IonRouterOutlet preserves DOM elements rather than unmounting them, so mounted hooks may not fire when expected. Use Ionic lifecycle hooks (`onIonViewWillEnter`) instead. See Data Fetching Pattern below.
|
||||
|
||||
**`useHead()` requires workarounds** — not compatible out of the box with IonRouterOutlet's component persistence.
|
||||
|
||||
**`<keep-alive>`, `<transition>`, `<router-view>` do not work as expected** — IonRouterOutlet manages its own lifecycle; don't layer Vue's built-in equivalents on top of it.
|
||||
|
||||
**No SSR** — this app targets mobile/PWA; SSR is disabled (`ssr: false` in nuxt.config). Do not add SSR-dependent patterns.
|
||||
|
||||
### Auth
|
||||
- Supabase Auth — magic link + OTP only (no password auth)
|
||||
- `useSupabaseUser()` composable (from @nuxtjs/supabase)
|
||||
@@ -55,6 +75,33 @@ You work with Patrick, a Solutions Architect, on the OYS Borrow a Boat app (oysq
|
||||
- Ionicons only (`ionicons/icons`) — no PrimeIcons
|
||||
- Always import individual icon names from `ionicons/icons` (tree-shakeable)
|
||||
|
||||
### Data Fetching Pattern
|
||||
Every page that reads from Supabase **must** use this pattern. Do NOT use `onMounted` for data fetches.
|
||||
|
||||
**Why**: `onMounted` (and `watch(user, { immediate: true })`) fire during component setup — before `IonRouterOutlet` has populated `route.params` and before `@nuxtjs/supabase` has restored the session into the Supabase JS client. The fetch runs unauthenticated, RLS returns 0 rows, and the page shows empty/error state.
|
||||
|
||||
```typescript
|
||||
// Route params: always computed, never destructured at setup time
|
||||
const id = computed(() => route.params.id as string)
|
||||
|
||||
const user = useSupabaseUser()
|
||||
|
||||
async function load() {
|
||||
if (!user.value) return // guard: session not ready
|
||||
if (!id.value) return // guard: param pages only
|
||||
// ... fetch data
|
||||
}
|
||||
|
||||
// Fires when session becomes available (handles direct URL load / page refresh)
|
||||
watch([user, id], ([u, rid]) => { if (u && rid) load() }, { immediate: true })
|
||||
// Fires on every Ionic page activation (handles IonRouterOutlet page cache)
|
||||
onIonViewWillEnter(() => { if (user.value) load() })
|
||||
```
|
||||
|
||||
- For pages **without** a route param: omit `id` from the watch array, keep `watch(user, ...)`.
|
||||
- Reactive filter deps (e.g. `selectedDate`, `filterDateFrom`) use a separate `watch(dep, () => { if (user.value) fetch() })` — not `watch(dep, fetch)`, so they don't fire before the session is ready.
|
||||
- `onMounted` is still valid for **non-auth DOM setup** (e.g., `window.addEventListener`, breakpoint detection).
|
||||
|
||||
### Offline Cache
|
||||
- **Rule**: Every table/view read from Supabase must be written to `useAppCache` on success and read from it when offline.
|
||||
- **Composables**: `useAppCache` (localStorage, 24h TTL), `useOfflineStatus` (reactive `isOnline`)
|
||||
|
||||
Reference in New Issue
Block a user