Merge remote changes, resolve conflicts in BottomHead.tsx
This commit is contained in:
@ -1,12 +1,12 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { GET_PARTSINDEX_CATEGORIES, GET_NAVIGATION_CATEGORIES } from '@/lib/graphql';
|
import { GET_PARTSINDEX_CATEGORIES, GET_NAVIGATION_CATEGORIES } from '@/lib/graphql';
|
||||||
import { PartsIndexCatalogsData, PartsIndexCatalogsVariables, PartsIndexCatalog } from '@/types/partsindex';
|
import { PartsIndexCatalogsData, PartsIndexCatalogsVariables, PartsIndexCatalog } from '@/types/partsindex';
|
||||||
import { NavigationCategory } from '@/types';
|
import { NavigationCategory } from '@/types';
|
||||||
|
|
||||||
function useIsMobile(breakpoint = 767) {
|
function useIsMobile(breakpoint = 767) {
|
||||||
const [isMobile, setIsMobile] = React.useState(false);
|
const [isMobile, setIsMobile] = React.useState(false);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const check = () => setIsMobile(window.innerWidth <= breakpoint);
|
const check = () => setIsMobile(window.innerWidth <= breakpoint);
|
||||||
@ -15,12 +15,12 @@ function useIsMobile(breakpoint = 767) {
|
|||||||
return () => window.removeEventListener("resize", check);
|
return () => window.removeEventListener("resize", check);
|
||||||
}, [breakpoint]);
|
}, [breakpoint]);
|
||||||
return isMobile;
|
return isMobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Fallback статичные данные
|
// Fallback статичные данные
|
||||||
const fallbackTabData = [
|
const fallbackTabData = [
|
||||||
{
|
{
|
||||||
label: "Оригинальные каталоги",
|
label: "Оригинальные каталоги",
|
||||||
heading: "Оригинальные каталоги",
|
heading: "Оригинальные каталоги",
|
||||||
@ -66,10 +66,10 @@ const fallbackTabData = [
|
|||||||
"Промывочные жидкости",
|
"Промывочные жидкости",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Преобразуем данные PartsIndex в формат нашего меню
|
// Преобразуем данные PartsIndex в формат нашего меню
|
||||||
const transformPartsIndexToTabData = (catalogs: PartsIndexCatalog[]) => {
|
const transformPartsIndexToTabData = (catalogs: PartsIndexCatalog[]) => {
|
||||||
console.log('🔄 Преобразуем каталоги PartsIndex:', catalogs.length, 'элементов');
|
console.log('🔄 Преобразуем каталоги PartsIndex:', catalogs.length, 'элементов');
|
||||||
|
|
||||||
const transformed = catalogs.map(catalog => {
|
const transformed = catalogs.map(catalog => {
|
||||||
@ -79,29 +79,21 @@ const transformPartsIndexToTabData = (catalogs: PartsIndexCatalog[]) => {
|
|||||||
let links: string[] = [];
|
let links: string[] = [];
|
||||||
|
|
||||||
if (catalog.groups && catalog.groups.length > 0) {
|
if (catalog.groups && catalog.groups.length > 0) {
|
||||||
// Сначала собираем все подгруппы из всех групп
|
// Для каждой группы проверяем есть ли подгруппы
|
||||||
catalog.groups.forEach(group => {
|
catalog.groups.forEach(group => {
|
||||||
if (group.subgroups && group.subgroups.length > 0) {
|
if (group.subgroups && group.subgroups.length > 0) {
|
||||||
// Если есть подгруппы, добавляем их названия
|
// Если есть подгруппы, добавляем их названия
|
||||||
group.subgroups.forEach(subgroup => {
|
links.push(...group.subgroups.slice(0, 9 - links.length).map(subgroup => subgroup.name));
|
||||||
|
} else {
|
||||||
|
// Если подгрупп нет, добавляем название самой группы
|
||||||
if (links.length < 9) {
|
if (links.length < 9) {
|
||||||
links.push(subgroup.name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Если подгрупп не набралось достаточно, добавляем названия групп
|
|
||||||
if (links.length < 9) {
|
|
||||||
catalog.groups.forEach(group => {
|
|
||||||
if (links.length < 9 && !links.includes(group.name)) {
|
|
||||||
links.push(group.name);
|
links.push(group.name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Если подкатегорий всё ещё нет, добавляем название самой категории
|
// Если подкатегорий нет, показываем название категории как указано в требованиях
|
||||||
if (links.length === 0) {
|
if (links.length === 0) {
|
||||||
links = [catalog.name];
|
links = [catalog.name];
|
||||||
}
|
}
|
||||||
@ -118,10 +110,10 @@ const transformPartsIndexToTabData = (catalogs: PartsIndexCatalog[]) => {
|
|||||||
|
|
||||||
console.log('✅ Преобразование завершено:', transformed.length, 'табов');
|
console.log('✅ Преобразование завершено:', transformed.length, 'табов');
|
||||||
return transformed;
|
return transformed;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Функция для поиска иконки для категории
|
// Функция для поиска иконки для категории
|
||||||
const findCategoryIcon = (catalogId: string, navigationCategories: NavigationCategory[]): string | null => {
|
const findCategoryIcon = (catalogId: string, navigationCategories: NavigationCategory[]): string | null => {
|
||||||
console.log('🔍 Ищем иконку для catalogId:', catalogId);
|
console.log('🔍 Ищем иконку для catalogId:', catalogId);
|
||||||
console.log('📋 Доступные навигационные категории:', navigationCategories);
|
console.log('📋 Доступные навигационные категории:', navigationCategories);
|
||||||
|
|
||||||
@ -134,9 +126,9 @@ const findCategoryIcon = (catalogId: string, navigationCategories: NavigationCat
|
|||||||
console.log('🖼️ Возвращаемая иконка:', categoryIcon?.icon || null);
|
console.log('🖼️ Возвращаемая иконка:', categoryIcon?.icon || null);
|
||||||
|
|
||||||
return categoryIcon?.icon || null;
|
return categoryIcon?.icon || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => void }) => {
|
const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => void }) => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [mobileCategory, setMobileCategory] = useState<null | any>(null);
|
const [mobileCategory, setMobileCategory] = useState<null | any>(null);
|
||||||
@ -266,7 +258,35 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
|||||||
<span>{mobileCategory.label}</span>
|
<span>{mobileCategory.label}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mobile-subcategories">
|
<div className="mobile-subcategories">
|
||||||
{mobileCategory.links.map((link: string, linkIndex: number) => (
|
{mobileCategory.links.length === 1 ? (
|
||||||
|
<div
|
||||||
|
className="mobile-subcategory"
|
||||||
|
onClick={() => {
|
||||||
|
let subcategoryId = `${mobileCategory.catalogId}_0`;
|
||||||
|
if (mobileCategory.groups) {
|
||||||
|
for (const group of mobileCategory.groups) {
|
||||||
|
if (group.subgroups && group.subgroups.length > 0) {
|
||||||
|
const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === mobileCategory.links[0]);
|
||||||
|
if (foundSubgroup) {
|
||||||
|
subcategoryId = foundSubgroup.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (group.name === mobileCategory.links[0]) {
|
||||||
|
subcategoryId = group.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const activeCatalog = catalogsData?.partsIndexCategoriesWithGroups?.[tabData.findIndex(tab => tab === mobileCategory)];
|
||||||
|
const catalogId = activeCatalog?.id || 'fallback';
|
||||||
|
handleCategoryClick(catalogId, mobileCategory.links[0], subcategoryId);
|
||||||
|
}}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
Показать все
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
mobileCategory.links.map((link: string, linkIndex: number) => (
|
||||||
<div
|
<div
|
||||||
className="mobile-subcategory"
|
className="mobile-subcategory"
|
||||||
key={link}
|
key={link}
|
||||||
@ -293,7 +313,8 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
|||||||
>
|
>
|
||||||
{link}
|
{link}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@ -497,7 +518,35 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
|||||||
<h3 className="heading-16">{tab.heading}</h3>
|
<h3 className="heading-16">{tab.heading}</h3>
|
||||||
<div className="w-layout-hflex flex-block-92">
|
<div className="w-layout-hflex flex-block-92">
|
||||||
<div className="w-layout-vflex flex-block-91">
|
<div className="w-layout-vflex flex-block-91">
|
||||||
{tab.links.map((link: string, linkIndex: number) => {
|
{tab.links.length === 1 ? (
|
||||||
|
<div
|
||||||
|
className="link-2"
|
||||||
|
onClick={() => {
|
||||||
|
const catalog = catalogsData?.partsIndexCategoriesWithGroups?.[idx];
|
||||||
|
let subcategoryId = `fallback_${idx}_0`;
|
||||||
|
if (catalog?.groups) {
|
||||||
|
for (const group of catalog.groups) {
|
||||||
|
if (group.subgroups && group.subgroups.length > 0) {
|
||||||
|
const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === tab.links[0]);
|
||||||
|
if (foundSubgroup) {
|
||||||
|
subcategoryId = foundSubgroup.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (group.name === tab.links[0]) {
|
||||||
|
subcategoryId = group.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const catalogId = catalog?.id || 'fallback';
|
||||||
|
handleCategoryClick(catalogId, tab.links[0], subcategoryId);
|
||||||
|
}}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
Показать все
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
tab.links.map((link: string, linkIndex: number) => {
|
||||||
const catalog = catalogsData?.partsIndexCategoriesWithGroups?.[idx];
|
const catalog = catalogsData?.partsIndexCategoriesWithGroups?.[idx];
|
||||||
let subcategoryId = `fallback_${idx}_${linkIndex}`;
|
let subcategoryId = `fallback_${idx}_${linkIndex}`;
|
||||||
if (catalog?.groups) {
|
if (catalog?.groups) {
|
||||||
@ -527,7 +576,8 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
|||||||
{link}
|
{link}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-layout-vflex flex-block-91-copy">
|
<div className="w-layout-vflex flex-block-91-copy">
|
||||||
<img src="https://d3e54v103j8qbb.cloudfront.net/plugins/Basic/assets/placeholder.60f9b1840c.svg" loading="lazy" alt="" className="image-17" />
|
<img src="https://d3e54v103j8qbb.cloudfront.net/plugins/Basic/assets/placeholder.60f9b1840c.svg" loading="lazy" alt="" className="image-17" />
|
||||||
@ -543,6 +593,6 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
|||||||
</nav>
|
</nav>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BottomHead;
|
export default BottomHead;
|
@ -1,270 +1,64 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import * as React from "react";
|
||||||
import { CookiePreferences, initializeAnalytics, initializeMarketing } from '@/lib/cookie-utils';
|
|
||||||
|
|
||||||
interface CookieConsentProps {
|
const CookieConsent: React.FC = () => {
|
||||||
onAccept?: () => void;
|
const [isVisible, setIsVisible] = React.useState(false);
|
||||||
onDecline?: () => void;
|
|
||||||
onConfigure?: (preferences: CookiePreferences) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CookieConsent: React.FC<CookieConsentProps> = ({ onAccept, onDecline, onConfigure }) => {
|
React.useEffect(() => {
|
||||||
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
|
|
||||||
const cookieConsent = localStorage.getItem('cookieConsent');
|
const cookieConsent = localStorage.getItem('cookieConsent');
|
||||||
if (!cookieConsent) {
|
if (!cookieConsent) {
|
||||||
setIsVisible(true);
|
setIsVisible(true);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAcceptAll = () => {
|
const handleAccept = () => {
|
||||||
const allAccepted = {
|
|
||||||
necessary: true,
|
|
||||||
analytics: true,
|
|
||||||
marketing: true,
|
|
||||||
functional: true,
|
|
||||||
};
|
|
||||||
localStorage.setItem('cookieConsent', 'accepted');
|
localStorage.setItem('cookieConsent', 'accepted');
|
||||||
localStorage.setItem('cookiePreferences', JSON.stringify(allAccepted));
|
|
||||||
|
|
||||||
// Инициализируем сервисы после согласия
|
|
||||||
initializeAnalytics();
|
|
||||||
initializeMarketing();
|
|
||||||
|
|
||||||
setIsVisible(false);
|
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;
|
if (!isVisible) return null;
|
||||||
|
|
||||||
return (
|
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">
|
<link
|
||||||
{!showDetails ? (
|
href="https://fonts.googleapis.com/css2?family=Onest:wght@400;500;600;700&display=swap"
|
||||||
// Основной вид
|
rel="stylesheet"
|
||||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
/>
|
||||||
{/* Текст согласия */}
|
<div
|
||||||
<div className="flex-1">
|
layer-name="cookie"
|
||||||
<div className="flex items-start gap-3">
|
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"
|
||||||
{/* Иконка cookie */}
|
>
|
||||||
<div className="flex-shrink-0 mt-1">
|
<div
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className="text-gray-600">
|
layer-name="Мы используем cookie-файлы, чтобы получить статистику, которая помогает нам улучшать сайт для Вас. Нажимая Принять, вы даёте согласие на использование ваших cookie-файлов. Подробнее о том, как мы используем ваши персональные данные, в нашей Политике обработки персональных данных."
|
||||||
<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"/>
|
className="flex-1 text-base font-medium leading-5 text-red-600 max-w-[933px] max-md:max-w-full max-sm:text-sm"
|
||||||
</svg>
|
>
|
||||||
</div>
|
<span className="text-base text-gray-600">
|
||||||
|
Мы используем cookie-файлы, чтобы получить статистику, которая
|
||||||
<div>
|
помогает нам улучшать сайт для Вас. Нажимая Принять, вы даёте
|
||||||
<h3 className="text-lg font-semibold text-gray-950 mb-2">
|
согласие на использование ваших cookie-файлов. Подробнее о том, как
|
||||||
Мы используем файлы cookie
|
мы используем ваши персональные данные, в нашей{' '}
|
||||||
</h3>
|
</span>
|
||||||
<p className="text-sm text-gray-600 leading-relaxed">
|
|
||||||
Наш сайт использует файлы cookie для улучшения работы сайта, персонализации контента и анализа трафика.
|
|
||||||
Продолжая использовать сайт, вы соглашаетесь с нашей{' '}
|
|
||||||
<a
|
<a
|
||||||
href="/privacy-policy"
|
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"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
политикой конфиденциальности
|
Политике обработки персональных данных.
|
||||||
</a>
|
</a>
|
||||||
{' '}и использованием файлов cookie.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Кнопки */}
|
|
||||||
<div className="flex flex-col sm:flex-row gap-3 md:flex-shrink-0">
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowDetails(true)}
|
onClick={handleAccept}
|
||||||
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]"
|
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"
|
||||||
>
|
>
|
||||||
Настроить
|
<span
|
||||||
</button>
|
layer-name="Принять"
|
||||||
<button
|
className="text-base font-semibold leading-5 text-center text-white max-sm:text-sm"
|
||||||
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]"
|
|
||||||
>
|
>
|
||||||
Отклонить
|
Принять
|
||||||
</button>
|
</span>
|
||||||
<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]"
|
|
||||||
>
|
|
||||||
Принять все
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user