import React, { useState, useEffect, useMemo } from 'react'; import { ChevronLeft, ChevronRight } from 'lucide-react'; interface Partner { name?: string; logo?: string; link?: string; } interface PartnersCarouselProps { partners: Partner[]; autoSlideInterval?: number; showNavigation?: boolean; itemsPerView?: number; } const PartnersCarousel: React.FC = ({ partners, autoSlideInterval = 5000, showNavigation = true, itemsPerView = 6, }) => { const [currentIndex, setCurrentIndex] = useState(0); const [windowWidth, setWindowWidth] = useState(typeof window !== 'undefined' ? window.innerWidth : 1920); // Handle window resize useEffect(() => { if (typeof window === 'undefined') return; const handleResize = () => { setWindowWidth(window.innerWidth); }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); // Calculate responsive items per view const responsiveItemsPerView = useMemo(() => { if (windowWidth < 640) return 2; // sm: 2 items if (windowWidth < 768) return 3; // md: 3 items if (windowWidth < 1024) return 4; // lg: 4 items return itemsPerView; // xl: 6 items }, [windowWidth, itemsPerView]); // Calculate max index (how many slides we can have) const maxIndex = Math.max(0, partners.length - responsiveItemsPerView); const canNavigate = partners.length > responsiveItemsPerView; const allItemsFit = partners.length <= responsiveItemsPerView; // Auto-slide functionality useEffect(() => { if (!canNavigate) return; const interval = setInterval(() => { setCurrentIndex((prev) => { if (prev >= maxIndex) { return 0; // Loop back to start } return prev + 1; }); }, autoSlideInterval); return () => clearInterval(interval); }, [canNavigate, maxIndex, autoSlideInterval]); // Reset index when it exceeds max useEffect(() => { if (currentIndex > maxIndex) { setCurrentIndex(0); } }, [maxIndex, currentIndex]); const goToPrevious = () => { if (!canNavigate) return; setCurrentIndex((prev) => (prev === 0 ? maxIndex : prev - 1)); }; const goToNext = () => { if (!canNavigate) return; setCurrentIndex((prev) => (prev >= maxIndex ? 0 : prev + 1)); }; const goToSlide = (index: number) => { if (index < 0 || index > maxIndex) return; setCurrentIndex(index); }; if (partners.length === 0) { return null; } const itemWidth = 100 / responsiveItemsPerView; const translateX = allItemsFit ? 0 : -(currentIndex * itemWidth); return (
{/* Carousel Container */}
{allItemsFit ? ( // Centered layout when all items fit - show only logos without containers
{partners.map((partner, index) => { return (
{partner.link ? ( {partner.logo ? ( {partner.name { const target = e.target as HTMLImageElement; target.style.display = 'none'; }} /> ) : ( {partner.name || `Partner ${index + 1}`} )} ) : ( <> {partner.logo ? ( {partner.name { const target = e.target as HTMLImageElement; target.style.display = 'none'; }} /> ) : ( {partner.name || `Partner ${index + 1}`} )} )}
); })}
) : ( // Carousel layout when items don't all fit
{partners.map((partner, index) => (
{partner.link ? ( {partner.logo ? ( {partner.name { const target = e.target as HTMLImageElement; target.style.display = 'none'; }} /> ) : ( {partner.name || `Partner ${index + 1}`} )} ) : ( <> {partner.logo ? ( {partner.name { const target = e.target as HTMLImageElement; target.style.display = 'none'; }} /> ) : ( {partner.name || `Partner ${index + 1}`} )} )}
))}
)}
{/* Navigation Buttons */} {showNavigation && canNavigate && ( <> )} {/* Dots Indicator */} {canNavigate && maxIndex > 0 && (
{Array.from({ length: maxIndex + 1 }).map((_, index) => (
)}
); }; export default PartnersCarousel;