Refactor MovieCard and MovieList components: streamline props by integrating Movie type, enhance filtering logic, and improve UI responsiveness with a new Dropdown for sorting options.
This commit is contained in:
@@ -6,59 +6,34 @@ import { useGlobalStore } from "@/app/store/globalStore";
|
||||
import { MdFavorite, MdFavoriteBorder, MdOutlinePostAdd } from "react-icons/md";
|
||||
import { RxEyeClosed, RxEyeOpen } from "react-icons/rx";
|
||||
import { IoMdRemoveCircleOutline } from "react-icons/io";
|
||||
import { Movie } from "@/types/global";
|
||||
import { FaFire } from "react-icons/fa";
|
||||
import { RiCalendarCheckLine, RiCalendarScheduleLine } from "react-icons/ri";
|
||||
|
||||
type Props = {
|
||||
id: number;
|
||||
title: string;
|
||||
overview: string;
|
||||
releaseDate: string;
|
||||
popularity: number;
|
||||
imagePath: string;
|
||||
seen: boolean;
|
||||
favorite: boolean;
|
||||
notes?: string;
|
||||
type Props = Movie & {
|
||||
layout?: "default" | "zeus";
|
||||
};
|
||||
|
||||
const buttonClass =
|
||||
"p-4 text-sm transition-colors cursor-pointer text-center group/toggle";
|
||||
|
||||
export const MovieCard: FC<Props> = ({
|
||||
id,
|
||||
title,
|
||||
releaseDate,
|
||||
popularity,
|
||||
overview,
|
||||
imagePath,
|
||||
seen,
|
||||
favorite,
|
||||
notes,
|
||||
layout = "default",
|
||||
}) => {
|
||||
export const MovieCard: FC<Props> = ({ layout = "default", ...movie }) => {
|
||||
const {
|
||||
movies,
|
||||
addMovie: addMovieToStore,
|
||||
deleteMovie: deleteMovieFromStore,
|
||||
updateMovie: updateMovieInStore,
|
||||
} = useGlobalStore();
|
||||
console.log(movies);
|
||||
const { id, title, overview, popularity, release_date, poster_path } = movie;
|
||||
const alreadyInStore = movies.find((m) => m.id === id);
|
||||
|
||||
const isReleased = new Date(releaseDate) < new Date();
|
||||
const iconSize = 64;
|
||||
const isReleased = new Date(release_date) < new Date();
|
||||
const iconSize = 48;
|
||||
|
||||
const seen = movie.seen;
|
||||
const favorite = movie.favorite;
|
||||
|
||||
const handleAdd = async () => {
|
||||
const movie = {
|
||||
id,
|
||||
title,
|
||||
overview,
|
||||
popularity,
|
||||
releaseDate,
|
||||
posterPath: imagePath,
|
||||
seen: 0,
|
||||
favorite: 0,
|
||||
notes: "",
|
||||
};
|
||||
await addMovie(movie);
|
||||
addMovieToStore(movie);
|
||||
};
|
||||
@@ -69,13 +44,13 @@ export const MovieCard: FC<Props> = ({
|
||||
};
|
||||
|
||||
const handleSeen = async () => {
|
||||
await updateMovie(id, { seen: seen ? 0 : 1 });
|
||||
updateMovieInStore(id, { seen: seen ? 0 : 1 });
|
||||
await updateMovie(id, { seen: !seen });
|
||||
updateMovieInStore(id, { seen: !seen });
|
||||
};
|
||||
|
||||
const handleFavorite = async () => {
|
||||
await updateMovie(id, { favorite: favorite ? 0 : 1 });
|
||||
updateMovieInStore(id, { favorite: favorite ? 0 : 1 });
|
||||
await updateMovie(id, { favorite: !favorite });
|
||||
updateMovieInStore(id, { favorite: !favorite });
|
||||
};
|
||||
|
||||
if (layout === "zeus") {
|
||||
@@ -83,19 +58,15 @@ export const MovieCard: FC<Props> = ({
|
||||
<article className="flex flex-col w-full shadow-md rounded-lg overflow-hidden bg-white">
|
||||
<figure className="relative ">
|
||||
<img
|
||||
className="w-full object-cover"
|
||||
style={{ height: "420px" }}
|
||||
src={`http://image.tmdb.org/t/p/w342/${imagePath}`}
|
||||
className="w-full object-cover xl:h-[420px]"
|
||||
src={`http://image.tmdb.org/t/p/w342${poster_path}`}
|
||||
/>
|
||||
<span
|
||||
className="absolute inset-0 bg-black/30 backdrop-blur-md opacity-0 hover:opacity-100 transition-opacity duration-300 flex items-center justify-center cursor-pointer"
|
||||
onClick={() => {
|
||||
if (!alreadyInStore) {
|
||||
handleAdd();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{!alreadyInStore && <MdOutlinePostAdd size={64} color="white" />}
|
||||
<span className="absolute inset-0 bg-black/30 backdrop-blur-md opacity-0 hover-any:opacity-100 transition-opacity duration-300 flex items-center justify-center cursor-pointer">
|
||||
{!alreadyInStore && (
|
||||
<button className={buttonClass} onClick={handleAdd}>
|
||||
<MdOutlinePostAdd size={64} color="white" />
|
||||
</button>
|
||||
)}
|
||||
{alreadyInStore && (
|
||||
<div className="flex flex-col">
|
||||
<>
|
||||
@@ -151,12 +122,25 @@ export const MovieCard: FC<Props> = ({
|
||||
</div>
|
||||
)}
|
||||
</span>
|
||||
<span className="absolute top-0 right-0 bg-black/50 px-2 py-1 rounded-bl-lg">
|
||||
<p className="text-sm text-white flex items-center gap-1">
|
||||
<FaFire />
|
||||
{popularity}
|
||||
</p>
|
||||
</span>
|
||||
</figure>
|
||||
<div className="p-4">
|
||||
<div className="flex justify-between">
|
||||
<h2 className="text-xl leading-[1.1] font-bold">{title}</h2>
|
||||
</div>
|
||||
<p className="text-sm text-gray-500 mt-2">{releaseDate}</p>
|
||||
<p
|
||||
className={`text-sm mt-2 flex items-center gap-1 leading-[1.1] ${
|
||||
isReleased ? "text-green-700" : "text-yellow-700"
|
||||
}`}
|
||||
>
|
||||
{isReleased ? <RiCalendarCheckLine /> : <RiCalendarScheduleLine />}
|
||||
{release_date}
|
||||
</p>
|
||||
<div className="text-xs text-gray-400 mt-4">
|
||||
<ReadMore text={overview} />
|
||||
</div>
|
||||
@@ -190,7 +174,7 @@ export const MovieCard: FC<Props> = ({
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="text-sm text-gray-400">Release date:</div>
|
||||
<div className="release">{releaseDate}</div>
|
||||
<div className="release">{release_date}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -235,7 +219,7 @@ export const MovieCard: FC<Props> = ({
|
||||
<figure className="absolute inset-0 w-full bottom-[20%]">
|
||||
<img
|
||||
className="w-full h-96 object-cover"
|
||||
src={`http://image.tmdb.org/t/p/w342/${imagePath}`}
|
||||
src={`http://image.tmdb.org/t/p/w342${poster_path}`}
|
||||
/>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user