diff --git a/client/src/components/PDF/TripPDF.tsx b/client/src/components/PDF/TripPDF.tsx index 41b63e1b3..724607cdc 100644 --- a/client/src/components/PDF/TripPDF.tsx +++ b/client/src/components/PDF/TripPDF.tsx @@ -357,8 +357,17 @@ export async function downloadTripPDF({ trip, days, places, assignments = {}, ca // A rental with stops is a drive, and the printout is what people take // into the car (#1797). Without this the route reads as pick-up and return // with everything in between missing. - const stops = (r.endpoints || []).slice().sort((a, b) => (a.sequence ?? 0) - (b.sequence ?? 0)).map(e => e.name) - subtitle = stops.length >= 2 ? stops.join(' → ') : '' + // + // Consecutive repeats collapse, and a chain that names one place only is + // dropped: the ordinary rental is picked up and returned at the same desk, + // which satisfies "two endpoints" and would otherwise print the counter's + // name twice with an arrow between. A genuine round trip keeps both ends, + // because Dresden sits between them. + const stops = (r.endpoints || []).slice() + .sort((a, b) => (a.sequence ?? 0) - (b.sequence ?? 0)) + .map(e => e.name) + .filter((name, i, all) => name && name !== all[i - 1]) + subtitle = new Set(stops).size >= 2 ? stops.join(' → ') : '' } else if (r.type === 'restaurant') subtitle = [meta.party_size ? `${meta.party_size} guests` : ''].filter(Boolean).join(' · ') else if (r.type === 'event') subtitle = [meta.venue].filter(Boolean).join(' · ')