"use client"; import React, { useEffect, useState } from "react"; import { ArrowUp, ArrowDown, Activity } from "lucide-react"; interface StatCardProps { label: string; value: number | string; trend?: "up" | "down" | "neutral"; trendLabels?: { label: string; value: string; }; previous?: number; delta?: number; goodWhen?: "up" | "down"; period?: string; format?: "number" | "currency" | "percent"; color?: string; animated?: boolean; className?: string; } export function StatCard({ label, value, trend = "neutral", trendLabels, previous, delta, goodWhen = "up", period, format = "number", color, animated = true, className, }: StatCardProps) { const [displayValue, setDisplayValue] = useState( typeof value === "number" ? 0 : value ); // Count-up animation useEffect(() => { if (!animated || typeof value !== "number") return; let start = 0; const end = value; const duration = 1000; const startTime = Date.now(); const animate = () => { const elapsed = Date.now() - startTime; const progress = Math.min(elapsed / duration, 1); const current = start + (end - start) * progress; setDisplayValue(current); if (progress < 1) { requestAnimationFrame(animate); } }; animate(); }, [value, animated]); const formatValue = (val: number | string) => { if (typeof val === "string") return val; if (format === "currency") return new Intl.NumberFormat("en-KE", { style: "currency", currency: "KES", }).format(val); if (format === "percent") return `${val}%`; return val.toLocaleString(); }; const isPositive = delta != null ? delta >= 0 : trend === "up"; const isGood = goodWhen === "up" ? isPositive : !isPositive; const trendColor = isGood ? "var(--color-accent)" : "var(--color-error)"; const trendBg = isGood ? "rgba(16, 185, 129, 0.12)" : "rgba(239, 68, 68, 0.12)"; const showDelta = delta != null || trendLabels?.value; const deltaText = delta != null ? `${isPositive ? "+" : ""}${delta.toLocaleString()}` : trendLabels?.value ?? ""; const sparklineColor = color || "var(--color-primary)"; // Simple sparkline data (mock) const sparklinePoints = [30, 50, 40, 70, 60, 90, 75, 110]; return (
{label}
{formatValue(displayValue)}
{period}
)} {/* Sparkline */}