import React, { useState, useEffect, useRef } from "react"; import { useRouter } from "next/router"; interface KnotPartsProps { parts?: Array<{ detailid?: string; codeonimage?: string | number; oem?: string; name?: string; price?: string | number; brand?: string; availability?: string; note?: string; attributes?: Array<{ key: string; name?: string; value: string }>; }>; selectedCodeOnImage?: string | number; catalogCode?: string; vehicleId?: string; highlightedCodeOnImage?: string | number | null; // Деталь подсвеченная при hover на изображении selectedParts?: Set; // Выбранные детали (множественный выбор) onPartSelect?: (codeOnImage: string | number | null) => void; // Коллбек для выбора детали onPartHover?: (codeOnImage: string | number | null) => void; // Коллбек для подсветки при hover } const KnotParts: React.FC = ({ parts = [], selectedCodeOnImage, catalogCode, vehicleId, highlightedCodeOnImage, selectedParts = new Set(), onPartSelect, onPartHover }) => { const router = useRouter(); const [showTooltip, setShowTooltip] = useState(false); const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 }); const [tooltipPart, setTooltipPart] = useState(null); const timeoutRef = useRef(null); // Отладочные логи для проверки данных React.useEffect(() => { console.log('🔍 KnotParts получил данные:', { partsCount: parts.length, firstPart: parts[0], firstPartAttributes: parts[0]?.attributes?.length || 0, allPartsWithAttributes: parts.map(part => ({ name: part.name, oem: part.oem, attributesCount: part.attributes?.length || 0, attributes: part.attributes })) }); }, [parts]); const handlePriceClick = (part: any) => { if (part.oem && catalogCode && vehicleId !== undefined) { // Переходим на страницу выбора бренда const url = `/vehicle-search/${catalogCode}/${vehicleId}/part/${part.oem}/brands?detailName=${encodeURIComponent(part.name || '')}`; router.push(url); } }; // Обработчик клика по детали в списке const handlePartClick = (part: any) => { if (part.codeonimage && onPartSelect) { onPartSelect(part.codeonimage); } }; // Обработчики наведения const handlePartMouseEnter = (part: any) => { if (part.codeonimage && onPartHover) { onPartHover(part.codeonimage); } }; const handlePartMouseLeave = () => { if (onPartHover) { onPartHover(null); } }; // Вычисляем позицию tooltip const calculateTooltipPosition = (iconElement: HTMLElement) => { if (!iconElement) { console.error('❌ calculateTooltipPosition: элемент не найден'); return; } const rect = iconElement.getBoundingClientRect(); const tooltipWidth = 400; const tooltipHeight = 300; // примерная высота let x = rect.left + rect.width / 2 - tooltipWidth / 2; let y = rect.bottom + 8; // Проверяем, не выходит ли tooltip за границы экрана if (x < 10) x = 10; if (x + tooltipWidth > window.innerWidth - 10) { x = window.innerWidth - tooltipWidth - 10; } // Если tooltip не помещается снизу, показываем сверху if (y + tooltipHeight > window.innerHeight - 10) { y = rect.top - tooltipHeight - 8; } setTooltipPosition({ x, y }); }; const handleInfoIconMouseEnter = (event: React.MouseEvent, part: any) => { event.stopPropagation(); if (timeoutRef.current) { clearTimeout(timeoutRef.current); } // Сохраняем ссылку на элемент до setTimeout const target = event.currentTarget as HTMLElement; timeoutRef.current = setTimeout(() => { if (target && typeof target.getBoundingClientRect === 'function') { calculateTooltipPosition(target); setTooltipPart(part); setShowTooltip(true); console.log('🔍 Показываем тултип для детали:', part.name, 'Атрибуты:', part.attributes?.length || 0); } else { console.error('❌ handleInfoIconMouseEnter: элемент не поддерживает getBoundingClientRect:', target); } }, 300); // Задержка 300ms }; const handleInfoIconMouseLeave = (event: React.MouseEvent) => { event.stopPropagation(); if (timeoutRef.current) { clearTimeout(timeoutRef.current); } timeoutRef.current = setTimeout(() => { setShowTooltip(false); setTooltipPart(null); }, 100); // Небольшая задержка перед скрытием }; // Очищаем таймеры при размонтировании useEffect(() => { return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } }; }, []); // Если нет деталей, показываем заглушку if (!parts || parts.length === 0) { return (
Список деталей
Выберите узел для отображения деталей
); } // Эффект для отслеживания изменений подсветки useEffect(() => { console.log('🔍 KnotParts - подсветка изменилась:', { highlightedCodeOnImage, highlightedType: typeof highlightedCodeOnImage, partsCodeOnImages: parts.map(p => p.codeonimage), partsDetailIds: parts.map(p => p.detailid), willHighlight: parts.some(part => (part.codeonimage && part.codeonimage.toString() === highlightedCodeOnImage?.toString()) || (part.detailid && part.detailid.toString() === highlightedCodeOnImage?.toString()) ), willHighlightStrict: parts.some(part => part.codeonimage === highlightedCodeOnImage || part.detailid === highlightedCodeOnImage ), firstPartWithCodeOnImage: parts.find(p => p.codeonimage) }); // Детальная информация о всех деталях console.log('📋 Все детали с их codeonimage и detailid:'); parts.forEach((part, idx) => { console.log(` Деталь ${idx}: "${part.name}" codeonimage="${part.codeonimage}" (${typeof part.codeonimage}) detailid="${part.detailid}" (${typeof part.detailid})`); }); console.log('🎯 Ищем подсветку для:', `"${highlightedCodeOnImage}" (${typeof highlightedCodeOnImage})`); }, [highlightedCodeOnImage, parts]); return ( <> {/* Статус выбранных деталей */} {selectedParts.size > 0 && (
Выбрано деталей: {selectedParts.size} (Кликните по детали, чтобы убрать из выбранных)
)}
{parts.map((part, idx) => { const isHighlighted = highlightedCodeOnImage !== null && highlightedCodeOnImage !== undefined && ( (part.codeonimage && part.codeonimage.toString() === highlightedCodeOnImage.toString()) || (part.detailid && part.detailid.toString() === highlightedCodeOnImage.toString()) ); const isSelected = selectedParts.has(part.detailid || part.codeonimage || idx.toString()); // Создаем уникальный ключ const uniqueKey = `part-${idx}-${part.detailid || part.oem || part.name || 'unknown'}`; return (
handlePartClick(part)} onMouseEnter={() => handlePartMouseEnter(part)} onMouseLeave={handlePartMouseLeave} style={{ cursor: 'pointer' }} >
{part.codeonimage || idx + 1}
{part.oem}
{part.name}
handleInfoIconMouseEnter(e, part)} onMouseLeave={handleInfoIconMouseLeave} style={{ cursor: 'pointer' }} >
); })}
{/* Красивый тултип с информацией о детали */} {showTooltip && tooltipPart && (
{/* Стрелка тултипа */}
{/* Заголовок */}

{tooltipPart.name}

{tooltipPart.oem && (
OEM {tooltipPart.oem}
)}
{/* Контент */}
{tooltipPart.attributes && tooltipPart.attributes.length > 0 ? (
Характеристики
{tooltipPart.attributes.map((attr: any, index: number) => (
{attr.name || attr.key}
{attr.value}
))}
) : (
Дополнительная информация
недоступна
)} {tooltipPart.note && (
Примечание
{tooltipPart.note}
)}
)} ); }; export default KnotParts;