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:
@@ -1,15 +1,21 @@
|
||||
"use client";
|
||||
import { FC, useState } from "react";
|
||||
import { MovieCard } from "@/components/atoms/MovieCard";
|
||||
import { Movie } from "@/types/global";
|
||||
import { useGlobalStore } from "@/app/store/globalStore";
|
||||
import { Dropdown } from "@/components/atoms/Dropdown";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
|
||||
type Props = {
|
||||
heading: string;
|
||||
filterSeen?: 0 | 1;
|
||||
filterFavorites?: 0 | 1;
|
||||
filterUpcoming?: 0 | 1;
|
||||
filterReleased?: 0 | 1;
|
||||
heading?: string;
|
||||
overrideMovies?: Movie[];
|
||||
|
||||
filterSeen?: boolean;
|
||||
filterFavorites?: boolean;
|
||||
filterUpcoming?: boolean;
|
||||
filterReleased?: boolean;
|
||||
|
||||
fluid?: boolean;
|
||||
showFilters?: boolean;
|
||||
sort?: "title" | "releaseDate" | "popularity";
|
||||
sortDirection?: "asc" | "desc";
|
||||
@@ -17,28 +23,32 @@ type Props = {
|
||||
|
||||
export const MovieList: FC<Props> = ({
|
||||
heading,
|
||||
overrideMovies,
|
||||
filterSeen,
|
||||
filterFavorites,
|
||||
filterUpcoming,
|
||||
filterReleased,
|
||||
showFilters = false,
|
||||
sort = "title",
|
||||
fluid = false,
|
||||
showFilters = true,
|
||||
sort = "releaseDate",
|
||||
sortDirection = "asc",
|
||||
}) => {
|
||||
const { movies: storeMovies } = useGlobalStore();
|
||||
const [filter, setFilter] = useState<"title" | "releaseDate" | "popularity">(
|
||||
sort
|
||||
);
|
||||
const { movies } = useGlobalStore();
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const movies = overrideMovies || storeMovies;
|
||||
|
||||
const filteredMovies = movies.filter((movie) => {
|
||||
let result = true;
|
||||
if (typeof filterSeen === "number") result = movie.seen === filterSeen;
|
||||
if (typeof filterFavorites === "number")
|
||||
result = result && movie.favorite === filterFavorites;
|
||||
if (typeof filterUpcoming === "number")
|
||||
result = result && new Date(movie.releaseDate) > new Date();
|
||||
if (typeof filterReleased === "number")
|
||||
result = result && new Date(movie.releaseDate) < new Date();
|
||||
if (filterSeen) result = !!movie.seen;
|
||||
if (filterFavorites) result = result && !!movie.favorite;
|
||||
if (filterUpcoming)
|
||||
result = result && new Date(movie.release_date) > new Date();
|
||||
if (filterReleased)
|
||||
result = result && new Date(movie.release_date) < new Date();
|
||||
return result;
|
||||
});
|
||||
|
||||
@@ -46,7 +56,7 @@ export const MovieList: FC<Props> = ({
|
||||
if (filter === "title") return a.title.localeCompare(b.title);
|
||||
if (filter === "releaseDate")
|
||||
return (
|
||||
new Date(b.releaseDate).getTime() - new Date(a.releaseDate).getTime()
|
||||
new Date(b.release_date).getTime() - new Date(a.release_date).getTime()
|
||||
);
|
||||
if (filter === "popularity") return b.popularity - a.popularity;
|
||||
return 0;
|
||||
@@ -56,32 +66,24 @@ export const MovieList: FC<Props> = ({
|
||||
sortedMovies = sortedMovies.reverse();
|
||||
}
|
||||
|
||||
const handleSort = (sort: "title" | "releaseDate" | "popularity") => {
|
||||
setFilter(sort);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="my-4 md:my-10">
|
||||
<div className="container">
|
||||
<div className={`${fluid ? "max-w-full" : "container"}`}>
|
||||
<div className="row">
|
||||
<div className="col-12 md:col-10">
|
||||
<h2 className="text-2xl font-bold">{heading}</h2>
|
||||
</div>
|
||||
{showFilters && (
|
||||
<div className="col-12 md:col-2">
|
||||
<select
|
||||
className="bg-accent/70 text-white px-4 py-2 rounded-md w-full hover:bg-primary transition-colors cursor-pointer"
|
||||
value={filter}
|
||||
onChange={(e) =>
|
||||
handleSort(
|
||||
e.target.value as "title" | "releaseDate" | "popularity"
|
||||
)
|
||||
}
|
||||
>
|
||||
<option value="title">Title</option>
|
||||
<option value="releaseDate">Release Date</option>
|
||||
<option value="popularity">Popularity</option>
|
||||
</select>
|
||||
{heading && (
|
||||
<div className="col-12 md:col-10 flex gap-2 items-center">
|
||||
{showFilters && (
|
||||
<Dropdown
|
||||
items={[
|
||||
{ label: "Title", value: "title" },
|
||||
{ label: "Release Date", value: "releaseDate" },
|
||||
{ label: "Popularity", value: "popularity" },
|
||||
]}
|
||||
defaultValue={filter}
|
||||
callback={(value) => setFilter(value as "title")}
|
||||
/>
|
||||
)}
|
||||
<h2 className="text-2xl font-bold">{heading}</h2>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -89,16 +91,12 @@ export const MovieList: FC<Props> = ({
|
||||
<p className="text-text/60 text-sm">No movies found</p>
|
||||
)}
|
||||
{filteredMovies.length > 0 && (
|
||||
<div className="grid grid-auto-cols-282 gap-6 mt-8 justify-center">
|
||||
<div
|
||||
className="grid grid-cols-1 xs:grid-cols-2 sm:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-y-6 gap-3 sm:gap-6 mt-8 justify-center"
|
||||
ref={parent}
|
||||
>
|
||||
{sortedMovies.map((movie) => (
|
||||
<MovieCard
|
||||
key={movie.id}
|
||||
layout="zeus"
|
||||
{...movie}
|
||||
imagePath={movie.posterPath || ""}
|
||||
seen={movie.seen === 1}
|
||||
favorite={movie.favorite === 1}
|
||||
/>
|
||||
<MovieCard key={movie.id} layout="zeus" {...movie} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user