feat: enhance actor details page with MovieGallery and Carousel components; implement movie conversion helper for improved movie data handling
This commit is contained in:
parent
cf7ec070fd
commit
3c286e705c
|
|
@ -1,5 +1,10 @@
|
|||
import { MovieCard } from "@/components/atoms/MovieCard";
|
||||
import { ActorHero } from "@/components/molecules/ActorHero";
|
||||
import { Carousel } from "@/components/molecules/Carousel";
|
||||
import { MovieGallery } from "@/components/molecules/MovieGallery";
|
||||
import { convertToMovie } from "@/helpers/convertToMovie";
|
||||
import { TMDB } from "@/lib/tmdb";
|
||||
import { FaStar } from "react-icons/fa";
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
|
|
@ -9,10 +14,29 @@ export default async function Page({
|
|||
const actorId = Number((await params).id);
|
||||
|
||||
const personDetails = await TMDB.getPersonDetails(actorId);
|
||||
const images = {
|
||||
backdrops: personDetails.images.profiles,
|
||||
posters: [],
|
||||
logos: [],
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900">
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 pb-16">
|
||||
<ActorHero personDetails={personDetails} />
|
||||
<MovieGallery images={images} movieTitle={personDetails.name} />
|
||||
<div className="container">
|
||||
<Carousel
|
||||
heading={`Filmy z udziałem ${personDetails.name}`}
|
||||
icon={<FaStar />}
|
||||
colors="purple"
|
||||
>
|
||||
{personDetails.movie_credits.cast.map((movie) => {
|
||||
const convertedMovie = convertToMovie(movie);
|
||||
if (!convertedMovie) return null;
|
||||
return <MovieCard key={movie.id} {...convertedMovie} />;
|
||||
})}
|
||||
</Carousel>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default async function Page({
|
|||
params: Promise<{ id: string }>;
|
||||
}) {
|
||||
const movieId = Number((await params).id);
|
||||
const movieDetails = await TMDB.getMovieDetailsRich(movieId);
|
||||
const movieDetails = await TMDB.getMovieDetails(movieId);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen mt-16">
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ type Props = Movie & {
|
|||
};
|
||||
|
||||
export const MovieCard: FC<Props> = ({
|
||||
layout = "minimal",
|
||||
layout = "aurora",
|
||||
showDayCounter = true,
|
||||
simpleToggle = false,
|
||||
...movie
|
||||
|
|
@ -73,6 +73,8 @@ export const MovieCard: FC<Props> = ({
|
|||
simpleToggle,
|
||||
buttonClass,
|
||||
iconSize,
|
||||
favorite: alreadyInStore?.favorite || movie.favorite,
|
||||
seen: alreadyInStore?.seen || movie.seen,
|
||||
};
|
||||
|
||||
switch (layout) {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export const AuroraLayout: FC<AuroraLayoutProps> = ({
|
|||
>
|
||||
<Link href={`/film/${id}`}>
|
||||
<img
|
||||
className="w-full h-full object-cover transition-all duration-700 group-hover:scale-110 group-hover:brightness-110"
|
||||
className="w-full h-full object-cover transition-all duration-700 group-hover:scale-110 group-hover:brightness-110 bg-gradient-to-b from-purple-600/50 to-emerald-600"
|
||||
src={`http://image.tmdb.org/t/p/w342${poster_path}`}
|
||||
alt={title}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ export const ActorHero: FC<Props> = ({ personDetails }) => {
|
|||
];
|
||||
return (
|
||||
<a
|
||||
key={key}
|
||||
href={url(value as string)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
|
@ -257,14 +258,4 @@ const externalIdsMap = {
|
|||
icon: <FaImdb />,
|
||||
url: (id: string) => `https://www.imdb.com/name/${id}`,
|
||||
},
|
||||
tvrage_id: {
|
||||
label: "TVRage",
|
||||
icon: null,
|
||||
url: (id: string) => `https://www.tvrage.com/people/${id}`,
|
||||
},
|
||||
wikidata_id: {
|
||||
label: "Wikidata",
|
||||
icon: null,
|
||||
url: (id: string) => `https://www.wikidata.org/wiki/${id}`,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
FaGlobe,
|
||||
FaEye,
|
||||
} from "react-icons/fa";
|
||||
import { convertToMovie } from "@/helpers/convertToMovie";
|
||||
|
||||
type Props = {
|
||||
movieDetails: MovieDetailsRich;
|
||||
|
|
@ -33,37 +34,24 @@ export const HeroMovie: FC<Props> = ({ movieDetails }) => {
|
|||
return `${hours}h ${mins}m`;
|
||||
};
|
||||
|
||||
// Convert TMDB movie to our Movie type.
|
||||
const convertToMovie = () => ({
|
||||
id: movieDetails.id,
|
||||
title: movieDetails.title,
|
||||
adult: movieDetails.adult,
|
||||
backdrop_path: movieDetails.backdrop_path || "",
|
||||
genre_ids: movieDetails.genres.map((g) => g.id).join(","),
|
||||
original_language: movieDetails.original_language,
|
||||
original_title: movieDetails.original_title,
|
||||
overview: movieDetails.overview || "",
|
||||
popularity: movieDetails.popularity,
|
||||
poster_path: movieDetails.poster_path || "",
|
||||
release_date: movieDetails.release_date,
|
||||
video: movieDetails.video,
|
||||
vote_average: movieDetails.vote_average,
|
||||
vote_count: movieDetails.vote_count,
|
||||
favorite: false,
|
||||
seen: false,
|
||||
});
|
||||
const convertedMovie = convertToMovie(movieDetails);
|
||||
|
||||
// Convert TMDB movie to our Movie type.
|
||||
const handleAddToList = () => {
|
||||
if (isInStore) {
|
||||
deleteMovie(movieDetails.id);
|
||||
} else {
|
||||
addMovie(convertToMovie());
|
||||
if (convertedMovie) {
|
||||
addMovie(convertedMovie);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleFavorite = () => {
|
||||
if (!isInStore) {
|
||||
addMovie({ ...convertToMovie(), favorite: true });
|
||||
if (convertedMovie) {
|
||||
addMovie({ ...convertedMovie, favorite: true });
|
||||
}
|
||||
} else {
|
||||
updateMovie(movieDetails.id, { favorite: !isFavorite });
|
||||
}
|
||||
|
|
@ -71,7 +59,9 @@ export const HeroMovie: FC<Props> = ({ movieDetails }) => {
|
|||
|
||||
const handleToggleSeen = () => {
|
||||
if (!isInStore) {
|
||||
addMovie({ ...convertToMovie(), seen: true });
|
||||
if (convertedMovie) {
|
||||
addMovie({ ...convertedMovie, seen: true });
|
||||
}
|
||||
} else {
|
||||
updateMovie(movieDetails.id, { seen: !isSeen });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export const RecommendedMovies: FC<Props> = ({ movies }) => {
|
|||
<Carousel
|
||||
heading="Rekomendowane filmy"
|
||||
icon={<FaStar />}
|
||||
iconColor="bg-gradient-to-r from-yellow-500 to-orange-500"
|
||||
colors="yellow"
|
||||
>
|
||||
{movies.results.map((movie) => (
|
||||
<MovieCard
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
import { Movie } from "@/types/global";
|
||||
|
||||
export const convertToMovie = (
|
||||
movie: any,
|
||||
override?: Partial<Movie>
|
||||
): Movie | null => {
|
||||
if (!movie.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: movie.id,
|
||||
title: movie.title,
|
||||
adult: movie.adult,
|
||||
backdrop_path: movie.backdrop_path || "",
|
||||
genre_ids: movie.genres?.join(",") || "",
|
||||
original_language: movie.original_language,
|
||||
original_title: movie.original_title,
|
||||
overview: movie.overview || "",
|
||||
popularity: movie.popularity,
|
||||
poster_path: movie.poster_path || "",
|
||||
release_date: movie.release_date,
|
||||
video: movie.video,
|
||||
vote_average: movie.vote_average,
|
||||
vote_count: movie.vote_count,
|
||||
favorite: false,
|
||||
seen: false,
|
||||
};
|
||||
};
|
||||
Loading…
Reference in New Issue