'use client'; import { useState, useRef, useCallback, useMemo, memo } from 'react'; import { VideoCard } from './VideoCard'; import { Video } from '@/lib/types'; interface VideoGridProps { videos: Video[]; className?: string; } export const VideoGrid = memo(function VideoGrid({ videos, className = '' }: VideoGridProps) { const [activeCardId, setActiveCardId] = useState(null); const [visibleCount, setVisibleCount] = useState(24); const gridRef = useRef(null); const observerRef = useRef(null); if (videos.length === 0) { return null; } // Callback ref for the load more trigger to handle dynamic mounting/unmounting const loadMoreRef = useCallback((node: HTMLDivElement | null) => { if (observerRef.current) observerRef.current.disconnect(); if (node) { observerRef.current = new IntersectionObserver(entries => { if (entries[0].isIntersecting) { setVisibleCount(prev => prev + 24); } }, { rootMargin: '400px' }); observerRef.current.observe(node); } }, []); // Memoize the click handler to prevent re-renders const handleCardClick = useCallback((e: React.MouseEvent, videoId: string, videoUrl: string) => { // Check if it's a mobile device const isMobile = window.innerWidth < 1024; // lg breakpoint if (isMobile) { // On mobile, first click shows details, second click navigates if (activeCardId === videoId) { // Already active, allow navigation window.location.href = videoUrl; } else { // First click, show details e.preventDefault(); setActiveCardId(videoId); } } // On desktop, let the Link work normally }, [activeCardId]); // Memoize video items to prevent unnecessary re-computations const videoItems = useMemo(() => { return videos.map((video, index) => { const videoUrl = `/player?${new URLSearchParams({ id: String(video.vod_id), source: video.source, title: video.vod_name, }).toString()}`; const cardId = `${video.vod_id}-${index}`; return { video, videoUrl, cardId, }; }); }, [videos]); const visibleItems = videoItems.slice(0, visibleCount); return ( <>
{visibleItems.map(({ video, videoUrl, cardId }) => { const isActive = activeCardId === cardId; return ( ); })}
{/* Load more trigger */} {visibleCount < videoItems.length && (