From 440bb8497f5ec1bce89ddfa465cac535a760dfd8 Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 2 Jul 2026 23:41:37 +0200 Subject: [PATCH] =?UTF-8?q?fix(map):=20transit=20polish=20=E2=80=94=20earl?= =?UTF-8?q?ier=20label=20collapse,=20route-toggle=20coupling,=20md=20note?= =?UTF-8?q?=20preview?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Station badges on transit journeys collapse to icon dots much earlier when zooming out (label threshold 900px instead of 400). The drawn transit paths now ride the day-route toggle: turning the route off hides them too, since they are part of the computed route. The journey card's note preview renders its first line as inline markdown instead of raw asterisks. --- client/src/components/Map/MapView.tsx | 8 +++++--- client/src/components/Map/MapViewGL.tsx | 9 ++++++--- client/src/components/Map/ReservationOverlay.tsx | 2 +- client/src/components/Map/reservationsMapbox.ts | 2 +- client/src/components/Planner/ReservationsPanel.tsx | 4 +++- client/src/pages/TripPlannerPage.tsx | 1 + 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/client/src/components/Map/MapView.tsx b/client/src/components/Map/MapView.tsx index a62099912..5293f1c07 100644 --- a/client/src/components/Map/MapView.tsx +++ b/client/src/components/Map/MapView.tsx @@ -428,6 +428,7 @@ export const MapView = memo(function MapView({ reservations = [] as Reservation[], showReservationStats = false, visibleConnectionIds = [] as number[], + showTransitRoutes = true, onReservationClick, pois = [] as Poi[], onPoiClick, @@ -446,9 +447,10 @@ export const MapView = memo(function MapView({ )), [pois, onPoiClick]) const visibleReservations = useMemo(() => { const set = new Set(visibleConnectionIds || []) - // Transit journeys are part of the plan itself — always on the map (#1065). - return reservations.filter((r: Reservation) => r.type === 'transit' || set.has(r.id)) - }, [reservations, visibleConnectionIds]) + // Transit journeys ride the route toggle — they are part of the computed + // day route, so hiding the route hides them too (#1065). + return reservations.filter((r: Reservation) => (r.type === 'transit' && showTransitRoutes) || set.has(r.id)) + }, [reservations, visibleConnectionIds, showTransitRoutes]) // Dynamic padding: account for sidebars + bottom inspector + day detail panel const paddingOpts = useMemo((): L.FitBoundsOptions => { const isMobile = typeof window !== 'undefined' && window.innerWidth < 768 diff --git a/client/src/components/Map/MapViewGL.tsx b/client/src/components/Map/MapViewGL.tsx index 0f8749075..51011ced1 100644 --- a/client/src/components/Map/MapViewGL.tsx +++ b/client/src/components/Map/MapViewGL.tsx @@ -81,6 +81,7 @@ interface Props { hasDayDetail?: boolean reservations?: Reservation[] visibleConnectionIds?: number[] + showTransitRoutes?: boolean showReservationStats?: boolean onReservationClick?: (reservationId: number) => void pois?: Poi[] @@ -199,6 +200,7 @@ export function MapViewGL({ hasDayDetail = false, reservations = [], visibleConnectionIds = [], + showTransitRoutes = true, showReservationStats = false, onReservationClick, pois = [], @@ -801,9 +803,10 @@ export function MapViewGL({ // booking's route, matching the Leaflet MapView's behaviour. const visibleReservations = useMemo(() => { const set = new Set(visibleConnectionIds || []) - // Transit journeys are part of the plan itself — always on the map (#1065). - return reservations.filter(r => r.type === 'transit' || set.has(r.id)) - }, [reservations, visibleConnectionIds]) + // Transit journeys ride the route toggle — they are part of the computed + // day route, so hiding the route hides them too (#1065). + return reservations.filter(r => (r.type === 'transit' && showTransitRoutes) || set.has(r.id)) + }, [reservations, visibleConnectionIds, showTransitRoutes]) useEffect(() => { const map = mapRef.current diff --git a/client/src/components/Map/ReservationOverlay.tsx b/client/src/components/Map/ReservationOverlay.tsx index 1df0bbec5..33d45f564 100644 --- a/client/src/components/Map/ReservationOverlay.tsx +++ b/client/src/components/Map/ReservationOverlay.tsx @@ -414,7 +414,7 @@ export default function ReservationOverlay({ reservations, showConnections, show for (const item of visibleItems) { const fromPx = map.latLngToContainerPoint([item.from.lat, item.from.lng]) const toPx = map.latLngToContainerPoint([item.to.lat, item.to.lng]) - const minPx = item.type === 'flight' ? 50 : item.type === 'cruise' ? 300 : item.type === 'car' ? 150 : 400 + const minPx = item.type === 'flight' ? 50 : item.type === 'cruise' ? 300 : item.type === 'car' ? 150 : item.type === 'transit' ? 900 : 400 if (fromPx.distanceTo(toPx) >= minPx) set.add(item.res.id) } return set diff --git a/client/src/components/Map/reservationsMapbox.ts b/client/src/components/Map/reservationsMapbox.ts index 139c6113e..34072ad9d 100644 --- a/client/src/components/Map/reservationsMapbox.ts +++ b/client/src/components/Map/reservationsMapbox.ts @@ -331,7 +331,7 @@ export class ReservationMapboxOverlay { const toPx = map.project([item.to.lng, item.to.lat]) const dx = fromPx.x - toPx.x, dy = fromPx.y - toPx.y const dist = Math.sqrt(dx * dx + dy * dy) - const minPx = item.type === 'flight' ? 50 : item.type === 'cruise' ? 300 : item.type === 'car' ? 150 : 400 + const minPx = item.type === 'flight' ? 50 : item.type === 'cruise' ? 300 : item.type === 'car' ? 150 : item.type === 'transit' ? 900 : 400 if (dist >= minPx) labelVisibleIds.add(item.res.id) } catch { /* ignore */ } } diff --git a/client/src/components/Planner/ReservationsPanel.tsx b/client/src/components/Planner/ReservationsPanel.tsx index 9ad2eecb6..a083b1eaf 100644 --- a/client/src/components/Planner/ReservationsPanel.tsx +++ b/client/src/components/Planner/ReservationsPanel.tsx @@ -561,7 +561,9 @@ function TransitJourneyCard({ r, days, onOpen, onDelete, canEdit }: { {r.notes && (
- {r.notes.split('\n')[0]} + + {r.notes.split('\n')[0]} +
)} {confirmOpen && ReactDOM.createPortal( diff --git a/client/src/pages/TripPlannerPage.tsx b/client/src/pages/TripPlannerPage.tsx index 6cd08866a..3274d03cc 100644 --- a/client/src/pages/TripPlannerPage.tsx +++ b/client/src/pages/TripPlannerPage.tsx @@ -304,6 +304,7 @@ export default function TripPlannerPage(): React.ReactElement | null { places={mapPlaces} dayPlaces={dayPlaces} route={route} + showTransitRoutes={routeShown} routeSegments={routeSegments} selectedPlaceId={selectedPlaceId} onMarkerClick={handleMarkerClick}