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(slug: 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(slug); async function fetchOnce(activeSlug: string) { try { const res = await fetch(`/api/v1/events/${encodeURIComponent(activeSlug)}/stats`, { headers: { 'Cache-Control': 'no-store' }, }); if (res.status === 304) 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 activeSlug = String(slug); fetchOnce(activeSlug); if (timer.current) window.clearInterval(timer.current); if (visible) { timer.current = window.setInterval(() => fetchOnce(activeSlug), 10_000); } return () => { if (timer.current) window.clearInterval(timer.current); }; }, [slug, visible, canPoll]); return { ...data, loading }; }