import React, { useState, useEffect } from "react"; import { useLazyQuery, useQuery } from '@apollo/client'; import { GET_LAXIMO_FULLTEXT_SEARCH, GET_LAXIMO_CATEGORIES, GET_LAXIMO_UNITS, GET_LAXIMO_QUICK_GROUPS, GET_LAXIMO_QUICK_DETAIL } from '@/lib/graphql/laximo'; import { useRouter } from 'next/router'; interface VinLeftbarProps { vehicleInfo?: { catalog: string; vehicleid: string; ssd: string; [key: string]: any; }; onSearchResults?: (data: { results: any[]; loading: boolean; error: any; query: string; isSearching?: boolean; }) => void; onNodeSelect?: (node: any) => void; onActiveTabChange?: (tab: 'uzly' | 'manufacturer') => void; onQuickGroupSelect?: (group: any) => void; activeTab?: 'uzly' | 'manufacturer'; openedPath?: string[]; setOpenedPath?: (path: string[]) => void; } interface QuickGroup { quickgroupid: string; name: string; link?: boolean; children?: QuickGroup[]; } const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, onNodeSelect, onActiveTabChange, onQuickGroupSelect, activeTab: activeTabProp, openedPath = [], setOpenedPath = () => {} }) => { const router = useRouter(); const catalogCode = vehicleInfo?.catalog || ''; const vehicleId = vehicleInfo?.vehicleid || ''; const ssd = vehicleInfo?.ssd || ''; const [searchQuery, setSearchQuery] = useState(''); const [executeSearch, { data, loading, error }] = useLazyQuery(GET_LAXIMO_FULLTEXT_SEARCH, { errorPolicy: 'all' }); const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, { variables: { catalogCode, vehicleId, ssd }, skip: !catalogCode || vehicleId === undefined || vehicleId === null, errorPolicy: 'all' }); const categories = categoriesData?.laximoCategories || []; const [unitsByCategory, setUnitsByCategory] = useState<{ [key: string]: any[] }>({}); const [getUnits] = useLazyQuery(GET_LAXIMO_UNITS, { onCompleted: (data) => { if (data && data.laximoUnits && lastCategoryIdRef.current) { setUnitsByCategory(prev => ({ ...prev, [lastCategoryIdRef.current!]: data.laximoUnits || [] })); } } }); const lastCategoryIdRef = React.useRef(null); // --- Синхронизация openedPath с URL --- // Обновляем openedPath и URL const setOpenedPathAndUrl = (newPath: string[]) => { setOpenedPath(newPath); const params = new URLSearchParams(router.query as any); if (newPath.length > 0) { params.set('catpath', newPath.join(',')); } else { params.delete('catpath'); } router.push( { pathname: router.pathname, query: { ...router.query, catpath: newPath.join(',') } }, undefined, { shallow: true } ); }; // Восстанавливаем openedPath из URL React.useEffect(() => { if (typeof window === 'undefined') return; const catpath = (router.query.catpath as string) || ''; if (catpath) { setOpenedPath(catpath.split(',').filter(Boolean)); } else { setOpenedPath([]); } }, [router.query.catpath]); const handleToggle = (categoryId: string, level: number) => { if (openedPath[level] === categoryId) { setOpenedPathAndUrl(openedPath.slice(0, level)); } else { setOpenedPathAndUrl([...openedPath.slice(0, level), categoryId]); // Загружаем units для категории, если они еще не загружены if (activeTabProp === 'manufacturer' && !unitsByCategory[categoryId]) { lastCategoryIdRef.current = categoryId; getUnits({ variables: { catalogCode, vehicleId, ssd, categoryId } }); } } }; const handleSearch = () => { if (!searchQuery.trim()) return; if (!ssd || ssd.trim() === '') { console.error('SSD обязателен для поиска по названию'); return; } executeSearch({ variables: { catalogCode, vehicleId, searchQuery: searchQuery.trim(), ssd } }); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); handleSearch(); } }; const searchResults = data?.laximoFulltextSearch; useEffect(() => { if (onSearchResults) { onSearchResults({ results: searchResults?.details || [], loading: loading, error: error, query: searchQuery }); } }, [searchResults, loading, error, searchQuery]); // --- Новый блок: вычисляем доступность поиска --- const isSearchAvailable = !!catalogCode && vehicleId !== undefined && vehicleId !== null && !!ssd && ssd.trim() !== ''; const showWarning = !isSearchAvailable; const showError = !!error && isSearchAvailable && searchQuery.trim(); const showNotFound = isSearchAvailable && searchQuery.trim() && !loading && data && searchResults && searchResults.details && searchResults.details.length === 0; const showTips = isSearchAvailable && !searchQuery.trim() && !loading; // --- QuickGroups (от производителя) --- const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, { variables: { catalogCode, vehicleId, ssd }, skip: !catalogCode || vehicleId === undefined || vehicleId === null, errorPolicy: 'all' }); const quickGroups = quickGroupsData?.laximoQuickGroups || []; const handleQuickGroupToggle = (groupId: string, level: number) => { if (openedPath[level] === groupId) { setOpenedPathAndUrl(openedPath.slice(0, level)); } else { setOpenedPathAndUrl([...openedPath.slice(0, level), groupId]); } }; // === Полнотекстовый поиск деталей (аналогично FulltextSearchSection) === const [fulltextQuery, setFulltextQuery] = useState(''); const [executeFulltextSearch, { data: fulltextData, loading: fulltextLoading, error: fulltextError }] = useLazyQuery(GET_LAXIMO_FULLTEXT_SEARCH, { errorPolicy: 'all' }); const handleFulltextSearch = () => { if (!fulltextQuery.trim()) { if (onSearchResults) { onSearchResults({ results: [], loading: false, error: null, query: '', isSearching: false }); } return; } if (!ssd || ssd.trim() === '') { console.error('SSD обязателен для поиска по названию'); return; } // Отправляем начальное состояние поиска родителю if (onSearchResults) { onSearchResults({ results: [], loading: true, error: null, query: fulltextQuery.trim(), isSearching: true }); } executeFulltextSearch({ variables: { catalogCode, vehicleId, searchQuery: fulltextQuery.trim(), ssd } }); }; const handleInputChange = (e: React.ChangeEvent) => { const newValue = e.target.value; setFulltextQuery(newValue); }; useEffect(() => { if (onSearchResults && (fulltextData || fulltextLoading || fulltextError)) { onSearchResults({ results: fulltextData?.laximoFulltextSearch?.details || [], loading: fulltextLoading, error: fulltextError, query: fulltextQuery, isSearching: true }); } }, [fulltextData, fulltextLoading, fulltextError, fulltextQuery]); const handleFulltextKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); handleFulltextSearch(); } }; const fulltextResults = fulltextData?.laximoFulltextSearch?.details || []; // Если нет данных о транспортном средстве, показываем заглушку if (!vehicleInfo) { return (
Поиск запчастей
Выберите автомобиль для поиска запчастей
); } return (
{/* === Форма полнотекстового поиска === */}
{(!ssd || ssd.trim() === '') && (

Полнотекстовый поиск недоступен

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

)}
{/* Tab content start */} {activeTabProp === 'uzly' ? ( // Общие (QuickGroups - бывшие "От производителя") quickGroupsLoading ? (
Загружаем группы быстрого поиска...
) : quickGroupsError ? (
Ошибка загрузки групп: {quickGroupsError.message}
) : ( <> {(quickGroups as QuickGroup[]).map((group: QuickGroup) => { const hasChildren = group.children && group.children.length > 0; const isOpen = openedPath.includes(group.quickgroupid); if (!hasChildren) { return ( { e.preventDefault(); // Если это конечная группа с link=true, открываем QuickGroup if (group.link && onQuickGroupSelect) { onQuickGroupSelect(group); } else { handleQuickGroupToggle(group.quickgroupid, 0); } }} > {group.name} ); } return (
{ e.preventDefault(); handleQuickGroupToggle(group.quickgroupid, 0); }} style={{ cursor: "pointer" }} >
{group.name}
); })} ) ) : ( // От производителя (Categories - узлы) categoriesLoading ? (
Загружаем категории...
) : categoriesError ? (
Ошибка загрузки категорий: {categoriesError.message}
) : ( <> {categories.map((category: any, idx: number) => { const isOpen = openedPath.includes(category.quickgroupid); const subcategories = category.children && category.children.length > 0 ? category.children : unitsByCategory[category.quickgroupid] || []; return (
{ e.preventDefault(); handleToggle(category.quickgroupid, 0); }} style={{ cursor: "pointer" }} >
{category.name}
); })} ) )} {/* Tab content end */}
); }; export default VinLeftbar;