From ea98e7bd07ccd9d084eb7bb6ee6bdeeb47b61eda Mon Sep 17 00:00:00 2001 From: Cliff Hill Date: Thu, 28 Aug 2025 16:24:32 -0400 Subject: [PATCH] Getting the stream right for the frontend. Signed-off-by: Cliff Hill --- frontend/src/components/BookingList.tsx | 12 +++++++--- frontend/src/components/RoomList.tsx | 10 +++++++- frontend/src/index.tsx | 19 +++++++++++++++ frontend/src/pages/LandingPage.tsx | 32 ++++++++++++++++++++++--- 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/BookingList.tsx b/frontend/src/components/BookingList.tsx index a3a3dcd0..d4b96239 100644 --- a/frontend/src/components/BookingList.tsx +++ b/frontend/src/components/BookingList.tsx @@ -78,14 +78,20 @@ const BookingList: FC = ({ eventSourceRef.current.close(); } // Subscribe to SSE for room availability/booking changes - const url = `/rooms/${roomId}/bookings/stream?date=${date}`; + const url = `http://localhost:8000/rooms/availability/stream`; const es = new window.EventSource(url); eventSourceRef.current = es; es.onmessage = (event) => { try { const data = JSON.parse(event.data); - // Expecting the backend to send the full list of bookings for the room/date - setLiveBookings(data.bookings || []); + // Filter bookings for the current room and date + let filtered = []; + if (Array.isArray(data.bookings)) { + filtered = data.bookings.filter( + (b: any) => b.roomId === roomId && b.startTime.startsWith(date) + ); + } + setLiveBookings(filtered); } catch (e) { // Ignore parse errors } diff --git a/frontend/src/components/RoomList.tsx b/frontend/src/components/RoomList.tsx index 6beb92fb..8905ce1e 100644 --- a/frontend/src/components/RoomList.tsx +++ b/frontend/src/components/RoomList.tsx @@ -118,7 +118,15 @@ const RoomList: FC = ({ onSelectRoom(room.id)} + onClick={(e) => { + console.log("RoomList: ListItemButton click", room.id); + e.preventDefault(); + e.stopPropagation(); + onSelectRoom(room.id); + setTimeout(() => { + console.log("RoomList: after onSelectRoom", room.id); + }, 0); + }} aria-label={`Select room ${room.name}`} data-testid={`room-item-${room.id}`} sx={ diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index f9c24764..07bdd7b2 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -9,6 +9,25 @@ import reportWebVitals from "./reportWebVitals"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import axios from "axios"; +// Global error handler to catch unhandled errors and prevent reloads +window.onerror = function (message, source, lineno, colno, error) { + console.error("Global error handler:", { + message, + source, + lineno, + colno, + error, + }); + // Prevent default browser reload on error + return true; +}; + +window.onunhandledrejection = function (event) { + console.error("Global unhandledrejection:", event.reason); + // Prevent default browser reload on unhandled promise rejection + return true; +}; + const queryClient = new QueryClient(); axios.defaults.baseURL = process.env.REACT_APP_API_URL || "http://localhost:8000"; diff --git a/frontend/src/pages/LandingPage.tsx b/frontend/src/pages/LandingPage.tsx index 732f506f..e3990a46 100644 --- a/frontend/src/pages/LandingPage.tsx +++ b/frontend/src/pages/LandingPage.tsx @@ -27,6 +27,22 @@ import BookingList, { Booking } from "../components/BookingList"; * @returns {JSX.Element} The landing page UI. */ const LandingPage: FC = () => { + // Debug: log when LandingPage mounts + useEffect(() => { + console.log("LandingPage: mounted"); + return () => { + console.log("LandingPage: unmounted"); + }; + }, []); + + // Debug: log before page unload + useEffect(() => { + const handler = (e: BeforeUnloadEvent) => { + console.log("window.onbeforeunload: page is unloading"); + }; + window.addEventListener("beforeunload", handler); + return () => window.removeEventListener("beforeunload", handler); + }, []); const navigate = useNavigate(); const today = new Date().toISOString().split("T")[0]; @@ -63,10 +79,19 @@ const LandingPage: FC = () => { } = useQuery({ queryKey: ["bookings", today, selectedRoomId], enabled: !!selectedRoomId, - queryFn: () => - axios + queryFn: () => { + console.log("LandingPage: fetching bookings for", selectedRoomId, today); + return axios .get(`/bookings/room/${selectedRoomId}?date=${today}`) - .then((res) => res.data as Booking[]), + .then((res) => { + console.log("LandingPage: bookings fetch result", res.data); + return res.data as Booking[]; + }) + .catch((err) => { + console.error("LandingPage: bookings fetch error", err); + throw err; + }); + }, }); // Display skeleton loaders during data fetching @@ -115,6 +140,7 @@ const LandingPage: FC = () => { // Display error message with retry option if (roomsError || bookingsError) { + console.error("LandingPage: error state", { roomsError, bookingsError }); return (