import React, { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import { useQuery } from '@apollo/client'; import Head from 'next/head'; import Footer from '@/components/Footer'; import Layout from '@/components/Layout'; import VehiclePartsSearchSection from '@/components/VehiclePartsSearchSection'; import LaximoDiagnostic from '@/components/LaximoDiagnostic'; import { GET_LAXIMO_VEHICLE_INFO, GET_LAXIMO_CATALOG_INFO, GET_LAXIMO_UNIT_DETAILS } from '@/lib/graphql'; import { LaximoCatalogInfo } from '@/types/laximo'; import InfoVin from '@/components/vin/InfoVin'; import VinLeftbar from '@/components/vin/VinLeftbar'; import VinKnot from '@/components/vin/VinKnot'; import VinCategory from '@/components/vin/VinCategory'; import PartDetailCard from '@/components/PartDetailCard'; import VinPartCard from '@/components/vin/VinPartCard'; import KnotIn from '@/components/vin/KnotIn'; import KnotParts from '@/components/vin/KnotParts'; import VinQuick from '@/components/vin/VinQuick'; import CatalogSubscribe from '@/components/CatalogSubscribe'; import MobileMenuBottomSection from '@/components/MobileMenuBottomSection'; interface LaximoVehicleInfo { vehicleid: string; name: string; ssd: string; brand: string; catalog: string; attributes: Array<{ key: string; name: string; value: string; }>; } const VehicleDetailsPage = () => { const router = useRouter(); const { brand, vehicleId, oemNumber, searchType: searchTypeParam } = router.query; // Устанавливаем тип поиска из URL или по умолчанию // Важно: согласно документации Laximo, для групп быстрого поиска используется ListQuickGroup // Если в URL передан searchType=categories, мы интерпретируем это как запрос на quickgroups let defaultSearchType: 'quickgroups' | 'categories' | 'fulltext' = 'quickgroups'; if (searchTypeParam === 'categories') { // В URL categories, но мы используем quickgroups для групп быстрого поиска defaultSearchType = 'quickgroups'; } else if (searchTypeParam === 'quickgroups') { defaultSearchType = 'quickgroups'; } else if (searchTypeParam === 'fulltext') { defaultSearchType = 'fulltext'; } // ====== ВСЕ ХУКИ В НАЧАЛЕ КОМПОНЕНТА ====== const [searchType, setSearchType] = useState<'quickgroups' | 'categories' | 'fulltext'>(defaultSearchType); const [showKnot, setShowKnot] = useState(false); const [foundParts, setFoundParts] = useState([]); const [activeTab, setActiveTab] = useState<'uzly' | 'manufacturer'>('uzly'); const [openedPath, setOpenedPath] = useState([]); const [searchState, setSearchState] = useState<{ loading: boolean; error: any; query: string; isSearching: boolean; }>({ loading: false, error: null, query: '', isSearching: false }); const [selectedNode, setSelectedNode] = useState(null); const [selectedQuickGroup, setSelectedQuickGroup] = useState(null); const handleCategoryClick = (e?: React.MouseEvent) => { if (e) e.preventDefault(); setShowKnot(true); }; useEffect(() => { const handler = (e: Event) => { const target = e.target as HTMLElement; if (target.classList.contains('link-2')) { e.preventDefault(); setShowKnot(true); } }; document.addEventListener('click', handler); return () => document.removeEventListener('click', handler); }, []); // ====== КОНЕЦ ХУКОВ ====== // Получаем информацию о каталоге const { data: catalogData } = useQuery<{ laximoCatalogInfo: LaximoCatalogInfo }>( GET_LAXIMO_CATALOG_INFO, { variables: { catalogCode: brand }, skip: !brand } ); // Получаем информацию о выбранном автомобиле const ssdFromQuery = Array.isArray(router.query.ssd) ? router.query.ssd[0] : router.query.ssd; const useStorage = router.query.use_storage === '1'; const ssdLengthFromUrl = router.query.ssd_length ? parseInt(router.query.ssd_length as string) : 0; // Если указано use_storage, пытаемся получить SSD из localStorage let finalSsd = ''; if (useStorage && typeof window !== 'undefined') { const vehicleKey = `vehicle_ssd_${brand}_${vehicleId}`; const storedSsd = localStorage.getItem(vehicleKey); if (storedSsd) { finalSsd = storedSsd; // НЕ ОЧИЩАЕМ SSD сразу, оставляем на случай перезагрузки страницы // localStorage.removeItem(vehicleKey); } } else if (ssdFromQuery && ssdFromQuery.trim() !== '') { finalSsd = ssdFromQuery; } const { data: vehicleData, loading: vehicleLoading, error: vehicleError } = useQuery<{ laximoVehicleInfo: LaximoVehicleInfo }>( GET_LAXIMO_VEHICLE_INFO, { variables: { catalogCode: brand, vehicleId: vehicleId, ...(finalSsd && { ssd: finalSsd }), localized: true }, skip: !brand || vehicleId === undefined || vehicleId === null, errorPolicy: 'all', onCompleted: (data) => { console.log('🔍 VehicleInfo GraphQL completed:', { requestedVehicleId: vehicleId, returnedVehicleId: data?.laximoVehicleInfo?.vehicleid, vehicleName: data?.laximoVehicleInfo?.name, ssdUsed: finalSsd?.substring(0, 50) + '...', fullData: data }); if (data?.laximoVehicleInfo?.vehicleid !== vehicleId) { console.log('🚨 ОБНАРУЖЕНО НЕСООТВЕТСТВИЕ VEHICLE ID!'); console.log(`📍 URL vehicleId: ${vehicleId}`); console.log(`📍 API vehicleId: ${data?.laximoVehicleInfo?.vehicleid}`); } else { console.log('✅ Vehicle ID соответствует URL'); } }, onError: (error) => { console.error('❌ VehicleInfo GraphQL error:', error); } } ); // Автоматическое перенаправление на правильный vehicleId если API вернул другой ID useEffect(() => { if (vehicleData?.laximoVehicleInfo && vehicleData.laximoVehicleInfo.vehicleid !== vehicleId) { const correctVehicleId = vehicleData.laximoVehicleInfo.vehicleid; console.log(`🔄 Автоматическое перенаправление: ${vehicleId} -> ${correctVehicleId}`); // Обновляем localStorage с правильным ключом if (finalSsd && typeof window !== 'undefined') { const oldKey = `vehicle_ssd_${brand}_${vehicleId}`; const newKey = `vehicle_ssd_${brand}_${correctVehicleId}`; // Перемещаем SSD на правильный ключ localStorage.setItem(newKey, finalSsd); localStorage.removeItem(oldKey); console.log(`💾 SSD перемещен: ${oldKey} -> ${newKey}`); } // Строим новый URL с правильным vehicleId const currentParams = new URLSearchParams(window.location.search); const newUrl = `/vehicle-search/${brand}/${correctVehicleId}?${currentParams.toString()}`; // Перенаправляем на правильный URL router.replace(newUrl); return; } }, [vehicleData, vehicleId, brand, finalSsd, router]); // Получаем детали выбранного узла, если он выбран const { data: unitDetailsData, loading: unitDetailsLoading, error: unitDetailsError } = useQuery( GET_LAXIMO_UNIT_DETAILS, { variables: selectedNode ? { catalogCode: selectedNode.catalogCode || selectedNode.catalog || brand, vehicleId: selectedNode.vehicleId || vehicleId, unitId: selectedNode.unitid || selectedNode.unitId, ssd: selectedNode.ssd || finalSsd || '', } : { catalogCode: '', vehicleId: '', unitId: '', ssd: '' }, skip: !selectedNode, errorPolicy: 'all', } ); const unitDetails = unitDetailsData?.laximoUnitDetails || []; // Логируем ошибки if (vehicleError) { console.error('Vehicle GraphQL error:', vehicleError); } if (vehicleLoading) { return ( <> Загрузка автомобиля...

Загружаем информацию об автомобиле...

); } // Если информация о каталоге недоступна, показываем ошибку if (!catalogData?.laximoCatalogInfo) { return ( <> Каталог не найден

