45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { ReactNode } from "react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface MetricCardProps {
|
|
title: string;
|
|
value: string | number;
|
|
subtitle?: string;
|
|
icon: ReactNode;
|
|
status?: "success" | "warning" | "error";
|
|
className?: string;
|
|
}
|
|
|
|
export function MetricCard({
|
|
title,
|
|
value,
|
|
subtitle,
|
|
icon,
|
|
status,
|
|
className,
|
|
}: MetricCardProps) {
|
|
return (
|
|
<div className={cn("metric-card animate-fade-in", className)}>
|
|
<div className="flex items-start justify-between mb-3">
|
|
<div className="p-2.5 rounded-lg bg-primary/10 text-primary">
|
|
{icon}
|
|
</div>
|
|
{status && (
|
|
<span
|
|
className={cn("status-dot", {
|
|
"status-connected": status === "success",
|
|
"status-warning": status === "warning",
|
|
"status-error": status === "error",
|
|
})}
|
|
/>
|
|
)}
|
|
</div>
|
|
<p className="text-muted-foreground text-sm mb-1">{title}</p>
|
|
<p className="text-2xl font-semibold text-foreground">{value}</p>
|
|
{subtitle && (
|
|
<p className="text-muted-foreground text-xs mt-1">{subtitle}</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|