Files
sam-react-prod/src/components/organisms/StatCards.tsx

77 lines
2.3 KiB
TypeScript
Raw Normal View History

"use client";
import { Card, CardContent } from "@/components/ui/card";
import { LucideIcon } from "lucide-react";
interface StatCardData {
label: string;
sublabel?: string;
value: string | number;
icon?: LucideIcon;
iconColor?: string;
trend?: {
value: string;
isPositive: boolean;
};
onClick?: () => void;
isActive?: boolean;
}
interface StatCardsProps {
stats: StatCardData[];
}
export function StatCards({ stats }: StatCardsProps) {
const count = stats.length;
const gridClass =
count >= 5
? 'grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-2'
: 'grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2';
return (
<div className={gridClass}>
{stats.map((stat, index) => {
const Icon = stat.icon;
const isClickable = !!stat.onClick;
return (
<Card
key={index}
className={`flex-1 min-w-0 transition-colors ${
isClickable ? 'cursor-pointer hover:border-primary/50' : ''
} ${
stat.isActive ? 'border-primary bg-primary/5' : ''
}`}
onClick={stat.onClick}
>
<CardContent className="p-2 md:p-3">
<div className="flex items-center justify-between">
<div className="flex-1 min-w-0">
<p className="text-[10px] md:text-xs text-muted-foreground mb-0.5 uppercase tracking-wide truncate">
{stat.label}
{stat.sublabel && (
<span className="ml-2 normal-case tracking-normal">{stat.sublabel}</span>
)}
</p>
<p className="font-bold text-base md:text-lg truncate">
{stat.value}
</p>
{stat.trend && (
<p className={`text-[9px] md:text-[10px] mt-0.5 font-medium ${stat.trend.isPositive ? 'text-green-600' : 'text-red-600'}`}>
{stat.trend.value}
</p>
)}
</div>
{Icon && (
<Icon
className={`w-6 h-6 md:w-8 md:h-8 opacity-15 flex-shrink-0 ${stat.iconColor || 'text-blue-600'}`}
/>
)}
</div>
</CardContent>
</Card>
);
})}
</div>
);
}