mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 18:20:57 +00:00
104 lines
2.9 KiB
TypeScript
104 lines
2.9 KiB
TypeScript
import { useState, useMemo } from "react";
|
|
import { Plus } from "lucide-react";
|
|
import { Button, Group, Modal, NumberInput, Select, Stack, Text } from "@mantine/core";
|
|
|
|
import { Freight } from "@edr/types";
|
|
|
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
|
|
import { api } from "@/services/api";
|
|
import { useToast } from "@/hooks/use-toast";
|
|
|
|
export function AssignWagonDialog({ trainId }: { trainId: string }) {
|
|
const [open, setOpen] = useState(false);
|
|
const [wagonId, setWagonId] = useState<string | null>(null);
|
|
const [sequence, setSequence] = useState<number | "">("");
|
|
const { data: wagons } = useQuery(api.wagons.list.queryOptions({ input: {} }));
|
|
const { data: yards = [] } = useQuery(api.routes.yards.queryOptions());
|
|
const assign = useMutation(api.wagons.assignToTrain.mutationOptions());
|
|
const { toast } = useToast();
|
|
|
|
const available = (wagons ?? []).filter(
|
|
(w) => w.status === Freight.WagonStatus.Available || !w.trainId,
|
|
);
|
|
|
|
const yardLabelById = useMemo(
|
|
() =>
|
|
new Map(
|
|
yards.map((y) => [y.id, y.label ?? y.code ?? y.id]),
|
|
),
|
|
[yards],
|
|
);
|
|
|
|
const wagonOptions = available.map((w) => ({
|
|
value: w.id,
|
|
label: w.currentYardId
|
|
? `${w.wagonNumber} (${yardLabelById.get(w.currentYardId) ?? "yard"})`
|
|
: `${w.wagonNumber} (no yard)`,
|
|
}));
|
|
|
|
const handleAssign = async () => {
|
|
if (!wagonId) return;
|
|
try {
|
|
await assign.mutateAsync({
|
|
wagonId,
|
|
trainId,
|
|
sequenceNumber: sequence === "" ? undefined : Number(sequence),
|
|
});
|
|
toast({ title: "Wagon attached to train" });
|
|
setOpen(false);
|
|
setWagonId(null);
|
|
setSequence("");
|
|
} catch {
|
|
toast({ title: "Failed to assign wagon", variant: "destructive" });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
color="edr-green"
|
|
size="sm"
|
|
radius="lg"
|
|
leftSection={<Plus size={16} />}
|
|
onClick={() => setOpen(true)}
|
|
>
|
|
Assign wagon
|
|
</Button>
|
|
|
|
<Modal
|
|
opened={open}
|
|
onClose={() => setOpen(false)}
|
|
title={<Text fw={600}>Assign wagon to train</Text>}
|
|
radius="lg"
|
|
centered
|
|
>
|
|
<Stack gap="md">
|
|
<Select
|
|
label="Wagon"
|
|
placeholder="Select wagon"
|
|
data={wagonOptions}
|
|
value={wagonId}
|
|
onChange={setWagonId}
|
|
searchable
|
|
/>
|
|
<NumberInput
|
|
label="Sequence (optional)"
|
|
value={sequence}
|
|
onChange={(value) => setSequence(value === "" ? "" : Number(value))}
|
|
min={1}
|
|
/>
|
|
<Group justify="flex-end">
|
|
<Button variant="default" onClick={() => setOpen(false)}>
|
|
Cancel
|
|
</Button>
|
|
<Button color="edr-green" loading={assign.isPending} onClick={handleAssign}>
|
|
Assign
|
|
</Button>
|
|
</Group>
|
|
</Stack>
|
|
</Modal>
|
|
</>
|
|
);
|
|
}
|