diff --git a/src/App.tsx b/src/App.tsx index e1df610..6f23505 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,7 +22,7 @@ function App() { - + diff --git a/src/Components/ClickMovie.tsx b/src/Components/ClickMovie.tsx index 15993b9..900970b 100644 --- a/src/Components/ClickMovie.tsx +++ b/src/Components/ClickMovie.tsx @@ -9,13 +9,13 @@ import { useQuery } from "react-query"; import { useHistory, useLocation, useRouteMatch } from "react-router-dom"; import styled from "styled-components"; import { - getMovieCredit, - getMovieDetail, - getSimilarMovie, - IGetMovieDetail, + getSimilarData, + getVideoCredit, + getVideoDetail, + IGetVideoDetail, IMovie, - IMovieCredit, - ISimilarMovie, + ISimilarProps, + IVideoCredit, } from "../api"; import { makeImageHelper } from "../utils"; @@ -239,9 +239,10 @@ const MoreTitle = styled.span` `; interface IClickMovie { - bigMovieMatch?: { params?: { movieId?: string } }; - movieData: IMovie[]; - search?: string | ""; + bigVideoMatch: { params?: { movieId?: string; tvId?: string } }; + videoData: IMovie[]; + isWhat: string; + search?: string; } const opacityV: Variants = { @@ -256,27 +257,42 @@ const opacityV: Variants = { }, }; -function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { - //console.log("빅무비매치임 :", bigMovieMatch, "무비데이터임:", movieData); - //console.log(movieData, isSearch); - //console.log(moreMovie); - // useEffect(() => {}, [bigMovieMatch?.params.movieId]); - //console.log(similarData.data?.results[0].id); +function ClickMovie({ bigVideoMatch, isWhat, videoData, search }: IClickMovie) { const history = useHistory(); const { scrollY } = useViewportScroll(); + const [over, setOver] = useState(false); const [clicked, setClicked] = useState(false); useEffect(() => { setClicked(false); }, [clicked]); // console.log(history); const location = useLocation(); - const newId: string = new URLSearchParams(location.search).get("movies") + const movieKeyword: string = new URLSearchParams(location.search).get( + "movies" + ) ? String(new URLSearchParams(location.search).get("movies")) : ""; - const isSearch = bigMovieMatch?.params?.movieId - ? bigMovieMatch?.params.movieId - : newId; + const tvKeyword: string = new URLSearchParams(location.search).get("tvs") + ? String(new URLSearchParams(location.search).get("tvs")) + : ""; + + const searchKeyword = movieKeyword ? movieKeyword : tvKeyword; + + const movieSearch = bigVideoMatch?.params?.movieId + ? bigVideoMatch?.params.movieId + : searchKeyword; + + // console.log(movieSearch); + + const tvSearch = bigVideoMatch?.params?.tvId + ? bigVideoMatch.params.tvId + : searchKeyword; + + const isSearch = movieSearch ? movieSearch : tvSearch; + // console.log( + // `isSearch: ${isSearch}, movieSearch : ${movieSearch}, tvSearch : ${tvSearch}` + // ); //console.log(isSearch); const keyword = new URLSearchParams(location.search).get("keyword"); const backUrl = `${location.pathname}?keyword=${keyword}`; @@ -285,68 +301,86 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { const onOverlayClicked = () => { setOver(false); if (!search) { - history.push("/"); + if (isWhat === "movie") { + history.push("/"); + } else if (isWhat === "tv") { + history.push("/tv"); + } } else { history.push(`${backUrl}`); } //history.push(location); }; - //console.log(clicked); - const [over, setOver] = useState(false); - // const { data } = useQuery(["movies", "video"], () => - // getVideo(bigMovieMatch?.params.movieId) - // ); - const detailData = useQuery(["movies", "detail"], () => - getMovieDetail(isSearch) + const detailData = useQuery(["videos", "detail"], () => + getVideoDetail(isWhat, isSearch) ); - const creditData = useQuery(["movies", "credit"], () => - getMovieCredit(isSearch) + + const creditData = useQuery(["video", "credit"], () => + getVideoCredit(isWhat, isSearch) ); - //console.log(creditData.data?.cast[0].name); - const similarData = useQuery(["movies", "similar"], () => - getSimilarMovie(isSearch) + + const similarData = useQuery(["video", "similar"], () => + getSimilarData(isWhat, isSearch) ); + //console.log(clicked); + // const { data } = useQuery(["movies", "video"], () => + // getVideo(bigVideoMatch=.params.movieId) + // ); - console.log(isSearch, detailData.data); + //console.log(similarMovieData); + // console.log(isSearch, creditData.data); //console.log(similarData.data?.results[0].id); - // const clickedMovie = - // bigMovieMatch.params.movieId && - // movieData.find((item) => item.id === +bigMovieMatch.params.movieId) - // ? movieData.find((item) => item.id === +bigMovieMatch.params.movieId) + // const clickedData = + // bigVideoMatch=params.movieId && + // movieData.find((item) => item.id === +bigVideoMatch=params.movieId) + // ? movieData.find((item) => item.id === +bigVideoMatch=params.movieId) // : similarData?.data?.results?.find( - // (item) => item.id === +bigMovieMatch.params.movieId + // (item) => item.id === +bigVideoMatch=params.movieId // ); + const similarMovieMatch = useRouteMatch<{ movieId: string }>( + !search ? `/movies/:movieId` : `/search` + ); - const clickedMovie = - isSearch && - (movieData.find((item) => item.id === +isSearch) - ? movieData.find((item) => item.id === +isSearch) - : detailData.data); + const similarTvMatch = useRouteMatch<{ tvId: string }>( + !search ? `/tv/:tvId` : `/search` + ); + const similarMatch = similarMovieMatch ? similarMovieMatch : similarTvMatch; + + const clickedData = videoData + ? videoData.find((item) => item.id === +isSearch) + : detailData.data; + // console.log(similarData.data); const mouseEnter = (event: any) => { setOver(true); }; - const similarMatch = useRouteMatch<{ movieId: string }>( - !search ? `/movies/:movieId` : `/search` - ); + //console.log(similarMatch, similarMovieMatch, similarTvMatch); + //console.log(similarMovieMatch, similarMatch); + //console.log(similarTvMatch); //console.log(data, isLoading); //console.log(detailData.data); //console.log(similarData.data?.results[0]); - //console.log(bigMovieMatch.params.movieId); - const onBoxClicked = (movieId: number) => { + //console.log(bigVideoMatch=params.movieId); + const onBoxClicked = (id: number) => { setOver(false); setClicked(true); if (!search) { - history.push(`/movies/${movieId}`); + if (isWhat === "movie") { + history.push(`/movies/${id}`); + } else if (isWhat === "tv") { + history.push(`/tv/${id}`); + } } else if (search) { - history.push( - `${location.pathname}?$keyword=${keyword}&movies=${movieId}` - ); + if (isWhat === "movie") { + history.push(`${location.pathname}?$keyword=${keyword}&movies=${id}`); + } else if (isWhat === "tv") { + history.push(`${location.pathname}?$keyword=${keyword}&tvs=${id}`); + } } }; //console.log(moreMovie); - //console.log(clickedMovie?.poster_path); - // console.log(clickedMovie); + //console.log(clickedData?.poster_path); + console.log(clickedData); // console.log("무비ㅏ아이디임", movieId); // console.log( // "시밀러 데이터 :", @@ -356,25 +390,25 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { // "시밀러맷치", // similarMatch // ); - // console.log(detailData.data); + //console.log(clickedData); return ( - {clickedMovie && ( + {clickedData && ( )} - {clickedMovie && ( + {clickedData && ( @@ -392,33 +426,37 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { frameBorder={0} userWidth={window.innerWidth} bgPhoto={makeImageHelper( - clickedMovie.backdrop_path - ? clickedMovie.backdrop_path - : clickedMovie.poster_path - ? clickedMovie.poster_path + clickedData.backdrop_path + ? clickedData.backdrop_path + : clickedData.poster_path + ? clickedData.poster_path : "" )} > ) : ( )} - {clickedMovie.title} - + + {isWhat === "movie" ? clickedData.title : clickedData.name} + + 재생 @@ -434,29 +472,41 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { - + - - {clickedMovie.vote_average - ? `${(clickedMovie.vote_average * 10).toFixed(0)}% 일치` + + {clickedData.vote_average + ? `${(clickedData.vote_average * 10).toFixed(0)}% 일치` : ""} - - {clickedMovie.release_date - ? clickedMovie.release_date.slice(0, 4) - : clickedMovie.release_date} + + {isWhat === "movie" && clickedData?.release_date + ? clickedData?.release_date.slice(0, 4) + : clickedData.first_air_date?.slice(0, 4)} 년 - {detailData.data?.runtime === 0 - ? "" - : detailData.data?.runtime === null + {detailData.data?.runtime === 0 || + detailData.data?.runtime === null || + detailData.data?.runtime === undefined ? "" : `${detailData.data?.runtime}분`} - - {clickedMovie.overview} + + {clickedData.overview} {detailData.data?.genres && @@ -465,24 +515,26 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { 장르: - {detailData.data?.genres.map((item) => ( + {detailData.data?.genres?.map((item: any) => ( {item.name}, ))} 출연진: - + {creditData.data?.cast[0] ? `${creditData.data?.cast[0].name},` : ""} - + {creditData.data?.cast[1] ? `${creditData.data?.cast[1].name},` : ""} - + {creditData.data?.cast[2] ? `${creditData.data?.cast[2].name}` : ""} @@ -490,17 +542,17 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { 크리에이터: - + {creditData.data?.crew[0] ? `${creditData.data?.crew[0].name},` : ""} - + {creditData.data?.crew[1] ? `${creditData.data?.crew[1].name},` : ""} - + {creditData.data?.crew[2] ? `${creditData.data?.crew[2].name}` : ""} @@ -525,7 +577,9 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { > {similarMatch && similarData.data?.results && ( - {similarData.data?.results[item].title} + {isWhat === "movie" + ? similarData.data?.results[item].title + : similarData.data?.results[item].name} - {similarData.data?.results[ - item - ]..slice(0, 4)} - + > {similarData.data?.results[item].overview && ( {similarData.data?.results[item].overview.length > @@ -582,14 +641,27 @@ function ClickMovie({ bigMovieMatch, movieData, search }: IClickMovie) { )} - {similarData.data?.results && clicked && similarMatch ? ( + {similarData.data?.results && clicked && similarMovieMatch ? ( - ) : null} + ) : ( + similarData.data?.results && + clicked && + similarTvMatch && ( + + ) + )} ) ); diff --git a/src/Components/ClickTv.tsx b/src/Components/ClickTv.tsx deleted file mode 100644 index e18936d..0000000 --- a/src/Components/ClickTv.tsx +++ /dev/null @@ -1,600 +0,0 @@ -import { - AnimatePresence, - motion, - useViewportScroll, - Variants, -} from "framer-motion"; -import { useEffect, useState } from "react"; -import { useQuery } from "react-query"; -import { useHistory, useLocation, useRouteMatch } from "react-router-dom"; -import styled from "styled-components"; -import { - getMovieCredit, - getMovieDetail, - getSimilarMovie, - getTvSimilar, - IGetMovieDetail, - IMovie, - IMovieCredit, - IOnAirData, - ISimilarMovie, -} from "../api"; -import { makeImageHelper } from "../utils"; - -const Overlay = styled(motion.div)` - position: fixed; - top: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.5); - opacity: 0; -`; - -const BigMovie = styled(motion.div)` - position: absolute; - width: 40vw; - left: 0; - right: 0; - margin: 0 auto; - overflow: hidden; - border-radius: 15px; - min-width: 426px; - background-color: ${(props) => props.theme.black.veryDark}; -`; - -const DisableCover = styled.div<{ isOver: boolean }>` - width: 100%; - height: 400px; - position: absolute; - top: 0; - left: 0; - right: 0; - margin: 0 auto; - z-index: ${(props) => (props.isOver ? 100 : -2)}; -`; - -const BigCover = styled(motion.iframe)<{ bgPhoto?: string; userWidth: number }>` - background-image: linear-gradient(to top, black, transparent), - url(${(props) => props.bgPhoto}); - background-size: cover; - top: 0; - right: 0; - left: 0; - margin: 0 auto; - aspect-ratio: 16/9; - width: 100%; - background-position: center center; - height: ${(props) => - props.userWidth > 3840 - ? 2160 - : props.userWidth > 2560 - ? 1440 - : props.userWidth > 1920 - ? 1080 - : props.userWidth > 1280 - ? 720 - : props.userWidth > 854 - ? 480 - : props.userWidth > 640 - ? 360 - : 240}; - - border: none; -`; - -const BigContainer = styled(motion.div)` - padding: 50px; - top: -230px; - position: relative; -`; - -const BigTitle = styled.h3` - color: ${(props) => props.theme.white.lighter}; - font-size: 48px; - position: relative; - margin-bottom: 50px; -`; - -const BigOverview = styled.p` - color: ${(props) => props.theme.white.lighter}; - position: relative; - margin-bottom: 100px; - font-size: 19px; - font-weight: 400; - line-height: 25px; - width: 80%; -`; - -const DetailGrid = styled.div` - display: grid; - grid-template-columns: 5fr 2fr; -`; - -const DetailBox = styled.div` - display: flex; - flex-direction: column; -`; - -const UserBox = styled.div` - display: flex; - align-items: center; - margin-bottom: 60px; -`; - -const PlayCircle = styled.div` - width: 40px; - margin-left: 10px; - height: 40px; - border-radius: 20px; - border: 2px solid ${(props) => props.theme.white.darker}; - display: flex; - justify-content: center; - align-items: center; - color: ${(props) => props.theme.white.lighter}; - font-size: 18px; - font-weight: 100; - i { - display: flex; - justify-content: center; - align-items: center; - } -`; - -const Playbox = styled.div` - width: 150px; - display: flex; - height: 40px; - justify-content: center; - align-items: center; - color: black; - font-size: 18px; - font-weight: 600; - border-radius: 5px; - background-color: ${(props) => props.theme.white.lighter}; - i { - margin-right: 10px; - } -`; - -const InfoBox = styled.div` - display: flex; - align-items: flex-start; - flex-wrap: wrap; - margin-bottom: 20px; -`; - -const InfoSpan = styled.div` - font-size: 14px; - color: ${(props) => props.theme.white.veryDark}; -`; - -const MovieInfoTop = styled.span` - color: ${(props) => props.theme.white.darker}; - margin-left: 5px; - font-size: 16px; - font-weight: 400; -`; - -const MovieInfo = styled.span` - color: ${(props) => props.theme.white.darker}; - margin-left: 5px; - display: flex; - line-height: 18px; - align-items: center; -`; - -const MoiveAverage = styled.span` - font-weight: 600; - color: #42c262; - font-size: 16px; - margin-bottom: 10px; -`; - -const MoreBox = styled.div` - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 20px; - grid-template-rows: repeat(3, minmax(100px, 1fr)); - width: 100%; -`; - -const MoreMovie = styled.div` - cursor: pointer; - width: 100%; - border-radius: 10px; - - background-color: ${(props) => props.theme.black.lighter}; - color: ${(props) => props.theme.white.darker}; -`; -const MoreCover = styled.div<{ bgPhoto: string }>` - background-image: url(${(props) => props.bgPhoto}); - background-position: center center; - background-size: cover; - height: 180px; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - margin-bottom: 10px; -`; - -const MoreInfoBox = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - padding: 15px; -`; - -const MoreInfo = styled.span` - display: flex; - margin-bottom: 10px; - font-size: 14px; - align-items: center; - line-height: 18px; -`; - -const MoreTitle = styled.span` - margin-bottom: 10px; - display: flex; - font-weight: 600; - font-size: 16px; - line-height: 20px; - color: ${(props) => props.theme.white.lighter}; -`; - -interface IClickMovie { - bigMovieMatch?: { params?: { movieId?: string } }; - movieData: IMovie[]; - search?: string | ""; -} - -const opacityV: Variants = { - normal: { - opacity: 1, - }, - entry: { - opacity: 0, - }, - exit: { - opacity: 0, - }, -}; - -function ClickTv({ bigMovieMatch, movieData, search }: IClickMovie) { - //console.log("빅무비매치임 :", bigMovieMatch, "무비데이터임:", movieData); - //console.log(movieData, isSearch); - //console.log(moreMovie); - // useEffect(() => {}, [bigMovieMatch?.params.movieId]); - //console.log(similarData.data?.results[0].id); - const history = useHistory(); - const { scrollY } = useViewportScroll(); - const [clicked, setClicked] = useState(false); - useEffect(() => { - setClicked(false); - }, [clicked]); - // console.log(history); - const location = useLocation(); - const newId: string = new URLSearchParams(location.search).get("movies") - ? String(new URLSearchParams(location.search).get("movies")) - : ""; - - const isSearch = bigMovieMatch?.params?.movieId - ? bigMovieMatch?.params.movieId - : newId; - //console.log(isSearch); - const keyword = new URLSearchParams(location.search).get("keyword"); - const backUrl = `${location.pathname}?keyword=${keyword}`; - //console.log(location.pathname); - // console.log(backUrl); - const onOverlayClicked = () => { - setOver(false); - if (!search) { - history.push("/"); - } else { - history.push(`${backUrl}`); - } - //history.push(location); - }; - //console.log(clicked); - const [over, setOver] = useState(false); - // const { data } = useQuery(["movies", "video"], () => - // getVideo(bigMovieMatch?.params.movieId) - // ); - const detailData = useQuery(["movies", "detail"], () => - getMovieDetail(isSearch) - ); - const creditData = useQuery(["movies", "credit"], () => - getMovieCredit(isSearch) - ); - //console.log(creditData.data?.cast[0].name); - const similarData = useQuery(["tv", "similar"], () => - getTvSimilar(isSearch) - ); - - console.log(similarData); - //console.log(similarData.data?.results[0].id); - // const clickedMovie = - // bigMovieMatch.params.movieId && - // movieData.find((item) => item.id === +bigMovieMatch.params.movieId) - // ? movieData.find((item) => item.id === +bigMovieMatch.params.movieId) - // : similarData?.data?.results?.find( - // (item) => item.id === +bigMovieMatch.params.movieId - // ); - - const clickedMovie = - isSearch && - (movieData.find((item) => item.id === +isSearch) - ? movieData.find((item) => item.id === +isSearch) - : detailData.data); - - const mouseEnter = (event: any) => { - setOver(true); - }; - const similarMatch = useRouteMatch<{ movieId: string }>( - !search ? `/movies/:movieId` : `/search` - ); - //console.log(data, isLoading); - //console.log(detailData.data); - //console.log(similarData.data?.results[0]); - //console.log(bigMovieMatch.params.movieId); - const onBoxClicked = (movieId: number) => { - setOver(false); - setClicked(true); - if (!search) { - history.push(`/movies/${movieId}`); - } else if (search) { - history.push( - `${location.pathname}?$keyword=${keyword}&movies=${movieId}` - ); - } - }; - //console.log(moreMovie); - //console.log(clickedMovie?.poster_path); - // console.log(clickedMovie); - // console.log("무비ㅏ아이디임", movieId); - // console.log( - // "시밀러 데이터 :", - // similarData.data?.results, - // "클릭임:", - // clicked, - // "시밀러맷치", - // similarMatch - // ); - // console.log(detailData.data); - return ( - - {clickedMovie && ( - - )} - {clickedMovie && ( - - <> - {detailData.data?.videos?.results[0] ? ( - - ) : ( - - )} - - - {clickedMovie.title} - - - - 재생 - - - - - - - - - - - - - - - - {clickedMovie.vote_average - ? `${(clickedMovie.vote_average * 10).toFixed(0)}% 일치` - : ""} - - - {clickedMovie.release_date - ? clickedMovie.release_date.slice(0, 4) - : clickedMovie.release_date} - 년 - - - {detailData.data?.runtime === 0 - ? "" - : detailData.data?.runtime === null - ? "" - : `${detailData.data?.runtime}분`} - - - - {clickedMovie.overview} - - - {detailData.data?.genres && - creditData.data?.crew && - creditData.data?.cast && ( - - - 장르: - {detailData.data?.genres.map((item) => ( - {item.name}, - ))} - - - - 출연진: - - {creditData.data?.cast[0] - ? `${creditData.data?.cast[0].name},` - : ""} - - - {creditData.data?.cast[1] - ? `${creditData.data?.cast[1].name},` - : ""} - - - {creditData.data?.cast[2] - ? `${creditData.data?.cast[2].name}` - : ""} - - - - 크리에이터: - - {creditData.data?.crew[0] - ? `${creditData.data?.crew[0].name},` - : ""} - - - {creditData.data?.crew[1] - ? `${creditData.data?.crew[1].name},` - : ""} - - - {creditData.data?.crew[2] - ? `${creditData.data?.crew[2].name}` - : ""} - - - - )} - - {similarData?.data?.results && ( - - {similarData.data?.results[9] && - Array.from({ length: 9 }, (v, i) => i).map((item) => ( - - onBoxClicked( - similarData?.data - ? similarData?.data?.results[item].id - : 0 - ) - } - > - {similarMatch && similarData.data?.results && ( - - )} - - - {similarData.data?.results[item].title} - - - {similarData.data?.results[item].vote_average - ? `${( - similarData.data?.results[item].vote_average * - 10 - ).toFixed(0)}%일치` - : ""} - - - {similarData.data?.results[ - item - ].first_air_date.slice(0, 4)} - - {similarData.data?.results[item].overview && ( - - {similarData.data?.results[item].overview.length > - 200 - ? `${similarData.data?.results[ - item - ].overview.slice(0, 200)}...` - : similarData.data?.results[item].overview} - - )} - - - ))} - - )} - - - - )} - {similarData.data?.results && clicked && similarMatch ? ( - - ) : null} - ) - - ); -} - -export default ClickTv; diff --git a/src/Components/NowMovies.tsx b/src/Components/NowMovies.tsx index f00c461..7b32b13 100644 --- a/src/Components/NowMovies.tsx +++ b/src/Components/NowMovies.tsx @@ -2,7 +2,7 @@ import { AnimatePresence, motion, Variants } from "framer-motion"; import React, { useState } from "react"; import { useHistory, useLocation, useRouteMatch } from "react-router-dom"; import styled from "styled-components"; -import { IGetMoviesProps, IMovie } from "../api"; +import { IMovie } from "../api"; import { makeImageHelper } from "../utils"; import ClickMovie from "./ClickMovie"; @@ -10,6 +10,7 @@ const Slider = styled.div` position: relative; height: 180px; top: -170px; + margin-bottom: 70px; `; const Row = styled(motion.div)<{ isFirst: number; hover: boolean }>` @@ -166,15 +167,16 @@ const ArrowVariants: Variants = { const offset = 6; interface INowProps { - movieData: IMovie[]; - page1?: IGetMoviesProps; + videoData: IMovie[]; + isWhat: string; sliderTitle: string; search?: string; } -function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { +function NowMovies({ videoData, sliderTitle, search, isWhat }: INowProps) { const history = useHistory(); const location = useLocation(); + //console.log(tvData); //console.log(pathName); const [leaving, setLeaving] = useState(false); const [rowHover, setRowHover] = useState(false); @@ -184,13 +186,14 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { const toggleLeaving = () => { setLeaving((prev) => !prev); }; + const [back, setBack] = useState(false); const [hover, setHover] = useState(false); const [index, setIndex] = useState(0); - const totalMovies = movieData.length - 1; - const maxIndex = Math.floor(totalMovies / offset) - 1; + const totalVideo = videoData.length - 1; + const maxIndex = Math.floor(totalVideo / offset) - 1; const decreaseIndex = () => { - if (page1) { + if (videoData) { if (leaving) return; setBack(false); toggleLeaving(); @@ -199,7 +202,7 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { } }; const increaseIndex = () => { - if (page1) { + if (videoData) { if (leaving) return; setBack(true); toggleLeaving(); @@ -209,17 +212,30 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { } }; const keyword = new URLSearchParams(location.search).get("keyword"); - const onBoxClicked = (movieId: number) => { + const onBoxClicked = (id: number) => { + //console.log(id); if (!search) { - history.push(`/movies/${movieId}`); + if (isWhat === "movie") { + history.push(`/movies/${id}`); + } else if (isWhat === "tv") { + history.push(`/tv/${id}`); + } } else if (search) { - history.push(`/search?keyword=${keyword}&movies=${movieId}`); + if (isWhat === "movie") { + history.push(`/search?keyword=${keyword}&movies=${id}`); + } else if (isWhat === "tv") { + history.push(`/search?keyword=${keyword}&tv=${id}`); + } } }; const bigMovieMatch = useRouteMatch<{ movieId?: string }>( !search ? `/movies/:movieId` : `/search` ); - console.log("빅매치임", bigMovieMatch); + const bigTvMatch = useRouteMatch<{ tvId?: string }>( + !search ? `/tv/:tvId` : `/search` + ); + //console.log(bigTvMatch); + //console.log("빅매치임", bigMovieMatch); //console.log(bigMovieMatch); //console.log("로우 호버의 값: ", rowHover); @@ -279,21 +295,21 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { initial={false} transition={{ type: "tween", duration: 0.1 }} bgPhoto={makeImageHelper( - movieData + videoData ? index === 0 - ? movieData[ - Math.floor((movieData.length - 1) / 6) * offset + ? videoData[ + Math.floor((videoData.length - 1) / 6) * offset ]?.backdrop_path - : movieData[offset * index]?.backdrop_path + : videoData[offset * index]?.backdrop_path : "", "w500" )} > ) : null} - {movieData + {videoData .slice(1) .slice(offset * index, offset * index + offset) - .map((item) => ( + .map((item: any) => ( onBoxClicked(item.id)} @@ -313,7 +329,9 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { key={item.id} > -

{item.title}

+

+ {item.title ? item.title : item.name} +

))} @@ -322,11 +340,11 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { key="nextBox" variants={boxVariants} initial="normal" - layoutId={movieData[offset * index + offset + 1]?.id + ""} + layoutId={videoData[offset * index + offset + 1]?.id + ""} transition={{ type: "tween", duration: 0.1 }} bgPhoto={makeImageHelper( - movieData - ? movieData[offset * index + offset + 1]?.backdrop_path + videoData + ? videoData[offset * index + offset + 1]?.backdrop_path : "", "w500" )} @@ -336,10 +354,10 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { key="nextBox" variants={boxVariants} initial="normal" - layoutId={movieData[1].id + ""} + layoutId={videoData[1].id + ""} transition={{ type: "tween", duration: 0.1 }} bgPhoto={makeImageHelper( - movieData ? movieData[1]?.backdrop_path : "", + videoData ? videoData[1]?.backdrop_path : "", "w500" )} > @@ -361,14 +379,24 @@ function NowMovies({ movieData, page1, sliderTitle, search }: INowProps) { ) - {bigMovieMatch ? ( + {bigMovieMatch && isWhat === "movie" && ( + + )} + {bigTvMatch && isWhat === "tv" && ( - ) : null} + )} ); } diff --git a/src/Components/TvSlider.tsx b/src/Components/TvSlider.tsx deleted file mode 100644 index 98658ef..0000000 --- a/src/Components/TvSlider.tsx +++ /dev/null @@ -1,370 +0,0 @@ -import { AnimatePresence, motion, Variants } from "framer-motion"; -import React, { useState } from "react"; -import { useHistory, useLocation, useRouteMatch } from "react-router-dom"; -import styled from "styled-components"; -import { IGetMoviesProps, IMovie } from "../api"; -import { makeImageHelper } from "../utils"; -import ClickMovie from "./ClickMovie"; -import ClickTv from "./ClickTv"; - -const Slider = styled.div` - position: relative; - height: 180px; - top: -170px; -`; - -const Row = styled(motion.div)<{ isFirst: number; hover: boolean }>` - display: grid; - grid-template-columns: ${(props) => - props.hover === false - ? "repeat(6, 1fr) 0.2fr" - : "0.2fr repeat(6, 1fr) 0.2fr"}; - gap: 5px; - width: 100%; - margin-top: 16px; - padding: ${(props) => - props.hover === false ? "0px 0px 0px 65px" : "0px 0px 0px 0px"}; - position: absolute; -`; - -const Box = styled(motion.div)<{ hover?: boolean; bgPhoto: string }>` - background-color: white; - height: 180px; - font-size: 66px; - background-image: ${(props) => - props.bgPhoto === `https://image.tmdb.org/t/p/w500/` - ? `url( - "https://lh3.googleusercontent.com/proxy/iMS9Htm7Nxk5phLAi9872VBCPpw7CyJLhjYtyoG0K8pMfgEYi4aSkWo8l7_pz7pq-KkF_-_pvhPxurMR4RN6kOg" - )` - : `url(${props.bgPhoto})`}; - background-position: center center; - background-size: cover; - cursor: pointer; - &:hover { - z-index: 2; - } - &:first-child { - transform-origin: ${(props) => - props.hover ? "center left" : "center left"}; - } - &:nth-child(2) { - transform-origin: ${(props) => - props.hover ? "center left" : "center center"}; - } - &:nth-child(6) { - transform-origin: ${(props) => - props.hover ? "center center" : "center right"}; - } - &:nth-child(7) { - transform-origin: ${(props) => - props.hover ? "center right" : "center center"}; - } -`; - -const Archive = styled.span` - font-size: 32px; - font-weight: 600; - padding-left: 65px; -`; - -const ArrowBtn = styled(motion.div)` - color: white; - z-index: 1; - width: 65px; - height: 185px; - display: flex; - justify-content: center; - align-items: center; - position: absolute; - bottom: -50px; - i { - position: relative; - text-align: center; - } - - &:first-child { - left: 0; - } - &:last-child { - right: 0; - } -`; - -const Info = styled(motion.div)` - padding: 10px; - background-color: ${(props) => props.theme.black.lighter}; - position: absolute; - width: 100%; - bottom: 0; - opacity: 0; - h4 { - font-size: 14px; - text-align: center; - } -`; - -const ArchiveContainer = styled.div` - display: flex; - justify-content: space-between; - align-items: flex-end; -`; - -const IndexBoxs = styled.div` - display: flex; - padding-right: 65px; -`; - -const IndexBox = styled(motion.div)<{ index: boolean }>` - width: 10px; - margin-left: 2px; - height: 2px; - background-color: ${(props) => - props.index ? props.theme.white.lighter : props.theme.black.lighter}; -`; - -const rowVariants: Variants = { - hidden: (back: boolean) => ({ - x: back ? window.outerWidth + 5 : -window.outerWidth - 5, - }), - visible: { x: 0 }, - exit: (back: boolean) => ({ - x: back ? -window.outerWidth - 5 : window.outerWidth + 5, - }), -}; - -const boxVariants: Variants = { - normal: { scale: 1, transition: { type: "tween" } }, - hover: { - scale: 1.3, - y: -50, - transition: { delay: 0.5, duration: 0.3, type: "tween" }, - }, -}; - -const infoVariants: Variants = { - hover: { - opacity: 1, - transition: { delay: 0.5, duration: 0.1, type: "tween" }, - }, -}; - -const ArrowVariants: Variants = { - btnNormal: { - backgroundColor: "rgba(0,0,0,0.5)", - fontSize: "20px", - color: "rgba(255,255,255,0)", - }, - btnHover: { - backgroundColor: "rgba(0, 0, 0, 0.9)", - fontSize: "30px", - color: "rgba(255,255,255,1)", - }, - exit: { - opacity: 0, - }, -}; - -const offset = 6; - -interface INowProps { - movieData: IMovie[]; - page1?: IGetMoviesProps; - sliderTitle: string; - search?: string; -} - -function TvSlider({ movieData, page1, sliderTitle, search }: INowProps) { - const history = useHistory(); - const location = useLocation(); - //console.log(pathName); - const [leaving, setLeaving] = useState(false); - const [rowHover, setRowHover] = useState(false); - const rowMouseEnterLeave = () => { - setRowHover((prev) => !prev); - }; - const toggleLeaving = () => { - setLeaving((prev) => !prev); - }; - const [back, setBack] = useState(false); - const [hover, setHover] = useState(false); - const [index, setIndex] = useState(0); - const totalMovies = movieData.length - 1; - const maxIndex = Math.floor(totalMovies / offset) - 1; - const decreaseIndex = () => { - if (page1) { - if (leaving) return; - setBack(false); - toggleLeaving(); - - setIndex((prev) => (index === 0 ? maxIndex : prev - 1)); - } - }; - const increaseIndex = () => { - if (page1) { - if (leaving) return; - setBack(true); - toggleLeaving(); - setHover(true); - console.log("맥스인덱스 : ", maxIndex, "인덱스 : ", index); - setIndex((prev) => (index === maxIndex ? 0 : prev + 1)); - } - }; - const keyword = new URLSearchParams(location.search).get("keyword"); - const onBoxClicked = (movieId: number) => { - if (!search) { - history.push(`/movies/${movieId}`); - } else if (search) { - history.push(`/search?keyword=${keyword}&movies=${movieId}`); - } - }; - const bigMovieMatch = useRouteMatch<{ movieId?: string }>( - !search ? `/movies/:movieId` : `/search` - ); - //console.log("빅매치임", bigMovieMatch); - //console.log(bigMovieMatch); - //console.log("로우 호버의 값: ", rowHover); - - return ( - <> - - - - {sliderTitle} - - {rowHover && - Array.from({ length: maxIndex + 1 }, (v, i) => i).map( - (item) => ( - - ) - )} - - - {hover && ( - - - - )} - - {hover === true ? ( - - ) : null} - {movieData - .slice(1) - .slice(offset * index, offset * index + offset) - .map((item) => ( - onBoxClicked(item.id)} - hover={hover} - variants={boxVariants} - initial="normal" - whileHover="hover" - transition={{ type: "tween", duration: 0.1 }} - bgPhoto={makeImageHelper( - item.backdrop_path - ? item.backdrop_path - : item.poster_path - ? item.poster_path - : "", - "w500" - )} - key={item.id} - > - -

