fix(plan): show tour and non-hotel bookings under their assigned day

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
This commit is contained in:
jubnl
2026-05-22 14:54:04 +02:00
parent c828fca059
commit 8f010e38cf
3 changed files with 23 additions and 3 deletions
@@ -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 (
<div style={{ marginBottom: 0 }}>
+17 -1
View File
@@ -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)
+1 -1
View File
@@ -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