/* global window, React */
// ============================================================
// Trip detail — Tab 2: Routing feasibility
// ============================================================
function Timeline({ nodes }) {
return (
{nodes.map((n, i) => (
{n.title}
{n.detail}
{n.note && typeof n.note === 'string' &&
{n.note}}
{n.note && typeof n.note === 'object' &&
{n.note.text}}
))}
);
}
function HOSGrid({ hos }) {
const gapNegative = hos.gap.startsWith('−') || hos.gap.startsWith('-');
return (
Drive time required
{hos.drive}
Total drive duration this trip
Best HOS available · private
{hos.best}
Top eligible driver on 70-hour clock
Gap
{hos.gap}
{gapNegative ? 'Private fleet cannot cover this trip' : 'Private fleet covers this trip'}
Carrier available
{hos.carrier}
{gapNegative ? 'Bridges HOS gap — see Fleet tab' : 'Backup only'}
);
}
function ConstraintList({ items }) {
const icon = (s) => s === 'pass' ? '✓' : s === 'warn' ? '!' : '✕';
return (
{items.map((c, i) => (
{icon(c.status)}
{c.name}
{c.detail}
{c.value}
))}
);
}
function RoutingTab({ trip }) {
const r = trip.routing;
return (
Route map
{trip.route.from} → {trip.route.to} · pickup, driver swaps, delivery
Route timeline
{trip.route.from} → {trip.route.to}
Hours of Service · feasibility
Route constraints · {r.constraints.length} checks
);
}
Object.assign(window, { RoutingTab });