164 lines
4.7 KiB
TypeScript
164 lines
4.7 KiB
TypeScript
import { getMovieGenres, getMoviesByGenre } from "@/lib/tmdb/server";
|
|
import { MovieList } from "@/components/molecules/MovieList";
|
|
import { FaCalendar, FaFire } from "react-icons/fa";
|
|
import { notFound } from "next/navigation";
|
|
import { GenreList } from "@/components/molecules/GenreList";
|
|
import { BackButton } from "@/components/atoms/BackButton";
|
|
|
|
// 6 hours cache for genre pages.
|
|
export const revalidate = 21600;
|
|
|
|
type PageProps = {
|
|
params: Promise<{ id: string }>;
|
|
};
|
|
|
|
export default async function GenrePage({ params }: PageProps) {
|
|
const { id } = await params;
|
|
const genreId = parseInt(id);
|
|
|
|
if (isNaN(genreId)) {
|
|
notFound();
|
|
}
|
|
|
|
const { genres } = await getMovieGenres();
|
|
const genre = genres.find((g) => g.id === genreId);
|
|
|
|
if (!genre) {
|
|
notFound();
|
|
}
|
|
|
|
const now = new Date();
|
|
|
|
// Get genre name and all movie data in parallel.
|
|
const [recentData, upcomingData, topRatedData] = await Promise.all([
|
|
getMoviesByGenre(genreId, 1, {
|
|
sort_by: "release_date.desc",
|
|
["release_date.lte"]: `${now.getFullYear()}-${
|
|
now.getMonth() + 1
|
|
}-${now.getDate()}`,
|
|
}),
|
|
getMoviesByGenre(genreId, 1, {
|
|
sort_by: "release_date.asc",
|
|
["release_date.gte"]: `${now.getFullYear()}-${now.getMonth() + 1}-${
|
|
now.getDate() + 1
|
|
} `,
|
|
}),
|
|
getMoviesByGenre(genreId, 1, {
|
|
sort_by: "",
|
|
vote_count_gte: "100",
|
|
["release_date.lte"]: `${now.getFullYear()}-${
|
|
now.getMonth() + 1
|
|
}-${now.getDate()}`,
|
|
}),
|
|
]);
|
|
|
|
// Convert TMDB movie format to our Movie type.
|
|
const convertMovies = (movies: any[]) =>
|
|
movies.map((movie) => ({
|
|
...movie,
|
|
genre_ids: JSON.stringify(movie.genre_ids),
|
|
seen: false,
|
|
favorite: false,
|
|
}));
|
|
|
|
const recentMovies = convertMovies(recentData.results);
|
|
const upcomingMovies = convertMovies(upcomingData.results);
|
|
const topRatedMovies = convertMovies(topRatedData.results);
|
|
|
|
return (
|
|
<>
|
|
{/* Hero section with genre name */}
|
|
<section className="blockp bg-gradient-to-br from-slate-900/50 via-slate-800/30 to-slate-900/50 border-b border-gray-800">
|
|
{/* Navigation */}
|
|
<div className="relative">
|
|
<div className="absolute top-0 left-0 right-0 z-20 px-6">
|
|
<BackButton />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="container text-center">
|
|
<h1 className="text-4xl md:text-6xl font-bold mb-4 bg-gradient-to-r from-purple-400 via-pink-400 to-cyan-400 bg-clip-text text-transparent">
|
|
{genre.name}
|
|
</h1>
|
|
<p className="text-lg text-gray-300 max-w-2xl mx-auto">
|
|
Odkryj najlepsze filmy z kategorii {genre.name.toLowerCase()}
|
|
</p>
|
|
<div className="mt-8 w-32 h-px bg-gradient-to-r from-transparent via-purple-400/50 to-transparent mx-auto" />
|
|
</div>
|
|
</section>
|
|
|
|
{/* Recent movies section */}
|
|
<section className="blocks">
|
|
<MovieList
|
|
overrideMovies={recentMovies}
|
|
heading="Najnowsze filmy"
|
|
loadMore
|
|
icon={<FaCalendar />}
|
|
colors="green"
|
|
showFilters={false}
|
|
displayType="list"
|
|
/>
|
|
</section>
|
|
|
|
{/* Top rated section */}
|
|
{upcomingMovies.length > 0 && (
|
|
<section className="blocks">
|
|
<MovieList
|
|
overrideMovies={upcomingMovies}
|
|
heading="Nadchodzące premiery"
|
|
loadMore
|
|
icon={<FaCalendar />}
|
|
colors="blue"
|
|
showFilters={false}
|
|
sortDirection="desc"
|
|
displayType="list"
|
|
/>
|
|
</section>
|
|
)}
|
|
|
|
{/* Top rated section */}
|
|
{topRatedMovies.length > 0 && (
|
|
<section className="blocks">
|
|
<MovieList
|
|
overrideMovies={topRatedMovies}
|
|
heading="Najpopularniejsze filmy"
|
|
icon={<FaFire />}
|
|
colors="red"
|
|
showFilters={false}
|
|
displayType="list"
|
|
/>
|
|
</section>
|
|
)}
|
|
|
|
<GenreList heading="Odkryj inne gatunki" />
|
|
</>
|
|
);
|
|
}
|
|
|
|
export async function generateMetadata({ params }: PageProps) {
|
|
const { id } = await params;
|
|
const genreId = parseInt(id);
|
|
|
|
if (isNaN(genreId)) {
|
|
return {
|
|
title: "Gatunek nie znaleziony",
|
|
};
|
|
}
|
|
|
|
try {
|
|
const { genres } = await getMovieGenres();
|
|
const genre = genres.find((g) => g.id === genreId);
|
|
|
|
return {
|
|
title: genre ? `${genre.name} - Movie Box` : "Gatunek - Movie Box",
|
|
description: genre
|
|
? `Odkryj najlepsze filmy z kategorii ${genre.name}. Najnowsze premiery, popularne tytuły i najwyżej oceniane produkcje.`
|
|
: "Przeglądaj filmy według gatunków",
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
title: "Gatunek - Movie Box",
|
|
};
|
|
}
|
|
}
|