import { useEffect, useRef, useState } from 'react'; export type EventStats = { onlineGuests: number; tasksSolved: number; latestPhotoAt: string | null; }; type StatsResponse = { online_guests?: number; tasks_solved?: number; latest_photo_at?: string; }; export function usePollStats(eventKey: string | null | undefined) { const [data, setData] = useState({ onlineGuests: 0, tasksSolved: 0, latestPhotoAt: null }); const [loading, setLoading] = useState(true); const timer = useRef(null); const [visible, setVisible] = useState( typeof document !== 'undefined' ? document.visibilityState === 'visible' : true ); const canPoll = Boolean(eventKey); async function fetchOnce(activeKey: string) { try { const res = await fetch(`/api/v1/events/${encodeURIComponent(activeKey)}/stats`, { headers: { 'Cache-Control': 'no-store' }, }); if (res.status === 304) return; if (!res.ok) { if (res.status === 404) { setData({ onlineGuests: 0, tasksSolved: 0, latestPhotoAt: null }); } return; } const json: StatsResponse = await res.json(); setData({ onlineGuests: json.online_guests ?? 0, tasksSolved: json.tasks_solved ?? 0, latestPhotoAt: json.latest_photo_at ?? null, }); } finally { setLoading(false); } } useEffect(() => { const onVis = () => setVisible(document.visibilityState === 'visible'); document.addEventListener('visibilitychange', onVis); return () => document.removeEventListener('visibilitychange', onVis); }, []); useEffect(() => { if (!canPoll) { setLoading(false); return; } setLoading(true); const activeKey = String(eventKey); fetchOnce(activeKey); if (timer.current) window.clearInterval(timer.current); if (visible) { timer.current = window.setInterval(() => fetchOnce(activeKey), 10_000); } return () => { if (timer.current) window.clearInterval(timer.current); }; }, [eventKey, visible, canPoll]); return { ...data, loading }; }