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( key: string | string[], url: string, params: Record = {}, options: Omit, 'queryKey' | 'queryFn'> = {} ) { const queryKey = Array.isArray(key) ? key : [key]; return useQuery({ queryKey, queryFn: async () => { try { return await api.get(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( method: 'post' | 'put' | 'delete', url: string, options: { onSuccessMessage?: string; onErrorMessage?: string; invalidateQueries?: (string | string[])[]; mutationOptions?: Omit, 'mutationFn'>; } = {} ) { const queryClient = useQueryClient(); const { onSuccessMessage = 'Операция выполнена успешно', onErrorMessage = 'Произошла ошибка при выполнении операции', invalidateQueries = [], mutationOptions = {} } = options; return useMutation({ mutationFn: async (variables) => { try { if (method === 'delete') { return await api.delete(url); } else { return await api[method](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 = {}, 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 = {}, options = {}) { return useAdminQuery( [cacheKeys.categories, JSON.stringify(params)], '/catalog/categories', params, options ); } /** * Хук для получения списка коллекций */ export function useCollections(params: Record = {}, options = {}) { return useAdminQuery( [cacheKeys.collections, JSON.stringify(params)], '/catalog/collections', params, options ); } /** * Хук для получения списка размеров */ export function useSizes(params: Record = {}, options = {}) { return useAdminQuery( [cacheKeys.sizes, JSON.stringify(params)], '/catalog/sizes', params, options ); } /** * Хук для получения списка заказов */ export function useOrders(params: Record = {}, 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 };