import React, { useRef, useState } from "react"; import { useQuery } from '@apollo/client'; import { useRouter } from 'next/router'; import { GET_LAXIMO_UNIT_INFO, GET_LAXIMO_UNIT_IMAGE_MAP } from '@/lib/graphql'; import BrandSelectionModal from '../BrandSelectionModal'; interface KnotInProps { catalogCode?: string; vehicleId?: string; ssd?: string; unitId?: string; unitName?: string; 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 }>; }>; } // Функция для корректного формирования URL изображения const getImageUrl = (baseUrl: string, size: string) => { if (!baseUrl) return ''; return baseUrl .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace('%size%', size); }; const KnotIn: React.FC = ({ catalogCode, vehicleId, ssd, unitId, unitName, parts }) => { const imgRef = useRef(null); const [imageScale, setImageScale] = useState({ x: 1, y: 1 }); const selectedImageSize = 'source'; const [isBrandModalOpen, setIsBrandModalOpen] = useState(false); const [selectedDetail, setSelectedDetail] = useState<{ oem: string; name: string } | null>(null); const router = useRouter(); // Получаем инфо об узле (для картинки) console.log('🔍 KnotIn - GET_LAXIMO_UNIT_INFO запрос:', { catalogCode, vehicleId, unitId, ssd: ssd ? `${ssd.substring(0, 50)}...` : 'отсутствует', ssdLength: ssd?.length, skipCondition: !catalogCode || !vehicleId || !unitId || !ssd || ssd.trim() === '' }); const { data: unitInfoData, loading: unitInfoLoading, error: unitInfoError } = useQuery( GET_LAXIMO_UNIT_INFO, { variables: { catalogCode, vehicleId, unitId, ssd }, skip: !catalogCode || !vehicleId || !unitId || !ssd || ssd.trim() === '', errorPolicy: 'all', } ); // Получаем карту координат console.log('🔍 KnotIn - GET_LAXIMO_UNIT_IMAGE_MAP запрос:', { catalogCode, vehicleId, unitId, ssd: ssd ? `${ssd.substring(0, 50)}...` : 'отсутствует', ssdLength: ssd?.length, skipCondition: !catalogCode || !vehicleId || !unitId || !ssd || ssd.trim() === '' }); const { data: imageMapData, loading: imageMapLoading, error: imageMapError } = useQuery( GET_LAXIMO_UNIT_IMAGE_MAP, { variables: { catalogCode, vehicleId, unitId, ssd }, skip: !catalogCode || !vehicleId || !unitId || !ssd || ssd.trim() === '', errorPolicy: 'all', } ); // Если нет необходимых данных, показываем заглушку if (!catalogCode || !vehicleId || !unitId || !ssd || ssd.trim() === '') { console.log('⚠️ KnotIn: отсутствуют необходимые данные:', { catalogCode: !!catalogCode, vehicleId: !!vehicleId, unitId: !!unitId, ssd: !!ssd, ssdValid: ssd ? ssd.trim() !== '' : false }); return (
Схема узла
Выберите узел для отображения схемы
{process.env.NODE_ENV === 'development' && (
Debug: catalogCode={catalogCode}, vehicleId={vehicleId}, unitId={unitId}, ssd={ssd ? 'есть' : 'нет'}
)}
); } const unitInfo = unitInfoData?.laximoUnitInfo; const coordinates = imageMapData?.laximoUnitImageMap?.coordinates || []; const imageUrl = unitInfo?.imageurl ? getImageUrl(unitInfo.imageurl, selectedImageSize) : ''; // Логируем успешную загрузку данных React.useEffect(() => { if (unitInfo) { console.log('✅ KnotIn: данные узла загружены:', { unitName: unitInfo.name, hasImage: !!unitInfo.imageurl, imageUrl: unitInfo.imageurl, processedImageUrl: imageUrl }); } }, [unitInfo, imageUrl]); React.useEffect(() => { if (coordinates.length > 0) { console.log('✅ KnotIn: координаты карты загружены:', { coordinatesCount: coordinates.length, firstCoordinate: coordinates[0] }); } else if (imageMapData) { console.log('⚠️ KnotIn: карта изображений загружена, но координаты пустые:', imageMapData); } }, [coordinates, imageMapData]); // Масштабируем точки после загрузки картинки const handleImageLoad = (e: React.SyntheticEvent) => { const img = e.currentTarget; if (!img.naturalWidth || !img.naturalHeight) return; setImageScale({ x: img.offsetWidth / img.naturalWidth, y: img.offsetHeight / img.naturalHeight, }); }; // Клик по точке: найти part по codeonimage/detailid и открыть BrandSelectionModal const handlePointClick = (codeonimage: string | number) => { if (!parts) return; console.log('Клик по точке:', codeonimage, 'Все детали:', parts); const part = parts.find( (p) => (p.codeonimage && p.codeonimage.toString() === codeonimage.toString()) || (p.detailid && p.detailid.toString() === codeonimage.toString()) ); console.log('Найдена деталь для точки:', part); if (part?.oem) { setSelectedDetail({ oem: part.oem, name: part.name || '' }); setIsBrandModalOpen(true); } else { console.warn('Нет артикула (oem) для выбранной точки:', codeonimage, part); } }; // Для отладки: вывести детали и координаты React.useEffect(() => { console.log('KnotIn parts:', parts); console.log('KnotIn coordinates:', coordinates); }, [parts, coordinates]); if (unitInfoLoading || imageMapLoading) { console.log('🔄 KnotIn: загрузка данных...', { unitInfoLoading, imageMapLoading, unitInfoError: unitInfoError?.message, imageMapError: imageMapError?.message }); return
Загружаем схему узла...
; } if (unitInfoError) { console.error('❌ KnotIn: ошибка загрузки информации об узле:', unitInfoError); return (
Ошибка загрузки схемы: {unitInfoError.message} {process.env.NODE_ENV === 'development' && (
GraphQL Error: {JSON.stringify(unitInfoError, null, 2)}
)}
); } if (imageMapError) { console.error('❌ KnotIn: ошибка загрузки карты изображений:', imageMapError); } if (!imageUrl) { console.log('⚠️ KnotIn: нет URL изображения:', { unitInfo: !!unitInfo, imageurl: unitInfo?.imageurl, unitInfoData: !!unitInfoData }); return (
Нет изображения для этого узла {process.env.NODE_ENV === 'development' && unitInfo && (
Debug: unitInfo.imageurl = {unitInfo.imageurl || 'отсутствует'}
)}
); } return ( <>
{/* ВРЕМЕННО: выводим количество точек для быстрой проверки */} {/*
{coordinates.length} точек
*/} {unitName {/* Точки/области */} {coordinates.map((coord: any, idx: number) => { // Кружки всегда 32x32px, центрируем по координате const size = 22; const scaledX = coord.x * imageScale.x - size / 2; const scaledY = coord.y * imageScale.y - size / 2; return (
{ if (e.key === 'Enter' || e.key === ' ') handlePointClick(coord.codeonimage); }} className="absolute flex items-center justify-center cursor-pointer transition-colors" style={{ left: scaledX, top: scaledY, width: size, height: size, background: '#B7CAE2', borderRadius: '50%', pointerEvents: 'auto', }} title={coord.codeonimage} onClick={() => handlePointClick(coord.codeonimage)} onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.background = '#EC1C24'; (e.currentTarget.querySelector('span') as HTMLSpanElement).style.color = '#fff'; }} onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.background = '#B7CAE2'; (e.currentTarget.querySelector('span') as HTMLSpanElement).style.color = '#000'; }} > {coord.codeonimage}
); })}
{/* Модалка выбора бренда */} setIsBrandModalOpen(false)} articleNumber={selectedDetail?.oem || ''} detailName={selectedDetail?.name || ''} /> ); }; export default KnotIn;