import React, { useState, useEffect } from "react"; import Link from "next/link"; import { useRouter } from "next/router"; import { useQuery } from '@apollo/client'; import { GET_PARTSINDEX_CATEGORIES } from '@/lib/graphql'; import { PartsIndexCatalogsData, PartsIndexCatalogsVariables, PartsIndexCatalog } from '@/types/partsindex'; function useIsMobile(breakpoint = 767) { const [isMobile, setIsMobile] = React.useState(false); React.useEffect(() => { const check = () => setIsMobile(window.innerWidth <= breakpoint); check(); window.addEventListener("resize", check); return () => window.removeEventListener("resize", check); }, [breakpoint]); return isMobile; } // Fallback статичные данные const fallbackTabData = [ { label: "Оригинальные каталоги", heading: "Оригинальные каталоги", links: [ "Моторные масла", "Трансмиссионные масла", "Тормозные жидкости", "Смазки", "Дистиллированная вода", "Жидкости для стеклоомывателей", "Индустриальные жидкости", "Антифриз и охлаждающие жидкости", "Промывочные жидкости", ], }, { label: "Масла и технические жидкости", heading: "Масла и технические жидкости", links: [ "Моторные масла", "Трансмиссионные масла", "Тормозные жидкости", "Смазки", "Дистиллированная вода", "Жидкости для стеклоомывателей", "Индустриальные жидкости", "Антифриз и охлаждающие жидкости", "Промывочные жидкости", ], }, { label: "Оборудование", heading: "Оборудование", links: [ "Моторные масла", "Трансмиссионные масла", "Тормозные жидкости", "Смазки", "Дистиллированная вода", "Жидкости для стеклоомывателей", "Индустриальные жидкости", "Антифриз и охлаждающие жидкости", "Промывочные жидкости", ], }, ]; // Преобразуем данные PartsIndex в формат нашего меню const transformPartsIndexToTabData = (catalogs: PartsIndexCatalog[]) => { console.log('🔄 Преобразуем каталоги PartsIndex:', catalogs.length, 'элементов'); const transformed = catalogs.map(catalog => { const groupsCount = catalog.groups?.length || 0; console.log(`📝 Каталог: "${catalog.name}" (${groupsCount} групп)`); let links: string[] = []; if (catalog.groups && catalog.groups.length > 0) { // Для каждой группы проверяем есть ли подгруппы catalog.groups.forEach(group => { if (group.subgroups && group.subgroups.length > 0) { // Если есть подгруппы, добавляем их названия links.push(...group.subgroups.slice(0, 9 - links.length).map(subgroup => subgroup.name)); } else { // Если подгрупп нет, добавляем название самой группы if (links.length < 9) { links.push(group.name); } } }); } // Если подкатегорий нет, показываем название категории как указано в требованиях if (links.length === 0) { links = [catalog.name]; } console.log(`🔗 Подкатегории для "${catalog.name}":`, links); return { label: catalog.name, heading: catalog.name, links: links.slice(0, 9), // Ограничиваем максимум 9 элементов catalogId: catalog.id // Сохраняем ID каталога для навигации }; }); console.log('✅ Преобразование завершено:', transformed.length, 'табов'); return transformed; }; const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => void }) => { const isMobile = useIsMobile(); const router = useRouter(); const [mobileCategory, setMobileCategory] = useState(null); const [tabData, setTabData] = useState(fallbackTabData); const [activeTabIndex, setActiveTabIndex] = useState(0); console.log('🔄 BottomHead render:', { menuOpen, tabDataLength: tabData.length, activeTabIndex, isMobile }); // --- Overlay animation state --- const [showOverlay, setShowOverlay] = useState(false); useEffect(() => { if (menuOpen) { setShowOverlay(true); } else { // Ждём окончания transition перед удалением из DOM const timeout = setTimeout(() => setShowOverlay(false), 300); return () => clearTimeout(timeout); } }, [menuOpen]); // --- End overlay animation state --- // Получаем каталоги PartsIndex const { data: catalogsData, loading, error } = useQuery( GET_PARTSINDEX_CATEGORIES, { variables: { lang: 'ru' }, errorPolicy: 'all', onCompleted: (data) => { console.log('🎉 Apollo Query onCompleted - данные получены:', data); }, onError: (error) => { console.error('❌ Apollo Query onError:', error); } } ); // Обновляем данные табов когда получаем данные от API useEffect(() => { if (catalogsData?.partsIndexCategoriesWithGroups && catalogsData.partsIndexCategoriesWithGroups.length > 0) { console.log('✅ Обновляем меню с данными PartsIndex:', catalogsData.partsIndexCategoriesWithGroups.length, 'каталогов'); console.log('🔍 Первые 3 каталога:', catalogsData.partsIndexCategoriesWithGroups.slice(0, 3).map(catalog => ({ name: catalog.name, id: catalog.id, groupsCount: catalog.groups?.length || 0, groups: catalog.groups?.slice(0, 3).map(group => group.name) }))); const apiTabData = transformPartsIndexToTabData(catalogsData.partsIndexCategoriesWithGroups); setTabData(apiTabData); // Сбрасываем активный таб на первый при обновлении данных setActiveTabIndex(0); } else if (error) { console.warn('⚠️ Используем fallback данные из-за ошибки PartsIndex:', error); setTabData(fallbackTabData); setActiveTabIndex(0); } }, [catalogsData, error]); // Логирование для отладки useEffect(() => { if (loading) { console.log('🔄 Загружаем каталоги PartsIndex...'); } if (error) { console.error('❌ Ошибка загрузки каталогов PartsIndex:', error); } }, [loading, error]); // Обработка клика по категории для перехода в каталог с товарами const handleCategoryClick = (catalogId: string, categoryName: string, entityId?: string) => { console.log('🔍 Клик по категории:', { catalogId, categoryName, entityId }); // Закрываем меню onClose(); // Переходим на страницу каталога с параметрами PartsIndex router.push({ pathname: '/catalog', query: { partsIndexCatalog: catalogId, categoryName: encodeURIComponent(categoryName), ...(entityId && { partsIndexCategory: entityId }) } }); }; // Только мобильный UX if (isMobile && menuOpen) { // Оверлей для мобильного меню return ( <> {showOverlay && (
)} {/* Экран подкатегорий */} {mobileCategory ? (
{mobileCategory.label}
{mobileCategory.links.map((link: string, linkIndex: number) => (
{ // Ищем соответствующую подгруппу по названию let subcategoryId = `${mobileCategory.catalogId}_${linkIndex}`; if (mobileCategory.groups) { for (const group of mobileCategory.groups) { // Проверяем в подгруппах if (group.subgroups && group.subgroups.length > 0) { const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === link); if (foundSubgroup) { subcategoryId = foundSubgroup.id; break; } } // Если нет подгрупп, проверяем саму группу else if (group.name === link) { subcategoryId = group.id; break; } } } // Получаем catalogId из данных const activeCatalog = catalogsData?.partsIndexCategoriesWithGroups?.[tabData.findIndex(tab => tab === mobileCategory)]; const catalogId = activeCatalog?.id || 'fallback'; handleCategoryClick(catalogId, link, subcategoryId); }} > {link}
))}
) : ( // Экран выбора категории
Категории {loading && (загрузка...)}
{tabData.map((cat, index) => { // Получаем ID каталога из данных PartsIndex или создаем fallback ID const catalogId = catalogsData?.partsIndexCategoriesWithGroups?.[index]?.id || `fallback_${index}`; return (
{ // Добавляем catalogId и groups для правильной обработки const categoryWithData = { ...cat, catalogId, groups: catalogsData?.partsIndexCategoriesWithGroups?.[index]?.groups }; setMobileCategory(categoryWithData); }} style={{ cursor: "pointer" }} > {cat.label}
); })}
)} ); } // Десктоп: оставить всё как есть, но добавить оверлей return ( <> {showOverlay && (
)} {showOverlay && (
)} ); }; export default BottomHead;