From d66ccc5363b34fc7e6e9962f00c8fcb4b82ab6c6 Mon Sep 17 00:00:00 2001 From: Nathnael Date: Mon, 22 Jun 2026 12:25:20 +0000 Subject: [PATCH] refactor: migrated of the customer hooks for warehouse data fetching --- .../warehouses/ActivityTimeline.tsx | 11 +- .../warehouses/CreateWarehouseModal.tsx | 8 +- .../components/warehouses/CreateYardModal.tsx | 8 +- .../components/warehouses/CreateZoneModal.tsx | 8 +- .../warehouses/DeliverInventoryModal.tsx | 6 +- .../components/warehouses/FeePreviewModal.tsx | 27 +- .../warehouses/InspectionReportModal.tsx | 12 +- .../InventoryMovementHistoryTable.tsx | 11 +- .../warehouses/InventoryWorkbench.tsx | 31 +- .../warehouses/LoadInventoryModal.tsx | 6 +- .../warehouses/MoveInventoryModal.tsx | 24 +- .../warehouses/ReceiveInventoryModal.tsx | 123 +++-- .../warehouses/ReleaseOrderModal.tsx | 6 +- .../warehouses/ReserveInventoryModal.tsx | 6 +- .../src/components/warehouses/WagonSelect.tsx | 7 +- .../warehouses/WarehouseDashboardCharts.tsx | 8 +- .../warehouses/WarehouseInfoCard.tsx | 15 +- .../backoffice/src/hooks/useWarehouses.ts | 505 ------------------ .../src/pages/warehouses/ArrivalQueuePage.tsx | 13 +- .../pages/warehouses/DispatchQueuePage.tsx | 8 +- .../pages/warehouses/InventoryInquiryPage.tsx | 31 +- .../pages/warehouses/LoadedInventoryPage.tsx | 13 +- .../src/pages/warehouses/LoadingQueuePage.tsx | 21 +- .../warehouses/WarehouseDashboardPage.tsx | 6 +- .../pages/warehouses/WarehouseDetailPage.tsx | 36 +- .../warehouses/WarehouseInventoryPage.tsx | 31 +- .../warehouses/WarehouseInvoicesPage.tsx | 26 +- .../pages/warehouses/WarehouseListPage.tsx | 8 +- .../pages/warehouses/WarehouseRulesPage.tsx | 25 +- 29 files changed, 336 insertions(+), 704 deletions(-) delete mode 100644 apps/edr-freight-web/backoffice/src/hooks/useWarehouses.ts diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/ActivityTimeline.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/ActivityTimeline.tsx index 49e8828dd..5fac23ea7 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/ActivityTimeline.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/ActivityTimeline.tsx @@ -9,7 +9,9 @@ import { Warehouse, } from 'lucide-react'; -import { useInventoryActivity } from '@/hooks/useWarehouses'; +import { useQuery } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import type { ActivityType } from '@/types/warehouse'; import { formatDate, humanizeEnum } from './options'; @@ -24,7 +26,12 @@ const activityIcon: Record = { }; export function ActivityTimeline({ inventoryId }: { inventoryId: string }) { - const { data, isLoading } = useInventoryActivity(inventoryId); + const { data, isLoading } = useQuery( + api.warehouses.activity.queryOptions({ + input: { id: inventoryId }, + enabled: Boolean(inventoryId), + }), + ); const items = data ?? []; if (isLoading) { diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/CreateWarehouseModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/CreateWarehouseModal.tsx index 87d5f2946..cc8557be2 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/CreateWarehouseModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/CreateWarehouseModal.tsx @@ -9,9 +9,11 @@ import { TextInput, } from '@mantine/core'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; import { useStations } from '@/hooks/useStations'; -import { useCreateWarehouse, useUpdateWarehouse } from '@/hooks/useWarehouses'; import type { SaveWarehousePayload, Warehouse, WarehouseType } from '@/types/warehouse'; import { extractErrorMessage, statusOptions, warehouseTypeOptions } from './options'; @@ -48,8 +50,8 @@ const emptyForm = (): FormState => ({ export function CreateWarehouseModal({ opened, onClose, warehouse }: CreateWarehouseModalProps) { const isEdit = Boolean(warehouse); const { toast } = useToast(); - const createMutation = useCreateWarehouse(); - const updateMutation = useUpdateWarehouse(); + const createMutation = useMutation(api.warehouses.create.mutationOptions()); + const updateMutation = useMutation(api.warehouses.update.mutationOptions()); const { data: stations } = useStations(); const [form, setForm] = useState(emptyForm()); diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/CreateYardModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/CreateYardModal.tsx index 9ef9ef26c..a2eb0aa0e 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/CreateYardModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/CreateYardModal.tsx @@ -1,8 +1,10 @@ import { useEffect, useState } from 'react'; import { Button, Group, Modal, NumberInput, Select, Stack, TextInput } from '@mantine/core'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useCreateYard, useUpdateYard } from '@/hooks/useWarehouses'; import type { SaveYardPayload, WarehouseYard, WarehouseYardType } from '@/types/warehouse'; import { extractErrorMessage, statusOptions, yardTypeOptions } from './options'; @@ -36,8 +38,8 @@ const emptyForm = (): FormState => ({ export function CreateYardModal({ opened, onClose, warehouseId, yard }: CreateYardModalProps) { const isEdit = Boolean(yard); const { toast } = useToast(); - const createMutation = useCreateYard(); - const updateMutation = useUpdateYard(); + const createMutation = useMutation(api.warehouses.createYard.mutationOptions()); + const updateMutation = useMutation(api.warehouses.updateYard.mutationOptions()); const [form, setForm] = useState(emptyForm()); useEffect(() => { diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/CreateZoneModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/CreateZoneModal.tsx index 7a67e4ff1..05bc1ce96 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/CreateZoneModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/CreateZoneModal.tsx @@ -1,8 +1,10 @@ import { useEffect, useState } from 'react'; import { Button, Group, Modal, NumberInput, Select, Stack, TextInput } from '@mantine/core'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useCreateZone, useUpdateZone } from '@/hooks/useWarehouses'; import type { SaveZonePayload, WarehouseZone, WarehouseZoneType } from '@/types/warehouse'; import { extractErrorMessage, statusOptions, zoneTypeOptions } from './options'; @@ -36,8 +38,8 @@ const emptyForm = (): FormState => ({ export function CreateZoneModal({ opened, onClose, yardId, zone }: CreateZoneModalProps) { const isEdit = Boolean(zone); const { toast } = useToast(); - const createMutation = useCreateZone(); - const updateMutation = useUpdateZone(); + const createMutation = useMutation(api.warehouses.createZone.mutationOptions()); + const updateMutation = useMutation(api.warehouses.updateZone.mutationOptions()); const [form, setForm] = useState(emptyForm()); useEffect(() => { diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/DeliverInventoryModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/DeliverInventoryModal.tsx index 4b5485815..d8a441de8 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/DeliverInventoryModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/DeliverInventoryModal.tsx @@ -2,8 +2,10 @@ import { useEffect, useState } from 'react'; import { Alert, Button, Group, Modal, Stack, Text, Textarea, TextInput } from '@mantine/core'; import { Info } from 'lucide-react'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useDeliverInventory } from '@/hooks/useWarehouses'; import type { WarehouseInventoryItem } from '@/types/warehouse'; import { extractErrorMessage } from './options'; @@ -15,7 +17,7 @@ interface DeliverInventoryModalProps { export function DeliverInventoryModal({ opened, onClose, item }: DeliverInventoryModalProps) { const { toast } = useToast(); - const deliverMutation = useDeliverInventory(); + const deliverMutation = useMutation(api.warehouses.deliver.mutationOptions()); const [receiverName, setReceiverName] = useState(''); const [remarks, setRemarks] = useState(''); diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/FeePreviewModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/FeePreviewModal.tsx index ce4b81c05..73ea669be 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/FeePreviewModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/FeePreviewModal.tsx @@ -1,13 +1,10 @@ import { Badge, Button, Card, Divider, Group, Loader, Modal, Stack, Text } from '@mantine/core'; import { CalendarClock, Coins, DoorOpen, FileText } from 'lucide-react'; +import { useMutation, useQuery } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { - useFeePreview, - useGateClearance, - useGenerateInvoice, - useInvoicesForInventory, -} from '@/hooks/useWarehouses'; import { extractErrorMessage } from './options'; import type { FeePreview, WarehouseInvoiceStatus } from '@/types/warehouse'; @@ -88,10 +85,20 @@ function Row({ label, value }: { label: string; value: string }) { export function FeePreviewModal({ opened, onClose, inventoryId }: FeePreviewModalProps) { const { toast } = useToast(); const enabledId = opened ? inventoryId ?? undefined : undefined; - const { data, isLoading } = useFeePreview(enabledId); - const { data: invoices } = useInvoicesForInventory(enabledId); - const generate = useGenerateInvoice(); - const gateClear = useGateClearance(); + const { data, isLoading } = useQuery( + api.warehouses.feePreview.queryOptions({ + input: { inventoryId: enabledId ?? '' }, + enabled: Boolean(enabledId), + }), + ); + const { data: invoices } = useQuery( + api.warehouses.invoicesForInventory.queryOptions({ + input: { inventoryId: enabledId ?? '' }, + enabled: Boolean(enabledId), + }), + ); + const generate = useMutation(api.warehouses.generateInvoice.mutationOptions()); + const gateClear = useMutation(api.warehouses.gateClearance.mutationOptions()); const activeInvoice = (invoices ?? []).find((i) => i.status !== 'CANCELLED'); diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/InspectionReportModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/InspectionReportModal.tsx index 15583345d..d56547455 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/InspectionReportModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/InspectionReportModal.tsx @@ -12,8 +12,10 @@ import { } from '@mantine/core'; import { Upload } from 'lucide-react'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useCreateInspectionReport, useUploadInspectionAttachments } from '@/hooks/useWarehouses'; import { INSPECTION_REPORT_TYPES, INSPECTION_STATUSES, @@ -45,8 +47,12 @@ const STATUS_LABELS: Record = { /** Batch 4.5 — record an inspection / damage report with optional image upload. */ export function InspectionReportModal({ opened, onClose, inventoryId }: InspectionReportModalProps) { const { toast } = useToast(); - const createReport = useCreateInspectionReport(); - const uploadAttachments = useUploadInspectionAttachments(); + const createReport = useMutation( + api.warehouses.createInspectionReport.mutationOptions(), + ); + const uploadAttachments = useMutation( + api.warehouses.uploadInspectionAttachments.mutationOptions(), + ); const [reportType, setReportType] = useState('INSPECTION'); const [inspectionStatus, setInspectionStatus] = useState('PASSED'); diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryMovementHistoryTable.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryMovementHistoryTable.tsx index 352c6bff2..304e4ca75 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryMovementHistoryTable.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryMovementHistoryTable.tsx @@ -1,12 +1,19 @@ import { Center, Loader, Table, Text } from '@mantine/core'; -import { useInventoryMovements } from '@/hooks/useWarehouses'; +import { useQuery } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { formatDate } from './options'; const shortId = (id?: string | null) => (id ? `${id.slice(0, 8)}…` : '—'); export function InventoryMovementHistoryTable({ inventoryId }: { inventoryId: string }) { - const { data, isLoading } = useInventoryMovements(inventoryId); + const { data, isLoading } = useQuery( + api.warehouses.movements.queryOptions({ + input: { id: inventoryId }, + enabled: Boolean(inventoryId), + }), + ); const movements = data ?? []; if (isLoading) { diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryWorkbench.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryWorkbench.tsx index 27ad0ebc6..b076510ab 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryWorkbench.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryWorkbench.tsx @@ -2,14 +2,10 @@ import { useState } from 'react'; import { Button, Center, Group, Loader, Stack, Text } from '@mantine/core'; import { ClipboardCheck } from 'lucide-react'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { - useBulkMarkInspected, - useDispatchInventory, - useMarkReadyForLoading, - useMarkReadyForPickup, - useStoreInventory, -} from '@/hooks/useWarehouses'; import type { InventoryAction, WarehouseInventoryItem } from '@/types/warehouse'; import { DeliverInventoryModal } from './DeliverInventoryModal'; import { FeePreviewModal } from './FeePreviewModal'; @@ -42,11 +38,17 @@ export function InventoryWorkbench({ items, isLoading, onLastMile }: InventoryWo const [releaseItem, setReleaseItem] = useState(null); const [deliverItem, setDeliverItem] = useState(null); - const storeMutation = useStoreInventory(); - const readyMutation = useMarkReadyForLoading(); - const pickupMutation = useMarkReadyForPickup(); - const dispatchMutation = useDispatchInventory(); - const inspectMutation = useBulkMarkInspected(); + const storeMutation = useMutation(api.warehouses.store.mutationOptions()); + const readyMutation = useMutation( + api.warehouses.markReadyForLoading.mutationOptions(), + ); + const pickupMutation = useMutation( + api.warehouses.markReadyForPickup.mutationOptions(), + ); + const dispatchMutation = useMutation(api.warehouses.dispatch.mutationOptions()); + const inspectMutation = useMutation( + api.warehouses.bulkMarkInspected.mutationOptions(), + ); const [selected, setSelected] = useState>(new Set()); const allSelected = items.length > 0 && selected.size === items.length; @@ -66,10 +68,7 @@ export function InventoryWorkbench({ items, isLoading, onLastMile }: InventoryWo return; } try { - const res = (await inspectMutation.mutateAsync({ inventoryIds: [...selected] })) as { - data: { inspectedCount: number; skippedCount: number }; - }; - const r = res.data; + const r = await inspectMutation.mutateAsync({ inventoryIds: [...selected] }); toast({ title: `${r.inspectedCount} marked inspected`, description: r.skippedCount ? `${r.skippedCount} skipped` : undefined, diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/LoadInventoryModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/LoadInventoryModal.tsx index 8def582cb..7fc43c0d5 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/LoadInventoryModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/LoadInventoryModal.tsx @@ -2,8 +2,10 @@ import { useEffect, useState } from 'react'; import { Alert, Button, Group, Modal, NumberInput, Stack, Text, Textarea } from '@mantine/core'; import { Info } from 'lucide-react'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useLoadInventory } from '@/hooks/useWarehouses'; import type { WarehouseInventoryItem } from '@/types/warehouse'; import { WagonSelect } from './WagonSelect'; import { extractErrorMessage } from './options'; @@ -17,7 +19,7 @@ interface LoadInventoryModalProps { /** Load READY_FOR_LOADING inventory onto a wagon (creates a loading record). */ export function LoadInventoryModal({ opened, onClose, item }: LoadInventoryModalProps) { const { toast } = useToast(); - const loadMutation = useLoadInventory(); + const loadMutation = useMutation(api.warehouses.load.mutationOptions()); const [wagonId, setWagonId] = useState(''); const [loadedWeight, setLoadedWeight] = useState(''); const [notes, setNotes] = useState(''); diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/MoveInventoryModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/MoveInventoryModal.tsx index b76458d5e..1ec596ffe 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/MoveInventoryModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/MoveInventoryModal.tsx @@ -1,8 +1,10 @@ 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 { useMoveInventory, useWarehouseYards, useWarehouseZones, useWarehouses } from '@/hooks/useWarehouses'; import type { WarehouseInventoryItem } from '@/types/warehouse'; import { extractErrorMessage } from './options'; @@ -14,7 +16,7 @@ interface MoveInventoryModalProps { export function MoveInventoryModal({ opened, onClose, item }: MoveInventoryModalProps) { const { toast } = useToast(); - const moveMutation = useMoveInventory(); + const moveMutation = useMutation(api.warehouses.move.mutationOptions()); const [warehouseId, setWarehouseId] = useState(''); const [yardId, setYardId] = useState(''); const [zoneId, setZoneId] = useState(''); @@ -29,9 +31,21 @@ export function MoveInventoryModal({ opened, onClose, item }: MoveInventoryModal } }, [opened]); - const warehousesQuery = useWarehouses({ status: 'ACTIVE' }); - const yardsQuery = useWarehouseYards(warehouseId || undefined); - const zonesQuery = useWarehouseZones(yardId || undefined); + 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})` })), 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 eab14ad63..3cd08461f 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/ReceiveInventoryModal.tsx @@ -18,34 +18,14 @@ import { } from '@mantine/core'; import { ChevronDown, ChevronRight, ClipboardCheck, Info, PackageSearch, Train, Truck } from 'lucide-react'; +import { useMutation, useQuery } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { - useAutoUnloadArrivedBookings, - useBulkDispatchExport, - useBulkMarkInspected, - useBulkReceive, - useEligibleBookings, - useImportArriveQueue, - useImportTrainItems, - useImportUnloadedQueue, - useLoadPassedExport, - useLoadedExport, - useReadyToLoadExport, - useReceiveInventory, - useWarehouseInventory, - useWarehouseYards, - useWarehouseZones, - useWarehouses, -} from '@/hooks/useWarehouses'; import type { - AutoUnloadArrivedResult, - BulkDispatchResult, - BulkInspectResult, - BulkReceiveResult, ImportTrain, ImportTrainItem, ImportUnloadedItem, - LoadPassedExportResult, ReadyToLoadRow, ReceiveInventoryPayload, } from '@/types/warehouse'; @@ -77,9 +57,21 @@ function LocationSelects({ value: Location; onChange: (next: Location) => void; }) { - const warehousesQuery = useWarehouses({ status: 'ACTIVE' }); - const yardsQuery = useWarehouseYards(value.warehouseId || undefined); - const zonesQuery = useWarehouseZones(value.yardId || undefined); + const warehousesQuery = useQuery( + api.warehouses.list.queryOptions({ input: { filter: { status: 'ACTIVE' } } }), + ); + const yardsQuery = useQuery( + api.warehouses.listYards.queryOptions({ + input: { warehouseId: value.warehouseId ?? '' }, + enabled: Boolean(value.warehouseId), + }), + ); + const zonesQuery = useQuery( + api.warehouses.listZones.queryOptions({ + input: { yardId: value.yardId ?? '' }, + enabled: Boolean(value.yardId), + }), + ); const warehouseOptions = useMemo( () => (warehousesQuery.data ?? []).map((w) => ({ value: w.id, label: `${w.name} (${w.code})` })), @@ -148,10 +140,12 @@ function EligibleTab({ onChanged?: () => void; }) { const { toast } = useToast(); - const { data: allRows = [], isLoading } = useEligibleBookings(enabled); + const { data: allRows = [], isLoading } = useQuery( + api.warehouses.eligibleBookings.queryOptions({ enabled }), + ); const rows = useMemo(() => allRows.filter((r) => r.direction === direction), [allRows, direction]); - const bulkReceive = useBulkReceive(); - const loadPassed = useLoadPassedExport(); + const bulkReceive = useMutation(api.warehouses.bulkReceive.mutationOptions()); + const loadPassed = useMutation(api.warehouses.loadPassedExport.mutationOptions()); const [selected, setSelected] = useState>(new Set()); const locationReady = Boolean(location.warehouseId && location.yardId && location.zoneId); @@ -177,10 +171,7 @@ function EligibleTab({ return; } try { - const res = (await bulkReceive.mutateAsync({ direction, ...location, bookingIds })) as { - data: BulkReceiveResult; - }; - const r = res.data; + const r = await bulkReceive.mutateAsync({ direction, ...location, bookingIds }); toast({ title: `${r.receivedCount} received at ${direction === 'EXPORT' ? 'facility' : 'warehouse'}`, description: r.skippedCount ? `${r.skippedCount} skipped` : undefined, @@ -194,8 +185,7 @@ function EligibleTab({ const loadPassedExport = async () => { try { - const res = (await loadPassed.mutateAsync(undefined)) as { data: LoadPassedExportResult }; - const r = res.data; + const r = await loadPassed.mutateAsync(undefined); toast({ title: `${r.loadedCount} loaded`, description: r.skippedCount ? `${r.skippedCount} skipped — inspection not passed` : undefined, @@ -353,8 +343,10 @@ function EligibleTab({ /** Export items that passed inspection and are queued to be loaded onto a train. */ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?: () => void }) { const { toast } = useToast(); - const { data: rows = [], isLoading } = useReadyToLoadExport(enabled); - const loadPassed = useLoadPassedExport(); + const { data: rows = [], isLoading } = useQuery( + api.warehouses.readyToLoadExport.queryOptions({ enabled }), + ); + const loadPassed = useMutation(api.warehouses.loadPassedExport.mutationOptions()); const [selected, setSelected] = useState>(new Set()); const allSelected = rows.length > 0 && selected.size === rows.length; @@ -369,8 +361,7 @@ function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?: const autoLoad = async () => { try { - const res = (await loadPassed.mutateAsync(undefined)) as { data: LoadPassedExportResult }; - const r = res.data; + const r = await loadPassed.mutateAsync(undefined); toast({ title: `${r.loadedCount} items loaded`, description: r.skippedCount ? `${r.skippedCount} skipped` : undefined, @@ -494,8 +485,12 @@ function LoadedExportTab({ onChanged?: () => void; }) { const { toast } = useToast(); - const { data: rows = [], isLoading } = useLoadedExport(enabled); - const bulkDispatch = useBulkDispatchExport(); + const { data: rows = [], isLoading } = useQuery( + api.warehouses.loadedExport.queryOptions({ enabled }), + ); + const bulkDispatch = useMutation( + api.warehouses.bulkDispatchExport.mutationOptions(), + ); const [selected, setSelected] = useState>(new Set()); const allSelected = rows.length > 0 && selected.size === rows.length; @@ -514,8 +509,7 @@ function LoadedExportTab({ return; } try { - const res = (await bulkDispatch.mutateAsync(inventoryIds)) as { data: BulkDispatchResult }; - const r = res.data; + const r = await bulkDispatch.mutateAsync(inventoryIds); toast({ title: `${r.dispatchedCount} dispatched`, description: r.skippedCount ? `${r.skippedCount} skipped` : undefined, @@ -659,7 +653,12 @@ function LoadedExportTab({ /** Assigned bookings/items for an arrived import train (read-only detail view). */ function ImportTrainDetailTable({ scheduleId }: { scheduleId: string }) { - const { data: items = [], isLoading } = useImportTrainItems(scheduleId); + const { data: items = [], isLoading } = useQuery( + api.warehouses.importTrainItems.queryOptions({ + input: { scheduleId }, + enabled: Boolean(scheduleId), + }), + ); if (isLoading) { return ( @@ -735,18 +734,19 @@ function ImportArriveQueueTab({ onChanged?: () => void; }) { const { toast } = useToast(); - const { data: trains = [], isLoading } = useImportArriveQueue(enabled); - const autoUnloadMutation = useAutoUnloadArrivedBookings(); + const { data: trains = [], isLoading } = useQuery( + api.warehouses.importArriveQueue.queryOptions({ enabled }), + ); + const autoUnloadMutation = useMutation( + api.warehouses.autoUnloadArrivedBookings.mutationOptions(), + ); const [openId, setOpenId] = useState(null); const [busyId, setBusyId] = useState(null); const autoUnload = async (train: ImportTrain) => { setBusyId(train.scheduleId); try { - const res = (await autoUnloadMutation.mutateAsync(train.scheduleId)) as { - data: AutoUnloadArrivedResult; - }; - const r = res.data; + const r = await autoUnloadMutation.mutateAsync(train.scheduleId); const extra = [ r.skippedCount ? `${r.skippedCount} skipped` : '', r.failedCount ? `${r.failedCount} failed` : '', @@ -866,8 +866,12 @@ function ImportArriveQueueTab({ */ function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) { const { toast } = useToast(); - const { data: rows = [], isLoading } = useImportUnloadedQueue(enabled); - const inspectMutation = useBulkMarkInspected(); + const { data: rows = [], isLoading } = useQuery( + api.warehouses.importUnloadedQueue.queryOptions({ enabled }), + ); + const inspectMutation = useMutation( + api.warehouses.bulkMarkInspected.mutationOptions(), + ); const [selected, setSelected] = useState>(new Set()); const [inspectId, setInspectId] = useState(null); @@ -888,10 +892,7 @@ function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) { return; } try { - const res = (await inspectMutation.mutateAsync({ inventoryIds: [...selected] })) as { - data: BulkInspectResult; - }; - const r = res.data; + const r = await inspectMutation.mutateAsync({ inventoryIds: [...selected] }); toast({ title: `${r.inspectedCount} marked inspected`, description: r.skippedCount ? `${r.skippedCount} skipped` : undefined, @@ -1033,8 +1034,10 @@ function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) { */ function ImportDispatchQueueTab({ enabled }: { enabled: boolean }) { const { toast } = useToast(); - const { data: items = [], isLoading } = useWarehouseInventory( - enabled ? { status: 'READY_FOR_PICKUP' } : undefined, + const { data: items = [], isLoading } = useQuery( + api.warehouses.listInventory.queryOptions({ + input: { filter: enabled ? { status: 'READY_FOR_PICKUP' } : undefined }, + }), ); return ( @@ -1155,7 +1158,9 @@ function SingleBookingReceiveModal({ onReceived, }: ReceiveInventoryModalProps) { const { toast } = useToast(); - const receiveMutation = useReceiveInventory(); + const receiveMutation = useMutation( + api.warehouses.receiveInventory.mutationOptions(), + ); const [selectedBooking, setSelectedBooking] = useState(bookingId ?? ''); const [form, setForm] = useState({ warehouseId: '', diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/ReleaseOrderModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/ReleaseOrderModal.tsx index 851066713..f2edd620b 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/ReleaseOrderModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/ReleaseOrderModal.tsx @@ -2,8 +2,10 @@ import { useEffect, useState } from 'react'; import { Alert, Button, Group, Modal, Stack, Text, TextInput } from '@mantine/core'; import { Info } from 'lucide-react'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useReleaseInventory } from '@/hooks/useWarehouses'; import type { WarehouseInventoryItem } from '@/types/warehouse'; import { extractErrorMessage } from './options'; @@ -15,7 +17,7 @@ interface ReleaseOrderModalProps { export function ReleaseOrderModal({ opened, onClose, item }: ReleaseOrderModalProps) { const { toast } = useToast(); - const releaseMutation = useReleaseInventory(); + const releaseMutation = useMutation(api.warehouses.release.mutationOptions()); const [reference, setReference] = useState(''); useEffect(() => { diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/ReserveInventoryModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/ReserveInventoryModal.tsx index 7a7ebb55b..d436bb6f2 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/ReserveInventoryModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/ReserveInventoryModal.tsx @@ -2,8 +2,10 @@ import { useEffect, useState } from 'react'; import { Alert, Button, Group, Modal, Stack, Text } from '@mantine/core'; import { Info } from 'lucide-react'; +import { useMutation } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { useToast } from '@/hooks/use-toast'; -import { useReserveInventory } from '@/hooks/useWarehouses'; import type { WarehouseInventoryItem } from '@/types/warehouse'; import { BookingSelect } from './BookingSelect'; import { extractErrorMessage } from './options'; @@ -16,7 +18,7 @@ interface ReserveInventoryModalProps { export function ReserveInventoryModal({ opened, onClose, item }: ReserveInventoryModalProps) { const { toast } = useToast(); - const reserveMutation = useReserveInventory(); + const reserveMutation = useMutation(api.warehouses.reserve.mutationOptions()); const [bookingId, setBookingId] = useState(''); useEffect(() => { diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/WagonSelect.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/WagonSelect.tsx index d6cc8c2cd..298df191b 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/WagonSelect.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/WagonSelect.tsx @@ -1,6 +1,7 @@ import { Select } from '@mantine/core'; +import { useQuery } from '@tanstack/react-query'; -import { useLoadableWagons } from '@/hooks/useWarehouses'; +import { api } from '@/services/api'; interface WagonSelectProps { value: string; @@ -11,7 +12,9 @@ interface WagonSelectProps { /** Searchable wagon picker. Lists wagons that are loadable (read-only from scheduling). */ export function WagonSelect({ value, onChange, label = 'Wagon', required }: WagonSelectProps) { - const { data, isLoading } = useLoadableWagons(); + const { data, isLoading } = useQuery( + api.warehouses.loadableWagons.queryOptions(), + ); const options = (data ?? []).map((w) => ({ value: w.id, diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseDashboardCharts.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseDashboardCharts.tsx index b2a628d88..993544fe3 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseDashboardCharts.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseDashboardCharts.tsx @@ -15,7 +15,9 @@ import { YAxis, } from 'recharts'; -import { useWarehouseInventory } from '@/hooks/useWarehouses'; +import { useQuery } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import type { WarehouseDashboard, WarehouseInventoryItem } from '@/types/warehouse'; interface WarehouseDashboardChartsProps { @@ -38,7 +40,9 @@ type Granularity = 'week' | 'month' | 'year'; export function WarehouseDashboardCharts({ data }: WarehouseDashboardChartsProps) { const [granularity, setGranularity] = useState('month'); - const { data: inventory } = useWarehouseInventory(); + const { data: inventory } = useQuery( + api.warehouses.listInventory.queryOptions({ input: {} }), + ); const statusData = STATUS_SERIES.map((s) => ({ name: s.label, diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseInfoCard.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseInfoCard.tsx index 83dcc4d63..e28513821 100644 --- a/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseInfoCard.tsx +++ b/apps/edr-freight-web/backoffice/src/components/warehouses/WarehouseInfoCard.tsx @@ -2,7 +2,9 @@ import { useState } from 'react'; import { Badge, Button, Card, Divider, Group, Stack, Text } from '@mantine/core'; import { PackagePlus, Train as TrainIcon, Warehouse as WarehouseIcon } from 'lucide-react'; -import { useBookingSchedule, useWarehouseInventory } from '@/hooks/useWarehouses'; +import { useQuery } from '@tanstack/react-query'; + +import { api } from '@/services/api'; import { InventoryStatusBadge } from './badges'; import { FreightVisual } from './FreightVisual'; import { formatDate } from './options'; @@ -28,8 +30,15 @@ function Row({ label, value }: { label: string; value: React.ReactNode }) { export function WarehouseInfoCard({ bookingId, bookingReference }: WarehouseInfoCardProps) { const [modalOpen, setModalOpen] = useState(false); - const { data, isLoading } = useWarehouseInventory({ bookingId }); - const { data: scheduleView } = useBookingSchedule(bookingId); + const { data, isLoading } = useQuery( + api.warehouses.listInventory.queryOptions({ input: { filter: { bookingId } } }), + ); + const { data: scheduleView } = useQuery( + api.warehouses.bookingSchedule.queryOptions({ + input: { bookingId }, + enabled: Boolean(bookingId), + }), + ); const items = data ?? []; const latest = items[0]; diff --git a/apps/edr-freight-web/backoffice/src/hooks/useWarehouses.ts b/apps/edr-freight-web/backoffice/src/hooks/useWarehouses.ts deleted file mode 100644 index 5e50c151a..000000000 --- a/apps/edr-freight-web/backoffice/src/hooks/useWarehouses.ts +++ /dev/null @@ -1,505 +0,0 @@ -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; - -import { warehouseService } from '@/services/warehouse.service'; -import type { - InspectionReportPayload, - SaveAllocationRulePayload, - SaveFeeRulePayload, - WarehouseInvoiceFilter, - PayInvoicePayload, - InventoryFilter, - InventoryInquiryFilter, - LoadInventoryPayload, - MoveInventoryPayload, - ReceiveInventoryPayload, - ReleaseOrderPayload, - DeliverInventoryPayload, - BulkReceivePayload, - BulkInspectPayload, - ReserveInventoryPayload, - SaveWarehousePayload, - SaveYardPayload, - SaveZonePayload, - WarehouseFilter, -} from '@/types/warehouse'; - -export const warehouseKeys = { - all: ['warehouses'] as const, - list: (filter?: WarehouseFilter) => ['warehouses', 'list', filter ?? {}] as const, - detail: (id: string) => ['warehouses', 'detail', id] as const, - yards: (warehouseId: string) => ['warehouses', warehouseId, 'yards'] as const, - zones: (yardId: string) => ['warehouse-yards', yardId, 'zones'] as const, - inventory: (filter?: InventoryFilter) => ['warehouse-inventory', 'list', filter ?? {}] as const, - inquiry: (filter: InventoryInquiryFilter) => ['warehouse-inventory', 'inquiry', filter] as const, -}; - -// ── Warehouses ───────────────────────────────────────────────────────────── - -export function useWarehouses(filter?: WarehouseFilter) { - return useQuery({ - queryKey: warehouseKeys.list(filter), - queryFn: () => warehouseService.list(filter).then((r) => r.data), - }); -} - -export function useWarehouse(id?: string) { - return useQuery({ - queryKey: warehouseKeys.detail(id ?? ''), - queryFn: () => warehouseService.getById(id as string).then((r) => r.data), - enabled: Boolean(id), - }); -} - -export function useCreateWarehouse() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: (payload: SaveWarehousePayload) => warehouseService.create(payload), - onSuccess: () => qc.invalidateQueries({ queryKey: warehouseKeys.all }), - }); -} - -export function useUpdateWarehouse() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: ({ id, payload }: { id: string; payload: Partial }) => - warehouseService.update(id, payload), - onSuccess: (_, { id }) => { - qc.invalidateQueries({ queryKey: warehouseKeys.all }); - qc.invalidateQueries({ queryKey: warehouseKeys.detail(id) }); - }, - }); -} - -// ── Yards ──────────────────────────────────────────────────────────────── - -export function useWarehouseYards(warehouseId?: string) { - return useQuery({ - queryKey: warehouseKeys.yards(warehouseId ?? ''), - queryFn: () => warehouseService.listYards(warehouseId as string).then((r) => r.data), - enabled: Boolean(warehouseId), - }); -} - -export function useCreateYard() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: ({ warehouseId, payload }: { warehouseId: string; payload: SaveYardPayload }) => - warehouseService.createYard(warehouseId, payload), - onSuccess: (_, { warehouseId }) => { - qc.invalidateQueries({ queryKey: warehouseKeys.yards(warehouseId) }); - qc.invalidateQueries({ queryKey: warehouseKeys.detail(warehouseId) }); - }, - }); -} - -export function useUpdateYard() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: ({ id, payload }: { id: string; payload: Partial }) => - warehouseService.updateYard(id, payload), - onSuccess: () => qc.invalidateQueries({ queryKey: warehouseKeys.all }), - }); -} - -// ── Zones ────────────────────────────────────────────────────────────────── - -export function useWarehouseZones(yardId?: string) { - return useQuery({ - queryKey: warehouseKeys.zones(yardId ?? ''), - queryFn: () => warehouseService.listZones(yardId as string).then((r) => r.data), - enabled: Boolean(yardId), - }); -} - -export function useCreateZone() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: ({ yardId, payload }: { yardId: string; payload: SaveZonePayload }) => - warehouseService.createZone(yardId, payload), - onSuccess: (_, { yardId }) => qc.invalidateQueries({ queryKey: warehouseKeys.zones(yardId) }), - }); -} - -export function useUpdateZone() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: ({ id, payload }: { id: string; payload: Partial }) => - warehouseService.updateZone(id, payload), - onSuccess: () => qc.invalidateQueries({ queryKey: ['warehouse-yards'] }), - }); -} - -// ── Inventory ────────────────────────────────────────────────────────────── - -export function useWarehouseInventory(filter?: InventoryFilter) { - return useQuery({ - queryKey: warehouseKeys.inventory(filter), - queryFn: () => warehouseService.listInventory(filter).then((r) => r.data), - }); -} - -export function useReceiveInventory() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: (payload: ReceiveInventoryPayload) => warehouseService.receiveInventory(payload), - onSuccess: () => { - qc.invalidateQueries({ queryKey: ['warehouse-inventory'] }); - qc.invalidateQueries({ queryKey: warehouseKeys.all }); - }, - }); -} - -function useInventoryMutation(fn: (args: TArgs) => Promise) { - const qc = useQueryClient(); - return useMutation({ - mutationFn: fn, - onSuccess: () => { - qc.invalidateQueries({ queryKey: ['warehouse-inventory'] }); - qc.invalidateQueries({ queryKey: ['warehouse-loadings'] }); - qc.invalidateQueries({ queryKey: warehouseKeys.all }); - }, - }); -} - -export const useStoreInventory = () => useInventoryMutation((id: string) => warehouseService.store(id)); -export const useReserveInventory = () => - useInventoryMutation((payload: ReserveInventoryPayload) => warehouseService.reserve(payload)); -export const useMarkReadyForLoading = () => - useInventoryMutation((id: string) => warehouseService.markReadyForLoading(id)); -export const useLoadInventory = () => - useInventoryMutation((args: { id: string; payload: LoadInventoryPayload }) => - warehouseService.load(args.id, args.payload), - ); -export const useDispatchInventory = () => useInventoryMutation((id: string) => warehouseService.dispatch(id)); -export const useMoveInventory = () => - useInventoryMutation((args: { id: string; payload: MoveInventoryPayload }) => - warehouseService.move(args.id, args.payload), - ); - -// ── Import branch (READY_FOR_PICKUP → DELIVERED) ─────────────────────────── -export const useMarkReadyForPickup = () => - useInventoryMutation((id: string) => warehouseService.markReadyForPickup(id)); -export const useReleaseInventory = () => - useInventoryMutation((args: { id: string; payload: ReleaseOrderPayload }) => - warehouseService.release(args.id, args.payload), - ); -export const useDeliverInventory = () => - useInventoryMutation((args: { id: string; payload: DeliverInventoryPayload }) => - warehouseService.deliver(args.id, args.payload), - ); - -// ── Receive (Import/Export bulk) ─────────────────────────────────────────── -/** - * All not-yet-received PAID bookings, classified IMPORT/EXPORT by route, in one call. - * Both Receive tabs share this single query (same key) — only one HTTP request fires — - * then filter client-side by direction. - */ -export function useEligibleBookings(enabled = true) { - return useQuery({ - queryKey: ['warehouse-inventory', 'eligible-bookings'], - queryFn: () => warehouseService.eligibleBookings().then((r) => r.data), - enabled, - }); -} -export const useBulkReceive = () => - useInventoryMutation((payload: BulkReceivePayload) => warehouseService.receiveBulk(payload)); -export const useLoadPassedExport = () => - useInventoryMutation(() => warehouseService.loadPassedExport()); -export const useBulkMarkInspected = () => - useInventoryMutation((payload: BulkInspectPayload) => warehouseService.bulkMarkInspected(payload)); - -export function useReadyToLoadExport(enabled = true) { - return useQuery({ - queryKey: ['warehouse-inventory', 'ready-to-load-export'], - queryFn: () => warehouseService.readyToLoadExport().then((r) => r.data), - enabled, - }); -} - -export function useLoadedExport(enabled = true) { - return useQuery({ - queryKey: ['warehouse-inventory', 'loaded-export'], - queryFn: () => warehouseService.loadedExport().then((r) => r.data), - enabled, - }); -} - -export const useBulkDispatchExport = () => - useInventoryMutation((inventoryIds: string[]) => warehouseService.bulkDispatchExport(inventoryIds)); - -/** Arrived IMPORT trains (route-derived). Read-only. */ -export function useImportArriveQueue(enabled = true) { - return useQuery({ - queryKey: ['warehouse-inventory', 'import-arrive-queue'], - queryFn: () => warehouseService.importArriveQueue().then((r) => r.data), - enabled, - }); -} - -/** Assigned bookings/items for an arrived import train. Read-only. */ -export function useImportTrainItems(scheduleId?: string) { - return useQuery({ - queryKey: ['warehouse-inventory', 'import-train-items', scheduleId], - queryFn: () => warehouseService.importTrainItems(scheduleId as string).then((r) => r.data), - enabled: Boolean(scheduleId), - }); -} - -/** Unload all eligible assigned bookings of an ARRIVED import train (→ UNLOADED). */ -export const useAutoUnloadArrivedBookings = () => - useInventoryMutation((scheduleId: string) => warehouseService.autoUnloadArrivedBookings(scheduleId)); - -/** IMPORT inventory in the Unloaded Queue (UNLOADED / destination inspection). Read-only. */ -export function useImportUnloadedQueue(enabled = true) { - return useQuery({ - queryKey: ['warehouse-inventory', 'import-unloaded-queue'], - queryFn: () => warehouseService.importUnloadedQueue().then((r) => r.data), - enabled, - }); -} - -/** IMPORT inventory that is PICKUP_READY (READY_FOR_PICKUP) awaiting pickup/dispatch. Read-only. */ -export function useImportPickupReadyQueue(enabled = true) { - return useQuery({ - queryKey: ['warehouse-inventory', 'import-pickup-ready-queue'], - queryFn: () => warehouseService.importPickupReadyQueue().then((r) => r.data), - enabled, - }); -} - -// ── Loading (Batch 3) ──────────────────────────────────────────────────────── - -export function useLoadableWagons(enabled = true) { - return useQuery({ - queryKey: ['warehouse', 'loadable-wagons'], - queryFn: () => warehouseService.loadableWagons().then((r) => r.data), - enabled, - }); -} - -export function useWarehouseLoadings(params?: { bookingId?: string; wagonId?: string }) { - return useQuery({ - queryKey: ['warehouse-loadings', params ?? {}], - queryFn: () => warehouseService.loadings(params).then((r) => r.data), - }); -} - -export function useBookingSchedule(bookingId?: string) { - return useQuery({ - queryKey: ['warehouse', 'booking-schedule', bookingId ?? ''], - queryFn: () => warehouseService.bookingSchedule(bookingId as string).then((r) => r.data), - enabled: Boolean(bookingId), - }); -} - -export function useInventoryMovements(id?: string) { - return useQuery({ - queryKey: ['warehouse-inventory', id, 'movements'], - queryFn: () => warehouseService.movements(id as string).then((r) => r.data), - enabled: Boolean(id), - }); -} - -export function useInventoryActivity(id?: string) { - return useQuery({ - queryKey: ['warehouse-inventory', id, 'activity'], - queryFn: () => warehouseService.activity(id as string).then((r) => r.data), - enabled: Boolean(id), - }); -} - -export function useWarehouseDashboard() { - return useQuery({ - queryKey: ['warehouses', 'dashboard'], - queryFn: () => warehouseService.dashboard().then((r) => r.data), - }); -} - -export function useInventoryInquiry(filter: InventoryInquiryFilter, enabled = true) { - return useQuery({ - queryKey: warehouseKeys.inquiry(filter), - queryFn: () => warehouseService.inquiry(filter).then((r) => r.data), - enabled, - }); -} - -// ── Batch 4.5: Arrival / Unload / Inspection ──────────────────────────────── - -export function useArrivalQueue() { - return useQuery({ - queryKey: ['warehouse-inventory', 'arrival-queue'], - queryFn: () => warehouseService.arrivalQueue().then((r) => r.data), - }); -} - -function useArrivalInvalidation() { - const qc = useQueryClient(); - return () => { - qc.invalidateQueries({ queryKey: ['warehouse-inventory'] }); - qc.invalidateQueries({ queryKey: warehouseKeys.all }); - }; -} - -export function useAutoUnloadArrived() { - const onSuccess = useArrivalInvalidation(); - return useMutation({ mutationFn: () => warehouseService.autoUnloadArrived(), onSuccess }); -} - -export function useAutoLoadReady() { - const onSuccess = useArrivalInvalidation(); - return useMutation({ mutationFn: () => warehouseService.autoLoadReady(), onSuccess }); -} - -export function useUnloadBooking() { - const onSuccess = useArrivalInvalidation(); - return useMutation({ - mutationFn: (args: { bookingId: string; payload?: Record }) => - warehouseService.unloadBooking(args.bookingId, args.payload), - onSuccess, - }); -} - -export function useInspectionReports(inventoryId?: string) { - return useQuery({ - queryKey: ['warehouse-inventory', inventoryId, 'inspection-reports'], - queryFn: () => warehouseService.listInspectionReports(inventoryId as string).then((r) => r.data), - enabled: Boolean(inventoryId), - }); -} - -export function useCreateInspectionReport() { - const qc = useQueryClient(); - return useMutation({ - mutationFn: ({ inventoryId, payload }: { inventoryId: string; payload: InspectionReportPayload }) => - warehouseService.createInspectionReport(inventoryId, payload).then((r) => r.data), - onSuccess: (_, { inventoryId }) => { - qc.invalidateQueries({ queryKey: ['warehouse-inventory', inventoryId, 'inspection-reports'] }); - qc.invalidateQueries({ queryKey: ['warehouse-inventory'] }); - }, - }); -} - -export function useUploadInspectionAttachments() { - return useMutation({ - mutationFn: ({ reportId, files }: { reportId: string; files: File[] }) => - warehouseService.uploadInspectionAttachments(reportId, files), - }); -} - -// ── Batch 5: Allocation + Fee rules / preview ─────────────────────────────── - -export function useAllocationRules() { - return useQuery({ - queryKey: ['warehouse-allocation-rules'], - queryFn: () => warehouseService.listAllocationRules().then((r) => r.data), - }); -} - -export function useFeeRules() { - return useQuery({ - queryKey: ['warehouse-fee-rules'], - queryFn: () => warehouseService.listFeeRules().then((r) => r.data), - }); -} - -function useRuleMutation(fn: (args: TArgs) => Promise, keys: string[]) { - const qc = useQueryClient(); - return useMutation({ - mutationFn: fn, - onSuccess: () => keys.forEach((k) => qc.invalidateQueries({ queryKey: [k] })), - }); -} - -export const useCreateAllocationRule = () => - useRuleMutation( - (payload: SaveAllocationRulePayload) => warehouseService.createAllocationRule(payload), - ['warehouse-allocation-rules'], - ); -export const useUpdateAllocationRule = () => - useRuleMutation( - (args: { id: string; payload: Partial }) => - warehouseService.updateAllocationRule(args.id, args.payload), - ['warehouse-allocation-rules'], - ); -export const useDeleteAllocationRule = () => - useRuleMutation((id: string) => warehouseService.deleteAllocationRule(id), ['warehouse-allocation-rules']); - -export const useCreateFeeRule = () => - useRuleMutation((payload: SaveFeeRulePayload) => warehouseService.createFeeRule(payload), ['warehouse-fee-rules']); -export const useUpdateFeeRule = () => - useRuleMutation( - (args: { id: string; payload: Partial }) => - warehouseService.updateFeeRule(args.id, args.payload), - ['warehouse-fee-rules'], - ); -export const useDeleteFeeRule = () => - useRuleMutation((id: string) => warehouseService.deleteFeeRule(id), ['warehouse-fee-rules']); - -export function useFeePreview(inventoryId?: string) { - return useQuery({ - queryKey: ['warehouse-inventory', inventoryId, 'fee-preview'], - queryFn: () => warehouseService.feePreview(inventoryId as string).then((r) => r.data), - enabled: Boolean(inventoryId), - }); -} - -// ── Batch 6: Warehouse fee invoices ───────────────────────────────────────── - -export function useWarehouseInvoices(filter?: WarehouseInvoiceFilter) { - return useQuery({ - queryKey: ['warehouse-fee-invoices', filter ?? {}], - queryFn: () => warehouseService.listInvoices(filter).then((r) => r.data), - }); -} - -export function useWarehouseInvoice(id?: string) { - return useQuery({ - queryKey: ['warehouse-fee-invoices', 'detail', id], - queryFn: () => warehouseService.getInvoice(id as string).then((r) => r.data), - enabled: Boolean(id), - }); -} - -export function useInvoicesForInventory(inventoryId?: string) { - return useQuery({ - queryKey: ['warehouse-inventory', inventoryId, 'fee-invoices'], - queryFn: () => warehouseService.invoicesForInventory(inventoryId as string).then((r) => r.data), - enabled: Boolean(inventoryId), - }); -} - -function useInvoiceInvalidation() { - const qc = useQueryClient(); - return () => { - qc.invalidateQueries({ queryKey: ['warehouse-fee-invoices'] }); - qc.invalidateQueries({ queryKey: ['warehouse-inventory'] }); - }; -} - -export function useGenerateInvoice() { - const onSuccess = useInvoiceInvalidation(); - return useMutation({ - mutationFn: ({ inventoryId, confirmZero }: { inventoryId: string; confirmZero?: boolean }) => - warehouseService.generateInvoice(inventoryId, confirmZero).then((r) => r.data), - onSuccess, - }); -} - -export function useCancelInvoice() { - const onSuccess = useInvoiceInvalidation(); - return useMutation({ mutationFn: (id: string) => warehouseService.cancelInvoice(id), onSuccess }); -} - -export function usePayInvoice() { - const onSuccess = useInvoiceInvalidation(); - return useMutation({ - mutationFn: ({ id, payload }: { id: string; payload: PayInvoicePayload }) => - warehouseService.payInvoice(id, payload), - onSuccess, - }); -} - -export function useGateClearance() { - const onSuccess = useInvoiceInvalidation(); - return useMutation({ mutationFn: (inventoryId: string) => warehouseService.gateClearance(inventoryId), onSuccess }); -} diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/ArrivalQueuePage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/ArrivalQueuePage.tsx index 0b52d1388..317520f48 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/ArrivalQueuePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/ArrivalQueuePage.tsx @@ -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(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}.`, diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/DispatchQueuePage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/DispatchQueuePage.tsx index 1776ac8e0..d2786c0b9 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/DispatchQueuePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/DispatchQueuePage.tsx @@ -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 ( diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/InventoryInquiryPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/InventoryInquiryPage.tsx index eeaaa8848..582a9cedd 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/InventoryInquiryPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/InventoryInquiryPage.tsx @@ -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({}); const [applied, setApplied] = useState({}); - 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( diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadedInventoryPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadedInventoryPage.tsx index d5dbd0b10..b5deec80e 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadedInventoryPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadedInventoryPage.tsx @@ -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['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[] = [ { @@ -60,7 +63,9 @@ const columns: ColumnDef[] = [ /** 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 ( diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadingQueuePage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadingQueuePage.tsx index bb65d8fe6..f80db55f4 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadingQueuePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/LoadingQueuePage.tsx @@ -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).`, diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDashboardPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDashboardPage.tsx index 683baca15..60dbb13c4 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDashboardPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDashboardPage.tsx @@ -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 ( diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDetailPage.tsx index 145d3579d..31509766d 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDetailPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseDetailPage.tsx @@ -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(null); @@ -49,9 +56,18 @@ export default function WarehouseDetailPage() { const [editingZone, setEditingZone] = useState(null); const [selectedYardId, setSelectedYardId] = useState(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( diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInventoryPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInventoryPage.tsx index 234c37826..2ae417db1 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInventoryPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInventoryPage.tsx @@ -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})` })), diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInvoicesPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInvoicesPage.tsx index 7b1ae4d30..3f0958a7f 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInvoicesPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseInvoicesPage.tsx @@ -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(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(''); const canPay = inv && (inv.status === 'ISSUED' || inv.status === 'PARTIALLY_PAID'); diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseListPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseListPage.tsx index 3f9df44f6..93fcde493 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseListPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseListPage.tsx @@ -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 = () => { diff --git a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseRulesPage.tsx b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseRulesPage.tsx index af5adb83d..81e998385 100644 --- a/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseRulesPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/warehouses/WarehouseRulesPage.tsx @@ -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: '',