mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 17:38:12 +00:00
Merge pull request #326 from Tria-plc/freight/feature/vehicle_2
Freight/feature/vehicle 2
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
|||||||
Group,
|
Group,
|
||||||
Menu,
|
Menu,
|
||||||
Modal,
|
Modal,
|
||||||
|
NumberInput,
|
||||||
Select,
|
Select,
|
||||||
SimpleGrid,
|
SimpleGrid,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -327,6 +328,9 @@ const FirstMilePage = () => {
|
|||||||
const [acceptVehicleValue, setAcceptVehicleValue] = useState<string | null>(null);
|
const [acceptVehicleValue, setAcceptVehicleValue] = useState<string | null>(null);
|
||||||
const [bookingSearch, setBookingSearch] = useState("");
|
const [bookingSearch, setBookingSearch] = useState("");
|
||||||
|
|
||||||
|
const [distanceOpen, setDistanceOpen] = useState(false);
|
||||||
|
const [distanceValue, setDistanceValue] = useState("");
|
||||||
|
|
||||||
const { data: listData, isLoading } = useQuery({
|
const { data: listData, isLoading } = useQuery({
|
||||||
queryKey: QUERY_KEYS.FIRST_MILE.list(),
|
queryKey: QUERY_KEYS.FIRST_MILE.list(),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
@@ -379,6 +383,21 @@ const FirstMilePage = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updateDistanceMutation = useMutation({
|
||||||
|
mutationFn: ({ id, exactKm }: { id: string; exactKm: number }) =>
|
||||||
|
firstMileService.update(id, { exactKm }),
|
||||||
|
onSuccess: () => {
|
||||||
|
void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT });
|
||||||
|
if (activeRecord) {
|
||||||
|
toast({ title: "Distance updated", description: `${bookingRef(activeRecord)} → ${distanceValue} km` });
|
||||||
|
}
|
||||||
|
closeDistance();
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
toast({ title: "Update failed", variant: "destructive" });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const acceptMutation = useMutation({
|
const acceptMutation = useMutation({
|
||||||
mutationFn: async ({ reference, vehicleId }: { reference: string; vehicleId: string | null }) => {
|
mutationFn: async ({ reference, vehicleId }: { reference: string; vehicleId: string | null }) => {
|
||||||
const res = await firstMileService.accept(reference);
|
const res = await firstMileService.accept(reference);
|
||||||
@@ -454,6 +473,27 @@ const FirstMilePage = () => {
|
|||||||
acceptMutation.mutate({ reference: selectedBooking.reference, vehicleId: acceptVehicleValue });
|
acceptMutation.mutate({ reference: selectedBooking.reference, vehicleId: acceptVehicleValue });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openDistance = (id: string) => {
|
||||||
|
setActiveId(id);
|
||||||
|
setDistanceValue("");
|
||||||
|
setDistanceOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDistance = () => {
|
||||||
|
setDistanceOpen(false);
|
||||||
|
setActiveId(null);
|
||||||
|
setDistanceValue("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveDistance = () => {
|
||||||
|
const distance = parseFloat(distanceValue);
|
||||||
|
if (!activeId || isNaN(distance) || distance < 0) {
|
||||||
|
toast({ title: "Invalid distance", description: "Enter a valid distance value.", variant: "destructive" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateDistanceMutation.mutate({ id: activeId, exactKm: distance });
|
||||||
|
};
|
||||||
|
|
||||||
const matchesFilter = (r: FirstMileRecord) => {
|
const matchesFilter = (r: FirstMileRecord) => {
|
||||||
switch (statusFilter) {
|
switch (statusFilter) {
|
||||||
case "ALL": return true;
|
case "ALL": return true;
|
||||||
@@ -726,6 +766,11 @@ const FirstMilePage = () => {
|
|||||||
>
|
>
|
||||||
View detail
|
View detail
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
onClick={() => openDistance(row.original.id)}
|
||||||
|
>
|
||||||
|
Add Actual distance
|
||||||
|
</Menu.Item>
|
||||||
{canPrint && (
|
{canPrint && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
leftSection={<Printer size={15} />}
|
leftSection={<Printer size={15} />}
|
||||||
@@ -1030,6 +1075,53 @@ const FirstMilePage = () => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
{/* Add Actual Distance modal */}
|
||||||
|
<Modal
|
||||||
|
opened={distanceOpen}
|
||||||
|
onClose={closeDistance}
|
||||||
|
title={<Text fw={600}>Add Actual Distance</Text>}
|
||||||
|
size="md"
|
||||||
|
radius="lg"
|
||||||
|
centered
|
||||||
|
>
|
||||||
|
<Stack gap="md">
|
||||||
|
{activeRecord && (
|
||||||
|
<Card withBorder padding="md" radius="md" bg="var(--mantine-color-gray-0)">
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Text fw={600} size="sm">{bookingRef(activeRecord)}</Text>
|
||||||
|
<Group justify="space-between">
|
||||||
|
<Text size="xs" c="dimmed">Customer</Text>
|
||||||
|
<Text size="sm">{customerName(activeRecord)}</Text>
|
||||||
|
</Group>
|
||||||
|
<Group justify="space-between">
|
||||||
|
<Text size="xs" c="dimmed">Est. Distance (KM)</Text>
|
||||||
|
<Text size="sm">{activeRecord.estimatedKm ?? "—"}</Text>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
<NumberInput
|
||||||
|
label="Actual Distance (KM)"
|
||||||
|
placeholder="Enter distance"
|
||||||
|
value={distanceValue}
|
||||||
|
onChange={(v) => setDistanceValue(String(v ?? ""))}
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
decimalScale={2}
|
||||||
|
/>
|
||||||
|
<Group justify="flex-end" gap="sm">
|
||||||
|
<Button variant="default" onClick={closeDistance}>Cancel</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleSaveDistance}
|
||||||
|
loading={updateDistanceMutation.isPending}
|
||||||
|
disabled={!distanceValue}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Modal>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user