import { NextResponse } from "next/server"; import { getPayload } from "payload"; import config from "@payload-config"; import { getAvailableSlots } from "@/lib/booking/slots"; export const dynamic = "force-dynamic"; /** GET /api/booking/slots?offer=&from=YYYY-MM-DD&to=YYYY-MM-DD */ export async function GET(request: Request) { const { searchParams } = new URL(request.url); const offerSlug = searchParams.get("offer"); const fromParam = searchParams.get("from"); const toParam = searchParams.get("to"); if (!offerSlug) { return NextResponse.json({ error: "offer ist erforderlich." }, { status: 400 }); } try { const payload = await getPayload({ config }); const { docs } = await payload.find({ collection: "offers", where: { slug: { equals: offerSlug } }, limit: 1, overrideAccess: false, }); const offer = docs[0]; if (!offer || !offer.bookable || !offer.durationMinutes) { return NextResponse.json({ error: "Dieses Angebot ist nicht buchbar." }, { status: 404 }); } const from = fromParam ? new Date(fromParam) : new Date(); from.setHours(0, 0, 0, 0); const to = toParam ? new Date(toParam) : new Date(from.getTime() + 21 * 24 * 60 * 60 * 1000); to.setHours(23, 59, 59, 999); // Cap the range so this can't be abused to run an expensive scan. const maxRangeMs = 62 * 24 * 60 * 60 * 1000; if (to.getTime() - from.getTime() > maxRangeMs) { return NextResponse.json({ error: "Zeitraum zu groß." }, { status: 400 }); } const slotsByDay = await getAvailableSlots(payload, { durationMinutes: offer.durationMinutes, from, to }); const result: Record = {}; for (const [day, slots] of slotsByDay) { result[day] = slots.map((s) => ({ start: s.start.toISOString(), end: s.end.toISOString() })); } return NextResponse.json({ durationMinutes: offer.durationMinutes, slots: result }); } catch (error) { console.error("booking slots failed", error); return NextResponse.json({ error: "Verfügbarkeiten konnten nicht geladen werden." }, { status: 500 }); } }