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) => (
);
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 (
);
}
if (totalCalls === 0 && !loading) {
return (
No data found for "{agentName}"
This agent has no call records.
);
}
return (
{/* Agent header + back button */}
{/* KPI row */}
{/* Call log table */}
{agentCalls.length === 0 ? (
) : (
{(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'}
);
}}
)}
);
};