|
|
|
|
|
import React, { useState, useRef, useEffect } from 'react'; |
|
|
import ContentCard from './ContentCard'; |
|
|
import { ChevronLeft, ChevronRight } from 'lucide-react'; |
|
|
|
|
|
interface ContentItem { |
|
|
type: 'movie' | 'tvshow'; |
|
|
title: string; |
|
|
image: string; |
|
|
description?: string; |
|
|
genre?: string[]; |
|
|
year?: number | string; |
|
|
} |
|
|
|
|
|
interface ContentRowProps { |
|
|
title: string; |
|
|
items: ContentItem[]; |
|
|
} |
|
|
|
|
|
const ContentRow: React.FC<ContentRowProps> = ({ title, items }) => { |
|
|
const rowRef = useRef<HTMLDivElement>(null); |
|
|
const [showLeftButton, setShowLeftButton] = useState(false); |
|
|
const [showRightButton, setShowRightButton] = useState(true); |
|
|
|
|
|
|
|
|
const handleScroll = () => { |
|
|
if (rowRef.current) { |
|
|
const { scrollLeft, scrollWidth, clientWidth } = rowRef.current; |
|
|
setShowLeftButton(scrollLeft > 20); |
|
|
setShowRightButton(scrollLeft < scrollWidth - clientWidth - 20); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
handleScroll(); |
|
|
window.addEventListener('resize', handleScroll); |
|
|
return () => window.removeEventListener('resize', handleScroll); |
|
|
}, [items]); |
|
|
|
|
|
const scroll = (direction: 'left' | 'right') => { |
|
|
if (rowRef.current) { |
|
|
const card = rowRef.current.querySelector('.card-hover'); |
|
|
const cardWidth = card ? card.clientWidth + 16 : 280; |
|
|
const scrollAmount = direction === 'left' ? -cardWidth * 3 : cardWidth * 3; |
|
|
rowRef.current.scrollBy({ left: scrollAmount, behavior: 'smooth' }); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
if (items.length === 0) { |
|
|
return null; |
|
|
} |
|
|
|
|
|
return ( |
|
|
<div className="content-row mb-8"> |
|
|
<h2 className="text-xl font-bold px-4 md:px-8 mb-4">{title}</h2> |
|
|
|
|
|
<div className="relative group"> |
|
|
{/* Left scroll button */} |
|
|
<button |
|
|
onClick={() => scroll('left')} |
|
|
className={`absolute left-2 top-1/2 transform -translate-y-1/2 z-30 |
|
|
bg-black/40 hover:bg-black/60 rounded-full p-2 transition-all duration-200 |
|
|
${showLeftButton ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} |
|
|
aria-label="Scroll left" |
|
|
> |
|
|
<ChevronLeft className="w-6 h-6 text-white" /> |
|
|
</button> |
|
|
|
|
|
{/* Content row */} |
|
|
<div |
|
|
ref={rowRef} |
|
|
onScroll={handleScroll} |
|
|
className="flex gap-4 overflow-x-auto py-4 px-4 md:px-8 scrollbar-none scroll-smooth" |
|
|
style={{ scrollbarWidth: 'none' }} |
|
|
> |
|
|
{items.map((item, index) => ( |
|
|
<div key={`${item.title}-${index}`} className="flex-shrink-0"> |
|
|
<ContentCard |
|
|
type={item.type} |
|
|
title={item.title} |
|
|
image={item.image} |
|
|
description={item.description} |
|
|
genre={item.genre} |
|
|
year={item.year} |
|
|
/> |
|
|
</div> |
|
|
))} |
|
|
</div> |
|
|
|
|
|
{/* Right scroll button */} |
|
|
<button |
|
|
onClick={() => scroll('right')} |
|
|
className={`absolute right-2 top-1/2 transform -translate-y-1/2 z-30 |
|
|
bg-black/40 hover:bg-black/60 rounded-full p-2 transition-all duration-200 |
|
|
${showRightButton ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} |
|
|
aria-label="Scroll right" |
|
|
> |
|
|
<ChevronRight className="w-6 h-6 text-white" /> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
); |
|
|
}; |
|
|
|
|
|
export default ContentRow; |
|
|
|