feat: major dashboard & waiter PWA overhaul
- Manager dashboard: replaced monolithic DashboardTab/OperationsPage with new DashboardPage; added OrderDetailModal, ShiftDetailModal, DeleteConfirmModal, PaymentMethodModal; updated Sidebar routing and App navigation - Reports: reworked WorkDaySummary, OrderHistory, ShiftsOverview with detail modals - Backend routers: extended orders, reports, shifts, products, business_day endpoints; updated cloud_sync service - Waiter PWA: refreshed app icons, improved ConnectionLostModal UX, updated TableCard, SSEContext, connectionStore; added useProductCache hook; vite config tweaks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,26 +4,50 @@ import { create } from 'zustand'
|
||||
* Tracks the live connection state and emergency mode flag.
|
||||
*
|
||||
* States:
|
||||
* 'online' — server reachable, SSE connected, normal operation
|
||||
* 'lost' — server unreachable, modal shown (Wait / Emergency)
|
||||
* 'emergency' — user chose emergency mode, working from IndexedDB snapshot
|
||||
* 'online' — server reachable, SSE connected, normal operation
|
||||
* 'reconnecting' — connection blip detected; 5-second grace before showing full modal
|
||||
* 'lost' — grace period expired, modal shown (Wait / Emergency)
|
||||
* 'emergency' — user chose emergency mode, working from IndexedDB snapshot
|
||||
*/
|
||||
|
||||
const GRACE_MS = 5_000
|
||||
|
||||
const useConnectionStore = create((set, get) => ({
|
||||
status: 'online', // 'online' | 'lost' | 'emergency'
|
||||
lostAt: null, // Date when connection was lost
|
||||
status: 'online', // 'online' | 'reconnecting' | 'lost' | 'emergency'
|
||||
lostAt: null,
|
||||
_graceTimer: null,
|
||||
|
||||
setLost: () => {
|
||||
if (get().status === 'online') {
|
||||
set({ status: 'lost', lostAt: new Date() })
|
||||
}
|
||||
const { status, _graceTimer } = get()
|
||||
// Already lost or in emergency — no-op
|
||||
if (status === 'lost' || status === 'emergency') return
|
||||
// Already in grace period — don't restart the timer
|
||||
if (status === 'reconnecting') return
|
||||
|
||||
// Start grace period
|
||||
const timer = setTimeout(() => {
|
||||
// Only escalate if we're still in reconnecting (not recovered in the meantime)
|
||||
if (get().status === 'reconnecting') {
|
||||
set({ status: 'lost', _graceTimer: null })
|
||||
}
|
||||
}, GRACE_MS)
|
||||
|
||||
set({ status: 'reconnecting', lostAt: new Date(), _graceTimer: timer })
|
||||
},
|
||||
|
||||
setOnline: () => set({ status: 'online', lostAt: null }),
|
||||
setOnline: () => {
|
||||
const { _graceTimer } = get()
|
||||
if (_graceTimer) clearTimeout(_graceTimer)
|
||||
set({ status: 'online', lostAt: null, _graceTimer: null })
|
||||
},
|
||||
|
||||
enterEmergency: () => set({ status: 'emergency' }),
|
||||
enterEmergency: () => {
|
||||
const { _graceTimer } = get()
|
||||
if (_graceTimer) clearTimeout(_graceTimer)
|
||||
set({ status: 'emergency', _graceTimer: null })
|
||||
},
|
||||
|
||||
// Called when server comes back while in emergency mode — triggers sync then go online
|
||||
exitEmergency: () => set({ status: 'online', lostAt: null }),
|
||||
exitEmergency: () => set({ status: 'online', lostAt: null, _graceTimer: null }),
|
||||
|
||||
isOnline: () => get().status === 'online',
|
||||
isLost: () => get().status === 'lost',
|
||||
|
||||
Reference in New Issue
Block a user