mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(roadtrip): a booked night holds its check-in and heads its day
A hotel entered under Days with a check-in at ten was reached at a quarter past twelve in road trip mode. Two things: the schedule read the check-in as a floor that held nothing once anything before it set the clock, and the server seated the night last unless something pinned later pulled it forward, so two stops without an hour stood ahead of it. The check-in now pins the night the way its own time would, in the plain schedule and in the daily window, where a check-in the drive cannot make is the conflict a missed pin is. The night is seated first on its day; only a stop with a clock at or before the check-in stays ahead of it, and the stops without one follow. A new check-in seats the night afresh, a change of notes leaves a dragged night where it is. A day that is nothing but its booked night stands among the days now, with the hotel and its check-in, instead of at the foot of the rail under "only X so far", which read as the hotel missing from the road trip. The client puts a stop the server seated at the front where the server put it, rather than appending it to draw second until the next reload.
This commit is contained in:
@@ -1553,12 +1553,16 @@ function DaySection({ day, selectedAssignmentId, onSelectStop, onReorderStop, on
|
||||
{formatDate(day.date, language)}
|
||||
</time>
|
||||
) : null}
|
||||
<span className={`${DAY_BADGE} bg-surface-card`} style={{ fontSize: FS.label }}>
|
||||
{t('roadtrip.leg.driveText', {
|
||||
distance: formatDistance(day.distance / 1000, distanceUnit),
|
||||
time: formatDurationShort(day.duration),
|
||||
})}
|
||||
</span>
|
||||
{/* A day that is only the night booked for it has no drive to sum up and no
|
||||
stop to count; the hotel row below says everything it has to say. */}
|
||||
{day.legs.length > 0 ? (
|
||||
<span className={`${DAY_BADGE} bg-surface-card`} style={{ fontSize: FS.label }}>
|
||||
{t('roadtrip.leg.driveText', {
|
||||
distance: formatDistance(day.distance / 1000, distanceUnit),
|
||||
time: formatDurationShort(day.duration),
|
||||
})}
|
||||
</span>
|
||||
) : null}
|
||||
{day.dayWarning ? (
|
||||
<Tooltip label={t('roadtrip.limit.hint')}>
|
||||
<span className={`${DAY_BADGE} gap-1 bg-warning-soft text-warning`} style={{ fontSize: FS.label }}>
|
||||
@@ -1569,9 +1573,11 @@ function DaySection({ day, selectedAssignmentId, onSelectStop, onReorderStop, on
|
||||
</span>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<span className={`${DAY_BADGE} bg-surface-card`} style={{ fontSize: FS.label }}>
|
||||
{t('roadtrip.day.stopCount', { count: day.stops.filter(s => !s.automaticNight && !isServiceStopType(s.stopType)).length })}
|
||||
</span>
|
||||
{day.legs.length > 0 ? (
|
||||
<span className={`${DAY_BADGE} bg-surface-card`} style={{ fontSize: FS.label }}>
|
||||
{t('roadtrip.day.stopCount', { count: day.stops.filter(s => !s.automaticNight && !isServiceStopType(s.stopType)).length })}
|
||||
</span>
|
||||
) : null}
|
||||
{/* The other half of "where possible". The setting is a weighting, so a day
|
||||
with no untolled crossing comes back on the toll road — and the only thing
|
||||
worse than not avoiding it is not avoiding it silently, which reads as the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useRoadtripSettings } from '../../hooks/useRoadtripSettings'
|
||||
import { assembleRoadtrip, foldRouteRun, type RoadtripStop, type RoadtripRoutes, type PlanDay, type QuietDay, type RoutedLeg } from '@trek/shared/roadtrip'
|
||||
import { assembleRoadtrip, foldRouteRun, standsAsDay, type RoadtripStop, type RoadtripRoutes, type PlanDay, type QuietDay, type RoutedLeg } from '@trek/shared/roadtrip'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { calculateRouteWithLegs, RoutingRefusedError } from '../Map/RouteCalculator'
|
||||
import { resolveLegMode } from '../Planner/legMode'
|
||||
@@ -91,6 +91,7 @@ const asStop = (a: Assignment, ownerDayId: number, ownerIndex: number, accommoda
|
||||
// traveller's own statement about this stop, and the stay then runs until it.
|
||||
leaveAt: a.assignment_end_time ?? p.end_time ?? null,
|
||||
checkInTime: stay?.check_in ?? null,
|
||||
night: stay !== undefined,
|
||||
dwellMinutes: typeof p.duration_minutes === 'number' ? p.duration_minutes : null,
|
||||
endDay: a.end_day === true,
|
||||
legMode: a.leg_transport_mode ?? null,
|
||||
@@ -222,7 +223,7 @@ export function useRoadtripRoutes(
|
||||
stops,
|
||||
}
|
||||
})
|
||||
.filter(d => d.stops.length > 1)
|
||||
.filter(d => standsAsDay(d.stops))
|
||||
}, [days, assignments, accommodations])
|
||||
|
||||
const quietDays = useMemo<QuietDay[]>(() => {
|
||||
@@ -240,7 +241,7 @@ export function useRoadtripRoutes(
|
||||
.filter((s): s is RoadtripStop => s !== null)
|
||||
.map((s, i) => ({ ...s, ownerIndex: i })),
|
||||
}))
|
||||
.filter(d => d.stops.length < 2)
|
||||
.filter(d => !standsAsDay(d.stops))
|
||||
}, [days, assignments, accommodations])
|
||||
|
||||
// Only the geometry decides whether legs have to be re-fetched: renaming a place or
|
||||
|
||||
@@ -252,11 +252,17 @@ export const STATE_APPLIERS: Partial<Record<TrekWsTripEventName, StateApplier>>
|
||||
}
|
||||
|
||||
// Genuinely new — including a legitimate second assignment of a place
|
||||
// already on this day (no temp version to reconcile). Append.
|
||||
// already on this day (no temp version to reconcile). Seated where the server
|
||||
// put it: a booked night lands at the front of its day, and the rows behind it
|
||||
// were moved up one there. Appending it with that index would leave it tied
|
||||
// with the old first row and drawn second until the next reload.
|
||||
const ordered = existing.slice().sort((a, b) => (a.order_index ?? 0) - (b.order_index ?? 0))
|
||||
const at = Math.max(0, Math.min(incoming.order_index ?? ordered.length, ordered.length))
|
||||
ordered.splice(at, 0, incoming)
|
||||
return {
|
||||
assignments: {
|
||||
...state.assignments,
|
||||
[dayKey]: [...existing, incoming],
|
||||
[dayKey]: ordered.map((a, i) => (a.order_index === i ? a : { ...a, order_index: i })),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user