TPAgent will:
re-run feasibility on {isMulti ? `${targetCount} trips` : 'this trip'} after save · update HOS gap · refresh fleet recommendations · log edit to audit trail.
>
);
}
// ============================================================
// Orders & drops — add from pool, move drops between trips,
// visualise on the route map.
// ============================================================
function EditOrdersDrops({ isMulti, primaryTrip, trips, moves, setMoves, adds, setAdds }) {
const allTrips = window.TRIPS || [];
const [activeTripId, setActiveTripId] = React.useState(primaryTrip ? primaryTrip.id : '');
const activeTrip = allTrips.find(t => t.id === activeTripId) || primaryTrip;
// Other trips this user can move drops to: in multi-edit, the bulk-selected trips;
// in single, all other planned trips on a similar lane.
const moveTargets = isMulti && trips
? trips.filter(t => t.id !== activeTrip.id)
: allTrips.filter(t => t.id !== activeTrip.id && t.status === 'PLANNED');
// Pool orders available to add — use activeTrip.poolOrders + cross-lane pool.
const pool = activeTrip.poolOrders || [];
const addToTrip = (poolOrder) => {
if (adds.some(a => a.poolOrderId === poolOrder.id)) return;
setAdds([...adds, { poolOrderId: poolOrder.id, toTripId: activeTrip.id, meta: poolOrder }]);
};
const removeAdd = (id) => setAdds(adds.filter(a => a.poolOrderId !== id));
const moveDrop = (orderId, toTripId) => {
setMoves([...moves.filter(m => m.orderId !== orderId), { orderId, fromTripId: activeTrip.id, toTripId }]);
};
const undoMove = (orderId) => setMoves(moves.filter(m => m.orderId !== orderId));
// Build the "after save" projection for the active trip
const movedAway = new Set(moves.filter(m => m.fromTripId === activeTrip.id).map(m => m.orderId));
const addedHere = adds.filter(a => a.toTripId === activeTrip.id);
const projectedOrders = activeTrip.orders.filter(o => !movedAway.has(o.id));
const projectedLbs = projectedOrders.reduce((a, o) => a + o.lbs, 0)
+ addedHere.reduce((a, x) => {
// pool order meta has "X pal · Y lbs · ..."
const m = (x.meta?.meta || '').match(/(\d[\d,]*)\s*lbs/);
return a + (m ? parseInt(m[1].replace(/,/g, ''), 10) : 0);
}, 0);
const projectedUtil = Math.round((projectedLbs / 45000) * 100);
const utilKind = projectedUtil > 100 ? 'red' : projectedUtil > 95 ? 'amber' : projectedUtil < 70 ? 'amber' : 'green';
// Extra trips for map preview = the trips orders are being moved TO
const moveTargetIds = Array.from(new Set(moves.map(m => m.toTripId)));
const extraTripsForMap = moveTargetIds
.map(id => allTrips.find(t => t.id === id))
.filter(Boolean);
return (