Files
helix-engage/src/components/campaigns/kpi-strip.tsx
2026-03-16 15:01:00 +05:30

89 lines
3.2 KiB
TypeScript

import { cx } from '@/utils/cx';
import { formatCurrency } from '@/lib/format';
import type { Campaign } from '@/types/entities';
interface KpiStripProps {
campaign: Campaign;
}
type KpiItem = {
label: string;
value: string;
subText: string;
subColor: string;
};
export const KpiStrip = ({ campaign }: KpiStripProps) => {
const leadCount = campaign.leadCount ?? 0;
const contactedCount = campaign.contactedCount ?? 0;
const convertedCount = campaign.convertedCount ?? 0;
const spentMicros = campaign.amountSpent?.amountMicros ?? 0;
const budgetMicros = campaign.budget?.amountMicros ?? 0;
const currencyCode = campaign.amountSpent?.currencyCode ?? 'INR';
const contactRate = leadCount > 0 ? ((contactedCount / leadCount) * 100).toFixed(1) : '0.0';
const conversionRate = leadCount > 0 ? ((convertedCount / leadCount) * 100).toFixed(1) : '0.0';
const budgetPercent = budgetMicros > 0 ? ((spentMicros / budgetMicros) * 100).toFixed(0) : '--';
const costPerLead = leadCount > 0 ? formatCurrency(spentMicros / leadCount, currencyCode) : '--';
const cac = convertedCount > 0 ? formatCurrency(spentMicros / convertedCount, currencyCode) : '--';
const items: KpiItem[] = [
{
label: 'Total Leads',
value: String(leadCount),
subText: `${campaign.impressionCount ?? 0} impressions`,
subColor: 'text-tertiary',
},
{
label: 'Contacted',
value: String(contactedCount),
subText: `${contactRate}% contact rate`,
subColor: 'text-success-primary',
},
{
label: 'Converted',
value: String(convertedCount),
subText: `${conversionRate}% conversion`,
subColor: 'text-success-primary',
},
{
label: 'Spent',
value: formatCurrency(spentMicros, currencyCode),
subText: `${budgetPercent}% of budget`,
subColor: Number(budgetPercent) > 90 ? 'text-error-primary' : 'text-warning-primary',
},
{
label: 'Cost / Lead',
value: costPerLead,
subText: 'avg per lead',
subColor: 'text-tertiary',
},
{
label: 'CAC',
value: cac,
subText: 'per conversion',
subColor: 'text-tertiary',
},
];
return (
<div className="flex items-stretch border-b border-secondary bg-primary px-7 py-4">
{items.map((item, index) => (
<div
key={item.label}
className={cx(
'flex flex-1 flex-col justify-center px-4',
index === 0 && 'pl-0',
index === items.length - 1 && 'pr-0',
index < items.length - 1 && 'border-r border-tertiary',
)}
>
<p className="text-xl font-bold text-primary">{item.value}</p>
<p className="text-xs font-medium uppercase text-quaternary">{item.label}</p>
<p className={cx('mt-0.5 text-xs', item.subColor)}>{item.subText}</p>
</div>
))}
</div>
);
};