From 6bd1b289d7e742803dbfe31001d177a797612854 Mon Sep 17 00:00:00 2001 From: Norbert Maciaszek Date: Thu, 21 Aug 2025 21:46:53 +0200 Subject: [PATCH] feat: simplify MovieList component by consolidating filters and adding new Label component for enhanced filtering options --- src/app/page.tsx | 14 +- src/components/atoms/Dropdown/index.tsx | 14 +- src/components/atoms/Label/index.tsx | 20 +++ src/components/molecules/MovieList/index.tsx | 136 ++++++++++++++----- 4 files changed, 132 insertions(+), 52 deletions(-) create mode 100644 src/components/atoms/Label/index.tsx diff --git a/src/app/page.tsx b/src/app/page.tsx index 78c171e..76e6738 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,19 +5,7 @@ export default async function Home() { return ( <> - - - - + ); } diff --git a/src/components/atoms/Dropdown/index.tsx b/src/components/atoms/Dropdown/index.tsx index 9676320..0731934 100644 --- a/src/components/atoms/Dropdown/index.tsx +++ b/src/components/atoms/Dropdown/index.tsx @@ -2,6 +2,7 @@ import { useOutsideClick } from "@/hooks/useOutsideClick"; import { FC, useEffect, useRef, useState } from "react"; import { FaFilter } from "react-icons/fa"; +import { Button } from "../Button"; type Props = { items: { @@ -25,15 +26,12 @@ export const Dropdown: FC = ({ items, defaultValue, callback }) => { return (
- +
= ({ items, defaultValue, callback }) => { onClick={() => { setValue(item.value); }} - className={`block px-4 py-3 text-sm text-gray-600 capitalize transition-colors duration-300 transform hover:bg-primary-50 cursor-pointer ${ - value === item.value ? "bg-primary-50" : "" + className={`block px-4 py-3 text-sm text-slate-400 capitalize transition-colors duration-300 transform hover:bg-slate-700/80 cursor-pointer ${ + value === item.value ? "bg-slate-700/80" : "" }`} > {item.label} diff --git a/src/components/atoms/Label/index.tsx b/src/components/atoms/Label/index.tsx new file mode 100644 index 0000000..cbe8c8f --- /dev/null +++ b/src/components/atoms/Label/index.tsx @@ -0,0 +1,20 @@ +import { FC, HTMLAttributes } from "react"; + +type Props = HTMLAttributes & { + active?: boolean; +}; + +export const Label: FC = ({ children, className, active, ...props }) => { + return ( +
+ + {children} + +
+ ); +}; diff --git a/src/components/molecules/MovieList/index.tsx b/src/components/molecules/MovieList/index.tsx index 3fe8e10..6780b1d 100644 --- a/src/components/molecules/MovieList/index.tsx +++ b/src/components/molecules/MovieList/index.tsx @@ -6,6 +6,7 @@ import { useGlobalStore } from "@/app/store/globalStore"; import { Dropdown } from "@/components/atoms/Dropdown"; import { useAutoAnimate } from "@formkit/auto-animate/react"; import { Button } from "@/components/atoms/Button"; +import { Label } from "@/components/atoms/Label"; type Props = { heading?: string; @@ -14,13 +15,14 @@ type Props = { overrideMovies?: Movie[]; + showFilters?: boolean; filterSeen?: 0 | 1; filterFavorites?: 0 | 1; filterUpcoming?: 0 | 1; filterReleased?: 0 | 1; fluid?: boolean; - showFilters?: boolean; + showSorting?: boolean; sort?: "title" | "releaseDate" | "popularity"; sortDirection?: "asc" | "desc"; @@ -32,54 +34,62 @@ export const MovieList: FC = ({ icon, colors = "white", overrideMovies, - filterSeen, - filterFavorites, - filterUpcoming, - filterReleased, - fluid = false, showFilters = true, - sort = "releaseDate", + filterSeen: filterSeenInitial, + filterFavorites: filterFavoritesInitial, + filterUpcoming: filterUpcomingInitial, + filterReleased: filterReleasedInitial, + fluid = false, + showSorting = true, + sort: sortType = "releaseDate", sortDirection = "asc", loadMore = false, }) => { const { movies: storeMovies } = useGlobalStore(); const movies = overrideMovies || storeMovies; - const [filter, setFilter] = useState<"title" | "releaseDate" | "popularity">( - sort + const [filter, setFilter] = useState({ + seen: filterSeenInitial, + favorites: filterFavoritesInitial, + upcoming: filterUpcomingInitial, + released: filterReleasedInitial, + }); + const [sort, setSort] = useState<"title" | "releaseDate" | "popularity">( + sortType ); + const [loaded, setLoaded] = useState(loadMore ? 4 : movies.length); const [parent] = useAutoAnimate(); const filteredMovies = movies.filter((movie) => { let result = true; const today = new Date(); - if (filterSeen !== undefined) { - result = movie.seen === !!filterSeen; + if (filter.seen !== undefined) { + result = movie.seen === !!filter.seen; } - if (filterFavorites !== undefined) { - result = result && movie.favorite === !!filterFavorites; + if (filter.favorites !== undefined) { + result = result && movie.favorite === !!filter.favorites; } - if (filterUpcoming !== undefined) { + if (filter.upcoming !== undefined) { const releaseDate = new Date(movie.release_date); result = - result && filterUpcoming ? releaseDate > today : releaseDate < today; + result && filter.upcoming ? releaseDate > today : releaseDate < today; } - if (filterReleased !== undefined) { + if (filter.released !== undefined) { const releaseDate = new Date(movie.release_date); result = - result && filterReleased ? releaseDate < today : releaseDate > today; + result && filter.released ? releaseDate < today : releaseDate > today; } return result; }); let sortedMovies = filteredMovies.sort((a, b) => { - if (filter === "title") return a.title.localeCompare(b.title); - if (filter === "releaseDate") + if (sort === "title") return a.title.localeCompare(b.title); + if (sort === "releaseDate") return ( new Date(b.release_date).getTime() - new Date(a.release_date).getTime() ); - if (filter === "popularity") return b.popularity - a.popularity; + if (sort === "popularity") return b.popularity - a.popularity; return 0; }); @@ -89,6 +99,16 @@ export const MovieList: FC = ({ sortedMovies = sortedMovies.reverse(); } + const handleFilter = (key?: keyof typeof filter) => { + setFilter({ + seen: filterSeenInitial, + favorites: filterFavoritesInitial, + upcoming: filterUpcomingInitial, + released: filterReleasedInitial, + ...(key && { [key]: 1 }), + }); + }; + return (
@@ -101,17 +121,6 @@ export const MovieList: FC = ({ {icon}
)} - {showFilters && !icon && ( - setFilter(value as "title")} - /> - )}

@@ -119,6 +128,71 @@ export const MovieList: FC = ({

)} + {showFilters && ( +
+ + + + + + + {showSorting && ( +
+ setSort(value as "title")} + /> +
+ )} +
+ )} {filteredMovies.length === 0 && (

Brak filmów

)}