From 186e98262b45988357147f3747e5b49a12f28325 Mon Sep 17 00:00:00 2001 From: Norbert Maciaszek Date: Mon, 11 Aug 2025 23:52:29 +0200 Subject: [PATCH] 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. --- src/app/(withGlobalData)/page.tsx | 18 +--- src/components/atoms/MovieCard/index.tsx | 94 ++++++++------------ src/components/molecules/MovieList/index.tsx | 94 ++++++++++---------- 3 files changed, 89 insertions(+), 117 deletions(-) diff --git a/src/app/(withGlobalData)/page.tsx b/src/app/(withGlobalData)/page.tsx index ea8fffb..4fed65e 100644 --- a/src/app/(withGlobalData)/page.tsx +++ b/src/app/(withGlobalData)/page.tsx @@ -3,20 +3,10 @@ import { MovieList } from "@/components/molecules/MovieList"; export default async function Home() { return ( <> - - - - + + + + ); } diff --git a/src/components/atoms/MovieCard/index.tsx b/src/components/atoms/MovieCard/index.tsx index c278274..a2d1795 100644 --- a/src/components/atoms/MovieCard/index.tsx +++ b/src/components/atoms/MovieCard/index.tsx @@ -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 = ({ - id, - title, - releaseDate, - popularity, - overview, - imagePath, - seen, - favorite, - notes, - layout = "default", -}) => { +export const MovieCard: FC = ({ 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 = ({ }; 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 = ({
- { - if (!alreadyInStore) { - handleAdd(); - } - }} - > - {!alreadyInStore && } + + {!alreadyInStore && ( + + )} {alreadyInStore && (
<> @@ -151,12 +122,25 @@ export const MovieCard: FC = ({
)}
+ +

+ + {popularity} +

+

{title}

-

{releaseDate}

+

+ {isReleased ? : } + {release_date} +

@@ -190,7 +174,7 @@ export const MovieCard: FC = ({
Release date:
-
{releaseDate}
+
{release_date}
@@ -235,7 +219,7 @@ export const MovieCard: FC = ({
diff --git a/src/components/molecules/MovieList/index.tsx b/src/components/molecules/MovieList/index.tsx index adf4f0a..60f9cf5 100644 --- a/src/components/molecules/MovieList/index.tsx +++ b/src/components/molecules/MovieList/index.tsx @@ -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 = ({ 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 = ({ 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 = ({ sortedMovies = sortedMovies.reverse(); } - const handleSort = (sort: "title" | "releaseDate" | "popularity") => { - setFilter(sort); - }; - return (
-
+
-
-

{heading}

-
- {showFilters && ( -
- + {heading && ( +
+ {showFilters && ( + setFilter(value as "title")} + /> + )} +

{heading}

)}
@@ -89,16 +91,12 @@ export const MovieList: FC = ({

No movies found

)} {filteredMovies.length > 0 && ( -
+
{sortedMovies.map((movie) => ( - + ))}
)}