import { useState, useEffect, useRef, useCallback } from "react"; import Image from "next/image"; import { X, ZoomIn, ZoomOut, RotateCw, RotateCcw, Maximize2, ChevronLeft, ChevronRight, } from "lucide-react"; import { useTranslations } from "next-intl"; interface ProductImageGalleryProps { images: string[]; productName: string; noImageText: string; } export function ProductImageGallery({ images, productName, noImageText, }: ProductImageGalleryProps) { const [selectedImage, setSelectedImage] = useState(0); const [isModalOpen, setIsModalOpen] = useState(false); const [zoom, setZoom] = useState(1); const [rotation, setRotation] = useState(0); const [position, setPosition] = useState({ x: 0, y: 0 }); const [isDragging, setIsDragging] = useState(false); const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); const t = useTranslations(); const autoplayTimerRef = useRef(undefined); const modalImageRef = useRef(null); useEffect(() => { setSelectedImage(0); }, [images]); useEffect(() => { if (images.length <= 1 || isModalOpen) return; const startAutoplay = () => { autoplayTimerRef.current = setInterval(() => { setSelectedImage((prev) => (prev + 1) % images.length); }, 3000); }; startAutoplay(); return () => { if (autoplayTimerRef.current) clearInterval(autoplayTimerRef.current); }; }, [images.length, isModalOpen]); useEffect(() => { if (isModalOpen) { document.body.style.overflow = "hidden"; if (autoplayTimerRef.current) clearInterval(autoplayTimerRef.current); } else { document.body.style.overflow = "unset"; } return () => { document.body.style.overflow = "unset"; }; }, [isModalOpen]); const handleImageSelect = useCallback( (index: number) => { setSelectedImage(index); if (autoplayTimerRef.current) clearInterval(autoplayTimerRef.current); if (images.length > 1 && !isModalOpen) { autoplayTimerRef.current = setInterval(() => { setSelectedImage((prev) => (prev + 1) % images.length); }, 3000); } }, [images.length, isModalOpen], ); const openModal = () => { setIsModalOpen(true); resetTransform(); }; const closeModal = () => { setIsModalOpen(false); resetTransform(); }; const resetTransform = () => { setZoom(1); setRotation(0); setPosition({ x: 0, y: 0 }); }; const handleZoomIn = () => { setZoom((prev) => Math.min(prev + 0.25, 5)); }; const handleZoomOut = () => { setZoom((prev) => Math.max(prev - 0.25, 0.5)); }; const handleRotateClockwise = () => { setRotation((prev) => (prev + 90) % 360); }; const handleRotateCounterClockwise = () => { setRotation((prev) => (prev - 90 + 360) % 360); }; const handleMouseDown = (e: React.MouseEvent | React.TouchEvent) => { if (zoom > 1) { setIsDragging(true); const clientX = "touches" in e ? e.touches[0].clientX : e.clientX; const clientY = "touches" in e ? e.touches[0].clientY : e.clientY; setDragStart({ x: clientX - position.x, y: clientY - position.y, }); } }; const handleMouseMove = (e: React.MouseEvent | React.TouchEvent) => { if (isDragging && zoom > 1) { const clientX = "touches" in e ? e.touches[0].clientX : e.clientX; const clientY = "touches" in e ? e.touches[0].clientY : e.clientY; setPosition({ x: clientX - dragStart.x, y: clientY - dragStart.y, }); } }; const handleMouseUp = () => { setIsDragging(false); }; const handleWheel = (e: React.WheelEvent) => { e.preventDefault(); if (e.deltaY < 0) { handleZoomIn(); } else { handleZoomOut(); } }; const handleModalImageChange = (direction: "prev" | "next") => { if (direction === "next") { setSelectedImage((prev) => (prev + 1) % images.length); } else { setSelectedImage((prev) => (prev - 1 + images.length) % images.length); } resetTransform(); }; return ( <>
{images.length > 0 && images[selectedImage] ? ( <> {productName}
) : (
{noImageText}
)}
{images.length > 1 && (
{images.map((image, index) => ( ))}
)}
{/* Modal */} {isModalOpen && (
{/* Top Bar */}
{productName}
{/* Main Image Area */}
{/* Left Arrow - Desktop */} {images.length > 1 && ( )} {/* Image Container */}
1 ? (isDragging ? "grabbing" : "grab") : "default", }} >
{productName}
{/* Right Arrow - Desktop */} {images.length > 1 && ( )}
{/* Bottom Control Bar */}
{/* Mobile Layout */}
{/* Row 1: Navigation */} {images.length > 1 && (
{selectedImage + 1} / {images.length}
)} {/* Row 2: Zoom & Rotate */}
{Math.round(zoom * 100)}%
{/* Desktop Layout */}
{Math.round(zoom * 100)}%
{images.length > 1 && ( <>
{selectedImage + 1} / {images.length}
)}
)} ); }