feat(journey): draw the trips' GPX tracks on the journey map (#1911)

* feat(journey): serve the GPX tracks behind a journey

A journey has no trip of its own, but every entry records the trip it came from,
and a trip's routed geometries live on its places. So the tracks are derivable
without any new storage: GET /journeys/:id/tracks walks that link and returns the
geometries, dropping elevation nothing on the map reads and skipping anything
that is not a usable line.

* feat(journey): draw those tracks on the journey map

Both renderers, Leaflet and GL, plus the mobile map-timeline that shares them.
Solid and in the track's own colour with a white casing, so it reads as a
recorded route rather than as the dashed line that merely connects entries in
time order, and stays legible on satellite tiles.

* feat(journey): load the tracks alongside the journey

Fetched separately from the journey itself: most journeys have no tracks, and a
failed lookup should cost the map its lines rather than the whole page.

* docs(journey): document the GPX tracks on the map

* fix(journey): label tracks with the house map tooltip

bindTooltip's default box ignores the appearance tokens, so it sat there in
Leaflet grey next to markers already using .map-tooltip. Same class now, and an
unnamed track gets no tooltip at all instead of an empty one.
This commit is contained in:
Maurice
2026-08-12 15:14:50 +02:00
committed by GitHub
parent 767dc662b7
commit 870bd6131f
15 changed files with 334 additions and 11 deletions
@@ -38,7 +38,7 @@ export default function MJourneyDetail() {
showInvite, setShowInvite,
showSettings, setShowSettings,
hideSkeletons,
sidebarMapItems,
sidebarMapItems, tracks,
loadJourney, updateEntry, deleteEntry, uploadPhotos,
} = useJourneyDetail()
@@ -209,6 +209,7 @@ export default function MJourneyDetail() {
ref={mapRef}
checkins={[]}
entries={sidebarMapItems}
tracks={tracks}
height={9999}
dark={dark}
activeMarkerId={entries[activeIndex] ? String(entries[activeIndex].id) : null}