Warehouse and customer truck edit and KG to Tons

This commit is contained in:
Hagernesh
2026-07-08 05:19:25 +00:00
parent 22a2a770d2
commit ba821b06ca
5 changed files with 257 additions and 57 deletions

View File

@@ -15,7 +15,7 @@ import {
} from "@mantine/core";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { Freight } from "@edr/types";
import { CheckCircle2, Clock, Download, Plus, Trash2, Truck } from "lucide-react";
import { CheckCircle2, Clock, Download, Pencil, Plus, Trash2, Truck } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
@@ -63,14 +63,19 @@ export function CustomerTruckAssignmentCard({
const [driverName, setDriverName] = useState("");
const [truckType, setTruckType] = useState("");
const [containers, setContainers] = useState<string[]>([]);
const [editingId, setEditingId] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
// Container numbers on the booking that aren't already loaded onto a truck.
const assignedNumbers = new Set(
trucks.flatMap((t) => (t.containers ?? []).map((c) => c.containerNumber)),
);
// When editing a truck, its own containers stay selectable.
const editingOwn = new Set(
(trucks.find((t) => t.id === editingId)?.containers ?? []).map((c) => c.containerNumber),
);
const availableContainers = (booking.containerNumbers ?? []).filter(
(n) => !assignedNumbers.has(n),
(n) => !assignedNumbers.has(n) || editingOwn.has(n),
);
// Both import and export specify the containers each truck carries.
@@ -79,24 +84,38 @@ export function CustomerTruckAssignmentCard({
setDriverName("");
setTruckType("");
setContainers([]);
setEditingId(null);
setError(null);
};
const startEdit = (t: Freight.ICustomerTruck) => {
setPlateNumber(t.plateNumber ?? "");
setDriverName(t.driverName ?? "");
setTruckType(t.truckType ?? "");
setContainers((t.containers ?? []).map((c) => c.containerNumber));
setEditingId(t.id);
setError(null);
};
const addMutation = useMutation({
mutationFn: () =>
customerTrucksService.add(booking.id, {
mutationFn: () => {
const payload = {
truckPlateNumber: plateNumber.trim().toUpperCase(),
driverName: driverName.trim(),
truckType: truckType.trim(),
containerNumbers: containers,
}),
};
return editingId
? customerTrucksService.update(booking.id, editingId, payload)
: customerTrucksService.add(booking.id, payload);
},
onSuccess: (list) => {
queryClient.setQueryData(trucksKey, list);
toast.success(editingId ? "Truck updated" : "Truck added");
resetForm();
onAssigned();
toast.success("Truck added");
},
onError: (e) => setError(errorMessage(e, "Could not add truck")),
onError: (e) => setError(errorMessage(e, editingId ? "Could not update truck" : "Could not add truck")),
});
const removeMutation = useMutation({
@@ -183,15 +202,25 @@ export function CustomerTruckAssignmentCard({
</Group>
</Stack>
{!t.arrivedAt && (
<ActionIcon
variant="subtle"
color="red"
aria-label="Remove truck"
onClick={() => removeMutation.mutate(t.id)}
loading={removeMutation.isPending}
>
<Trash2 size={16} />
</ActionIcon>
<Group gap={4} wrap="nowrap">
<ActionIcon
variant="subtle"
color="blue"
aria-label="Edit truck"
onClick={() => startEdit(t)}
>
<Pencil size={16} />
</ActionIcon>
<ActionIcon
variant="subtle"
color="red"
aria-label="Remove truck"
onClick={() => removeMutation.mutate(t.id)}
loading={removeMutation.isPending}
>
<Trash2 size={16} />
</ActionIcon>
</Group>
)}
</Group>
))
@@ -206,7 +235,7 @@ export function CustomerTruckAssignmentCard({
{/* Add-truck form — both directions assign the containers each truck carries. */}
{availableContainers.length > 0 ? (
<>
<Divider label="Add a truck" labelPosition="center" />
<Divider label={editingId ? "Edit truck" : "Add a truck"} labelPosition="center" />
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
<TextInput
label="Truck Plate Number"
@@ -241,13 +270,18 @@ export function CustomerTruckAssignmentCard({
/>
</SimpleGrid>
<Group justify="flex-end">
{editingId && (
<Button variant="default" onClick={resetForm} disabled={addMutation.isPending}>
Cancel
</Button>
)}
<Button
leftSection={<Plus size={16} />}
leftSection={editingId ? <Pencil size={16} /> : <Plus size={16} />}
color="edr-green"
onClick={submitAdd}
loading={addMutation.isPending}
>
Add truck
{editingId ? "Save changes" : "Add truck"}
</Button>
</Group>
</>

View File

@@ -23,6 +23,15 @@ export const customerTrucksService = {
return data.data ?? data;
},
update: async (
bookingId: string,
assignmentId: string,
payload: Freight.AddCustomerTruckPayload,
): Promise<Freight.ICustomerTruck[]> => {
const { data } = await client.patch(B.CUSTOMER_TRUCK(bookingId, assignmentId), payload);
return data.data ?? data;
},
remove: async (
bookingId: string,
assignmentId: string,