From 75aeba29edf160b5839c3b41a2d5c2e15641073f Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 13 Nov 2026 12:40:16 +0100 Subject: [PATCH] feat(mobile): calmer trip settings, list editing, selecting places and the journey map switch The trip settings sheet opens on a list of its areas, each a page of its own with a way back, and the journal there is drawn in the phone's own cards. A new packing list is typed into a card with its add and cancel, selecting places keeps its way out in view with the actions as icons below, and the journey's satellite switch sits in its bar beside the menu. --- .../components/Journey/JourneyLayeredMap.tsx | 43 ++++++++- .../screens/collections/MCollections.tsx | 96 ++++++++++++------- .../mobile/screens/journey/MJourneyDetail.tsx | 18 +++- .../trip/sheets/MTripSettingsSheet.tsx | 92 +++++++++++++++--- .../screens/trip/tabs/MPackingListTab.tsx | 21 +++- .../mobile/collections/MCollections.test.tsx | 12 ++- .../mobile/trip/MTripSettingsSheet.test.tsx | 23 ++++- .../mobile/trip/MTripSheets.members.test.tsx | 10 +- 8 files changed, 247 insertions(+), 68 deletions(-) diff --git a/client/src/components/Journey/JourneyLayeredMap.tsx b/client/src/components/Journey/JourneyLayeredMap.tsx index 021d549c5..75685de01 100644 --- a/client/src/components/Journey/JourneyLayeredMap.tsx +++ b/client/src/components/Journey/JourneyLayeredMap.tsx @@ -26,6 +26,11 @@ interface Props extends MapProps { hideLayerControl?: boolean; /** How far from the map's top the switches sit, clear of a bar laid over the map. */ controlsTop?: number | string; + /** + * The base layer, when the page keeps the satellite switch in its own bar (the + * phone); left out, the map carries the switch in its top corner. + */ + baseLayer?: BaseLayer; /** Leads from a picked place or stay to its entry. */ onOpenEntry?: (entryId: string) => void; entryTitleOf?: (entryId: number) => string | null; @@ -41,6 +46,36 @@ function offeredIf(offered: unknown, action: T): T | undefined { return offered ? action : undefined; } +/** + * The base layer the map shows: the page's, where it keeps the switch in its own + * bar, otherwise the map's own, switched from its corner. + */ +function useBaseLayer(page: BaseLayer | undefined) { + const [own, setOwn] = useState('default'); + const toggleBaseLayer = useCallback(() => setOwn((was) => (was === 'satellite' ? 'default' : 'satellite')), []); + return { baseLayer: page ?? own, toggleBaseLayer, switchOnMap: page === undefined }; +} + +/** The satellite switch in the map's top corner, unless the page keeps it in its own bar. */ +function CornerSwitcher({ + hidden, + top, + active, + onToggle, +}: { + hidden: boolean; + top: number | string; + active: BaseLayer; + onToggle: () => void; +}) { + if (hidden) return null; + return ( +
+ +
+ ); +} + /** * A journey map with its layers (JRN-04): the renderer, the reader's layer * switches and the card of a picked plan place or stay. Every journey map @@ -59,6 +94,7 @@ export default function JourneyLayeredMap({ engine = 'auto', hideLayerControl = false, controlsTop = 12, + baseLayer: pageBaseLayer, onOpenEntry, entryTitleOf, onWriteAboutPlace, @@ -68,8 +104,7 @@ export default function JourneyLayeredMap({ ...rest }: Props) { const [picked, setPicked] = useState<{ marks: JourneyMapMark[]; key: string } | null>(null); - const [baseLayer, setBaseLayer] = useState('default'); - const toggleBaseLayer = useCallback(() => setBaseLayer((was) => (was === 'satellite' ? 'default' : 'satellite')), []); + const { baseLayer, toggleBaseLayer, switchOnMap } = useBaseLayer(pageBaseLayer); const visibility = layers?.visibility; const onMarksPick = useCallback((marks: JourneyMapMark[]) => { setPicked({ marks, key: marks.map((m) => m.key).join(',') }); @@ -111,9 +146,7 @@ export default function JourneyLayeredMap({
{engine === 'leaflet' ? : }
-
- -
+