import { useState, useCallback, useRef } from 'react'; import { TopBar } from '@/components/layout/top-bar'; import { CallSimulator } from '@/components/call-desk/call-simulator'; import { IncomingCallCard } from '@/components/call-desk/incoming-call-card'; import { CallLog } from '@/components/call-desk/call-log'; import { DailyStats } from '@/components/call-desk/daily-stats'; import { useAuth } from '@/providers/auth-provider'; import { useData } from '@/providers/data-provider'; import { useLeads } from '@/hooks/use-leads'; import type { Call, CallDisposition, LeadStatus } from '@/types/entities'; type CallState = 'idle' | 'ringing' | 'active' | 'completed'; const isToday = (dateStr: string): boolean => { const d = new Date(dateStr); const now = new Date(); return ( d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth() && d.getDate() === now.getDate() ); }; const dispositionToStatus: Partial> = { APPOINTMENT_BOOKED: 'APPOINTMENT_SET', FOLLOW_UP_SCHEDULED: 'CONTACTED', INFO_PROVIDED: 'CONTACTED', NO_ANSWER: 'NEW', WRONG_NUMBER: 'LOST', CALLBACK_REQUESTED: 'LOST', }; export const CallDeskPage = () => { const { user } = useAuth(); const { calls, leadActivities, campaigns, addCall } = useData(); const { leads, updateLead } = useLeads(); const [callState, setCallState] = useState('idle'); const [activeLead, setActiveLead] = useState['leads'][number] | null>(null); const [completedDisposition, setCompletedDisposition] = useState(null); const callStartRef = useRef(null); const ringingTimerRef = useRef | null>(null); const completedTimerRef = useRef | null>(null); const todaysCalls = calls.filter( (c) => c.agentName === user.name && c.startedAt !== null && isToday(c.startedAt), ); const handleSimulateCall = useCallback(() => { if (callState !== 'idle') return; // Prefer leads with aiSummary, fall back to any lead const leadsWithAi = leads.filter((l) => l.aiSummary !== null); const pool = leadsWithAi.length > 0 ? leadsWithAi : leads; if (pool.length === 0) return; const randomLead = pool[Math.floor(Math.random() * pool.length)]; setActiveLead(randomLead); setCallState('ringing'); setCompletedDisposition(null); ringingTimerRef.current = setTimeout(() => { setCallState('active'); callStartRef.current = new Date(); }, 1500); }, [callState, leads]); const handleDisposition = useCallback( (disposition: CallDisposition, notes: string) => { if (activeLead === null) return; const now = new Date(); const startedAt = callStartRef.current ?? now; const durationSeconds = Math.floor((now.getTime() - startedAt.getTime()) / 1000); const newCall: Call = { id: `call-sim-${Date.now()}`, createdAt: startedAt.toISOString(), callDirection: 'INBOUND', callStatus: 'COMPLETED', callerNumber: activeLead.contactPhone, agentName: user.name, startedAt: startedAt.toISOString(), endedAt: now.toISOString(), durationSeconds: Math.max(durationSeconds, 60), recordingUrl: null, disposition, callNotes: notes || null, patientId: null, appointmentId: null, leadId: activeLead.id, leadName: `${activeLead.contactName?.firstName ?? ''} ${activeLead.contactName?.lastName ?? ''}`.trim() || 'Unknown', leadPhone: activeLead.contactPhone?.[0]?.number ?? undefined, leadService: activeLead.interestedService ?? undefined, }; addCall(newCall); const newStatus = dispositionToStatus[disposition]; if (newStatus !== undefined) { updateLead(activeLead.id, { leadStatus: newStatus, lastContactedAt: now.toISOString(), contactAttempts: (activeLead.contactAttempts ?? 0) + 1, }); } setCompletedDisposition(disposition); setCallState('completed'); completedTimerRef.current = setTimeout(() => { setCallState('idle'); setActiveLead(null); setCompletedDisposition(null); }, 3000); }, [activeLead, user.name, addCall, updateLead], ); return (
); };