Show upcoming appointments for the rest of today and link each KPI card to its relevant dashboard tab. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import { Link } from '@/i18n/navigation';
|
|
import { Card } from '@/components/ui/shared/Card';
|
|
import type { KpiCardColor } from '@/components/today/widget-registry';
|
|
import type { LucideIcon } from 'lucide-react';
|
|
|
|
const colorClasses: Record<KpiCardColor, string> = {
|
|
blue: '!bg-purpose-visit-bg !text-purpose-visit-fg !border-purpose-visit-border',
|
|
yellow: '!bg-badge-warning-bg !text-badge-warning-fg !border-badge-warning-border',
|
|
green: '!bg-badge-success-bg !text-badge-success-fg !border-badge-success-border',
|
|
red: '!bg-badge-danger-bg !text-badge-danger-fg !border-badge-danger-border',
|
|
purple: '!bg-purpose-consultation-bg !text-purpose-consultation-fg !border-purpose-consultation-border',
|
|
default: '',
|
|
};
|
|
|
|
interface KpiCardProps {
|
|
title: string;
|
|
value: string;
|
|
subtitle?: string | null;
|
|
icon?: LucideIcon;
|
|
color?: KpiCardColor;
|
|
loading?: boolean;
|
|
href?: string;
|
|
}
|
|
|
|
export function KpiCard({
|
|
title,
|
|
value,
|
|
subtitle,
|
|
icon: Icon,
|
|
color = 'default',
|
|
loading = false,
|
|
href,
|
|
}: KpiCardProps) {
|
|
const card = (
|
|
<Card
|
|
className={`${colorClasses[color]} ${href && !loading ? 'transition-opacity hover:opacity-90' : ''}`}
|
|
>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<p className="text-sm font-medium">{title}</p>
|
|
{Icon ? <Icon className="h-4 w-4 shrink-0 opacity-80" aria-hidden /> : null}
|
|
</div>
|
|
{loading ? (
|
|
<div className="mt-2 h-8 w-16 animate-pulse rounded bg-current/10" />
|
|
) : (
|
|
<p className="text-2xl font-bold mt-2">{value}</p>
|
|
)}
|
|
{subtitle ? (
|
|
<p className="text-xs opacity-80 mt-1">{subtitle}</p>
|
|
) : null}
|
|
</Card>
|
|
);
|
|
|
|
if (href && !loading) {
|
|
return (
|
|
<Link href={href} className="block focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 rounded-[var(--radius-lg)]">
|
|
{card}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
return card;
|
|
}
|