Spaces:
Sleeping
Sleeping
| import React from "react"; | |
| import { cn } from "@/lib/utils"; | |
| import { LucideIcon } from "lucide-react"; | |
| import { Card, CardContent } from "@/components/ui/card"; | |
| interface StatsCardProps { | |
| title: string; | |
| value: string | number; | |
| icon?: LucideIcon; | |
| iconColor?: string; | |
| change?: { | |
| value: number; | |
| positive: boolean; | |
| }; | |
| className?: string; | |
| iconClassName?: string; | |
| } | |
| const StatsCard = ({ | |
| title, | |
| value, | |
| icon: Icon, | |
| iconColor, | |
| change, | |
| className, | |
| iconClassName, | |
| }: StatsCardProps) => { | |
| return ( | |
| <Card className={cn("overflow-hidden hover-scale", className)}> | |
| <CardContent className="p-6"> | |
| <div className="flex items-center justify-between"> | |
| <div> | |
| <p className="text-sm font-medium text-muted-foreground">{title}</p> | |
| <h3 className="text-2xl font-bold mt-1">{value}</h3> | |
| {change && ( | |
| <p className={cn( | |
| "text-xs font-medium mt-1", | |
| change.positive ? "text-green-500" : "text-red-500" | |
| )}> | |
| {change.positive ? "+" : "-"}{Math.abs(change.value)}% | |
| </p> | |
| )} | |
| </div> | |
| {Icon && ( | |
| <div | |
| className={cn( | |
| "h-10 w-10 rounded-full flex items-center justify-center", | |
| iconColor ? `bg-${iconColor}-100` : "bg-primary/10", | |
| iconClassName | |
| )} | |
| > | |
| <Icon className={cn( | |
| "h-5 w-5", | |
| iconColor ? `text-${iconColor}-500` : "text-primary" | |
| )} /> | |
| </div> | |
| )} | |
| </div> | |
| </CardContent> | |
| </Card> | |
| ); | |
| }; | |
| export default StatsCard; | |