import React, { useState, useEffect } from 'react'; import { useQuery } from '@apollo/client'; import { useRouter } from 'next/router'; import { GET_LAXIMO_UNIT_INFO, GET_LAXIMO_UNIT_DETAILS, GET_LAXIMO_UNIT_IMAGE_MAP } from '@/lib/graphql'; import { LaximoUnitInfo, LaximoUnitDetail, LaximoUnitImageMap, LaximoImageCoordinate } from '@/types/laximo'; import BrandSelectionModal from './BrandSelectionModal'; interface UnitDetailsSectionProps { catalogCode: string; vehicleId: string; ssd?: string; unitId: string; unitName: string; onBack: () => void; } const UnitDetailsSection: React.FC = ({ catalogCode, vehicleId, ssd, unitId, unitName, onBack }) => { const router = useRouter(); const [selectedImageSize, setSelectedImageSize] = useState('250'); const [imageScale, setImageScale] = useState<{ x: number; y: number }>({ x: 1, y: 1 }); const [imageLoadTimeout, setImageLoadTimeout] = useState(null); const [isBrandModalOpen, setIsBrandModalOpen] = useState(false); const [selectedDetail, setSelectedDetail] = useState(null); // Отладочная информация для SSD console.log('🔍 UnitDetailsSection получил SSD:', { ssd: ssd ? `${ssd.substring(0, 50)}...` : 'отсутствует', ssdLength: ssd?.length, unitId, unitName }); // Получаем информацию об узле console.log('🔍 UnitDetailsSection - GET_LAXIMO_UNIT_INFO SSD:', { ssd: ssd ? `${ssd.substring(0, 50)}...` : 'отсутствует', ssdLength: ssd?.length, unitId, unitName, note: 'Используем SSD узла для API запросов' }); const { data: unitInfoData, loading: unitInfoLoading, error: unitInfoError } = useQuery<{ laximoUnitInfo: LaximoUnitInfo }>( GET_LAXIMO_UNIT_INFO, { variables: { catalogCode, vehicleId, unitId, ssd }, skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId || !ssd || ssd.trim() === '', errorPolicy: 'all', fetchPolicy: 'no-cache', // Отключаем кэширование для получения актуальных данных notifyOnNetworkStatusChange: true } ); // Получаем детали узла console.log('🔍 UnitDetailsSection - GET_LAXIMO_UNIT_DETAILS SSD:', { ssd: ssd ? `${ssd.substring(0, 50)}...` : 'отсутствует', ssdLength: ssd?.length, unitId, unitName }); const { data: unitDetailsData, loading: unitDetailsLoading, error: unitDetailsError } = useQuery<{ laximoUnitDetails: LaximoUnitDetail[] }>( GET_LAXIMO_UNIT_DETAILS, { variables: { catalogCode, vehicleId, unitId, ssd }, skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId || !ssd || ssd.trim() === '', errorPolicy: 'all', fetchPolicy: 'no-cache', // Отключаем кэширование для получения актуального SSD notifyOnNetworkStatusChange: true } ); // Получаем карту изображений узла console.log('🔍 UnitDetailsSection - GET_LAXIMO_UNIT_IMAGE_MAP SSD:', { ssd: ssd ? `${ssd.substring(0, 50)}...` : 'отсутствует', ssdLength: ssd?.length, unitId, unitName }); const { data: unitImageMapData, loading: unitImageMapLoading, error: unitImageMapError } = useQuery<{ laximoUnitImageMap: LaximoUnitImageMap }>( GET_LAXIMO_UNIT_IMAGE_MAP, { variables: { catalogCode, vehicleId, unitId, ssd }, skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId || !ssd || ssd.trim() === '', errorPolicy: 'all', fetchPolicy: 'no-cache', // Отключаем кэширование для получения актуального SSD notifyOnNetworkStatusChange: true } ); // Используем данные из API или показываем сообщение о загрузке const unitInfo = unitInfoData?.laximoUnitInfo; console.log('📊 Данные узла из GraphQL:', { unitInfoData, unitInfo }); // Эффект для установки таймаута загрузки изображения useEffect(() => { if (unitInfo?.imageurl) { console.log('🔄 Начинаем загрузку изображения:', getImageUrl(unitInfo.imageurl, selectedImageSize)); // Устанавливаем таймаут на 10 секунд const timeout = setTimeout(() => { console.warn('⚠️ Таймаут загрузки изображения (10 сек)'); const placeholder = document.getElementById('image-placeholder'); if (placeholder) { placeholder.style.display = 'block'; } }, 10000); setImageLoadTimeout(timeout); return () => { if (timeout) { clearTimeout(timeout); } }; } }, [unitInfo?.imageurl, selectedImageSize]); const unitDetails = unitDetailsData?.laximoUnitDetails || []; const unitImageMap = unitImageMapData?.laximoUnitImageMap; const handleDetailClick = (detail: LaximoUnitDetail) => { console.log('🔍 Выбрана деталь для выбора бренда:', detail.name, 'OEM:', detail.oem); if (detail.oem) { setSelectedDetail(detail); setIsBrandModalOpen(true); } }; const handleCloseBrandModal = () => { setIsBrandModalOpen(false); setSelectedDetail(null); }; const handleCoordinateClick = (coord: LaximoImageCoordinate) => { console.log('🖱️ Клик по интерактивной области:', coord.codeonimage); // Сначала пытаемся найти деталь в списке const detail = unitDetails.find(d => d.detailid === coord.detailid || d.codeonimage === coord.codeonimage || d.detailid === coord.codeonimage ); if (detail && detail.oem) { console.log('✅ Найдена деталь для выбора бренда:', detail.name, 'OEM:', detail.oem); // Показываем модал выбора бренда setSelectedDetail(detail); setIsBrandModalOpen(true); } else { // Если деталь не найдена в списке, переходим к общему поиску по коду на изображении console.log('⚠️ Деталь не найдена в списке, переходим к поиску по коду:', coord.codeonimage); router.push(`/search-result?q=${coord.codeonimage}&catalog=${catalogCode}&vehicle=${vehicleId}`); } }; const getImageUrl = (baseUrl: string, size: string) => { // Декодируем HTML-сущности и заменяем размер const decodedUrl = baseUrl .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace('%size%', size); console.log('🔗 Преобразование URL:', { original: baseUrl, decoded: decodedUrl, size: size }); return decodedUrl; }; const imageSizes = [ { value: '150', label: 'Маленькое' }, { value: '200', label: 'Среднее' }, { value: '250', label: 'Большое' }, { value: 'source', label: 'Оригинал' } ]; // Показываем загрузку если загружаются основные данные if (unitInfoLoading || unitDetailsLoading) { return (

{unitName}

Загружаем детали узла...

); } // Показываем ошибку если есть критические ошибки if (unitInfoError && unitDetailsError) { return (

