'use client'; import { useEffect, useState } from 'react'; import Autoplay from 'embla-carousel-autoplay'; import { Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from '@/components/ui/carousel'; import type { BannerItem } from '@/types/response/banner/active-list'; type Props = { items: BannerItem[]; }; export default function HomeBannerCarousel({ items }: Props) { const [api, setApi] = useState(null); const [selectedIndex, setSelectedIndex] = useState(0); const [slideCount, setSlideCount] = useState(0); useEffect(() => { if (!api) { return; } setSlideCount(api.scrollSnapList().length); setSelectedIndex(api.selectedScrollSnap()); const handleSelect = () => { setSelectedIndex(api.selectedScrollSnap()); }; api.on('select', handleSelect); api.on('reInit', handleSelect); return () => { api.off('select', handleSelect); api.off('reInit', handleSelect); }; }, [api]); if (items.length === 0) { return null; } return (
1, align: 'start' }} plugins={items.length > 1 ? [Autoplay({ delay: 5000, stopOnInteraction: false, stopOnMouseEnter: true })] : []} className="relative" > {items.map((banner, idx) => ( ))} {items.length > 1 && ( <>
{Array.from({ length: slideCount }).map((_, idx) => (
)}
); } type SlideProps = { banner: BannerItem; index: number; total: number; }; function BannerSlide({ banner, index, total }: SlideProps) { const desktop = banner.desktopImage; const mobile = banner.mobileImage ?? banner.desktopImage; const content = ( {mobile && ( )} {desktop && ( // eslint-disable-next-line @next/next/no-img-element {banner.subject} )} ); const ariaLabel = `${banner.subject} (${index + 1}/${total})`; if (banner.link) { return ( {content} ); } return (
{content}
); }