import { type ReactNode, useEffect, useRef, useState } from '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; } 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 statusColors: Record = { good: '#5ee6a0', average: '#f2c94c', warning: '#f2c94c', }; // Horizontal layout for cards like Active User if (horizontal) { return (
{icon}
{title}
{value}
{subtitle && (
{subtitle}
)} {details &&
{details}
}
Details
{chart && (
{chart}
)}
); } // Standard vertical card layout - matching self.html exactly return (
{icon}
{title}
{value}
{(subtitle || statusText) && (
{statusText && status && ( {statusText} )}{' '} {subtitle}
)} {chart &&
{chart}
} {details &&
{details}
}
Details
); }