fix(planner): hide the booked night where the day list is actually drawn

The filter sat on the planner hook's assignments, but the day sidebar is handed
storedAssignments straight from the store, so it never saw it. The hotel was
listed as an ordinary place right under the overnight block naming it, on every
day someone booked a night for.

Filtered in getDayAssignments now, next to the service-stop filter that is there
for the neighbouring reason. That is the list itself, so the reorder and undo
paths keep reading the full day and nothing shifts underneath them. The phone
was never affected: its timeline reads the hook's copy.
This commit is contained in:
Maurice
2026-09-13 13:04:19 +02:00
parent d0d3f455a8
commit 274dbea069
2 changed files with 35 additions and 1 deletions
@@ -229,6 +229,28 @@ describe('DayPlanSidebar', () => {
expect(screen.getByText('Amsterdam Day')).toBeInTheDocument()
})
it('FE-PLANNER-DAYPLAN-002b: the stop a booked night wrote is not listed under the day', () => {
// Booking a night puts its hotel on the check-in day as a stop, because road trip
// mode drives to it. The day header already shows that booking as its own overnight
// block, so listing the stop here would be the same hotel twice. The one the
// traveller placed keeps its row.
const day = buildDay({ id: 10, date: '2025-06-01', title: 'Day One' })
const museum = buildPlace({ id: 601, name: 'Pergamonmuseum' })
const hotel = buildPlace({ id: 602, name: 'Hotel Adlon', stop_type: 'hotel' })
render(<DayPlanSidebar {...makeDefaultProps({
days: [day], places: [museum, hotel], selectedDayId: 10,
assignments: {
'10': [
buildAssignment({ id: 401, day_id: 10, order_index: 0, place: museum }),
buildAssignment({ id: 402, day_id: 10, order_index: 1, place: hotel, accommodation_id: 7 } as never),
],
},
})} />)
expect(screen.getAllByText('Pergamonmuseum').length).toBeGreaterThan(0)
expect(screen.queryByText('Hotel Adlon')).toBeNull()
})
it('FE-PLANNER-DAYPLAN-003: renders day number when title is null', () => {
const day = buildDay({ title: null, date: '2025-06-01' })
render(<DayPlanSidebar {...makeDefaultProps({ days: [day] })} />)
@@ -412,8 +412,20 @@ function useDayPlanSidebar(props: DayPlanSidebarProps) {
})
}
// Two reasons a stop can be road-trip-only, and they are not the same reason.
//
// The switch is the traveller's: it keeps the petrol stations and rest areas they
// added along the drive out of a day list they want to read as a plan.
//
// A stop a lodging booking put there is out whatever the switch says. The day
// already carries that booking as its own overnight block in the header, so the
// row would be the same hotel a second time. Road trip mode wants it, which is
// why it is a stop at all: the drive has to end somewhere, and that somewhere is
// where you sleep.
const getDayAssignments = (dayId) =>
(assignments[String(dayId)] || []).filter(a => mirrorServiceStops || !isServiceStopType(a.place?.stop_type)).slice().sort((a, b) => a.order_index - b.order_index)
(assignments[String(dayId)] || [])
.filter(a => a.accommodation_id == null && (mirrorServiceStops || !isServiceStopType(a.place?.stop_type)))
.slice().sort((a, b) => a.order_index - b.order_index)
// Compute initial day_plan_position for a transport based on time
const computeTransportPosition = (r, da) => {