mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 16:28:12 +00:00
Merge pull request #431 from Tria-plc/freight/feature/first_mile_invoice
Freight/feature/first mile invoice
This commit is contained in:
@@ -22,8 +22,10 @@ export interface LastMileContainerRow {
|
||||
qty: number;
|
||||
}
|
||||
|
||||
/** One vehicle (with trailer) carries at most this many containers. */
|
||||
const CONTAINERS_PER_VEHICLE = 2;
|
||||
|
||||
export interface LastMileContainerAllocationTableProps {
|
||||
lastMileId: string;
|
||||
containers: LastMileContainerRow[];
|
||||
onSave: (allocations: Array<{ containerId: string; vehicleId: string }>) => Promise<void>;
|
||||
}
|
||||
@@ -33,7 +35,6 @@ export interface LastMileContainerAllocationTableProps {
|
||||
* Displays containers with type/qty, vehicle dropdown per row, and save action.
|
||||
*/
|
||||
export function LastMileContainerAllocationTable({
|
||||
lastMileId,
|
||||
containers,
|
||||
onSave,
|
||||
}: LastMileContainerAllocationTableProps) {
|
||||
@@ -43,7 +44,8 @@ export function LastMileContainerAllocationTable({
|
||||
|
||||
const { data: vehicles = [], isLoading: vehiclesLoading } = useQuery({
|
||||
queryKey: ["vehicles", "free"],
|
||||
queryFn: () => vehiclesService.getAll({ status: "ACTIVE", availability: "FREE" }),
|
||||
queryFn: () =>
|
||||
vehiclesService.getAll({ status: "ACTIVE", availability: "FREE" }).then((r) => r.data),
|
||||
});
|
||||
|
||||
const vehicleOptions = useMemo(
|
||||
@@ -85,13 +87,32 @@ export function LastMileContainerAllocationTable({
|
||||
});
|
||||
|
||||
const allocatedCount = Object.values(allocations).filter(Boolean).length;
|
||||
const allAllocated = allocatedCount === containers.length;
|
||||
|
||||
// Containers already loaded onto each vehicle, to enforce the 2-per-vehicle cap.
|
||||
const loadByVehicle = useMemo(() => {
|
||||
const map: Record<string, number> = {};
|
||||
for (const c of containers) {
|
||||
const v = allocations[c.id];
|
||||
if (v) map[v] = (map[v] ?? 0) + (c.qty || 1);
|
||||
}
|
||||
return map;
|
||||
}, [allocations, containers]);
|
||||
|
||||
/** Options for a given row: a vehicle is disabled if assigning this container
|
||||
* to it would exceed its 2-container capacity. */
|
||||
const optionsForRow = (row: LastMileContainerRow) =>
|
||||
vehicleOptions.map((o) => {
|
||||
const already = loadByVehicle[o.value] ?? 0;
|
||||
const selfHere = allocations[row.id] === o.value ? row.qty || 1 : 0;
|
||||
const over = already - selfHere + (row.qty || 1) > CONTAINERS_PER_VEHICLE;
|
||||
return { ...o, disabled: over };
|
||||
});
|
||||
|
||||
if (vehiclesLoading) {
|
||||
return (
|
||||
<Box display="flex" justifyContent="center" p="xl">
|
||||
<Group justify="center" p="xl">
|
||||
<Loader size="sm" />
|
||||
</Box>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -126,7 +147,7 @@ export function LastMileContainerAllocationTable({
|
||||
<Table.Td>
|
||||
<Select
|
||||
placeholder="Select vehicle"
|
||||
data={vehicleOptions}
|
||||
data={optionsForRow(container)}
|
||||
value={allocations[container.id] ?? null}
|
||||
onChange={(value) =>
|
||||
setAllocations((prev) => ({
|
||||
@@ -148,7 +169,8 @@ export function LastMileContainerAllocationTable({
|
||||
|
||||
<Group justify="space-between">
|
||||
<Text size="sm" c="dimmed">
|
||||
{allocatedCount} of {containers.length} containers allocated
|
||||
{allocatedCount} of {containers.length} containers allocated · max{" "}
|
||||
{CONTAINERS_PER_VEHICLE} per vehicle
|
||||
</Text>
|
||||
<Button
|
||||
color="edr-green"
|
||||
|
||||
Reference in New Issue
Block a user