// ============================================================================ // public/screens/monitor.jsx — Live Call Monitor (Phase 5) // ---------------------------------------------------------------------------- // Connects to GET /api/calls/live (SSE) for real-time active calls. // Shows cards with waveform, status, duration timer, agent info. // ============================================================================ function MonitorScreen() { const [activeCalls, setActive] = React.useState([]); const [connected, setConnected] = React.useState(false); const [error, setError] = React.useState(null); const [stats, setStats] = React.useState(null); const esRef = React.useRef(null); const timerRef = React.useRef(null); // SSE connection React.useEffect(() => { const base = (window.VOAIS_API_BASE || ""); const sess = VoaisAPI.getSession(); if (!sess?.token) return; // SSE doesn't support custom headers easily, so we'll poll instead // (browser EventSource can't set Authorization header) let alive = true; const poll = async () => { if (!alive) return; try { const r = await VoaisAPI.get("/api/calls?status=in_progress&limit=50&page=1"); if (r.ok && r.data?.ok) { // Also get initiated + ringing const r2 = await VoaisAPI.get("/api/calls?status=initiated&limit=50&page=1"); const r3 = await VoaisAPI.get("/api/calls?status=ringing&limit=50&page=1"); const r4 = await VoaisAPI.get("/api/calls?status=answered&limit=50&page=1"); const all = [ ...(r.data.calls || []), ...(r2.ok ? r2.data.calls || [] : []), ...(r3.ok ? r3.data.calls || [] : []), ...(r4.ok ? r4.data.calls || [] : []), ]; // Deduplicate by id const seen = new Set(); const unique = all.filter(c => { if (seen.has(c.id)) return false; seen.add(c.id); return true; }); setActive(unique); setConnected(true); } } catch (e) { console.warn("[monitor] poll error:", e.message); } }; poll(); const interval = setInterval(poll, 3000); // Also load stats VoaisAPI.get("/api/calls/stats").then(r => { if (r.ok && r.data?.ok) setStats(r.data.stats); }); return () => { alive = false; clearInterval(interval); }; }, []); return (
When campaigns start dialing, active calls will appear here in real-time.