Spaces:
Sleeping
Sleeping
| import { useRef, useState, useEffect } from 'react'; | |
| import { ChevronLeft, ChevronRight } from 'lucide-react'; | |
| import TopTenCard from './TopTenCard'; | |
| export default function TopTenSection({ series = [], rated = [], favorited = [] }) { | |
| const [activeTab, setActiveTab] = useState('series'); | |
| const scrollRef = useRef(null); | |
| const [showLeft, setShowLeft] = useState(false); | |
| const [showRight, setShowRight] = useState(true); | |
| const getMoviesForTab = () => { | |
| switch (activeTab) { | |
| case 'rated': return rated; | |
| case 'favorited': return favorited; | |
| case 'series': | |
| default: return series; | |
| } | |
| }; | |
| const movies = getMoviesForTab(); | |
| const handleScroll = () => { | |
| if (!scrollRef.current) return; | |
| const { scrollLeft, scrollWidth, clientWidth } = scrollRef.current; | |
| setShowLeft(scrollLeft > 10); | |
| setShowRight(scrollLeft < scrollWidth - clientWidth - 10); | |
| }; | |
| const scroll = (dir) => { | |
| if (!scrollRef.current) return; | |
| const amount = scrollRef.current.clientWidth * 0.8; | |
| scrollRef.current.scrollBy({ left: dir * amount, behavior: 'smooth' }); | |
| }; | |
| // Reset scroll position on tab change | |
| useEffect(() => { | |
| if (scrollRef.current) { | |
| scrollRef.current.scrollLeft = 0; | |
| handleScroll(); | |
| } | |
| }, [activeTab]); | |
| if (!movies?.length) return null; | |
| return ( | |
| <section className="mx-auto max-w-7xl px-4 py-10 md:px-8 overflow-hidden"> | |
| {/* Header Tabs */} | |
| <div className="mb-10 flex flex-col md:flex-row md:items-center justify-between gap-6 border-b border-white/5 pb-5"> | |
| <div className="flex items-center gap-3"> | |
| <span className="h-8 w-2 rounded-full bg-primary shadow-[0_0_20px_rgba(229,9,20,0.6)]" /> | |
| <h2 className="text-2xl font-black uppercase tracking-tight text-white"> | |
| Bảng Xếp Hạng | |
| </h2> | |
| </div> | |
| {/* Premium Tab Buttons */} | |
| <div className="flex flex-wrap gap-2 bg-white/5 p-1 rounded-2xl border border-white/5 backdrop-blur-md self-start md:self-auto"> | |
| {[ | |
| { id: 'series', name: 'Top Phim Bộ', icon: 'fa-fire' }, | |
| { id: 'rated', name: 'Đánh Giá Cao', icon: 'fa-star' }, | |
| { id: 'favorited', name: 'Yêu Thích Nhất', icon: 'fa-heart' } | |
| ].map(tab => ( | |
| <button | |
| key={tab.id} | |
| onClick={() => setActiveTab(tab.id)} | |
| className={`flex items-center gap-2 px-5 py-2.5 rounded-xl text-[10px] font-black uppercase tracking-widest transition-all duration-300 cursor-pointer ${ | |
| activeTab === tab.id | |
| ? 'bg-primary text-white shadow-[0_0_20px_rgba(229,9,20,0.3)] scale-[1.02]' | |
| : 'text-gray-400 hover:text-white hover:bg-white/5' | |
| }`} | |
| > | |
| <i className={`fas ${tab.icon} text-[9px] ${activeTab === tab.id ? 'text-white' : 'text-gray-500'}`}></i> | |
| {tab.name} | |
| </button> | |
| ))} | |
| </div> | |
| </div> | |
| {/* Row có scroll ngang */} | |
| <div className="relative group/section"> | |
| {/* Nút trái */} | |
| {showLeft && ( | |
| <button | |
| onClick={() => scroll(-1)} | |
| className="absolute left-1 top-[42%] z-40 -translate-y-1/2 flex h-10 w-10 items-center justify-center rounded-full bg-black/80 text-white backdrop-blur-sm opacity-0 transition-all duration-300 group-hover/section:opacity-100 hover:bg-primary border border-white/10 shadow-lg cursor-pointer" | |
| > | |
| <ChevronLeft size={20} /> | |
| </button> | |
| )} | |
| {/* Nút phải */} | |
| {showRight && ( | |
| <button | |
| onClick={() => scroll(1)} | |
| className="absolute right-1 top-[42%] z-40 -translate-y-1/2 flex h-10 w-10 items-center justify-center rounded-full bg-black/80 text-white backdrop-blur-sm opacity-0 transition-all duration-300 group-hover/section:opacity-100 hover:bg-primary border border-white/10 shadow-lg cursor-pointer" | |
| > | |
| <ChevronRight size={20} /> | |
| </button> | |
| )} | |
| {/* Track */} | |
| <div | |
| ref={scrollRef} | |
| onScroll={handleScroll} | |
| className="scrollbar-hide flex overflow-x-auto pb-16 pt-2 px-4 md:px-8 gap-6 md:gap-8" | |
| > | |
| {movies.slice(0, 10).map((movie, idx) => ( | |
| <div | |
| key={`${movie._id || movie.slug}-${activeTab}-${idx}`} | |
| className="w-[180px] md:w-[240px] flex-shrink-0" | |
| > | |
| <TopTenCard movie={movie} index={idx} /> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| </section> | |
| ); | |
| } |