"use client"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; import { X, CalendarIcon, Clock } from "lucide-react"; import toast from "react-hot-toast"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { getStationsAPI } from "(app)/_querys/stations"; import { createBookingAPI } from "(app)/_querys/bookings"; import { Button } from "@repo/shared-components"; import { useRouter } from "next/navigation"; import { AxiosError } from "axios"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { DateInput } from "_components/ui/DateInput"; import { Select } from "_components/ui/Select"; interface NewBookingFormData { type: "STATION" | "LST_01" | "LST_02" | "LST_03" | "LST_04"; stationId?: number; startTime: string; endTime: string; title?: string; description?: string; } interface NewBookingModalProps { isOpen: boolean; onClose: () => void; onBookingCreated: () => void; userPermissions: string[]; } export const NewBookingModal = ({ isOpen, onClose, onBookingCreated, userPermissions, }: NewBookingModalProps) => { const queryClient = useQueryClient(); const { data: stations, isLoading: isLoadingStations } = useQuery({ queryKey: ["stations"], queryFn: () => getStationsAPI({}), }); const router = useRouter(); const { mutate: createBooking, isPending: isCreateBookingLoading } = useMutation({ mutationKey: ["createBooking"], mutationFn: createBookingAPI, onMutate() { // Optionally show a loading toast or indicator toast.loading("Buchung wird erstellt...", { id: "createBooking" }); }, onError(error: AxiosError) { const errorData = error.response?.data as { error?: string }; toast.error(errorData?.error || "Fehler beim Erstellen der Buchung", { id: "createBooking" }); }, onSuccess: () => { toast.success("Buchung erfolgreich erstellt", { id: "createBooking" }); queryClient.invalidateQueries({ queryKey: ["bookings"] }); onBookingCreated(); onClose(); router.refresh(); }, }); const newBookingSchema = z .object({ type: z.enum(["STATION", "LST_01", "LST_02", "LST_03", "LST_04"], { message: "Bitte wähle einen Typ aus", }), stationId: z.number().optional(), startTime: z.string(), endTime: z.string(), title: z.string().optional(), description: z.string().optional(), }) .superRefine((data, ctx) => { const start = new Date(data.startTime); const end = new Date(data.endTime); if (end <= start) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Endzeit muss nach der Startzeit liegen", path: ["endTime"], }); } }); const form = useForm({ resolver: zodResolver(newBookingSchema), }); const { register, handleSubmit, watch, setValue, reset, formState: { errors }, } = form; const selectedType = watch("type"); const hasDISPOPermission = userPermissions.includes("DISPO"); // Reset form when modal opens useEffect(() => { if (isOpen) { reset(); // Set default datetime to current hour const now = new Date(); const currentHour = new Date( now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), 0, 0, ); const nextHour = new Date(currentHour.getTime() + 60 * 60 * 1000); setValue("startTime", currentHour.toISOString().slice(0, 16)); setValue("endTime", nextHour.toISOString().slice(0, 16)); } }, [isOpen, reset, setValue]); if (!isOpen) return null; return (
{/* Header */}

Neue Buchung erstellen

{/* Form */}
createBooking(data))} className="space-y-6"> {/* Resource Type Selection */}
{errors.type && ( )}
{/* Station Selection (only if STATION type is selected) */} {selectedType === "STATION" && (
{isLoadingStations ? (
) : (