245 lines
6.6 KiB
TypeScript
245 lines
6.6 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';
|
||
|
||
/**
|
||
* Хук для выполнения GET-запросов с использованием react-query
|
||
* @param key Ключ кэша
|
||
* @param url URL для запроса
|
||
* @param params Параметры запроса
|
||
* @param options Дополнительные опции для useQuery
|
||
* @returns Результат выполнения useQuery
|
||
*/
|
||
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
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Хук для выполнения мутаций (POST, PUT, DELETE) с использованием react-query
|
||
* @param method Метод запроса (post, put, delete)
|
||
* @param url URL для запроса
|
||
* @param options Дополнительные опции для useMutation
|
||
* @returns Результат выполнения useMutation
|
||
*/
|
||
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
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Хук для получения продукта по ID
|
||
*/
|
||
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
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Хук для получения заказа по ID
|
||
*/
|
||
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
|
||
};
|