import { useState, useCallback, useEffect } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { toast } from 'react-hot-toast'; import { useAdminQuery, useAdminMutation } from '@/hooks/useAdminApi'; import { cacheKeys } from '@/lib/api-cache'; import { Order } from '@/lib/orders'; interface OrdersState { orders: Order[]; loading: { fetch: boolean; update: boolean; }; error: Error | null; selectedOrders: number[]; pagination: { page: number; pageSize: number; total: number; }; filters: { search: string; status: string; dateRange: string; }; } export function useOrders() { const router = useRouter(); const searchParams = useSearchParams(); // Состояние const [state, setState] = useState({ orders: [], loading: { fetch: true, update: false, }, error: null, selectedOrders: [], pagination: { page: 1, pageSize: 10, total: 0, }, filters: { search: '', status: '', dateRange: '', }, }); // Получаем параметры из URL при первой загрузке useEffect(() => { const page = searchParams.get('page') ? parseInt(searchParams.get('page') as string, 10) : 1; const search = searchParams.get('search') || ''; const status = searchParams.get('status') || ''; const dateRange = searchParams.get('dateRange') || ''; setState(prev => ({ ...prev, pagination: { ...prev.pagination, page, }, filters: { search, status, dateRange, }, })); }, [searchParams]); // Формируем параметры запроса const queryParams = { skip: (state.pagination.page - 1) * state.pagination.pageSize, limit: state.pagination.pageSize, search: state.filters.search, status: state.filters.status || undefined, date_range: state.filters.dateRange || undefined, }; // Запрос на получение заказов const { data, isLoading, error, refetch } = useAdminQuery( [cacheKeys.orders, JSON.stringify(queryParams)], '/orders', queryParams, { onSuccess: (data) => { if (data) { // API возвращает массив заказов, а не объект с полями orders и total const orders = Array.isArray(data) ? data : []; setState(prev => ({ ...prev, orders: orders, pagination: { ...prev.pagination, total: orders.length, // Используем длину массива как общее количество }, loading: { ...prev.loading, fetch: false, }, })); } }, onError: (err) => { setState(prev => ({ ...prev, error: err as Error, loading: { ...prev.loading, fetch: false, }, })); }, } ); // Мутация для обновления статуса заказа const updateStatusMutation = useAdminMutation( 'put', ({ id }) => `/orders/${id}`, { onSuccessMessage: 'Статус заказа успешно обновлен', onErrorMessage: 'Не удалось обновить статус заказа', invalidateQueries: [cacheKeys.orders], mutationOptions: { onMutate: () => { setState(prev => ({ ...prev, loading: { ...prev.loading, update: true, }, })); }, onSettled: () => { setState(prev => ({ ...prev, loading: { ...prev.loading, update: false, }, })); }, }, } ); // Обработчик обновления статуса заказа const updateOrderStatus = useCallback(async (id: number, status: string) => { try { // Передаем только статус в теле запроса, как требуется API await updateStatusMutation.mutateAsync({ id, status }); } catch (error) { console.error('Error updating order status:', error); } }, [updateStatusMutation]); // Обработчик изменения фильтров const setFilter = useCallback((key: keyof OrdersState['filters'], value: any) => { setState(prev => ({ ...prev, filters: { ...prev.filters, [key]: value, }, pagination: { ...prev.pagination, page: 1, // Сбрасываем страницу при изменении фильтров }, })); // Обновляем URL с новыми параметрами const params = new URLSearchParams(searchParams.toString()); params.set('page', '1'); if (value !== null && value !== '') { params.set(key, value.toString()); } else { params.delete(key); } // Обновляем URL router.push(`/admin/orders?${params.toString()}`); }, [router, searchParams]); // Обработчик изменения страницы const setPage = useCallback((page: number) => { setState(prev => ({ ...prev, pagination: { ...prev.pagination, page, }, })); // Обновляем URL с новой страницей const params = new URLSearchParams(searchParams.toString()); params.set('page', page.toString()); router.push(`/admin/orders?${params.toString()}`); }, [router, searchParams]); // Обработчик изменения размера страницы const setPageSize = useCallback((pageSize: number) => { setState(prev => ({ ...prev, pagination: { ...prev.pagination, pageSize, page: 1, // Сбрасываем страницу при изменении размера }, })); // Обновляем URL с новым размером страницы const params = new URLSearchParams(searchParams.toString()); params.set('page', '1'); params.set('pageSize', pageSize.toString()); router.push(`/admin/orders?${params.toString()}`); }, [router, searchParams]); // Обработчик выбора заказов const selectOrders = useCallback((selectedIds: number[]) => { setState(prev => ({ ...prev, selectedOrders: selectedIds, })); }, []); // Обновляем состояние при изменении данных useEffect(() => { if (data) { // API возвращает массив заказов, а не объект с полями orders и total const orders = Array.isArray(data) ? data : []; setState(prev => ({ ...prev, orders: orders, pagination: { ...prev.pagination, total: orders.length, // Используем длину массива как общее количество }, loading: { ...prev.loading, fetch: false, }, })); } }, [data]); // Обновляем состояние при ошибке useEffect(() => { if (error) { setState(prev => ({ ...prev, error: error as Error, loading: { ...prev.loading, fetch: false, }, })); } }, [error]); return { orders: state.orders, loading: { fetch: isLoading || state.loading.fetch, update: state.loading.update }, error: state.error, selectedOrders: state.selectedOrders, pagination: state.pagination, filters: state.filters, updateOrderStatus, setFilter, setPage, setPageSize, selectOrders, refetch, }; } export default useOrders;