mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-05-18 20:08:19 +00:00
57 lines
2.3 KiB
TypeScript
57 lines
2.3 KiB
TypeScript
import { cx } from '@/utils/cx';
|
|
import type { Campaign, Lead } from '@/types/entities';
|
|
|
|
interface ConversionFunnelProps {
|
|
campaign: Campaign;
|
|
leads: Lead[];
|
|
}
|
|
|
|
type FunnelStep = {
|
|
label: string;
|
|
count: number;
|
|
color: string;
|
|
};
|
|
|
|
export const ConversionFunnel = ({ campaign, leads }: ConversionFunnelProps) => {
|
|
const leadCount = campaign.leadCount ?? 0;
|
|
const contactedCount = campaign.contactedCount ?? 0;
|
|
const appointmentCount = leads.filter((l) => l.leadStatus === 'APPOINTMENT_SET').length;
|
|
const convertedCount = campaign.convertedCount ?? 0;
|
|
|
|
const steps: FunnelStep[] = [
|
|
{ label: 'Leads', count: leadCount, color: 'bg-brand-solid' },
|
|
{ label: 'Contacted', count: contactedCount, color: 'bg-brand-primary' },
|
|
{ label: 'Appointment Set', count: appointmentCount, color: 'bg-brand-primary_alt' },
|
|
{ label: 'Converted', count: convertedCount, color: 'bg-success-solid' },
|
|
];
|
|
|
|
const maxCount = Math.max(...steps.map((s) => s.count), 1);
|
|
|
|
return (
|
|
<div className="rounded-xl border border-secondary bg-primary p-4">
|
|
<h4 className="mb-3 text-sm font-bold text-primary">Conversion Funnel</h4>
|
|
<div className="space-y-2.5">
|
|
{steps.map((step) => {
|
|
const widthPercent = (step.count / maxCount) * 100;
|
|
return (
|
|
<div key={step.label} className="flex items-center gap-3">
|
|
<span className="w-24 shrink-0 text-xs text-tertiary">{step.label}</span>
|
|
<div className="flex-1">
|
|
<div className="h-5 rounded bg-secondary overflow-hidden">
|
|
<div
|
|
className={cx('h-full rounded transition-all duration-300', step.color)}
|
|
style={{ width: `${Math.max(widthPercent, 2)}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<span className="w-10 shrink-0 text-right text-xs font-bold text-primary">
|
|
{step.count}
|
|
</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|