import { type ReactNode, useEffect, useRef, useState } from 'react'; import { ChevronRight } from 'lucide-react'; interface MetricCardProps { title: string; value: string | number; subtitle?: string; status?: 'good' | 'average' | 'warning'; statusText?: string; icon: ReactNode; chart?: ReactNode; details?: ReactNode; onClick?: () => void; className?: string; animationDelay?: number; horizontal?: boolean; } const statusColors: Record = { good: 'var(--success)', average: 'var(--warning)', warning: 'var(--warning)', }; export function MetricCard({ title, value, subtitle, status, statusText, icon, chart, details, onClick, className = '', animationDelay = 0, horizontal = false, }: MetricCardProps) { const [isVisible, setIsVisible] = useState(false); const cardRef = useRef(null); useEffect(() => { const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setTimeout(() => setIsVisible(true), animationDelay * 1000); } }, { threshold: 0.1 } ); if (cardRef.current) { observer.observe(cardRef.current); } return () => observer.disconnect(); }, [animationDelay]); const reveal = { opacity: isVisible ? 1 : 0, transform: isVisible ? 'translateY(0)' : 'translateY(12px)', transition: 'all 0.5s ease', } as const; const footer = (
{statusText && status ? ( {statusText} ) : null}{' '} {subtitle ?? 'Details'} {onClick ? ( ) : null}
); if (horizontal) { return (
{icon} {title}
{value}
{details ?
{details}
: null}
{footer}
{chart ? (
{chart}
) : null}
); } return (
{icon} {title}
{value}
{chart ?
{chart}
: null} {details ?
{details}
: null}
{footer}
); }