/** * Sales React Query hooks */ import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'; import { salesService } from '../services/sales'; import { SalesDataCreate, SalesDataUpdate, SalesDataResponse, SalesDataQuery, SalesAnalytics, } from '../types/sales'; import { ApiError } from '../client'; // Query Keys export const salesKeys = { all: ['sales'] as const, lists: () => [...salesKeys.all, 'list'] as const, list: (tenantId: string, filters?: SalesDataQuery) => [...salesKeys.lists(), tenantId, filters] as const, details: () => [...salesKeys.all, 'detail'] as const, detail: (tenantId: string, recordId: string) => [...salesKeys.details(), tenantId, recordId] as const, analytics: (tenantId: string, startDate?: string, endDate?: string) => [...salesKeys.all, 'analytics', tenantId, { startDate, endDate }] as const, productSales: (tenantId: string, productId: string, startDate?: string, endDate?: string) => [...salesKeys.all, 'product-sales', tenantId, productId, { startDate, endDate }] as const, categories: (tenantId: string) => [...salesKeys.all, 'categories', tenantId] as const, } as const; // Queries export const useSalesRecords = ( tenantId: string, query?: SalesDataQuery, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: salesKeys.list(tenantId, query), queryFn: () => salesService.getSalesRecords(tenantId, query), enabled: !!tenantId, staleTime: 30 * 1000, // 30 seconds ...options, }); }; export const useSalesRecord = ( tenantId: string, recordId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: salesKeys.detail(tenantId, recordId), queryFn: () => salesService.getSalesRecord(tenantId, recordId), enabled: !!tenantId && !!recordId, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; export const useSalesAnalytics = ( tenantId: string, startDate?: string, endDate?: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: salesKeys.analytics(tenantId, startDate, endDate), queryFn: () => salesService.getSalesAnalytics(tenantId, startDate, endDate), enabled: !!tenantId, staleTime: 5 * 60 * 1000, // 5 minutes ...options, }); }; export const useProductSales = ( tenantId: string, inventoryProductId: string, startDate?: string, endDate?: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: salesKeys.productSales(tenantId, inventoryProductId, startDate, endDate), queryFn: () => salesService.getProductSales(tenantId, inventoryProductId, startDate, endDate), enabled: !!tenantId && !!inventoryProductId, staleTime: 2 * 60 * 1000, // 2 minutes ...options, }); }; export const useProductCategories = ( tenantId: string, options?: Omit, 'queryKey' | 'queryFn'> ) => { return useQuery({ queryKey: salesKeys.categories(tenantId), queryFn: () => salesService.getProductCategories(tenantId), enabled: !!tenantId, staleTime: 10 * 60 * 1000, // 10 minutes ...options, }); }; // Mutations export const useCreateSalesRecord = ( options?: UseMutationOptions ) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ tenantId, salesData }) => salesService.createSalesRecord(tenantId, salesData), onSuccess: (data, { tenantId }) => { // Invalidate sales lists to refresh data queryClient.invalidateQueries({ queryKey: salesKeys.lists() }); queryClient.invalidateQueries({ queryKey: salesKeys.analytics(tenantId) }); // Set the new record in cache queryClient.setQueryData(salesKeys.detail(tenantId, data.id), data); }, ...options, }); }; export const useUpdateSalesRecord = ( options?: UseMutationOptions< SalesDataResponse, ApiError, { tenantId: string; recordId: string; updateData: SalesDataUpdate } > ) => { const queryClient = useQueryClient(); return useMutation< SalesDataResponse, ApiError, { tenantId: string; recordId: string; updateData: SalesDataUpdate } >({ mutationFn: ({ tenantId, recordId, updateData }) => salesService.updateSalesRecord(tenantId, recordId, updateData), onSuccess: (data, { tenantId, recordId }) => { // Update the record cache queryClient.setQueryData(salesKeys.detail(tenantId, recordId), data); // Invalidate related queries queryClient.invalidateQueries({ queryKey: salesKeys.lists() }); queryClient.invalidateQueries({ queryKey: salesKeys.analytics(tenantId) }); }, ...options, }); }; export const useDeleteSalesRecord = ( options?: UseMutationOptions<{ message: string }, ApiError, { tenantId: string; recordId: string }> ) => { const queryClient = useQueryClient(); return useMutation<{ message: string }, ApiError, { tenantId: string; recordId: string }>({ mutationFn: ({ tenantId, recordId }) => salesService.deleteSalesRecord(tenantId, recordId), onSuccess: (data, { tenantId, recordId }) => { // Remove from cache queryClient.removeQueries({ queryKey: salesKeys.detail(tenantId, recordId) }); // Invalidate related queries queryClient.invalidateQueries({ queryKey: salesKeys.lists() }); queryClient.invalidateQueries({ queryKey: salesKeys.analytics(tenantId) }); }, ...options, }); }; export const useValidateSalesRecord = ( options?: UseMutationOptions< SalesDataResponse, ApiError, { tenantId: string; recordId: string; validationNotes?: string } > ) => { const queryClient = useQueryClient(); return useMutation< SalesDataResponse, ApiError, { tenantId: string; recordId: string; validationNotes?: string } >({ mutationFn: ({ tenantId, recordId, validationNotes }) => salesService.validateSalesRecord(tenantId, recordId, validationNotes), onSuccess: (data, { tenantId, recordId }) => { // Update the record cache queryClient.setQueryData(salesKeys.detail(tenantId, recordId), data); // Invalidate sales lists to reflect validation status queryClient.invalidateQueries({ queryKey: salesKeys.lists() }); }, ...options, }); };