Warehouse zone occupancy heatmap

Visualize live per-zone occupancy on the warehouse detail page.
This commit is contained in:
Hagernesh
2026-07-13 11:38:23 +00:00
parent 1034756bab
commit 4e8d35a7fb
18 changed files with 550 additions and 1 deletions

View File

@@ -57,6 +57,7 @@ import { vehiclesService } from "@/services/vehicles.service";
import { driversService, type Driver } from "@/services/drivers.service";
import { ReleaseOrderModal, type ReleaseOrderTruckPrefill } from "@/components/warehouses/ReleaseOrderModal";
import { TruckDetentionModal } from "@/components/operations/TruckDetentionModal";
import { ProofOfDeliveryModal } from "@/components/operations/ProofOfDeliveryModal";
import { LastMileStepper, type LastMileStepState } from "@/components/operations/LastMileSteps";
const formatPrice = (amount: number | string | null | undefined, currency = "ETB") =>
@@ -546,6 +547,7 @@ const buildTripSlipHtml = (record: LastMileRecord, vehicle?: TripSlipVehicle | n
const LastMilePage = () => {
const { toast } = useToast();
const qc = useQueryClient();
const [podRecord, setPodRecord] = useState<LastMileRecord | null>(null);
const navigate = useNavigate();
const { pagination, setPagination } = usePagination({ pageSize: 10 });
@@ -1031,6 +1033,12 @@ const LastMilePage = () => {
const handleAdvanceStatus = (record: LastMileRecord) => {
const next = NEXT_STATUS[record.status];
if (!next) return;
// Completing a delivery requires proof of delivery — open the capture modal
// instead of advancing straight to DELIVERED.
if (next === "DELIVERED") {
setPodRecord(record);
return;
}
updateMutation.mutate(
{ id: record.id, data: { status: next } },
{
@@ -2080,6 +2088,17 @@ const LastMilePage = () => {
onClose={() => setDetentionRecord(null)}
record={detentionRecord}
/>
<ProofOfDeliveryModal
opened={Boolean(podRecord)}
onClose={() => setPodRecord(null)}
lastMileId={podRecord?.id ?? null}
reference={podRecord?.booking?.reference ?? null}
onDone={() => {
void qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE.ROOT });
void qc.invalidateQueries({ queryKey: ["vehicles"] });
}}
/>
</Stack>
);
};

View File

@@ -23,6 +23,7 @@ import {
InventoryWorkbench,
WarehouseStatusBadge,
WarehouseTypeBadge,
ZoneOccupancyHeatmap,
formatCapacity,
humanizeEnum,
} from '@/components/warehouses';
@@ -298,6 +299,8 @@ export default function WarehouseDetailPage() {
</Button>
</Group>
<ZoneOccupancyHeatmap yardId={selectedYardId ?? undefined} />
{!selectedYardId ? (
<Text c="dimmed" ta="center" py="lg">
Select a yard to view its zones.