mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 04:08:11 +00:00
140 lines
4.3 KiB
TypeScript
140 lines
4.3 KiB
TypeScript
import { useEffect, useMemo, useState } from 'react';
|
|
import { Button, Group, Modal, Select, Stack, Textarea } from '@mantine/core';
|
|
|
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
|
|
|
import { api } from '@/services/api';
|
|
import { useToast } from '@/hooks/use-toast';
|
|
import type { WarehouseInventoryItem } from '@/types/warehouse';
|
|
import { extractErrorMessage } from './options';
|
|
|
|
interface MoveInventoryModalProps {
|
|
opened: boolean;
|
|
onClose: () => void;
|
|
item: WarehouseInventoryItem | null;
|
|
}
|
|
|
|
export function MoveInventoryModal({ opened, onClose, item }: MoveInventoryModalProps) {
|
|
const { toast } = useToast();
|
|
const moveMutation = useMutation(api.warehouses.move.mutationOptions());
|
|
const [warehouseId, setWarehouseId] = useState('');
|
|
const [yardId, setYardId] = useState('');
|
|
const [zoneId, setZoneId] = useState('');
|
|
const [remarks, setRemarks] = useState('');
|
|
|
|
useEffect(() => {
|
|
if (opened) {
|
|
setWarehouseId('');
|
|
setYardId('');
|
|
setZoneId('');
|
|
setRemarks('');
|
|
}
|
|
}, [opened]);
|
|
|
|
const warehousesQuery = useQuery(
|
|
api.warehouses.list.queryOptions({ input: { filter: { status: 'ACTIVE' } } }),
|
|
);
|
|
const yardsQuery = useQuery(
|
|
api.warehouses.listYards.queryOptions({
|
|
input: { warehouseId },
|
|
enabled: Boolean(warehouseId),
|
|
}),
|
|
);
|
|
const zonesQuery = useQuery(
|
|
api.warehouses.listZones.queryOptions({
|
|
input: { yardId },
|
|
enabled: Boolean(yardId),
|
|
}),
|
|
);
|
|
|
|
const warehouseOptions = useMemo(
|
|
() => (warehousesQuery.data ?? []).map((w) => ({ value: w.id, label: `${w.name} (${w.code})` })),
|
|
[warehousesQuery.data],
|
|
);
|
|
const yardOptions = useMemo(
|
|
() => (yardsQuery.data ?? []).filter((y) => y.status === 'ACTIVE').map((y) => ({ value: y.id, label: `${y.name} (${y.code})` })),
|
|
[yardsQuery.data],
|
|
);
|
|
const zoneOptions = useMemo(
|
|
() => (zonesQuery.data ?? []).filter((z) => z.status === 'ACTIVE').map((z) => ({ value: z.id, label: `${z.name} (${z.code})` })),
|
|
[zonesQuery.data],
|
|
);
|
|
|
|
const handleSubmit = async () => {
|
|
if (!item) return;
|
|
if (!warehouseId || !yardId || !zoneId) {
|
|
toast({ variant: 'destructive', title: 'Select destination warehouse, yard and zone' });
|
|
return;
|
|
}
|
|
try {
|
|
await moveMutation.mutateAsync({
|
|
id: item.id,
|
|
payload: { warehouseId, yardId, zoneId, remarks: remarks.trim() || undefined },
|
|
});
|
|
toast({ title: 'Inventory moved' });
|
|
onClose();
|
|
} catch (error) {
|
|
toast({ variant: 'destructive', title: 'Move failed', description: extractErrorMessage(error) });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal opened={opened} onClose={onClose} title="Move inventory" centered size="lg">
|
|
<Stack gap="md">
|
|
<Select
|
|
label="Destination warehouse"
|
|
placeholder="Select warehouse"
|
|
required
|
|
searchable
|
|
data={warehouseOptions}
|
|
value={warehouseId || null}
|
|
onChange={(v) => {
|
|
setWarehouseId(v ?? '');
|
|
setYardId('');
|
|
setZoneId('');
|
|
}}
|
|
/>
|
|
<Select
|
|
label="Destination yard"
|
|
placeholder={!warehouseId ? 'Select a warehouse first' : 'Select yard'}
|
|
required
|
|
searchable
|
|
disabled={!warehouseId}
|
|
data={yardOptions}
|
|
value={yardId || null}
|
|
onChange={(v) => {
|
|
setYardId(v ?? '');
|
|
setZoneId('');
|
|
}}
|
|
/>
|
|
<Select
|
|
label="Destination zone"
|
|
placeholder={!yardId ? 'Select a yard first' : 'Select zone'}
|
|
required
|
|
searchable
|
|
disabled={!yardId}
|
|
data={zoneOptions}
|
|
value={zoneId || null}
|
|
onChange={(v) => setZoneId(v ?? '')}
|
|
/>
|
|
<Textarea
|
|
label="Remarks"
|
|
placeholder="Reason for the move"
|
|
autosize
|
|
minRows={2}
|
|
value={remarks}
|
|
onChange={(e) => setRemarks(e.currentTarget.value)}
|
|
/>
|
|
<Group justify="flex-end" mt="sm">
|
|
<Button variant="default" onClick={onClose} disabled={moveMutation.isPending}>
|
|
Cancel
|
|
</Button>
|
|
<Button onClick={handleSubmit} loading={moveMutation.isPending}>
|
|
Move inventory
|
|
</Button>
|
|
</Group>
|
|
</Stack>
|
|
</Modal>
|
|
);
|
|
}
|