/** Kalendertag lokal als `YYYY-MM-DD` (für Vergleich mit DB). */ export function localDateKey(d: Date): string { const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${y}-${m}-${day}`; } /** UI-Wert für `` aus API-Wert. */ export function deadlineToDateInput(deadlineAt: string | null | undefined): string { if (!deadlineAt) return ""; const s = deadlineAt.trim(); if (/^\d{4}-\d{2}-\d{2}$/.test(s)) return s; const t = new Date(s); if (Number.isNaN(t.getTime())) return ""; return localDateKey(t); } export type DeadlineTone = "none" | "upcoming" | "today" | "overdue"; /** Blau = künftig (nicht heute), Orange = heute fällig, Rot = überschritten. */ export function deadlineTone(deadlineAt: string | null | undefined): DeadlineTone { if (!deadlineAt) return "none"; const key = deadlineToDateInput(deadlineAt); if (!key) return "none"; const today = localDateKey(new Date()); if (key < today) return "overdue"; if (key === today) return "today"; return "upcoming"; } export function deadlineBadgeClass(tone: DeadlineTone): string { switch (tone) { case "upcoming": return "text-blue-500/70 text-blue-800 dark:text-blue-200"; case "today": return "text-orange-500/80 text-orange-900 dark:text-orange-100"; case "overdue": return "text-destructive/80 text-destructive"; default: return ""; } } export function formatDeadlineLabel(deadlineAt: string): string { const key = deadlineToDateInput(deadlineAt); if (!key) return deadlineAt; try { const [y, m, d] = key.split("-").map(Number); const dt = new Date(y, m - 1, d); return dt.toLocaleDateString(undefined, { dateStyle: "medium" }); } catch { return key; } }