'use client';
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { Swiper, SwiperSlide } from "swiper/react";
import { Navigation, Pagination, Thumbs, FreeMode } from "swiper/modules";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import "swiper/css/thumbs";
import "swiper/css/free-mode";
const ImageWithRetry = ({ src, alt, className }) => {
const [imageSrc, setImageSrc] = useState(src);
const retryCountRef = useRef(0);
useEffect(() => {
setImageSrc(src);
retryCountRef.current = 0;
}, [src]);
const handleError = useCallback(() => {
if (retryCountRef.current >= 3) return;
retryCountRef.current += 1;
const delay = 300 * retryCountRef.current;
setTimeout(() => {
const url = new URL(imageSrc, typeof window !== 'undefined' ? window.location.origin : 'http://localhost');
url.searchParams.set('v', String(Date.now()));
setImageSrc(url.pathname + url.search);
}, delay);
}, [imageSrc]);
return (
);
};
const ProductImageGallery = ({ data }) => {
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const [thumbsSwiper, setThumbsSwiper] = useState(null);
const thumbsSwiperRef = useRef(null);
if (!data?.attachments || data.attachments.length === 0) {
return null;
}
const mainImageIndex = useMemo(() => {
if (!data.image) return 0;
const mainImageIndex = data.attachments.findIndex(
attachment => attachment.file_url === data.image
);
return mainImageIndex >= 0 ? mainImageIndex : 0;
}, [data.image, data.attachments]);
const currentImage = useMemo(() => {
return data.attachments[currentImageIndex]?.file_url || data.attachments[0]?.file_url;
}, [data.attachments, currentImageIndex]);
const scrollThumbnailToIndex = useCallback((index) => {
if (thumbsSwiperRef.current?.swiper) {
try {
const swiper = thumbsSwiperRef.current.swiper;
if (index === 0) {
swiper.scrollTo(0, 300);
} else {
swiper.slideTo(index, 300);
}
} catch (error) {
}
}
}, []);
const changeMainImage = useCallback((direction) => {
if (data.attachments.length <= 1) return;
let newIndex;
if (direction === 'next') {
newIndex = (currentImageIndex + 1) % data.attachments.length;
} else {
newIndex = (currentImageIndex - 1 + data.attachments.length) % data.attachments.length;
}
setCurrentImageIndex(newIndex);
setTimeout(() => {
scrollThumbnailToIndex(newIndex);
}, 100);
}, [currentImageIndex, data.attachments.length, scrollThumbnailToIndex]);
const changeMainImageByIndex = useCallback((index) => {
setCurrentImageIndex(index);
setTimeout(() => {
scrollThumbnailToIndex(index);
}, 100);
}, [scrollThumbnailToIndex]);
useEffect(() => {
setCurrentImageIndex(mainImageIndex);
}, [mainImageIndex]);
const handleKeyDown = useCallback((event) => {
if (data.attachments.length <= 1) return;
switch (event.key) {
case 'ArrowLeft':
event.preventDefault();
changeMainImage('prev');
break;
case 'ArrowRight':
event.preventDefault();
changeMainImage('next');
break;
case 'Home':
event.preventDefault();
setCurrentImageIndex(0);
setTimeout(() => scrollThumbnailToIndex(0), 100);
break;
case 'End':
event.preventDefault();
setCurrentImageIndex(data.attachments.length - 1);
setTimeout(() => scrollThumbnailToIndex(data.attachments.length - 1), 100);
break;
default:
break;
}
}, [data.attachments.length, changeMainImage, scrollThumbnailToIndex]);
useEffect(() => {
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [handleKeyDown]);
const thumbnailSlides = useMemo(() => {
return data.attachments.map((attachment, index) => (