import React, { useState, useEffect, useCallback } from 'react'; import { createPortal } from 'react-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { X, HelpCircle, Users, ChevronLeft, ChevronRight } from 'lucide-react'; import useEmblaCarousel from 'embla-carousel-react'; import { useTranslation } from 'react-i18next'; interface WatchPartyTutorialModalProps { isOpen: boolean; onClose: () => void; } const WatchPartyTutorialModal: React.FC = ({ isOpen, onClose }) => { const { t } = useTranslation(); const [currentSlide, setCurrentSlide] = useState(0); const [isClosing, setIsClosing] = useState(false); const [zoomedImage, setZoomedImage] = useState(null); const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }); // Disable body scroll when modal is open useEffect(() => { if (!isOpen) return; const originalOverflow = document.body.style.overflow; document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = originalOverflow; }; }, [isOpen]); const tutorialSlides = [ { image: '/WatchpartyTutorial/1.png', text: t('watchParty.tutorialStep1') }, { image: '/WatchpartyTutorial/2.png', text: t('watchParty.tutorialStep2') }, { image: '/WatchpartyTutorial/3.png', text: t('watchParty.tutorialStep3') }, { title: t('watchParty.advancedFeatures'), text: t('watchParty.advancedFeaturesDesc') } ]; const scrollPrev = useCallback(() => { if (emblaApi) emblaApi.scrollPrev(); }, [emblaApi]); const scrollNext = useCallback(() => { if (emblaApi) emblaApi.scrollNext(); }, [emblaApi]); const scrollTo = useCallback((index: number) => { if (emblaApi) emblaApi.scrollTo(index); }, [emblaApi]); const onSelect = useCallback((emblaApi: any) => { setCurrentSlide(emblaApi.selectedScrollSnap()); }, []); useEffect(() => { if (!emblaApi) return; onSelect(emblaApi); emblaApi.on('select', onSelect); emblaApi.on('reInit', onSelect); return () => { emblaApi.off('select', onSelect); emblaApi.off('reInit', onSelect); }; }, [emblaApi, onSelect]); const handleClose = () => { setIsClosing(true); setTimeout(() => { onClose(); setIsClosing(false); setCurrentSlide(0); // We can't easily reset embla here without mounting, but state reset helps }, 300); }; if (!isOpen) return null; const modalContent = ( {isOpen && !isClosing && ( { if (e.target === e.currentTarget) handleClose(); }} > {/* Header */}

{t('watchParty.howToCreate')}

{/* Content */}
{/* Embla Carousel Viewport */}
{tutorialSlides.map((slide, index) => (
{slide.image ? ( {`${t('watchParty.step')} { e.stopPropagation(); setZoomedImage(slide.image); }} /> ) : (

{slide.title}

{slide.text}

)}
))}
{/* Navigation Buttons */}
{/* Dynamic Text for current slide */}

{tutorialSlides[currentSlide].text}

{/* Pagination Dots */}
{tutorialSlides.map((_, index) => (
)}
); const zoomOverlay = ( {zoomedImage && ( setZoomedImage(null)} > )} ); return createPortal( <> {modalContent} {zoomOverlay} , document.body ); }; export default WatchPartyTutorialModal;