mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
feat: build Lead Workspace page with KPIs, source grid, lead cards, and sidebar widgets
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
93
src/components/leads/kpi-cards.tsx
Normal file
93
src/components/leads/kpi-cards.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import { cx } from '@/utils/cx';
|
||||
import type { Lead } from '@/types/entities';
|
||||
|
||||
interface KpiCardsProps {
|
||||
leads: Lead[];
|
||||
}
|
||||
|
||||
type KpiCard = {
|
||||
label: string;
|
||||
value: number;
|
||||
delta: string;
|
||||
deltaColor: string;
|
||||
isHero: boolean;
|
||||
};
|
||||
|
||||
export const KpiCards = ({ leads }: KpiCardsProps) => {
|
||||
const newCount = leads.filter((l) => l.leadStatus === 'NEW').length;
|
||||
const assignedCount = leads.filter((l) => l.assignedAgent !== null).length;
|
||||
const contactedCount = leads.filter((l) => l.leadStatus === 'CONTACTED').length;
|
||||
const convertedCount = leads.filter((l) => l.leadStatus === 'CONVERTED').length;
|
||||
|
||||
const cards: KpiCard[] = [
|
||||
{
|
||||
label: 'New Leads Today',
|
||||
value: newCount,
|
||||
delta: '+12% vs yesterday',
|
||||
deltaColor: 'text-success-primary',
|
||||
isHero: true,
|
||||
},
|
||||
{
|
||||
label: 'Assigned to CC',
|
||||
value: assignedCount,
|
||||
delta: '85% assigned',
|
||||
deltaColor: 'text-brand-secondary',
|
||||
isHero: false,
|
||||
},
|
||||
{
|
||||
label: 'Contacted',
|
||||
value: contactedCount,
|
||||
delta: '+8% vs yesterday',
|
||||
deltaColor: 'text-success-primary',
|
||||
isHero: false,
|
||||
},
|
||||
{
|
||||
label: 'Converted',
|
||||
value: convertedCount,
|
||||
delta: '+3 this week',
|
||||
deltaColor: 'text-warning-primary',
|
||||
isHero: false,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex gap-3">
|
||||
{cards.map((card) => (
|
||||
<div
|
||||
key={card.label}
|
||||
className={cx(
|
||||
'rounded-2xl p-5 transition hover:shadow-md',
|
||||
card.isHero
|
||||
? 'flex-[1.3] bg-brand-solid text-white'
|
||||
: 'flex-1 border border-secondary bg-primary',
|
||||
)}
|
||||
>
|
||||
<p
|
||||
className={cx(
|
||||
'text-xs font-medium uppercase tracking-wider',
|
||||
card.isHero ? 'text-white/70' : 'text-quaternary',
|
||||
)}
|
||||
>
|
||||
{card.label}
|
||||
</p>
|
||||
<p
|
||||
className={cx(
|
||||
'mt-1 text-display-sm font-bold',
|
||||
card.isHero ? 'text-white' : 'text-primary',
|
||||
)}
|
||||
>
|
||||
{card.value}
|
||||
</p>
|
||||
<p
|
||||
className={cx(
|
||||
'mt-1 text-xs',
|
||||
card.isHero ? 'text-white/80' : card.deltaColor,
|
||||
)}
|
||||
>
|
||||
{card.delta}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user