{item.title}

-
-
- ))} - {index !== maxIndex ? ( - - ) : ( - - )} -
- ( - - - - ) -
-
- {bigMovieMatch ? : null} - - ); -} - -export default React.memo(TvSlider); diff --git a/src/Routes/Home.tsx b/src/Routes/Home.tsx index c0ff9d8..b9ad4f6 100644 --- a/src/Routes/Home.tsx +++ b/src/Routes/Home.tsx @@ -9,7 +9,7 @@ import { getMoviesPage4, getMoviesPage5, getMoviesPage6, - IGetMoviesProps, + IGetVideosProps, IMovie, topRateMoviePage1, topRateMoviePage2, @@ -45,9 +45,6 @@ const Overview = styled.p` font-size: 34px; width: 50%; `; -const Slider = styled.div` - margin-bottom: 70px; -`; function Home() { const nowMovieData: IMovie[] = []; @@ -55,57 +52,57 @@ function Home() { const topRateMovies: IMovie[] = []; const recommendData2: IMovie[] = []; const [isLoading, setIsLoading] = useState(true); - const nowPage1 = useQuery( + const nowPage1 = useQuery( ["movies", "nowPlayingPage1"], getMoviesPage1 ); - const nowPage2 = useQuery( + const nowPage2 = useQuery( ["movies", "nowPlayingPage2"], getMoviesPage2 ); - const nowPage3 = useQuery( + const nowPage3 = useQuery( ["movies", "nowPlayingPage3"], getMoviesPage3 ); - const nowPage4 = useQuery( + const nowPage4 = useQuery( ["movies", "nowPlayingPage4"], getMoviesPage4 ); - const nowPage5 = useQuery( + const nowPage5 = useQuery( ["movies", "nowPlayingPage5"], getMoviesPage5 ); - const nowPage6 = useQuery( + const nowPage6 = useQuery( ["movies", "nowPlayingPage6"], getMoviesPage6 ); - const topRatePage1 = useQuery( + const topRatePage1 = useQuery( ["movies", "topRatePage1"], topRateMoviePage1 ); - const topRatePage2 = useQuery( + const topRatePage2 = useQuery( ["movies", "topRatePage2"], topRateMoviePage2 ); - const topRatePage3 = useQuery( + const topRatePage3 = useQuery( ["movies", "topRatePage3"], topRateMoviePage3 ); - const topRatePage4 = useQuery( + const topRatePage4 = useQuery( ["movies", "topRatePage4"], topRateMoviePage4 ); - const topRatePage5 = useQuery( + const topRatePage5 = useQuery( ["movies", "topRatePage5"], topRateMoviePage5 ); - const topRatePage6 = useQuery( + const topRatePage6 = useQuery( ["movies", "topRatePage6"], topRateMoviePage6 ); @@ -150,44 +147,36 @@ function Home() { {nowPage1.data?.results[0].overview} {nowMovieData && ( - - - + )} {topRateMovies && ( - - - + )} {recommendData && ( - - - + )} {recommendData2 && ( - - - + )} )} diff --git a/src/Routes/Search.tsx b/src/Routes/Search.tsx index 12c5b74..0f86df2 100644 --- a/src/Routes/Search.tsx +++ b/src/Routes/Search.tsx @@ -21,9 +21,6 @@ const Loader = styled.div` justify-content: center; align-items: center; `; -const Slider = styled.div` - margin-bottom: 70px; -`; function Search() { const location = useLocation(); @@ -71,37 +68,31 @@ function Search() { ) : ( <> {searchData.data?.results[0] && ( - - - + )} {searchData2.data?.results[0] && ( - - - + )} {searchData3.data?.results[0] && ( - - - + )} )} diff --git a/src/Routes/Tv.tsx b/src/Routes/Tv.tsx index 630a720..29be786 100644 --- a/src/Routes/Tv.tsx +++ b/src/Routes/Tv.tsx @@ -1,19 +1,23 @@ import { useQuery } from "react-query"; +import { useLocation } from "react-router-dom"; import styled from "styled-components"; -import { getTvOnAir, IOnAirData } from "../api"; +import { getTvOnAir, IGetVideosProps } from "../api"; import NowMovies from "../Components/NowMovies"; -import TvSlider from "../Components/TvSlider"; -const Wrapper = styled.div``; +const Wrapper = styled.div` + padding-top: 500px; +`; function Tv() { - const onAirData = useQuery(["Tv", "onAir"], getTvOnAir); + const location = useLocation(); + const onAirData = useQuery(["Tv", "onAir"], getTvOnAir); // console.log(onAirData.data); return ( {onAirData.data && ( - )} diff --git a/src/api.ts b/src/api.ts index 62076ad..e799906 100644 --- a/src/api.ts +++ b/src/api.ts @@ -13,12 +13,14 @@ export interface IMovie { poster_path: string; release_date?: string; title?: string; - video?: boolean; + video: boolean; vote_average: number; vote_count: number; + name?: string; + first_air_date?: string; } -export interface IGetMoviesProps { +export interface IGetVideosProps { dates?: { maximum: string; minimum: string; @@ -29,27 +31,12 @@ export interface IGetMoviesProps { total_results: number; } -export interface IGetVideoProps { - id: number; - results: [ - { - id: string; - iso_639_1: string; - iso_3166_1: string; - key: string; - name: string; - official: boolean; - published_at: string; - site: string; - size: number; - type: string; - } - ]; -} - -export interface IGetMovieDetail { +export interface IGetVideoDetail { data: object; - + name?: string; + first_air_date?: string; + origin_country?: string[]; + original_name?: string; dataUpdatedAt: number; errorUpdatedAt: number; failureCount: number; @@ -94,7 +81,7 @@ export interface IGetMovieDetail { }; } -export interface IMovieCredit { +export interface IVideoCredit { cast: ICast[]; crew: ICrew[]; id: number; @@ -129,7 +116,7 @@ interface ICrew { profile_path: string; } -export interface ISimilarMovie { +export interface ISimilarProps { page: number; results: IMovie[]; total_pages: number; @@ -143,7 +130,7 @@ export interface ISearchMovie { total_results: number; } -export interface IOnAir { +export interface ITvProps { backdrop_path: string; first_air_date: string; genre_ids: number[]; @@ -159,13 +146,12 @@ export interface IOnAir { vote_count: number; } -export interface IOnAirData { +export interface IGetTvProps { page: number; - results: IOnAir[]; + results: ITvProps[]; total_pages: number; total_results: number; } - export function getMoviesPage1() { return fetch( `${BASE_URL}/movie/now_playing?api_key=${API_KEY}&language=en-US&page=1` @@ -234,27 +220,15 @@ export function topRateMoviePage6() { ).then((response) => response.json()); } -export function getVideo(id: string) { - return fetch( - `${BASE_URL}/movie/${id}/videos?api_key=${API_KEY}&language=en-US` - ).then((response) => response.json()); -} - -export function getMovieDetail(id: string) { - return fetch( - `${BASE_URL}/movie/${id}?api_key=${API_KEY}&language=en-US&append_to_response=videos,images` - ).then((response) => response.json()); -} - -export function getMovieCredit(id: string) { +export function getVideoDetail(format: string, id: string) { return fetch( - `${BASE_URL}/movie/${id}/credits?api_key=${API_KEY}&language=en-US` + `${BASE_URL}/${format}/${id}?api_key=${API_KEY}&language=en-US&append_to_response=videos` ).then((response) => response.json()); } -export function getSimilarMovie(id: string) { +export function getVideoCredit(format: string, id: string) { return fetch( - `${BASE_URL}/movie/${id}/similar?api_key=${API_KEY}&language=en-US&page=1` + `${BASE_URL}/${format}/${id}/credits?api_key=${API_KEY}&language=en-US` ).then((response) => response.json()); } @@ -282,9 +256,9 @@ export function getTvOnAir() { ).then((response) => response.json()); } -export function getTvSimilar(id: string) { +export function getSimilarData(format: string, id: string) { return fetch( ` - ${BASE_URL}/tv/${id}/similar?api_key=${API_KEY}}&language=en-US&page=1` + ${BASE_URL}/${format}/${id}/similar?api_key=${API_KEY}&language=en-US&page=1` ).then((response) => response.json()); } diff --git a/src/atoms.ts b/src/atoms.ts index 4a1f3fe..2baa86b 100644 --- a/src/atoms.ts +++ b/src/atoms.ts @@ -1,15 +1,6 @@ import { useQuery } from "react-query"; import { atom } from "recoil"; -import { getMoviesPage1, getMoviesPage2, IGetMoviesProps, IMovie } from "./api"; - -const nowPage1 = useQuery( - ["movies", "nowPlayingPage1"], - getMoviesPage1 -); -const nowPage2 = useQuery( - ["movies", "nowPlayingPage2"], - getMoviesPage2 -); +import { getMoviesPage1, getMoviesPage2, IGetVideosProps, IMovie } from "./api"; export const nowMovies = atom({ key: "nowMovies",