ChandimaPrabath's picture
0.0.0.3 Alpha
0879a03
raw
history blame
5.21 kB
"use client";
import { useState, useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faSearch,
faCaretLeft,
faCaretRight,
} from "@fortawesome/free-solid-svg-icons";
import { search } from "@/api/searchApi";
import "./searchPage.css";
import MovieCard from "@/components/MovieCard";
import TvShowCard from "@/components/TvShowCard";
const SearchPage = () => {
const [query, setQuery] = useState("");
const [results, setResults] = useState({ films: [], tv_series: [] });
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [debouncedQuery, setDebouncedQuery] = useState("");
const [loadingDelay, setLoadingDelay] = useState(null);
const router = useRouter();
const timeoutRef = useRef(null);
const moviesRef = useRef(null);
const seriesRef = useRef(null);
useEffect(() => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
timeoutRef.current = setTimeout(() => {
if (debouncedQuery) {
handleSearch();
}
}, 200);
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, [debouncedQuery]);
const handleSearch = async () => {
setLoading(true);
setError(null);
try {
const data = await search(debouncedQuery);
setResults(data);
} catch (err) {
setError("Failed to fetch search results.");
} finally {
if (loadingDelay) {
clearTimeout(loadingDelay);
}
setLoadingDelay(setTimeout(() => setLoading(false), 800));
}
};
const handleChange = (e) => {
setQuery(e.target.value);
setDebouncedQuery(e.target.value);
};
const handleItemClick = (path) => {
router.push(path);
};
const scroll = (ref, direction) => {
if (ref.current) {
const scrollAmount = direction === "left" ? -400 : 400;
ref.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
}
};
return (
<div className="search-page">
<div className="search-container">
<input
type="text"
value={query}
onChange={handleChange}
placeholder="Search for films or TV shows..."
className="search-input"
/>
{loading && (
<div className="loading-indicator">
<div className="search-icon">
<FontAwesomeIcon icon={faSearch} size="xl" />
</div>
<div className="spinner"></div>
</div>
)}
</div>
{error && <div className="error-message">{error}</div>}
<div className="results-container">
{results.films.length > 0 && (
<div className="results-section">
<div className="result-scroll">
<h2>Films</h2>
<div className="scroll-controls">
<button
onClick={() => scroll(moviesRef, "left")}
className="scroll-button"
>
<FontAwesomeIcon icon={faCaretLeft} size="2xl" />
</button>
<button
onClick={() => scroll(moviesRef, "right")}
className="scroll-button"
>
<FontAwesomeIcon icon={faCaretRight} size="2xl" />
</button>
</div>
</div>
<ul className="results-list" ref={moviesRef}>
{results.films.map((film, index) => (
<li
key={index}
className="result-item"
onClick={() =>
handleItemClick(`/movie/${encodeURIComponent(film)}`)
}
>
<MovieCard title={film} />
</li>
))}
</ul>
</div>
)}
{results.tv_series.length > 0 && (
<div className="results-section">
<div className="result-scroll">
<h2>TV Series</h2>
<div className="scroll-controls">
<button
onClick={() => scroll(seriesRef, "left")}
className="scroll-button"
>
<FontAwesomeIcon icon={faCaretLeft} size="2xl" />
</button>
<button
onClick={() => scroll(seriesRef, "right")}
className="scroll-button"
>
<FontAwesomeIcon icon={faCaretRight} size="2xl" />
</button>
</div>
</div>
<ul className="results-list" ref={seriesRef}>
{results.tv_series.map((series, index) => (
<li
key={index}
className="result-item"
onClick={() =>
handleItemClick(`/tvshow/${encodeURIComponent(series)}`)
}
>
<TvShowCard title={series} />
</li>
))}
</ul>
</div>
)}
</div>
</div>
);
};
export default SearchPage;