mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 07:45:45 +00:00
Warehouse and customer truck edit and KG to Tons
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user