48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
import type { LucideIcon } from 'lucide-react';
|
|
import { Card, CardContent } from './ui/Card';
|
|
import { cn } from '../lib/utils';
|
|
|
|
export function MetricCard({
|
|
title,
|
|
value,
|
|
subtitle,
|
|
icon: Icon,
|
|
trend,
|
|
className,
|
|
}: {
|
|
title: string;
|
|
value: string | number;
|
|
subtitle?: string;
|
|
icon?: LucideIcon;
|
|
trend?: { value: string; positive?: boolean };
|
|
className?: string;
|
|
}) {
|
|
return (
|
|
<Card className={cn('', className)}>
|
|
<CardContent className="p-5">
|
|
<div className="flex items-start justify-between">
|
|
<div className="space-y-1">
|
|
<p className="text-sm font-medium text-slate-500">{title}</p>
|
|
<p className="text-2xl font-bold text-slate-900">{value}</p>
|
|
{subtitle && <p className="text-xs text-slate-500">{subtitle}</p>}
|
|
{trend && (
|
|
<p
|
|
className={cn(
|
|
'text-xs font-medium',
|
|
trend.positive ? 'text-emerald-600' : 'text-red-600',
|
|
)}
|
|
>
|
|
{trend.value}
|
|
</p>
|
|
)}
|
|
</div>
|
|
{Icon && (
|
|
<div className="rounded-lg bg-primary-50 p-2.5 text-primary-600">
|
|
<Icon className="h-5 w-5" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|