/** * Suppliers React Query hooks * Provides data fetching, caching, and state management for supplier operations */ import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'; import { suppliersService } from '../services/suppliers'; import { ApiError } from '../client/apiClient'; import type { SupplierCreate, SupplierUpdate, SupplierResponse, SupplierSummary, SupplierApproval, SupplierQueryParams, SupplierStatistics, TopSuppliersResponse, PurchaseOrderCreate, PurchaseOrderUpdate, PurchaseOrderResponse, PurchaseOrderApproval, PurchaseOrderQueryParams, DeliveryCreate, DeliveryUpdate, DeliveryResponse, DeliveryReceiptConfirmation, DeliveryQueryParams, PerformanceCalculationRequest, PerformanceMetrics, PerformanceAlert, PaginatedResponse, } from '../types/suppliers'; // Query Keys Factory export const suppliersKeys = { all: ['suppliers'] as const, suppliers: { all: () => [...suppliersKeys.all, 'suppliers'] as const, lists: () => [...suppliersKeys.suppliers.all(), 'list'] as const, list: (tenantId: string, params?: SupplierQueryParams) => [...suppliersKeys.suppliers.lists(), tenantId, params] as const, details: () => [...suppliersKeys.suppliers.all(), 'detail'] as const, detail: (tenantId: string, supplierId: string) => [...suppliersKeys.suppliers.details(), tenantId, supplierId] as const, statistics: (tenantId: string) => [...suppliersKeys.suppliers.all(), 'statistics', tenantId] as const, top: (tenantId: string) => [...suppliersKeys.suppliers.all(), 'top', tenantId] as const, byType: (tenantId: string, supplierType: string) => [...suppliersKeys.suppliers.all(), 'by-type', tenantId, supplierType] as const, }, purchaseOrders: { all: () => [...suppliersKeys.all, 'purchase-orders'] as const, lists: () => [...suppliersKeys.purchaseOrders.all(), 'list'] as const, list: (params?: PurchaseOrderQueryParams) => [...suppliersKeys.purchaseOrders.lists(), params] as const, details: () => [...suppliersKeys.purchaseOrders.all(), 'detail'] as const, detail: (orderId: string) => [...suppliersKeys.purchaseOrders.details(), orderId] as const, }, deliveries: { all: () => [...suppliersKeys.all, 'deliveries'] as const, lists: () => [...suppliersKeys.deliveries.all(), 'list'] as const, list: (params?: DeliveryQueryParams) => [...suppliersKeys.deliveries.lists(), params] as const, details: () => [...suppliersKeys.deliveries.all(), 'detail'] as const, detail: (deliveryId: string) => [...suppliersKeys.deliveries.details(), deliveryId] as const, }, performance: { all: () => [...suppliersKeys.all, 'performance'] as const, metrics: (tenantId: string, supplierId: string) => [...suppliersKeys.performance.all(), 'metrics', tenantId, supplierId] as const, alerts: (tenantId: string, supplierId?: string) => [...suppliersKeys.performance.all(), 'alerts', tenantId, supplierId] as const, }, } as const; // Supplier Queries export const useSuppliers = ( tenantId: string, queryParams?: SupplierQueryParams, options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: suppliersKeys.suppliers.list(tenantId, queryParams), queryFn: () => suppliersService.getSuppliers(tenantId, queryParams), enabled: !!tenantId, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; export const useSupplier = ( tenantId: string, supplierId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.suppliers.detail(tenantId, supplierId), queryFn: () => suppliersService.getSupplier(tenantId, supplierId), enabled: !!tenantId && !!supplierId, staleTime: 5 * 60 * 1000, // 5 minutes ...options, }); }; export const useSupplierStatistics = ( tenantId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.suppliers.statistics(tenantId), queryFn: () => suppliersService.getSupplierStatistics(tenantId), enabled: !!tenantId, staleTime: 5 * 60 * 1000, // 5 minutes ...options, }); }; export const useActiveSuppliers = ( tenantId: string, queryParams?: Omit, options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: suppliersKeys.suppliers.list(tenantId, { ...queryParams, status: 'active' }), queryFn: () => suppliersService.getActiveSuppliers(tenantId, queryParams), enabled: !!tenantId, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; export const useTopSuppliers = ( tenantId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.suppliers.top(tenantId), queryFn: () => suppliersService.getTopSuppliers(tenantId), enabled: !!tenantId, staleTime: 10 * 60 * 1000, // 10 minutes ...options, }); }; export const usePendingApprovalSuppliers = ( tenantId: string, options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: suppliersKeys.suppliers.list(tenantId, { status: 'pending_approval' }), queryFn: () => suppliersService.getPendingApprovalSuppliers(tenantId), enabled: !!tenantId, staleTime: 1 * 60 * 1000, // 1 minute ...options, }); }; export const useSuppliersByType = ( tenantId: string, supplierType: string, queryParams?: Omit, options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: suppliersKeys.suppliers.byType(tenantId, supplierType), queryFn: () => suppliersService.getSuppliersByType(tenantId, supplierType, queryParams), enabled: !!tenantId && !!supplierType, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; // Purchase Order Queries export const usePurchaseOrders = ( queryParams?: PurchaseOrderQueryParams, options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: suppliersKeys.purchaseOrders.list(queryParams), queryFn: () => suppliersService.getPurchaseOrders(queryParams), staleTime: 1 * 60 * 1000, // 1 minute ...options, }); }; export const usePurchaseOrder = ( orderId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.purchaseOrders.detail(orderId), queryFn: () => suppliersService.getPurchaseOrder(orderId), enabled: !!orderId, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; // Delivery Queries export const useDeliveries = ( queryParams?: DeliveryQueryParams, options?: Omit, ApiError>, 'queryKey' | 'queryFn'> ) => { return useQuery, ApiError>({ queryKey: suppliersKeys.deliveries.list(queryParams), queryFn: () => suppliersService.getDeliveries(queryParams), staleTime: 1 * 60 * 1000, // 1 minute ...options, }); }; export const useDelivery = ( deliveryId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.deliveries.detail(deliveryId), queryFn: () => suppliersService.getDelivery(deliveryId), enabled: !!deliveryId, staleTime: 30 * 1000, // 30 seconds ...options, }); }; // Performance Queries export const useSupplierPerformanceMetrics = ( tenantId: string, supplierId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.performance.metrics(tenantId, supplierId), queryFn: () => suppliersService.getSupplierPerformanceMetrics(tenantId, supplierId), enabled: !!tenantId && !!supplierId, staleTime: 10 * 60 * 1000, // 10 minutes ...options, }); }; export const usePerformanceAlerts = ( tenantId: string, supplierId?: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: suppliersKeys.performance.alerts(tenantId, supplierId), queryFn: () => suppliersService.getPerformanceAlerts(tenantId, supplierId), enabled: !!tenantId, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; // Supplier Mutations export const useCreateSupplier = ( options?: UseMutationOptions< SupplierResponse, ApiError, { tenantId: string; supplierData: SupplierCreate } > ) => { const queryClient = useQueryClient(); return useMutation< SupplierResponse, ApiError, { tenantId: string; supplierData: SupplierCreate } >({ mutationFn: ({ tenantId, supplierData }) => suppliersService.createSupplier(tenantId, supplierData), onSuccess: (data, { tenantId }) => { // Add to cache queryClient.setQueryData( suppliersKeys.suppliers.detail(tenantId, data.id), data ); // Invalidate lists and statistics queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.lists() }); queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.statistics(tenantId) }); }, ...options, }); }; export const useUpdateSupplier = ( options?: UseMutationOptions< SupplierResponse, ApiError, { tenantId: string; supplierId: string; updateData: SupplierUpdate } > ) => { const queryClient = useQueryClient(); return useMutation< SupplierResponse, ApiError, { tenantId: string; supplierId: string; updateData: SupplierUpdate } >({ mutationFn: ({ tenantId, supplierId, updateData }) => suppliersService.updateSupplier(tenantId, supplierId, updateData), onSuccess: (data, { tenantId, supplierId }) => { // Update cache queryClient.setQueryData( suppliersKeys.suppliers.detail(tenantId, supplierId), data ); // Invalidate lists queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.lists() }); }, ...options, }); }; export const useDeleteSupplier = ( options?: UseMutationOptions< { message: string }, ApiError, { tenantId: string; supplierId: string } > ) => { const queryClient = useQueryClient(); return useMutation< { message: string }, ApiError, { tenantId: string; supplierId: string } >({ mutationFn: ({ tenantId, supplierId }) => suppliersService.deleteSupplier(tenantId, supplierId), onSuccess: (_, { tenantId, supplierId }) => { // Remove from cache queryClient.removeQueries({ queryKey: suppliersKeys.suppliers.detail(tenantId, supplierId) }); // Invalidate lists and statistics queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.lists() }); queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.statistics(tenantId) }); }, ...options, }); }; export const useApproveSupplier = ( options?: UseMutationOptions< SupplierResponse, ApiError, { tenantId: string; supplierId: string; approval: SupplierApproval } > ) => { const queryClient = useQueryClient(); return useMutation< SupplierResponse, ApiError, { tenantId: string; supplierId: string; approval: SupplierApproval } >({ mutationFn: ({ tenantId, supplierId, approval }) => suppliersService.approveSupplier(tenantId, supplierId, approval), onSuccess: (data, { tenantId, supplierId }) => { // Update cache queryClient.setQueryData( suppliersKeys.suppliers.detail(tenantId, supplierId), data ); // Invalidate lists and statistics queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.lists() }); queryClient.invalidateQueries({ queryKey: suppliersKeys.suppliers.statistics(tenantId) }); }, ...options, }); }; // Purchase Order Mutations export const useCreatePurchaseOrder = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (orderData) => suppliersService.createPurchaseOrder(orderData), onSuccess: (data) => { // Add to cache queryClient.setQueryData( suppliersKeys.purchaseOrders.detail(data.id), data ); // Invalidate lists queryClient.invalidateQueries({ queryKey: suppliersKeys.purchaseOrders.lists() }); }, ...options, }); }; export const useUpdatePurchaseOrder = ( options?: UseMutationOptions< PurchaseOrderResponse, ApiError, { orderId: string; updateData: PurchaseOrderUpdate } > ) => { const queryClient = useQueryClient(); return useMutation< PurchaseOrderResponse, ApiError, { orderId: string; updateData: PurchaseOrderUpdate } >({ mutationFn: ({ orderId, updateData }) => suppliersService.updatePurchaseOrder(orderId, updateData), onSuccess: (data, { orderId }) => { // Update cache queryClient.setQueryData( suppliersKeys.purchaseOrders.detail(orderId), data ); // Invalidate lists queryClient.invalidateQueries({ queryKey: suppliersKeys.purchaseOrders.lists() }); }, ...options, }); }; export const useApprovePurchaseOrder = ( options?: UseMutationOptions< PurchaseOrderResponse, ApiError, { orderId: string; approval: PurchaseOrderApproval } > ) => { const queryClient = useQueryClient(); return useMutation< PurchaseOrderResponse, ApiError, { orderId: string; approval: PurchaseOrderApproval } >({ mutationFn: ({ orderId, approval }) => suppliersService.approvePurchaseOrder(orderId, approval), onSuccess: (data, { orderId }) => { // Update cache queryClient.setQueryData( suppliersKeys.purchaseOrders.detail(orderId), data ); // Invalidate lists queryClient.invalidateQueries({ queryKey: suppliersKeys.purchaseOrders.lists() }); }, ...options, }); }; // Delivery Mutations export const useCreateDelivery = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (deliveryData) => suppliersService.createDelivery(deliveryData), onSuccess: (data) => { // Add to cache queryClient.setQueryData( suppliersKeys.deliveries.detail(data.id), data ); // Invalidate lists queryClient.invalidateQueries({ queryKey: suppliersKeys.deliveries.lists() }); }, ...options, }); }; export const useUpdateDelivery = ( options?: UseMutationOptions< DeliveryResponse, ApiError, { deliveryId: string; updateData: DeliveryUpdate } > ) => { const queryClient = useQueryClient(); return useMutation< DeliveryResponse, ApiError, { deliveryId: string; updateData: DeliveryUpdate } >({ mutationFn: ({ deliveryId, updateData }) => suppliersService.updateDelivery(deliveryId, updateData), onSuccess: (data, { deliveryId }) => { // Update cache queryClient.setQueryData( suppliersKeys.deliveries.detail(deliveryId), data ); // Invalidate lists queryClient.invalidateQueries({ queryKey: suppliersKeys.deliveries.lists() }); }, ...options, }); }; export const useConfirmDeliveryReceipt = ( options?: UseMutationOptions< DeliveryResponse, ApiError, { deliveryId: string; confirmation: DeliveryReceiptConfirmation } > ) => { const queryClient = useQueryClient(); return useMutation< DeliveryResponse, ApiError, { deliveryId: string; confirmation: DeliveryReceiptConfirmation } >({ mutationFn: ({ deliveryId, confirmation }) => suppliersService.confirmDeliveryReceipt(deliveryId, confirmation), onSuccess: (data, { deliveryId }) => { // Update cache queryClient.setQueryData( suppliersKeys.deliveries.detail(deliveryId), data ); // Invalidate lists and performance metrics queryClient.invalidateQueries({ queryKey: suppliersKeys.deliveries.lists() }); queryClient.invalidateQueries({ queryKey: suppliersKeys.performance.all() }); }, ...options, }); }; // Performance Mutations export const useCalculateSupplierPerformance = ( options?: UseMutationOptions< { message: string; calculation_id: string }, ApiError, { tenantId: string; supplierId: string; request?: PerformanceCalculationRequest } > ) => { const queryClient = useQueryClient(); return useMutation< { message: string; calculation_id: string }, ApiError, { tenantId: string; supplierId: string; request?: PerformanceCalculationRequest } >({ mutationFn: ({ tenantId, supplierId, request }) => suppliersService.calculateSupplierPerformance(tenantId, supplierId, request), onSuccess: (_, { tenantId, supplierId }) => { // Invalidate performance metrics after calculation queryClient.invalidateQueries({ queryKey: suppliersKeys.performance.metrics(tenantId, supplierId) }); queryClient.invalidateQueries({ queryKey: suppliersKeys.performance.alerts(tenantId) }); }, ...options, }); }; export const useEvaluatePerformanceAlerts = ( options?: UseMutationOptions< { alerts_generated: number; message: string }, ApiError, { tenantId: string } > ) => { const queryClient = useQueryClient(); return useMutation< { alerts_generated: number; message: string }, ApiError, { tenantId: string } >({ mutationFn: ({ tenantId }) => suppliersService.evaluatePerformanceAlerts(tenantId), onSuccess: (_, { tenantId }) => { // Invalidate performance alerts queryClient.invalidateQueries({ queryKey: suppliersKeys.performance.alerts(tenantId) }); }, ...options, }); }; // Utility Hooks export const useSuppliersByStatus = (tenantId: string, status: string) => { return useSuppliers(tenantId, { status: status as any }); }; export const useSuppliersCount = (tenantId: string) => { const { data: statistics } = useSupplierStatistics(tenantId); return statistics?.total_suppliers || 0; }; export const useActiveSuppliersCount = (tenantId: string) => { const { data: statistics } = useSupplierStatistics(tenantId); return statistics?.active_suppliers || 0; }; export const usePendingOrdersCount = (supplierId?: string) => { const { data: orders } = usePurchaseOrders({ supplier_id: supplierId, status: 'pending_approval', limit: 1000 }); return orders?.data?.length || 0; };