{unitName}

Ошибка загрузки деталей узла

Не удалось загрузить информацию об узле

{unitInfoError?.message || unitDetailsError?.message}

); } // Показываем заглушку если детали не загружены (временное решение) if (!unitDetailsLoading && unitDetails.length === 0) { console.log('⚠️ Детали узла не загружены - показываем заглушку') } // Если данные об узле не загружены, показываем сообщение if (!unitInfo) { return (

{unitName}

Информация об узле не найдена

Попробуйте обновить страницу

); } return (
{/* Навигация */}

{unitInfo.name}

{/* Информация об узле */}
{/* Изображение узла */}
{unitInfo.imageurl && (
{/* Отладочная информация для изображения */} {process.env.NODE_ENV === 'development' && (

URL изображения:

Базовый: {unitInfo.imageurl}

Итоговый: {getImageUrl(unitInfo.imageurl, selectedImageSize)}

)}
{unitInfo.name} { // Очищаем таймаут если изображение загрузилось if (imageLoadTimeout) { clearTimeout(imageLoadTimeout); setImageLoadTimeout(null); } // Обновляем масштаб интерактивных областей при загрузке изображения const img = e.currentTarget; const naturalWidth = img.naturalWidth; const naturalHeight = img.naturalHeight; const displayWidth = img.offsetWidth; const displayHeight = img.offsetHeight; const scaleX = displayWidth / naturalWidth; const scaleY = displayHeight / naturalHeight; setImageScale({ x: scaleX, y: scaleY }); console.log('✅ Изображение успешно загружено:', { src: img.src, natural: { width: naturalWidth, height: naturalHeight }, display: { width: displayWidth, height: displayHeight }, scale: { x: scaleX, y: scaleY } }); // Скрываем placeholder если он был показан const placeholder = document.getElementById('image-placeholder'); if (placeholder) { placeholder.style.display = 'none'; } }} onError={(e) => { const target = e.currentTarget; console.error('❌ Ошибка загрузки изображения:', { src: target.src, error: e, naturalWidth: target.naturalWidth, naturalHeight: target.naturalHeight }); target.style.display = 'none'; const placeholder = document.getElementById('image-placeholder'); if (placeholder) { placeholder.style.display = 'block'; } }} /> {/* Интерактивные области изображения */} {unitImageMap?.coordinates && unitImageMap.coordinates.map((coord, index) => { const detail = unitDetails.find(d => d.detailid === coord.detailid || d.codeonimage === coord.codeonimage); // Применяем масштаб к координатам const scaledX = coord.x * imageScale.x; const scaledY = coord.y * imageScale.y; const scaledWidth = coord.width * imageScale.x; const scaledHeight = coord.height * imageScale.y; // Создаем уникальный ключ для каждой области const uniqueKey = `coord-${unitId}-${index}-${coord.x}-${coord.y}`; return (
handleCoordinateClick(coord)} title={detail ? `${coord.codeonimage}: ${detail.name}` : `Деталь ${coord.codeonimage}`} >
{coord.codeonimage}
); })}

