diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx
index 8e39ea53e..465b59aca 100644
--- a/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx
+++ b/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx
@@ -51,6 +51,7 @@ import { warehouseService } from '@/services/warehouse.service';
import type {
EligibleBooking,
InventoryInquiryFilter,
+ InventoryStatus,
InventoryInquiryResult,
ImportTrain,
ImportTrainItem,
@@ -63,6 +64,7 @@ import type {
WarehouseYard,
WarehouseZone,
} from '@/types/warehouse';
+import { InventoryStatusBadge } from './badges';
import { BookingSelect } from './BookingSelect';
import { DeliverInventoryModal } from './DeliverInventoryModal';
import { ContainerItemsModal } from './ContainerItemsModal';
@@ -253,6 +255,50 @@ const toTruckEntrancePayload = (form: TruckEntranceFormState): TruckEntrancePayl
warehouseManagerName: form.warehouseManagerName.trim() || undefined,
});
+
+
+type ConfirmAction = { title: string; message: string; confirmLabel: string; run: () => void };
+
+/** One-click bulk actions are irreversible — make the click deliberate. */
+function ConfirmActionModal({
+ action,
+ onClose,
+}: {
+ action: ConfirmAction | null;
+ onClose: () => void;
+}) {
+ return (
+
+
+ {action?.message}
+
+
+
+
+
+
+ );
+}
+
+/** "3 skipped — Booking not PAID" instead of a bare count. */
+const skippedSummary = (
+ skippedCount: number,
+ results: Array<{ reason?: string; message?: string }>,
+): string | undefined => {
+ if (!skippedCount) return undefined;
+ const reason = results.find((x) => x.reason || x.message);
+ return `${skippedCount} skipped${reason ? ` — ${reason.reason ?? reason.message}` : ''}`;
+};
+
const commonNonEmptyValue = (values: Array) => {
const unique = [...new Set(values.map((value) => value?.trim()).filter(Boolean))] as string[];
return unique.length === 1 ? unique[0] : '';
@@ -860,7 +906,7 @@ function EligibleTab({
});
toast({
title: `${r.receivedCount} received at ${direction === 'EXPORT' ? 'facility' : 'warehouse'}`,
- description: r.results.find((item) => item.grnNumber)?.grnNumber ?? (r.skippedCount ? `${r.skippedCount} skipped` : undefined),
+ description: r.results.find((item) => item.grnNumber)?.grnNumber ?? skippedSummary(r.skippedCount, r.results),
});
const firstGrn = r.results.find((item) => item.inventoryId && item.grnNumber);
if (focusedBookingId && firstGrn?.inventoryId && firstGrn.grnNumber) {
@@ -1030,7 +1076,7 @@ function EligibleTab({
: `No eligible PAID ${direction.toLowerCase()} bookings to receive.`}
) : (
-
+
@@ -1248,6 +1294,7 @@ function ExportReceivedTab({ enabled, onChanged }: { enabled: boolean; onChanged
api.warehouses.bulkMarkInspected.mutationOptions(),
);
const [selected, setSelected] = useState>(new Set());
+ const [confirmAction, setConfirmAction] = useState(null);
const [inspectId, setInspectId] = useState(null);
const pendingRows = rows.filter((r) => r.inspectionStatus !== 'PASSED');
@@ -1271,7 +1318,7 @@ function ExportReceivedTab({ enabled, onChanged }: { enabled: boolean; onChanged
const r = await inspectMutation.mutateAsync({ inventoryIds: [...selected] });
toast({
title: `${r.inspectedCount} marked inspected`,
- description: r.skippedCount ? `${r.skippedCount} skipped` : undefined,
+ description: skippedSummary(r.skippedCount, r.results),
});
setSelected(new Set());
onChanged?.();
@@ -1292,7 +1339,14 @@ function ExportReceivedTab({ enabled, onChanged }: { enabled: boolean; onChanged
leftSection={}
disabled={selected.size === 0}
loading={inspectMutation.isPending}
- onClick={markInspected}
+ onClick={() =>
+ setConfirmAction({
+ title: 'Mark inspected',
+ message: `Mark ${selected.size} selected item(s) as inspection PASSED?`,
+ confirmLabel: `Mark ${selected.size} inspected`,
+ run: markInspected,
+ })
+ }
>
Mark Selected as Inspected
@@ -1307,7 +1361,7 @@ function ExportReceivedTab({ enabled, onChanged }: { enabled: boolean; onChanged
No received export items awaiting inspection.
) : (
-
+
@@ -1363,9 +1417,7 @@ function ExportReceivedTab({ enabled, onChanged }: { enabled: boolean; onChanged
-
- {r.status}
-
+
@@ -2323,7 +2379,7 @@ function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) {
No unloaded import items. Items appear here after Auto Unload on an arrived train.
) : (
-
+
@@ -2384,7 +2440,7 @@ function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) {
- {r.currentStatus}
+
@@ -2506,6 +2562,7 @@ function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) {
bookingId={containerItemsItem?.booking?.id ?? null}
bookingReference={containerItemsItem?.booking?.reference ?? null}
/>
+ setConfirmAction(null)} />
);
}