Files
helix-engage/src/components/leads/aging-widget.tsx

72 lines
2.4 KiB
TypeScript

import { cx } from '@/utils/cx';
import { daysAgoFromNow } from '@/lib/format';
import type { Lead } from '@/types/entities';
interface AgingWidgetProps {
leads: Lead[];
}
type AgingBracket = {
label: string;
color: string;
barColor: string;
count: number;
};
export const AgingWidget = ({ leads }: AgingWidgetProps) => {
const leadsWithAge = leads.filter((l) => l.createdAt !== null);
const total = leadsWithAge.length || 1;
const freshCount = leadsWithAge.filter((l) => daysAgoFromNow(l.createdAt!) < 2).length;
const warmCount = leadsWithAge.filter((l) => {
const days = daysAgoFromNow(l.createdAt!);
return days >= 2 && days <= 5;
}).length;
const coldCount = leadsWithAge.filter((l) => daysAgoFromNow(l.createdAt!) > 5).length;
const brackets: AgingBracket[] = [
{
label: 'Fresh (<2 days)',
color: 'text-success-primary',
barColor: 'bg-success-solid',
count: freshCount,
},
{
label: 'Warm (2-5 days)',
color: 'text-warning-primary',
barColor: 'bg-warning-solid',
count: warmCount,
},
{
label: 'Cold (>5 days)',
color: 'text-error-primary',
barColor: 'bg-error-solid',
count: coldCount,
},
];
return (
<div>
<h3 className="mb-3 text-sm font-bold text-primary">Lead Aging</h3>
<div className="space-y-3">
{brackets.map((bracket) => (
<div key={bracket.label}>
<div className="mb-1 flex items-center justify-between">
<span className={cx('text-xs', bracket.color)}>{bracket.label}</span>
<span className={cx('text-sm font-bold', bracket.color)}>
{bracket.count}
</span>
</div>
<div className="h-2 overflow-hidden rounded-full bg-tertiary">
<div
className={cx('h-full rounded-full transition-all', bracket.barColor)}
style={{ width: `${(bracket.count / total) * 100}%` }}
/>
</div>
</div>
))}
</div>
</div>
);
};