Initial commit adds core UI components, including layout elements, form controls, and navigation elements, along with the main application structure and routing. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 99f0fce6-9386-489a-9632-1d81223cab44 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/99f0fce6-9386-489a-9632-1d81223cab44/nGJAldO
38 lines
1.1 KiB
TypeScript
38 lines
1.1 KiB
TypeScript
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { LucideIcon } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface KPICardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
title: string;
|
|
value: string | number;
|
|
icon: LucideIcon;
|
|
trend?: {
|
|
value: string;
|
|
isPositive: boolean;
|
|
};
|
|
}
|
|
|
|
export function KPICard({ title, value, icon: Icon, trend, className, ...props }: KPICardProps) {
|
|
return (
|
|
<Card className={cn("hover-elevate", className)} {...props}>
|
|
<CardHeader className="flex flex-row items-center justify-between gap-2 space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium text-muted-foreground">
|
|
{title}
|
|
</CardTitle>
|
|
<Icon className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-semibold">{value}</div>
|
|
{trend && (
|
|
<p className={cn(
|
|
"text-xs mt-1",
|
|
trend.isPositive ? "text-[hsl(140,60%,45%)]" : "text-destructive"
|
|
)}>
|
|
{trend.value}
|
|
</p>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|