From 2caae158a46e8d2b4a15d0bcb985e218cbaac155 Mon Sep 17 00:00:00 2001 From: phj Date: Mon, 28 Oct 2024 14:40:11 +0900 Subject: [PATCH] =?UTF-8?q?[Feat]=20=EC=BB=A4=EC=8A=A4=ED=85=80=ED=9B=85?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- movie-site/.gitignore | 1 + movie-site/src/apis/axios-instance.js | 10 ++++ movie-site/src/components/MovieList.jsx | 62 ++++++++++++++++++------- movie-site/src/hooks/useCustomFetch.js | 29 ++++++++++++ movie-site/src/page/NowPlaying.jsx | 38 ++++++--------- movie-site/src/page/Popular.jsx | 37 +++++---------- movie-site/src/page/TopRated.jsx | 35 +++++--------- movie-site/src/page/UpComing.jsx | 31 ++++--------- 8 files changed, 130 insertions(+), 113 deletions(-) create mode 100644 movie-site/src/apis/axios-instance.js create mode 100644 movie-site/src/hooks/useCustomFetch.js diff --git a/movie-site/.gitignore b/movie-site/.gitignore index a547bf3..7ceb59f 100644 --- a/movie-site/.gitignore +++ b/movie-site/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.env diff --git a/movie-site/src/apis/axios-instance.js b/movie-site/src/apis/axios-instance.js new file mode 100644 index 0000000..200692f --- /dev/null +++ b/movie-site/src/apis/axios-instance.js @@ -0,0 +1,10 @@ +import axios from "axios"; + +const axiosInstance=axios.create({ + headers: { + Authorization: `Bearer ${import.meta.env.VITE_TMDB_TOKEN}`, + }, + baseURL:import.meta.env.VITE_MOVIE_API_URL, +}) + +export {axiosInstance} \ No newline at end of file diff --git a/movie-site/src/components/MovieList.jsx b/movie-site/src/components/MovieList.jsx index 34a0b98..1472d53 100644 --- a/movie-site/src/components/MovieList.jsx +++ b/movie-site/src/components/MovieList.jsx @@ -1,23 +1,27 @@ import React from 'react'; import styled from 'styled-components'; -const MovieList = ({ movies }) => { // props로 movies 받기 - console.log(movies); +const MovieList = ({ movies }) => { + + return ( - {movies.map(movie => ( + {movies.map(movie => ( - - - {movie.title} - {movie.release_date} - + + + + + + {movie.title} + {movie.release_date} + - ))} - + ))} + ); }; @@ -25,6 +29,19 @@ const Content = styled.div` color: white; padding: 10px; `; +const MovieItem = styled.div` + position: relative; + overflow: hidden; + border-radius: 8px; + width: 100%; + color: white; /* 흰색 글씨 색상 */ + &:hover { + transition: transform 0.2s ease-in-out; + } + &:hover > div { + opacity: 1; /* hover 시 overlay를 보이게 함 */ + } +`; const Title = styled.p` margin: 0; @@ -42,10 +59,8 @@ const MoviesGrid = styled.ul` gap: 10px; padding: 20px; list-style: none; - `; - const MovieContainer = styled.li` display: flex; flex-direction: column; @@ -55,9 +70,20 @@ const MovieContainer = styled.li` const MoviePoster = styled.img` width: 100%; - `; +const Overlay = styled.div` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(0, 0, 0, 0.5); /* 반투명 검정 배경 */ + opacity: 0; /* 기본 상태에서 투명함 */ + transition: opacity 0.2s ease-in-out; +`; - -export default MovieList; \ No newline at end of file +export default MovieList; diff --git a/movie-site/src/hooks/useCustomFetch.js b/movie-site/src/hooks/useCustomFetch.js new file mode 100644 index 0000000..8bcc2e4 --- /dev/null +++ b/movie-site/src/hooks/useCustomFetch.js @@ -0,0 +1,29 @@ +import { useEffect, useState } from "react"; +import { axiosInstance } from "../apis/axios-instance"; + +const useCustomFetch = (url) => { + const [data, setData] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [isError, setIsError] = useState(false); + + useEffect(() => { + const fetchData = async () => { + setIsLoading(true); + try { + const response = await axiosInstance.get(url); + console.log(response.data); + setData(response.data.results); + } catch (error) { + console.error("Error fetching data:", error); + setIsError(true); + } finally { + setIsLoading(false); + } + }; + fetchData(); + }, [url]); + + return { data, isLoading, isError }; +}; + +export default useCustomFetch; diff --git a/movie-site/src/page/NowPlaying.jsx b/movie-site/src/page/NowPlaying.jsx index dd3bee5..f2bf75b 100644 --- a/movie-site/src/page/NowPlaying.jsx +++ b/movie-site/src/page/NowPlaying.jsx @@ -1,33 +1,23 @@ -import { useEffect, useState } from "react"; -import axios from "axios"; +import React from "react"; +import useCustomFetch from "../hooks/useCustomFetch"; import MovieList from "../components/MovieList.jsx"; const NowPlaying = () => { - const [movies, setMovies] = useState([]); + const { data: movies, isLoading, isError } = useCustomFetch( + `/movie/now_playing?language=ko-KR&page=1` + ); - useEffect(() => { - const getMovies = async () => { - try { - const response = await axios.get( - `https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=ko&page=1&with_release_type=2|3&release_date.gte={min_date}&release_date.lte={max_date}`, - { - headers: { - Authorization: `Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhN2FjYmFhOTBlNjczM2MxYjJkMWZmYTJhZmMzY2MzZiIsIm5iZiI6MTcyODM4ODkwNi40NTk3NSwic3ViIjoiNjcwM2YzMWNjYzkwNGYxMmQ5MTM5ZGZkIiwic2NvcGVzIjpbImFwaV9yZWFkIl0sInZlcnNpb24iOjF9.q16fWO2QGu5aTtN8Q4SrbJe9LA7bDsfWrpUG6O9XH7Y`, - }, - } - ); - setMovies(response.data.results); - } catch (error) { - console.error("Error fetching movies:", error); - } - }; + console.log(movies); - getMovies(); - }, []); + if (isLoading) { + return

로딩중입니다..

; + } - return ; + if (isError) { + return

에러가 발생했습니다.

; + } + + return ; }; export default NowPlaying; - - diff --git a/movie-site/src/page/Popular.jsx b/movie-site/src/page/Popular.jsx index f25cc25..9452eac 100644 --- a/movie-site/src/page/Popular.jsx +++ b/movie-site/src/page/Popular.jsx @@ -1,34 +1,19 @@ import MovieList from "../components/MovieList.jsx"; -import {useEffect, useState} from "react"; -import axios from "axios"; +import useCustomFetch from "../hooks/useCustomFetch.js"; const Popular = () => { - const [movies, setMovies] = useState([]) + const { data:movies, isLoading, isError } = useCustomFetch(`/movie/popular?language=ko-KR&page=1`); - useEffect(() => { - const getMovies = async () => { - try { - const response = await axios.get( - `https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=ko&page=1&sort_by=popularity.desc`, - { - headers: { - Authorization: `Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhN2FjYmFhOTBlNjczM2MxYjJkMWZmYTJhZmMzY2MzZiIsIm5iZiI6MTcyODM4ODkwNi40NTk3NSwic3ViIjoiNjcwM2YzMWNjYzkwNGYxMmQ5MTM5ZGZkIiwic2NvcGVzIjpbImFwaV9yZWFkIl0sInZlcnNpb24iOjF9.q16fWO2QGu5aTtN8Q4SrbJe9LA7bDsfWrpUG6O9XH7Y`, - }, - } - ); - setMovies(response.data.results); - } catch (error) { - console.error("Error fetching movies:", error); - } - }; - - getMovies(); - }, []); + if (isLoading) { + return

로딩중입니다..

; +} - return ( - - ); - +if (isError) { + return

에러가 발생했습니다.

; +} + + + return ; }; export default Popular; diff --git a/movie-site/src/page/TopRated.jsx b/movie-site/src/page/TopRated.jsx index 06671d1..82019e3 100644 --- a/movie-site/src/page/TopRated.jsx +++ b/movie-site/src/page/TopRated.jsx @@ -1,34 +1,21 @@ import MovieList from "../components/MovieList.jsx"; import {useEffect, useState} from "react"; import axios from "axios"; +import useCustomFetch from '../hooks/useCustomFetch'; + const TopRated = () => { - const [movies, setMovies] = useState([]) + const { data: movies, isLoading, isError } = useCustomFetch(`/movie/top_rated?language=ko-KR&page=1`); + + if (isLoading) { + return

로딩중입니다..

; +} - useEffect(() => { - const getMovies = async () => { - try { - const response = await axios.get( - `https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=ko&page=1&sort_by=vote_average.desc&without_genres=99,10755&vote_count.gte=200`, - { - headers: { - Authorization: `Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhN2FjYmFhOTBlNjczM2MxYjJkMWZmYTJhZmMzY2MzZiIsIm5iZiI6MTcyODM4ODkwNi40NTk3NSwic3ViIjoiNjcwM2YzMWNjYzkwNGYxMmQ5MTM5ZGZkIiwic2NvcGVzIjpbImFwaV9yZWFkIl0sInZlcnNpb24iOjF9.q16fWO2QGu5aTtN8Q4SrbJe9LA7bDsfWrpUG6O9XH7Y`, - }, - } - ); - setMovies(response.data.results); - } catch (error) { - console.error("Error fetching movies:", error); - } - }; - - getMovies(); - }, []); +if (isError) { + return

에러가 발생했습니다.

; +} - return ( - - ); - + return ; }; export default TopRated; \ No newline at end of file diff --git a/movie-site/src/page/UpComing.jsx b/movie-site/src/page/UpComing.jsx index 41a985a..614ce4b 100644 --- a/movie-site/src/page/UpComing.jsx +++ b/movie-site/src/page/UpComing.jsx @@ -1,32 +1,21 @@ import MovieList from "../components/MovieList.jsx"; import { useEffect, useState } from "react"; +import useCustomFetch from "../hooks/useCustomFetch"; import axios from "axios"; const UpComing = () => { - const [movies, setMovies] = useState([]); + const { data: movies, isLoading, isError } = useCustomFetch( + `/movie/upcoming?language=ko-KR&page=1` + ); - useEffect(() => { - const getMovies = async () => { - //const min_date = new Date().toISOString().split('T')[0]; // 오늘 날짜 (YYYY-MM-DD) - //const max_date = "2024-12-31"; // 미래의 특정 날짜 - try { - const response = await axios.get( - `https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc&with_release_type=2|3&release_date.gte={min_date}&release_date.lte={max_date}`, - { - headers: { - Authorization: `Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhN2FjYmFhOTBlNjczM2MxYjJkMWZmYTJhZmMzY2MzZiIsIm5iZiI6MTcyODM4ODkwNi40NTk3NSwic3ViIjoiNjcwM2YzMWNjYzkwNGYxMmQ5MTM5ZGZkIiwic2NvcGVzIjpbImFwaV9yZWFkIl0sInZlcnNpb24iOjF9.q16fWO2QGu5aTtN8Q4SrbJe9LA7bDsfWrpUG6O9XH7Y`, - }, - } - ); - setMovies(response.data.results); - } catch (error) { - console.error("Error fetching movies:", error); - } - }; + if (isLoading) { + return

로딩중입니다..

; + } - getMovies(); - }, []); + if (isError) { + return

에러가 발생했습니다.

; + } return ; };