refactor: migrated of the customer hooks for warehouse data fetching

This commit is contained in:
Nathnael
2026-06-22 12:25:20 +00:00
parent 74e03f2067
commit d66ccc5363
29 changed files with 336 additions and 704 deletions

View File

@@ -16,7 +16,9 @@ import {
VisualEmptyState,
formatDate,
} from '@/components/warehouses';
import { useArrivalQueue, useAutoUnloadArrived, useUnloadBooking } from '@/hooks/useWarehouses';
import { useMutation, useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import { useToast } from '@/hooks/use-toast';
import type { ArrivalQueueItem } from '@/types/warehouse';
@@ -30,17 +32,16 @@ function inspectionBadge(status: string | null) {
export default function ArrivalQueuePage() {
const navigate = useNavigate();
const { toast } = useToast();
const { data, isLoading } = useArrivalQueue();
const autoUnload = useAutoUnloadArrived();
const unloadOne = useUnloadBooking();
const { data, isLoading } = useQuery(api.warehouses.arrivalQueue.queryOptions());
const autoUnload = useMutation(api.warehouses.autoUnloadArrived.mutationOptions());
const unloadOne = useMutation(api.warehouses.unloadBooking.mutationOptions());
const [inspectInventoryId, setInspectInventoryId] = useState<string | null>(null);
const items = data ?? [];
const handleAutoUnload = async () => {
try {
const res = await autoUnload.mutateAsync();
const r = res.data;
const r = await autoUnload.mutateAsync();
toast({
title: 'Auto-unload complete',
description: `Processed ${r.processedCount}, skipped ${r.skippedCount}, failed ${r.failedCount}.`,

View File

@@ -1,12 +1,16 @@
import { Card } from '@mantine/core';
import { PageContainer, PageHeader } from '@/components/page';
import { useQuery } from '@tanstack/react-query';
import { InventoryWorkbench, VisualEmptyState } from '@/components/warehouses';
import { useWarehouseInventory } from '@/hooks/useWarehouses';
import { api } from '@/services/api';
/** Items that are LOADED and awaiting dispatch (train departure). */
export default function DispatchQueuePage() {
const { data, isLoading } = useWarehouseInventory({ status: 'LOADED' });
const { data, isLoading } = useQuery(
api.warehouses.listInventory.queryOptions({ input: { filter: { status: 'LOADED' } } }),
);
const items = data ?? [];
return (

View File

@@ -3,24 +3,35 @@ import { Button, Card, Center, Group, Loader, Select, Stack, TextInput } from '@
import { Search } from 'lucide-react';
import { PageContainer, PageHeader } from '@/components/page';
import { useQuery } from '@tanstack/react-query';
import { VisualEmptyState, WarehouseInquiryTable, inventoryStatusOptions } from '@/components/warehouses';
import {
useInventoryInquiry,
useWarehouseYards,
useWarehouseZones,
useWarehouses,
} from '@/hooks/useWarehouses';
import { api } from '@/services/api';
import type { InventoryInquiryFilter, InventoryStatus } from '@/types/warehouse';
export default function InventoryInquiryPage() {
const [draft, setDraft] = useState<InventoryInquiryFilter>({});
const [applied, setApplied] = useState<InventoryInquiryFilter>({});
const warehousesQuery = useWarehouses();
const yardsQuery = useWarehouseYards(draft.warehouseId);
const zonesQuery = useWarehouseZones(draft.yardId);
const warehousesQuery = useQuery(
api.warehouses.list.queryOptions({ input: {} }),
);
const yardsQuery = useQuery(
api.warehouses.listYards.queryOptions({
input: { warehouseId: draft.warehouseId ?? '' },
enabled: Boolean(draft.warehouseId),
}),
);
const zonesQuery = useQuery(
api.warehouses.listZones.queryOptions({
input: { yardId: draft.yardId ?? '' },
enabled: Boolean(draft.yardId),
}),
);
const { data, isFetching } = useInventoryInquiry(applied);
const { data, isFetching } = useQuery(
api.warehouses.inquiry.queryOptions({ input: { filter: applied } }),
);
const results = data ?? [];
const warehouseOptions = useMemo(

View File

@@ -2,10 +2,13 @@ import { Badge, Card, Group, Text } from '@mantine/core';
import { DataTable, type ColumnDef } from '@edr/ui-common';
import { PageContainer, PageHeader } from '@/components/page';
import { FreightVisual, VisualEmptyState, formatDate, formatNumber } from '@/components/warehouses';
import { useWarehouseLoadings } from '@/hooks/useWarehouses';
import { useQuery } from '@tanstack/react-query';
type Loading = NonNullable<ReturnType<typeof useWarehouseLoadings>['data']>[number];
import { FreightVisual, VisualEmptyState, formatDate, formatNumber } from '@/components/warehouses';
import { api } from '@/services/api';
import type { WarehouseLoading } from '@/types/warehouse';
type Loading = WarehouseLoading;
const columns: ColumnDef<Loading>[] = [
{
@@ -60,7 +63,9 @@ const columns: ColumnDef<Loading>[] = [
/** Record of every inventory item loaded onto a wagon. */
export default function LoadedInventoryPage() {
const { data, isLoading } = useWarehouseLoadings();
const { data, isLoading } = useQuery(
api.warehouses.loadings.queryOptions({ input: {} }),
);
const loadings = data ?? [];
return (

View File

@@ -10,7 +10,9 @@ import {
VisualEmptyState,
formatNumber,
} from '@/components/warehouses';
import { useAutoLoadReady, useWarehouseInventory } from '@/hooks/useWarehouses';
import { useMutation, useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import { useToast } from '@/hooks/use-toast';
import type { WarehouseInventoryItem } from '@/types/warehouse';
@@ -27,16 +29,19 @@ const isPaid = (item: WarehouseInventoryItem) => item.booking?.status === 'PAID'
export default function LoadingQueuePage() {
const navigate = useNavigate();
const { toast } = useToast();
const autoLoad = useAutoLoadReady();
const { data: readyData, isLoading: readyLoading } = useWarehouseInventory({
status: 'READY_FOR_LOADING',
});
const { data: loadedData, isLoading: loadedLoading } = useWarehouseInventory({ status: 'LOADED' });
const autoLoad = useMutation(api.warehouses.autoLoadReady.mutationOptions());
const { data: readyData, isLoading: readyLoading } = useQuery(
api.warehouses.listInventory.queryOptions({
input: { filter: { status: 'READY_FOR_LOADING' } },
}),
);
const { data: loadedData, isLoading: loadedLoading } = useQuery(
api.warehouses.listInventory.queryOptions({ input: { filter: { status: 'LOADED' } } }),
);
const handleAutoLoad = async () => {
try {
const res = await autoLoad.mutateAsync();
const r = res.data;
const r = await autoLoad.mutateAsync();
toast({
title: 'Auto-load complete',
description: `Loaded ${r.loadedCount} PAID item(s); skipped ${r.skippedCount} (unpaid stay pending).`,

View File

@@ -16,8 +16,10 @@ import {
} from 'lucide-react';
import { PageContainer, PageHeader } from '@/components/page';
import { useQuery } from '@tanstack/react-query';
import { WarehouseDashboardCharts } from '@/components/warehouses';
import { useWarehouseDashboard } from '@/hooks/useWarehouses';
import { api } from '@/services/api';
import type { WarehouseDashboard } from '@/types/warehouse';
interface Metric {
@@ -49,7 +51,7 @@ const METRICS: Metric[] = [
export default function WarehouseDashboardPage() {
const navigate = useNavigate();
const { data, isLoading } = useWarehouseDashboard();
const { data, isLoading } = useQuery(api.warehouses.dashboard.queryOptions());
return (
<PageContainer>

View File

@@ -27,20 +27,27 @@ import {
formatCapacity,
humanizeEnum,
} from '@/components/warehouses';
import {
useWarehouse,
useWarehouseInventory,
useWarehouseYards,
useWarehouseZones,
} from '@/hooks/useWarehouses';
import { useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import type { WarehouseYard, WarehouseZone } from '@/types/warehouse';
export default function WarehouseDetailPage() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { data: warehouse, isLoading } = useWarehouse(id);
const yardsQuery = useWarehouseYards(id);
const { data: warehouse, isLoading } = useQuery(
api.warehouses.getById.queryOptions({
input: { id: id ?? '' },
enabled: Boolean(id),
}),
);
const yardsQuery = useQuery(
api.warehouses.listYards.queryOptions({
input: { warehouseId: id ?? '' },
enabled: Boolean(id),
}),
);
const [yardModalOpen, setYardModalOpen] = useState(false);
const [editingYard, setEditingYard] = useState<WarehouseYard | null>(null);
@@ -49,9 +56,18 @@ export default function WarehouseDetailPage() {
const [editingZone, setEditingZone] = useState<WarehouseZone | null>(null);
const [selectedYardId, setSelectedYardId] = useState<string | null>(null);
const zonesQuery = useWarehouseZones(selectedYardId ?? undefined);
const zonesQuery = useQuery(
api.warehouses.listZones.queryOptions({
input: { yardId: selectedYardId ?? '' },
enabled: Boolean(selectedYardId),
}),
);
const inventoryQuery = useWarehouseInventory(id ? { warehouseId: id } : undefined);
const inventoryQuery = useQuery(
api.warehouses.listInventory.queryOptions({
input: { filter: id ? { warehouseId: id } : undefined },
}),
);
const yards = yardsQuery.data ?? [];
const yardOptions = useMemo(

View File

@@ -10,12 +10,9 @@ import {
ReceiveInventoryModal,
inventoryStatusOptions,
} from '@/components/warehouses';
import {
useWarehouseInventory,
useWarehouseYards,
useWarehouseZones,
useWarehouses,
} from '@/hooks/useWarehouses';
import { useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import type { InventoryFilter, InventoryStatus } from '@/types/warehouse';
export default function WarehouseInventoryPage() {
@@ -33,10 +30,24 @@ export default function WarehouseInventoryPage() {
[filter, debouncedSearch],
);
const warehousesQuery = useWarehouses();
const yardsQuery = useWarehouseYards(filter.warehouseId);
const zonesQuery = useWarehouseZones(filter.yardId);
const inventoryQuery = useWarehouseInventory(queryFilter);
const warehousesQuery = useQuery(
api.warehouses.list.queryOptions({ input: {} }),
);
const yardsQuery = useQuery(
api.warehouses.listYards.queryOptions({
input: { warehouseId: filter.warehouseId ?? '' },
enabled: Boolean(filter.warehouseId),
}),
);
const zonesQuery = useQuery(
api.warehouses.listZones.queryOptions({
input: { yardId: filter.yardId ?? '' },
enabled: Boolean(filter.yardId),
}),
);
const inventoryQuery = useQuery(
api.warehouses.listInventory.queryOptions({ input: { filter: queryFilter } }),
);
const warehouseOptions = useMemo(
() => (warehousesQuery.data ?? []).map((w) => ({ value: w.id, label: `${w.name} (${w.code})` })),

View File

@@ -19,13 +19,10 @@ import { Ban, CreditCard, Eye, Search } from 'lucide-react';
import { DataTable, type ColumnDef } from '@edr/ui-common';
import { PageContainer, PageHeader } from '@/components/page';
import { useMutation, useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import { useToast } from '@/hooks/use-toast';
import {
useCancelInvoice,
usePayInvoice,
useWarehouseInvoice,
useWarehouseInvoices,
} from '@/hooks/useWarehouses';
import {
WAREHOUSE_INVOICE_STATUSES,
type WarehouseFeeInvoice,
@@ -48,7 +45,11 @@ export default function WarehouseInvoicesPage() {
const [search, setSearch] = useState('');
const [detailId, setDetailId] = useState<string | null>(null);
const { data, isLoading } = useWarehouseInvoices(status ? { status } : undefined);
const { data, isLoading } = useQuery(
api.warehouses.invoices.queryOptions({
input: { filter: status ? { status } : undefined },
}),
);
const invoices = data ?? [];
const filtered = useMemo(() => {
@@ -149,9 +150,14 @@ export default function WarehouseInvoicesPage() {
function InvoiceDetailModal({ id, onClose }: { id: string | null; onClose: () => void }) {
const { toast } = useToast();
const { data: inv, isLoading } = useWarehouseInvoice(id ?? undefined);
const pay = usePayInvoice();
const cancel = useCancelInvoice();
const { data: inv, isLoading } = useQuery(
api.warehouses.invoice.queryOptions({
input: { id: id ?? '' },
enabled: Boolean(id),
}),
);
const pay = useMutation(api.warehouses.payInvoice.mutationOptions());
const cancel = useMutation(api.warehouses.cancelInvoice.mutationOptions());
const [payAmount, setPayAmount] = useState<number | ''>('');
const canPay = inv && (inv.status === 'ISSUED' || inv.status === 'PARTIALLY_PAID');

View File

@@ -12,7 +12,9 @@ import {
WarehouseTable,
type WarehouseView,
} from '@/components/warehouses';
import { useWarehouses } from '@/hooks/useWarehouses';
import { useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import type { Warehouse, WarehouseFilter } from '@/types/warehouse';
export default function WarehouseListPage() {
@@ -28,7 +30,9 @@ export default function WarehouseListPage() {
[filter, debouncedSearch],
);
const { data, isLoading, isError } = useWarehouses(queryFilter);
const { data, isLoading, isError } = useQuery(
api.warehouses.list.queryOptions({ input: { filter: queryFilter } }),
);
const warehouses = data ?? [];
const openCreate = () => {

View File

@@ -17,15 +17,10 @@ import { Plus, Trash2 } from 'lucide-react';
import { DataTable, type ColumnDef } from '@edr/ui-common';
import { PageContainer, PageHeader } from '@/components/page';
import { useMutation, useQuery } from '@tanstack/react-query';
import { api } from '@/services/api';
import { useToast } from '@/hooks/use-toast';
import {
useAllocationRules,
useCreateAllocationRule,
useCreateFeeRule,
useDeleteAllocationRule,
useDeleteFeeRule,
useFeeRules,
} from '@/hooks/useWarehouses';
import { FEE_RULE_TYPES, type FeeRuleType } from '@/types/warehouse';
const FREIGHT = [
@@ -67,9 +62,11 @@ export default function WarehouseRulesPage() {
function AllocationRules() {
const { toast } = useToast();
const { data, isLoading } = useAllocationRules();
const create = useCreateAllocationRule();
const remove = useDeleteAllocationRule();
const { data, isLoading } = useQuery(
api.warehouses.allocationRules.queryOptions(),
);
const create = useMutation(api.warehouses.createAllocationRule.mutationOptions());
const remove = useMutation(api.warehouses.deleteAllocationRule.mutationOptions());
const [open, setOpen] = useState(false);
const [form, setForm] = useState({
name: '',
@@ -181,9 +178,9 @@ function AllocationRules() {
function FeeRules() {
const { toast } = useToast();
const { data, isLoading } = useFeeRules();
const create = useCreateFeeRule();
const remove = useDeleteFeeRule();
const { data, isLoading } = useQuery(api.warehouses.feeRules.queryOptions());
const create = useMutation(api.warehouses.createFeeRule.mutationOptions());
const remove = useMutation(api.warehouses.deleteFeeRule.mutationOptions());
const [open, setOpen] = useState(false);
const [form, setForm] = useState({
name: '',