"use client"; import { useEffect, useRef } from "react"; import Link from "next/link"; import { AlertTriangle, Clock, CheckCircle } from "lucide-react"; import type { DeadlineSummary } from "@/lib/types"; function AnimatedCount({ value }: { value: number }) { const ref = useRef(null); const prevValue = useRef(value); useEffect(() => { const el = ref.current; if (!el || prevValue.current === value) return; el.classList.remove("animate-count-up"); void el.offsetWidth; el.classList.add("animate-count-up"); prevValue.current = value; }, [value]); return ( {value} ); } interface Props { data: DeadlineSummary; } export function DeadlineTrafficLights({ data }: Props) { const safe = data ?? { overdue_count: 0, due_this_week: 0, due_next_week: 0, ok_count: 0 }; const cards = [ { key: "overdue" as const, label: "Überfällig", count: safe.overdue_count ?? 0, icon: AlertTriangle, href: "/fristen?status=overdue", bg: "bg-red-50", border: "border-red-200", iconColor: "text-red-500", countColor: "text-red-700", labelColor: "text-red-600", ring: (safe.overdue_count ?? 0) > 0 ? "ring-2 ring-red-300 ring-offset-1" : "", pulse: (safe.overdue_count ?? 0) > 0, }, { key: "this_week" as const, label: "Diese Woche", count: safe.due_this_week ?? 0, icon: Clock, href: "/fristen?status=this_week", bg: "bg-amber-50", border: "border-amber-200", iconColor: "text-amber-500", countColor: "text-amber-700", labelColor: "text-amber-600", ring: "", pulse: false, }, { key: "ok" as const, label: "Im Zeitplan", count: (safe.ok_count ?? 0) + (safe.due_next_week ?? 0), icon: CheckCircle, href: "/fristen?status=ok", bg: "bg-emerald-50", border: "border-emerald-200", iconColor: "text-emerald-500", countColor: "text-emerald-700", labelColor: "text-emerald-600", ring: "", pulse: false, }, ]; return (
{cards.map((card) => ( {card.pulse && ( )}
{card.label}
))}
); }