Каталог не найден

Информация о каталоге недоступна

); } // Если vehicleId отсутствует или пустой, показываем предупреждение // Важно: vehicleId может быть '0' для некоторых автомобилей, найденных по VIN if (!vehicleId || vehicleId === '') { return (

Автомобиль не выбран

Для поиска по деталям необходимо выбрать конкретный автомобиль через VIN или мастер подбора.

); } // Гарантируем, что vehicleId — строка const vehicleIdStr = Array.isArray(vehicleId) ? (vehicleId[0] || '') : (vehicleId || ''); // Для Laximo API vehicleId может быть '0' для автомобилей, найденных по VIN const fallbackVehicleId = vehicleIdStr; let vehicleInfo = vehicleData?.laximoVehicleInfo || { vehicleid: fallbackVehicleId, name: `Автомобиль ${catalogData.laximoCatalogInfo.name}`, ssd: finalSsd, brand: catalogData.laximoCatalogInfo.brand, catalog: catalogData.laximoCatalogInfo.code, attributes: [] as never[] }; // Убеждаемся, что vehicleid соответствует параметру из URL if (vehicleInfo.vehicleid !== fallbackVehicleId && fallbackVehicleId) { vehicleInfo = { ...vehicleInfo, vehicleid: fallbackVehicleId }; } // Если нет данных автомобиля и есть ошибка, показываем предупреждение const hasError = vehicleError && !vehicleData?.laximoVehicleInfo; const catalogInfo = catalogData.laximoCatalogInfo; return ( <> VIN {/* ====== ВРЕМЕННЫЙ МАКЕТ ДЛЯ ВЕРСТКИ (начало) ====== */} 0 ? vehicleInfo.attributes.map(attr => attr.value).join(' · ') : '' } vehicleAttributes={vehicleInfo.attributes || []} />
{!selectedNode ? (
{vehicleInfo && vehicleInfo.catalog && vehicleInfo.vehicleid && vehicleInfo.ssd && ( <> { setFoundParts(results); setSearchState({ loading, error, query, isSearching: isSearching || false }); }} onNodeSelect={setSelectedNode} onActiveTabChange={(tab) => setActiveTab(tab)} onQuickGroupSelect={setSelectedQuickGroup} activeTab={activeTab} openedPath={openedPath} setOpenedPath={setOpenedPath} /> {searchState.isSearching ? (
{searchState.loading ? (

Выполняется поиск...

) : searchState.error ? (

Ошибка поиска

{searchState.error.message}

) : foundParts.length > 0 ? ( foundParts.map((detail, idx) => ( )) ) : (

По запросу "{searchState.query}" ничего не найдено

Попробуйте изменить поисковый запрос

)}
) : showKnot ? ( ) : selectedQuickGroup ? ( setSelectedQuickGroup(null)} onNodeSelect={setSelectedNode} /> ) : ( )} )}
) : (
{/* */} {unitDetailsLoading ? (
Загружаем детали узла...
) : unitDetailsError ? (
Ошибка загрузки деталей: {unitDetailsError.message}
) : unitDetails.length > 0 ? ( ) : (
Детали не найдены
)}
)}