feat: add caching for backend objects
This commit is contained in:
@@ -149,6 +149,9 @@ import {
|
||||
todayToronto, toDateToronto, addDays,
|
||||
fmtTime, fmtDateLong, fmtDayHeader, weekDates, utcRange,
|
||||
} from '~/utils/toronto'
|
||||
import { useAppCache } from '~/composables/useAppCache'
|
||||
import { useOfflineStatus } from '~/composables/useOfflineStatus'
|
||||
import { useBookingDraft } from '~/composables/useBookingDraft'
|
||||
|
||||
type Boat = Database['public']['Tables']['boats']['Row']
|
||||
type Interval = Database['public']['Tables']['intervals']['Row']
|
||||
@@ -167,6 +170,9 @@ definePageMeta({ layout: false, middleware: ['auth'] })
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const supabase = useSupabaseClient() as any
|
||||
const cache = useAppCache()
|
||||
const { isOnline } = useOfflineStatus()
|
||||
const { set: setDraft } = useBookingDraft()
|
||||
|
||||
// ── Responsive ──────────────────────────────────────────────
|
||||
const isMobile = ref(true)
|
||||
@@ -200,23 +206,42 @@ const intervals = ref<Interval[]>([])
|
||||
const slotViews = ref<SlotView[]>([])
|
||||
|
||||
async function fetchBoats() {
|
||||
if (!isOnline.value) {
|
||||
const cached = cache.peek<Boat[]>('boats')
|
||||
if (cached) boats.value = cached
|
||||
return
|
||||
}
|
||||
const { data } = await supabase.from('boats').select('*').order('name')
|
||||
boats.value = data ?? []
|
||||
if (data) cache.set('boats', data)
|
||||
}
|
||||
|
||||
async function fetchSchedule() {
|
||||
loading.value = true
|
||||
const dates = visibleDates.value
|
||||
const { from, to } = utcRange(dates[0]!, dates[dates.length - 1]!)
|
||||
const wk = cache.weekKey(dates[0]!)
|
||||
|
||||
if (!isOnline.value) {
|
||||
const cachedIntervals = cache.peek<Interval[]>(`intervals:${wk}`)
|
||||
const cachedSlots = cache.peek<SlotView[]>(`slots:${wk}`)
|
||||
if (cachedIntervals) intervals.value = cachedIntervals
|
||||
if (cachedSlots) slotViews.value = cachedSlots
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
|
||||
const { from, to } = utcRange(dates[0]!, dates[dates.length - 1]!)
|
||||
const [intRes, slotRes] = await Promise.all([
|
||||
supabase.from('intervals').select('*').gte('start_time', from).lte('start_time', to),
|
||||
supabase.from('reservation_slots').select('*').gte('start_time', from).lte('start_time', to),
|
||||
])
|
||||
|
||||
intervals.value = intRes.data ?? []
|
||||
slotViews.value = slotRes.data ?? []
|
||||
loading.value = false
|
||||
intervals.value = intRes.data ?? []
|
||||
slotViews.value = slotRes.data ?? []
|
||||
loading.value = false
|
||||
|
||||
if (intRes.data) cache.set(`intervals:${wk}`, intRes.data)
|
||||
if (slotRes.data) cache.set(`slots:${wk}`, slotRes.data)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -284,14 +309,9 @@ function slotLabelShort(slot: SlotBlock): string {
|
||||
}
|
||||
|
||||
function bookSlot(slot: SlotBlock) {
|
||||
router.push({
|
||||
path: '/reservations/create',
|
||||
query: {
|
||||
boatId: slot.boatId,
|
||||
startTime: slot.startTime,
|
||||
endTime: slot.endTime,
|
||||
},
|
||||
})
|
||||
const boat = boats.value.find(b => b.id === slot.boatId)
|
||||
if (boat) setDraft(boat, slot.startTime, slot.endTime)
|
||||
router.push('/reservations/create')
|
||||
}
|
||||
|
||||
function slotTitle(slot: SlotBlock): string {
|
||||
|
||||
Reference in New Issue
Block a user