import { useEffect, useMemo, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faHeadset, faPhoneVolume, faPause, faClock, faSparkles, faCalendarCheck, faClockRotateLeft } from '@fortawesome/pro-duotone-svg-icons';
import { PageHeader } from '@/components/layout/page-header';
import { Badge } from '@/components/base/badges/badges';
import { Table } from '@/components/application/table/table';
import { BargeControls } from '@/components/call-desk/barge-controls';
import { apiClient } from '@/lib/api-client';
import { useData } from '@/providers/data-provider';
import { formatShortDate } from '@/lib/format';
import { cx } from '@/utils/cx';
type ActiveCall = {
ucid: string;
agentId: string;
callerNumber: string;
callType: string;
startTime: string;
status: 'active' | 'on-hold';
};
type CallerContext = {
name: string;
phone: string;
source: string | null;
status: string | null;
interestedService: string | null;
aiSummary: string | null;
patientType: string | null;
leadId: string | null;
appointments: Array<{ id: string; scheduledAt: string; doctorName: string; department: string; status: string }>;
};
const formatDuration = (startTime: string): string => {
const seconds = Math.max(0, Math.floor((Date.now() - new Date(startTime).getTime()) / 1000));
const m = Math.floor(seconds / 60);
const s = seconds % 60;
return `${m}:${s.toString().padStart(2, '0')}`;
};
const KpiCard = ({ value, label, icon }: { value: string | number; label: string; icon: any }) => (
);
export const LiveMonitorPage = () => {
const [activeCalls, setActiveCalls] = useState([]);
const [loading, setLoading] = useState(true);
const [tick, setTick] = useState(0);
const [selectedCall, setSelectedCall] = useState(null);
const [callerContext, setCallerContext] = useState(null);
const [contextLoading, setContextLoading] = useState(false);
const { leads } = useData();
// Initial load + SSE stream for real-time active call updates
useEffect(() => {
// Initial snapshot
apiClient.get('/api/supervisor/active-calls', { silent: true })
.then(setActiveCalls)
.catch(() => {})
.finally(() => setLoading(false));
// SSE stream — receives update/remove events in real-time
const apiUrl = import.meta.env.VITE_API_URL ?? '';
const es = new EventSource(`${apiUrl}/api/supervisor/active-calls/stream`);
es.onmessage = (msg) => {
try {
const event = JSON.parse(msg.data) as { type: 'update' | 'remove'; call?: ActiveCall; ucid: string };
setActiveCalls(prev => {
if (event.type === 'remove') {
return prev.filter(c => c.ucid !== event.ucid);
}
if (event.type === 'update' && event.call) {
const exists = prev.find(c => c.ucid === event.ucid);
if (exists) {
return prev.map(c => c.ucid === event.ucid ? event.call! : c);
}
return [...prev, event.call];
}
return prev;
});
} catch {}
};
es.onerror = () => {
// SSE reconnects automatically; no-op
};
return () => es.close();
}, []);
// Clear selection if the selected call ended
useEffect(() => {
if (selectedCall && !activeCalls.find(c => c.ucid === selectedCall.ucid)) {
setSelectedCall(null);
setCallerContext(null);
}
}, [activeCalls, selectedCall]);
// Tick every second for duration display
useEffect(() => {
const interval = setInterval(() => setTick(t => t + 1), 1000);
return () => clearInterval(interval);
}, []);
const onHold = activeCalls.filter(c => c.status === 'on-hold').length;
const avgDuration = useMemo(() => {
if (activeCalls.length === 0) return '0:00';
const totalSec = activeCalls.reduce((sum, c) => {
return sum + Math.max(0, Math.floor((Date.now() - new Date(c.startTime).getTime()) / 1000));
}, 0);
const avg = Math.floor(totalSec / activeCalls.length);
return `${Math.floor(avg / 60)}:${(avg % 60).toString().padStart(2, '0')}`;
}, [activeCalls, tick]);
// Match caller to lead
const resolveCallerName = (phone: string): string | null => {
if (!phone) return null;
const clean = phone.replace(/\D/g, '');
const lead = leads.find(l => {
const lp = (l.contactPhone?.[0]?.number ?? '').replace(/\D/g, '');
return lp && (lp.endsWith(clean) || clean.endsWith(lp));
});
if (lead) {
return `${lead.contactName?.firstName ?? ''} ${lead.contactName?.lastName ?? ''}`.trim() || null;
}
return null;
};
// Fetch caller context when a call is selected
const handleSelectCall = (call: ActiveCall) => {
setSelectedCall(call);
setContextLoading(true);
setCallerContext(null);
const phoneClean = call.callerNumber.replace(/\D/g, '');
// Search for lead by phone
apiClient.graphql<{ leads: { edges: Array<{ node: any }> } }>(
`{ leads(first: 5, filter: { contactPhone: { primaryPhoneNumber: { like: "%${phoneClean.slice(-10)}" } } }) { edges { node {
id contactName { firstName lastName } source status interestedService aiSummary patientId
} } } }`,
).then(async (data) => {
const lead = data.leads.edges[0]?.node;
const name = lead
? `${lead.contactName?.firstName ?? ''} ${lead.contactName?.lastName ?? ''}`.trim()
: resolveCallerName(call.callerNumber) ?? 'Unknown Caller';
let appointments: CallerContext['appointments'] = [];
if (lead?.patientId) {
try {
const apptData = await apiClient.graphql<{ appointments: { edges: Array<{ node: any }> } }>(
`{ appointments(first: 5, filter: { patientId: { eq: "${lead.patientId}" } }, orderBy: [{ scheduledAt: DescNullsLast }]) { edges { node {
id scheduledAt doctorName department status
} } } }`,
);
appointments = apptData.appointments.edges.map(e => e.node);
} catch { /* best effort */ }
}
setCallerContext({
name,
phone: call.callerNumber,
source: lead?.source ?? null,
status: lead?.status ?? null,
interestedService: lead?.interestedService ?? null,
aiSummary: lead?.aiSummary ?? null,
patientType: lead?.patientId ? 'RETURNING' : 'NEW',
leadId: lead?.id ?? null,
appointments,
});
}).catch(() => {
setCallerContext({
name: resolveCallerName(call.callerNumber) ?? 'Unknown Caller',
phone: call.callerNumber,
source: null, status: null, interestedService: null,
aiSummary: null, patientType: null, leadId: null, appointments: [],
});
}).finally(() => setContextLoading(false));
};
return (
<>
{/* Left panel — KPIs + call list */}
{/* KPI Cards */}
{/* Active Calls Table */}
Active Calls
{loading ? (
) : activeCalls.length === 0 ? (
No active calls
Active calls will appear here in real-time
) : (
{(call) => {
const callerName = resolveCallerName(call.callerNumber);
const typeLabel = call.callType === 'InBound' ? 'In' : 'Out';
const typeColor = call.callType === 'InBound' ? 'blue' : 'brand';
const isSelected = selectedCall?.ucid === call.ucid;
return (
handleSelectCall(call)}
>
{call.agentId}
{callerName && {callerName}}
{call.callerNumber}
{typeLabel}
{formatDuration(call.startTime)}
{call.status}
);
}}
)}
{/* Right panel — context + barge controls */}
{!selectedCall ? (
Select a call to monitor
Click on any active call to see context and connect
) : contextLoading ? (
Loading caller context...
) : (
{/* Caller header */}
{(callerContext?.name ?? '?')[0].toUpperCase()}
{callerContext?.name}
{callerContext?.phone}
{callerContext?.patientType && (
{callerContext.patientType === 'RETURNING' ? 'Returning' : 'New'}
)}
{/* Source + status */}
{(callerContext?.source || callerContext?.status) && (
{callerContext.source && (
{callerContext.source.replace(/_/g, ' ')}
)}
{callerContext.status && (
{callerContext.status.replace(/_/g, ' ')}
)}
)}
{callerContext?.interestedService && (
Interested in: {callerContext.interestedService}
)}
{/* AI Summary */}
{callerContext?.aiSummary && (
AI Insight
{callerContext.aiSummary}
)}
{/* Appointments */}
{callerContext?.appointments && callerContext.appointments.length > 0 && (
Appointments
{callerContext.appointments.map(appt => (
{appt.doctorName ?? 'Appointment'}
{appt.department && {appt.department}}
{appt.scheduledAt && (
— {formatShortDate(appt.scheduledAt)}
)}
{(appt.status ?? 'Scheduled').replace(/_/g, ' ').toLowerCase().replace(/\b\w/g, c => c.toUpperCase())}
))}
)}
{/* Call info */}
Current Call
Agent: {selectedCall.agentId}
Type: {selectedCall.callType === 'InBound' ? 'Inbound' : 'Outbound'}
Duration: {formatDuration(selectedCall.startTime)}
Status: {selectedCall.status}
{/* Barge Controls */}
{
// Keep selection visible but controls reset to idle/ended
}}
/>
)}
>
);
};