/* global window, React */
// ============================================================
// Trip list — left column
// ============================================================
const { useState } = React;
function TripCard({ trip, selected, checked, onClick, onCheck, onEdit }) {
const urgClass = `urg-${trip.urgency}`;
const fleetPillKind = {
private: 'green',
dedicated: 'amber',
market: 'blue',
spot: 'red',
}[trip.fleet];
const utilFillClass = trip.utilState === 'low' ? 'low'
: trip.utilState === 'red' ? 'over'
: trip.utilState === 'amber' ? 'warn' : '';
const minsAgoLabel = (m) => m < 60 ? `${m}m ago` : `${Math.round(m/60*10)/10}h ago`;
return (
{ e.stopPropagation(); onCheck(); }}
title="Select for bulk action"
>
{trip.changedInLastRun && (
UPD · {minsAgoLabel(trip.updatedMinsAgo)}
)}
{trip.id}
{trip.fleetLabel}
{trip.route.from}
→
{trip.route.to}
{trip.customer}
{trip.chips.map((c, i) => (
{c.label}
))}
{trip.util}%
{trip.window.icon}
{trip.window.value}
);
}
function TripList({ trips, selectedId, onSelect, onBatchApprove, checked, onCheck, onClearChecks, onEdit, onBulkEdit }) {
const [filter, setFilter] = useState('action');
const filters = [
{ id: 'action', label: 'Needs action', n: trips.length },
{ id: 'changed', label: 'Changed', n: trips.filter(t => t.changedInLastRun).length },
{ id: 'recent', label: '< 2h', n: trips.filter(t => t.updatedMinsAgo < 120).length },
{ id: 'held', label: 'HELD', n: trips.filter(t => /HELD/i.test(t.chips.map(c=>c.label).join(' '))).length },
];
const filtered = trips.filter(t => {
if (filter === 'changed') return t.changedInLastRun;
if (filter === 'recent') return t.updatedMinsAgo < 120;
if (filter === 'held') return /HELD/i.test(t.chips.map(c=>c.label).join(' '));
return true; // 'action' shows all needing review
});
const numChecked = checked.size;
return (
);
}
Object.assign(window, { TripList });