Обновлены компоненты для улучшения обработки групп быстрого поиска и деталей узлов. Внесены изменения в логику отображения подкатегорий в VinCategory и VinLeftbar, добавлены комментарии для ясности. Исправлены условия пропуска запросов и обновлены типы для поддержки SSD узлов.
This commit is contained in:
@ -25,9 +25,17 @@ const QuickGroupItem: React.FC<QuickGroupItemProps> = ({ group, level, onGroupCl
|
|||||||
|
|
||||||
const handleGroupClick = () => {
|
const handleGroupClick = () => {
|
||||||
if (canShowDetails) {
|
if (canShowDetails) {
|
||||||
|
// Если это конечная группа с поиском деталей - переходим к просмотру деталей
|
||||||
onGroupClick(group);
|
onGroupClick(group);
|
||||||
} else if (hasChildren) {
|
} else if (hasChildren) {
|
||||||
|
// Если это родительская группа с подгруппами
|
||||||
|
if (group.children?.some(child => child.link)) {
|
||||||
|
// Есть подгруппы с активным поиском - показываем пользователю выбор
|
||||||
|
setIsExpanded(!isExpanded);
|
||||||
|
} else {
|
||||||
|
// Все подгруппы неактивны - просто разворачиваем
|
||||||
setIsExpanded(!isExpanded);
|
setIsExpanded(!isExpanded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,6 +77,11 @@ const QuickGroupItem: React.FC<QuickGroupItemProps> = ({ group, level, onGroupCl
|
|||||||
Доступен поиск
|
Доступен поиск
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
{hasChildren && !canShowDetails && (
|
||||||
|
<span className="ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800">
|
||||||
|
{group.children?.filter(child => child.link).length || 0} подгрупп
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -143,8 +156,10 @@ const QuickDetailSection: React.FC<QuickDetailSectionProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleUnitClick = (unit: LaximoUnit) => {
|
const handleUnitClick = (unit: LaximoUnit) => {
|
||||||
console.log('🔍 Выбран узел для детального просмотра:', unit.name, 'ID:', unit.unitid);
|
setSelectedUnit({
|
||||||
setSelectedUnit(unit);
|
...unit,
|
||||||
|
ssd: unit.ssd || ssd // Сохраняем правильный SSD в selectedUnit
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBackFromUnit = () => {
|
const handleBackFromUnit = () => {
|
||||||
@ -198,7 +213,7 @@ const QuickDetailSection: React.FC<QuickDetailSectionProps> = ({
|
|||||||
<UnitDetailsSection
|
<UnitDetailsSection
|
||||||
catalogCode={catalogCode}
|
catalogCode={catalogCode}
|
||||||
vehicleId={vehicleId}
|
vehicleId={vehicleId}
|
||||||
ssd={ssd}
|
ssd={selectedUnit.ssd || ssd} // Используем SSD узла
|
||||||
unitId={selectedUnit.unitid}
|
unitId={selectedUnit.unitid}
|
||||||
unitName={selectedUnit.name}
|
unitName={selectedUnit.name}
|
||||||
onBack={handleBackFromUnit}
|
onBack={handleBackFromUnit}
|
||||||
|
@ -22,19 +22,24 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
setSelectedCategory(null);
|
setSelectedCategory(null);
|
||||||
}, [activeTab]);
|
}, [activeTab]);
|
||||||
|
|
||||||
// Запрос для "Узлы"
|
// Запрос для "Общие" (QuickGroups)
|
||||||
const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, {
|
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
||||||
variables: { catalogCode: catalogCode || '', vehicleId: vehicleId || '', ssd: ssd || '' },
|
variables: { catalogCode: catalogCode || '', vehicleId: vehicleId || '', ssd: ssd || '' },
|
||||||
skip: !catalogCode || !vehicleId || activeTab !== 'uzly',
|
skip: !catalogCode || !vehicleId || activeTab !== 'uzly',
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Запрос для получения units (подкатегорий) в режиме "Узлы"
|
// Запрос для "От производителя" (Categories)
|
||||||
|
const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, {
|
||||||
|
variables: { catalogCode: catalogCode || '', vehicleId: vehicleId || '', ssd: ssd || '' },
|
||||||
|
skip: !catalogCode || !vehicleId || activeTab !== 'manufacturer',
|
||||||
|
errorPolicy: 'all'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Запрос для получения units (подкатегорий) в режиме "От производителя"
|
||||||
const [getUnits] = useLazyQuery(GET_LAXIMO_UNITS, {
|
const [getUnits] = useLazyQuery(GET_LAXIMO_UNITS, {
|
||||||
onCompleted: (data) => {
|
onCompleted: (data) => {
|
||||||
console.log('Units loaded:', data);
|
|
||||||
if (data && data.laximoUnits && lastCategoryIdRef.current) {
|
if (data && data.laximoUnits && lastCategoryIdRef.current) {
|
||||||
console.log('Setting units for category:', lastCategoryIdRef.current, data.laximoUnits);
|
|
||||||
setUnitsByCategory(prev => ({
|
setUnitsByCategory(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
[lastCategoryIdRef.current!]: data.laximoUnits || []
|
[lastCategoryIdRef.current!]: data.laximoUnits || []
|
||||||
@ -46,16 +51,9 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Запрос для "От производителя"
|
const categories = activeTab === 'uzly' ? (quickGroupsData?.laximoQuickGroups || []) : (categoriesData?.laximoCategories || []);
|
||||||
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
const loading = activeTab === 'uzly' ? quickGroupsLoading : categoriesLoading;
|
||||||
variables: { catalogCode: catalogCode || '', vehicleId: vehicleId || '', ssd: ssd || '' },
|
const error = activeTab === 'uzly' ? quickGroupsError : categoriesError;
|
||||||
skip: !catalogCode || !vehicleId || 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 = () => {
|
const handleBack = () => {
|
||||||
setSelectedCategory(null);
|
setSelectedCategory(null);
|
||||||
@ -68,7 +66,8 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeTab === 'manufacturer') {
|
if (activeTab === 'uzly') {
|
||||||
|
// Логика для вкладки "Общие" (QuickGroups)
|
||||||
if (category.children && category.children.length > 0) {
|
if (category.children && category.children.length > 0) {
|
||||||
setSelectedCategory(category);
|
setSelectedCategory(category);
|
||||||
} else if (category.link && onQuickGroupSelect) {
|
} else if (category.link && onQuickGroupSelect) {
|
||||||
@ -77,7 +76,7 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
onNodeSelect(category);
|
onNodeSelect(category);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Логика для вкладки "Узлы"
|
// Логика для вкладки "От производителя" (Categories)
|
||||||
if (category.children && category.children.length > 0) {
|
if (category.children && category.children.length > 0) {
|
||||||
setSelectedCategory(category);
|
setSelectedCategory(category);
|
||||||
} else {
|
} else {
|
||||||
@ -85,7 +84,6 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
const categoryId = category.categoryid || category.quickgroupid || category.id;
|
const categoryId = category.categoryid || category.quickgroupid || category.id;
|
||||||
if (!unitsByCategory[categoryId] && catalogCode && vehicleId) {
|
if (!unitsByCategory[categoryId] && catalogCode && vehicleId) {
|
||||||
lastCategoryIdRef.current = categoryId;
|
lastCategoryIdRef.current = categoryId;
|
||||||
console.log('Loading units for category:', { categoryId, category });
|
|
||||||
getUnits({
|
getUnits({
|
||||||
variables: {
|
variables: {
|
||||||
catalogCode,
|
catalogCode,
|
||||||
@ -101,8 +99,8 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSubcategoryClick = (subcat: any) => {
|
const handleSubcategoryClick = (subcat: any) => {
|
||||||
if (activeTab === 'uzly' && onNodeSelect) {
|
if (activeTab === 'manufacturer' && onNodeSelect) {
|
||||||
// Для режима "Узлы" при клике на подкатегорию открываем KnotIn
|
// Для режима "От производителя" при клике на подкатегорию открываем KnotIn
|
||||||
onNodeSelect({
|
onNodeSelect({
|
||||||
...subcat,
|
...subcat,
|
||||||
unitid: subcat.unitid || subcat.categoryid || subcat.quickgroupid || subcat.id
|
unitid: subcat.unitid || subcat.categoryid || subcat.quickgroupid || subcat.id
|
||||||
@ -130,11 +128,11 @@ const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd,
|
|||||||
// Определяем, какие подкатегории показывать
|
// Определяем, какие подкатегории показывать
|
||||||
let subcategories: any[] = [];
|
let subcategories: any[] = [];
|
||||||
if (selectedCategory) {
|
if (selectedCategory) {
|
||||||
if (activeTab === 'manufacturer') {
|
if (activeTab === 'uzly') {
|
||||||
// Для вкладки "От производителя" используем children
|
// Для вкладки "Общие" используем children
|
||||||
subcategories = selectedCategory.children || [];
|
subcategories = selectedCategory.children || [];
|
||||||
} else {
|
} else {
|
||||||
// Для вкладки "Узлы" используем либо children, либо units
|
// Для вкладки "От производителя" используем либо children, либо units
|
||||||
if (selectedCategory.children && selectedCategory.children.length > 0) {
|
if (selectedCategory.children && selectedCategory.children.length > 0) {
|
||||||
subcategories = selectedCategory.children;
|
subcategories = selectedCategory.children;
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,7 +73,6 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
console.error('SSD обязателен для поиска по названию');
|
console.error('SSD обязателен для поиска по названию');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('SEARCH PARAMS', { catalogCode, vehicleId, searchQuery: searchQuery.trim(), ssd });
|
|
||||||
executeSearch({
|
executeSearch({
|
||||||
variables: {
|
variables: {
|
||||||
catalogCode,
|
catalogCode,
|
||||||
@ -102,7 +101,7 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
query: searchQuery
|
query: searchQuery
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [searchResults, loading, error, searchQuery, onSearchResults]);
|
}, [searchResults, loading, error, searchQuery]);
|
||||||
|
|
||||||
// --- Новый блок: вычисляем доступность поиска ---
|
// --- Новый блок: вычисляем доступность поиска ---
|
||||||
const isSearchAvailable = !!catalogCode && vehicleId !== undefined && vehicleId !== null && !!ssd && ssd.trim() !== '';
|
const isSearchAvailable = !!catalogCode && vehicleId !== undefined && vehicleId !== null && !!ssd && ssd.trim() !== '';
|
||||||
@ -112,10 +111,9 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
const showTips = isSearchAvailable && !searchQuery.trim() && !loading;
|
const showTips = isSearchAvailable && !searchQuery.trim() && !loading;
|
||||||
|
|
||||||
// --- QuickGroups (от производителя) ---
|
// --- QuickGroups (от производителя) ---
|
||||||
const [selectedQuickGroup, setSelectedQuickGroup] = useState<any | null>(null);
|
|
||||||
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
||||||
variables: { catalogCode, vehicleId, ssd },
|
variables: { catalogCode, vehicleId, ssd },
|
||||||
skip: !catalogCode || vehicleId === undefined || vehicleId === null || activeTab !== 'manufacturer',
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
});
|
});
|
||||||
const quickGroups = quickGroupsData?.laximoQuickGroups || [];
|
const quickGroups = quickGroupsData?.laximoQuickGroups || [];
|
||||||
@ -136,57 +134,15 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
|
|
||||||
const handleQuickGroupClick = (group: any) => {
|
const handleQuickGroupClick = (group: any) => {
|
||||||
if (group.link) {
|
if (group.link) {
|
||||||
setSelectedQuickGroup(group);
|
// Передаем выбранную группу в родительский компонент для отображения справа
|
||||||
|
if (onQuickGroupSelect) {
|
||||||
|
onQuickGroupSelect(group);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
handleQuickGroupToggle(group.quickgroupid);
|
handleQuickGroupToggle(group.quickgroupid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Детали выбранной группы (если link: true)
|
|
||||||
console.log('QuickDetail QUERY VARS', {
|
|
||||||
catalogCode,
|
|
||||||
vehicleId,
|
|
||||||
quickGroupId: selectedQuickGroup?.quickgroupid,
|
|
||||||
ssd
|
|
||||||
});
|
|
||||||
|
|
||||||
const skipQuickDetail =
|
|
||||||
!selectedQuickGroup ||
|
|
||||||
!catalogCode ||
|
|
||||||
vehicleId === undefined ||
|
|
||||||
vehicleId === null ||
|
|
||||||
!selectedQuickGroup?.quickgroupid ||
|
|
||||||
!ssd ||
|
|
||||||
ssd.trim() === '';
|
|
||||||
|
|
||||||
console.log('QuickDetail QUERY VARS', {
|
|
||||||
catalogCode,
|
|
||||||
vehicleId,
|
|
||||||
quickGroupId: selectedQuickGroup?.quickgroupid,
|
|
||||||
ssd: ssd ? `${ssd.substring(0, 30)}...` : 'отсутствует'
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('QuickDetail SKIP CONDITIONS', {
|
|
||||||
hasSelectedQuickGroup: !!selectedQuickGroup,
|
|
||||||
hasCatalogCode: !!catalogCode,
|
|
||||||
hasVehicleId: vehicleId !== undefined && vehicleId !== null,
|
|
||||||
hasQuickGroupId: !!selectedQuickGroup?.quickgroupid,
|
|
||||||
hasSsd: !!ssd && ssd.trim() !== '',
|
|
||||||
skipQuickDetail
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: quickDetailData, loading: quickDetailLoading, error: quickDetailError } = useQuery(GET_LAXIMO_QUICK_DETAIL, {
|
|
||||||
variables: selectedQuickGroup?.quickgroupid && !skipQuickDetail ? {
|
|
||||||
catalogCode,
|
|
||||||
vehicleId,
|
|
||||||
quickGroupId: selectedQuickGroup.quickgroupid,
|
|
||||||
ssd
|
|
||||||
} : undefined,
|
|
||||||
skip: skipQuickDetail,
|
|
||||||
errorPolicy: 'all'
|
|
||||||
});
|
|
||||||
const quickDetail = quickDetailData?.laximoQuickDetail;
|
|
||||||
|
|
||||||
// === Полнотекстовый поиск деталей (аналогично FulltextSearchSection) ===
|
// === Полнотекстовый поиск деталей (аналогично FulltextSearchSection) ===
|
||||||
const [fulltextQuery, setFulltextQuery] = useState('');
|
const [fulltextQuery, setFulltextQuery] = useState('');
|
||||||
const [executeFulltextSearch, { data: fulltextData, loading: fulltextLoading, error: fulltextError }] = useLazyQuery(GET_LAXIMO_FULLTEXT_SEARCH, { errorPolicy: 'all' });
|
const [executeFulltextSearch, { data: fulltextData, loading: fulltextLoading, error: fulltextError }] = useLazyQuery(GET_LAXIMO_FULLTEXT_SEARCH, { errorPolicy: 'all' });
|
||||||
@ -243,7 +199,7 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
isSearching: true
|
isSearching: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [fulltextData, fulltextLoading, fulltextError, onSearchResults]);
|
}, [fulltextData, fulltextLoading, fulltextError, fulltextQuery]);
|
||||||
|
|
||||||
const handleFulltextKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
const handleFulltextKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
@ -258,7 +214,7 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
if (onActiveTabChange) {
|
if (onActiveTabChange) {
|
||||||
onActiveTabChange(activeTab);
|
onActiveTabChange(activeTab);
|
||||||
}
|
}
|
||||||
}, [activeTab, onActiveTabChange]);
|
}, [activeTab]);
|
||||||
|
|
||||||
// Если нет данных о транспортном средстве, показываем заглушку
|
// Если нет данных о транспортном средстве, показываем заглушку
|
||||||
if (!vehicleInfo) {
|
if (!vehicleInfo) {
|
||||||
@ -336,9 +292,13 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (searchQuery) setSearchQuery('');
|
if (searchQuery) setSearchQuery('');
|
||||||
setActiveTab('uzly');
|
setActiveTab('uzly');
|
||||||
|
// Очищаем выбранную группу при смене таба
|
||||||
|
if (onQuickGroupSelect) {
|
||||||
|
onQuickGroupSelect(null);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Узлы
|
Общие
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
@ -353,6 +313,10 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (searchQuery) setSearchQuery('');
|
if (searchQuery) setSearchQuery('');
|
||||||
setActiveTab('manufacturer');
|
setActiveTab('manufacturer');
|
||||||
|
// Очищаем выбранную группу при смене таба
|
||||||
|
if (onQuickGroupSelect) {
|
||||||
|
onQuickGroupSelect(null);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
От производителя
|
От производителя
|
||||||
@ -360,6 +324,112 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
</div>
|
</div>
|
||||||
{/* Tab content start */}
|
{/* Tab content start */}
|
||||||
{activeTab === 'uzly' ? (
|
{activeTab === 'uzly' ? (
|
||||||
|
// Общие (QuickGroups - бывшие "От производителя")
|
||||||
|
quickGroupsLoading ? (
|
||||||
|
<div style={{ padding: 16, textAlign: 'center' }}>Загружаем группы быстрого поиска...</div>
|
||||||
|
) : quickGroupsError ? (
|
||||||
|
<div style={{ color: 'red', padding: 16 }}>Ошибка загрузки групп: {quickGroupsError.message}</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{(quickGroups as QuickGroup[]).map((group: QuickGroup) => {
|
||||||
|
const hasChildren = group.children && group.children.length > 0;
|
||||||
|
const isOpen = expandedQuickGroups.has(group.quickgroupid);
|
||||||
|
|
||||||
|
if (!hasChildren) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
key={group.quickgroupid}
|
||||||
|
className="dropdown-link-3 w-dropdown-link"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleQuickGroupClick(group);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{group.name}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={group.quickgroupid}
|
||||||
|
data-hover="false"
|
||||||
|
data-delay="0"
|
||||||
|
className={`dropdown-4 w-dropdown${isOpen ? " w--open" : ""}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`dropdown-toggle-3 w-dropdown-toggle${isOpen ? " w--open" : ""}`}
|
||||||
|
onClick={() => handleQuickGroupToggle(group.quickgroupid)}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
<div className="w-icon-dropdown-toggle"></div>
|
||||||
|
<div className="text-block-56">{group.name}</div>
|
||||||
|
</div>
|
||||||
|
<nav className={`dropdown-list-4 w-dropdown-list${isOpen ? " w--open" : ""}`}>
|
||||||
|
{group.children?.map((child: QuickGroup) => {
|
||||||
|
const hasSubChildren = child.children && child.children.length > 0;
|
||||||
|
const isChildOpen = expandedQuickGroups.has(child.quickgroupid);
|
||||||
|
|
||||||
|
if (!hasSubChildren) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
key={child.quickgroupid}
|
||||||
|
className="dropdown-link-3 w-dropdown-link "
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleQuickGroupClick(child);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{child.name}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={child.quickgroupid}
|
||||||
|
data-hover="false"
|
||||||
|
data-delay="0"
|
||||||
|
className={`dropdown-4 w-dropdown pl-0${isChildOpen ? " w--open" : ""}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`dropdown-toggle-card w-dropdown-toggle pl-0${isChildOpen ? " w--open" : ""}`}
|
||||||
|
onClick={() => handleQuickGroupToggle(child.quickgroupid)}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
<div className="w-icon-dropdown-toggle"></div>
|
||||||
|
<div className="text-block-56">{child.name}</div>
|
||||||
|
</div>
|
||||||
|
<nav className={`dropdown-list-4 w-dropdown-list pl-0${isChildOpen ? " w--open" : ""}`}>
|
||||||
|
{child.children?.map((subChild: QuickGroup) => (
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
key={subChild.quickgroupid}
|
||||||
|
className="dropdown-link-3 w-dropdown-link "
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleQuickGroupClick(subChild);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{subChild.name}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
// От производителя (Categories - узлы)
|
||||||
categoriesLoading ? (
|
categoriesLoading ? (
|
||||||
<div style={{ padding: 16, textAlign: 'center' }}>Загружаем категории...</div>
|
<div style={{ padding: 16, textAlign: 'center' }}>Загружаем категории...</div>
|
||||||
) : categoriesError ? (
|
) : categoriesError ? (
|
||||||
@ -415,160 +485,6 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
) : (
|
|
||||||
// Manufacturer tab content (QuickGroups)
|
|
||||||
quickGroupsLoading ? (
|
|
||||||
<div style={{ padding: 16, textAlign: 'center' }}>Загружаем группы быстрого поиска...</div>
|
|
||||||
) : quickGroupsError ? (
|
|
||||||
<div style={{ color: 'red', padding: 16 }}>Ошибка загрузки групп: {quickGroupsError.message}</div>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{(quickGroups as QuickGroup[]).map((group: QuickGroup) => {
|
|
||||||
const hasChildren = group.children && group.children.length > 0;
|
|
||||||
const isOpen = expandedQuickGroups.has(group.quickgroupid);
|
|
||||||
|
|
||||||
if (!hasChildren) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
key={group.quickgroupid}
|
|
||||||
className="dropdown-link-3 w-dropdown-link"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (group.link && onQuickGroupSelect) {
|
|
||||||
onQuickGroupSelect(group);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{group.name}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={group.quickgroupid}
|
|
||||||
data-hover="false"
|
|
||||||
data-delay="0"
|
|
||||||
className={`dropdown-4 w-dropdown${isOpen ? " w--open" : ""}`}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`dropdown-toggle-3 w-dropdown-toggle${isOpen ? " w--open" : ""}`}
|
|
||||||
onClick={() => handleQuickGroupToggle(group.quickgroupid)}
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
|
||||||
<div className="w-icon-dropdown-toggle"></div>
|
|
||||||
<div className="text-block-56">{group.name}</div>
|
|
||||||
</div>
|
|
||||||
<nav className={`dropdown-list-4 w-dropdown-list${isOpen ? " w--open" : ""}`}>
|
|
||||||
{group.children?.map((child: QuickGroup) => {
|
|
||||||
const hasSubChildren = child.children && child.children.length > 0;
|
|
||||||
const isChildOpen = expandedQuickGroups.has(child.quickgroupid);
|
|
||||||
|
|
||||||
if (!hasSubChildren) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
key={child.quickgroupid}
|
|
||||||
className="dropdown-link-3 w-dropdown-link "
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (child.link && onQuickGroupSelect) {
|
|
||||||
onQuickGroupSelect(child);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{child.name}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={child.quickgroupid}
|
|
||||||
data-hover="false"
|
|
||||||
data-delay="0"
|
|
||||||
className={`dropdown-4 w-dropdown pl-0${isChildOpen ? " w--open" : ""}`}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`dropdown-toggle-card w-dropdown-toggle pl-0${isChildOpen ? " w--open" : ""}`}
|
|
||||||
onClick={() => handleQuickGroupToggle(child.quickgroupid)}
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
|
||||||
<div className="w-icon-dropdown-toggle"></div>
|
|
||||||
<div className="text-block-56">{child.name}</div>
|
|
||||||
</div>
|
|
||||||
<nav className={`dropdown-list-4 w-dropdown-list pl-0${isChildOpen ? " w--open" : ""}`}>
|
|
||||||
{child.children?.map((subChild: QuickGroup) => (
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
key={subChild.quickgroupid}
|
|
||||||
className="dropdown-link-3 w-dropdown-link "
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (subChild.link && onQuickGroupSelect) {
|
|
||||||
onQuickGroupSelect(subChild);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{subChild.name}
|
|
||||||
</a>
|
|
||||||
))}
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{/* Quick Detail Modal */}
|
|
||||||
{selectedQuickGroup && (
|
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
|
|
||||||
<div className="bg-white rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto p-6">
|
|
||||||
<div className="flex justify-between items-center mb-4">
|
|
||||||
<h3 className="text-lg font-semibold">{selectedQuickGroup.name}</h3>
|
|
||||||
<button
|
|
||||||
onClick={() => setSelectedQuickGroup(null)}
|
|
||||||
className="text-gray-500 hover:text-gray-700"
|
|
||||||
>
|
|
||||||
✕
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{quickDetailLoading ? (
|
|
||||||
<div className="text-center py-4">Загружаем детали...</div>
|
|
||||||
) : quickDetailError ? (
|
|
||||||
<div className="text-red-600 py-4">Ошибка загрузки деталей: {quickDetailError.message}</div>
|
|
||||||
) : quickDetail?.units?.length > 0 ? (
|
|
||||||
<div className="space-y-4">
|
|
||||||
{quickDetail.units.map((unit: any) => (
|
|
||||||
<div key={unit.unitid} className="border border-gray-200 rounded-lg p-4">
|
|
||||||
<div className="font-medium text-gray-900 mb-2">{unit.name}</div>
|
|
||||||
{unit.details && unit.details.length > 0 && (
|
|
||||||
<div className="space-y-2">
|
|
||||||
{unit.details.map((detail: any) => (
|
|
||||||
<div key={detail.detailid} className="flex items-center justify-between bg-gray-50 p-2 rounded">
|
|
||||||
<span className="font-medium text-gray-700">{detail.name}</span>
|
|
||||||
<span className="text-sm bg-blue-100 text-blue-800 px-2 py-1 rounded">
|
|
||||||
OEM: {detail.oem}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="text-center text-gray-500 py-4">Нет деталей для этой группы</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
)}
|
)}
|
||||||
{/* Tab content end */}
|
{/* Tab content end */}
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,6 +24,8 @@ const VinQuick: React.FC<VinQuickProps> = ({ quickGroup, catalogCode, vehicleId,
|
|||||||
});
|
});
|
||||||
const quickDetail = data?.laximoQuickDetail;
|
const quickDetail = data?.laximoQuickDetail;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [isBrandModalOpen, setIsBrandModalOpen] = useState(false);
|
const [isBrandModalOpen, setIsBrandModalOpen] = useState(false);
|
||||||
const [selectedDetail, setSelectedDetail] = useState<any>(null);
|
const [selectedDetail, setSelectedDetail] = useState<any>(null);
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ const VinQuick: React.FC<VinQuickProps> = ({ quickGroup, catalogCode, vehicleId,
|
|||||||
name: unit.name,
|
name: unit.name,
|
||||||
catalogCode,
|
catalogCode,
|
||||||
vehicleId,
|
vehicleId,
|
||||||
ssd
|
ssd: unit.ssd || ssd // Используем SSD узла, а не родительский
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const handleDetailClick = (detail: any) => {
|
const handleDetailClick = (detail: any) => {
|
||||||
|
@ -46,7 +46,7 @@ const VehicleDetailsPage = () => {
|
|||||||
if (searchTypeParam === 'categories') {
|
if (searchTypeParam === 'categories') {
|
||||||
// В URL categories, но мы используем quickgroups для групп быстрого поиска
|
// В URL categories, но мы используем quickgroups для групп быстрого поиска
|
||||||
defaultSearchType = 'quickgroups';
|
defaultSearchType = 'quickgroups';
|
||||||
console.log('🔄 URL содержит searchType=categories, интерпретируем как quickgroups (группы быстрого поиска)');
|
|
||||||
} else if (searchTypeParam === 'quickgroups') {
|
} else if (searchTypeParam === 'quickgroups') {
|
||||||
defaultSearchType = 'quickgroups';
|
defaultSearchType = 'quickgroups';
|
||||||
} else if (searchTypeParam === 'fulltext') {
|
} else if (searchTypeParam === 'fulltext') {
|
||||||
@ -109,27 +109,14 @@ const VehicleDetailsPage = () => {
|
|||||||
const storedSsd = localStorage.getItem(vehicleKey);
|
const storedSsd = localStorage.getItem(vehicleKey);
|
||||||
if (storedSsd) {
|
if (storedSsd) {
|
||||||
finalSsd = storedSsd;
|
finalSsd = storedSsd;
|
||||||
console.log('🔧 SSD получен из localStorage, длина:', storedSsd.length);
|
|
||||||
// НЕ ОЧИЩАЕМ SSD сразу, оставляем на случай перезагрузки страницы
|
// НЕ ОЧИЩАЕМ SSD сразу, оставляем на случай перезагрузки страницы
|
||||||
// localStorage.removeItem(vehicleKey);
|
// localStorage.removeItem(vehicleKey);
|
||||||
} else {
|
|
||||||
console.log('⚠️ SSD не найден в localStorage, ключ:', vehicleKey);
|
|
||||||
console.log('🔍 Все ключи localStorage:', Object.keys(localStorage));
|
|
||||||
}
|
}
|
||||||
} else if (ssdFromQuery && ssdFromQuery.trim() !== '') {
|
} else if (ssdFromQuery && ssdFromQuery.trim() !== '') {
|
||||||
finalSsd = ssdFromQuery;
|
finalSsd = ssdFromQuery;
|
||||||
console.log('🔧 SSD получен из URL');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 Vehicle page params:', {
|
|
||||||
brand,
|
|
||||||
vehicleId,
|
|
||||||
useStorage,
|
|
||||||
ssdLengthFromUrl,
|
|
||||||
ssdFromQuery: ssdFromQuery ? `${ssdFromQuery.substring(0, 50)}...` : 'отсутствует',
|
|
||||||
finalSsd: finalSsd ? `${finalSsd.substring(0, 50)}...` : 'отсутствует',
|
|
||||||
ssdLength: finalSsd.length
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: vehicleData, loading: vehicleLoading, error: vehicleError } = useQuery<{ laximoVehicleInfo: LaximoVehicleInfo }>(
|
const { data: vehicleData, loading: vehicleLoading, error: vehicleError } = useQuery<{ laximoVehicleInfo: LaximoVehicleInfo }>(
|
||||||
GET_LAXIMO_VEHICLE_INFO,
|
GET_LAXIMO_VEHICLE_INFO,
|
||||||
@ -141,9 +128,56 @@ const VehicleDetailsPage = () => {
|
|||||||
localized: true
|
localized: true
|
||||||
},
|
},
|
||||||
skip: !brand || vehicleId === undefined || vehicleId === null,
|
skip: !brand || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: 'all'
|
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 {
|
const {
|
||||||
@ -249,12 +283,7 @@ const VehicleDetailsPage = () => {
|
|||||||
vehicleInfo = { ...vehicleInfo, vehicleid: fallbackVehicleId };
|
vehicleInfo = { ...vehicleInfo, vehicleid: fallbackVehicleId };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Логируем, что реально передаём в VinLeftbar
|
|
||||||
console.log('Передаём в VinLeftbar:', {
|
|
||||||
catalog: vehicleInfo.catalog,
|
|
||||||
vehicleid: vehicleInfo.vehicleid,
|
|
||||||
ssd: vehicleInfo.ssd
|
|
||||||
});
|
|
||||||
|
|
||||||
// Если нет данных автомобиля и есть ошибка, показываем предупреждение
|
// Если нет данных автомобиля и есть ошибка, показываем предупреждение
|
||||||
const hasError = vehicleError && !vehicleData?.laximoVehicleInfo;
|
const hasError = vehicleError && !vehicleData?.laximoVehicleInfo;
|
||||||
|
@ -154,6 +154,7 @@ export interface LaximoUnit {
|
|||||||
description?: string
|
description?: string
|
||||||
imageurl?: string
|
imageurl?: string
|
||||||
largeimageurl?: string
|
largeimageurl?: string
|
||||||
|
ssd?: string // 🎯 ДОБАВЛЕНИЕ: SSD для узла
|
||||||
details?: LaximoDetail[]
|
details?: LaximoDetail[]
|
||||||
attributes?: LaximoDetailAttribute[]
|
attributes?: LaximoDetailAttribute[]
|
||||||
}
|
}
|
||||||
@ -279,6 +280,7 @@ export interface LaximoUnitInfo {
|
|||||||
description?: string
|
description?: string
|
||||||
imageurl?: string
|
imageurl?: string
|
||||||
largeimageurl?: string
|
largeimageurl?: string
|
||||||
|
ssd?: string // 🎯 ДОБАВЛЕНИЕ: SSD для узла
|
||||||
attributes?: LaximoDetailAttribute[]
|
attributes?: LaximoDetailAttribute[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user