"use client";
import { useMemo, useState, useTransition } from "react";
import Link from "next/link";
import { format } from "date-fns";
import { de } from "date-fns/locale";
import { NotdienstPlanStatus } from "@prisma/client";
import {
ArrowRight,
CheckSquare,
Download,
Loader2,
RotateCcw,
Send,
Wand2,
} from "lucide-react";
import { toast } from "sonner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
generatePlanAction,
publishPlanAction,
updateAssignmentAction,
sendNotdienstRemindersAction,
resetPlanAction,
} from "./actions";
interface PlanViewProps {
planId?: string;
remindersOpen: boolean;
status?: NotdienstPlanStatus;
days: {
date: string;
assignmentId: string | null;
activeAlarmId?: string | null;
canAlarm?: boolean;
childId: string | null;
isOriginallyUnassigned?: boolean;
isInvalid?: boolean;
}[];
allChildren: {
id: string;
name: string;
parentName: string;
familyId: string;
}[];
familyStatuses: {
id: string;
name: string;
childCount: number;
requiredDays: number;
selectedDays: {
iso: string;
label: string;
}[];
}[];
requiredDays: number;
respondedFamilies: number;
openFamilies: number;
totalFamilies: number;
totalAvailabilitySlots: number;
coverageFactor: number;
closureCount: number;
monthName: string;
year: number;
month: number;
}
export function PlanView({
planId,
remindersOpen,
status,
days,
allChildren,
familyStatuses,
requiredDays,
respondedFamilies,
openFamilies,
totalFamilies,
totalAvailabilitySlots,
coverageFactor,
closureCount,
monthName,
year,
month,
}: PlanViewProps) {
const [isPending, startTransition] = useTransition();
const [activeTab, setActiveTab] = useState<"preview" | "manual">("preview");
const [resetDialogOpen, setResetDialogOpen] = useState(false);
const responsePercent =
totalFamilies > 0
? Math.round((respondedFamilies / totalFamilies) * 100)
: 0;
const handleGenerate = () => {
startTransition(async () => {
const result = await generatePlanAction(year, month);
if ("error" in result && result.error) {
toast.error(result.error as string);
} else {
toast.success("Plan erfolgreich generiert.");
}
});
};
const handlePublish = () => {
if (!planId) return;
startTransition(async () => {
const result = await publishPlanAction(planId);
if ("error" in result && result.error) {
toast.error(result.error as string);
} else if ("success" in result && result.success) {
if (result.failed || ("deferred" in result && result.deferred))
toast.warning(
"Plan veröffentlicht. Einige E-Mails stehen noch aus – siehe Versandstatus.",
);
else
toast.success(
"Plan veröffentlicht. Die Benachrichtigungen wurden vorbereitet.",
);
}
});
};
const handleSendReminders = () => {
startTransition(async () => {
const result = await sendNotdienstRemindersAction(year, month);
if ("error" in result && result.error) {
toast.error(result.error as string);
} else if ("success" in result && result.success) {
if (result.failed || ("deferred" in result && result.deferred))
toast.warning(
`${result.count} E-Mails versendet. Offene Nachrichten bleiben gespeichert – siehe Versandstatus.`,
);
else
toast.success(
`${result.count} E-Mails versendet. Bereits heute erinnerte Haushalte erhalten keine zweite Erinnerung.`,
);
}
});
};
const handleReset = () => {
if (!planId) return;
startTransition(async () => {
const result = await resetPlanAction(planId);
if ("error" in result && result.error) {
toast.error(result.error as string);
} else {
toast.success("Plan wurde erfolgreich zurückgesetzt.");
setResetDialogOpen(false);
}
});
};
const handleAssignmentChange = (date: string, newChildId: string) => {
if (!planId || (status !== "DRAFT" && status !== "PUBLISHED")) return;
const valueToSet = newChildId === "empty" ? null : newChildId;
startTransition(async () => {
const result = await updateAssignmentAction(
planId,
date.slice(0, 10),
valueToSet,
);
if ("error" in result && result.error) {
toast.error(result.error as string);
} else {
toast.success("Zuteilung aktualisiert.");
}
});
};
if (!planId && totalAvailabilitySlots === 0) {
return (
Für {monthName} hat noch keine Familie geantwortet. Verschicke
zuerst Erinnerungen, damit die automatische Planung belastbar ist.
Noch keine Verfügbarkeiten
{respondedFamilies} von {totalFamilies} Familien haben vollständig geantwortet · noch {openFamilies} offen
{family.name}
{family.childCount} Kind {family.childCount === 1 ? "" : "er"}
Planungsgrundlage für {monthName}.
Verteilt {requiredDays} Notdiensttage fair auf die verfügbaren Familien.
{selectedChild ? selectedAvailable ? "Eingeteilte Familie ist verfügbar." : "Eingeteilte Familie hat für diesen Tag keine Verfügbarkeit angegeben." : `${availableFamilies} ${availableFamilies === 1 ? "Familie ist" : "Familien sind"} verfügbar.`}
) : null}