first commit

This commit is contained in:
Bivekich
2025-06-26 06:59:59 +03:00
commit d44874775c
450 changed files with 76635 additions and 0 deletions

View File

@ -0,0 +1,688 @@
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<UnitDetailsSectionProps> = ({
catalogCode,
vehicleId,
ssd,
unitId,
unitName,
onBack
}) => {
const router = useRouter();
const [selectedImageSize, setSelectedImageSize] = useState<string>('250');
const [imageScale, setImageScale] = useState<{ x: number; y: number }>({ x: 1, y: 1 });
const [imageLoadTimeout, setImageLoadTimeout] = useState<NodeJS.Timeout | null>(null);
const [isBrandModalOpen, setIsBrandModalOpen] = useState(false);
const [selectedDetail, setSelectedDetail] = useState<LaximoUnitDetail | null>(null);
// Получаем информацию об узле
const { data: unitInfoData, loading: unitInfoLoading, error: unitInfoError } = useQuery<{ laximoUnitInfo: LaximoUnitInfo }>(
GET_LAXIMO_UNIT_INFO,
{
variables: {
catalogCode,
vehicleId,
unitId,
ssd: ssd || ''
},
skip: !catalogCode || !vehicleId || !unitId,
errorPolicy: 'all'
}
);
// Получаем детали узла
const { data: unitDetailsData, loading: unitDetailsLoading, error: unitDetailsError } = useQuery<{ laximoUnitDetails: LaximoUnitDetail[] }>(
GET_LAXIMO_UNIT_DETAILS,
{
variables: {
catalogCode,
vehicleId,
unitId,
ssd: ssd || ''
},
skip: !catalogCode || !vehicleId || !unitId,
errorPolicy: 'all'
}
);
// Получаем карту изображений узла
const { data: unitImageMapData, loading: unitImageMapLoading, error: unitImageMapError } = useQuery<{ laximoUnitImageMap: LaximoUnitImageMap }>(
GET_LAXIMO_UNIT_IMAGE_MAP,
{
variables: {
catalogCode,
vehicleId,
unitId,
ssd: ssd || ''
},
skip: !catalogCode || !vehicleId || !unitId,
errorPolicy: 'all'
}
);
// Используем данные из 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(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/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 (
<div>
<div className="flex items-center mb-6">
<button
onClick={onBack}
className="flex items-center text-gray-600 hover:text-gray-900 mr-4 transition-colors"
>
<svg className="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Назад к узлам
</button>
<h3 className="text-lg font-medium text-gray-900">
{unitName}
</h3>
</div>
<div className="text-center py-8">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-red-600 mx-auto"></div>
<p className="mt-4 text-gray-600">Загружаем детали узла...</p>
</div>
</div>
);
}
// Показываем ошибку если есть критические ошибки
if (unitInfoError && unitDetailsError) {
return (
<div>
<div className="flex items-center mb-6">
<button
onClick={onBack}
className="flex items-center text-gray-600 hover:text-gray-900 mr-4 transition-colors"
>
<svg className="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Назад к узлам
</button>
<h3 className="text-lg font-medium text-gray-900">
{unitName}
</h3>
</div>
<div className="text-center py-8">
<div className="text-red-600 mb-4">
<svg className="w-12 h-12 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
</svg>
</div>
<h3 className="text-lg font-medium text-gray-900 mb-2">Ошибка загрузки деталей узла</h3>
<p className="text-gray-600 mb-4">Не удалось загрузить информацию об узле</p>
<p className="text-sm text-gray-500">
{unitInfoError?.message || unitDetailsError?.message}
</p>
</div>
</div>
);
}
// Показываем заглушку если детали не загружены (временное решение)
if (!unitDetailsLoading && unitDetails.length === 0) {
console.log('⚠️ Детали узла не загружены - показываем заглушку')
}
// Если данные об узле не загружены, показываем сообщение
if (!unitInfo) {
return (
<div>
<div className="flex items-center mb-6">
<button
onClick={onBack}
className="flex items-center text-gray-600 hover:text-gray-900 mr-4 transition-colors"
>
<svg className="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Назад к узлам
</button>
<h3 className="text-lg font-medium text-gray-900">
{unitName}
</h3>
</div>
<div className="text-center py-8">
<div className="text-gray-400 mb-2">
<svg className="w-8 h-8 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<p className="text-gray-500">Информация об узле не найдена</p>
<p className="text-sm text-gray-400 mt-1">Попробуйте обновить страницу</p>
</div>
</div>
);
}
return (
<div>
{/* Навигация */}
<div className="flex items-center mb-6">
<button
onClick={onBack}
className="flex items-center text-gray-600 hover:text-gray-900 mr-4 transition-colors"
>
<svg className="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Назад к узлам
</button>
<h3 className="text-lg font-medium text-gray-900">
{unitInfo.name}
</h3>
</div>
{/* Информация об узле */}
<div className="bg-white border border-gray-200 rounded-lg p-6 mb-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Изображение узла */}
<div>
<div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-2">
Размер изображения:
</label>
<select
value={selectedImageSize}
onChange={(e) => {
setSelectedImageSize(e.target.value);
// Сбрасываем масштаб при изменении размера
setImageScale({ x: 1, y: 1 });
}}
className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-red-500 focus:border-red-500"
>
{imageSizes.map((size) => (
<option key={size.value} value={size.value}>
{size.label}
</option>
))}
</select>
</div>
{unitInfo.imageurl && (
<div className="bg-gray-50 rounded-lg p-4 text-center">
{/* Отладочная информация для изображения */}
{process.env.NODE_ENV === 'development' && (
<div className="mb-2 p-2 bg-blue-50 border border-blue-200 rounded text-xs text-left">
<p><strong>URL изображения:</strong></p>
<p>Базовый: {unitInfo.imageurl}</p>
<p>Итоговый: {getImageUrl(unitInfo.imageurl, selectedImageSize)}</p>
<div className="mt-2 space-x-2">
<button
onClick={() => {
if (unitInfo.imageurl) {
window.open(getImageUrl(unitInfo.imageurl, selectedImageSize), '_blank');
}
}}
className="px-2 py-1 bg-blue-500 text-white rounded text-xs"
>
Открыть в новой вкладке
</button>
<button
onClick={() => {
const img = document.getElementById('unit-image') as HTMLImageElement;
if (img) {
console.log('🔄 Принудительная перезагрузка изображения');
img.src = img.src + '?t=' + Date.now();
}
}}
className="px-2 py-1 bg-green-500 text-white rounded text-xs"
>
Перезагрузить
</button>
</div>
</div>
)}
<div className="relative inline-block">
<img
id="unit-image"
src={getImageUrl(unitInfo.imageurl, selectedImageSize)}
alt={unitInfo.name}
className="max-w-full h-auto mx-auto rounded"
onLoad={(e) => {
// Очищаем таймаут если изображение загрузилось
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 (
<div
key={uniqueKey}
className="absolute border-2 border-red-500 bg-red-500 bg-opacity-20 hover:bg-opacity-40 cursor-pointer transition-all duration-200"
style={{
left: `${scaledX}px`,
top: `${scaledY}px`,
width: `${scaledWidth}px`,
height: `${scaledHeight}px`,
borderRadius: coord.shape === 'circle' ? '50%' : '0'
}}
onClick={() => handleCoordinateClick(coord)}
title={detail ? `${coord.codeonimage}: ${detail.name}` : `Деталь ${coord.codeonimage}`}
>
<div className="absolute -top-6 left-1/2 transform -translate-x-1/2 bg-red-600 text-white text-xs px-2 py-1 rounded font-bold">
{coord.codeonimage}
</div>
</div>
);
})}
</div>
<div className="hidden bg-gray-100 border-2 border-dashed border-gray-300 rounded-lg p-8" id="image-placeholder">
<div className="text-gray-400 mb-2">
<svg className="w-12 h-12 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
<p className="text-sm text-gray-500">Изображение недоступно</p>
{process.env.NODE_ENV === 'development' && (
<p className="text-xs text-gray-400 mt-2">
URL: {getImageUrl(unitInfo.imageurl, selectedImageSize)}
</p>
)}
</div>
<p className="text-xs text-gray-500 mt-2">
Схема узла с номерами деталей
{unitImageMap?.coordinates && unitImageMap.coordinates.length > 0 && (
<span className="text-green-600 ml-2">
{unitImageMap.coordinates.length} интерактивных областей
</span>
)}
{(!unitImageMap?.coordinates || unitImageMap.coordinates.length === 0) && (
<span className="text-yellow-600 ml-2">
Интерактивные области не найдены
</span>
)}
</p>
{/* Отладочная информация */}
{process.env.NODE_ENV === 'development' && unitImageMap && (
<div className="mt-2 p-2 bg-gray-100 rounded text-xs">
<p><strong>Отладка:</strong></p>
<p>Unit ID: {unitImageMap.unitid}</p>
<p>Координат: {unitImageMap.coordinates?.length || 0}</p>
<p>Масштаб: x={imageScale.x.toFixed(3)}, y={imageScale.y.toFixed(3)}</p>
{unitImageMap.coordinates?.map((coord, i) => (
<p key={`debug-coord-${unitId}-${i}`}>
Область {i+1}: код={coord.codeonimage}, x={coord.x}, y={coord.y}, w={coord.width}, h={coord.height}
</p>
))}
</div>
)}
</div>
)}
</div>
{/* Информация об узле */}
<div>
<h4 className="text-lg font-semibold text-gray-900 mb-4">
Информация об узле
</h4>
<dl className="space-y-3">
<div>
<dt className="text-sm font-medium text-gray-500">ID узла:</dt>
<dd className="text-sm text-gray-900">{unitInfo.unitid}</dd>
</div>
{unitInfo.code && (
<div>
<dt className="text-sm font-medium text-gray-500">Код:</dt>
<dd className="text-sm text-gray-900">{unitInfo.code}</dd>
</div>
)}
{unitInfo.description && (
<div>
<dt className="text-sm font-medium text-gray-500">Описание:</dt>
<dd className="text-sm text-gray-900">{unitInfo.description}</dd>
</div>
)}
<div>
<dt className="text-sm font-medium text-gray-500">Каталог:</dt>
<dd className="text-sm text-gray-900">{catalogCode}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Автомобиль:</dt>
<dd className="text-sm text-gray-900">ID: {vehicleId}</dd>
</div>
</dl>
{/* Дополнительные атрибуты узла */}
{unitInfo.attributes && unitInfo.attributes.length > 0 && (
<div className="mt-6">
<h5 className="text-sm font-medium text-gray-900 mb-3">Дополнительная информация</h5>
<dl className="space-y-2">
{unitInfo.attributes.map((attr, attrIndex) => (
<div key={`unit-attr-${unitId}-${attrIndex}-${attr.key}`} className="flex">
<dt className="text-sm text-gray-500 w-1/3">{attr.name || attr.key}:</dt>
<dd className="text-sm text-gray-900 w-2/3">{attr.value}</dd>
</div>
))}
</dl>
</div>
)}
</div>
</div>
</div>
{/* Список деталей */}
<div className="bg-white border border-gray-200 rounded-lg p-6">
<div className="flex items-center justify-between mb-4">
<h4 className="text-lg font-semibold text-gray-900">
Детали узла ({unitDetails.length})
</h4>
{unitDetailsLoading && (
<div className="flex items-center text-sm text-gray-500">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-red-600 mr-2"></div>
Загружаем детали...
</div>
)}
</div>
{unitDetailsError && (
<div className="mb-4 p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
<p className="text-sm text-yellow-800">
Ошибка загрузки деталей: {unitDetailsError.message}
</p>
</div>
)}
{unitDetails.length === 0 && !unitDetailsLoading ? (
<div className="text-center py-8">
<div className="text-gray-400 mb-2">
<svg className="w-8 h-8 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<p className="text-gray-500">Детали узла не найдены</p>
{/* Отладочная информация для деталей */}
{process.env.NODE_ENV === 'development' && (
<div className="mt-4 p-3 bg-yellow-50 border border-yellow-200 rounded text-xs text-left">
<p><strong>Отладка деталей:</strong></p>
<p>Ошибка загрузки: {unitDetailsError?.message || 'нет'}</p>
<p>Загружается: {unitDetailsLoading ? 'да' : 'нет'}</p>
<p>Количество деталей: {unitDetails.length}</p>
</div>
)}
</div>
) : (
<div className="space-y-4">
{unitDetails.map((detail, index) => (
<div
key={`detail-${unitId}-${index}-${detail.detailid}`}
className="border border-gray-200 rounded-lg p-4 hover:border-red-300 hover:shadow-md transition-all duration-200 cursor-pointer"
onClick={() => handleDetailClick(detail)}
>
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center space-x-3 mb-2">
{detail.codeonimage && (
<span className="inline-flex items-center justify-center w-6 h-6 bg-red-600 text-white text-xs font-bold rounded-full">
{detail.codeonimage}
</span>
)}
<h5 className="font-medium text-gray-900">{detail.name}</h5>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3 text-sm">
{detail.oem && (
<div>
<span className="text-gray-500">OEM:</span>
<span className="ml-1 font-medium text-gray-900">{detail.oem}</span>
</div>
)}
{detail.brand && (
<div>
<span className="text-gray-500">Бренд:</span>
<span className="ml-1 font-medium text-gray-900">{detail.brand}</span>
</div>
)}
{detail.price && (
<div>
<span className="text-gray-500">Цена:</span>
<span className="ml-1 font-medium text-green-600">{detail.price} </span>
</div>
)}
{detail.availability && (
<div>
<span className="text-gray-500">Наличие:</span>
<span className={`ml-1 font-medium ${detail.availability === 'В наличии' ? 'text-green-600' : 'text-orange-600'}`}>
{detail.availability}
</span>
</div>
)}
</div>
{detail.note && (
<p className="text-sm text-gray-600 mt-2">{detail.note}</p>
)}
{/* Дополнительные атрибуты детали */}
{detail.attributes && detail.attributes.length > 0 && (
<div className="mt-3 pt-3 border-t border-gray-100">
<h6 className="text-xs font-medium text-gray-700 mb-2">Дополнительные характеристики:</h6>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-xs">
{detail.attributes.map((attr, attrIndex) => (
<div key={`attr-${unitId}-${index}-${attrIndex}-${attr.key}`} className="flex">
<span className="text-gray-500 w-1/2">{attr.name || attr.key}:</span>
<span className="text-gray-700 w-1/2">{attr.value}</span>
</div>
))}
</div>
</div>
)}
</div>
<div className="ml-4 text-gray-400">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</div>
))}
</div>
)}
</div>
{/* Информационное сообщение */}
<div className="mt-6 p-4 bg-green-50 border border-green-200 rounded-lg">
<div className="flex items-start">
<div className="flex-shrink-0">
<svg className="w-5 h-5 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
</div>
<div className="ml-3">
<h4 className="text-sm font-medium text-green-900">
Полная интеграция с Laximo API
</h4>
<p className="text-sm text-green-700 mt-1">
Компонент использует официальные API Laximo: GetUnitInfo для информации об узле,
ListDetailByUnit для получения деталей и ListImageMapByUnit для интерактивной карты изображений.
Нажмите на номера деталей на схеме или в списке для подробной информации.
</p>
</div>
</div>
</div>
{/* Модал выбора бренда */}
{selectedDetail && (
<BrandSelectionModal
isOpen={isBrandModalOpen}
onClose={handleCloseBrandModal}
articleNumber={selectedDetail.oem || ''}
detailName={selectedDetail.name}
/>
)}
</div>
);
};
export default UnitDetailsSection;