dressed_for_succes_store/frontend/hooks/useAdminApi.ts
ilya_zahvatkin 41c1385546 for deploy
2025-05-01 18:29:38 +07:00

220 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 {
const response = await api.get<TData>(url, { params });
return response;
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
throw error;
}
},
// Оптимизированные настройки кэширования
staleTime: 5 * 60 * 1000, // 5 минут - данные считаются свежими
gcTime: 10 * 60 * 1000, // 10 минут - данные хранятся в кэше
...options
});
}
/**
* Хук для выполнения мутаций (POST, PUT, DELETE) с использованием react-query
* @param method Метод запроса
* @param url URL для запроса или функция, возвращающая URL
* @param options Дополнительные опции для useMutation
* @returns Результат выполнения useMutation
*/
export function useAdminMutation<TData = unknown, TError = unknown, TVariables = unknown>(
method: 'post' | 'put' | 'delete',
url: string | ((variables: TVariables) => 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 {
const resolvedUrl = typeof url === 'function' ? url(variables) : url;
if (method === 'delete') {
return await api.delete<TData>(resolvedUrl);
} else {
return await api[method]<TData>(resolvedUrl, variables);
}
} catch (error) {
console.error(`Error in ${method.toUpperCase()} request to ${typeof url === 'string' ? url : 'dynamic URL'}:`, error);
throw error;
}
},
onSuccess: (data, variables, context) => {
// Показываем сообщение об успехе
if (onSuccessMessage) {
toast.success(onSuccessMessage);
}
// Инвалидируем кэш для указанных запросов
if (invalidateQueries.length > 0) {
invalidateQueries.forEach(queryKey => {
if (Array.isArray(queryKey)) {
queryClient.invalidateQueries({ queryKey });
} else {
queryClient.invalidateQueries({ queryKey: [queryKey] });
}
});
}
// Вызываем пользовательский обработчик успеха
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)],
'/orders',
params,
options
);
}
export function useOrder(id: number | string, options = {}) {
return useAdminQuery(
cacheKeys.order(id),
`/orders/${id}`,
{},
options
);
}
export function useDashboardStats(options = {}) {
return useAdminQuery(
cacheKeys.dashboardStats,
'/dashboard/stats',
{},
options
);
}
export function useRecentOrders(limit = 5, options = {}) {
return useAdminQuery(
cacheKeys.recentOrders,
'/orders/recent',
{ limit },
options
);
}
export function usePopularProducts(limit = 5, options = {}) {
return useAdminQuery(
cacheKeys.popularProducts,
'/catalog/products/popular',
{ limit },
options
);
}
export default {
useAdminQuery,
useAdminMutation,
useProducts,
useProduct,
useCategories,
useCollections,
useSizes,
useOrders,
useOrder,
useDashboardStats,
useRecentOrders,
usePopularProducts
};