From 2e0e84dedd09ee2d48f52997152432470c6bd010 Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 11:26:20 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat(assets):=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=ED=99=9C=EC=9A=A9=EC=9D=84=20=EC=9C=84=ED=95=9C=20assets=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/src/assets/images/logo.png | Bin 0 -> 1416 bytes ssr/src/assets/images/modal_button_close.png | Bin 0 -> 455 bytes ssr/src/assets/images/star_empty.png | Bin 0 -> 1187 bytes ssr/src/assets/images/star_filled.png | Bin 0 -> 770 bytes ssr/src/assets/images/woowacourse_logo.png | Bin 0 -> 7012 bytes ssr/src/assets/styles/colors.css | 13 ++ ssr/src/assets/styles/main.css | 134 +++++++++++++++++++ ssr/src/assets/styles/modal.css | 88 ++++++++++++ ssr/src/assets/styles/reset.css | 129 ++++++++++++++++++ ssr/src/assets/styles/tab.css | 32 +++++ ssr/src/assets/styles/thumbnail.css | 40 ++++++ 11 files changed, 436 insertions(+) create mode 100644 ssr/src/assets/images/logo.png create mode 100644 ssr/src/assets/images/modal_button_close.png create mode 100644 ssr/src/assets/images/star_empty.png create mode 100644 ssr/src/assets/images/star_filled.png create mode 100644 ssr/src/assets/images/woowacourse_logo.png create mode 100644 ssr/src/assets/styles/colors.css create mode 100644 ssr/src/assets/styles/main.css create mode 100644 ssr/src/assets/styles/modal.css create mode 100644 ssr/src/assets/styles/reset.css create mode 100644 ssr/src/assets/styles/tab.css create mode 100644 ssr/src/assets/styles/thumbnail.css diff --git a/ssr/src/assets/images/logo.png b/ssr/src/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d8476f93eda26b0a937e0961c676fd87f1883b27 GIT binary patch literal 1416 zcmV;31$X+1P)g&&W+h(h0^SYHl)@$Cfqj_2_-w$ismyFt5b(2$%-*y1ZEmnA^K--4d)L*=+_ho*F7g-z|NfN8X9Yb@ zbHxblJ5=C;(P@$z!ywvarW7O4lst=O?`CK>y0CCsWg|U&$qjxYXkpAzKQkpL1id_9 zB$Ba{`^a6vzXJWV@Lc1`u}0g3a?oy@Mfb%G)>F2pj$UKgGdEDDIbS_@6&P3~iPEc9_3f4{N%iR-6zTHrURAbKgqs;w^{ z5j-B159rIL-05khv}tTMZW^20L&e_%%6hk1d5PH+gJ=hB;yX=3%AsFkT;$2|?Bv*$ z`qM)FS1w(lk9};D;?o1;-?H}aS=)X@ze_>3r9d}#C&X+g>t!p9y%Fft(A;voXRF{j zy^!1V476%;w@Z_n#Q4WoWHnx+zjH($IyJlgT}P6E7RQ>kX@ncUCksSG@o9;Kwn-S>iUjch1)muRHx`_~yr2p#koM6M5uSta=rVpHfLG3-m)9x%dql zk&K;=?+Td`<6)_HNE7;LS=|y%?^49c7Zse>pqrbLGBl&11!&NQLqWC`lkE%oIq_eR z=Qi{7KM~@qK^aT*)Kf}g3PFNR=JMY`9y@{Tq*(jB^A>Zm z-uLXRedUHRi?qc&JGL*~aZpTV)xa}n6R+l?uI*0TRrpKy+RMV&wLH5OIvambx9>7t zD9CQ%SQjl}h4BZPPdv?t?{Fc$ruaj@AL2NaCMgs?aU!_kO(k`DLO<0?D1C<9p{tOW=XgG$ zYf17_cbRNxku7F3)PBSGY+>x2m%iwwaCr@R71ud*yHN{HhFx0JCr}zBb3gp>C@aU+bI9SB)#JtZt@NU|8g{(n1W&a>M&rw zfGp9>2 zo{wegA%2Mv(D^s4vJ`r-JGk&pGTiQMf=$3;cqMhPsEUQC5W5LfqB__FtVIoBC8$MZ z!esu=Iky#;z65xr0%g>73Y%S4gEAKDeBaj1#aghYuq(5bClB`qH83#*<)$2%o;)-J z|908r-{V~S}1VTs&IL2%Hd~u|7J~6-l31`e98Hf!fEtQ#Jrc&!TkptseD0qZ9_{v#!VX< zMLCb`(fCdLv{t{?k$Px7e;In}e%Fb9Op?usA0lVtSHP0uW#fI0<9S15pXL`!8}S7l zz?sd+Bj@K4-U3VOWCb?4LVAMgNDQ?^ z!S8i1l)ZH$m8yKNq#eYKNg_9~>*E;wBoO}eCk4N-{QSr-&Guu!74fG9~_4od5=qyL$r!i?ddbVuocEXbK8WxJHJ z=S9~{G1VyhEx|_uv9*y0xrtI0j;QwLrLNqj5bC#{zJ_rjoH=8ZgbxFUm~HH%AxSdS zI9GD>B~}Z8ebwMxbn%!j{io}wl{F{*=MW{aoCNe~snl00J&&!83~5$Q!qg`v-CCFw z;;A(s_w`JQZc9Lxmw=BANb8mF{m+pVHK!R{lx`RJaed-#xEEoJRLv<>1?FW3J`D6w zteYvdXW z*;)0|sZuMcZtJE2EJaP9WNQVNud0MyVTBdE@E0btf^*b`FRK6m002ovPDHLkV1iPB BDenLP literal 0 HcmV?d00001 diff --git a/ssr/src/assets/images/star_filled.png b/ssr/src/assets/images/star_filled.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6f2999376b487ecf3cc67858825898891046ab GIT binary patch literal 770 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 *:not(:last-child) { + margin-bottom: 8px; +} + +h1.logo { + font-size: 2rem; +} + +.rate { + display: flex; + align-items: baseline; + color: var(--color-yellow); +} + +.rate > img { + position: relative; + top: 2px; +} + +span.rate-value { + margin-left: 8px; + font-weight: bold; + font-size: 1.66rem; +} + +.title { + font-size: 3rem; + font-weight: bold; +} + +footer.footer { + min-height: 180px; + background-color: var(--color-bluegray-80); + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + font-size: 1.1rem; +} + +footer.footer p:not(:last-child) { + margin-bottom: 8px; +} diff --git a/ssr/src/assets/styles/modal.css b/ssr/src/assets/styles/modal.css new file mode 100644 index 0000000..240a7a3 --- /dev/null +++ b/ssr/src/assets/styles/modal.css @@ -0,0 +1,88 @@ +@import "./colors.css"; + +/* modal.css */ +body.modal-open { + overflow: hidden; +} + +.modal-background { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); /* 반투명 배경을 위해 설정 */ + backdrop-filter: blur(10px); /* 블러 효과 적용 */ + display: flex; + justify-content: center; + align-items: center; + z-index: 10; + visibility: hidden; /* 모달이 기본적으로 보이지 않도록 설정 */ + opacity: 0; + transition: + opacity 0.3s ease, + visibility 0.3s ease; +} + +.modal-background.active { + visibility: visible; + opacity: 1; +} + +.modal { + background-color: var(--color-bluegray-90); + padding: 20px; + border-radius: 16px; + color: white; + z-index: 2; + position: relative; + width: 1000px; +} + +.close-modal { + position: absolute; + margin: 0; + padding: 0; + top: 24px; + right: 24px; + background: none; + border: none; + color: white; + font-size: 20px; + cursor: pointer; +} + +.modal-container { + display: flex; +} + +.modal-image img { + width: 380px; + border-radius: 16px; +} + +.modal-description { + width: 100%; + padding: 8px; + margin-left: 16px; + line-height: 1.6rem; +} + +.modal-description .rate > img { + position: relative; + top: 5px; +} + +.modal-description > *:not(:last-child) { + margin-bottom: 8px; +} + +.modal-description h2 { + font-size: 2rem; + margin: 0 0 8px; +} + +.detail { + max-height: 430px; + overflow-y: auto; +} diff --git a/ssr/src/assets/styles/reset.css b/ssr/src/assets/styles/reset.css new file mode 100644 index 0000000..3675e64 --- /dev/null +++ b/ssr/src/assets/styles/reset.css @@ -0,0 +1,129 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ""; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/ssr/src/assets/styles/tab.css b/ssr/src/assets/styles/tab.css new file mode 100644 index 0000000..ac357b5 --- /dev/null +++ b/ssr/src/assets/styles/tab.css @@ -0,0 +1,32 @@ +@import "./colors.css"; + +.tab { + display: flex; + margin: 32px 0; +} + +.tab-item { + cursor: pointer; + user-select: none; + + display: flex; + align-items: center; + justify-content: center; + width: 120px; + height: 40px; + + border-radius: 40px; + background: linear-gradient(90deg, #14191f 0%, #0a0d12 100%); +} + +.tab-item.selected { + background: linear-gradient(90deg, #4b8bf4 0%, #1c2a3a 100%); +} + +.tab-item:hover { + background: linear-gradient(90deg, #2f3e54 0%, #4b8bf4 100%); +} + +.tab li:not(:last-child) { + margin-right: 8px; +} diff --git a/ssr/src/assets/styles/thumbnail.css b/ssr/src/assets/styles/thumbnail.css new file mode 100644 index 0000000..378a494 --- /dev/null +++ b/ssr/src/assets/styles/thumbnail.css @@ -0,0 +1,40 @@ +@import "./colors.css"; + +.thumbnail-list { + margin: 0 auto 56px; + display: grid; + grid-template-columns: repeat(5, 200px); + gap: 70px; +} + +.thumbnail { + width: 200px; + height: 300px; + border-radius: 8px; +} + +.item { + user-select: none; + cursor: pointer; +} + +.item-desc > *:not(:last-child) { + position: relative; + margin-bottom: 4px; + line-height: 1.2rem; +} + +p.rate { + display: flex; + align-items: baseline; + color: var(--color-yellow); +} + +p.rate > span { + margin-left: 4px; +} + +.item .star { + width: 16px; + top: 1px; +} From 2ca8aa09796199bcb2b563a57050ed588ca96425 Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 11:26:53 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat(constant):=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/src/constant.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 ssr/src/constant.js diff --git a/ssr/src/constant.js b/ssr/src/constant.js new file mode 100644 index 0000000..b26b9a7 --- /dev/null +++ b/ssr/src/constant.js @@ -0,0 +1,22 @@ +export const BASE_URL = "https://api.themoviedb.org/3/movie"; + +export const TMDB_THUMBNAIL_URL = + "https://media.themoviedb.org/t/p/w440_and_h660_face/"; +export const TMDB_ORIGINAL_URL = "https://image.tmdb.org/t/p/original/"; +export const TMDB_BANNER_URL = + "https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/"; +export const TMDB_MOVIE_LISTS = { + POPULAR: BASE_URL + "/popular?language=ko-KR&page=1", + NOW_PLAYING: BASE_URL + "/now_playing?language=ko-KR&page=1", + TOP_RATED: BASE_URL + "/top_rated?language=ko-KR&page=1", + UPCOMING: BASE_URL + "/upcoming?language=ko-KR&page=1", +}; +export const TMDB_MOVIE_DETAIL_URL = "https://api.themoviedb.org/3/movie/"; + +export const FETCH_OPTIONS = { + method: "GET", + headers: { + accept: "application/json", + Authorization: "Bearer " + process.env.TMDB_TOKEN, + }, +}; From f78a097920b6ce8b6b0e94c39852d09f56522409 Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 11:27:55 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat(index):=20selected=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EB=A5=BC=20=EC=9C=84=ED=95=9C=20tabItem=EC=97=90=20cl?= =?UTF-8?q?ass=20=EB=AA=87=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/views/index.html | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ssr/views/index.html b/ssr/views/index.html index a052396..2576277 100644 --- a/ssr/views/index.html +++ b/ssr/views/index.html @@ -14,10 +14,15 @@
-
+
-

