nexora / frontend /src /components /HeroSection.js
ChandimaPrabath's picture
hero section 2.0
b10c786
raw
history blame
No virus
4.44 kB
"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;