diff --git a/client/src/mobile/screens/trip/map/MMapArea.tsx b/client/src/mobile/screens/trip/map/MMapArea.tsx index a61a44022..4ad3622a5 100644 --- a/client/src/mobile/screens/trip/map/MMapArea.tsx +++ b/client/src/mobile/screens/trip/map/MMapArea.tsx @@ -46,7 +46,7 @@ export default function MMapArea({ planner, shell }: MMapAreaProps) { dayPlaces={planner.dayPlaces} route={planner.route} routeVias={planner.routeVias} - showTransitRoutes={planner.routeShown} + showTransitRoutes={planner.transitRoutesShown} // The route toggle belongs to one day, so the map needs that day to know // which automated transports may ride it (#2019). days={planner.days} diff --git a/client/src/pages/TripPlannerPage.tsx b/client/src/pages/TripPlannerPage.tsx index bee8f23ba..e46d5abd8 100644 --- a/client/src/pages/TripPlannerPage.tsx +++ b/client/src/pages/TripPlannerPage.tsx @@ -259,7 +259,7 @@ function TripPlannerPageDesktop(): React.ReactElement | null { transportModalDayId, setTransportModalDayId, transportModalAutomated, setTransportModalAutomated, transitPrefill, setTransitPrefill, transitJourney, setTransitJourney, reservationPrefill, transportPrefill, importReviewActive, advanceImportReview, - routeShown, setRouteShown, routeProfile, setRouteProfile, routeVias, fitKey, setFitKey, + routeShown, setRouteShown, transitRoutesShown, routeProfile, setRouteProfile, routeVias, fitKey, setFitKey, mobileSidebarOpen, setMobileSidebarOpen, mobilePlanScrollTopRef, mobilePlacesScrollTopRef, deletePlaceId, setDeletePlaceId, deletePlaceIds, setDeletePlaceIds, visibleConnections, toggleConnection, allConnectionsShown, toggleAllConnections, mapTransportDetail, setMapTransportDetail, @@ -365,7 +365,7 @@ function TripPlannerPageDesktop(): React.ReactElement | null { dayPlaces={dayPlaces} route={route} routeVias={routeVias} - showTransitRoutes={routeShown} + showTransitRoutes={transitRoutesShown} // The route toggle belongs to one day, so the map needs that day to // know which automated transports may ride it (#2019). days={days} diff --git a/client/src/pages/TripPlannerPage.wiring.test.tsx b/client/src/pages/TripPlannerPage.wiring.test.tsx index 523eee217..48a3eebde 100644 --- a/client/src/pages/TripPlannerPage.wiring.test.tsx +++ b/client/src/pages/TripPlannerPage.wiring.test.tsx @@ -219,6 +219,7 @@ function baseState(): HookState { advanceImportReview: vi.fn(), routeShown: false, setRouteShown: vi.fn(), + transitRoutesShown: false, routeProfile: 'driving', setRouteProfile: vi.fn(), routeVias: [], @@ -354,7 +355,7 @@ describe('TripPlannerPage — shell', () => { describe('TripPlannerPage — plan tab', () => { it('FE-PAGE-TPW-008: the map receives the filtered markers, the tile url, the panel widths and the selected day', () => { - renderPage() + renderPage({ transitRoutesShown: true }) expect(props('map').places).toEqual([place]) expect(props('map').tileUrl).toBe('https://tiles/{z}/{x}/{y}.png') @@ -364,6 +365,9 @@ describe('TripPlannerPage — plan tab', () => { // transport in the trip as soon as any day's route is on (#2019). expect(props('map').days).toEqual([day]) expect(props('map').selectedDayId).toBe(7) + // Transit visibility rides the hook's day-aware derivation, not the raw + // toggle — routeShown is still false in this fixture (#2019). + expect(props('map').showTransitRoutes).toBe(true) }) it('FE-PAGE-TPW-009: collapsed panels report a zero width to the map', () => { diff --git a/client/src/pages/tripPlanner/useTripPlanner.test.tsx b/client/src/pages/tripPlanner/useTripPlanner.test.tsx index 5921cd455..7c25827cc 100644 --- a/client/src/pages/tripPlanner/useTripPlanner.test.tsx +++ b/client/src/pages/tripPlanner/useTripPlanner.test.tsx @@ -1,4 +1,4 @@ -// FE-TP-HOOK-001 to FE-TP-HOOK-110 +// FE-TP-HOOK-001 to FE-TP-HOOK-115 import React from 'react' import { renderHook, act, waitFor } from '@testing-library/react' import { TranslationProvider } from '../../i18n/TranslationContext' @@ -825,6 +825,32 @@ describe('useTripPlanner — connection visibility', () => { expect(result.current.visibleConnections).toEqual([1]) }) + + it('FE-TP-HOOK-115: a persisted route toggle keeps transit routes off the map until a day is selected (#2019)', async () => { + localStorage.setItem('trek:day-route:42', 'true') + // The fixture action is a no-op; the derivation reads the store, so this + // one has to write the selection like the real slice does. + actions.setSelectedDay.mockImplementation(dayId => { + useTripStore.setState({ selectedDayId: dayId as number | null }) + }) + seedTrip() + + const { result } = await renderPlanner() + + // Trip re-entry: the toggle rehydrated but nothing selected a day yet. + expect(result.current.routeShown).toBe(true) + expect(result.current.transitRoutesShown).toBe(false) + + act(() => { result.current.handleSelectDay(7) }) + expect(result.current.transitRoutesShown).toBe(true) + + // Clicking the selected day's header again deselects it — the whole trip's + // automated transports must not flood back. + act(() => { result.current.handleSelectDay(null) }) + expect(result.current.transitRoutesShown).toBe(false) + + localStorage.removeItem('trek:day-route:42') + }) }) describe('useTripPlanner — selection handlers', () => { diff --git a/client/src/pages/tripPlanner/useTripPlanner.ts b/client/src/pages/tripPlanner/useTripPlanner.ts index a7f1aa39f..2076cd40a 100644 --- a/client/src/pages/tripPlanner/useTripPlanner.ts +++ b/client/src/pages/tripPlanner/useTripPlanner.ts @@ -306,6 +306,12 @@ export function useTripPlanner() { const autoShowRoute = useCallback(() => { setRouteChoice(prev => (prev === null ? true : prev)) }, []) + // What the planner maps actually draw. The persisted toggle can rehydrate as + // true while no day is selected yet (trip re-entry resets the selection, and + // a second click on the day header clears it) — without a day context the + // per-day transit filter is off, so the map would draw every automated + // transport in the trip (#2019). + const transitRoutesShown = routeShown && selectedDayId != null const [routeProfile, setRouteProfile] = useState('driving') const [fitKey, setFitKey] = useState(0) const initialFitTripId = useRef(null) @@ -1067,7 +1073,7 @@ export function useTripPlanner() { transportModalDayId, setTransportModalDayId, transportModalAutomated, setTransportModalAutomated, transitPrefill, setTransitPrefill, transitJourney, setTransitJourney, reservationPrefill, transportPrefill, importReviewActive, startImportReview, advanceImportReview, - routeShown, setRouteShown, autoShowRoute, routeProfile, setRouteProfile, routeVias, fitKey, setFitKey, + routeShown, setRouteShown, autoShowRoute, transitRoutesShown, routeProfile, setRouteProfile, routeVias, fitKey, setFitKey, mobileSidebarOpen, setMobileSidebarOpen, mobilePlanScrollTopRef, mobilePlacesScrollTopRef, deletePlaceId, setDeletePlaceId, deletePlaceIds, setDeletePlaceIds, visibleConnections, toggleConnection, allConnectionsShown, toggleAllConnections, mapTransportDetail, setMapTransportDetail,