dressed_for_succes_store/frontend/hooks/useAdminApi.ts
2025-04-27 03:00:13 +07:00

185 lines
4.7 KiB
TypeScript

import { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
import { toast } from 'react-hot-toast';
import api from '@/lib/api';
import { cacheKeys } from '@/lib/api-cache';
export function useAdminQuery<TData = unknown, TError = unknown>(
key: string | string[],
url: string,
params: Record<string, any> = {},
options: Omit<UseQueryOptions<TData, TError, TData>, 'queryKey' | 'queryFn'> = {}
) {
const queryKey = Array.isArray(key) ? key : [key];
return useQuery<TData, TError>({
queryKey,
queryFn: async () => {
try {
return await api.get<TData>(url, { params });
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
throw error;
}
},
...options
});
}
export function useAdminMutation<TData = unknown, TError = unknown, TVariables = unknown>(
method: 'post' | 'put' | 'delete',
url: string,
options: {
onSuccessMessage?: string;
onErrorMessage?: string;
invalidateQueries?: (string | string[])[];
mutationOptions?: Omit<UseMutationOptions<TData, TError, TVariables>, 'mutationFn'>;
} = {}
) {
const queryClient = useQueryClient();
const {
onSuccessMessage = 'Операция выполнена успешно',
onErrorMessage = 'Произошла ошибка при выполнении операции',
invalidateQueries = [],
mutationOptions = {}
} = options;
return useMutation<TData, TError, TVariables>({
mutationFn: async (variables) => {
try {
if (method === 'delete') {
return await api.delete<TData>(url);
} else {
return await api[method]<TData>(url, variables);
}
} catch (error) {
console.error(`Error executing ${method.toUpperCase()} ${url}:`, error);
throw error;
}
},
onSuccess: (data, variables, context) => {
if (onSuccessMessage) toast.success(onSuccessMessage);
if (invalidateQueries.length > 0) {
invalidateQueries.forEach(key => {
if (Array.isArray(key)) {
queryClient.invalidateQueries({ queryKey: key });
} else {
queryClient.invalidateQueries({ queryKey: [key] });
}
});
}
if (mutationOptions.onSuccess) {
mutationOptions.onSuccess(data, variables, context);
}
},
onError: (error, variables, context) => {
if (onErrorMessage) toast.error(onErrorMessage);
if (mutationOptions.onError) {
mutationOptions.onError(error, variables, context);
}
},
...mutationOptions
});
}
export function useProducts(params: Record<string, any> = {}, options = {}) {
return useAdminQuery(
[cacheKeys.products, JSON.stringify(params)],
'/catalog/products',
params,
options
);
}
export function useProduct(id: number | string, options = {}) {
return useAdminQuery(
cacheKeys.product(id),
`/catalog/products/${id}`,
{},
options
);
}
export function useCategories(params: Record<string, any> = {}, options = {}) {
return useAdminQuery(
[cacheKeys.categories, JSON.stringify(params)],
'/catalog/categories',
params,
options
);
}
export function useCollections(params: Record<string, any> = {}, options = {}) {
return useAdminQuery(
[cacheKeys.collections, JSON.stringify(params)],
'/catalog/collections',
params,
options
);
}
export function useSizes(params: Record<string, any> = {}, options = {}) {
return useAdminQuery(
[cacheKeys.sizes, JSON.stringify(params)],
'/catalog/sizes',
params,
options
);
}
export function useOrders(params: Record<string, any> = {}, options = {}) {
return useAdminQuery(
[cacheKeys.orders, JSON.stringify(params)],
'/admin/orders',
params,
options
);
}
export function useOrder(id: number | string, options = {}) {
return useAdminQuery(
cacheKeys.order(id),
`/admin/orders/${id}`,
{},
options
);
}
export function useDashboardStats(options = {}) {
return useAdminQuery(
cacheKeys.dashboardStats,
'/admin/dashboard/stats',
{},
options
);
}
export function useRecentOrders(limit = 5, options = {}) {
return useAdminQuery(
cacheKeys.recentOrders,
'/admin/orders/recent',
{ limit },
options
);
}
export function usePopularProducts(limit = 5, options = {}) {
return useAdminQuery(
cacheKeys.popularProducts,
'/admin/products/popular',
{ limit },
options
);
}
export default {
useAdminQuery,
useAdminMutation,
useProducts,
useProduct,
useCategories,
useCollections,
useSizes,
useOrders,
useOrder,
useDashboardStats,
useRecentOrders,
usePopularProducts
};