From 8f010e38cf24b256bf6d0c91929b5a8da65bea11 Mon Sep 17 00:00:00 2001 From: jubnl Date: Fri, 22 May 2026 14:54:04 +0200 Subject: [PATCH] fix(plan): show tour and non-hotel bookings under their assigned day MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getTransportForDay was rejecting any reservation type not in TRANSPORT_TYPES (flight/train/bus/car/cruise), silently dropping tours, restaurants, events, and other bookings before day_id matching ran. The server already resolves day_id from reservation_time for all non-hotel types (added in reservationService). The merged-item renderer already handles non-transport types via RES_ICONS and onEditReservation — only the filter was wrong. Also broaden DayDetailPanel's per-day reservation filter to match by day_id in addition to assignment_id, so tours appear in the day-detail popup too. Fixes #1008 --- .../src/components/Planner/DayDetailPanel.tsx | 6 +++++- client/src/utils/dayMerge.test.ts | 18 +++++++++++++++++- client/src/utils/dayMerge.ts | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/client/src/components/Planner/DayDetailPanel.tsx b/client/src/components/Planner/DayDetailPanel.tsx index 407db408..df23d690 100644 --- a/client/src/components/Planner/DayDetailPanel.tsx +++ b/client/src/components/Planner/DayDetailPanel.tsx @@ -288,7 +288,11 @@ export default function DayDetailPanel({ day, days, places, categories = [], tri {/* ── Reservations for this day's assignments ── */} {(() => { const dayAssignments = assignments[String(day.id)] || [] - const dayReservations = reservations.filter(r => dayAssignments.some(a => a.id === r.assignment_id)) + const dayReservations = reservations.filter(r => { + if (r.type === 'hotel') return false + if (r.assignment_id && dayAssignments.some(a => a.id === r.assignment_id)) return true + return r.day_id === day.id + }) if (dayReservations.length === 0) return null return (
diff --git a/client/src/utils/dayMerge.test.ts b/client/src/utils/dayMerge.test.ts index 1f894792..bc1b5d74 100644 --- a/client/src/utils/dayMerge.test.ts +++ b/client/src/utils/dayMerge.test.ts @@ -57,11 +57,27 @@ describe('getTransportForDay', () => { { id: 3, day_number: 3 }, ] - it('excludes non-transport types', () => { + it('excludes hotel (rendered via accommodation path)', () => { const reservations = [{ id: 10, type: 'hotel', day_id: 1 }] expect(getTransportForDay({ reservations, dayId: 1, dayAssignmentIds: [], days })).toHaveLength(0) }) + it('includes tour booking on the correct day', () => { + const reservations = [{ id: 20, type: 'tour', day_id: 1 }] + expect(getTransportForDay({ reservations, dayId: 1, dayAssignmentIds: [], days })).toHaveLength(1) + expect(getTransportForDay({ reservations, dayId: 2, dayAssignmentIds: [], days })).toHaveLength(0) + }) + + it('includes restaurant, event, and other bookings by day_id', () => { + const reservations = [ + { id: 30, type: 'restaurant', day_id: 2 }, + { id: 31, type: 'event', day_id: 2 }, + { id: 32, type: 'other', day_id: 2 }, + ] + expect(getTransportForDay({ reservations, dayId: 2, dayAssignmentIds: [], days })).toHaveLength(3) + expect(getTransportForDay({ reservations, dayId: 1, dayAssignmentIds: [], days })).toHaveLength(0) + }) + it('includes single-day transport on the correct day', () => { const reservations = [{ id: 10, type: 'flight', day_id: 1, end_day_id: 1 }] expect(getTransportForDay({ reservations, dayId: 1, dayAssignmentIds: [], days })).toHaveLength(1) diff --git a/client/src/utils/dayMerge.ts b/client/src/utils/dayMerge.ts index 0889ace2..d465139c 100644 --- a/client/src/utils/dayMerge.ts +++ b/client/src/utils/dayMerge.ts @@ -55,7 +55,7 @@ export function getTransportForDay(opts: { const thisDayOrder = getDayOrder(dayId) return reservations.filter(r => { - if (!TRANSPORT_TYPES.has(r.type)) return false + if (r.type === 'hotel') return false if (r.assignment_id && dayAssignmentIds.includes(r.assignment_id)) return false const startDayId = r.day_id