import { useEffect, useState, useRef } from 'react'; import MovieSection from './MovieSection.jsx'; import CombinedRegionSection from './CombinedRegionSection.jsx'; const SECTION_CONFIGS = [ { type: 'newest', title: 'Phim mới cập nhật', href: '/danh-sach/phim-moi-cap-nhat' }, { type: 'series', title: 'Phim bộ đặc sắc', href: '/danh-sach/phim-bo' }, { type: 'single', title: 'Phim Điện Ảnh Mới Coóng', href: '/danh-sach/phim-le' }, { category: 'phim-chieu-rap', title: 'Mãn Nhãn với Phim Chiếu Rạp', href: '/the-loai/phim-chieu-rap' }, { type: 'cartoon', title: 'Thế giới hoạt hình', href: '/danh-sach/hoat-hinh' }, { country: 'trung-quoc', title: 'Phim Trung Quốc mới', href: '/quoc-gia/trung-quoc' }, { country: 'han-quoc', title: 'Phim Hàn Quốc mới', href: '/quoc-gia/han-quoc' }, { country: 'au-my', title: 'Phim Âu-Mỹ mới', href: '/quoc-gia/au-my' } ]; export default function HomeSectionsLoader() { const [loadedSections, setLoadedSections] = useState([]); const [loading, setLoading] = useState(false); const [currentIndex, setCurrentIndex] = useState(0); const loaderRef = useRef(null); const fetchSectionData = async (config) => { try { const params = new URLSearchParams(); if (config.type) params.append('type', config.type); if (config.category) params.append('category', config.category); if (config.country) params.append('country', config.country); const res = await fetch(`/api/movies?${params.toString()}`); if (!res.ok) throw new Error('Failed to fetch movies'); const data = await res.json(); return data.items || []; } catch (e) { console.error(`[HomeSectionsLoader] Error loading ${config.title}:`, e); return []; } }; // Tải danh mục tiếp theo khi cuộn xuống const loadNextSection = async () => { if (loading || currentIndex >= SECTION_CONFIGS.length) return; setLoading(true); const config = SECTION_CONFIGS[currentIndex]; const movies = await fetchSectionData(config); if (movies.length > 0) { setLoadedSections(prev => { if (prev.some(s => s.title === config.title)) return prev; return [...prev, { ...config, movies }]; }); } setCurrentIndex(prev => prev + 1); setLoading(false); }; // Lần đầu tải 2 Section đầu tiên để lấp đầy khung nhìn ngay lập tức useEffect(() => { let active = true; const initLoad = async () => { setLoading(true); // Load Section 1 const config1 = SECTION_CONFIGS[0]; const movies1 = await fetchSectionData(config1); if (active && movies1.length > 0) { setLoadedSections([{ ...config1, movies: movies1 }]); } // Load Section 2 const config2 = SECTION_CONFIGS[1]; const movies2 = await fetchSectionData(config2); if (active && movies2.length > 0) { setLoadedSections(prev => [...prev, { ...config2, movies: movies2 }]); } if (active) { setCurrentIndex(2); setLoading(false); } }; initLoad(); return () => { active = false; }; }, []); // Lắng nghe Intersection Observer để kích hoạt tải Section tiếp theo khi cuộn xuống gần cuối useEffect(() => { if (!loaderRef.current || currentIndex >= SECTION_CONFIGS.length || loading) return; const observer = new IntersectionObserver((entries) => { const target = entries[0]; if (target.isIntersecting && !loading) { loadNextSection(); } }, { rootMargin: '350px', // Bắt đầu tải ngầm trước khi cuộn tới 350px để tạo trải nghiệm bất tận mượt mà threshold: 0.1 }); observer.observe(loaderRef.current); return () => observer.disconnect(); }, [currentIndex, loading]); const normalSections = loadedSections.filter(sec => !['trung-quoc', 'han-quoc', 'au-my'].includes(sec.country)); const regionSections = loadedSections.filter(sec => ['trung-quoc', 'han-quoc', 'au-my'].includes(sec.country)); return (
{normalSections.map((sec, i) => ( ))} {regionSections.length > 0 && ( )} {/* Điểm kích hoạt cuộn tải Section */} {currentIndex < SECTION_CONFIGS.length && (
{loading && ( <>
{/* Vòng quay hiệu ứng Neon cao cấp */}
Đang tải thêm danh mục phim... )}
)}
); }