import { useMemo } from 'react'; import { Link, useParams } from 'react-router'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faArrowLeft, faPhone, faPhoneArrowDownLeft, faPhoneArrowUpRight, faPhoneMissed, faClock, faPercent, faPhoneArrowDown, faPhoneArrowUp, faPhoneXmark, faUserHeadset, } from '@fortawesome/pro-duotone-svg-icons'; import type { IconDefinition } from '@fortawesome/fontawesome-svg-core'; import { Avatar } from '@/components/base/avatar/avatar'; import { Badge } from '@/components/base/badges/badges'; import { Button } from '@/components/base/buttons/button'; import { Table, TableCard } from '@/components/application/table/table'; import { TopBar } from '@/components/layout/top-bar'; import { formatShortDate, formatPhone, getInitials } from '@/lib/format'; import { useData } from '@/providers/data-provider'; import type { Call, CallDirection, CallDisposition } from '@/types/entities'; type KpiCardProps = { label: string; value: number | string; icon: IconDefinition; iconColor: string; iconBg: string; }; const KpiCard = ({ label, value, icon, iconColor, iconBg }: KpiCardProps) => (
{label} {value}
); const formatDuration = (seconds: number): string => { if (seconds < 60) return `${seconds}s`; const mins = Math.floor(seconds / 60); const secs = seconds % 60; return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`; }; const formatPercent = (value: number): string => { if (isNaN(value) || !isFinite(value)) return '0%'; return `${Math.round(value)}%`; }; const formatPhoneDisplay = (call: Call): string => { if (call.callerNumber && call.callerNumber.length > 0) { return formatPhone(call.callerNumber[0]); } return '\u2014'; }; const dispositionConfig: Record = { APPOINTMENT_BOOKED: { label: 'Appt Booked', color: 'success' }, FOLLOW_UP_SCHEDULED: { label: 'Follow-up', color: 'brand' }, INFO_PROVIDED: { label: 'Info Provided', color: 'blue-light' }, NO_ANSWER: { label: 'No Answer', color: 'warning' }, WRONG_NUMBER: { label: 'Wrong Number', color: 'gray' }, CALLBACK_REQUESTED: { label: 'Callback', color: 'brand' }, }; const DirectionIcon = ({ direction, status }: { direction: CallDirection | null; status: Call['callStatus'] }) => { if (status === 'MISSED') { return ; } if (direction === 'OUTBOUND') { return ; } return ; }; export const AgentDetailPage = () => { const { id } = useParams<{ id: string }>(); const { calls, leads, loading } = useData(); const agentName = id ? decodeURIComponent(id) : ''; const agentCalls = useMemo( () => calls .filter((c) => c.agentName === agentName) .sort((a, b) => { const dateA = a.startedAt ? new Date(a.startedAt).getTime() : 0; const dateB = b.startedAt ? new Date(b.startedAt).getTime() : 0; return dateB - dateA; }), [calls, agentName], ); // Build lead name map for enrichment const leadNameMap = useMemo(() => { const map = new Map(); for (const lead of leads) { if (lead.id && lead.contactName) { const name = `${lead.contactName.firstName ?? ''} ${lead.contactName.lastName ?? ''}`.trim(); if (name) map.set(lead.id, name); } } return map; }, [leads]); // KPI calculations const totalCalls = agentCalls.length; const inboundCalls = agentCalls.filter((c) => c.callDirection === 'INBOUND').length; const outboundCalls = agentCalls.filter((c) => c.callDirection === 'OUTBOUND').length; const missedCalls = agentCalls.filter((c) => c.callStatus === 'MISSED').length; const completedCalls = agentCalls.filter((c) => (c.durationSeconds ?? 0) > 0); const totalDuration = completedCalls.reduce((sum, c) => sum + (c.durationSeconds ?? 0), 0); const avgHandle = completedCalls.length > 0 ? Math.round(totalDuration / completedCalls.length) : 0; const booked = agentCalls.filter((c) => c.disposition === 'APPOINTMENT_BOOKED').length; const conversion = totalCalls > 0 ? (booked / totalCalls) * 100 : 0; const nameParts = agentName.split(' '); const initials = getInitials(nameParts[0] ?? '', nameParts[1] ?? ''); if (loading) { return (

Loading...

); } if (totalCalls === 0 && !loading) { return (

No data found for "{agentName}"

This agent has no call records.

); } return (
{/* Agent header + back button */}

{agentName}

Agent

{/* KPI row */}
{/* Call log table */} {agentCalls.length === 0 ? (

No calls found.

) : ( {(call) => { const patientName = call.leadName ?? leadNameMap.get(call.leadId ?? '') ?? 'Unknown'; const phoneDisplay = formatPhoneDisplay(call); const durationStr = call.durationSeconds !== null && call.durationSeconds > 0 ? formatDuration(call.durationSeconds) : '\u2014'; const dispositionCfg = call.disposition !== null ? dispositionConfig[call.disposition] : null; return ( {patientName} {phoneDisplay} {durationStr} {dispositionCfg ? ( {dispositionCfg.label} ) : ( {'\u2014'} )} {call.startedAt ? formatShortDate(call.startedAt) : '\u2014'} ); }}
)}
); };