diff --git a/client/src/components/Map/dayRoutePlan.ts b/client/src/components/Map/dayRoutePlan.ts index a7227a58b..07f0079a7 100644 --- a/client/src/components/Map/dayRoutePlan.ts +++ b/client/src/components/Map/dayRoutePlan.ts @@ -3,7 +3,7 @@ import { getTransportRouteEndpoints, getTransportForDay, getMergedItems, isCarri import { getDayBookendHotels, shouldDrawMorningLeg, shouldDrawEveningLeg, type CarrierEdge } from '../../utils/dayOrder' import { withinDriveRange } from '@trek/shared/roadtrip' import type { Accommodation, AssignmentsMap, Day, Place, Reservation } from '../../types' -import { projectDayItinerary, type TourStageStops } from './dayTourProjection' +import { projectedById, type TourStageStops } from './dayTourProjection' export const TRANSPORT_TYPES = ['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'cable_car', 'transit', 'transport_other'] @@ -85,7 +85,7 @@ export function buildDayRouteRuns(dayId: number, input: DayRouteInputs): DayRout days: allDays, }) const merged = getMergedItems({ dayAssignments: da, dayNotes: [], dayTransports, dayId }) - const projected = new Map(projectDayItinerary(da, input.toursEnabled ?? false, input.places, input.tourStageStops).map(item => [item.assignment.id, item])) + const projected = projectedById(da, input.toursEnabled ?? false, input.places, input.tourStageStops) type Entry = | { kind: 'place'; id: number; lat: number; lng: number; pos: number; time: string | null; mode: string | null; incoming: string | null } diff --git a/client/src/components/Map/dayTourProjection.ts b/client/src/components/Map/dayTourProjection.ts index cf137dea3..1d5f4a3cd 100644 --- a/client/src/components/Map/dayTourProjection.ts +++ b/client/src/components/Map/dayTourProjection.ts @@ -85,4 +85,14 @@ export function projectDayItinerary( loop: !!start && !!end && start.lat === end.lat && start.lng === end.lng, valid: !!end } as const }) +} + +/** The day's stops projected as `projectDayItinerary` does, by assignment id, for the route that runs through them. */ +export function projectedById( + assignments: Assignment[], + toursEnabled: boolean, + places?: readonly Place[], + stageStops?: TourStageStops, +): Map { + return new Map(projectDayItinerary(assignments, toursEnabled, places, stageStops).map(item => [item.assignment.id, item])) } \ No newline at end of file diff --git a/client/src/components/Planner/DayPlanSidebar.tsx b/client/src/components/Planner/DayPlanSidebar.tsx index f40e19bd2..f02c09473 100644 --- a/client/src/components/Planner/DayPlanSidebar.tsx +++ b/client/src/components/Planner/DayPlanSidebar.tsx @@ -69,7 +69,8 @@ import { RouteConnector, HotelRouteConnector } from './DayPlanSidebarRouteConnec import { resolveLegMode } from './legMode' import { useLegModeActions } from './useLegModeActions' import { dayExportStops, fillAroundLocked } from './dayRoute' -import { projectDayItinerary, type TourStageStops } from '../Map/dayTourProjection' +import { projectDayItinerary, projectedById, type TourStageStops } from '../Map/dayTourProjection' +import type { DayRoutePoint } from '../Map/dayRoutePlan' import { usePluginDaySchedule, usePluginDayTints, dayTintBackground, dayTinted, PluginDayScheduleRow, formatScheduleMinutes } from '../Plugins/PluginDaySchedule' import { MobileAddPlaceButton } from './DayPlanSidebarMobileAddPlaceButton' import { DayPlanSidebarToolbar } from './DayPlanSidebarToolbar' @@ -623,12 +624,12 @@ function useDayPlanSidebar(props: DayPlanSidebarProps) { // legs to draw. Side-effect free, so the async loop below only does OSRM I/O. const planDay = (dayId: number) => { const merged = mergedItemsMap[dayId] || [] - const projected = new Map(projectDayItinerary(assignments[String(dayId)] || [], toursEnabled, places, props.tourStageStops).map(item => [item.assignment.id, item])) + const projected = projectedById(assignments[String(dayId)] || [], toursEnabled, places, props.tourStageStops) // Each run point carries the ORIGIN assignment's per-segment travel mode // (#1281): the leg from this point to the next is routed with `mode` (null = // inherit the day default). Transport endpoints carry no mode → day default. - const runs: { id: number; lat: number; lng: number; isPlace: boolean; leg_transport_mode?: string | null; incoming_leg_transport_mode?: string | null; assignmentId?: number }[][] = [] - let cur: { id: number; lat: number; lng: number; isPlace: boolean; leg_transport_mode?: string | null; incoming_leg_transport_mode?: string | null; assignmentId?: number }[] = [] + const runs: (DayRoutePoint & { id: number })[][] = [] + let cur: (DayRoutePoint & { id: number })[] = [] // A run is only a real drive when it holds an actual place. Two back-to-back // transports (e.g. two flights on one day) would otherwise pair the first's // arrival with the second's departure into a phantom airport→airport leg — the