fix(mobile): pick the plan timeline's hotel legs by what the route drew (#2501)

On a day that opens with a flight, where the traveller also put the
hotel on the day as a stop of their own, the phone timeline started the
day with a hotel row and the drive from that stop to the next place,
above the flight, and then showed the same drive again in its own spot.

hotelLegsForDay guessed the bookends from coordinates: the first
segment leaving the hotel's spot was the morning leg. The route had
correctly drawn no morning leg on that day, but the stop on the
hotel's spot starts a leg there too, so that hop was taken for it.

The route calculation now tags the two legs it draws from and to the
accommodation, and the timeline reads that tag instead. The hotel end
of a tagged leg still has to be the day's own stay, because the
calculation keeps the previous day's legs until the new day has
routed. The stop to stop connectors leave tagged legs alone, so one
leg can no longer show up in both places.
This commit is contained in:
Maurice
2026-09-25 19:46:29 +02:00
parent 5d4178d067
commit 62f8b0deee
8 changed files with 314 additions and 51 deletions
+7 -2
View File
@@ -4,7 +4,7 @@ import { useState, useCallback, useRef, useEffect, useMemo } from 'react'
import { useTripStore } from '../store/tripStore'
import { useSettingsStore } from '../store/settingsStore'
import { calculateRouteWithLegs, type RouteProfileKey } from '../components/Map/RouteCalculator'
import { buildDayRouteRuns, TRANSPORT_TYPES } from '../components/Map/dayRoutePlan'
import { buildDayRouteRuns, hotelBookendOf, TRANSPORT_TYPES } from '../components/Map/dayRoutePlan'
import { resolveLegMode } from '../components/Planner/legMode'
import type { TripStoreState } from '../store/tripStore'
import type { RouteSegment, RouteResult, RouteVia, Accommodation } from '../types'
@@ -100,7 +100,12 @@ export function useRouteCalculation(tripStore: TripStoreState, selectedDayId: nu
try {
const r = await calculateRouteWithLegs(chunk.map(p => ({ lat: p.lat, lng: p.lng })), { signal: controller.signal, profile: mode, tripId, dayId })
pushCoords(r.coordinates.length >= 2 ? r.coordinates : straight())
for (const leg of r.legs) allLegs.push({ ...leg, mode })
// Leg k runs from chunk[k] to chunk[k + 1]; a hotel bookend says so on the
// segment, which is how the phone timeline finds it (#2501).
r.legs.forEach((leg, k) => {
const hotelBookend = chunk[k + 1] ? hotelBookendOf(chunk[k], chunk[k + 1]) : undefined
allLegs.push(hotelBookend ? { ...leg, mode, hotelBookend } : { ...leg, mode })
})
if (r.vias) allVias.push(...r.vias)
} catch (err) {
if (err instanceof Error && err.name === 'AbortError') throw err