"use client" import * as React from "react" import FullCalendar from "@fullcalendar/react" import dayGridPlugin from "@fullcalendar/daygrid" import timeGridPlugin from "@fullcalendar/timegrid" import interactionPlugin from "@fullcalendar/interaction" import type { DatesSetArg, EventInput } from "@fullcalendar/core" import { getBookings } from "@/lib/api/bookings" import { ApiError } from "@/lib/api/core-http" import type { Booking, BookingStatus } from "@/lib/models/booking" const STATUS_COLORS: Record = { Confirmed: "#2563eb", CheckedIn: "#16a34a", Completed: "#6b7280", NoShow: "#dc2626", Cancelled: "#dc2626", } function bookingToEvent(booking: Booking): EventInput { const color = STATUS_COLORS[booking.status] ?? "#2563eb" return { id: booking.bookingId, title: `${booking.facilityName ?? "Facility"} — ${booking.isGuest ? booking.guestName ?? "Guest" : "Member"}`, start: booking.startTime, end: booking.endTime, backgroundColor: color, borderColor: color, } } /** Read-only calendar view of bookings — reuses the existing roster's getBookings query, * refetched for whatever range FullCalendar currently has visible. */ function BookingCalendar() { const [events, setEvents] = React.useState([]) const [loading, setLoading] = React.useState(false) const [error, setError] = React.useState(null) async function handleDatesSet(arg: DatesSetArg) { setLoading(true) setError(null) try { const bookings = await getBookings({ fromDate: arg.start.toISOString(), toDate: arg.end.toISOString(), }) setEvents(bookings.map(bookingToEvent)) } catch (err) { setError(err instanceof ApiError ? err.message : "Couldn't load bookings for this range.") } finally { setLoading(false) } } return (
{loading && Loading…} {error && {error}} {(Object.keys(STATUS_COLORS) as BookingStatus[]).map((status) => ( {status} ))}
) } export { BookingCalendar }