From 7d22857de8159ed1f815a3f262c925c9a8a202bc Mon Sep 17 00:00:00 2001 From: Luffy Date: Mon, 28 Sep 2026 12:03:15 +0800 Subject: [PATCH] fix(mobile): restore day selection when reopening a trip --- client/src/mobile/screens/trip/MTripShell.tsx | 12 ++++++++++-- .../tests/unit/mobile/trip/MTripShell.test.tsx | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/client/src/mobile/screens/trip/MTripShell.tsx b/client/src/mobile/screens/trip/MTripShell.tsx index 190761781..58d5407dc 100644 --- a/client/src/mobile/screens/trip/MTripShell.tsx +++ b/client/src/mobile/screens/trip/MTripShell.tsx @@ -204,7 +204,7 @@ export default function MTripShell({ Sheets = MTripSheets, }: MTripShellProps) { const planner = useTripPlanner() - const { t, language, tripId, days, trip, navigate, packingItems, todoItems } = planner + const { t, language, tripId, days, trip, navigate, packingItems, todoItems, isLoading } = planner // Per-day colours from the dayTintProvider plugin hook — the mobile counterpart // of the desktop day-card wash, carried on the day chips. Empty without a plugin. @@ -240,6 +240,14 @@ export default function MTripShell({ // back to the first day once the whole trip is behind us. const seededDayRef = useRef(false) useEffect(() => { + // Re-entering the same trip from the dashboard starts with that trip's old + // selection still in the store. The first render treats it as seeded, then + // loadTrip clears it. Reset the guard with that load cycle so the freshly + // loaded days get their normal today/Day 1 selection. + if (isLoading) { + seededDayRef.current = false + return + } if (seededDayRef.current) return // A day that is already active counts as seeded: a later deselect is the // user's, and re-seeding it here would be exactly the fight this guard @@ -250,7 +258,7 @@ export default function MTripShell({ // Off the same helper file as the desktop day plan (#1567), so the two // cannot drift on what "today" means. planner.tripActions.setSelectedDay(findFocusDayId(days) ?? days[0].id) - }, [planner.selectedDayId, days, planner.tripActions]) + }, [isLoading, planner.selectedDayId, days, planner.tripActions]) // Swiping the day panel (#2051) can move the day well past the chips on // screen — the rail overflows from roughly six days on — so the active chip diff --git a/client/tests/unit/mobile/trip/MTripShell.test.tsx b/client/tests/unit/mobile/trip/MTripShell.test.tsx index 6082b038b..33f787087 100644 --- a/client/tests/unit/mobile/trip/MTripShell.test.tsx +++ b/client/tests/unit/mobile/trip/MTripShell.test.tsx @@ -202,6 +202,24 @@ describe('MTripShell', () => { expect(screen.queryByRole('button', { name: 'Sat 2' })).not.toBeInTheDocument() }) + it('FE-MOB-SHELL-007b: re-seeds after re-entering the same trip from the dashboard', () => { + const { planner, rerenderShell } = renderShell() + expect(planner.tripActions.setSelectedDay).not.toHaveBeenCalled() + + // The dashboard leaves the previous trip snapshot in the store. loadTrip + // clears that selection while it reloads the same trip. + planner.isLoading = true + planner.days = [] + planner.selectedDayId = null + rerenderShell() + + planner.isLoading = false + planner.days = DAYS + rerenderShell() + + expect(planner.tripActions.setSelectedDay).toHaveBeenCalledWith(11) + }) + it('FE-MOB-SHELL-008: the back button leaves for the dashboard', () => { const { planner } = renderShell() fireEvent.click(screen.getByRole('button', { name: 'common.back' }))