Files
edr-platform/apps/edr-freight-web/backoffice/src/components/warehouses/CreateWarehouseModal.tsx
Hagernesh f528b75737 Warehouse
2026-06-17 12:44:57 +00:00

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>
);
}