Frontend for the per-truck EDR backend:
- Assign modal takes a container LOAD per truck (MultiSelect, max 2) instead of a
single container, so a truck can carry one 40ft or two 20ft. Sends
containerNumbers[]; the API enforces the size rule.
- requiredVehicles is now size-aware: a 40ft fills a truck (1 each), two 20ft
share one. It previously assumed ceil(containers / 2) regardless of size, so a
2x40ft booking under-counted the trucks needed.
- Bulk bookings show the drawdown in the assign modal — remaining vs total
tonnage, what's been hauled, and a "fully hauled" state when it reaches 0.
- New "Truck exit papers" row action opens a per-truck list (plate, containers,
arrival, exit, net weight) with a per-truck exit-paper download.
- last-mile findAll/findById now load each assignment's containers so the UI can
hydrate a truck's load.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Truck loading:
- loadTruck enforces max 2 containers / one 40ft (two 20ft) and auto-marks an
assigned truck arrived on load; container-items payload + modal expose
container size with a client-side selection cap.
- Show "#x containers pending assignment" in the portal truck card and the
backoffice container modal.
Last-mile:
- create() is idempotent — return the existing record for a booking instead of
inserting a duplicate delivery row (fixed the same booking showing twice in
Assign-Mile).
- setVehicles/update reject a truck with no assigned driver; the Assign toast
now surfaces the reason.
- New GET /last-mile/booking/:id/arrival-trucks returns assigned EDR trucks with
driver details; ReleaseOrderModal fetches and auto-fills them so an assigned
EDR truck no longer reads as "not assigned yet".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>