MovieList

+

+ MovieList +

@@ -33,28 +38,28 @@

MovieList

  • -
  • + >

    상영 예정

    From e985639acf2fa58084e1391e7911059fdae0ebe6 Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 11:28:28 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat(movies):=20=EC=98=81=ED=99=94=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/server/routes/index.js | 47 +++++++++++++++----- ssr/src/movies.js | 91 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 ssr/src/movies.js diff --git a/ssr/server/routes/index.js b/ssr/server/routes/index.js index 84d32f2..eafc682 100644 --- a/ssr/server/routes/index.js +++ b/ssr/server/routes/index.js @@ -1,19 +1,46 @@ import { Router } from "express"; -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import { + fetchNowPlayingMovies, + fetchPopularMovies, + fetchTopRatedMovies, + fetchUpcomingMovies, + generateRenderedHTML, +} from "../../src/movies.js"; const router = Router(); -router.get("/", (_, res) => { - const templatePath = path.join(__dirname, "../../views", "index.html"); - const moviesHTML = "

    들어갈 본문 작성

    "; +router.get("/", async (_, res) => { + const movies = await fetchNowPlayingMovies(); + const renderedHTML = generateRenderedHTML(movies.results, "nowPlaying"); - const template = fs.readFileSync(templatePath, "utf-8"); - const renderedHTML = template.replace("", moviesHTML); + res.send(renderedHTML); +}); + +router.get("/now-playing", async (_, res) => { + const movies = await fetchNowPlayingMovies(); + const renderedHTML = generateRenderedHTML(movies.results, "nowPlaying"); + + res.send(renderedHTML); +}); + +router.get("/popular", async (_, res) => { + const movies = await fetchPopularMovies(); + const renderedHTML = generateRenderedHTML(movies.results, "popular"); + + res.send(renderedHTML); +}); + +router.get("/top-rated", async (_, res) => { + const movies = await fetchTopRatedMovies(); + const renderedHTML = generateRenderedHTML(movies.results, "topRated"); + + res.send(renderedHTML); +}); + +router.get("/upcoming", async (_, res) => { + const movies = await fetchUpcomingMovies(); + const renderedHTML = generateRenderedHTML(movies.results, "upcoming"); res.send(renderedHTML); }); diff --git a/ssr/src/movies.js b/ssr/src/movies.js new file mode 100644 index 0000000..de4e839 --- /dev/null +++ b/ssr/src/movies.js @@ -0,0 +1,91 @@ +import { FETCH_OPTIONS, TMDB_MOVIE_LISTS } from "./constant.js"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export const fetchNowPlayingMovies = async () => { + const response = await fetch(TMDB_MOVIE_LISTS.NOW_PLAYING, FETCH_OPTIONS); + + return await response.json(); +}; + +export const fetchPopularMovies = async () => { + const response = await fetch(TMDB_MOVIE_LISTS.POPULAR, FETCH_OPTIONS); + + return await response.json(); +}; + +export const fetchTopRatedMovies = async () => { + const response = await fetch(TMDB_MOVIE_LISTS.TOP_RATED, FETCH_OPTIONS); + + return await response.json(); +}; + +export const fetchUpcomingMovies = async () => { + const response = await fetch(TMDB_MOVIE_LISTS.UPCOMING, FETCH_OPTIONS); + + return await response.json(); +}; + +export const generateMovies = (movieItems = []) => + movieItems + .map( + ({ id, title, poster_path, vote_average }) => /*html*/ ` +
  • + +
    + ${title} +
    +

    ${vote_average.toFixed( + 1 + )}

    + ${title} +
    +
    +
    +
  • + ` + ) + .join("\n"); + +export const generateRenderedHTML = (movieItems, tabItem) => { + const bestMovieItem = movieItems[0]; + const moviesHTML = generateMovies(movieItems); + + const templatePath = path.join(__dirname, "../views", "index.html"); + let template = fs.readFileSync(templatePath, "utf-8"); + + template = template.replace("", moviesHTML); + template = template.replace( + "${background-container}", + "https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/" + + bestMovieItem.poster_path + ); + template = template.replace("${bestMovie.rate}", bestMovieItem.vote_average); + template = template.replace("${bestMovie.title}", bestMovieItem.title); + template = template.replace( + "${nowPlayingTabItem}", + tabItem === "nowPlaying" ? "selected" : "" + ); + template = template.replace( + "${popularTabItem}", + tabItem === "popular" ? "selected" : "" + ); + template = template.replace( + "${topRatedTabItem}", + tabItem === "topRated" ? "selected" : "" + ); + template = template.replace( + "${upcomingTabItem}", + tabItem === "upcoming" ? "selected" : "" + ); + + return template; +}; From e16e1caaebbf66e43bc7297eb71ecf603e2122ba Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 22:52:03 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refactor(movies):=20rendered=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/src/movies.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ssr/src/movies.js b/ssr/src/movies.js index de4e839..3b165db 100644 --- a/ssr/src/movies.js +++ b/ssr/src/movies.js @@ -55,7 +55,7 @@ export const generateMovies = (movieItems = []) => ) .join("\n"); -export const generateRenderedHTML = (movieItems, tabItem) => { +export const generateRenderedMovieItemsHTML = (movieItems, tabItem) => { const bestMovieItem = movieItems[0]; const moviesHTML = generateMovies(movieItems); @@ -68,8 +68,13 @@ export const generateRenderedHTML = (movieItems, tabItem) => { "https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/" + bestMovieItem.poster_path ); - template = template.replace("${bestMovie.rate}", bestMovieItem.vote_average); + template = template.replace( + "${bestMovie.rate}", + bestMovieItem.vote_average.toFixed(1) + ); template = template.replace("${bestMovie.title}", bestMovieItem.title); + template = template.replace("${id}", bestMovieItem.id); + template = template.replace( "${nowPlayingTabItem}", tabItem === "nowPlaying" ? "selected" : "" From 21dd160827d42eae3f53c81f187da93733430220 Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 22:52:48 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat(modal):=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=AA=A8=EB=8B=AC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/server/routes/index.js | 44 +++++++++++++++++++++++---- ssr/src/modal.js | 62 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 ssr/src/modal.js diff --git a/ssr/server/routes/index.js b/ssr/server/routes/index.js index eafc682..4823530 100644 --- a/ssr/server/routes/index.js +++ b/ssr/server/routes/index.js @@ -5,42 +5,74 @@ import { fetchPopularMovies, fetchTopRatedMovies, fetchUpcomingMovies, - generateRenderedHTML, + generateRenderedMovieItemsHTML, } from "../../src/movies.js"; +import { + fetchMovieItemDetail, + generateRenderedModalHTML, +} from "../../src/modal.js"; const router = Router(); router.get("/", async (_, res) => { const movies = await fetchNowPlayingMovies(); - const renderedHTML = generateRenderedHTML(movies.results, "nowPlaying"); + const renderedHTML = generateRenderedMovieItemsHTML( + movies.results, + "nowPlaying" + ); res.send(renderedHTML); }); router.get("/now-playing", async (_, res) => { const movies = await fetchNowPlayingMovies(); - const renderedHTML = generateRenderedHTML(movies.results, "nowPlaying"); + const renderedHTML = generateRenderedMovieItemsHTML( + movies.results, + "nowPlaying" + ); res.send(renderedHTML); }); router.get("/popular", async (_, res) => { const movies = await fetchPopularMovies(); - const renderedHTML = generateRenderedHTML(movies.results, "popular"); + const renderedHTML = generateRenderedMovieItemsHTML( + movies.results, + "popular" + ); res.send(renderedHTML); }); router.get("/top-rated", async (_, res) => { const movies = await fetchTopRatedMovies(); - const renderedHTML = generateRenderedHTML(movies.results, "topRated"); + const renderedHTML = generateRenderedMovieItemsHTML( + movies.results, + "topRated" + ); res.send(renderedHTML); }); router.get("/upcoming", async (_, res) => { const movies = await fetchUpcomingMovies(); - const renderedHTML = generateRenderedHTML(movies.results, "upcoming"); + const renderedHTML = generateRenderedMovieItemsHTML( + movies.results, + "upcoming" + ); + + res.send(renderedHTML); +}); + +router.get("/detail/:id", async (req, res) => { + const id = req.params.id; + const movieItems = await fetchNowPlayingMovies(); + const movieDetail = await fetchMovieItemDetail(id); + + const renderedHTML = generateRenderedModalHTML( + movieItems.results, + movieDetail + ); res.send(renderedHTML); }); diff --git a/ssr/src/modal.js b/ssr/src/modal.js new file mode 100644 index 0000000..d322024 --- /dev/null +++ b/ssr/src/modal.js @@ -0,0 +1,62 @@ +import { FETCH_OPTIONS, TMDB_MOVIE_DETAIL_URL } from "./constant.js"; +import { generateRenderedMovieItemsHTML } from "./movies.js"; + +export const fetchMovieItemDetail = async (id) => { + const url = TMDB_MOVIE_DETAIL_URL + id; + const params = new URLSearchParams({ + language: "ko-KR", + }); + const response = await fetch(url + "?" + params, FETCH_OPTIONS); + + return await response.json(); +}; + +export const generateRenderedModalHTML = (movieItems, movieDetail) => { + const moviesPageTemplate = generateRenderedMovieItemsHTML( + movieItems, + "nowPlaying" + ); + + return moviesPageTemplate.replace( + "", + /*html*/ ` + + + + ` + ); +}; From 75cd730d3956c65f27628c3986f27262482e60c2 Mon Sep 17 00:00:00 2001 From: simhorim Date: Thu, 3 Oct 2024 22:53:11 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat(index):=20=EC=9E=90=EC=84=B8=ED=9E=88?= =?UTF-8?q?=20=EB=B3=B4=EA=B8=B0=20=ED=81=B4=EB=A6=AD=EC=8B=9C=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=EC=B0=BD=20=EC=BC=9C=EC=A7=80=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ssr/views/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ssr/views/index.html b/ssr/views/index.html index 2576277..afeb44b 100644 --- a/ssr/views/index.html +++ b/ssr/views/index.html @@ -29,7 +29,9 @@

    ${bestMovie.rate}

${bestMovie.title}
- +