Skip to content

Commit e4aef96

Browse files
committed
무비페이지3단계완성
1 parent a518047 commit e4aef96

File tree

9 files changed

+277
-134
lines changed

9 files changed

+277
-134
lines changed

package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"react-dom": "^19.1.1",
1616
"react-router": "^7.9.6",
1717
"react-router-dom": "^7.9.6",
18+
"swiper": "^12.0.3",
1819
"tailwindcss": "^4.1.17"
1920
},
2021
"devDependencies": {

src/components/MovieCard.css

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,20 @@
1-
.movie-card {
2-
width: 180px;
3-
display: flex;
4-
flex-direction: column;
5-
align-items: center;
6-
margin-bottom: 20px;
7-
cursor: pointer;
8-
transition: transform 0.2s ease;
9-
}
10-
11-
.movie-card:hover {
12-
transform: scale(1.05);
1+
.movie-list {
2+
display: grid;
3+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
4+
gap: 20px;
5+
padding: 0 30px;
6+
max-width: 1400px;
7+
margin: 0 auto;
138
}
149

15-
.movie-card-img {
10+
.movie-card {
1611
width: 100%;
17-
height: 270px;
18-
border-radius: 8px;
19-
object-fit: cover;
20-
}
21-
22-
.movie-card-title {
23-
margin: 8px 0 4px;
24-
font-size: 15px;
25-
text-align: center;
12+
max-width: 180px; /* 카드 전체 최대 크기 축소 */
13+
margin: 0 auto;
2614
}
2715

28-
.movie-card-rating {
29-
font-size: 14px;
30-
color: #f5c518;
31-
text-align: center;
32-
}
33-
34-
@media (max-width: 768px) {
35-
.movie-card {
36-
width: 140px;
37-
}
38-
39-
.movie-card-img {
40-
height: 200px;
41-
}
42-
43-
.movie-card-title {
44-
font-size: 14px;
45-
}
16+
.movie-card img {
17+
width: 100%;
18+
height: auto;
19+
border-radius: 10px;
4620
}

src/components/MovieSwiper.css

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
.top-rated-section {
2+
margin-top: 30px;
3+
width: 100%;
4+
}
5+
6+
.top-rated-title {
7+
font-size: 1.8rem;
8+
font-weight: 700;
9+
color: #fff;
10+
margin-bottom: 15px;
11+
text-align: left;
12+
padding-left: 40px;
13+
}
14+
15+
/* 슬라이드 이미지 크기 업그레이드 */
16+
.swiper-slide {
17+
width: 210px !important;
18+
flex: 0 0 210px !important;
19+
}
20+
21+
.swiper-movie-card {
22+
width: 210px;
23+
cursor: pointer;
24+
}
25+
26+
.swiper-movie-card img {
27+
width: 210px;
28+
height: auto;
29+
border-radius: 10px;
30+
}
31+
32+
/* 영화 제목 */
33+
.s-title {
34+
margin-top: 6px;
35+
font-size: 0.9rem;
36+
color: #fff;
37+
text-align: center;
38+
}
39+
40+
/* 평점 */
41+
.s-rating {
42+
font-size: 0.8rem;
43+
color: #f5c518;
44+
text-align: center;
45+
}

src/components/MovieSwiper.jsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// src/components/MovieSwiper.jsx
2+
import { useEffect, useState } from "react";
3+
import { Swiper, SwiperSlide } from "swiper/react";
4+
import { Navigation, Pagination, Scrollbar, A11y } from "swiper/modules";
5+
import { Link } from "react-router-dom";
6+
import "./MovieSwiper.css";
7+
8+
import "swiper/css";
9+
import "swiper/css/navigation";
10+
import "swiper/css/pagination";
11+
import "swiper/css/scrollbar";
12+
13+
const API_TOKEN = import.meta.env.VITE_TMDB_API_TOKEN;
14+
15+
const MovieSwiper = () => {
16+
const [movies, setMovies] = useState([]);
17+
18+
const fetchTopRated = async () => {
19+
const res = await fetch(
20+
"https://api.themoviedb.org/3/movie/top_rated?language=ko-KR",
21+
{
22+
headers: {
23+
accept: "application/json",
24+
Authorization: `Bearer ${API_TOKEN}`,
25+
},
26+
}
27+
);
28+
29+
const data = await res.json();
30+
setMovies(data.results || []);
31+
};
32+
33+
useEffect(() => {
34+
fetchTopRated();
35+
}, []);
36+
37+
return (
38+
<div className="top-rated-section">
39+
<h2 className="top-rated-title">Top Rated Movies ⭐</h2>
40+
41+
<Swiper
42+
modules={[Navigation, Pagination, Scrollbar, A11y]}
43+
spaceBetween={10} // 기존 20 → 10 감소
44+
slidesPerView={6} // 한 줄 더 꽉 채워보임
45+
navigation
46+
pagination={{ clickable: true }}
47+
scrollbar={{ draggable: true }}
48+
autoHeight={false}
49+
style={{ height: "360px" }}
50+
>
51+
{movies.map((movie) => (
52+
<SwiperSlide key={movie.id}>
53+
<Link to={`/detail/${movie.id}`}>
54+
<div className="swiper-movie-card">
55+
<img
56+
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
57+
alt={movie.title}
58+
/>
59+
<p className="s-title">{movie.title}</p>
60+
<p className="s-rating">{movie.vote_average.toFixed(2)}</p>
61+
</div>
62+
</Link>
63+
</SwiperSlide>
64+
))}
65+
</Swiper>
66+
</div>
67+
);
68+
};
69+
70+
export default MovieSwiper;

src/components/TopRatedSwiper.jsx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { useEffect, useState } from "react";
2+
import { Swiper, SwiperSlide } from "swiper/react";
3+
import { Navigation, Pagination, Scrollbar, A11y } from "swiper/modules";
4+
5+
import "swiper/css";
6+
import "swiper/css/navigation";
7+
import "swiper/css/pagination";
8+
import "swiper/css/scrollbar";
9+
10+
const API_TOKEN = import.meta.env.VITE_TMDB_API_TOKEN;
11+
const IMAGE_URL = "https://image.tmdb.org/t/p/w500";
12+
13+
const TopRatedSwiper = () => {
14+
const [movies, setMovies] = useState([]);
15+
16+
const fetchTopRated = async () => {
17+
const res = await fetch(
18+
"https://api.themoviedb.org/3/movie/top_rated?language=ko-KR",
19+
{
20+
headers: {
21+
accept: "application/json",
22+
Authorization: `Bearer ${API_TOKEN}`,
23+
},
24+
}
25+
);
26+
const data = await res.json();
27+
setMovies(data.results || []);
28+
};
29+
30+
useEffect(() => {
31+
fetchTopRated();
32+
}, []);
33+
34+
return (
35+
<div style={{ marginTop: "40px" }}>
36+
<h2 style={{ color: "#fff", marginBottom: "20px" }}>
37+
Top Rated Movies ⭐
38+
</h2>
39+
40+
<Swiper
41+
modules={[Navigation, Pagination, Scrollbar, A11y]}
42+
spaceBetween={20}
43+
slidesPerView={6}
44+
navigation
45+
pagination={{ clickable: true }}
46+
scrollbar={{ draggable: true }}
47+
>
48+
{movies.map((movie) => (
49+
<SwiperSlide key={movie.id}>
50+
<div
51+
style={{
52+
background: "#1c1c1c",
53+
padding: "10px",
54+
borderRadius: "12px",
55+
textAlign: "center",
56+
}}
57+
>
58+
<img
59+
src={IMAGE_URL + movie.poster_path}
60+
alt={movie.title}
61+
style={{
62+
width: "100%",
63+
borderRadius: "10px",
64+
marginBottom: "10px",
65+
}}
66+
/>
67+
68+
<h4
69+
style={{ color: "#fff", fontSize: "15px", marginBottom: "5px" }}
70+
>
71+
{movie.title}
72+
</h4>
73+
74+
<p style={{ color: "#f1c40f", fontWeight: "bold" }}>
75+
{movie.vote_average}
76+
</p>
77+
</div>
78+
</SwiperSlide>
79+
))}
80+
</Swiper>
81+
</div>
82+
);
83+
};
84+
85+
export default TopRatedSwiper;

src/index.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
html,
22
body,
33
#root {
4-
background-color: #000 !important;
5-
margin: 0 !important;
6-
padding: 0 !important;
4+
background-color: #000;
5+
margin: 0;
6+
padding: 0;
77
width: 100%;
8-
height: 100%;
8+
min-height: 100%;
99
overflow-x: hidden;
1010
}

0 commit comments

Comments
 (0)