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

245 lines
6.6 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 {
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
};