|
"use client"; |
|
import { useState, useEffect, useRef } from "react"; |
|
import "./HeroSection.css"; |
|
import apiClient from "@/api/apiClient"; |
|
import SkeletonLoader from "@/skeletons/HeroSection"; |
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; |
|
import { faPlay } from "@fortawesome/free-solid-svg-icons"; |
|
import Link from "next/link"; |
|
|
|
const HeroSection = () => { |
|
const [currentIndex, setCurrentIndex] = useState(0); |
|
const intervalRef = useRef(null); |
|
const [fadeOut, setFadeOut] = useState(false); |
|
const [items, setItems] = useState([]); |
|
const [loading, setLoading] = useState(true); |
|
const [isDragging, setIsDragging] = useState(false); |
|
const [startX, setStartX] = useState(0); |
|
|
|
useEffect(() => { |
|
const fetchRecentItems = async () => { |
|
try { |
|
const response = await apiClient.getRecent(); |
|
const movies = response.movies.map((film) => ({ |
|
title: film[0], |
|
description: film[2], |
|
imageUrl: film[3], |
|
type: "Movie", |
|
})); |
|
const series = response.series.map((serie) => ({ |
|
title: serie[0], |
|
description: serie[2], |
|
imageUrl: serie[3], |
|
type: "Series", |
|
})); |
|
setItems([...movies, ...series]); |
|
} catch (error) { |
|
console.error("Error fetching recent items:", error); |
|
} finally { |
|
setLoading(false); |
|
} |
|
}; |
|
|
|
fetchRecentItems(); |
|
}, []); |
|
|
|
const startAutoSwitch = () => { |
|
if (intervalRef.current) clearInterval(intervalRef.current); |
|
intervalRef.current = setInterval(() => { |
|
setFadeOut(true); |
|
setTimeout(() => { |
|
setCurrentIndex((prevIndex) => (prevIndex + 1) % items.length); |
|
setFadeOut(false); |
|
}, 200); |
|
}, 5000); |
|
}; |
|
|
|
useEffect(() => { |
|
if (items.length > 0) { |
|
startAutoSwitch(); |
|
} |
|
|
|
return () => { |
|
clearInterval(intervalRef.current); |
|
}; |
|
}, [items]); |
|
|
|
const handleSwipe = (direction) => { |
|
setFadeOut(true); |
|
setTimeout(() => { |
|
setCurrentIndex((prevIndex) => { |
|
if (direction === "left") { |
|
return (prevIndex + 1) % items.length; |
|
} else { |
|
return (prevIndex - 1 + items.length) % items.length; |
|
} |
|
}); |
|
setFadeOut(false); |
|
}, 100); |
|
startAutoSwitch(); |
|
}; |
|
|
|
const handleTouchStart = (e) => { |
|
const touchStartX = e.touches[0].clientX; |
|
setStartX(touchStartX); |
|
const handleTouchMove = (event) => { |
|
const touchEndX = event.touches[0].clientX; |
|
const diffX = touchStartX - touchEndX; |
|
if (diffX > 50) { |
|
handleSwipe("left"); |
|
document.removeEventListener("touchmove", handleTouchMove); |
|
} else if (diffX < -50) { |
|
handleSwipe("right"); |
|
document.removeEventListener("touchmove", handleTouchMove); |
|
} |
|
}; |
|
document.addEventListener("touchmove", handleTouchMove); |
|
}; |
|
|
|
const handleMouseDown = (e) => { |
|
setStartX(e.clientX); |
|
setIsDragging(true); |
|
}; |
|
|
|
const handleMouseMove = (e) => { |
|
if (!isDragging) return; |
|
const diffX = startX - e.clientX; |
|
if (diffX > 50) { |
|
handleSwipe("left"); |
|
setIsDragging(false); |
|
} else if (diffX < -50) { |
|
handleSwipe("right"); |
|
setIsDragging(false); |
|
} |
|
}; |
|
|
|
const handleMouseUp = () => { |
|
setIsDragging(false); |
|
}; |
|
|
|
if (loading) { |
|
return <SkeletonLoader />; |
|
} |
|
|
|
const { title, description, imageUrl, type } = items[currentIndex]; |
|
const linkPath = `/${type.toLowerCase()}/${encodeURIComponent(title)}`; |
|
|
|
return ( |
|
<div |
|
className="hero-container" |
|
onTouchStart={handleTouchStart} |
|
onMouseDown={handleMouseDown} |
|
onMouseMove={handleMouseMove} |
|
onMouseUp={handleMouseUp} |
|
onMouseLeave={handleMouseUp} |
|
> |
|
<div className="hero-section"> |
|
{items.map((item, index) => ( |
|
<div |
|
key={index} |
|
className={`hero-image ${index === currentIndex ? "active" : ""} ${ |
|
fadeOut ? "fade-out" : "" |
|
}`} |
|
style={{ |
|
backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.1) 20%, #11121f 80%), url("${item.imageUrl}")`, |
|
}} |
|
></div> |
|
))} |
|
<div className="hero-text"> |
|
<Link href={linkPath}> |
|
<h1 className="hero-title">{title}</h1> |
|
</Link> |
|
<p className="hero-description">{description}</p> |
|
</div> |
|
</div> |
|
</div> |
|
); |
|
}; |
|
|
|
export default HeroSection; |
|
|