Files
xenia-pos-local/waiter_pwa/src/store/connectionStore.js
bonamin 34ae328b0d feat: bump client-services (accumulated feature work + deploy fixes)
Snapshot of in-progress work across local_backend, manager_dashboard,
and waiter_pwa (pricing, chat, fiscal, prep zones, recovery codes, CRM,
inventory, permissions), plus the nginx/docker-compose deploy fixes for
the Unraid + NPM reverse-proxy setup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 10:00:14 +03:00

78 lines
2.7 KiB
JavaScript

import { create } from 'zustand'
/**
* Tracks live connection state.
*
* status:
* 'online' — server reachable, SSE connected, normal operation
* 'reconnecting' — blip detected, grace period (amber bar)
* 'offline' — confirmed unreachable, working from local DB (red bar)
*
* The old 'emergency' and 'lost' states are gone. The app now enters offline
* mode automatically — no user prompt needed.
*
* After 5 minutes offline the bar flashes to signal a serious problem.
*/
const GRACE_MS = 4_000 // how long to wait before declaring offline
const FLASH_MS = 5 * 60 * 1000 // 5 minutes before bar starts flashing
const useConnectionStore = create((set, get) => ({
status: 'online', // 'online' | 'reconnecting' | 'offline'
sseAlive: false, // true when SSE stream is actively connected
lostAt: null, // Date when connection was first lost
flashing: false, // true when offline > 5 min
_graceTimer: null,
_flashTimer: null,
setSseAlive: (alive) => set({ sseAlive: alive }),
setLost: () => {
const { status, _graceTimer } = get()
if (status === 'offline') return
if (status === 'reconnecting') return
const graceTimer = setTimeout(() => {
if (get().status !== 'reconnecting') return
const lostAt = get().lostAt
// Start the 5-min flash timer
const flashTimer = setTimeout(() => {
if (get().status === 'offline') set({ flashing: true })
}, FLASH_MS)
set({ status: 'offline', _graceTimer: null, _flashTimer: flashTimer })
}, GRACE_MS)
set({ status: 'reconnecting', lostAt: new Date(), _graceTimer: graceTimer })
},
setOnline: () => {
const { _graceTimer, _flashTimer } = get()
if (_graceTimer) clearTimeout(_graceTimer)
if (_flashTimer) clearTimeout(_flashTimer)
set({ status: 'online', lostAt: null, flashing: false, _graceTimer: null, _flashTimer: null })
},
// Convenience accessors
isOnline: () => get().status === 'online',
isOffline: () => get().status === 'offline' || get().status === 'reconnecting',
// Legacy compat — SSEContext still calls these
enterEmergency: () => {
// treated as manual offline entry (immediate, no grace period)
const { _graceTimer, _flashTimer } = get()
if (_graceTimer) clearTimeout(_graceTimer)
if (_flashTimer) clearTimeout(_flashTimer)
const flashTimer = setTimeout(() => {
if (get().status === 'offline') set({ flashing: true })
}, FLASH_MS)
set({ status: 'offline', lostAt: new Date(), flashing: false, _graceTimer: null, _flashTimer: flashTimer })
},
exitEmergency: () => get().setOnline(),
isEmergency: () => get().status === 'offline',
isLost: () => get().status === 'offline',
}))
export default useConnectionStore