This commit is contained in:
natib21
2026-06-29 08:37:48 +00:00
parent 86c51574b9
commit 40320d247a

View File

@@ -18,10 +18,12 @@ import {
Button,
Card,
Checkbox,
DateInput,
Divider,
Group,
Menu,
Modal,
NumberInput,
Select,
SimpleGrid,
Stack,
@@ -327,6 +329,10 @@ const FirstMilePage = () => {
const [acceptVehicleValue, setAcceptVehicleValue] = useState<string | null>(null);
const [bookingSearch, setBookingSearch] = useState("");
const [distanceOpen, setDistanceOpen] = useState(false);
const [distanceValue, setDistanceValue] = useState("");
const [distanceDate, setDistanceDate] = useState<Date | null>(null);
const { data: listData, isLoading } = useQuery({
queryKey: QUERY_KEYS.FIRST_MILE.list(),
queryFn: async () => {
@@ -379,6 +385,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({
mutationFn: async ({ reference, vehicleId }: { reference: string; vehicleId: string | null }) => {
const res = await firstMileService.accept(reference);
@@ -454,6 +475,29 @@ const FirstMilePage = () => {
acceptMutation.mutate({ reference: selectedBooking.reference, vehicleId: acceptVehicleValue });
};
const openDistance = (id: string) => {
setActiveId(id);
setDistanceValue("");
setDistanceDate(new Date());
setDistanceOpen(true);
};
const closeDistance = () => {
setDistanceOpen(false);
setActiveId(null);
setDistanceValue("");
setDistanceDate(null);
};
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) => {
switch (statusFilter) {
case "ALL": return true;
@@ -726,6 +770,11 @@ const FirstMilePage = () => {
>
View detail
</Menu.Item>
<Menu.Item
onClick={() => openDistance(row.original.id)}
>
Add Actual distance
</Menu.Item>
{canPrint && (
<Menu.Item
leftSection={<Printer size={15} />}
@@ -1030,6 +1079,59 @@ const FirstMilePage = () => {
</Stack>
)}
</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}
/>
<DateInput
label="Date"
placeholder="Select date"
value={distanceDate}
onChange={setDistanceDate}
/>
<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>
);
};