SELECT BOX

This commit is contained in:
Hagernesh
2026-07-11 08:18:04 +00:00
parent eec3d1863a
commit da44752c70
4 changed files with 180 additions and 6 deletions

View File

@@ -1550,6 +1550,18 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
const [trainPickerOpen, setTrainPickerOpen] = useState(false);
const [expandedRow, setExpandedRow] = useState<string | null>(null);
const [targetScheduleId, setTargetScheduleId] = useState<string | null>(null);
const [selected, setSelected] = useState<Set<string>>(new Set());
const allSelected = rows.length > 0 && selected.size === rows.length;
const someSelected = selected.size > 0 && !allSelected;
const toggleAll = () => setSelected(allSelected ? new Set() : new Set(rows.map((r) => r.id)));
const toggleOne = (id: string) =>
setSelected((prev) => {
const next = new Set(prev);
next.has(id) ? next.delete(id) : next.add(id);
return next;
});
// Loading is always onto a SPECIFIC pre-dispatch train. No train -> no auto-load.
const { data: trains = [], isLoading: trainsLoading } = useQuery({
queryKey: ['warehouse-inventory', 'loadable-trains'],
@@ -1557,11 +1569,20 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
enabled: enabled && trainPickerOpen,
});
const loadOntoTrain = useMutation({
mutationFn: async (scheduleId: string) => {
mutationFn: async ({ scheduleId, onlyIds }: { scheduleId: string; onlyIds: string[] }) => {
const items = await warehouseService.getTrainLoadableItems(scheduleId);
const loadableIds = items.filter((i) => i.loadable).map((i) => i.id);
let loadableIds = items.filter((i) => i.loadable).map((i) => i.id);
// When rows are checked, load only those; otherwise load every loadable item.
if (onlyIds.length) {
const picked = new Set(onlyIds);
loadableIds = loadableIds.filter((id) => picked.has(id));
}
if (!loadableIds.length) {
throw new Error('No ready items with an allocated wagon on this train');
throw new Error(
onlyIds.length
? 'None of the selected items have an allocated wagon on this train'
: 'No ready items with an allocated wagon on this train',
);
}
return warehouseService.loadItemsOntoTrain(scheduleId, loadableIds);
},
@@ -1578,7 +1599,10 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
return;
}
try {
const r = await loadOntoTrain.mutateAsync(targetScheduleId);
const r = await loadOntoTrain.mutateAsync({
scheduleId: targetScheduleId,
onlyIds: [...selected],
});
const train = trains.find((t) => t.scheduleId === targetScheduleId);
toast({
title: `${r.loadedCount} item(s) loaded onto train ${train?.trainNumber ?? ''}`.trim(),
@@ -1588,6 +1612,7 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
});
setTrainPickerOpen(false);
setTargetScheduleId(null);
setSelected(new Set());
onChanged?.();
} catch (error) {
toast({ variant: 'destructive', title: 'Load failed', description: extractErrorMessage(error) });
@@ -1598,7 +1623,11 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
<Stack gap="sm" mt="sm">
<Group justify="space-between">
<Text size="sm" c="dimmed">
<b>{rows.length}</b> item{rows.length !== 1 ? 's' : ''} ready to load
{selected.size > 0 ? (
<><b>{selected.size}</b> of {rows.length} selected</>
) : (
<><b>{rows.length}</b> item{rows.length !== 1 ? 's' : ''} ready to load</>
)}
</Text>
<Button
size="compact-sm"
@@ -1608,7 +1637,7 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
disabled={rows.length === 0}
onClick={() => setTrainPickerOpen(true)}
>
Auto Load Ready Items
{selected.size > 0 ? `Load Selected (${selected.size})` : 'Auto Load Ready Items'}
</Button>
</Group>
@@ -1670,6 +1699,14 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
<Table highlightOnHover verticalSpacing="xs" striped>
<Table.Thead>
<Table.Tr>
<Table.Th w={40}>
<Checkbox
aria-label="Select all"
checked={allSelected}
indeterminate={someSelected}
onChange={toggleAll}
/>
</Table.Th>
<Table.Th w={34} />
<Table.Th>Booking Ref</Table.Th>
<Table.Th>GRN</Table.Th>
@@ -1686,6 +1723,13 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?:
{rows.map((r: ReadyToLoadRow) => (
<Fragment key={r.id}>
<Table.Tr>
<Table.Td>
<Checkbox
aria-label={`Select ${r.bookingReference ?? r.id}`}
checked={selected.has(r.id)}
onChange={() => toggleOne(r.id)}
/>
</Table.Td>
<Table.Td>
<ActionIcon
variant="subtle"