Waiter PWA fixes, and extra feautures. Also added Emergency Mode, search etc
This commit is contained in:
@@ -52,9 +52,8 @@ function NotificationBanner({ message, onAck }) {
|
||||
|
||||
export function NotificationProvider({ children }) {
|
||||
const { token, user } = useAuthStore()
|
||||
const [pendingMessages, setPendingMessages] = useState([]) // unacked
|
||||
const [recentMessages, setRecentMessages] = useState([]) // last 10 (for history)
|
||||
const pollRef = useRef(null)
|
||||
const [pendingMessages, setPendingMessages] = useState([])
|
||||
const [recentMessages, setRecentMessages] = useState([])
|
||||
|
||||
const fetchUnread = useCallback(async () => {
|
||||
if (!token || !user) return
|
||||
@@ -72,14 +71,62 @@ export function NotificationProvider({ children }) {
|
||||
} catch { }
|
||||
}, [token, user?.id])
|
||||
|
||||
// Initial load + 5s fallback poll (SSE is primary, poll is safety net)
|
||||
useEffect(() => {
|
||||
if (!token || !user) return
|
||||
fetchUnread()
|
||||
fetchRecent()
|
||||
pollRef.current = setInterval(fetchUnread, 2000)
|
||||
return () => clearInterval(pollRef.current)
|
||||
const id = setInterval(fetchUnread, 5000)
|
||||
return () => clearInterval(id)
|
||||
}, [token, user?.id])
|
||||
|
||||
// SSE message_sent events → add to pending without polling
|
||||
useEffect(() => {
|
||||
function onSSEEvent(e) {
|
||||
const { type, data } = e.detail
|
||||
if (type !== 'message_sent') return
|
||||
if (!user) return
|
||||
|
||||
// Check if this message targets us (empty = broadcast)
|
||||
const targets = data.target_waiter_ids || []
|
||||
if (targets.length > 0 && !targets.includes(user.id)) return
|
||||
|
||||
const msg = {
|
||||
id: data.id,
|
||||
sender_id: data.sender_id,
|
||||
sender_name: data.sender_name,
|
||||
body: data.body,
|
||||
table_ids: data.table_ids,
|
||||
created_at: data.created_at,
|
||||
acked_by: [],
|
||||
}
|
||||
|
||||
setPendingMessages(prev => {
|
||||
if (prev.find(m => m.id === msg.id)) return prev
|
||||
return [msg, ...prev]
|
||||
})
|
||||
setRecentMessages(prev => {
|
||||
if (prev.find(m => m.id === msg.id)) return prev
|
||||
return [msg, ...prev].slice(0, 10)
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener('sse-event', onSSEEvent)
|
||||
return () => window.removeEventListener('sse-event', onSSEEvent)
|
||||
}, [user?.id])
|
||||
|
||||
// Fallback: re-fetch unread when SSE reconnects (catches any messages missed during gap)
|
||||
useEffect(() => {
|
||||
function onSSEConnect() {
|
||||
fetchUnread()
|
||||
fetchRecent()
|
||||
}
|
||||
// SSEProvider fires this via setOnline — we listen to the connection store indirectly
|
||||
// through the backend-coming-back-online signal that SSEProvider dispatches
|
||||
window.addEventListener('sse-reconnected', onSSEConnect)
|
||||
return () => window.removeEventListener('sse-reconnected', onSSEConnect)
|
||||
}, [fetchUnread, fetchRecent])
|
||||
|
||||
async function ackMessage(messageId) {
|
||||
try {
|
||||
await client.post(`/api/messages/${messageId}/ack`)
|
||||
@@ -91,7 +138,7 @@ export function NotificationProvider({ children }) {
|
||||
const unreadCount = pendingMessages.length
|
||||
|
||||
return (
|
||||
<NotificationContext.Provider value={{ pendingMessages, recentMessages, unreadCount, ackMessage, fetchRecent }}>
|
||||
<NotificationContext.Provider value={{ pendingMessages, recentMessages, unreadCount, ackMessage, fetchRecent, fetchUnread }}>
|
||||
{children}
|
||||
|
||||
{/* Floating banner stack (max 3 visible) */}
|
||||
|
||||
Reference in New Issue
Block a user