diff --git a/backend/src/lib/booking-flow.js b/backend/src/lib/booking-flow.js index 1722b17..1f16a8e 100644 --- a/backend/src/lib/booking-flow.js +++ b/backend/src/lib/booking-flow.js @@ -113,12 +113,10 @@ export function classifyRoom(site, allBookings, viewDate, yesterday, tomorrow) { // the card right — it ends tonight and its right border should be visible. const spansNext = !!primaryBooking && !!departureDate && departureDate > tomorrow - // Previous-day bracket: if the previous booking departs TODAY, force "departed" - // colour regardless of whether NewBook has updated its status yet. - const rawPrevStatus = prevBooking ? (prevBooking.booking_status || '').toLowerCase() : null - const prevStatus = (rawPrevStatus && toDateStr(prevBooking?.booking_departure) === viewDate) - ? 'departed' - : rawPrevStatus + // Previous-day bracket: use real NewBook status so the sliver remains 'arrived' + // (wide, with checkout time) until the guest actually checks out and NewBook + // flips the status to 'departed'. Do not override — let real status drive colour. + const prevStatus = prevBooking ? (prevBooking.booking_status || '').toLowerCase() : null // NewBook may return category info as flat fields or a nested object. const catId = site.site_category_id ?? site.category_id ?? site.category?.id ?? null diff --git a/frontend/src/components/RoomCard.tsx b/frontend/src/components/RoomCard.tsx index 74acb71..2d02d0f 100644 --- a/frontend/src/components/RoomCard.tsx +++ b/frontend/src/components/RoomCard.tsx @@ -86,12 +86,18 @@ function RoomCard({ room, viewDate, config, onClick }: Props) { ? nightsInfo(booking.booking_arrival, booking.booking_departure, viewDate) : null - // Time pills + // Arrival ETA pill — only for arriving bookings const arriveTime = (room.flow_type === 'arrive' || room.flow_type === 'back-to-back') ? etaTime(booking?.booking_eta) : null - const departTime = (room.flow_type === 'depart' || room.flow_type === 'back-to-back') - ? (room.departing_time?.slice(0, 5) ?? null) + + // Departure time shown in the left-bracket sliver (not as a card pill). + // Show only when there's a departing booking whose status is still 'arrived' + // (not yet checked out). Matches original: collapses once status flips to 'departed'. + const sliverDepartTime = !room.spans_previous && + room.departing_time && + room.departing_booking?.booking_status?.toLowerCase() === 'arrived' + ? room.departing_time.slice(0, 5) : null // CSS data attributes for the Gantt bracket system @@ -129,6 +135,14 @@ function RoomCard({ room, viewDate, config, onClick }: Props) { {...(dataAttrs as React.HTMLAttributes)} onClick={() => onClick(room)} > + {/* ── Departure time in left-bracket sliver ── */} + {sliverDepartTime && ( +
+ + {sliverDepartTime} +
+ )} + {/* ── Header row ─────────────────────────────── */}
{room.site_name} @@ -193,13 +207,6 @@ function RoomCard({ room, viewDate, config, onClick }: Props) { )} - {/* Departure time */} - {departTime && ( - - {departTime} - - )} - {/* Bed type */} {twinType === 'twin' ? ( diff --git a/frontend/src/index.css b/frontend/src/index.css index 1cd6337..7466bbe 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -444,6 +444,24 @@ html, body, #root { .room-card[data-next-status="unconfirmed"]::after { border-color: #f59e0b; } .room-card[data-next-status="departed"]::after { border-color: #a855f7; } +/* Departure time shown in left-bracket sliver (while prev booking still 'arrived') */ +.card-sliver-depart { + position: absolute; + left: -21px; + top: 50%; + transform: translateY(-50%); + display: flex; + flex-direction: column; + align-items: center; + gap: 1px; + font-size: 8px; + font-weight: 600; + color: var(--col-arrived); + line-height: 1; + pointer-events: none; + white-space: nowrap; +} + /* Blocked room */ .room-card.room-blocked { background: #4b5563; @@ -912,6 +930,8 @@ html, body, #root { .settings-page { padding: 20px; max-width: 720px; + overflow-y: auto; + flex: 1; } .settings-section { background: var(--card-bg);