Добавлено получение баннеров для главного слайдера с использованием GraphQL. Обновлен компонент HeroSlider для отображения активных баннеров с сортировкой. Реализована логика отображения дефолтного баннера при отсутствии данных. Обновлены стили и структура компонента для улучшения пользовательского интерфейса.

This commit is contained in:
Bivekich
2025-07-15 09:03:32 +03:00
parent 9c152501db
commit 3e98f8fed6
19 changed files with 1109 additions and 342 deletions

View File

@ -1,39 +1,141 @@
import React from "react";
import { useQuery } from '@apollo/client';
import { GET_PARTSINDEX_CATEGORIES } from '@/lib/graphql';
import { useRouter } from 'next/router';
const CategoryNavSection: React.FC = () => (
<section className="catnav">
<div className="w-layout-blockcontainer batd w-container">
<div className="w-layout-hflex flex-block-108-copy">
<div className="ci1">
<div className="text-block-54-copy">Детали для ТО</div>
interface PartsIndexCatalog {
id: string;
name: string;
image?: string;
groups?: PartsIndexGroup[];
}
interface PartsIndexGroup {
id: string;
name: string;
image?: string;
subgroups?: PartsIndexSubgroup[];
entityNames?: { id: string; name: string }[];
}
interface PartsIndexSubgroup {
id: string;
name: string;
image?: string;
entityNames?: { id: string; name: string }[];
}
const CategoryNavSection: React.FC = () => {
const router = useRouter();
const { data, loading, error } = useQuery<{ partsIndexCategoriesWithGroups: PartsIndexCatalog[] }>(
GET_PARTSINDEX_CATEGORIES,
{
variables: {
lang: 'ru'
},
errorPolicy: 'all',
fetchPolicy: 'cache-first'
}
);
// Обработчик клика по категории для перехода в каталог с товарами
const handleCategoryClick = (catalog: PartsIndexCatalog) => {
console.log('🔍 Клик по категории:', { catalogId: catalog.id, categoryName: catalog.name });
// Получаем первую группу для groupId (это правильный ID для partsIndexCategory)
const firstGroup = catalog.groups?.[0];
const groupId = firstGroup?.id;
console.log('🔍 Найденная группа:', { groupId, groupName: firstGroup?.name });
// Переходим на страницу каталога с параметрами PartsIndex
router.push({
pathname: '/catalog',
query: {
partsIndexCatalog: catalog.id,
categoryName: encodeURIComponent(catalog.name),
...(groupId && { partsIndexCategory: groupId })
}
});
};
// Fallback данные на случай ошибки
const fallbackCategories = [
{ id: '1', name: 'Двигатель', image: '/images/catalog_item.png' },
{ id: '2', name: 'Трансмиссия', image: '/images/catalog_item2.png' },
{ id: '3', name: 'Подвеска', image: '/images/catalog_item3.png' },
{ id: '4', name: 'Тормоза', image: '/images/catalog_item4.png' },
{ id: '5', name: 'Электрика', image: '/images/catalog_item5.png' },
{ id: '6', name: 'Кузов', image: '/images/catalog_item6.png' },
{ id: '7', name: 'Салон', image: '/images/catalog_item7.png' },
{ id: '8', name: 'Климат', image: '/images/catalog_item8.png' },
{ id: '9', name: 'Расходники', image: '/images/catalog_item9.png' }
];
// Используем данные из API или fallback
const categories = data?.partsIndexCategoriesWithGroups || [];
const displayCategories = categories.length > 0 ? categories : fallbackCategories;
if (loading) {
return (
<div className="w-layout-blockcontainer container-2 w-container">
<div className="w-layout-hflex flex-block-6">
{Array.from({ length: 9 }).map((_, index) => (
<div key={index} className="w-layout-vflex flex-block-7">
<div className="animate-pulse bg-gray-200 h-6 w-20 rounded mb-2"></div>
</div>
))}
</div>
<div className="ci2">
<div className="text-block-54">Шины</div>
</div>
<div className="ci3">
<div className="text-block-54">Диски</div>
</div>
<div className="ci4">
<div className="text-block-54">Масла и жидкости</div>
</div>
<div className="ci5">
<div className="text-block-54">Инструменты</div>
</div>
<div className="ci6">
<div className="text-block-54">Автохимия</div>
</div>
<div className="ci7">
<div className="text-block-54">Аксессуары</div>
</div>
<div className="ci8">
<div className="text-block-54">Электрика</div>
</div>
<div className="ci9">
<div className="text-block-54">АКБ</div>
<div className="w-layout-hflex flex-block-5">
{Array.from({ length: 9 }).map((_, index) => (
<div key={index} className="w-layout-vflex flex-block-8">
<div className="animate-pulse bg-gray-200 h-32 w-full rounded"></div>
</div>
))}
</div>
</div>
);
}
return (
<div className="w-layout-blockcontainer container-2 w-container">
{/* Навигационная панель с названиями категорий */}
<div className="w-layout-hflex flex-block-6">
{displayCategories.slice(0, 9).map((catalog) => (
<div key={catalog.id} className="w-layout-vflex flex-block-7">
<div
className="text-block-10"
onClick={() => handleCategoryClick(catalog)}
style={{ cursor: 'pointer' }}
>
{catalog.name}
</div>
</div>
))}
</div>
{/* Блок с изображениями категорий */}
<div className="w-layout-hflex flex-block-5">
{displayCategories.slice(0, 9).map((catalog) => (
<div key={catalog.id} className="w-layout-vflex flex-block-8">
<img
src={catalog.image || '/images/catalog_item.png'}
loading="lazy"
alt={catalog.name}
className="image-5"
onClick={() => handleCategoryClick(catalog)}
style={{ cursor: 'pointer' }}
onError={(e) => {
const target = e.target as HTMLImageElement;
target.src = '/images/catalog_item.png';
}}
/>
</div>
))}
</div>
</div>
</section>
);
);
};
export default CategoryNavSection;

