diff --git a/backend/src/routes/tasks.js b/backend/src/routes/tasks.js index 87dd8c2..a442fea 100644 --- a/backend/src/routes/tasks.js +++ b/backend/src/routes/tasks.js @@ -78,10 +78,12 @@ async function fetchRoomOccupancy() { arriving.add(id) } } - // A site can have more than one booking on a turnover day (e.g. a departing guest - // plus a same-day incoming one) — physically-present-right-now always wins over a - // booking that's merely confirmed to arrive later. - for (const id of departing) { occupied.delete(id); arriving.delete(id) } + // A site can have more than one booking on a turnover day. Physically-present-right- + // now always wins over "merely confirmed to arrive later", so departing beats + // occupied. But a departing site that ALSO has a same-day incoming booking is a + // genuine back-to-back turnover worth flagging — leave it in `arriving` too rather + // than dropping it, so the UI can show both "Departing" and "Arrival today". + for (const id of departing) occupied.delete(id) for (const id of occupied) arriving.delete(id) return { occupied, departing, arriving } } @@ -353,7 +355,9 @@ export async function taskRoutes(app) { // GET /api/occupancy — room state from NewBook for the Rooms Accessible View // Returns three lists: occupied (staying, guest in room), departing (guest in room - // but checking out today — accessible later) and arriving (booked today, not yet checked in) + // but checking out today — accessible later) and arriving (booked today, not yet + // checked in). A site can appear in both departing and arriving — a back-to-back + // turnover, today's guest not gone yet but the next one already booked in. app.get('/api/occupancy', { preHandler: requireCap('view') }, async (req, reply) => { try { const { occupied, departing, arriving } = await fetchRoomOccupancy() diff --git a/frontend/src/pages/Summary.tsx b/frontend/src/pages/Summary.tsx index 1ea6f77..d5f26d5 100644 --- a/frontend/src/pages/Summary.tsx +++ b/frontend/src/pages/Summary.tsx @@ -258,7 +258,9 @@ export default function Summary() { const sid = t.newbook_site_id ? String(t.newbook_site_id) : null const isOccupied = roomsView && !!sid && occupiedSiteIds.has(sid) const isDeparting = roomsView && !!sid && !isOccupied && departingSiteIds.has(sid) - const isArriving = roomsView && !!sid && !isOccupied && !isDeparting && arrivingSiteIds.has(sid) + // Not exclusive with isDeparting — a departing room can also have a same-day + // incoming booking (back-to-back turnover), and both badges should show. + const isArriving = roomsView && !!sid && !isOccupied && arrivingSiteIds.has(sid) return (