mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
feat: build CC Agent Call Desk with CTI simulation, AI insights, disposition form, and call log
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
77
src/components/call-desk/call-log.tsx
Normal file
77
src/components/call-desk/call-log.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Badge } from '@/components/base/badges/badges';
|
||||
import { Button } from '@/components/base/buttons/button';
|
||||
import { ArrowRight } from '@untitledui/icons';
|
||||
import { formatShortDate } from '@/lib/format';
|
||||
import type { Call, CallDisposition } from '@/types/entities';
|
||||
|
||||
interface CallLogProps {
|
||||
calls: Call[];
|
||||
}
|
||||
|
||||
const dispositionConfig: Record<CallDisposition, { label: string; color: 'success' | 'brand' | 'blue-light' | 'warning' | 'gray' | 'error' }> = {
|
||||
APPOINTMENT_BOOKED: { label: 'Booked', color: 'success' },
|
||||
FOLLOW_UP_SCHEDULED: { label: 'Follow-up', color: 'brand' },
|
||||
INFO_PROVIDED: { label: 'Info', color: 'blue-light' },
|
||||
NO_ANSWER: { label: 'No Answer', color: 'warning' },
|
||||
WRONG_NUMBER: { label: 'Wrong #', color: 'gray' },
|
||||
CALLBACK_REQUESTED: { label: 'Not Interested', color: 'error' },
|
||||
};
|
||||
|
||||
const formatDuration = (seconds: number | null): string => {
|
||||
if (seconds === null || seconds === 0) return '0 min';
|
||||
const minutes = Math.round(seconds / 60);
|
||||
return `${minutes} min`;
|
||||
};
|
||||
|
||||
export const CallLog = ({ calls }: CallLogProps) => {
|
||||
return (
|
||||
<div className="rounded-2xl border border-secondary bg-primary">
|
||||
<div className="flex items-center justify-between border-b border-secondary px-5 py-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-bold text-primary">Today's Calls</span>
|
||||
<Badge size="sm" color="gray">{calls.length}</Badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{calls.length > 0 ? (
|
||||
<div className="divide-y divide-secondary">
|
||||
{calls.map((call) => {
|
||||
const config = call.disposition !== null
|
||||
? dispositionConfig[call.disposition]
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={call.id}
|
||||
className="flex items-center gap-3 px-5 py-3"
|
||||
>
|
||||
<span className="w-20 shrink-0 text-xs text-quaternary">
|
||||
{call.startedAt !== null ? formatShortDate(call.startedAt) : '—'}
|
||||
</span>
|
||||
<span className="min-w-0 flex-1 truncate text-sm font-medium text-primary">
|
||||
{call.leadName ?? call.callerNumber?.[0]?.number ?? 'Unknown'}
|
||||
</span>
|
||||
{config !== null && (
|
||||
<Badge size="sm" color={config.color}>{config.label}</Badge>
|
||||
)}
|
||||
<span className="w-12 shrink-0 text-right text-xs text-quaternary">
|
||||
{formatDuration(call.durationSeconds)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<p className="text-sm text-quaternary">No calls handled today</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="border-t border-secondary px-5 py-3">
|
||||
<Button href="/call-history" color="link-color" size="sm" iconTrailing={ArrowRight}>
|
||||
View Full History
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user