View File

@ -1,6 +1,23 @@
import React, { useEffect } from "react";
import { useQuery } from '@apollo/client';
import { GET_HERO_BANNERS } from '@/lib/graphql';
import Link from 'next/link';
interface HeroBanner {
id: string;
title: string;
subtitle?: string;
imageUrl: string;
linkUrl?: string;
isActive: boolean;
sortOrder: number;
}
const HeroSlider = () => {
const { data, loading, error } = useQuery(GET_HERO_BANNERS, {
errorPolicy: 'all'
});
useEffect(() => {
if (typeof window !== "undefined" && window.Webflow && window.Webflow.require) {
if (window.Webflow.destroy) {
@ -12,118 +29,152 @@ const HeroSlider = () => {
}
}, []);
// Фильтруем только активные баннеры и сортируем их
const banners: HeroBanner[] = data?.heroBanners
?.filter((banner: HeroBanner) => banner.isActive)
?.slice()
?.sort((a: HeroBanner, b: HeroBanner) => a.sortOrder - b.sortOrder) || [];
// Если нет данных или происходит загрузка, показываем дефолтный баннер
if (loading || error || banners.length === 0) {
return (
<section className="section-5" style={{ overflow: 'hidden' }}>
<div className="w-layout-blockcontainer container w-container">
<div data-delay="4000" data-animation="slide" className="slider w-slider" data-autoplay="false" data-easing="ease"
data-hide-arrows="false" data-disable-swipe="false" data-autoplay-limit="0" data-nav-spacing="3"
data-duration="500" data-infinite="true">
<div className="mask w-slider-mask">
<div className="slide w-slide">
<div className="w-layout-vflex flex-block-100">
<div className="div-block-35">
<img src="/images/imgfb.png" loading="lazy"
sizes="(max-width: 767px) 100vw, (max-width: 991px) 728px, 940px"
srcSet="/images/imgfb-p-500.png 500w, /images/imgfb-p-800.png 800w, /images/imgfb.png 1027w"
alt="Автозапчасти ProteK"
className="image-21" />
</div>
<div className="w-layout-vflex flex-block-99">
<h2 className="heading-17">ШИРОКИЙ ВЫБОР АВТОЗАПЧАСТЕЙ</h2>
<div className="text-block-51">
Сотрудничаем только с проверенными поставщиками. Постоянно обновляем
ассортимент, чтобы предложить самые лучшие и актуальные детали.
</div>
</div>
<div className="w-layout-hflex flex-block-101">
<div className="w-layout-hflex flex-block-102">
<img src="/images/1.png" loading="lazy" alt="" className="image-20" />
<div className="text-block-52">Быстрая доставка по всей стране</div>
</div>
<div className="w-layout-hflex flex-block-102">
<img src="/images/2.png" loading="lazy" alt="" className="image-20" />
<div className="text-block-52">Высокое качество продукции</div>
</div>
<div className="w-layout-hflex flex-block-102">
<img src="/images/3.png" loading="lazy" alt="" className="image-20" />
<div className="text-block-52">Выгодные цены</div>
</div>
<div className="w-layout-hflex flex-block-102">
<img src="/images/4.png" loading="lazy" alt="" className="image-20" />
<div className="text-block-52">Профессиональная консультация</div>
</div>
</div>
</div>
</div>
</div>
<div className="left-arrow w-slider-arrow-left">
<div className="div-block-34">
<div className="icon-2 w-icon-slider-left"></div>
</div>
</div>
<div className="right-arrow w-slider-arrow-right">
<div className="div-block-34">
<div className="icon-2 w-icon-slider-right"></div>
</div>
</div>
<div className="slide-nav w-slider-nav w-slider-nav-invert w-round"></div>
</div>
</div>
</section>
);
}
const renderSlide = (banner: HeroBanner) => {
const slideContent = (
<div className="w-layout-vflex flex-block-100">
<div className="div-block-35">
<img
src={banner.imageUrl}
loading="lazy"
sizes="(max-width: 767px) 100vw, (max-width: 991px) 728px, 940px"
alt={banner.title}
className="image-21"
/>
</div>
<div className="w-layout-vflex flex-block-99">
<h2 className="heading-17">{banner.title}</h2>
{banner.subtitle && (
<div className="text-block-51">{banner.subtitle}</div>
)}
</div>
</div>
);
// Если есть ссылка, оборачиваем в Link
if (banner.linkUrl) {
return (
<Link href={banner.linkUrl} className="slide w-slide" style={{ cursor: 'pointer' }}>
{slideContent}
</Link>
);
}
return (
<div className="slide w-slide">
{slideContent}
</div>
);
};
return (
<section className="section-5">
<section className="section-5" style={{ overflow: 'hidden' }}>
<div className="w-layout-blockcontainer container w-container">
<div data-delay="4000" data-animation="slide" className="slider w-slider" data-autoplay="false" data-easing="ease"
data-hide-arrows="false" data-disable-swipe="false" data-autoplay-limit="0" data-nav-spacing="3"
data-duration="500" data-infinite="true">
<div
data-delay="4000"
data-animation="slide"
className="slider w-slider"
data-autoplay="true"
data-easing="ease"
data-hide-arrows="false"
data-disable-swipe="false"
data-autoplay-limit="0"
data-nav-spacing="3"
data-duration="500"
data-infinite="true"
>
<div className="mask w-slider-mask">
<div className="slide w-slide">
<div className="w-layout-vflex flex-block-100">
<div className="div-block-35"><img src="/images/imgfb.png" loading="lazy"
sizes="(max-width: 767px) 100vw, (max-width: 991px) 728px, 940px"
srcSet="/images/imgfb-p-500.png 500w, /images/imgfb-p-800.png 800w, /images/imgfb.png 1027w" alt=""
className="image-21" /></div>
<div className="w-layout-vflex flex-block-99">
<h2 className="heading-17">ШИРОКИЙ ВЫБОР АВТОЗАПЧАСТЕЙ</h2>
<div className="text-block-51">Сотрудничаем только с проверенными поставщиками.Постоянно обновляем
ассортимент, чтобы предложить самые лучшие и актуальные детали.</div>
</div>
<div className="w-layout-hflex flex-block-101">
<div className="w-layout-hflex flex-block-102"><img src="/images/1.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Быстрая доставка по всей стране</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/2.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Высокое качество продукции</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/3.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Выгодные цены</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/4.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Профессиональная консультация</div>
</div>
{banners.map((banner) => (
<React.Fragment key={banner.id}>
{renderSlide(banner)}
</React.Fragment>
))}
</div>
{/* Показываем стрелки и навигацию только если баннеров больше одного */}
{banners.length > 1 && (
<>
<div className="left-arrow w-slider-arrow-left">
<div className="div-block-34">
<div className="icon-2 w-icon-slider-left"></div>
</div>
</div>
</div>
<div className="w-slide">
<div className="w-layout-vflex flex-block-100">
<div className="div-block-35"><img src="/images/imgfb.png" loading="lazy"
sizes="(max-width: 767px) 100vw, (max-width: 991px) 728px, 940px"
srcSet="/images/imgfb-p-500.png 500w, /images/imgfb-p-800.png 800w, /images/imgfb.png 1027w" alt=""
className="image-21" /></div>
<div className="w-layout-vflex flex-block-99">
<h2 className="heading-17">УЗКИЙ ВЫБОР АВТОЗАПЧАСТЕЙ</h2>
<div className="text-block-51">Сотрудничаем только с проверенными поставщиками.Постоянно обновляем
ассортимент, чтобы предложить самые лучшие и актуальные детали.</div>
</div>
<div className="w-layout-hflex flex-block-101">
<div className="w-layout-hflex flex-block-102"><img src="/images/1.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Быстрая доставка по всей стране</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/2.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Высокое качество продукции</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/3.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Выгодные цены</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/4.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Профессиональная консультация</div>
</div>
<div className="right-arrow w-slider-arrow-right">
<div className="div-block-34">
<div className="icon-2 w-icon-slider-right"></div>
</div>
</div>
</div>
<div className="w-slide">
<div className="w-layout-vflex flex-block-100">
<div className="div-block-35"><img src="/images/imgfb.png" loading="lazy"
sizes="(max-width: 767px) 100vw, (max-width: 991px) 728px, 940px"
srcSet="/images/imgfb-p-500.png 500w, /images/imgfb-p-800.png 800w, /images/imgfb.png 1027w" alt=""
className="image-21" /></div>
<div className="w-layout-vflex flex-block-99">
<h2 className="heading-17">ЛУЧШИЙ ВЫБОР АВТОЗАПЧАСТЕЙ</h2>
<div className="text-block-51">Сотрудничаем только с проверенными поставщиками.Постоянно обновляем
ассортимент, чтобы предложить самые лучшие и актуальные детали.</div>
</div>
<div className="w-layout-hflex flex-block-101">
<div className="w-layout-hflex flex-block-102"><img src="/images/1.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Быстрая доставка по всей стране</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/2.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Высокое качество продукции</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/3.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Выгодные цены</div>
</div>
<div className="w-layout-hflex flex-block-102"><img src="/images/4.png" loading="lazy" alt=""
className="image-20" />
<div className="text-block-52">Профессиональная консультация</div>
</div>
</div>
</div>
</div>
</div>
<div className="left-arrow w-slider-arrow-left">
<div className="div-block-34">
<div className="icon-2 w-icon-slider-left"></div>
</div>
</div>
<div className="right-arrow w-slider-arrow-right">
<div className="div-block-34">
<div className="icon-2 w-icon-slider-right"></div>
</div>
</div>
<div className="slide-nav w-slider-nav w-slider-nav-invert w-round"></div>
<div className="slide-nav w-slider-nav w-slider-nav-invert w-round"></div>
</>
)}
</div>
</div>
</section>

View File

@ -0,0 +1,209 @@
import React, { useState, useEffect } from 'react';
import { useQuery } from '@apollo/client';
import { GET_HERO_BANNERS } from '@/lib/graphql';
import Link from 'next/link';
interface HeroBanner {
id: string;
title: string;
subtitle?: string;
imageUrl: string;
linkUrl?: string;
isActive: boolean;
sortOrder: number;
}
const ProductOfDayBanner: React.FC = () => {
const [currentSlide, setCurrentSlide] = useState(0);
const { data, loading, error } = useQuery(GET_HERO_BANNERS, {
errorPolicy: 'all'
});
// Фильтруем только активные баннеры и сортируем их
const banners: HeroBanner[] = data?.heroBanners
?.filter((banner: HeroBanner) => banner.isActive)
?.slice()
?.sort((a: HeroBanner, b: HeroBanner) => a.sortOrder - b.sortOrder) || [];
// Если нет баннеров из админки, показываем дефолтный
const allBanners = banners.length > 0 ? banners : [{
id: 'default',
title: 'ДОСТАВИМ БЫСТРО!',
subtitle: 'Дополнительная скидка на товары с местного склада',
imageUrl: '/images/imgfb.png',
linkUrl: '',
isActive: true,
sortOrder: 0
}];
// Автопрокрутка слайдов
useEffect(() => {
if (allBanners.length > 1) {
const interval = setInterval(() => {
setCurrentSlide(prev => (prev + 1) % allBanners.length);
}, 5000); // Меняем слайд каждые 5 секунд
return () => clearInterval(interval);
}
}, [allBanners.length]);
// Сброс текущего слайда если он вне диапазона
useEffect(() => {
if (currentSlide >= allBanners.length) {
setCurrentSlide(0);
}
}, [allBanners.length, currentSlide]);
const handlePrevSlide = () => {
setCurrentSlide(prev => prev === 0 ? allBanners.length - 1 : prev - 1);
};
const handleNextSlide = () => {
setCurrentSlide(prev => (prev + 1) % allBanners.length);
};
const handleSlideIndicator = (index: number) => {
setCurrentSlide(index);
};
const currentBanner = allBanners[currentSlide];
const renderBannerContent = (banner: HeroBanner) => {
return (
<div className="div-block-128" style={{
backgroundImage: `url(${banner.imageUrl})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
minHeight: '200px',
width: '100%',
height: '100%',
borderRadius: '20px',
overflow: 'hidden'
}}>
{(banner.title || banner.subtitle) && (
<div style={{
position: 'absolute',
bottom: '20px',
left: '20px',
right: '20px',
color: 'white',
textShadow: '0 2px 4px rgba(0,0,0,0.5)'
}}>
{banner.title && (
<h3 style={{ margin: 0, fontSize: '18px', fontWeight: 'bold' }}>
{banner.title}
</h3>
)}
{banner.subtitle && (
<p style={{ margin: '5px 0 0 0', fontSize: '14px' }}>
{banner.subtitle}
</p>
)}
</div>
)}
</div>
);
};
const bannerContent = renderBannerContent(currentBanner);
const finalContent = currentBanner.linkUrl ? (
<Link href={currentBanner.linkUrl} style={{ cursor: 'pointer', display: 'block', width: '100%', height: '100%' }}>
{bannerContent}
</Link>
) : bannerContent;
return (
<div style={{ position: 'relative', width: '100%', height: '100%' }}>
{finalContent}
{/* Навигация стрелками (показываем только если баннеров больше 1) */}
{allBanners.length > 1 && (
<>
<div
onClick={handlePrevSlide}
style={{
position: 'absolute',
left: '10px',
top: '50%',
transform: 'translateY(-50%)',
background: 'rgba(0,0,0,0.5)',
color: 'white',
border: 'none',
borderRadius: '50%',
width: '40px',
height: '40px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
zIndex: 10,
fontSize: '18px'
}}
>
</div>
<div
onClick={handleNextSlide}
style={{
position: 'absolute',
right: '10px',
top: '50%',
transform: 'translateY(-50%)',
background: 'rgba(0,0,0,0.5)',
color: 'white',
border: 'none',
borderRadius: '50%',
width: '40px',
height: '40px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
zIndex: 10,
fontSize: '18px'
}}
>
</div>
</>
)}
{/* Индикаторы слайдов (показываем только если баннеров больше 1) */}
{allBanners.length > 1 && (
<div style={{
position: 'absolute',
bottom: '10px',
left: '50%',
transform: 'translateX(-50%)',
display: 'flex',
gap: '8px',
zIndex: 10
}}>
{allBanners.map((_, index) => (
<div
key={index}
onClick={() => handleSlideIndicator(index)}
style={{
width: '10px',
height: '10px',
borderRadius: '50%',
background: index === currentSlide ? 'white' : 'rgba(255,255,255,0.5)',
cursor: 'pointer',
transition: 'background 0.3s'
}}
/>
))}
</div>
)}
</div>
);
};
export default ProductOfDayBanner;

View File

@ -1,7 +1,8 @@
import React, { useState, useEffect, useRef } from "react";
import React, { useState, useEffect } from "react";
import { useQuery } from '@apollo/client';
import { GET_DAILY_PRODUCTS, PARTS_INDEX_SEARCH_BY_ARTICLE } from '@/lib/graphql';
import Link from 'next/link';
import ProductOfDayBanner from './ProductOfDayBanner';
interface DailyProduct {
id: string;
@ -31,7 +32,6 @@ const ProductOfDaySection: React.FC = () => {
// Состояние для текущего слайда
const [currentSlide, setCurrentSlide] = useState(0);
const sliderRef = useRef<HTMLDivElement>(null);
const { data, loading, error } = useQuery<{ dailyProducts: DailyProduct[] }>(
GET_DAILY_PRODUCTS,
@ -111,9 +111,9 @@ const ProductOfDaySection: React.FC = () => {
}
return null;
};
};
// Обработчики для слайдера
// Обработчики для навигации по товарам дня
const handlePrevSlide = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
@ -158,63 +158,7 @@ const ProductOfDaySection: React.FC = () => {
<section className="main">
<div className="w-layout-blockcontainer batd w-container">
<div className="w-layout-hflex flex-block-108">
<div
ref={sliderRef}
className="slider w-slider"
>
<div className="mask w-slider-mask">
{activeProducts.map((_, index) => (
<div
key={index}
className={`slide w-slide ${index === currentSlide ? 'w--current' : ''}`}
style={{
display: index === currentSlide ? 'block' : 'none'
}}
>
<div className="div-block-128"></div>
</div>
))}
</div>
{/* Стрелки слайдера (показываем только если товаров больше 1) */}
{activeProducts.length > 1 && (
<>
<div className="left-arrow w-slider-arrow-left">
<div className="div-block-34">
<div className="code-embed-14 w-embed">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.6673 10H3.33398M3.33398 10L8.33398 5M3.33398 10L8.33398 15" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
</svg>
</div>
</div>
</div>
<div className="right-arrow w-slider-arrow-right">
<div className="div-block-34 right">
<div className="code-embed-14 w-embed">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.6673 10H3.33398M3.33398 10L8.33398 5M3.33398 10L8.33398 15" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
</svg>
</div>
</div>
</div>
</>
)}
{/* Индикаторы слайдов */}
{activeProducts.length > 1 && (
<div className="slide-nav w-slider-nav w-slider-nav-invert w-round">
{activeProducts.map((_, index) => (
<div
key={index}
className={`w-slider-dot ${index === currentSlide ? 'w--current' : ''}`}
onClick={() => handleSlideIndicator(index)}
onMouseDown={(e) => e.preventDefault()}
style={{ cursor: 'pointer', zIndex: 10 }}
></div>
))}
</div>
)}
</div>
<ProductOfDayBanner />
<div className="div-block-129">
<div className="w-layout-hflex flex-block-109">