Compare commits
3 Commits
87339d577e
...
fix1407
Author | SHA1 | Date | |
---|---|---|---|
47844749eb | |||
d95d008c0c | |||
657016731c |
@ -1,270 +1,64 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { CookiePreferences, initializeAnalytics, initializeMarketing } from '@/lib/cookie-utils';
|
||||
import * as React from "react";
|
||||
|
||||
interface CookieConsentProps {
|
||||
onAccept?: () => void;
|
||||
onDecline?: () => void;
|
||||
onConfigure?: (preferences: CookiePreferences) => void;
|
||||
}
|
||||
const CookieConsent: React.FC = () => {
|
||||
const [isVisible, setIsVisible] = React.useState(false);
|
||||
|
||||
const CookieConsent: React.FC<CookieConsentProps> = ({ onAccept, onDecline, onConfigure }) => {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
const [preferences, setPreferences] = useState<CookiePreferences>({
|
||||
necessary: true, // Всегда включены
|
||||
analytics: false,
|
||||
marketing: false,
|
||||
functional: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Проверяем, есть ли уже согласие в localStorage
|
||||
React.useEffect(() => {
|
||||
const cookieConsent = localStorage.getItem('cookieConsent');
|
||||
if (!cookieConsent) {
|
||||
setIsVisible(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleAcceptAll = () => {
|
||||
const allAccepted = {
|
||||
necessary: true,
|
||||
analytics: true,
|
||||
marketing: true,
|
||||
functional: true,
|
||||
};
|
||||
const handleAccept = () => {
|
||||
localStorage.setItem('cookieConsent', 'accepted');
|
||||
localStorage.setItem('cookiePreferences', JSON.stringify(allAccepted));
|
||||
|
||||
// Инициализируем сервисы после согласия
|
||||
initializeAnalytics();
|
||||
initializeMarketing();
|
||||
|
||||
setIsVisible(false);
|
||||
onAccept?.();
|
||||
};
|
||||
|
||||
const handleDeclineAll = () => {
|
||||
const onlyNecessary = {
|
||||
necessary: true,
|
||||
analytics: false,
|
||||
marketing: false,
|
||||
functional: false,
|
||||
};
|
||||
localStorage.setItem('cookieConsent', 'declined');
|
||||
localStorage.setItem('cookiePreferences', JSON.stringify(onlyNecessary));
|
||||
setIsVisible(false);
|
||||
onDecline?.();
|
||||
};
|
||||
|
||||
const handleSavePreferences = () => {
|
||||
localStorage.setItem('cookieConsent', 'configured');
|
||||
localStorage.setItem('cookiePreferences', JSON.stringify(preferences));
|
||||
|
||||
// Инициализируем сервисы согласно настройкам
|
||||
if (preferences.analytics) {
|
||||
initializeAnalytics();
|
||||
}
|
||||
if (preferences.marketing) {
|
||||
initializeMarketing();
|
||||
}
|
||||
|
||||
setIsVisible(false);
|
||||
onConfigure?.(preferences);
|
||||
};
|
||||
|
||||
const togglePreference = (key: keyof CookiePreferences) => {
|
||||
if (key === 'necessary') return; // Необходимые cookies нельзя отключить
|
||||
setPreferences(prev => ({
|
||||
...prev,
|
||||
[key]: !prev[key]
|
||||
}));
|
||||
};
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 z-50 bg-white border-t border-gray-200 shadow-lg cookie-consent-enter">
|
||||
<div className="max-w-7xl mx-auto p-6 max-md:p-4">
|
||||
{!showDetails ? (
|
||||
// Основной вид
|
||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
||||
{/* Текст согласия */}
|
||||
<div className="flex-1">
|
||||
<div className="flex items-start gap-3">
|
||||
{/* Иконка cookie */}
|
||||
<div className="flex-shrink-0 mt-1">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className="text-gray-600">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1.5 3.5c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm3 2c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-6 1c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm2.5 3c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm4.5-1c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-2 4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-3.5-2c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1z" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-gray-950 mb-2">
|
||||
Мы используем файлы cookie
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 leading-relaxed">
|
||||
Наш сайт использует файлы cookie для улучшения работы сайта, персонализации контента и анализа трафика.
|
||||
Продолжая использовать сайт, вы соглашаетесь с нашей{' '}
|
||||
<>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Onest:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<div
|
||||
layer-name="cookie"
|
||||
className="box-border flex gap-16 justify-between items-center px-16 py-10 mx-auto my-0 w-full bg-white rounded-3xl shadow-sm max-w-[1240px] max-md:flex-col max-md:gap-10 max-md:px-10 max-md:py-8 max-md:text-center max-sm:gap-5 max-sm:p-5 max-sm:rounded-2xl fixed bottom-6 left-1/2 -translate-x-1/2 z-5000"
|
||||
>
|
||||
<div
|
||||
layer-name="Мы используем cookie-файлы, чтобы получить статистику, которая помогает нам улучшать сайт для Вас. Нажимая Принять, вы даёте согласие на использование ваших cookie-файлов. Подробнее о том, как мы используем ваши персональные данные, в нашей Политике обработки персональных данных."
|
||||
className="flex-1 text-base font-medium leading-5 text-red-600 max-w-[933px] max-md:max-w-full max-sm:text-sm"
|
||||
>
|
||||
<span className="text-base text-gray-600">
|
||||
Мы используем cookie-файлы, чтобы получить статистику, которая
|
||||
помогает нам улучшать сайт для Вас. Нажимая Принять, вы даёте
|
||||
согласие на использование ваших cookie-файлов. Подробнее о том, как
|
||||
мы используем ваши персональные данные, в нашей{' '}
|
||||
</span>
|
||||
<a
|
||||
href="/privacy-policy"
|
||||
className="text-red-600 hover:text-red-700 underline"
|
||||
className="text-base text-red-600 underline hover:text-red-700"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
политикой конфиденциальности
|
||||
Политике обработки персональных данных.
|
||||
</a>
|
||||
{' '}и использованием файлов cookie.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Кнопки */}
|
||||
<div className="flex flex-col sm:flex-row gap-3 md:flex-shrink-0">
|
||||
<button
|
||||
onClick={() => setShowDetails(true)}
|
||||
className="px-6 py-3 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors duration-200 min-w-[120px]"
|
||||
onClick={handleAccept}
|
||||
className="box-border flex gap-5 justify-center items-center px-8 py-4 bg-red-600 hover:bg-red-700 rounded-xl h-[51px] min-w-[126px] max-md:w-full max-md:max-w-[200px] max-sm:px-5 max-sm:py-3.5 max-sm:w-full max-sm:h-auto focus:outline-none focus:ring-2 focus:ring-red-400 transition-colors duration-200"
|
||||
>
|
||||
Настроить
|
||||
</button>
|
||||
<button
|
||||
onClick={handleDeclineAll}
|
||||
className="px-6 py-3 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors duration-200 min-w-[120px]"
|
||||
<span
|
||||
layer-name="Принять"
|
||||
className="text-base font-semibold leading-5 text-center text-white max-sm:text-sm"
|
||||
>
|
||||
Отклонить
|
||||
</button>
|
||||
<button
|
||||
onClick={handleAcceptAll}
|
||||
className="px-6 py-3 text-sm font-medium text-white bg-red-600 hover:bg-red-700 rounded-lg transition-colors duration-200 min-w-[120px]"
|
||||
>
|
||||
Принять все
|
||||
Принять
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
// Детальный вид с настройками
|
||||
<div className="space-y-6">
|
||||
{/* Заголовок */}
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-lg font-semibold text-gray-950">
|
||||
Настройки файлов cookie
|
||||
</h3>
|
||||
<button
|
||||
onClick={() => setShowDetails(false)}
|
||||
className="text-gray-500 hover:text-gray-700 p-1"
|
||||
>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<path d="M15 5L5 15M5 5l10 10" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Настройки cookies */}
|
||||
<div className="space-y-4">
|
||||
{/* Необходимые cookies */}
|
||||
<div className="flex items-start justify-between p-4 bg-gray-50 rounded-lg">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h4 className="font-medium text-gray-950">Необходимые cookies</h4>
|
||||
<span className="text-xs px-2 py-1 bg-gray-200 text-gray-600 rounded">Обязательные</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">
|
||||
Эти файлы cookie необходимы для работы сайта и не могут быть отключены.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 ml-4">
|
||||
<div className="w-12 h-6 bg-red-600 rounded-full flex items-center justify-end px-1">
|
||||
<div className="w-4 h-4 bg-white rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Аналитические cookies */}
|
||||
<div className="flex items-start justify-between p-4 bg-gray-50 rounded-lg">
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-950 mb-2">Аналитические cookies</h4>
|
||||
<p className="text-sm text-gray-600">
|
||||
Помогают нам понять, как посетители взаимодействуют с сайтом.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 ml-4">
|
||||
<button
|
||||
onClick={() => togglePreference('analytics')}
|
||||
className={`w-12 h-6 rounded-full flex items-center transition-colors duration-200 ${
|
||||
preferences.analytics ? 'bg-red-600 justify-end' : 'bg-gray-300 justify-start'
|
||||
} px-1`}
|
||||
>
|
||||
<div className="w-4 h-4 bg-white rounded-full"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Маркетинговые cookies */}
|
||||
<div className="flex items-start justify-between p-4 bg-gray-50 rounded-lg">
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-950 mb-2">Маркетинговые cookies</h4>
|
||||
<p className="text-sm text-gray-600">
|
||||
Используются для отслеживания посетителей и показа релевантной рекламы.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 ml-4">
|
||||
<button
|
||||
onClick={() => togglePreference('marketing')}
|
||||
className={`w-12 h-6 rounded-full flex items-center transition-colors duration-200 ${
|
||||
preferences.marketing ? 'bg-red-600 justify-end' : 'bg-gray-300 justify-start'
|
||||
} px-1`}
|
||||
>
|
||||
<div className="w-4 h-4 bg-white rounded-full"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Функциональные cookies */}
|
||||
<div className="flex items-start justify-between p-4 bg-gray-50 rounded-lg">
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-gray-950 mb-2">Функциональные cookies</h4>
|
||||
<p className="text-sm text-gray-600">
|
||||
Обеспечивают расширенную функциональность и персонализацию.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex-shrink-0 ml-4">
|
||||
<button
|
||||
onClick={() => togglePreference('functional')}
|
||||
className={`w-12 h-6 rounded-full flex items-center transition-colors duration-200 ${
|
||||
preferences.functional ? 'bg-red-600 justify-end' : 'bg-gray-300 justify-start'
|
||||
} px-1`}
|
||||
>
|
||||
<div className="w-4 h-4 bg-white rounded-full"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Кнопки действий */}
|
||||
<div className="flex flex-col sm:flex-row gap-3 pt-4 border-t border-gray-200">
|
||||
<button
|
||||
onClick={handleDeclineAll}
|
||||
className="px-6 py-3 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors duration-200 flex-1 sm:flex-initial min-w-[120px]"
|
||||
>
|
||||
Только необходимые
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSavePreferences}
|
||||
className="px-6 py-3 text-sm font-medium text-white bg-red-600 hover:bg-red-700 rounded-lg transition-colors duration-200 flex-1 sm:flex-initial min-w-[120px]"
|
||||
>
|
||||
Сохранить настройки
|
||||
</button>
|
||||
<button
|
||||
onClick={handleAcceptAll}
|
||||
className="px-6 py-3 text-sm font-medium text-white bg-red-600 hover:bg-red-700 rounded-lg transition-colors duration-200 flex-1 sm:flex-initial min-w-[120px]"
|
||||
>
|
||||
Принять все
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -273,6 +273,10 @@ const CoreProductCard: React.FC<CoreProductCardProps> = ({
|
||||
<>
|
||||
<div className="w-layout-hflex core-product-search-s1">
|
||||
<div className="w-layout-vflex flex-block-48-copy">
|
||||
<div className="w-layout-vflex product-list-search-s1">
|
||||
|
||||
<div className="w-layout-vflex flex-block-48-copy">
|
||||
|
||||
<div className="w-layout-vflex product-list-search-s1">
|
||||
<div className="w-layout-vflex core-product-s1">
|
||||
<div className="w-layout-vflex flex-block-47">
|
||||
@ -310,8 +314,6 @@ const CoreProductCard: React.FC<CoreProductCardProps> = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-layout-vflex flex-block-48-copy">
|
||||
<div className="w-layout-vflex product-list-search-s1">
|
||||
<div className="w-layout-hflex sort-list-s1">
|
||||
<div className="w-layout-hflex flex-block-49">
|
||||
<div className="sort-item first">Наличие</div>
|
||||
|
@ -88,7 +88,7 @@ const Filters: React.FC<FiltersProps> = ({
|
||||
if (filter.type === "range") {
|
||||
return (
|
||||
<FilterRange
|
||||
key={filter.title + idx}
|
||||
key={filter.title + idx + JSON.stringify((filterValues && filterValues[filter.title]) || null)}
|
||||
title={filter.title}
|
||||
min={filter.min}
|
||||
max={filter.max}
|
||||
|
@ -134,7 +134,7 @@ const FiltersPanelMobile: React.FC<FiltersPanelMobileProps> = ({
|
||||
if (filter.type === "range") {
|
||||
return (
|
||||
<FilterRange
|
||||
key={filter.title + idx}
|
||||
key={filter.title + idx + JSON.stringify(localFilterValues[filter.title] || null)}
|
||||
title={filter.title}
|
||||
min={filter.min}
|
||||
max={filter.max}
|
||||
|
@ -24,20 +24,24 @@ const FilterRange: React.FC<FilterRangeProps> = ({ title, min = DEFAULT_MIN, max
|
||||
const [open, setOpen] = useState(true);
|
||||
const trackRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Обновляем локальное состояние при изменении внешнего значения
|
||||
// Обновляем локальное состояние при изменении внешнего значения или границ
|
||||
useEffect(() => {
|
||||
if (value) {
|
||||
setFrom(String(value[0]));
|
||||
setTo(String(value[1]));
|
||||
setConfirmedFrom(value[0]);
|
||||
setConfirmedTo(value[1]);
|
||||
} else {
|
||||
setFrom(String(min));
|
||||
setTo(String(max));
|
||||
setConfirmedFrom(min);
|
||||
setConfirmedTo(max);
|
||||
let nextFrom = value ? value[0] : min;
|
||||
let nextTo = value ? value[1] : max;
|
||||
let changed = false;
|
||||
// Корректируем значения, если они вне новых границ
|
||||
if (nextFrom < min) { nextFrom = min; changed = true; }
|
||||
if (nextTo > max) { nextTo = max; changed = true; }
|
||||
if (nextFrom > nextTo) { nextFrom = nextTo; changed = true; }
|
||||
setFrom(String(nextFrom));
|
||||
setTo(String(nextTo));
|
||||
setConfirmedFrom(nextFrom);
|
||||
setConfirmedTo(nextTo);
|
||||
// Если значения были скорректированы, уведомляем родителя
|
||||
if (changed && onChange) {
|
||||
onChange([nextFrom, nextTo]);
|
||||
}
|
||||
}, [value, min, max]);
|
||||
}, [value, min, max, onChange]);
|
||||
|
||||
// Обновляем ширину полосы при монтировании и ресайзе
|
||||
useLayoutEffect(() => {
|
||||
|
@ -49,6 +49,16 @@ const ProductOfDaySection: React.FC = () => {
|
||||
.sort((a, b) => a.sortOrder - b.sortOrder);
|
||||
}, [data]);
|
||||
|
||||
// Корректный сброс currentSlide только если индекс вне диапазона
|
||||
useEffect(() => {
|
||||
if (currentSlide > activeProducts.length - 1) {
|
||||
setCurrentSlide(activeProducts.length > 0 ? activeProducts.length - 1 : 0);
|
||||
}
|
||||
// Если товаров стало больше и текущий слайд = 0, ничего не делаем
|
||||
// Если товаров стало меньше и текущий слайд в диапазоне, ничего не делаем
|
||||
// Если товаров стало меньше и текущий слайд вне диапазона, сбрасываем на последний
|
||||
}, [activeProducts.length]);
|
||||
|
||||
// Получаем данные из PartsIndex для текущего товара
|
||||
const currentProduct = activeProducts[currentSlide];
|
||||
const { data: partsIndexData } = useQuery(
|
||||
@ -132,11 +142,6 @@ const ProductOfDaySection: React.FC = () => {
|
||||
setCurrentSlide(index);
|
||||
};
|
||||
|
||||
// Сброс слайда при изменении товаров
|
||||
useEffect(() => {
|
||||
setCurrentSlide(0);
|
||||
}, [activeProducts]);
|
||||
|
||||
// Если нет активных товаров дня, не показываем секцию
|
||||
if (loading || error || activeProducts.length === 0) {
|
||||
return null;
|
||||
@ -244,7 +249,7 @@ const ProductOfDaySection: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{productImage && (
|
||||
<div className="relative">
|
||||
<div className="">
|
||||
<img
|
||||
width="Auto"
|
||||
height="Auto"
|
||||
|
@ -55,6 +55,7 @@ const KnotIn: React.FC<KnotInProps> = ({
|
||||
const [selectedDetail, setSelectedDetail] = useState<{ oem: string; name: string } | null>(null);
|
||||
const [hoveredCodeOnImage, setHoveredCodeOnImage] = useState<string | number | null>(null);
|
||||
const router = useRouter();
|
||||
const [isImageModalOpen, setIsImageModalOpen] = useState(false);
|
||||
|
||||
// Получаем инфо об узле (для картинки)
|
||||
console.log('🔍 KnotIn - GET_LAXIMO_UNIT_INFO запрос:', {
|
||||
@ -164,6 +165,12 @@ const KnotIn: React.FC<KnotInProps> = ({
|
||||
});
|
||||
};
|
||||
|
||||
// Обработчик клика по картинке (zoom)
|
||||
const handleImageClick = (e: React.MouseEvent<HTMLImageElement>) => {
|
||||
// Если клик был по точке, не открываем модалку (точки выше по z-index)
|
||||
setIsImageModalOpen(true);
|
||||
};
|
||||
|
||||
// Обработчик наведения на точку
|
||||
const handlePointHover = (coord: any) => {
|
||||
// Попробуем использовать разные поля для связи
|
||||
@ -318,8 +325,9 @@ const KnotIn: React.FC<KnotInProps> = ({
|
||||
loading="lazy"
|
||||
alt={unitName || unitInfo?.name || "Изображение узла"}
|
||||
onLoad={handleImageLoad}
|
||||
className="max-w-full h-auto mx-auto rounded"
|
||||
className="max-w-full h-auto mx-auto rounded cursor-zoom-in"
|
||||
style={{ maxWidth: 400, display: 'block' }}
|
||||
onClick={handleImageClick}
|
||||
/>
|
||||
{/* Точки/области */}
|
||||
{coordinates.map((coord: any, idx: number) => {
|
||||
@ -369,8 +377,8 @@ const KnotIn: React.FC<KnotInProps> = ({
|
||||
pointerEvents: 'auto',
|
||||
}}
|
||||
title={`${codeValue} (Клик - выделить в списке, двойной клик - перейти к выбору бренда)`}
|
||||
onClick={() => handlePointClick(coord)}
|
||||
onDoubleClick={() => handlePointDoubleClick(coord)}
|
||||
onClick={e => { e.stopPropagation(); handlePointClick(coord); }}
|
||||
onDoubleClick={e => { e.stopPropagation(); handlePointDoubleClick(coord); }}
|
||||
onMouseEnter={() => handlePointHover(coord)}
|
||||
onMouseLeave={() => {
|
||||
setHoveredCodeOnImage(null);
|
||||
@ -389,6 +397,30 @@ const KnotIn: React.FC<KnotInProps> = ({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{/* Модалка увеличенного изображения */}
|
||||
{isImageModalOpen && (
|
||||
<div
|
||||
className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/20 bg-opacity-70"
|
||||
onClick={() => setIsImageModalOpen(false)}
|
||||
style={{ cursor: 'zoom-out' }}
|
||||
>
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt={unitName || unitInfo?.name || "Изображение узла"}
|
||||
className="max-h-[90vh] max-w-[90vw] rounded shadow-lg"
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{ background: '#fff' }}
|
||||
/>
|
||||
<button
|
||||
onClick={() => setIsImageModalOpen(false)}
|
||||
className="absolute top-4 right-4 text-white text-3xl font-bold bg-black bg-opacity-40 rounded-full w-10 h-10 flex items-center justify-center"
|
||||
aria-label="Закрыть"
|
||||
style={{ zIndex: 10000 }}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{/* Модалка выбора бренда */}
|
||||
<BrandSelectionModal
|
||||
isOpen={isBrandModalOpen}
|
||||
|
@ -53,6 +53,7 @@
|
||||
|
||||
.flex-block-40 {
|
||||
background-color: #fff;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
input.text-block-31 {
|
||||
@ -364,6 +365,15 @@ input.input-receiver:focus {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.image-5-copy {
|
||||
width: 97px !important;
|
||||
height: 97px !important;
|
||||
}
|
||||
.flex-block-111 {
|
||||
width: 172px !important;
|
||||
}
|
||||
|
||||
|
||||
.show-more-btn {
|
||||
background-color: #ec1c24;
|
||||
color: #fff;
|
||||
@ -516,6 +526,9 @@ input#VinSearchInput {
|
||||
}
|
||||
}
|
||||
|
||||
.div-block-19{
|
||||
padding-left: 20px !important;
|
||||
}
|
||||
|
||||
.dropdown-toggle-card {
|
||||
align-self: stretch;
|
||||
@ -913,8 +926,8 @@ a.link-block-2.w-inline-block {
|
||||
|
||||
|
||||
.flex-block-15-copy {
|
||||
width: 235px!important;
|
||||
min-width: 235px!important;
|
||||
width: 232px!important;
|
||||
min-width: 232px!important;
|
||||
}
|
||||
|
||||
.nameitembp {
|
||||
@ -966,7 +979,16 @@ a.link-block-2.w-inline-block {
|
||||
|
||||
|
||||
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.flex-block-110 {
|
||||
flex-direction: row !important;
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
.image-5-copy {
|
||||
width: 75px !important;
|
||||
height: 75px !important;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.topmenub {
|
||||
display: none !important;
|
||||
|
Reference in New Issue
Block a user