From 056da2e5d6cfe09f381f658d735d957315061968 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 22 Jan 2023 16:32:16 -0800 Subject: [PATCH 01/23] [Polee] First Work on Player Feature --- components/Card.tsx | 12 ++++ components/GenreBadges.tsx | 68 ++++++++++++++++++ components/Hero.tsx | 71 +++++++++++++++++++ package-lock.json | 14 +++- package.json | 3 +- pages/movies/watch/[id]/index.tsx | 113 ++++++++++++++++++++++++++++++ styles/globals.css | 1 + typings.ts | 8 +++ 8 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 components/GenreBadges.tsx create mode 100644 components/Hero.tsx create mode 100644 pages/movies/watch/[id]/index.tsx diff --git a/components/Card.tsx b/components/Card.tsx index d4e8c26..aad269d 100644 --- a/components/Card.tsx +++ b/components/Card.tsx @@ -1,8 +1,19 @@ import Image from "next/image"; import { Movie, TvShow } from "../typings"; import moment from "moment"; +import Link from "next/link"; +import { useRouter } from "next/router"; const MovieCard = ({ movie }: { movie: Movie }) => { + const router = useRouter(); + + const handleClick = () => { + router.push({ + pathname: `/movies/watch/[id]`, + query: { id: movie.id }, + }); + }; + if (movie.poster_path === null) return null; if (moment(movie.release_date).isAfter(moment())) return null; return ( @@ -14,6 +25,7 @@ const MovieCard = ({ movie }: { movie: Movie }) => { src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} alt={movie.title} width={500} + onClick={handleClick} height={550} /> diff --git a/components/GenreBadges.tsx b/components/GenreBadges.tsx new file mode 100644 index 0000000..9801b89 --- /dev/null +++ b/components/GenreBadges.tsx @@ -0,0 +1,68 @@ +import { Badge, MediaQuery } from "@mantine/core"; +import React from "react"; +import { MapGenreMovie } from "../typings"; +import { FastAverageColor } from "fast-average-color"; +import { useEffect, useState } from "react"; + +interface GenreBadgesProps { + genres: { + id: number; + name: string; + }[]; + poster_path?: string; // will be used for gradient + backdrop_path?: string; // will be used for gradient (if poster_path is not available) +} + +const GenreBadges = ({ + genres, +}: GenreBadgesProps) => { + // const [color, setColor] = useState("gray"); + + useEffect(() => { + // console.log(genres); + // const fac = new FastAverageColor(); + // const color = fac + // //poster_path + // .getColorAsync(`https://image.tmdb.org/t/p/w185${poster_path}`) + // .then((color) => { + // // setColor(color.hex); + // console.log(color); + // }); + }, []); + return ( + <> + +
+ {genres && + genres.map((genre, index) => { + console.log(genre); + return ( + + {MapGenreMovie[genre.id]} + + ); + })} +
+
+ + ); +}; + +export default GenreBadges; diff --git a/components/Hero.tsx b/components/Hero.tsx new file mode 100644 index 0000000..e29e2d0 --- /dev/null +++ b/components/Hero.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { Text } from "@mantine/core"; +import GenreBadges from "./GenreBadges"; +import { MediaQuery } from "@mantine/core"; + +interface HeroProps { + backdrop_path: string; + title: string; + poster_path: string; + genres: { id: number; name: string }[]; +} + +const Hero = ({ backdrop_path, title, poster_path, genres }: HeroProps) => { + return ( +
+
+
+
+
+
+

+ {/* Possibly get secondary color to form better gradient */} + + {title} + +

+ + {/* */} +
+
+ + {/*
*/} +
+ ); +}; + +export default Hero; diff --git a/package-lock.json b/package-lock.json index f11e4de..83f8ca7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "movie-u", + "name": "NyumatFlix", "lockfileVersion": 3, "requires": true, "packages": { @@ -28,10 +28,10 @@ "axios": "^1.2.2", "dayjs": "^1.11.7", "embla-carousel-react": "^7.0.5", + "fast-average-color": "^9.3.0", "framer-motion": "^8.2.4", "moment": "^2.29.4", "next": "latest", - "prettier": "^2.8.3", "react": "18.2.0", "react-dom": "18.2.0", "react-infinite-scroll-component": "^6.1.0", @@ -43,6 +43,7 @@ "@types/react-dom": "18.0.6", "autoprefixer": "^10.4.12", "postcss": "^8.4.18", + "prettier": "^2.8.3", "tailwindcss": "^3.2.4", "typescript": "4.9.4" } @@ -2003,6 +2004,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fast-average-color": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-9.3.0.tgz", + "integrity": "sha512-FlPROSqDMOnoBgkFhWMHJODPvpS0Od0WDpedcKq4U/t0JVapGAkblNwxOr75qT+ZNd0dQM4qlgqrtnXbCJ8cNg==", + "engines": { + "node": ">= 12" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2795,6 +2804,7 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", + "dev": true, "bin": { "prettier": "bin-prettier.js" }, diff --git a/package.json b/package.json index c94e025..21ac4d3 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "axios": "^1.2.2", "dayjs": "^1.11.7", "embla-carousel-react": "^7.0.5", + "fast-average-color": "^9.3.0", "framer-motion": "^8.2.4", "moment": "^2.29.4", "next": "latest", @@ -39,12 +40,12 @@ "swr": "^2.0.0" }, "devDependencies": { - "prettier": "^2.8.3", "@types/node": "18.11.3", "@types/react": "18.0.21", "@types/react-dom": "18.0.6", "autoprefixer": "^10.4.12", "postcss": "^8.4.18", + "prettier": "^2.8.3", "tailwindcss": "^3.2.4", "typescript": "4.9.4" } diff --git a/pages/movies/watch/[id]/index.tsx b/pages/movies/watch/[id]/index.tsx new file mode 100644 index 0000000..d7b8fe0 --- /dev/null +++ b/pages/movies/watch/[id]/index.tsx @@ -0,0 +1,113 @@ +import React from "react"; +import { useRouter } from "next/router"; +import PopOutTransition from "../../../../components/PopOutTransition"; +import { useEffect } from "react"; +import Hero from "../../../../components/Hero"; +import axios from "axios"; +import { Movie } from "../../../../typings"; +import GenreBadges from "../../../../components/GenreBadges"; +import { Text } from "@mantine/core"; +import moment from "moment"; + +interface PlayerProps { + movie: Movie; +} + +const Player = ({ movie }: PlayerProps) => { + const router = useRouter(); + const { id } = router.query; + + useEffect(() => { + console.log(id); + }, [id]); + + return ( + <> +
+ +
+ + + Released: {moment(movie.release_date).format("MMMM Do, YYYY")} + + + {/* Badges don't have a great spot yet. */} + +
+

+ + Genres + +

+ + +
+ +
+

+ + Overview: + +

+

+ + {movie.overview} + +

+
+ + ); +}; + +export async function getServerSideProps(context: any) { + const { id } = context.query; + + let response = await axios.get( + `https://api.themoviedb.org/3/movie/${id}?api_key=${process.env.API_KEY}&language=en-US`, + ); + + console.log(response.data.genres.map((genre: any) => [genre.id, genre.name])); + + return { + props: { + movie: response.data, + }, + }; +} + +export default Player; diff --git a/styles/globals.css b/styles/globals.css index 6f4f38d..f4c80a0 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -17,3 +17,4 @@ @apply min-w-full; @apply -z-50; } + diff --git a/typings.ts b/typings.ts index 096f51c..542c29e 100644 --- a/typings.ts +++ b/typings.ts @@ -73,5 +73,13 @@ export enum MapGenreMovie { Fantasy = 14, History = 36, Horror = 27, + "Science Fiction" = 878, + Thriller = 53, + War = 10752, + Western = 37, + Mystery = 9648, + Music = 10402, + Romance = 10749, + "TV Movie" = 10770, } From 3f9144a5f85fcbdddbbb43f6ee48245dca80ba46 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 27 Jan 2023 19:32:43 -0800 Subject: [PATCH 02/23] [Pole & Deps] New Player Components & Lottie Package --- components/CastCarousel.tsx | 56 ++++++++++++ components/GenreBadges.tsx | 5 +- components/Hero.tsx | 4 +- components/SideBar.tsx | 39 +++++--- package-lock.json | 18 ++++ package.json | 1 + pages/movies/watch/[id]/index.tsx | 146 ++++++++++++++++-------------- 7 files changed, 184 insertions(+), 85 deletions(-) create mode 100644 components/CastCarousel.tsx diff --git a/components/CastCarousel.tsx b/components/CastCarousel.tsx new file mode 100644 index 0000000..9683b05 --- /dev/null +++ b/components/CastCarousel.tsx @@ -0,0 +1,56 @@ +import { Carousel } from "@mantine/carousel"; +import { Actor } from "../typings"; + +function CastCarousel({ actors }: { actors: Actor[] }) { + return ( + actors && ( + + {actors.map((actor: Actor) => ( +
+
+ ... +
+

+ {actor.name} +

+
+ ))} +
+ ) + ); +} + +export default CastCarousel; diff --git a/components/GenreBadges.tsx b/components/GenreBadges.tsx index 9801b89..a11d1a3 100644 --- a/components/GenreBadges.tsx +++ b/components/GenreBadges.tsx @@ -13,9 +13,7 @@ interface GenreBadgesProps { backdrop_path?: string; // will be used for gradient (if poster_path is not available) } -const GenreBadges = ({ - genres, -}: GenreBadgesProps) => { +const GenreBadges = ({ genres }: GenreBadgesProps) => { // const [color, setColor] = useState("gray"); useEffect(() => { @@ -44,7 +42,6 @@ const GenreBadges = ({ > {genres && genres.map((genre, index) => { - console.log(genre); return ( { }} > -
-

+
+

{/* Possibly get secondary color to form better gradient */} { return MapGenreMovie[parseInt(item)]; }); let parsed = res.join(",").substring(1).toLowerCase(); + router.push( { pathname: router.pathname, @@ -29,18 +31,24 @@ const SideBar = ({ filter, setFilter, setSearchTerm }: SideBarProps) => { ); }; - useEffect(() => { - if (filter.length === 1) { - router.push( - { - pathname: router.pathname, - query: { filter: [] }, - }, - `${router.pathname}`, - { shallow: true }, - ); - } - }, [router.query.filter]); + useEffect( + () => { + // This is the code that causes the issue with the routing. + // if (filter.length === 1) { + // router.push( + // { + // pathname: router.pathname, + // query: { filter: [] }, + // }, + // `${router.pathname}`, + // { shallow: true }, + // ); + // } + }, + [ + // router.query.filter + ], + ); return (
@@ -79,6 +87,13 @@ const SideBar = ({ filter, setFilter, setSearchTerm }: SideBarProps) => { Fantasy History Horror + Music + Mystery + Romance + Science Fiction + TV Movie + Thriller + War
diff --git a/package-lock.json b/package-lock.json index 83f8ca7..8e5ecdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "embla-carousel-react": "^7.0.5", "fast-average-color": "^9.3.0", "framer-motion": "^8.2.4", + "lottie-react": "^2.3.1", "moment": "^2.29.4", "next": "latest", "react": "18.2.0", @@ -2404,6 +2405,23 @@ "loose-envify": "cli.js" } }, + "node_modules/lottie-react": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.3.1.tgz", + "integrity": "sha512-8cxd6XZZtECT6LoAhCftRdYrEpHxiouvB5EPiYA+TtCG5LHNYAdMS9IVIHcxKtWnpo7x16QfCLj1XLXZpaN81A==", + "dependencies": { + "lottie-web": "^5.9.4" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.10.2.tgz", + "integrity": "sha512-d0PFIGiwuMsJYaF4uPo+qG8dEorlI+xFI2zrrFtE1bGO4WoLIz+NjremxEq1swpR7juR10aeOtmNh3d6G3ub0A==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", diff --git a/package.json b/package.json index 21ac4d3..ba94874 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "embla-carousel-react": "^7.0.5", "fast-average-color": "^9.3.0", "framer-motion": "^8.2.4", + "lottie-react": "^2.3.1", "moment": "^2.29.4", "next": "latest", "react": "18.2.0", diff --git a/pages/movies/watch/[id]/index.tsx b/pages/movies/watch/[id]/index.tsx index d7b8fe0..96dab9e 100644 --- a/pages/movies/watch/[id]/index.tsx +++ b/pages/movies/watch/[id]/index.tsx @@ -6,106 +6,118 @@ import Hero from "../../../../components/Hero"; import axios from "axios"; import { Movie } from "../../../../typings"; import GenreBadges from "../../../../components/GenreBadges"; -import { Text } from "@mantine/core"; import moment from "moment"; +import CastCarousel from "../../../../components/CastCarousel"; +import { Text, Rating, Group, Stack } from "@mantine/core"; +import { Actor, CreditsReponse } from "../../../../typings"; +import MoviePlayer from "../../../../components/MoviePlayer"; +import useAvailable from "../../../../hooks/useAvailable"; interface PlayerProps { movie: Movie; + actors: Actor[]; } -const Player = ({ movie }: PlayerProps) => { +const Player = ({ movie, actors }: PlayerProps) => { const router = useRouter(); const { id } = router.query; + const ts_id = parseInt(id as string); - useEffect(() => { - console.log(id); - }, [id]); + const [isAvailable] = useAvailable(ts_id); - return ( - <> -
- -
+ console.log(isAvailable); + return ( +
- Released: {moment(movie.release_date).format("MMMM Do, YYYY")} + {moment(movie.release_date).format("MMMM Do, YYYY")} - {/* Badges don't have a great spot yet. */} - -
-

- - Genres - -

- - -
+ -
-

- - Overview: - -

-

- - {movie.overview} - +

+

+ Cast List

+
+ +
+
+
+ +
+

+ {movie.overview} +

+ +
+ +

{movie.vote_average} / 10

+
+ + <> + {isAvailable ? ( + + ) : ( +

+ The movie you are trying to watch is currently not available on + NyumatFlix. +

+ )} + +
- +
); }; export async function getServerSideProps(context: any) { const { id } = context.query; - let response = await axios.get( + let movieDetails = await axios.get( `https://api.themoviedb.org/3/movie/${id}?api_key=${process.env.API_KEY}&language=en-US`, ); - console.log(response.data.genres.map((genre: any) => [genre.id, genre.name])); + let staffData = await axios.get( + `https://api.themoviedb.org/3/movie/${id}/credits?api_key=${process.env.API_KEY}&language=en-US`, + ); + + let nonNullPosterCast = staffData.data.cast.filter((actor: Actor) => { + return actor.profile_path !== null; + }); + + let sortedTopTenCast = nonNullPosterCast + .sort((a: Actor, b: Actor) => { + return b.popularity - a.popularity; + }) + .slice(0, 10); return { props: { - movie: response.data, + movie: movieDetails.data, + actors: sortedTopTenCast, }, }; } From 3e4d686c529d73d29d413b67b478a3b32b0f06b8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 27 Jan 2023 19:35:39 -0800 Subject: [PATCH 03/23] [Mini] New Actor Interface and CreditsReponse Type --- typings.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/typings.ts b/typings.ts index 542c29e..3ad6d39 100644 --- a/typings.ts +++ b/typings.ts @@ -8,6 +8,15 @@ export interface Title { query: string; } +export interface Actor { + [x: string]: any; + id: number; + name: string; + profile_path: string; + character: string; + popularity: number; +} + export interface Movie { [x: string]: any; results?: Movie[]; @@ -56,6 +65,12 @@ export interface TmdbResponse { total_results?: number; } +export type CreditsReponse = { + id: number; + cast: Actor[]; + crew: Actor[]; +}; + export interface LayoutProps { children: React.ReactNode; isPathRoot: boolean; From 431742baa8c3605e67490270b6b0acc56b5d5227 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 27 Jan 2023 19:42:51 -0800 Subject: [PATCH 04/23] [Mini] Style Improvements --- .gitignore | 6 ++++++ components/Body.tsx | 2 -- components/Card.tsx | 6 +++--- components/Heading.tsx | 4 +--- components/Layout.tsx | 4 ++-- components/NavigationBar.tsx | 3 ++- pages/index.tsx | 9 ++++++++- 7 files changed, 22 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 0ca58cc..ee0b7d0 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,9 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + + +components +pages +hooks +public \ No newline at end of file diff --git a/components/Body.tsx b/components/Body.tsx index 9565b77..a12612b 100644 --- a/components/Body.tsx +++ b/components/Body.tsx @@ -60,9 +60,7 @@ const Body = ({ {filterData && filterData.filter_data.length > 0 ? (
{filterData.filter_data.map((movie, index) => ( -
-
))}
) : ( diff --git a/components/Card.tsx b/components/Card.tsx index aad269d..fab4ce4 100644 --- a/components/Card.tsx +++ b/components/Card.tsx @@ -17,11 +17,11 @@ const MovieCard = ({ movie }: { movie: Movie }) => { if (movie.poster_path === null) return null; if (moment(movie.release_date).isAfter(moment())) return null; return ( -
+
{movie.title} {
-
+

{movie.title}

{moment(movie.release_date).format("MMMM Do, YYYY")} diff --git a/components/Heading.tsx b/components/Heading.tsx index c8eb38d..69c4769 100644 --- a/components/Heading.tsx +++ b/components/Heading.tsx @@ -10,9 +10,7 @@ const Heading = () => { " > NyumatFlix{" "} - - 🎬 - +

diff --git a/components/Layout.tsx b/components/Layout.tsx index 62273e9..2b38f8b 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -121,7 +121,7 @@ export default function Layout({ children, isPathRoot }: LayoutProps) { } > - + {/* */} {children} - + {/* */} )} diff --git a/components/NavigationBar.tsx b/components/NavigationBar.tsx index fb82463..ace1e33 100644 --- a/components/NavigationBar.tsx +++ b/components/NavigationBar.tsx @@ -134,7 +134,8 @@ export default function NavigationBar({ return; } setActive(index); - router.push(link.label.toLowerCase()); + router.push({ pathname: `/${link.label.toLowerCase()}` }); + }} /> )); diff --git a/pages/index.tsx b/pages/index.tsx index c09c7f4..5ee9245 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -3,6 +3,7 @@ import type { NextPage } from "next"; import Head from "next/head"; import Link from "next/link"; import { motion } from "framer-motion"; +import Lottie from "lottie-react"; const Home: NextPage = () => { return ( @@ -14,6 +15,9 @@ const Home: NextPage = () => {
+
+ {/* */} +
{ > - + Get Started From 1bcc4a811c686a48ab618407ddb34feb77180d45 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 10 Apr 2023 22:35:33 -0700 Subject: [PATCH 05/23] Filter Work --- .gitignore | 8 +-- components/Body.tsx | 104 +++++++++++++++++++++--------- components/Card.tsx | 74 ++++++++++++++------- components/Layout.tsx | 17 +++-- components/MoviePlayer.tsx | 26 ++++++++ components/NavigationBar.tsx | 10 ++- components/SideBar.tsx | 52 ++++++++------- hooks/useAvailable.tsx | 32 +++++++++ hooks/useCurrentState.tsx | 6 +- hooks/useFilter.tsx | 78 +++++++++++++++------- pages/[prev]/[...filter].tsx | 37 +++++++++++ pages/api/verify/[id].ts | 36 +++++++++++ pages/filter/[filter].tsx | 17 +++++ pages/movies/watch/[id]/index.tsx | 30 ++++++--- pages/search/[title].tsx | 18 ++++++ pages/search/index.tsx | 6 +- utils/requests.ts | 2 + 17 files changed, 426 insertions(+), 127 deletions(-) create mode 100644 components/MoviePlayer.tsx create mode 100644 hooks/useAvailable.tsx create mode 100644 pages/[prev]/[...filter].tsx create mode 100644 pages/api/verify/[id].ts create mode 100644 pages/filter/[filter].tsx create mode 100644 pages/search/[title].tsx diff --git a/.gitignore b/.gitignore index ee0b7d0..e21c236 100644 --- a/.gitignore +++ b/.gitignore @@ -34,10 +34,4 @@ yarn-error.log* # typescript *.tsbuildinfo -next-env.d.ts - - -components -pages -hooks -public \ No newline at end of file +next-env.d.ts \ No newline at end of file diff --git a/components/Body.tsx b/components/Body.tsx index a12612b..5ac40c7 100644 --- a/components/Body.tsx +++ b/components/Body.tsx @@ -2,6 +2,9 @@ import { MapGenreMovie, Movie, TvShow } from "../typings"; import Card from "./Card"; import { Chip, Loader } from "@mantine/core"; import { useAutoAnimate } from "@formkit/auto-animate/react"; +import React, { useState } from "react"; +import { useEffect, useMemo } from "react"; +import { useRouter } from "next/router"; type Data = { filter_data: TvShow[] | Movie[]; @@ -16,22 +19,47 @@ interface BodyProps { filterData?: Data; isLoaded?: boolean; filterLoading?: boolean; + setSearchTerm: React.Dispatch>; + setFilter: React.Dispatch>; + searchTerm?: string; + setCurrentState: React.Dispatch>; } const Body = ({ children, filter, + setCurrentState, searchData, currentState, filterData, isLoaded, filterLoading, + setSearchTerm, + setFilter, + searchTerm, }: BodyProps) => { const [parent] = useAutoAnimate({ - duration: 650, - easing: "ease-in-out", + duration: 400, + easing: "ease-out", }); + const [show, setShow] = useState(false); + const router = useRouter(); + const memoizedSearchTerm = useMemo(() => searchTerm, [searchTerm]); + // const memoizedFilter = useMemo(() => filter, [filter]); + + useEffect(() => { + if (currentState !== "all" && searchTerm!.length === 0) { + router.push({ + pathname: `/movies/`, + }); + } + + if (router.pathname.includes("watch")) { + setShow(false); + } + }, [memoizedSearchTerm]); + const renderChips = () => { if (filter.length > 1) { return ( @@ -51,23 +79,32 @@ const Body = ({ )}

- {filterLoading ? ( + {/* {filterLoading ? (
- ) : null} + ) : null} */} - {filterData && filterData.filter_data.length > 0 ? ( -
- {filterData.filter_data.map((movie, index) => ( - - ))} -
+ {show ? ( + children ) : ( -

- No movies found with these filters. -

+ <> + {filterData && filterData.filter_data.length > 0 ? ( +
+ {filterData.filter_data.map((movie, index) => ( + setShow(true)}> + + + ))} +
+ ) : ( +

+ No movies found with these filters. +

+ )} + )} + {/* {searchData && searchData.length > 0 ? renderSearch() : } */} @@ -75,7 +112,7 @@ const Body = ({ } }; - const renderSearch = () => { + const renderSearch = (children: React.ReactNode) => { if (searchData) { const renderMessage = () => { return ( @@ -91,28 +128,37 @@ const Body = ({
{renderMessage()}
) : null} - {!isLoaded ? ( -
- -
- ) : ( -
-
- {searchData.map((movie, index) => ( -
- + {show && children} + {!show && ( + <> + {!isLoaded ? ( +
+ +
+ ) : ( +
+
+ {searchData.map((movie, index) => ( +
setShow(true)} + > + +
+ ))}
- ))} -
-
+
+ )} + )} ); } }; return ( -
} className="w-full"> - {currentState === "search" ? renderSearch() : null} +
+ {currentState === "search" ? renderSearch(children) : null} {currentState === "filter" ? renderChips() : null} {currentState === "all" ? children : null}
diff --git a/components/Card.tsx b/components/Card.tsx index fab4ce4..215b990 100644 --- a/components/Card.tsx +++ b/components/Card.tsx @@ -1,10 +1,15 @@ import Image from "next/image"; import { Movie, TvShow } from "../typings"; import moment from "moment"; -import Link from "next/link"; import { useRouter } from "next/router"; +import { useEffect } from "react"; +import Link from "next/link"; -const MovieCard = ({ movie }: { movie: Movie }) => { +interface MovieCardProps { + movie: Movie; +} + +const MovieCard = ({ movie }: MovieCardProps) => { const router = useRouter(); const handleClick = () => { @@ -17,29 +22,42 @@ const MovieCard = ({ movie }: { movie: Movie }) => { if (movie.poster_path === null) return null; if (moment(movie.release_date).isAfter(moment())) return null; return ( -
-
-
- {movie.title} -
-
-
-
-

{movie.title}

-

- {moment(movie.release_date).format("MMMM Do, YYYY")} -

+ <> + +
+
+
+ {movie.title} +
+
+
+
+

+ {movie.title} +

+

+ {moment(movie.release_date).format("MMMM Do, YYYY")} +

+
+

+ {movie.vote_average} +

+
-

{movie.vote_average}

-
-
+ + ); }; @@ -70,7 +88,13 @@ const TvShowCard = ({ tvShow }: { tvShow: TvShow }) => { ); }; -const Card = ({ item }: { item: any }) => { +interface CardProps { + item: any; + selected?: boolean; + setSelected?: React.Dispatch>; +} + +const Card = ({ item, selected, setSelected }: CardProps) => { if (!item) return null; if (item.media_type === "person") return null; return ( diff --git a/components/Layout.tsx b/components/Layout.tsx index 2b38f8b..c761d3e 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -37,7 +37,10 @@ export default function Layout({ children, isPathRoot }: LayoutProps) { }); const { defaultData, defaultLoading, defaultError } = useDefaultMovies(1); - const { currentState, setCurrentState } = useCurrentState({ filter, searchTerm }); + const { currentState, setCurrentState } = useCurrentState({ + filter, + searchTerm, + }); const isLoaded = useLoading({ filterLoading, @@ -67,6 +70,7 @@ export default function Layout({ children, isPathRoot }: LayoutProps) {