import { format } from "date-fns"; import { useEffect, useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { apiGet } from "@/lib/api"; import type { Room } from "@/lib/types"; interface TimelineResp { days: string[]; rooms: Room[]; segments: { bookingId: string; guestName: string; roomId: string; start: string; end: string; status: string; paymentLabel: string; source: string; }[]; } export function ReservationsPage() { const [month, setMonth] = useState(format(new Date(), "yyyy-MM")); const [data, setData] = useState(null); useEffect(() => { apiGet(`/reservations/timeline?month=${month}`) .then(setData) .catch(console.error); }, [month]); if (!data) return

Loading timeline…

; const dayWidth = 56; const roomCol = 120; return (

Reservations

Gantt-style view (mock data)

setMonth(e.target.value)} className="rounded-xl border border-input bg-background px-3 py-2 text-sm" />
Occupied Check-in / out Reserved
Timeline
Room
{data.days.map((d) => (
{d.slice(8)}
))}
{data.rooms.map((room) => (
{room.name}
{data.segments .filter((s) => s.roomId === room.id) .map((s) => { const startIdx = data.days.findIndex( (d) => d >= s.start ); const endIdx = data.days.findIndex((d) => d >= s.end); const si = startIdx >= 0 ? startIdx : 0; const ei = endIdx >= 0 ? endIdx : data.days.length; const span = Math.max(1, ei - si); return (
{s.guestName}
); })}
))}
); }