import { AlertTriangle, Route } from 'lucide-react' import { useTranslation } from '../../i18n' import { MapTogglePill } from './MapTogglePill' import { routeModeIcon } from '../Planner/routeModes' import { formatDistance } from '../../utils/units' import type { TripRouteOverview as Overview } from './useTripRouteOverview' import type { DistanceUnit } from '../../types' /** * Toggle for the whole-trip route overview (#1736). Same frosted shell as the other * map controls, so it lines up with the compass and the layer switcher. */ export function TripRouteOverviewPill({ active, onToggle }: { active: boolean; onToggle: () => void }) { const { t } = useTranslation() return ( } /> ) } /** * The trip's stages and its total distance, read off the overview the map is drawing. * * One component for both shells: the phone and the desktop place it differently but the * rows are the same rows, and a second copy of them is a second thing to keep in step. */ export function TripRouteOverviewPanel({ overview, unit, selectedDayId, onSelectDay, maxWidth = 320 }: { overview: Overview unit: DistanceUnit selectedDayId?: number | null onSelectDay?: (dayId: number) => void /** How wide the card may grow before day names start to ellipsize. */ maxWidth?: number }) { const { t } = useTranslation() if (!overview.days.length) return null // Only once the round is over: while it runs every leg still waiting is unrouted too, // and the ellipsis on the total already says the number is growing. const unrouted = overview.loading ? 0 : (overview.unroutedLegs ?? 0) return (
{t('map.overview.total')} {/* Same tier as the label beside it: the two read as one line rather than as a heading with a number stuck under it. */} {formatDistance(overview.totalDistance / 1000, unit)} {/* Still routing: the number is a partial sum, and saying so beats a total that silently grows while you read it. */} {overview.loading && {' '}…}
{/* A leg the router refused stays a straight line and adds nothing to the sum, so the total is short by however much road those legs are. Said in words rather than left to the reader to notice, because the number is what a fuel estimate starts from. */} {unrouted > 0 && (
{t('map.overview.unrouted', { count: unrouted })}
)}
{overview.days.map(day => { const label = day.title || t('dayplan.dayN', { n: day.dayNumber }) const dayUnrouted = overview.loading ? 0 : (day.unroutedLegs ?? 0) const row = ( <> {label} {day.modes.map(mode => { const Icon = routeModeIcon(mode) return })} {/* The day's own share of the shortfall, so the reader knows which figure to distrust rather than only that one of them is off. */} {dayUnrouted > 0 && ( )} {formatDistance(day.distance / 1000, unit)} ) const style = { display: 'flex', alignItems: 'center', gap: 8, width: '100%', padding: '7px 14px', textAlign: 'start' as const, fontSize: 'calc(12px * var(--fs-scale-body, 1))', background: day.dayId === selectedDayId ? 'var(--bg-hover)' : 'transparent', border: 'none', } return onSelectDay ? ( ) : (
{row}
) })}
) }