diff --git a/CLAUDE.md b/CLAUDE.md index d6fbab7..4b7b8d4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -55,6 +55,27 @@ 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) +### 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`) +- **Pattern** for any data fetch: + ```typescript + const cache = useAppCache() + const { isOnline } = useOfflineStatus() + + if (!isOnline.value) { + const cached = cache.peek('my-key') + if (cached) data.value = cached + return + } + const { data: fresh } = await supabase.from('my_table').select('*') + data.value = fresh ?? [] + if (fresh) cache.set('my-key', fresh) + ``` +- **Schedule data** is keyed by ISO week Monday: `cache.weekKey(utcIso)` → use keys `intervals:{monday}` and `slots:{monday}`. +- **Realtime**: `app/app.vue` subscribes to `reservations`, `intervals`, and `boats` changes and patches the cache in real time. When adding a new table subscription, add it to the `app-cache-sync` channel in `app.vue`. +- **Cross-page navigation state** (not persistence): use `useBookingDraft` as a pattern — module-level `ref` set by the source page, consumed (`take()`) by the destination page. Do not use query params for structured objects. + ## Rules 1. Do not mix unrelated project contexts in one session. diff --git a/app/app.vue b/app/app.vue index 177149d..690a4da 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,5 +1,11 @@