"use client"; import type { ComponentProps, FormEvent } from "react"; import { useMemo, useState, useTransition } from "react"; import { TerminType } from "@prisma/client"; import { CalendarPlus } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { createTerminRequest } from "../actions"; type TerminRequestFormState = { title: string; type: TerminType; startDate: string; endDate: string; allDay: boolean; }; const initialFormState: TerminRequestFormState = { title: "", type: TerminType.KITA_FEST, startDate: "", endDate: "", allDay: false, }; type TerminRequestModalProps = { triggerLabel?: string; triggerVariant?: ComponentProps["variant"]; triggerClassName?: string; }; export function TerminRequestModal({ triggerLabel = "Termin anfragen", triggerVariant = "ghost", triggerClassName = "gap-2", }: TerminRequestModalProps) { const [open, setOpen] = useState(false); const [formState, setFormState] = useState(initialFormState); const [isPending, startTransition] = useTransition(); const minDateTime = useMemo(() => getLocalDateTimeInputValue(new Date()), []); const minEndDateTime = formState.startDate || minDateTime; const updateField = ( key: TKey, value: TerminRequestFormState[TKey], ) => { setFormState((current) => { const next = { ...current, [key]: value }; if (key === "startDate" && typeof value === "string" && next.endDate && next.endDate < value) { next.endDate = value; } return next; }); }; const handleSubmit = (event: FormEvent) => { event.preventDefault(); if (!formState.startDate || !formState.endDate) { toast.error("Bitte Start und Ende ausfüllen."); return; } if (formState.startDate < minDateTime) { toast.error("Der Startzeitpunkt darf nicht in der Vergangenheit liegen."); return; } if (formState.endDate < formState.startDate) { toast.error("Das Ende darf nicht vor dem Start liegen."); return; } const data = { title: formState.title, type: formState.type, startDate: new Date(formState.startDate).toISOString(), endDate: new Date(formState.endDate).toISOString(), allDay: formState.allDay, }; startTransition(async () => { const res = await createTerminRequest(data); if (res.error) { toast.error(res.error); } else { toast.success("Terminanfrage wurde erfolgreich gestellt!"); setFormState(initialFormState); setOpen(false); } }); }; return (
Termin anfragen Frage einen privaten Termin (z.B. Kindergeburtstag) in den Räumlichkeiten der Kita an. Die Anfrage muss von einem Admin bestätigt werden.
updateField("title", event.target.value)} />
updateField("startDate", event.target.value)} required />
updateField("endDate", event.target.value)} required />
updateField("allDay", event.target.checked)} />
); } function getLocalDateTimeInputValue(date: Date) { const localDate = new Date(date); localDate.setSeconds(0, 0); const offset = localDate.getTimezoneOffset() * 60_000; return new Date(localDate.getTime() - offset).toISOString().slice(0, 16); }