Изображение недоступно

{process.env.NODE_ENV === 'development' && (

URL: {getImageUrl(unitInfo.imageurl, selectedImageSize)}

)}

Схема узла с номерами деталей {unitImageMap?.coordinates && unitImageMap.coordinates.length > 0 && ( • {unitImageMap.coordinates.length} интерактивных областей )} {(!unitImageMap?.coordinates || unitImageMap.coordinates.length === 0) && ( • Интерактивные области не найдены )}

{/* Отладочная информация */} {process.env.NODE_ENV === 'development' && unitImageMap && (

Отладка:

Unit ID: {unitImageMap.unitid}

Координат: {unitImageMap.coordinates?.length || 0}

Масштаб: x={imageScale.x.toFixed(3)}, y={imageScale.y.toFixed(3)}

{unitImageMap.coordinates?.map((coord, i) => (

Область {i+1}: код={coord.codeonimage}, x={coord.x}, y={coord.y}, w={coord.width}, h={coord.height}

))}
)}
)}
{/* Информация об узле */}

Информация об узле

ID узла:
{unitInfo.unitid}
{unitInfo.code && (
Код:
{unitInfo.code}
)} {unitInfo.description && (
Описание:
{unitInfo.description}
)}
Каталог:
{catalogCode}
Автомобиль:
ID: {vehicleId}
{/* Дополнительные атрибуты узла */} {unitInfo.attributes && unitInfo.attributes.length > 0 && (
Дополнительная информация
{unitInfo.attributes.map((attr, attrIndex) => (
{attr.name || attr.key}:
{attr.value}
))}
)}
{/* Список деталей */}

Детали узла ({unitDetails.length})

{unitDetailsLoading && (
Загружаем детали...
)}
{unitDetailsError && (

⚠️ Ошибка загрузки деталей: {unitDetailsError.message}

)} {unitDetails.length === 0 && !unitDetailsLoading ? (

Детали узла не найдены

{/* Отладочная информация для деталей */} {process.env.NODE_ENV === 'development' && (

Отладка деталей:

Ошибка загрузки: {unitDetailsError?.message || 'нет'}

Загружается: {unitDetailsLoading ? 'да' : 'нет'}

Количество деталей: {unitDetails.length}

)}
) : (
{unitDetails.map((detail, index) => (
handleDetailClick(detail)} >
{detail.codeonimage && ( {detail.codeonimage} )}
{detail.name}
{detail.oem && (
OEM: {detail.oem}
)} {detail.brand && (
Бренд: {detail.brand}
)} {detail.price && (
Цена: {detail.price} ₽
)} {detail.availability && (
Наличие: {detail.availability}
)}
{detail.note && (

{detail.note}

)} {/* Дополнительные атрибуты детали */} {detail.attributes && detail.attributes.length > 0 && (
Дополнительные характеристики:
{detail.attributes.map((attr, attrIndex) => (
{attr.name || attr.key}: {attr.value}
))}
)}
))}
)}
{/* Информационное сообщение */}

Полная интеграция с Laximo API

Компонент использует официальные API Laximo: GetUnitInfo для информации об узле, ListDetailByUnit для получения деталей и ListImageMapByUnit для интерактивной карты изображений. Нажмите на номера деталей на схеме или в списке для подробной информации.

{/* Модал выбора бренда */} {selectedDetail && ( )}
); }; export default UnitDetailsSection;