Files
bakery-ia/frontend/src/api/hooks/sales.ts

190 lines
6.6 KiB
TypeScript
Raw Normal View History

/**
* 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<UseQueryOptions<SalesDataResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<SalesDataResponse[], ApiError>({
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<UseQueryOptions<SalesDataResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<SalesDataResponse, ApiError>({
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<UseQueryOptions<SalesAnalytics, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<SalesAnalytics, ApiError>({
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<UseQueryOptions<SalesDataResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<SalesDataResponse[], ApiError>({
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<UseQueryOptions<string[], ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<string[], ApiError>({
queryKey: salesKeys.categories(tenantId),
queryFn: () => salesService.getProductCategories(tenantId),
enabled: !!tenantId,
staleTime: 10 * 60 * 1000, // 10 minutes
...options,
});
};
// Mutations
export const useCreateSalesRecord = (
options?: UseMutationOptions<SalesDataResponse, ApiError, { tenantId: string; salesData: SalesDataCreate }>
) => {
const queryClient = useQueryClient();
return useMutation<SalesDataResponse, ApiError, { tenantId: string; salesData: SalesDataCreate }>({
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,
});
};