'use client'; import {useEffect, useRef, useState} from 'react'; import Link from 'next/link'; import {gsap} from 'gsap'; import {ScrollTrigger} from 'gsap/ScrollTrigger'; import VendingCard from './VendingCard'; import {showcaseVideoSrc} from '@/data/content'; import {featuredMachines} from '@/data/products'; import {commerceCopy} from '@/data/commerce'; import {useLanguage} from '@/app/context/LanguageContext'; gsap.registerPlugin(ScrollTrigger); export default function HorizontalShowcase() { const sectionRef = useRef(null); const trackRef = useRef(null); const videoRef = useRef(null); const {t, locale} = useLanguage(); const copy = commerceCopy[locale]; const [videoAvailable, setVideoAvailable] = useState(true); useEffect(() => { const ctx = gsap.context(() => { const track = trackRef.current; const section = sectionRef.current; if (!track || !section) return; const scrollDistance = () => ( Math.max(track.scrollWidth - window.innerWidth, 0) ); let animationFrameId: number | null = null; let latestProgress = 0; const syncVideo = (progress: number) => { latestProgress = progress; if (animationFrameId !== null) return; animationFrameId = window.requestAnimationFrame(() => { const video = videoRef.current; if (video && Number.isFinite(video.duration) && video.duration > 0) { video.currentTime = latestProgress * video.duration; } animationFrameId = null; }); }; const horizontalTween = gsap.to(track, { x: () => -scrollDistance(), ease: 'none', scrollTrigger: { trigger: section, start: 'top top', end: () => `+=${scrollDistance()}`, scrub: 1, pin: true, invalidateOnRefresh: true, onUpdate: (self) => syncVideo(self.progress), }, }); return () => { if (animationFrameId !== null) window.cancelAnimationFrame(animationFrameId); horizontalTween.scrollTrigger?.kill(); horizontalTween.kill(); }; }, sectionRef); return () => ctx.revert(); }, []); return (
{videoAvailable && (
); }