fix11072025
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import VehicleAttributesTooltip from './VehicleAttributesTooltip';
|
||||
|
||||
interface VehicleAttribute {
|
||||
key: string;
|
||||
@ -206,42 +207,14 @@ const InfoVin: React.FC<InfoVinProps> = ({
|
||||
</section>
|
||||
|
||||
{/* Tooltip с фиксированным позиционированием */}
|
||||
{showTooltip && vehicleAttributes.length > 0 && (
|
||||
<div
|
||||
className="fixed w-[500px] max-w-[90vw] bg-white border border-gray-200 rounded-lg shadow-xl z-[9999] p-4 animate-in fade-in-0 zoom-in-95 duration-200"
|
||||
style={{
|
||||
left: `${tooltipPosition.x}px`,
|
||||
top: `${tooltipPosition.y}px`,
|
||||
}}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
{/* Заголовок */}
|
||||
<div className="mb-3 pb-2 border-b border-gray-100">
|
||||
<h3 className="text-sm font-semibold text-gray-900">
|
||||
Полная информация об автомобиле
|
||||
</h3>
|
||||
<p className="text-xs text-gray-600 mt-1">{vehicleName}</p>
|
||||
</div>
|
||||
|
||||
{/* Атрибуты в сетке */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{vehicleAttributes.map((attr, index) => (
|
||||
<div key={index} className="flex flex-col">
|
||||
<dt className="text-xs font-medium text-gray-500 mb-1">{attr.name}</dt>
|
||||
<dd className="text-xs text-gray-900 break-words">{attr.value}</dd>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Подвал */}
|
||||
<div className="mt-3 pt-2 border-t border-gray-100">
|
||||
<div className="text-xs text-gray-500 text-center">
|
||||
Всего параметров: {vehicleAttributes.length}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<VehicleAttributesTooltip
|
||||
show={showTooltip && vehicleAttributes.length > 0}
|
||||
position={tooltipPosition}
|
||||
vehicleName={vehicleName}
|
||||
vehicleAttributes={vehicleAttributes}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
interface KnotPartsProps {
|
||||
@ -195,7 +195,7 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
return (
|
||||
<>
|
||||
{/* Статус выбранных деталей */}
|
||||
{selectedParts.size > 0 && (
|
||||
{/* {selectedParts.size > 0 && (
|
||||
<div className="bg-green-50 border border-green-200 rounded-lg p-3 mb-4">
|
||||
<div className="flex items-center">
|
||||
<svg className="w-5 h-5 text-green-600 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@ -209,7 +209,7 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)} */}
|
||||
|
||||
<div className="knot-parts">
|
||||
{parts.map((part, idx) => {
|
||||
@ -226,11 +226,11 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={uniqueKey}
|
||||
className={`part-item p-4 border rounded-lg cursor-pointer transition-colors ${
|
||||
className={`w-layout-hflex knotlistitem rounded-lg cursor-pointer transition-colors ${
|
||||
isSelected
|
||||
? 'bg-green-100 border-green-500'
|
||||
: isHighlighted
|
||||
? 'bg-yellow-100 border-yellow-500'
|
||||
? 'bg-slate-200'
|
||||
: 'bg-white border-gray-200 hover:border-gray-300'
|
||||
}`}
|
||||
onClick={() => handlePartClick(part)}
|
||||
@ -240,13 +240,13 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
>
|
||||
<div className="w-layout-hflex flex-block-116">
|
||||
<div
|
||||
className={`nuberlist ${isSelected ? 'text-green-700 font-bold' : isHighlighted ? 'text-red-700 font-bold' : ''}`}
|
||||
className={`nuberlist ${isSelected ? 'text-green-700 font-bold' : isHighlighted ? ' font-bold' : ''}`}
|
||||
>
|
||||
{part.codeonimage || idx + 1}
|
||||
</div>
|
||||
<div className="oemnuber">{part.oem}</div>
|
||||
<div className={`oemnuber ${isSelected ? 'text-green-800 font-semibold' : isHighlighted ? ' font-semibold' : ''}`}>{part.oem}</div>
|
||||
</div>
|
||||
<div className={`partsname ${isSelected ? 'text-green-800 font-semibold' : isHighlighted ? 'text-red-800 font-semibold' : ''}`}>
|
||||
<div className={`partsname ${isSelected ? 'text-green-800 font-semibold' : isHighlighted ? ' font-semibold' : ''}`}>
|
||||
{part.name}
|
||||
</div>
|
||||
<div className="w-layout-hflex flex-block-117">
|
||||
@ -279,82 +279,45 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
{/* Красивый тултип с информацией о детали */}
|
||||
{showTooltip && tooltipPart && (
|
||||
<div
|
||||
className="tooltip-detail-modern"
|
||||
className="flex overflow-hidden flex-col items-center px-8 py-8 bg-slate-50 shadow-[0px_0px_20px_rgba(0,0,0,0.15)] rounded-2xl w-[350px] min-h-[220px] max-w-full fixed z-[9999]"
|
||||
style={{
|
||||
position: 'fixed',
|
||||
left: tooltipPosition.x,
|
||||
top: tooltipPosition.y,
|
||||
zIndex: 1000,
|
||||
pointerEvents: 'none'
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
>
|
||||
<div className="tooltip-content-modern">
|
||||
{/* Стрелка тултипа */}
|
||||
<div className="tooltip-arrow"></div>
|
||||
|
||||
{/* Заголовок */}
|
||||
<div className="tooltip-header-modern">
|
||||
<div className="tooltip-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 2L13.09 8.26L20 9L13.09 9.74L12 16L10.91 9.74L4 9L10.91 8.26L12 2Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="tooltip-title-section">
|
||||
<h4 className="tooltip-title">{tooltipPart.name}</h4>
|
||||
{tooltipPart.oem && (
|
||||
<div className="tooltip-oem-badge">
|
||||
<span className="tooltip-oem-label">OEM</span>
|
||||
<span className="tooltip-oem-value">{tooltipPart.oem}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Контент */}
|
||||
<div className="tooltip-body-modern">
|
||||
{tooltipPart.attributes && tooltipPart.attributes.length > 0 ? (
|
||||
<div className="tooltip-attributes-modern">
|
||||
<div className="tooltip-section-title">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 12L11 14L15 10M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
Характеристики
|
||||
</div>
|
||||
<div className="tooltip-attributes-grid">
|
||||
{tooltipPart.attributes.map((attr: any, index: number) => (
|
||||
<div key={index} className="tooltip-attribute-item">
|
||||
<div className="tooltip-attribute-key">{attr.name || attr.key}</div>
|
||||
<div className="tooltip-attribute-value">{attr.value}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="tooltip-no-data">
|
||||
<div className="tooltip-no-data-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 9V13M12 17H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="tooltip-no-data-text">
|
||||
<div>Дополнительная информация</div>
|
||||
<div>недоступна</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tooltipPart.note && (
|
||||
<div className="tooltip-note-modern">
|
||||
<div className="tooltip-section-title">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 7H13V9H11V7ZM11 11H13V17H11V11ZM12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z" fill="currentColor"/>
|
||||
</svg>
|
||||
Примечание
|
||||
</div>
|
||||
<div className="tooltip-note-text">{tooltipPart.note}</div>
|
||||
</div>
|
||||
<div className="flex relative flex-col w-full">
|
||||
{/* Заголовок и OEM */}
|
||||
<div className="mb-4">
|
||||
<div className="font-semibold text-lg text-black mb-1 truncate">{tooltipPart.name}</div>
|
||||
{tooltipPart.oem && (
|
||||
<div className="inline-block bg-gray-100 text-gray-700 text-xs font-mono px-2 py-1 rounded mb-1">OEM: {tooltipPart.oem}</div>
|
||||
)}
|
||||
</div>
|
||||
{/* Характеристики */}
|
||||
{tooltipPart.attributes && tooltipPart.attributes.length > 0 ? (
|
||||
tooltipPart.attributes.map((attr: any, idx: number) => (
|
||||
<div key={idx} className="flex gap-5 items-center mt-2 w-full whitespace-normal first:mt-0">
|
||||
<div className="self-stretch my-auto text-gray-400 w-[150px] break-words">
|
||||
{attr.name || attr.key}
|
||||
</div>
|
||||
<div className="self-stretch my-auto font-medium text-black break-words">
|
||||
{attr.value}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center w-full py-8">
|
||||
<div className="text-gray-400 mb-2">Дополнительная информация недоступна</div>
|
||||
</div>
|
||||
)}
|
||||
{tooltipPart.note && (
|
||||
<div className="flex flex-col mt-6 w-full">
|
||||
<div className="text-gray-400 text-xs mb-1">Примечание</div>
|
||||
<div className="font-medium text-black text-sm">{tooltipPart.note}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
63
src/components/vin/VehicleAttributesTooltip.tsx
Normal file
63
src/components/vin/VehicleAttributesTooltip.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
|
||||
interface VehicleAttribute {
|
||||
key: string;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface VehicleAttributesTooltipProps {
|
||||
show: boolean;
|
||||
position: { x: number; y: number };
|
||||
vehicleName?: string;
|
||||
vehicleAttributes: VehicleAttribute[];
|
||||
onMouseEnter?: () => void;
|
||||
onMouseLeave?: () => void;
|
||||
imageUrl?: string; // опционально, для будущего
|
||||
}
|
||||
|
||||
const VehicleAttributesTooltip: React.FC<VehicleAttributesTooltipProps> = ({
|
||||
show,
|
||||
position,
|
||||
vehicleAttributes,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
imageUrl,
|
||||
}) => {
|
||||
if (!show) return null;
|
||||
return (
|
||||
<div
|
||||
className="flex overflow-hidden flex-col items-center px-8 py-8 bg-slate-50 shadow-[0px_0px_20px_rgba(0,0,0,0.15)] rounded-2xl w-[450px] min-h-[365px] max-w-full fixed z-[9999]"
|
||||
style={{
|
||||
left: `${position.x + 120}px`,
|
||||
top: `${position.y}px`,
|
||||
}}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
{/* Фоновое изображение, если будет нужно */}
|
||||
{imageUrl && (
|
||||
<img
|
||||
loading="lazy"
|
||||
src={imageUrl}
|
||||
className="object-cover absolute inset-0 size-full rounded-2xl opacity-10 pointer-events-none"
|
||||
alt="vehicle background"
|
||||
/>
|
||||
)}
|
||||
<div className="flex relative flex-col w-full">
|
||||
{vehicleAttributes.map((attr, idx) => (
|
||||
<div key={idx} className="flex gap-5 items-center mt-2 w-full whitespace-nowrap first:mt-0">
|
||||
<div className="self-stretch my-auto text-gray-400 w-[150px] truncate">
|
||||
{attr.name}
|
||||
</div>
|
||||
<div className="self-stretch my-auto font-medium text-black truncate">
|
||||
{attr.value}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VehicleAttributesTooltip;
|
Reference in New Issue
Block a user