feat: complete train scheduling integration

This commit is contained in:
hagiye
2026-06-06 05:52:47 +03:00
parent 29247d4140
commit 788de5381e
56 changed files with 1191 additions and 141 deletions

View File

@@ -4,6 +4,8 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@edr/ui-common';
import { useWagonTypes } from '@/hooks/use-wagon-types';
import { useCreateWagon, useUpdateWagon } from '@/hooks/useWagons';
import { useToast } from '@/hooks/use-toast';
@@ -25,6 +27,7 @@ export function WagonFormDialog({ trigger, wagon, onSuccess }: WagonFormDialogPr
});
const createWagon = useCreateWagon();
const updateWagon = useUpdateWagon();
const { data: wagonTypes = [], isLoading: wagonTypesLoading } = useWagonTypes();
const { toast } = useToast();
useEffect(() => {
@@ -40,6 +43,10 @@ export function WagonFormDialog({ trigger, wagon, onSuccess }: WagonFormDialogPr
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!form.wagonNumber || !form.wagonTypeId) {
toast({ title: 'Missing required field', description: 'Please select a wagon type.', variant: 'destructive' });
return;
}
try {
if (wagon) await updateWagon.mutateAsync({ id: wagon.id, data: form });
else await createWagon.mutateAsync(form);
@@ -57,10 +64,37 @@ export function WagonFormDialog({ trigger, wagon, onSuccess }: WagonFormDialogPr
<DialogContent>
<DialogHeader><DialogTitle>{wagon ? 'Edit Wagon' : 'Create Wagon'}</DialogTitle></DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div><Label>Wagon Number*</Label><Input required value={form.wagonNumber} onChange={e => setForm({...form, wagonNumber: e.target.value})} /></div>
<div><Label>Wagon Type ID*</Label><Input required value={form.wagonTypeId} onChange={e => setForm({...form, wagonTypeId: e.target.value})} /></div>
<div><Label>Tare Weight (kg)*</Label><Input type="number" required value={form.tareWeight} onChange={e => setForm({...form, tareWeight: parseFloat(e.target.value)})} /></div>
<div><Label>Max Payload (kg)*</Label><Input type="number" required value={form.maxPayloadWeight} onChange={e => setForm({...form, maxPayloadWeight: parseFloat(e.target.value)})} /></div>
<div><Label>Wagon Number*</Label><Input value={form.wagonNumber} onChange={e => setForm({...form, wagonNumber: e.target.value})} /></div>
<div>
<Label>Wagon Type*</Label>
<Select
value={form.wagonTypeId}
disabled={wagonTypesLoading}
onValueChange={(value) => {
const selectedType = wagonTypes.find((type: any) => type.id === value);
setForm((current) => ({
...current,
wagonTypeId: value,
maxPayloadWeight: current.maxPayloadWeight > 0
? current.maxPayloadWeight
: Number(selectedType?.capacityTons ?? current.maxPayloadWeight),
}));
}}
>
<SelectTrigger>
<SelectValue placeholder="Select wagon type" />
</SelectTrigger>
<SelectContent>
{wagonTypes.map((type: any) => (
<SelectItem key={type.id} value={type.id}>
{type.code} - {type.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div><Label>Tare Weight (kg)*</Label><Input type="number" value={form.tareWeight} onChange={e => setForm({...form, tareWeight: Number(e.target.value)})} /></div>
<div><Label>Max Payload (kg)*</Label><Input type="number" value={form.maxPayloadWeight} onChange={e => setForm({...form, maxPayloadWeight: Number(e.target.value)})} /></div>
<div><Label>Status</Label><Input value={form.status} onChange={e => setForm({...form, status: e.target.value})} /></div>
<div><Label>Notes</Label><Input value={form.notes} onChange={e => setForm({...form, notes: e.target.value})} /></div>
<Button type="submit" disabled={createWagon.isPending || updateWagon.isPending}>Save</Button>
@@ -68,4 +102,4 @@ export function WagonFormDialog({ trigger, wagon, onSuccess }: WagonFormDialogPr
</DialogContent>
</Dialog>
);
}
}

View File

@@ -12,8 +12,10 @@ import {
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@edr/ui-common';
import { Textarea } from '@/components/ui/textarea';
import { Loader2 } from 'lucide-react';
import { useWagonTypes } from '@/hooks/use-wagon-types';
interface Wagon {
id: string;
@@ -49,6 +51,7 @@ export default function WagonFormDialog({
onSuccess,
}: WagonFormDialogProps) {
const queryClient = useQueryClient();
const { data: wagonTypes = [], isLoading: wagonTypesLoading } = useWagonTypes();
const [formData, setFormData] = useState<Partial<Wagon>>({
wagonNumber: '',
wagonTypeId: '',
@@ -146,15 +149,31 @@ export default function WagonFormDialog({
</div>
<div>
<Label htmlFor="wagonTypeId">Type *</Label>
<Input
id="wagonTypeId"
<Select
value={formData.wagonTypeId || ''}
onChange={(e) =>
setFormData({ ...formData, wagonTypeId: e.target.value })
}
placeholder="e.g., Flat Bed"
required
/>
disabled={wagonTypesLoading}
onValueChange={(value) => {
const selectedType = wagonTypes.find((type: any) => type.id === value);
setFormData({
...formData,
wagonTypeId: value,
capacity: formData.capacity && formData.capacity > 0
? formData.capacity
: Number(selectedType?.capacityTons ?? 0),
});
}}
>
<SelectTrigger id="wagonTypeId">
<SelectValue placeholder="Select wagon type" />
</SelectTrigger>
<SelectContent>
{wagonTypes.map((type: any) => (
<SelectItem key={type.id} value={type.id}>
{type.code} - {type.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>