From 7f1e82acc2aaad5ef8a7f6e9f2b8587a5893bec3 Mon Sep 17 00:00:00 2001 From: Patrick Toal Date: Tue, 21 Apr 2026 19:38:57 -0400 Subject: [PATCH] feat: add caching for backend objects --- CLAUDE.md | 21 +++ app/app.vue | 75 ++++++++++- app/composables/useAppCache.ts | 74 +++++++++++ app/composables/useBookingDraft.ts | 26 ++++ app/composables/useOfflineStatus.ts | 10 ++ app/pages/reservations/create.vue | 122 +++++++++++------- app/pages/schedule.vue | 44 +++++-- ...4-20-edge-functions-auth-and-test-fixes.md | 0 ...26-04-21-project-brief-webawesome-spike.md | 55 ++++++++ docs/summaries/00-project-brief.md | 90 +++++++++++++ ...-04-21-historical-booking-offline-cache.md | 100 ++++++++++++++ playwright-report/index.html | 2 +- .../functions/create-reservation/index.ts | 18 ++- tests/integration/booking-constraints.test.ts | 62 +++++++++ 14 files changed, 637 insertions(+), 62 deletions(-) create mode 100644 app/composables/useAppCache.ts create mode 100644 app/composables/useBookingDraft.ts create mode 100644 app/composables/useOfflineStatus.ts rename docs/{summaries => archive/handoffs}/handoff-2026-04-20-edge-functions-auth-and-test-fixes.md (100%) create mode 100644 docs/archive/handoffs/handoff-2026-04-21-project-brief-webawesome-spike.md create mode 100644 docs/summaries/00-project-brief.md create mode 100644 docs/summaries/handoff-2026-04-21-historical-booking-offline-cache.md 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 @@