Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Week4/#9] 4주차 워크북 미션-01 #10

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions movie-site/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
.env
10 changes: 10 additions & 0 deletions movie-site/src/apis/axios-instance.js
Original file line number Diff line number Diff line change
@@ -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}
62 changes: 44 additions & 18 deletions movie-site/src/components/MovieList.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
import React from 'react';
import styled from 'styled-components';

const MovieList = ({ movies }) => { // props로 movies 받기
console.log(movies);
const MovieList = ({ movies }) => {


return (
<MoviesGrid>
{movies.map(movie => (
{movies.map(movie => (
<MovieContainer key={movie.id}>
<MoviePoster
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt={movie.title}
/>
<Content>
<Title>{movie.title}</Title>
<Date>{movie.release_date}</Date>
</Content>
<MovieItem>
<MoviePoster
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt={movie.title}
/>
<Overlay />
</MovieItem>
<Content>
<Title>{movie.title}</Title>
<Date>{movie.release_date}</Date>
</Content>
</MovieContainer>
))}
</MoviesGrid>
))}
</MoviesGrid>
);
};

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;
Expand All @@ -42,10 +59,8 @@ const MoviesGrid = styled.ul`
gap: 10px;
padding: 20px;
list-style: none;

`;


const MovieContainer = styled.li`
display: flex;
flex-direction: column;
Expand All @@ -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;
export default MovieList;
29 changes: 29 additions & 0 deletions movie-site/src/hooks/useCustomFetch.js
Original file line number Diff line number Diff line change
@@ -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;
38 changes: 14 additions & 24 deletions movie-site/src/page/NowPlaying.jsx
Original file line number Diff line number Diff line change
@@ -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 <h1 style={{ color: 'white' }}>로딩중입니다..</h1>;
}

return <MovieList movies={movies} />;
if (isError) {
return <h1 style={{ color: 'white' }}>에러가 발생했습니다.</h1>;
}

return <MovieList movies={movies} />;
};

export default NowPlaying;


37 changes: 11 additions & 26 deletions movie-site/src/page/Popular.jsx
Original file line number Diff line number Diff line change
@@ -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 <h1 style={{ color: 'white' }}>로딩중입니다..</h1>;
}

return (
<MovieList movies={movies} />
);

if (isError) {
return <h1 style={{ color: 'white' }}>에러가 발생했습니다.</h1>;
}


return <MovieList movies={movies} />;
};

export default Popular;
35 changes: 11 additions & 24 deletions movie-site/src/page/TopRated.jsx
Original file line number Diff line number Diff line change
@@ -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 <h1 style={{ color: 'white' }}>로딩중입니다..</h1>;
}

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 <h1 style={{ color: 'white' }}>에러가 발생했습니다.</h1>;
}

return (
<MovieList movies={movies} />
);

return <MovieList movies={movies} />;
};

export default TopRated;
31 changes: 10 additions & 21 deletions movie-site/src/page/UpComing.jsx
Original file line number Diff line number Diff line change
@@ -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 <h1 style={{ color: 'white' }}>로딩중입니다..</h1>;
}

getMovies();
}, []);
if (isError) {
return <h1 style={{ color: 'white' }}>에러가 발생했습니다.</h1>;
}

return <MovieList movies={movies} />;
};
Expand Down