feat: enhance MovieList and MovieRow components with display type toggle and additional props for improved flexibility
This commit is contained in:
parent
6bd1b289d7
commit
653380f0fb
|
|
@ -47,6 +47,8 @@ export default async function Home() {
|
|||
loadMore
|
||||
icon={<FaPlay />}
|
||||
colors="blue"
|
||||
showFilters={false}
|
||||
displayType="list"
|
||||
/>
|
||||
</section>
|
||||
|
||||
|
|
@ -57,6 +59,8 @@ export default async function Home() {
|
|||
loadMore
|
||||
icon={<FaCalendar />}
|
||||
colors="blue"
|
||||
showFilters={false}
|
||||
displayType="list"
|
||||
/>
|
||||
</section>
|
||||
|
||||
|
|
@ -67,6 +71,8 @@ export default async function Home() {
|
|||
loadMore
|
||||
icon={<FaFire />}
|
||||
colors="red"
|
||||
showFilters={false}
|
||||
displayType="list"
|
||||
/>
|
||||
</section>
|
||||
|
||||
|
|
@ -77,6 +83,8 @@ export default async function Home() {
|
|||
loadMore
|
||||
icon={<FaChartLine />}
|
||||
colors="green"
|
||||
showFilters={false}
|
||||
displayType="list"
|
||||
/>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
import { useOutsideClick } from "@/hooks/useOutsideClick";
|
||||
import { FC, useEffect, useRef, useState } from "react";
|
||||
import { FC, ReactNode, useEffect, useRef, useState } from "react";
|
||||
import { FaFilter } from "react-icons/fa";
|
||||
import { Button } from "../Button";
|
||||
|
||||
|
|
@ -9,11 +9,17 @@ type Props = {
|
|||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
icon?: ReactNode;
|
||||
defaultValue: string;
|
||||
callback?: (value: string) => void;
|
||||
};
|
||||
|
||||
export const Dropdown: FC<Props> = ({ items, defaultValue, callback }) => {
|
||||
export const Dropdown: FC<Props> = ({
|
||||
items,
|
||||
icon,
|
||||
defaultValue,
|
||||
callback,
|
||||
}) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [value, setValue] = useState<string>(defaultValue);
|
||||
|
|
@ -27,7 +33,7 @@ export const Dropdown: FC<Props> = ({ items, defaultValue, callback }) => {
|
|||
return (
|
||||
<div ref={ref} className="relative inline-block">
|
||||
<Button theme="glass" size="icon" onClick={() => setIsOpen(!isOpen)}>
|
||||
<FaFilter />
|
||||
{icon || <FaFilter />}
|
||||
</Button>
|
||||
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -4,9 +4,16 @@ import Link from "next/link";
|
|||
import { FC } from "react";
|
||||
import { FaCalendar, FaClock, FaStar } from "react-icons/fa";
|
||||
|
||||
export const MovieRow: FC<{ movie: Movie; isUpcoming: boolean }> = ({
|
||||
type Props = {
|
||||
movie: Movie;
|
||||
isUpcoming?: boolean;
|
||||
compact?: boolean;
|
||||
};
|
||||
|
||||
export const MovieRow: FC<Props> = ({
|
||||
movie,
|
||||
isUpcoming,
|
||||
isUpcoming = false,
|
||||
compact = false,
|
||||
}) => {
|
||||
const daysSinceRelease = Math.abs(
|
||||
Math.floor(
|
||||
|
|
@ -56,17 +63,19 @@ export const MovieRow: FC<{ movie: Movie; isUpcoming: boolean }> = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`text-xs px-2 py-1 rounded-full font-medium ${
|
||||
isUpcoming
|
||||
? "bg-blue-500/20 text-blue-400"
|
||||
: "bg-green-500/20 text-green-400"
|
||||
}`}
|
||||
>
|
||||
{isUpcoming
|
||||
? `za ${daysSinceRelease} dni`
|
||||
: `od ${daysSinceRelease} dni`}
|
||||
</div>
|
||||
{!compact && (
|
||||
<div
|
||||
className={`text-xs px-2 py-1 rounded-full font-medium ${
|
||||
isUpcoming
|
||||
? "bg-blue-500/20 text-blue-400"
|
||||
: "bg-green-500/20 text-green-400"
|
||||
}`}
|
||||
>
|
||||
{isUpcoming
|
||||
? `za ${daysSinceRelease} dni`
|
||||
: `od ${daysSinceRelease} dni`}
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export const MovieCast: FC<Props> = ({ movieDetails }) => {
|
|||
{limit < movieDetails.credits.cast.length && (
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
theme="teal"
|
||||
theme="glass"
|
||||
size="small"
|
||||
className="mt-6"
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,14 @@ 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";
|
||||
import { FaList } from "react-icons/fa";
|
||||
import { MovieRow } from "@/components/atoms/MovieRow";
|
||||
|
||||
type Props = {
|
||||
heading?: string;
|
||||
icon?: ReactNode;
|
||||
colors?: keyof typeof colorsMap;
|
||||
displayType?: "grid" | "list";
|
||||
|
||||
overrideMovies?: Movie[];
|
||||
|
||||
|
|
@ -44,10 +47,12 @@ export const MovieList: FC<Props> = ({
|
|||
sort: sortType = "releaseDate",
|
||||
sortDirection = "asc",
|
||||
loadMore = false,
|
||||
displayType = "grid",
|
||||
}) => {
|
||||
const { movies: storeMovies } = useGlobalStore();
|
||||
const movies = overrideMovies || storeMovies;
|
||||
|
||||
const [display, setDisplay] = useState<"grid" | "list">(displayType);
|
||||
const [filter, setFilter] = useState({
|
||||
seen: filterSeenInitial,
|
||||
favorites: filterFavoritesInitial,
|
||||
|
|
@ -58,7 +63,7 @@ export const MovieList: FC<Props> = ({
|
|||
sortType
|
||||
);
|
||||
|
||||
const [loaded, setLoaded] = useState(loadMore ? 4 : movies.length);
|
||||
const [loaded, setLoaded] = useState(loadMore ? 8 : movies.length);
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const filteredMovies = movies.filter((movie) => {
|
||||
|
|
@ -189,6 +194,15 @@ export const MovieList: FC<Props> = ({
|
|||
defaultValue={sort}
|
||||
callback={(value) => setSort(value as "title")}
|
||||
/>
|
||||
<Button
|
||||
theme="glass"
|
||||
size="icon"
|
||||
onClick={() =>
|
||||
setDisplay(display === "grid" ? "list" : "grid")
|
||||
}
|
||||
>
|
||||
<FaList />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -201,14 +215,22 @@ export const MovieList: FC<Props> = ({
|
|||
className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-y-6 gap-3 sm:gap-6 mt-8 justify-center"
|
||||
ref={parent}
|
||||
>
|
||||
{sortedMovies.map((movie) => (
|
||||
<MovieCard key={movie.id} layout="aurora" {...movie} />
|
||||
))}
|
||||
{sortedMovies.map((movie) =>
|
||||
display === "grid" ? (
|
||||
<MovieCard key={movie.id} layout="aurora" {...movie} />
|
||||
) : (
|
||||
<MovieRow key={movie.id} movie={movie} compact />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{loadMore && filteredMovies.length > loaded && (
|
||||
<div className="flex justify-center mt-10">
|
||||
<Button theme="teal" onClick={() => setLoaded(movies.length)}>
|
||||
<Button
|
||||
size="small"
|
||||
theme="glass"
|
||||
onClick={() => setLoaded(movies.length)}
|
||||
>
|
||||
Pokaż więcej
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue