diff --git a/client/src/components/Planner/DayPlanSidebar.test.tsx b/client/src/components/Planner/DayPlanSidebar.test.tsx
index 06fcb4161..1d9da4c76 100644
--- a/client/src/components/Planner/DayPlanSidebar.test.tsx
+++ b/client/src/components/Planner/DayPlanSidebar.test.tsx
@@ -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()
+
+ 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()
diff --git a/client/src/components/Planner/DayPlanSidebar.tsx b/client/src/components/Planner/DayPlanSidebar.tsx
index 204182148..cba5e42fd 100644
--- a/client/src/components/Planner/DayPlanSidebar.tsx
+++ b/client/src/components/Planner/DayPlanSidebar.tsx
@@ -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) => {