183 lines
5.9 KiB
TypeScript
183 lines
5.9 KiB
TypeScript
|
|
/**
|
||
|
|
* Inventory Dashboard React Query hooks
|
||
|
|
*/
|
||
|
|
import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
||
|
|
import { inventoryDashboardService } from '../services/inventoryDashboard';
|
||
|
|
import {
|
||
|
|
InventoryDashboardSummary,
|
||
|
|
InventoryAnalytics,
|
||
|
|
BusinessModelInsights,
|
||
|
|
DashboardFilter,
|
||
|
|
AlertsFilter,
|
||
|
|
RecentActivity,
|
||
|
|
} from '../types/dashboard';
|
||
|
|
import { ApiError } from '../client';
|
||
|
|
|
||
|
|
// Query Keys
|
||
|
|
export const inventoryDashboardKeys = {
|
||
|
|
all: ['inventory-dashboard'] as const,
|
||
|
|
summary: (tenantId: string, filter?: DashboardFilter) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'summary', tenantId, filter] as const,
|
||
|
|
analytics: (tenantId: string, startDate?: string, endDate?: string) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'analytics', tenantId, { startDate, endDate }] as const,
|
||
|
|
insights: (tenantId: string) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'business-insights', tenantId] as const,
|
||
|
|
activity: (tenantId: string, limit?: number) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'recent-activity', tenantId, limit] as const,
|
||
|
|
alerts: (tenantId: string, filter?: AlertsFilter) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'alerts', tenantId, filter] as const,
|
||
|
|
stockSummary: (tenantId: string) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'stock-summary', tenantId] as const,
|
||
|
|
topCategories: (tenantId: string, limit?: number) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'top-categories', tenantId, limit] as const,
|
||
|
|
expiryCalendar: (tenantId: string, daysAhead?: number) =>
|
||
|
|
[...inventoryDashboardKeys.all, 'expiry-calendar', tenantId, daysAhead] as const,
|
||
|
|
} as const;
|
||
|
|
|
||
|
|
// Queries
|
||
|
|
export const useInventoryDashboardSummary = (
|
||
|
|
tenantId: string,
|
||
|
|
filter?: DashboardFilter,
|
||
|
|
options?: Omit<UseQueryOptions<InventoryDashboardSummary, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<InventoryDashboardSummary, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.summary(tenantId, filter),
|
||
|
|
queryFn: () => inventoryDashboardService.getDashboardSummary(tenantId, filter),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 30 * 1000, // 30 seconds
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useInventoryAnalytics = (
|
||
|
|
tenantId: string,
|
||
|
|
startDate?: string,
|
||
|
|
endDate?: string,
|
||
|
|
options?: Omit<UseQueryOptions<InventoryAnalytics, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<InventoryAnalytics, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.analytics(tenantId, startDate, endDate),
|
||
|
|
queryFn: () => inventoryDashboardService.getInventoryAnalytics(tenantId, startDate, endDate),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 2 * 60 * 1000, // 2 minutes
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useBusinessModelInsights = (
|
||
|
|
tenantId: string,
|
||
|
|
options?: Omit<UseQueryOptions<BusinessModelInsights, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<BusinessModelInsights, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.insights(tenantId),
|
||
|
|
queryFn: () => inventoryDashboardService.getBusinessModelInsights(tenantId),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 10 * 60 * 1000, // 10 minutes
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useRecentActivity = (
|
||
|
|
tenantId: string,
|
||
|
|
limit: number = 20,
|
||
|
|
options?: Omit<UseQueryOptions<RecentActivity[], ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<RecentActivity[], ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.activity(tenantId, limit),
|
||
|
|
queryFn: () => inventoryDashboardService.getRecentActivity(tenantId, limit),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 30 * 1000, // 30 seconds
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useInventoryAlerts = (
|
||
|
|
tenantId: string,
|
||
|
|
filter?: AlertsFilter,
|
||
|
|
options?: Omit<UseQueryOptions<{ items: any[]; total: number }, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<{ items: any[]; total: number }, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.alerts(tenantId, filter),
|
||
|
|
queryFn: () => inventoryDashboardService.getAlerts(tenantId, filter),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 30 * 1000, // 30 seconds
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useStockSummary = (
|
||
|
|
tenantId: string,
|
||
|
|
options?: Omit<UseQueryOptions<{
|
||
|
|
in_stock: number;
|
||
|
|
low_stock: number;
|
||
|
|
out_of_stock: number;
|
||
|
|
overstock: number;
|
||
|
|
total_value: number;
|
||
|
|
}, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<{
|
||
|
|
in_stock: number;
|
||
|
|
low_stock: number;
|
||
|
|
out_of_stock: number;
|
||
|
|
overstock: number;
|
||
|
|
total_value: number;
|
||
|
|
}, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.stockSummary(tenantId),
|
||
|
|
queryFn: () => inventoryDashboardService.getStockSummary(tenantId),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 1 * 60 * 1000, // 1 minute
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useTopCategories = (
|
||
|
|
tenantId: string,
|
||
|
|
limit: number = 10,
|
||
|
|
options?: Omit<UseQueryOptions<Array<{
|
||
|
|
category: string;
|
||
|
|
ingredient_count: number;
|
||
|
|
total_value: number;
|
||
|
|
low_stock_count: number;
|
||
|
|
}>, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<Array<{
|
||
|
|
category: string;
|
||
|
|
ingredient_count: number;
|
||
|
|
total_value: number;
|
||
|
|
low_stock_count: number;
|
||
|
|
}>, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.topCategories(tenantId, limit),
|
||
|
|
queryFn: () => inventoryDashboardService.getTopCategories(tenantId, limit),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
export const useExpiryCalendar = (
|
||
|
|
tenantId: string,
|
||
|
|
daysAhead: number = 30,
|
||
|
|
options?: Omit<UseQueryOptions<Array<{
|
||
|
|
date: string;
|
||
|
|
items: Array<{
|
||
|
|
ingredient_name: string;
|
||
|
|
quantity: number;
|
||
|
|
batch_number?: string;
|
||
|
|
}>;
|
||
|
|
}>, ApiError>, 'queryKey' | 'queryFn'>
|
||
|
|
) => {
|
||
|
|
return useQuery<Array<{
|
||
|
|
date: string;
|
||
|
|
items: Array<{
|
||
|
|
ingredient_name: string;
|
||
|
|
quantity: number;
|
||
|
|
batch_number?: string;
|
||
|
|
}>;
|
||
|
|
}>, ApiError>({
|
||
|
|
queryKey: inventoryDashboardKeys.expiryCalendar(tenantId, daysAhead),
|
||
|
|
queryFn: () => inventoryDashboardService.getExpiryCalendar(tenantId, daysAhead),
|
||
|
|
enabled: !!tenantId,
|
||
|
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
||
|
|
...options,
|
||
|
|
});
|
||
|
|
};
|