import React, { useState, useEffect } from "react"; import { useQuery, useMutation } from '@apollo/client'; import ProfileHistoryItem from "./ProfileHistoryItem"; import SearchInput from "./SearchInput"; import ProfileHistoryTabs from "./ProfileHistoryTabs"; import Pagination from '../Pagination'; import { GET_PARTS_SEARCH_HISTORY, DELETE_SEARCH_HISTORY_ITEM, CLEAR_SEARCH_HISTORY, CREATE_SEARCH_HISTORY_ITEM, PartsSearchHistoryItem, PartsSearchHistoryResponse } from '@/lib/graphql/search-history'; const ProfileHistoryMain = () => { const [search, setSearch] = useState(""); const [activeTab, setActiveTab] = useState("Все"); const [selectedManufacturer, setSelectedManufacturer] = useState("Все"); const [sortField, setSortField] = useState<"date" | "manufacturer" | "name">("date"); const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc"); const [filteredItems, setFilteredItems] = useState([]); // Состояние пагинации const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(10); // Количество элементов на странице const tabOptions = ["Все", "Сегодня", "Вчера", "Эта неделя", "Этот месяц"]; // GraphQL запросы const { data, loading, error, refetch } = useQuery<{ partsSearchHistory: PartsSearchHistoryResponse }>( GET_PARTS_SEARCH_HISTORY, { variables: { limit: 1000, // Загружаем больше для клиентской пагинации с фильтрами offset: 0 }, fetchPolicy: 'cache-and-network', onCompleted: (data) => { console.log('История поиска загружена:', data); }, onError: (error) => { console.error('Ошибка загрузки истории поиска:', error); } } ); const [deleteItem] = useMutation(DELETE_SEARCH_HISTORY_ITEM, { onCompleted: () => { refetch(); }, onError: (error) => { console.error('Ошибка удаления элемента истории:', error); } }); const [clearHistory] = useMutation(CLEAR_SEARCH_HISTORY, { onCompleted: () => { refetch(); }, onError: (error) => { console.error('Ошибка очистки истории:', error); } }); const [createHistoryItem] = useMutation(CREATE_SEARCH_HISTORY_ITEM, { onCompleted: () => { refetch(); }, onError: (error) => { console.error('Ошибка создания записи истории:', error); } }); const historyItems = data?.partsSearchHistory?.items || []; // Отладочная информация console.log('ProfileHistoryMain состояние:', { loading, error: error?.message, data, historyItemsCount: historyItems.length }); // Фильтрация по времени const getFilteredByTime = (items: PartsSearchHistoryItem[], timeFilter: string) => { const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const yesterday = new Date(today); yesterday.setDate(yesterday.getDate() - 1); const weekAgo = new Date(today); weekAgo.setDate(weekAgo.getDate() - 7); const monthAgo = new Date(today); monthAgo.setMonth(monthAgo.getMonth() - 1); switch (timeFilter) { case "Сегодня": return items.filter(item => new Date(item.createdAt) >= today); case "Вчера": return items.filter(item => { const itemDate = new Date(item.createdAt); return itemDate >= yesterday && itemDate < today; }); case "Эта неделя": return items.filter(item => new Date(item.createdAt) >= weekAgo); case "Этот месяц": return items.filter(item => new Date(item.createdAt) >= monthAgo); default: return items; } }; // Фильтрация и сортировка useEffect(() => { let filtered = [...getFilteredByTime(historyItems, activeTab)]; // Фильтрация по производителю if (selectedManufacturer !== "Все") { filtered = filtered.filter(item => item.brand === selectedManufacturer || item.vehicleInfo?.brand === selectedManufacturer ); } // Поиск if (search.trim()) { const searchLower = search.toLowerCase(); filtered = filtered.filter(item => item.searchQuery.toLowerCase().includes(searchLower) || item.brand?.toLowerCase().includes(searchLower) || item.articleNumber?.toLowerCase().includes(searchLower) || item.vehicleInfo?.brand?.toLowerCase().includes(searchLower) || item.vehicleInfo?.model?.toLowerCase().includes(searchLower) ); } // Сортировка if (sortField) { filtered.sort((a, b) => { let aValue: string | number = ''; let bValue: string | number = ''; switch (sortField) { case 'date': aValue = new Date(a.createdAt).getTime(); bValue = new Date(b.createdAt).getTime(); break; case 'manufacturer': aValue = a.brand || a.vehicleInfo?.brand || ''; bValue = b.brand || b.vehicleInfo?.brand || ''; break; case 'name': aValue = a.searchQuery; bValue = b.searchQuery; break; } if (typeof aValue === 'string' && typeof bValue === 'string') { const comparison = aValue.localeCompare(bValue); return sortOrder === 'asc' ? comparison : -comparison; } if (typeof aValue === 'number' && typeof bValue === 'number') { return sortOrder === 'asc' ? aValue - bValue : bValue - aValue; } return 0; }); } setFilteredItems(filtered); // Сбрасываем страницу на первую при изменении фильтров setCurrentPage(1); }, [historyItems, search, activeTab, selectedManufacturer, sortField, sortOrder]); // Вычисляем элементы для текущей страницы const totalPages = Math.ceil(filteredItems.length / itemsPerPage); const startIndex = (currentPage - 1) * itemsPerPage; const endIndex = startIndex + itemsPerPage; const currentPageItems = filteredItems.slice(startIndex, endIndex); // Обработчик изменения страницы const handlePageChange = (page: number) => { setCurrentPage(page); // Прокручиваем к началу списка при смене страницы const historyContainer = document.querySelector('.flex.flex-col.mt-5.w-full.text-gray-400'); if (historyContainer) { historyContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }; // Обработчик изменения количества элементов на странице const handleItemsPerPageChange = (newItemsPerPage: number) => { setItemsPerPage(newItemsPerPage); setCurrentPage(1); // Сбрасываем на первую страницу }; const handleSort = (field: "date" | "manufacturer" | "name") => { if (sortField === field) { setSortOrder(sortOrder === "asc" ? "desc" : "asc"); } else { setSortField(field); setSortOrder("desc"); // По умолчанию сначала новые } }; const handleDeleteItem = async (id: string) => { if (window.confirm('Удалить этот элемент из истории?')) { try { await deleteItem({ variables: { id } }); } catch (error) { console.error('Ошибка удаления:', error); } } }; const handleClearHistory = async () => { if (window.confirm('Очистить всю историю поиска? Это действие нельзя отменить.')) { try { await clearHistory(); } catch (error) { console.error('Ошибка очистки истории:', error); } } }; const handleCreateTestData = async () => { const testItems = [ { searchQuery: "тормозные колодки", searchType: "TEXT" as const, brand: "BREMBO", resultCount: 15, vehicleBrand: "BMW", vehicleModel: "X5", vehicleYear: 2020 }, { searchQuery: "0986424781", searchType: "ARTICLE" as const, brand: "BOSCH", articleNumber: "0986424781", resultCount: 3 }, { searchQuery: "масляный фильтр", searchType: "TEXT" as const, brand: "MANN", resultCount: 22, vehicleBrand: "AUDI", vehicleModel: "A4", vehicleYear: 2018 }, { searchQuery: "34116858652", searchType: "OEM" as const, brand: "BMW", articleNumber: "34116858652", resultCount: 8, vehicleBrand: "BMW", vehicleModel: "3 Series", vehicleYear: 2019 }, { searchQuery: "свечи зажигания", searchType: "TEXT" as const, brand: "NGK", resultCount: 45 } ]; try { for (const item of testItems) { await createHistoryItem({ variables: { input: item } }); // Небольшая задержка между запросами await new Promise(resolve => setTimeout(resolve, 200)); } } catch (error) { console.error('Ошибка создания тестовых данных:', error); } }; if (loading && historyItems.length === 0) { return (
Загрузка истории поиска...
); } if (error) { return (
Ошибка загрузки истории поиска
); } return (
setSearch(e.target.value)} placeholder="Поиск в истории..." />
{(selectedManufacturer !== "Все" || search.trim() || activeTab !== "Все") && ( )} {historyItems.length === 0 && ( )} {historyItems.length > 0 && ( )}
handleSort('date')} > Дата и время
handleSort('manufacturer')} > Производитель
Артикул/Тип
handleSort('name')} > Поисковый запрос
Действия
{filteredItems.length === 0 ? (
{historyItems.length === 0 ? ( <>
История поиска пуста
Ваши поисковые запросы будут отображаться здесь
) : ( <>
Ничего не найдено
Попробуйте изменить фильтры или поисковый запрос
)}
) : ( currentPageItems.map((item) => ( )) )}
{/* Пагинация */} {filteredItems.length > 0 && (
{/* Селектор количества элементов на странице */}
Показывать по: записей
Показано {startIndex + 1}-{Math.min(endIndex, filteredItems.length)} из {filteredItems.length} записей {filteredItems.length !== historyItems.length && ( (всего {historyItems.length}) )} {(selectedManufacturer !== "Все" || search.trim() || activeTab !== "Все") && ( (применены фильтры) )}
{/* Компонент пагинации */} {filteredItems.length > itemsPerPage && ( )}
)}
); }; export default ProfileHistoryMain;