"use client"; import { useQuery, useMutation } from "@tanstack/react-query"; import { api } from "@/lib/api"; import type { ProceedingType, CalculateResponse, CalculatedDeadline, } from "@/lib/types"; import { format, parseISO, isPast, isThisWeek } from "date-fns"; import { de } from "date-fns/locale"; import { Calculator, Calendar, ArrowRight, AlertTriangle, } from "lucide-react"; import { useState } from "react"; function getTimelineUrgency(dueDate: string): "red" | "amber" | "green" { const due = parseISO(dueDate); if (isPast(due)) return "red"; if (isThisWeek(due, { weekStartsOn: 1 })) return "amber"; return "green"; } const dotColors = { red: "bg-red-500", amber: "bg-amber-500", green: "bg-green-500", }; const inputClass = "w-full rounded-md border border-neutral-200 bg-white px-3 py-2 text-sm text-neutral-900 outline-none transition-colors focus:border-neutral-400 focus:ring-1 focus:ring-neutral-400"; export function DeadlineCalculator() { const [proceedingType, setProceedingType] = useState(""); const [triggerDate, setTriggerDate] = useState( new Date().toISOString().split("T")[0], ); const { data: proceedingTypes, isLoading: typesLoading } = useQuery({ queryKey: ["proceeding-types"], queryFn: () => api.get("/proceeding-types"), }); const calculateMutation = useMutation({ mutationFn: (params: { proceeding_type: string; trigger_event_date: string; }) => api.post("/deadlines/calculate", params), }); // Auto-calculate when proceeding type changes (using current trigger date) function doCalculate(type: string, date: string) { if (!type || !date) return; calculateMutation.mutate({ proceeding_type: type, trigger_event_date: date, }); } function handleProceedingChange(newType: string) { setProceedingType(newType); doCalculate(newType, triggerDate); } function handleDateChange(newDate: string) { setTriggerDate(newDate); if (proceedingType) doCalculate(proceedingType, newDate); } function handleCalculate(e: React.FormEvent) { e.preventDefault(); doCalculate(proceedingType, triggerDate); } const results = calculateMutation.data; return (
{/* Input form */}
Fristenberechnung
handleDateChange(e.target.value)} className={inputClass} />
{/* Error */} {calculateMutation.isError && (
Fehler bei der Berechnung. Bitte Eingaben prüfen.
)} {/* Results */} {results && results.deadlines && (

Berechnete Fristen

{results.deadlines.length} Fristen ab{" "} {format(parseISO(results.trigger_event_date), "dd. MMM yyyy", { locale: de, })}
{/* Timeline */}
{results.deadlines.map((d: CalculatedDeadline, i: number) => { const urgency = getTimelineUrgency(d.due_date); const isLast = i === results.deadlines.length - 1; return (
{!isLast && (
)}
{d.title} {format(parseISO(d.due_date), "dd.MM.yyyy")}
{d.rule_code && {d.rule_code}} {d.was_adjusted && ( <> {d.rule_code && ·} Angepasst (Original:{" "} {format( parseISO(d.original_due_date), "dd.MM.yyyy", )} ) )}
); })}
)} {/* Empty state */} {!results && !calculateMutation.isPending && (

Verfahrensart und Auslösedatum wählen, um Fristen zu berechnen

)}
); }