Skip to content

Commit

Permalink
[feat] Movie Poster Detail 연결 중..
Browse files Browse the repository at this point in the history
  • Loading branch information
OhDG committed May 19, 2024
1 parent 4375205 commit 04cbc12
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 12 deletions.
2 changes: 2 additions & 0 deletions week_4/movie_poster/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import PopularPage from "./Pages/PopularPage";
import NowPlayingPage from "./Pages/NowPlayingPage";
import TopRatedPage from "./Pages/TopRatedPage";
import UpComingPage from "./Pages/UpComing";
import MovieDetailPage from "./Pages/MovieDetailPage";

function App() {
return (
Expand All @@ -19,6 +20,7 @@ function App() {
<Route path="/nowplaying" element={<NowPlayingPage />} />
<Route path="/toprated" element={<TopRatedPage />} />
<Route path="/upcoming" element={<UpComingPage />} />
<Route path="/movie/:id" element={<MovieDetailPage />} />
</Routes>
</BrowserRouter>
);
Expand Down
178 changes: 178 additions & 0 deletions week_4/movie_poster/src/Pages/MovieDetailPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// import React from "react";
// import styled from "styled-components";
// import { useLocation } from "react-router-dom";

// // 컨테이너 스타일
// const Container = styled.div`
// display: flex;
// justify-content: center;
// align-items: flex-start;
// padding: 20px;
// height: calc(100vh - 40px); // 전체 높이에서 패딩을 빼준 값
// `;

// // 이미지 스타일
// const ImageContainer = styled.div`
// flex: 1;
// padding-right: 20px;
// `;

// const Image = styled.img`
// width: 100%;
// height: auto;
// border-radius: 8px;
// `;

// // 정보 섹션 스타일
// const InfoContainer = styled.div`
// flex: 2;
// display: flex;
// flex-direction: column;
// `;

// const Title = styled.h1`
// font-size: 24px;
// color: #333;
// margin-bottom: 10px;
// `;

// const Rating = styled.span`
// font-size: 18px;
// color: #666;
// margin-bottom: 10px;
// `;

// const ReleaseDate = styled.span`
// font-size: 16px;
// color: #666;
// margin-bottom: 20px;
// `;

// const Overview = styled.p`
// font-size: 16px;
// color: #444;
// line-height: 1.6;
// `;

// const MovieDetailPage = () => {
// const location = useLocation();
// const { movie } = location.state; // 영화 정보는 location.state에서 가져옴

// return (
// <Container>
// <ImageContainer>
// <Image src={movie.posterPath} alt={`${movie.title} Poster`} />
// </ImageContainer>
// <InfoContainer>
// <Title>{movie.title}</Title>
// <Rating>평점: {movie.rating}</Rating>
// <ReleaseDate>개봉일: {movie.releaseDate}</ReleaseDate>
// <Overview>{movie.overview}</Overview>
// </InfoContainer>
// </Container>
// );
// };

// export default MovieDetailPage;

import React, { useEffect } from "react";
import styled from "styled-components";
import { useLocation } from "react-router-dom";

// Styled components
const Container = styled.div`
display: flex;
justify-content: center;
align-items: flex-start;
padding: 20px;
height: calc(100vh - 40px);
`;

const ImageContainer = styled.div`
flex: 1;
padding-right: 20px;
`;

const Image = styled.img`
width: 100%;
height: auto;
border-radius: 8px;
`;

const InfoContainer = styled.div`
flex: 2;
display: flex;
flex-direction: column;
`;

const Title = styled.h1`
font-size: 24px;
color: #333;
margin-bottom: 10px;
`;

const Rating = styled.span`
font-size: 18px;
color: #666;
margin-bottom: 10px;
`;

const ReleaseDate = styled.span`
font-size: 16px;
color: #666;
margin-bottom: 20px;
`;

const Overview = styled.p`
font-size: 16px;
color: #444;
line-height: 1.6;
`;

const MovieDetailPage = () => {
const location = useLocation();
const movie = location.state; // Use optional chaining to avoid errors

useEffect(() => {
// console.log(movie.state?.movie);
});

if (!movie) {
return <div>영화 정보가 없습니다.</div>;
}

// return (
// <Container>
// <ImageContainer>
// <Image
// src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
// alt={`${movie.title} Poster`}
// />
// </ImageContainer>
// <InfoContainer>
// <Title>{movie.title}</Title>
// <Rating>평점: {movie.vote_average}</Rating>
// <ReleaseDate>개봉일: {movie.release_date}</ReleaseDate>
// <Overview>{movie.overview}</Overview>
// </InfoContainer>
// </Container>
// );
return (
<Container>
<ImageContainer>
<Image
src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
alt={`${movie.title} Poster`}
/>
</ImageContainer>
<InfoContainer>
<Title>{movie.title}</Title>
<Rating>평점: {movie.vote_average}</Rating>
<ReleaseDate>개봉일: {movie.release_date}</ReleaseDate>
<Overview>{movie.overview}</Overview>
</InfoContainer>
</Container>
);
};

export default MovieDetailPage;
19 changes: 18 additions & 1 deletion week_4/movie_poster/src/Pages/PopularPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
import axios from "axios";
import styled from "styled-components";
import { ClipLoader } from "react-spinners";
import { Link, useLocation } from "react-router-dom";

export default function PopularPage() {
const API_KEY =
Expand Down Expand Up @@ -38,13 +39,29 @@ export default function PopularPage() {
) : null}

<Container>
{movieList.map((movie) => (
{/* {movieList.map((movie) => (
<Movie>
<img
src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`}
/>
<div key={movie.id}>{movie.title}</div>
</Movie>
))} */}
{movieList.map((movie) => (
<Movie>
<Link
to={{
pathname: `/movie/${movie.id}`,
state: { movie },
}}
>
<img
src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`}
alt={movie.title}
/>
<div>{movie.title}</div>
</Link>
</Movie>
))}
</Container>
</>
Expand Down
99 changes: 89 additions & 10 deletions week_4/movie_poster/src/components/Movie.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,39 +73,118 @@
// );
// }

// import React, { useState, useEffect } from "react";
// import axios from "axios"; // HTTP 통신을 위한 라이브러리
// import styled from "styled-components";
// import { Link } from "react-router-dom";

// export default function Movie() {
// const API_KEY =
// "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0NzkzZjU2ZjUwNDhjMTJiMWY5N2ZlMDRkN2VjZDgxNSIsInN1YiI6IjY2MzM0ODAyYWQ1OWI1MDEyYjZkMzk4MyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.0qdBDtGgV6dfHFLw0NdERZbNHNqfC6UQM_TrssPhyqY";

// const [movie, setMovie] = useState([]); // movie 라는 상태를 정의하고 영화 정보를 저장하는데 사용

// const apiCall = async () => {
// try {
// const response = await axios.get(
// "https://api.themoviedb.org/3/movie/upcoming?language=ko&page=1",
// { headers: { Authorization: `Bearer ${API_KEY}` } } // 요청 헤더에는 인증을 위해 API 키를 Bearer 토큰으로 포함
// );
// const data = response.data.results[0]; // 응답으로 받은 영화 데이터 중 results 배열
// console.log("응답 : ", data);
// setMovie(data); // moive 상태에 저장
// } catch (e) {
// console.log(e);
// }
// };

// useEffect(() => {
// // 컴포넌트가 마운트될 때([] 의존성 배열로 인해 컴포넌트의 생명주기에서 딱 한 번 실행) apiCall 함수 호출
// apiCall();
// }, []);

// if (!movie) return null; // 데이터가 없으면 아무것도 렌더링하지 않음

// return (
// // <div>
// // <img src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`} />
// // <div key={movie.id}>{movie.title}</div>
// // </div>
// <Link to={{ pathname: `/movie/${movie.id}`, state: { movie } }}>
// <img
// src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`}
// alt={movie.title}
// />
// <div>{movie.title}</div>
// </Link>
// );
// }

import React, { useState, useEffect } from "react";
import axios from "axios"; // HTTP 통신을 위한 라이브러리
import axios from "axios";
import styled from "styled-components";
import { useNavigate } from "react-router-dom"; // Import useNavigate

export default function Movie() {
const API_KEY =
"eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI0NzkzZjU2ZjUwNDhjMTJiMWY5N2ZlMDRkN2VjZDgxNSIsInN1YiI6IjY2MzM0ODAyYWQ1OWI1MDEyYjZkMzk4MyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.0qdBDtGgV6dfHFLw0NdERZbNHNqfC6UQM_TrssPhyqY";

const [movie, setMovie] = useState([]); // movie 라는 상태를 정의하고 영화 정보를 저장하는데 사용
const [movie, setMovie] = useState(null); // Initialize state to null for better handling
const navigate = useNavigate(); // Use the useNavigate hook

const apiCall = async () => {
try {
const response = await axios.get(
"https://api.themoviedb.org/3/movie/upcoming?language=ko&page=1",
{ headers: { Authorization: `Bearer ${API_KEY}` } } // 요청 헤더에는 인증을 위해 API 키를 Bearer 토큰으로 포함
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
const data = response.data.results; // 응답으로 받은 영화 데이터 중 results 배열
const data = response.data.results[0]; // Assuming we're only interested in the first result
console.log("응답 : ", data);
setMovie(data); // moive 상태에 저장
setMovie(data);
} catch (e) {
console.log(e);
}
};

useEffect(() => {
// 컴포넌트가 마운트될 때([] 의존성 배열로 인해 컴포넌트의 생명주기에서 딱 한 번 실행) apiCall 함수 호출
apiCall();
}, []);

if (!movie) return null; // If no movie data, render nothing

// Function to handle navigation
const goToMovieDetail = () => {
navigate(`/movie/${movie.id}`, {
state: movie,
});
};

return (
<div>
<img src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`} />
<div key={movie.id}>{movie.title}</div>
</div>
<MovieContainer onClick={goToMovieDetail}>
<img
src={`https://image.tmdb.org/t/p/w200/${movie.poster_path}`}
alt={movie.title}
/>
<div>{movie.title}</div>
</MovieContainer>
);
}

const MovieContainer = styled.div`
cursor: pointer; // Make the whole container clickable
display: flex;
flex-direction: column;
align-items: center;
margin: 20px;
transition: transform 0.3s;
&:hover {
transform: scale(1.05);
}
img {
width: 100%;
height: auto;
border-radius: 8px;
}
`;
Loading

0 comments on commit 04cbc12

Please sign in to comment.