mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 19:30:57 +00:00
203 lines
6.4 KiB
TypeScript
203 lines
6.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import {
|
|
Button,
|
|
Group,
|
|
Modal,
|
|
NumberInput,
|
|
Select,
|
|
Stack,
|
|
TextInput,
|
|
} from '@mantine/core';
|
|
|
|
import { useToast } from '@/hooks/use-toast';
|
|
import { useStations } from '@/hooks/useStations';
|
|
import { useCreateWarehouse, useUpdateWarehouse } from '@/hooks/useWarehouses';
|
|
import type { SaveWarehousePayload, Warehouse, WarehouseType } from '@/types/warehouse';
|
|
import { extractErrorMessage, statusOptions, warehouseTypeOptions } from './options';
|
|
|
|
interface CreateWarehouseModalProps {
|
|
opened: boolean;
|
|
onClose: () => void;
|
|
warehouse?: Warehouse | null;
|
|
}
|
|
|
|
interface FormState {
|
|
name: string;
|
|
code: string;
|
|
type: WarehouseType;
|
|
stationId: string | null;
|
|
locationName: string;
|
|
capacityWeight: number | '';
|
|
capacityContainers: number | '';
|
|
maxVolume: number | '';
|
|
status: 'ACTIVE' | 'INACTIVE';
|
|
}
|
|
|
|
const emptyForm = (): FormState => ({
|
|
name: '',
|
|
code: '',
|
|
type: 'OPEN_WAREHOUSE',
|
|
stationId: null,
|
|
locationName: '',
|
|
capacityWeight: '',
|
|
capacityContainers: '',
|
|
maxVolume: '',
|
|
status: 'ACTIVE',
|
|
});
|
|
|
|
export function CreateWarehouseModal({ opened, onClose, warehouse }: CreateWarehouseModalProps) {
|
|
const isEdit = Boolean(warehouse);
|
|
const { toast } = useToast();
|
|
const createMutation = useCreateWarehouse();
|
|
const updateMutation = useUpdateWarehouse();
|
|
const { data: stations } = useStations();
|
|
const [form, setForm] = useState<FormState>(emptyForm());
|
|
|
|
const stationOptions = (stations ?? []).map((s) => ({ value: s.id, label: `${s.name} (${s.code})` }));
|
|
|
|
useEffect(() => {
|
|
if (opened) {
|
|
setForm(
|
|
warehouse
|
|
? {
|
|
name: warehouse.name,
|
|
code: warehouse.code,
|
|
type: warehouse.type,
|
|
stationId: warehouse.stationId ?? null,
|
|
locationName: warehouse.locationName ?? '',
|
|
capacityWeight: warehouse.capacityWeight ?? '',
|
|
capacityContainers: warehouse.capacityContainers ?? '',
|
|
maxVolume: warehouse.maxVolume ?? '',
|
|
status: warehouse.status,
|
|
}
|
|
: emptyForm(),
|
|
);
|
|
}
|
|
}, [opened, warehouse]);
|
|
|
|
const submitting = createMutation.isPending || updateMutation.isPending;
|
|
|
|
const handleSubmit = async () => {
|
|
if (!form.name.trim() || !form.code.trim()) {
|
|
toast({ variant: 'destructive', title: 'Name and code are required' });
|
|
return;
|
|
}
|
|
|
|
const payload: SaveWarehousePayload = {
|
|
name: form.name.trim(),
|
|
code: form.code.trim(),
|
|
type: form.type,
|
|
stationId: form.stationId ?? undefined,
|
|
locationName: form.locationName.trim() || undefined,
|
|
capacityWeight: form.capacityWeight === '' ? undefined : Number(form.capacityWeight),
|
|
capacityContainers: form.capacityContainers === '' ? undefined : Number(form.capacityContainers),
|
|
maxVolume: form.maxVolume === '' ? undefined : Number(form.maxVolume),
|
|
};
|
|
|
|
try {
|
|
if (warehouse) {
|
|
await updateMutation.mutateAsync({ id: warehouse.id, payload: { ...payload, status: form.status } });
|
|
toast({ title: 'Warehouse updated' });
|
|
} else {
|
|
await createMutation.mutateAsync(payload);
|
|
toast({ title: 'Warehouse created' });
|
|
}
|
|
onClose();
|
|
} catch (error) {
|
|
toast({ variant: 'destructive', title: 'Save failed', description: extractErrorMessage(error) });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal opened={opened} onClose={onClose} title={isEdit ? 'Edit warehouse' : 'Create warehouse'} centered size="lg">
|
|
<Stack gap="md">
|
|
<Group grow>
|
|
<TextInput
|
|
label="Name"
|
|
placeholder="Modjo Open Warehouse"
|
|
required
|
|
value={form.name}
|
|
onChange={(e) => { const v = e.currentTarget.value; setForm((f) => ({ ...f, name: v })); }}
|
|
/>
|
|
<TextInput
|
|
label="Code"
|
|
placeholder="MODJO-OW"
|
|
required
|
|
value={form.code}
|
|
onChange={(e) => { const v = e.currentTarget.value; setForm((f) => ({ ...f, code: v })); }}
|
|
/>
|
|
</Group>
|
|
|
|
<Select
|
|
label="Facility / Port (Station)"
|
|
placeholder="Select parent station"
|
|
data={stationOptions}
|
|
value={form.stationId}
|
|
onChange={(value) => setForm((f) => ({ ...f, stationId: value }))}
|
|
searchable
|
|
clearable
|
|
/>
|
|
|
|
<Group grow>
|
|
<Select
|
|
label="Type"
|
|
data={warehouseTypeOptions}
|
|
value={form.type}
|
|
onChange={(value) => setForm((f) => ({ ...f, type: (value as WarehouseType) ?? 'OPEN_WAREHOUSE' }))}
|
|
allowDeselect={false}
|
|
/>
|
|
{isEdit && (
|
|
<Select
|
|
label="Status"
|
|
data={statusOptions}
|
|
value={form.status}
|
|
onChange={(value) => setForm((f) => ({ ...f, status: (value as 'ACTIVE' | 'INACTIVE') ?? 'ACTIVE' }))}
|
|
allowDeselect={false}
|
|
/>
|
|
)}
|
|
</Group>
|
|
|
|
<TextInput
|
|
label="Location name"
|
|
placeholder="Modjo, Oromia"
|
|
value={form.locationName}
|
|
onChange={(e) => { const v = e.currentTarget.value; setForm((f) => ({ ...f, locationName: v })); }}
|
|
/>
|
|
|
|
<Group grow>
|
|
<NumberInput
|
|
label="Capacity weight (kg)"
|
|
placeholder="Optional"
|
|
min={0}
|
|
value={form.capacityWeight}
|
|
onChange={(value) => setForm((f) => ({ ...f, capacityWeight: value === '' ? '' : Number(value) }))}
|
|
/>
|
|
<NumberInput
|
|
label="Capacity containers"
|
|
placeholder="Optional"
|
|
min={0}
|
|
value={form.capacityContainers}
|
|
onChange={(value) => setForm((f) => ({ ...f, capacityContainers: value === '' ? '' : Number(value) }))}
|
|
/>
|
|
<NumberInput
|
|
label="Max volume (m³)"
|
|
placeholder="Optional"
|
|
min={0}
|
|
value={form.maxVolume}
|
|
onChange={(value) => setForm((f) => ({ ...f, maxVolume: value === '' ? '' : Number(value) }))}
|
|
/>
|
|
</Group>
|
|
|
|
<Group justify="flex-end" mt="sm">
|
|
<Button variant="default" onClick={onClose} disabled={submitting}>
|
|
Cancel
|
|
</Button>
|
|
<Button onClick={handleSubmit} loading={submitting}>
|
|
{isEdit ? 'Save changes' : 'Create warehouse'}
|
|
</Button>
|
|
</Group>
|
|
</Stack>
|
|
</Modal>
|
|
);
|
|
}
|