From 1f1ea8baaf85e18b802332b442a199d58d464637 Mon Sep 17 00:00:00 2001 From: egortriston Date: Mon, 30 Jun 2025 17:28:15 +0300 Subject: [PATCH] =?UTF-8?q?=D1=83=D1=80=D0=B0=20=D0=B5=D0=BF=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/vin/VinCategory.tsx | 183 ++++++++++++------ src/components/vin/VinLeftbar.tsx | 32 +-- src/components/vin/VinQuick.tsx | 101 ++++++++++ .../vehicle-search/[brand]/[vehicleId].tsx | 42 +++- 4 files changed, 273 insertions(+), 85 deletions(-) create mode 100644 src/components/vin/VinQuick.tsx diff --git a/src/components/vin/VinCategory.tsx b/src/components/vin/VinCategory.tsx index e5a4d87..e2f4e37 100644 --- a/src/components/vin/VinCategory.tsx +++ b/src/components/vin/VinCategory.tsx @@ -1,83 +1,138 @@ -import React, { useState, useRef } from "react"; -import { useQuery, useLazyQuery } from "@apollo/client"; -import { GET_LAXIMO_CATEGORIES, GET_LAXIMO_UNITS } from "@/lib/graphql/laximo"; +import React, { useState, useEffect, useRef } from 'react'; +import { useQuery, useLazyQuery } from '@apollo/client'; +import { GET_LAXIMO_CATEGORIES, GET_LAXIMO_QUICK_GROUPS, GET_LAXIMO_UNITS } from '@/lib/graphql/laximo'; interface VinCategoryProps { catalogCode: string; vehicleId: string; - ssd?: string; + ssd: string; onNodeSelect?: (node: any) => void; + activeTab: 'uzly' | 'manufacturer'; + onQuickGroupSelect?: (group: any) => void; } -const VinCategory: React.FC = ({ catalogCode, vehicleId, ssd, onNodeSelect }) => { - 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 VinCategory: React.FC = ({ catalogCode, vehicleId, ssd, onNodeSelect, activeTab, onQuickGroupSelect }) => { + const [selectedCategory, setSelectedCategory] = useState(null); 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 [selectedCategory, setSelectedCategory] = useState(null); const lastCategoryIdRef = useRef(null); - // Если выбрана категория — показываем подкатегории (children или units) - let subcategories: any[] = []; - if (selectedCategory) { - if (selectedCategory.children && selectedCategory.children.length > 0) { - subcategories = selectedCategory.children; - } else { - subcategories = unitsByCategory[selectedCategory.quickgroupid] || []; - } - } + // Сброс выбранной категории при смене вкладки + useEffect(() => { + setSelectedCategory(null); + }, [activeTab]); - const handleCategoryClick = (cat: any) => { - if (cat.children && cat.children.length > 0) { - setSelectedCategory(cat); - } else { - // Если нет children, грузим units (подкатегории) - if (!unitsByCategory[cat.quickgroupid]) { - lastCategoryIdRef.current = cat.quickgroupid; - getUnits({ variables: { catalogCode, vehicleId, ssd, categoryId: cat.quickgroupid } }); + // Запрос для "Узлы" + const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, { + variables: { catalogCode, vehicleId, ssd }, + skip: !catalogCode || vehicleId === undefined || vehicleId === null || activeTab !== 'uzly', + errorPolicy: 'all' + }); + + // Запрос для получения units (подкатегорий) в режиме "Узлы" + const [getUnits] = useLazyQuery(GET_LAXIMO_UNITS, { + onCompleted: (data) => { + console.log('Units loaded:', data); + if (data && data.laximoUnits && lastCategoryIdRef.current) { + console.log('Setting units for category:', lastCategoryIdRef.current, data.laximoUnits); + setUnitsByCategory(prev => ({ + ...prev, + [lastCategoryIdRef.current!]: data.laximoUnits || [] + })); } - setSelectedCategory(cat); + }, + onError: (error) => { + console.error('Error loading units:', error); } - }; + }); + + // Запрос для "От производителя" + const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, { + variables: { catalogCode, vehicleId, ssd }, + skip: !catalogCode || vehicleId === undefined || vehicleId === null || activeTab !== 'manufacturer', + errorPolicy: 'all' + }); + + const categories = activeTab === 'uzly' ? (categoriesData?.laximoCategories || []) : (quickGroupsData?.laximoQuickGroups || []); + const loading = activeTab === 'uzly' ? categoriesLoading : quickGroupsLoading; + const error = activeTab === 'uzly' ? categoriesError : quickGroupsError; const handleBack = () => { setSelectedCategory(null); }; - const handleSubcategoryClick = (subcat: any) => { - if (onNodeSelect) { - onNodeSelect({ - ...subcat, - unitid: subcat.unitid || subcat.quickgroupid || subcat.id, - }); + const handleCategoryClick = (category: any) => { + if (activeTab === 'manufacturer') { + if (category.children && category.children.length > 0) { + setSelectedCategory(category); + } else if (category.link && onQuickGroupSelect) { + onQuickGroupSelect(category); + } else if (onNodeSelect) { + onNodeSelect(category); + } + } else { + // Логика для вкладки "Узлы" + if (category.children && category.children.length > 0) { + setSelectedCategory(category); + } else { + // Если нет children, грузим units (подкатегории) + const categoryId = category.categoryid || category.quickgroupid || category.id; + if (!unitsByCategory[categoryId]) { + lastCategoryIdRef.current = categoryId; + console.log('Loading units for category:', { categoryId, category }); + getUnits({ + variables: { + catalogCode, + vehicleId, + ssd, + categoryId + } + }); + } + setSelectedCategory(category); + } } }; - if (categoriesLoading) return
Загрузка категорий...
; - if (categoriesError) return
Ошибка: {categoriesError.message}
; + const handleSubcategoryClick = (subcat: any) => { + if (activeTab === 'uzly' && onNodeSelect) { + // Для режима "Узлы" при клике на подкатегорию открываем KnotIn + onNodeSelect({ + ...subcat, + unitid: subcat.unitid || subcat.categoryid || subcat.quickgroupid || subcat.id + }); + } else { + handleCategoryClick(subcat); + } + }; + + if (loading) return
Загрузка категорий...
; + if (error) return
Ошибка: {error.message}
; + + // Определяем, какие подкатегории показывать + let subcategories: any[] = []; + if (selectedCategory) { + if (activeTab === 'manufacturer') { + // Для вкладки "От производителя" используем children + subcategories = selectedCategory.children || []; + } else { + // Для вкладки "Узлы" используем либо children, либо units + if (selectedCategory.children && selectedCategory.children.length > 0) { + subcategories = selectedCategory.children; + } else { + const categoryId = selectedCategory.categoryid || selectedCategory.quickgroupid || selectedCategory.id; + subcategories = unitsByCategory[categoryId] || []; + } + } + } return ( -
+
{!selectedCategory ? ( // Список категорий categories.map((cat: any, idx: number) => (
handleCategoryClick(cat)} style={{ cursor: "pointer" }} > @@ -91,7 +146,7 @@ const VinCategory: React.FC = ({ catalogCode, vehicleId, ssd,
)) ) : ( - // Список подкатегорий (children или units) + // Список подкатегорий <>
← Назад
@@ -106,23 +161,23 @@ const VinCategory: React.FC = ({ catalogCode, vehicleId, ssd, {subcategories.map((subcat: any, idx: number) => (
handleSubcategoryClick(subcat)} style={{ cursor: "pointer" }} >
{subcat.name}
-
- - - - -
-
- ))} +
+ + + + +
+
+ ))} )} -
-); +
+ ); }; export default VinCategory; \ No newline at end of file diff --git a/src/components/vin/VinLeftbar.tsx b/src/components/vin/VinLeftbar.tsx index 9bd39dd..9429b1e 100644 --- a/src/components/vin/VinLeftbar.tsx +++ b/src/components/vin/VinLeftbar.tsx @@ -18,6 +18,8 @@ interface VinLeftbarProps { isSearching?: boolean; }) => void; onNodeSelect?: (node: any) => void; + onActiveTabChange?: (tab: 'uzly' | 'manufacturer') => void; + onQuickGroupSelect?: (group: any) => void; } interface QuickGroup { @@ -27,7 +29,7 @@ interface QuickGroup { children?: QuickGroup[]; } -const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, onNodeSelect }) => { +const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, onNodeSelect, onActiveTabChange, onQuickGroupSelect }) => { const catalogCode = vehicleInfo.catalog; const vehicleId = vehicleInfo.vehicleid; const ssd = vehicleInfo.ssd; @@ -252,6 +254,12 @@ const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, o const fulltextResults = fulltextData?.laximoFulltextSearch?.details || []; + useEffect(() => { + if (onActiveTabChange) { + onActiveTabChange(activeTab); + } + }, [activeTab, onActiveTabChange]); + return (
{/* === Форма полнотекстового поиска === */} @@ -358,11 +366,11 @@ const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, o data-delay="0" className={`dropdown-4 w-dropdown${isOpen ? " w--open" : ""}`} > -
handleToggle(idx, category.quickgroupid)} - style={{ cursor: "pointer" }} - > +
handleToggle(idx, category.quickgroupid)} + style={{ cursor: "pointer" }} + >
{category.name}
@@ -415,8 +423,8 @@ const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, o className="dropdown-link-3 w-dropdown-link" onClick={(e) => { e.preventDefault(); - if (group.link) { - handleQuickGroupClick(group); + if (group.link && onQuickGroupSelect) { + onQuickGroupSelect(group); } }} > @@ -453,8 +461,8 @@ const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, o className="dropdown-link-3 w-dropdown-link " onClick={(e) => { e.preventDefault(); - if (child.link) { - handleQuickGroupClick(child); + if (child.link && onQuickGroupSelect) { + onQuickGroupSelect(child); } }} > @@ -486,8 +494,8 @@ const VinLeftbar: React.FC = ({ vehicleInfo, onSearchResults, o className="dropdown-link-3 w-dropdown-link " onClick={(e) => { e.preventDefault(); - if (subChild.link) { - handleQuickGroupClick(subChild); + if (subChild.link && onQuickGroupSelect) { + onQuickGroupSelect(subChild); } }} > diff --git a/src/components/vin/VinQuick.tsx b/src/components/vin/VinQuick.tsx new file mode 100644 index 0000000..d92c377 --- /dev/null +++ b/src/components/vin/VinQuick.tsx @@ -0,0 +1,101 @@ +import React, { useState } from 'react'; +import { useQuery } from '@apollo/client'; +import { GET_LAXIMO_QUICK_DETAIL } from '@/lib/graphql/laximo'; +import BrandSelectionModal from '../BrandSelectionModal'; + +interface VinQuickProps { + quickGroup: any; + catalogCode: string; + vehicleId: string; + ssd: string; + onBack: () => void; + onNodeSelect: (unit: any) => void; +} + +const VinQuick: React.FC = ({ quickGroup, catalogCode, vehicleId, ssd, onBack, onNodeSelect }) => { + const { data, loading, error } = useQuery(GET_LAXIMO_QUICK_DETAIL, { + variables: { + catalogCode, + vehicleId, + quickGroupId: quickGroup.quickgroupid, + ssd + }, + skip: !quickGroup || !quickGroup.quickgroupid + }); + const quickDetail = data?.laximoQuickDetail; + + const [isBrandModalOpen, setIsBrandModalOpen] = useState(false); + const [selectedDetail, setSelectedDetail] = useState(null); + + const handleUnitClick = (unit: any) => { + onNodeSelect({ + ...unit, + unitid: unit.unitid, + name: unit.name, + catalogCode, + vehicleId, + ssd + }); + }; + const handleDetailClick = (detail: any) => { + setSelectedDetail(detail); + setIsBrandModalOpen(true); + }; + const handleCloseBrandModal = () => { + setIsBrandModalOpen(false); + setSelectedDetail(null); + }; + + return ( +
+ {/* */} + {loading ? ( +
Загружаем детали...
+ ) : error ? ( +
Ошибка загрузки деталей: {error.message}
+ ) : quickDetail && quickDetail.units ? ( + quickDetail.units.map((unit: any) => ( +
+
+ {unit.imageurl || unit.largeimageurl ? ( + {unit.name} { (e.currentTarget as HTMLImageElement).src = '/images/image-44.jpg'; }} + /> + ) : ( + Нет изображения + )} +
+
+

{unit.name}

+ + {unit.details && unit.details.length > 0 && unit.details.map((detail: any) => ( + + ))} + + { e.preventDefault(); handleUnitClick(unit); }}>Подробнее +
+
+ )) + ) : ( +
Нет деталей для этой группы
+ )} + {isBrandModalOpen && selectedDetail && ( + + )} +
+ ); +}; + +export default VinQuick; \ No newline at end of file diff --git a/src/pages/vehicle-search/[brand]/[vehicleId].tsx b/src/pages/vehicle-search/[brand]/[vehicleId].tsx index 3c6bbf5..82024ae 100644 --- a/src/pages/vehicle-search/[brand]/[vehicleId].tsx +++ b/src/pages/vehicle-search/[brand]/[vehicleId].tsx @@ -15,7 +15,11 @@ 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 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; @@ -53,6 +57,7 @@ const VehicleDetailsPage = () => { 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 [searchState, setSearchState] = useState<{ loading: boolean; error: any; @@ -65,6 +70,7 @@ const VehicleDetailsPage = () => { isSearching: false }); const [selectedNode, setSelectedNode] = useState(null); + const [selectedQuickGroup, setSelectedQuickGroup] = useState(null); const handleCategoryClick = (e?: React.MouseEvent) => { if (e) e.preventDefault(); setShowKnot(true); @@ -291,6 +297,8 @@ const VehicleDetailsPage = () => { setSearchState({ loading, error, query, isSearching: isSearching || false }); }} onNodeSelect={setSelectedNode} + onActiveTabChange={(tab) => setActiveTab(tab)} + onQuickGroupSelect={setSelectedQuickGroup} /> {searchState.isSearching ? (
@@ -342,12 +350,23 @@ const VehicleDetailsPage = () => {
) : showKnot ? ( + ) : selectedQuickGroup ? ( + setSelectedQuickGroup(null)} + onNodeSelect={setSelectedNode} + /> ) : ( )} @@ -378,10 +397,15 @@ const VehicleDetailsPage = () => {
)}
+
+ +
+