mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
import { cx } from '@/utils/cx';
|
|
import type { Lead } from '@/types/entities';
|
|
|
|
interface SourceBreakdownProps {
|
|
leads: Lead[];
|
|
}
|
|
|
|
const sourceColors: Record<string, string> = {
|
|
FACEBOOK_AD: 'bg-brand-solid',
|
|
GOOGLE_AD: 'bg-success-solid',
|
|
INSTAGRAM: 'bg-error-solid',
|
|
GOOGLE_MY_BUSINESS: 'bg-warning-solid',
|
|
WEBSITE: 'bg-fg-brand-primary',
|
|
REFERRAL: 'bg-fg-tertiary',
|
|
WHATSAPP: 'bg-success-solid',
|
|
WALK_IN: 'bg-fg-quaternary',
|
|
PHONE: 'bg-fg-secondary',
|
|
OTHER: 'bg-fg-disabled',
|
|
};
|
|
|
|
const sourceLabel = (source: string): string =>
|
|
source.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
|
|
export const SourceBreakdown = ({ leads }: SourceBreakdownProps) => {
|
|
const sourceCounts = leads.reduce<Record<string, number>>((acc, lead) => {
|
|
const source = lead.leadSource ?? 'OTHER';
|
|
acc[source] = (acc[source] ?? 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
|
|
const sorted = Object.entries(sourceCounts).sort(([, a], [, b]) => b - a);
|
|
const maxCount = sorted.length > 0 ? sorted[0][1] : 1;
|
|
|
|
if (sorted.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className="rounded-xl border border-secondary bg-primary p-4">
|
|
<h4 className="mb-3 text-sm font-bold text-primary">Lead Sources</h4>
|
|
<div className="space-y-2">
|
|
{sorted.map(([source, count]) => {
|
|
const widthPercent = (count / maxCount) * 100;
|
|
return (
|
|
<div key={source} className="flex items-center gap-3">
|
|
<span className="w-28 shrink-0 truncate text-xs text-tertiary">
|
|
{sourceLabel(source)}
|
|
</span>
|
|
<div className="flex-1">
|
|
<div className="h-4 rounded bg-secondary overflow-hidden">
|
|
<div
|
|
className={cx(
|
|
'h-full rounded transition-all duration-300',
|
|
sourceColors[source] ?? 'bg-fg-disabled',
|
|
)}
|
|
style={{ width: `${Math.max(widthPercent, 4)}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<span className="w-8 shrink-0 text-right text-xs font-bold text-primary">
|
|
{count}
|
|
</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|