60 lines
1.4 KiB
TypeScript
60 lines
1.4 KiB
TypeScript
import Link from "next/link";
|
|
import { cn } from "@/lib/utils";
|
|
import type { LucideIcon } from "lucide-react";
|
|
|
|
interface StatCardProps {
|
|
label: string;
|
|
value: string | number;
|
|
icon: LucideIcon;
|
|
color?: "blue" | "green" | "orange" | "red";
|
|
href?: string;
|
|
}
|
|
|
|
const COLOR_MAP = {
|
|
blue: {
|
|
bg: "bg-primary-50",
|
|
icon: "text-primary-600",
|
|
iconBg: "bg-primary-100",
|
|
},
|
|
green: {
|
|
bg: "bg-success-50",
|
|
icon: "text-success",
|
|
iconBg: "bg-success-100",
|
|
},
|
|
orange: {
|
|
bg: "bg-warning-50",
|
|
icon: "text-warning",
|
|
iconBg: "bg-warning-100",
|
|
},
|
|
red: {
|
|
bg: "bg-danger-50",
|
|
icon: "text-danger",
|
|
iconBg: "bg-danger-100",
|
|
},
|
|
};
|
|
|
|
export function StatCard({ label, value, icon: Icon, color = "blue", href }: StatCardProps) {
|
|
const colors = COLOR_MAP[color];
|
|
|
|
const card = (
|
|
<div
|
|
className={cn(
|
|
"rounded-lg border border-neutral-200 bg-white p-5 flex items-center gap-4",
|
|
href && "hover:border-neutral-300 transition-colors"
|
|
)}
|
|
>
|
|
<div className={cn("flex h-12 w-12 shrink-0 items-center justify-center rounded-xl", colors.iconBg)}>
|
|
<Icon className={cn("h-6 w-6", colors.icon)} />
|
|
</div>
|
|
<div>
|
|
<p className="text-2xl font-semibold text-neutral-900">{value}</p>
|
|
<p className="text-sm text-neutral-500 mt-0.5">{label}</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
if (href) {
|
|
return <Link href={href}>{card}</Link>;
|
|
}
|
|
return card;
|
|
}
|