From 22d0448e62de5e75569e030856323e724de7c842 Mon Sep 17 00:00:00 2001 From: 00kang <70834044+00kang@users.noreply.github.com> Date: Thu, 4 Apr 2024 17:37:36 +0900 Subject: [PATCH] =?UTF-8?q?[2=EB=8B=A8=EA=B3=84=20-=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=20=EC=A0=95=EB=B3=B4=20&=20UI/UX=20=EA=B0=9C=EC=84=A0=ED=95=98?= =?UTF-8?q?=EA=B8=B0]=20=EC=B4=88=EC=BD=94(=EA=B0=95=EB=8B=A4=EB=B9=88)=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A0=9C=EC=B6=9C=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.=20(#171)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: eslint와 prettier 기본 세팅 * feat: eslint, prettier 패키지 설치 * feat: eslint error를 warn으로 설정 변경 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * chore: ts-eslint parse 설정 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * feat: image 소스 파일 추가 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * feat : css - common.css, reset.css 추가 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * feat: index.html 템플릿 설정 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * docs: 기능 요구 사항 정리 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * feat: mockingData 설정 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * feat: MovieCard 컴포넌트 구현 - mockingData 사용 - template을 컴포넌트화 Co-Authored-By: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> * chore: eslint - browser env : true로 변경 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: mockingData 20개로 업데이트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * chore: webpack-dev-server - 설정 및 이미지 파일 경로 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * refactor: MovieCard 메서드 분리 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: index.js에 css import Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: MoreButton 컴포넌트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: API에서 받아온 데이터 렌더링 mocking 데이터 제거 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: MovieCard 영화 데이터 주입 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: 더보기 버튼 클릭 시, 다음 페이지 영화 렌더링 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: 영화 검색 기능 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: skeleton UI 적용 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * feat: 영화 검색 기능 추가, page가 더 있을 때에만 더보기 버튼 렌더링 * feat: 검색 결과가 없을때, UI 표시 * feat: 현재 영화 리스트에 따른 리스트 Title 변경 * feat: 응답에 따른 에러 처리 * fix: 검색어 입력 후 Enter 누를 시, 두번 event가 발생하는 버그 수정 * fix: 검색어 입력마다 presentPage count 리셋 검색 -> 더보기 버튼 클릭 -> 다시 검색 시, presentPage count가 유지되는 버그 수정 * fix: skeleton li element가 완전히 제거되지 않는 버그 수정 * feat: 검색 후 home으로 돌아올 시, 기존 가져온 인기 영화 render * style: 영화 평점 css * chore: cypress 설정 * chore: gitignore - dist,, env 추가 * chore: tsconfig 옵션 추가 * test: 인기순 영화 페이지 E2E 테스트 * chore: gitignore에 cypress.env.json 추가 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * test: TMDB에서 인기순 영화 GET요청 API 테스트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * test: TMDB에서 영화 검색 GET요청 API 테스트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * test: Fixture를 이용한 인기순 영화 목록 테스트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * test: Fixture를 이용한 영화 검색 결과 렌더링 테스트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * test: fixture - search 데이터 업데이트 Co-Authored-By: 00kang <70834044+00kang@users.noreply.github.com> * chore: output Path 수정 * refactor: image 디렉토리 위치 변 * refactor: css 디렉토리 위칭 이동 및 css variables 생성 * refactor: 매직넘버 상수화 * refactor: ErrorRender로 클래스명 수정 * refactor: SearchBox 컴포넌트 내 함수 이름 변경 및 메서드 분리 - onClick- > searchBoxElement - #addFormEvent -> #addFormEvent + #handleSubmit * refactor: MovieStore와 SearchMovieStore에서 API 호출 로직 분리 * refactor: DocumentFragement 사용으로 DOM 접근 줄이기 * refactor: early return으로 depth 줄이기 * refactor: #genereateMovieList와 #generateSearchMovieList의 중복 코드 메서드 분리 * refctor: 헤더 고정, 포스터 이미지 없는 데이터 이미지 삽입 * refactor: 검색결과에 검색어(해리)가 포함되어 있는지 test 코드 추가 * feat: deploy 디렉토리에 css와 png 추가 * chore: eslint, package, tsconfig 설정 * docs: 구현 기능 목록 작성 * feat: 스켈레톤의 태그 제거 * feat: 임의 데이터를 활용한 모달창 오픈 * feat: 모달 클로즈 기능 구현 - 무비카드 클릭 이벤트 메서드 분리 - 모달 인스턴스 공유 메서드 생성 * feat: movieDetail API로부터 데이터 받아와서 모달에 보여주기 * fix: 이미지 영역 고정 - 이미지가 다 로드되기 전에는 컨텐츠 영역이 이미지 영역을 침범하는 문제 해결 * fix: 모달 내 텍스트 영역 조정 - overview 데이터가 길 경우를 대비해 크기 지정 및 스크롤 기능 추가 * fix: 모달 클로즈 오류 비동기 키워드 사용으로 해결 - 비동기 작업이 완료되기 전에 그 결과를 사용하려고 시도하는 경우 * feat: 클릭한 무비카드에 맞는 데이터 모달에 띄우기 * feat: API 요청 메서드 분리 * feat: 더보기 버튼 대신 무한 스크롤 기능 구현 - 그런데 안됨!! * refactor: 데이터 로드시 스켈레톤 ui 확인을 위한 딜레이 메서드 삭제 * feat: 모달 내 별점 0으로 세팅 * feat: 모달 내 별점 클릭 이벤트 구현 - 클릭한 지점까지 'star_filled.png'로 채우기 * feat: 모달 내 평점 소수점 2자리까지 표현 * feat: tablet size 반응형 디자인 적용 * feat: tablet size 일 때 스켈레톤 ui 6개로 변경 * feat: mobile size일 때 그리드 조절 * feat: mobile size일 때 스켈레톤 4개로 조정 * feat: mobile size일 때 모달 사이즈 수정 * feat: npm run build * feat: 스크립트 추가 후 npm run build * feat: npm run build * feat: npm run build * feat: import문 삽입 * refactor: mobile, tablet 사이즈 기준 상수화 * refactor: let 연산자 삭제 * refactor: moviesData의 타입 명확히 Movie[]로 지정 * feat: 무한 스크롤 구현! * refactor: 반응형 디자인 수정 - 레이아웃 기준 재설정 - 헤더 넘침으로 인한 x축 스크롤 이벤트 해결 * feat: 모달 내 별점 localstorage에 반영 및 localstorage에 저장된 결과 보여주기 * feat: ESC key 로 모달 클로즈 * docs: 업데이트 * feat: 영화 포스터와 검색창 hover시 border 디자인 * feat: 최상단으로 이동하는 버튼 * refactor: 모달 디테일 수정 - overview가 없을 시 문구 삽입 - 모달이 오픈되었을 때 백그라운드 스크롤 금지 - 평점의 별 이미지와 텍스트 정렬 - 모달 내 별점 컨테이너의 요소 위치 고정 * fix: 모달 오픈시 무비리스트의 스크롤이 최상단으로 가는 문제 해결 * refactor: store 코드 메서드 분리 * fix: 없는 데이터에 forEach() 를 사용하는 문제 * refactor: response 반환 * refactor: 메서드 분리 * refactor: return new Error * refactor: 스크립트 파일 제거 * fix: 초기 세팅 시 별 이미지 안 뜨는 문제 * refactor: movieCard 클래스 메서드 분리 * refactor: Modal 클래스 메서드 분리 * refactor: Modal 클래스 분리 : Modal, MovieInfo, VoteHandler * feat: 모달에 skeleton UI 추가 * refactor: 반응형 디자인 수정 및 모달 스켈레톤 UI 적용 --------- Co-authored-by: jayming66 Co-authored-by: MYONG JAEWI <78201530+jaymyong66@users.noreply.github.com> --- .eslintrc | 3 + .gitignore | 1 - deploy/images/modal_close_button.png | Bin 0 -> 856 bytes dist/06f0f15cfcb8d681b62c.png | Bin 0 -> 88197 bytes dist/2e162b4fefb34cd7ed8d.png | Bin 0 -> 1839 bytes dist/6328741810b732410eec.png | Bin 0 -> 412 bytes dist/6c9611deedf4b85849c9.png | Bin 0 -> 444 bytes dist/bundle.js | 484 +++++++++++++++++++++++++++ dist/e9a379619c759f886f7c.png | Bin 0 -> 856 bytes dist/f1bd4269f4446ceae306.png | Bin 0 -> 1014 bytes dist/index.html | 26 ++ docs/REQUIREMENTS.md | 24 +- index.html | 7 +- src/App.ts | 182 +++++++--- src/components/ErrorRender.ts | 1 + src/components/Modal.ts | 107 ++++++ src/components/MovieCard.ts | 59 ++-- src/components/MovieInfo.ts | 108 ++++++ src/components/VoteHandler.ts | 83 +++++ src/constants.ts | 16 +- src/css/common.css | 192 ++++++++++- src/css/modal.css | 365 ++++++++++++++++++++ src/css/theme.css | 36 +- src/custom.d.ts | 5 + src/images/modal_close_button.png | Bin 0 -> 856 bytes src/index.d.ts | 8 + src/index.js | 2 + src/store/API.ts | 28 ++ src/store/MovieStore.ts | 41 +-- src/store/SearchMovieStore.ts | 39 +-- 30 files changed, 1682 insertions(+), 135 deletions(-) create mode 100644 deploy/images/modal_close_button.png create mode 100644 dist/06f0f15cfcb8d681b62c.png create mode 100644 dist/2e162b4fefb34cd7ed8d.png create mode 100644 dist/6328741810b732410eec.png create mode 100644 dist/6c9611deedf4b85849c9.png create mode 100644 dist/bundle.js create mode 100644 dist/e9a379619c759f886f7c.png create mode 100644 dist/f1bd4269f4446ceae306.png create mode 100644 dist/index.html create mode 100644 src/components/Modal.ts create mode 100644 src/components/MovieInfo.ts create mode 100644 src/components/VoteHandler.ts create mode 100644 src/css/modal.css create mode 100644 src/custom.d.ts create mode 100644 src/images/modal_close_button.png create mode 100644 src/store/API.ts diff --git a/.eslintrc b/.eslintrc index fa2cf7f0a..9b03fcda7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -12,6 +12,9 @@ "no-promise-executor-return": "off", "consistent-return": "off", "no-return-await": "off", + "no-plusplus": "off", + "camelcase": "off", + "object-curly-newline": "off", }, "env": { "es6": true, diff --git a/.gitignore b/.gitignore index c7164714d..1f8de325b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules -dist .env cypress.env.json \ No newline at end of file diff --git a/deploy/images/modal_close_button.png b/deploy/images/modal_close_button.png new file mode 100644 index 0000000000000000000000000000000000000000..cbe1b680fd019bc5518f80aac9e818474e2530f9 GIT binary patch literal 856 zcmV-e1E>6nP)L`#><{y}pu3{;clFoMLNRAZBRIz_S(o+~W_R--~ zsmNKPFjYup(QtX^jw2UxAG>!L`z>HOW|xPV+1U?4imKIWW!tu22_dRP!mw@13PD-^ z4()L!L)LUUweax_Hs4Isv{c3yvW5U@;cbf{NI`(@;}5g}b}VHdX8;fbW?#@OQ#x7j z;Xxc&D3DmnR%y0F);OdokpV(4F&^JfvHp~l*>J$^Ye=^(`=zoxEc)XpCTqEq>M9X-2xSYWq9dC z%jfegEP^lNtYx7R!Z^aLyV6Rf(tEU@%5;c>N&~~fLVT?ii=}sH=VUvDL2=@yftev? z#m2_wFK<7iqNwSd494A0!9&GEN}xqgrG;U^F>4vRXTmHi?l2iCDlBBG#nUe@WZP&f zxOZ{0 zu&``7clMMK3kzR5^luaRf~8)dY!Lhrw>xX3&%zQc!NL-8i-m;Kid23)^2ywvk`LB;oE*kb*_BAcD!WnS6N5)p3T#eC+#*n zHJ2q>2{t%xdrXXf(FY_g)L^$a-|zKdtSdO za&h1JLkB$hkRByHxKs8oc%2K2w9a`-TL&rz;KY7Thqt^tA{Vx5dHBzJosZw?@7VqB!$DrvOKK(Y8dUi!anG~&T`um^=glBe zJ>Zh3UwbaATkh?e{-#mp<4@=k2xoo9-LMfkAuA1HaoShse-Ll$gN*sNen1P&x!UJ3^tfjK9dcVb7*h zR27|gmb*9A5y`P_i)L411e6IcQEa7}g!#DN! zGOyiDvZakGDUX}qTYXdZAAND)1ZU<0S%U*JDY#}&(>lXACB;o5S9&7v|G6`ALexMw zP%Fyb>|tcC9`0_QzVO+7DPC2U`<}Ph5@NFxsH$Ns>`@vHYNzoxLH=3(Potf^eC;5k z!;H;6s^xe{T~hw+mHTVzoKxAmhcx^V_kDZ2-5+sm+G@Q0$fMX$>YC!}Z{r(}yS3ZR zH|?nlY5lFnslny>Rf?lVtKKn$`?7n%b&nTO$?qIw3q#IpZFT9i5Pc|lZ_}kdce_VU zp#^d8{94VlJQZsApH*q^aNE~nxao0hY-C~f;dmY`?p->uFP#e->ly`PcB8bCY}4IN zTx*gKF&%#`XpSC^+8P~rD{~Xcy!m9}+jdd2F`e&!&Ut6lH5$#14gL%`gO+u<7$GQh zED6Ul?R((S!m0Y`s{(uX>SjqN*ztJX$PeB4$+)ELiC31DA-9G%tJUpsy=$H%`7Is$ z3@)ZVp87L#Q7BdMQe3S>-_zfE^K9J3_}?R!V&i^yXXFPyk6v2U|Fa-mvVEQdH9#41 zU+uRM5BnTlt|?Qt8~$XCb>&UnL67tUAOSW6|4*U=-Mt{5JFb{NekI4V)+M#P$);z! zNOZ(%@_TassAv6t_Q!HxZC$$dAGg0|Zd8euYZ4|8vVA79{8}kU=O)ns@*KoFSoDI$74TxUL7pOl_k>2>?1N=>EIm)K#w z*U!a-^SC=hjvV_^9wIzKX@D)J^n&R@u!Q9@xbeCi;-;NXDW*ZwSHp4Dz>9swVqbz zSQ}P^p-K!B%)c1t{U$h^+MU#j+pSI5rZu(47baVeJ<10|mfj4)JL8%k$(N_JehJX4 z6yqhZR=k4cgnp7wm^tlQ6MW!{%9n(!OmpoxU(4`PS4*NBI{5}KHAE-K{#T~|kw;Nm zMGf)7iPZRsh?ldUr|sKsoX-q&L3SY`+vARXZhf0m@-zav#pZLuh4guvyB`(+BYIVttZ|YZIC>((>_H^I{Sh_ELOHN+iHIxzPS}l-Yn-%XI1D5|d03GAMJot|TXn_1L5B}rezdZP_ zKKQRj`mav>uRQ*5I{dFBpglMKR~G$O7X4Qi{Z|(KR~G$O7XAMzi!L1tUGXdG^Uxq8 zSzw#M4yIv`x!90@c0nNTnx-ZvOT_!Z#g%#&PxbosTn2woNz!7X*xR;ZK8NXi!v zvI*-pE?QgIwK5oWqV~Q_#s(@4DXJ|86AeccSCF^1cEKnT5iyYRvoZn_u?bUWtyV9( zavn14(BLAWaJE7uJ>F@8*c^#w_hn&uJGQmb+SHP|x~bgf4)2;SB)4mjh%Ty|>NQ1b zmumP9A7%xswUf%rNP;C5y$$-t8k%@7c}>EH;zr8M%ZF|arsm%0islWKfV?=6MOo~K zj{d$>XT6lM!J1}tvnLs2jXlY!K{GgimWZZuVSo*?kPQbX>nMw!yv;y*miBoDMOmDU zgFgR5Z!6Fqy5$=-QAP92f!vIs%veG`C_$D8;O(fZrt4_akTx27JUqPoXg=>zr+xC(r>+t( zfYCh)(C1u3Adbu*JU8+15u|Q%AaMRVJ}ZNQ6%W#s7}X%aeN{ z0xYsm(Fm}E1rrXYoIFbV?v*`twWzBk0CzIlo@VKV3_x1jYI{*8AYvOJVwk&zh_0N} z5cvWBVs*gFfTs2iKmmiY?o!%=W2!_Uio7CUkTJ+lt3NC!9>zje3B3na8E87Fz{>xtEfW!_VNkK?Z z=+Ei`Bxr=tGy+Iw5Yhq&6FWru!zTbr7=ro$pfYGsz~#HAAt=z-H22et0tUZ?3_g1X zKtWwc^C*Byq(QX+D2Vxo_W;yE2+9qz3d)ezF98%Z#)^vqs8cknASh^@IC~O6B|%Wz z0aP~)3UUw%-NTyzN*RKZhODANr30u75Y!d`We-8!13o8ihNNoR5WEc#S5@DD)8kq| z%w`p6DnP->cLVrI5T#}($e1c=$VcfH6dxNIsLdUKW;sq89Pm4FHw_N3(*O}xr47O9 zKyW1x9K=|@9s~#RYIX>~eW1aCq148M1_!v7lcd1`-xHxZBBBN`)BurI^$j>behz{Q zg5V(5@}(g-h+DH=kadu+(y;(8mj(y;mODd(1O6wf(%=9~4G?iv+7O&R1PAp=1&FzP z9taNN*Nhvojs_P6;BYiJz`2|g1os(mXT}Y|^#JaqY1}mcXP?u!qX4+g5O;E(0PZ%# zU7{+0+Y33{0C6V;!8ro%@@cvD8E|K|iv|a{lcsT}2f@*}tAOAj?&J(0IEcGM(8H=; z(%>NOoM~`?yL?){eFof_9iqVj?xbnlH2`Oy)3^(V;2`egWFa_+yTsj)b&#_S5O?or zaDcmfTF!k2+?k!A!2#~1Y24{Sa5U~TAUKFSIX(yu;x2JBWE~9-;torL1Kj1)@-727 z_6g!-6Y&2bt&4gAO%X`yH(+x=#N1Y>k8(k6P5^u<$kSVZ^B=T6ss>VcBNT=`5ER76 zCgA%+S|2q8P!=>Oz~p|2wXIMe-3dXx1yJv3P=N0rv_2{gpd=uu4B*fwh>K0YZ`$;x zDF>iZXi$K~{SaeYp*|`FL0yNef;_whxc))wqapz6G|egq3gTfC@cALFk8TA}{WK`R z;C_g$txz9TfuIgTR?(mU&p&8=lm|dLLQwj^L1l=m>tKkC07m=@hiL8tK(xB)I&ip()^Qbq zUMNIaGsuDnKFHn|z}`8U3kpDf5Q6A`25!#Mu2R7jf_9YzeFrt!kA%LXT_u1kPug7& z%m`1~cmGTGHn=-PlY0QJXlC}uK;O|c;=vV+b~hSaS<|jS7$U4`cmId(r8mGuHHf_q zK+y^`uWC8~{130qtz@OAgszr zNbCR*lcAwO#(k!tL1MIWrvQi*(?TT(iP6v?zZM}e0jSXvP@^@V(c%;c%@&B|($La? z*gZ(>DI|6X5_25QZSdKwzks3HvwY80A5HTM894;oq=5X+{aL1MHd ze*=lpdfYZhjD~g}h)qFa{a~im+zFv6fnMlE%cR|)`Ge4yHtY{6K#A)G#tIf48u{me z0xL}cbPz-6*`lfuq)V7SsX=-Q2eYh~e;C2ME2Na&)ro0F|N_`jNUiv5oAN&B@UpBfqxI1y5MuiqTa zuNlU6Vt;dRI*WLsM+Z_cW^@^8>JoA@km)sW>b!3QbV^f zo01M55jQt8oALk)x4y+}%5^>J>fSHRiL)D+^5!p7S`ZZn|1u>OnBvTAiX$-P>|dt5 zq=sJn%aonKl-9pYnSfhA{mT^a1ox8Jl&UabZ6>owu>u)$ubml%0DO*NZfF<>Y%yfE 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%0Dxfzi@>$q{dOdDVhXe?Eat{qtWaXtaUkC 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 literal 0 HcmV?d00001 diff --git a/dist/6328741810b732410eec.png b/dist/6328741810b732410eec.png new file mode 100644 index 0000000000000000000000000000000000000000..a17bed7c64f258786ffb703ec457842e35dd3b1e GIT binary patch literal 412 zcmV;N0b~A&P)X1^@s6D=Y3@00009a7bBm000Gv z000Gv0c~iV`Tzg`0drDELIAGL9O(c600d`2O+f$vv5yPWGmE0sZ!Q2E+l8T{qPJlQ8RCFNzYU~-uUQO1<9eIscqusyS zl_dfHitvJ6c*Sl?jI%mYxZvll9hUA6-V(Qhm4Lc8dVmpA1%uUhn5wW2sQxzvG zNUXl&WEE~C_Jf>e#hHrr-Eh32ohRZw=NkIFNBf)h6&kn3=O_WiWt9b%!Lzbb4EtX+ zlYW9NH?zUtIYh0N<2~53*B98w{?8T9uu=D5fg~ewHNngzp5p7FxS(#b+tSgEos$F{ zH1TADHYkS`huid&rY$YX@PR30xHh+l&U)`d6!7ZYmwrfB386|6e#B)wopN5Dm8fb; zf`0#>M3_gvmKMn6=I-OGRt^#sup*ZppU1krNf+}yqw))7KVLeJzVC+s0000P000>X1^@s6#OZ}&00009a7bBm000Gv z000Gv0c~iV`Tzg`0drDELIAGL9O(c600d`2O+f$vv5yP>AShglM!PRaNnB6FLuM zp699RxSX!l_!B`&9`V(5BEYd@F0BX`5cxbwhy}p0SssSH(}kkNVHkd(pc$ { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "./node_modules/css-loader/dist/cjs.js!./src/css/common.css": +/*!******************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./src/css/common.css ***! + \******************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/getUrl.js */ \"./node_modules/css-loader/dist/runtime/getUrl.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__);\n// Imports\n\n\n\nvar ___CSS_LOADER_URL_IMPORT_0___ = new URL(/* asset import */ __webpack_require__(/*! ../images/search_button.png */ \"./src/images/search_button.png\"), __webpack_require__.b);\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\nvar ___CSS_LOADER_URL_REPLACEMENT_0___ = _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default()(___CSS_LOADER_URL_IMPORT_0___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"* {\\r\\n box-sizing: border-box !important;\\r\\n}\\r\\n\\r\\nbody {\\r\\n position: relative;\\r\\n\\r\\n background-color: var(--black);\\r\\n\\r\\n font-family: Roboto;\\r\\n font-size: 14px;\\r\\n color: var(--white);\\r\\n}\\r\\n\\r\\na {\\r\\n color: inherit;\\r\\n text-decoration: none;\\r\\n}\\r\\n\\r\\nbutton {\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n#app {\\r\\n margin-top: 150px;\\r\\n padding-bottom: 48px;\\r\\n}\\r\\n\\r\\n*:focus {\\r\\n outline: none;\\r\\n}\\r\\n.item-view,\\r\\n.item-test {\\r\\n width: 100%;\\r\\n}\\r\\n\\r\\n.item-view {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: center;\\r\\n max-width: 1200px;\\r\\n margin: 0 auto;\\r\\n}\\r\\n\\r\\n.item-view h2 {\\r\\n font-size: 2rem;\\r\\n font-weight: bold;\\r\\n user-select: none;\\r\\n}\\r\\n\\r\\n/* https://andrew.hedges.name/experiments/aspect_ratio/ */\\r\\n\\r\\n.item-list {\\r\\n display: grid;\\r\\n margin: 48px 0;\\r\\n grid-template-columns: repeat(4, 180px);\\r\\n grid-column-gap: 160px;\\r\\n grid-row-gap: 48px;\\r\\n}\\r\\n\\r\\n.item-card {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n}\\r\\n\\r\\n.item-thumbnail {\\r\\n border-radius: 8px;\\r\\n width: 180px;\\r\\n height: 270px;\\r\\n background-size: contain;\\r\\n}\\r\\n\\r\\n.item-title {\\r\\n margin-top: 16px;\\r\\n font-size: 1.2rem;\\r\\n font-weight: bold;\\r\\n}\\r\\n\\r\\n.item-score {\\r\\n margin-top: 16px;\\r\\n font-size: 1.2rem;\\r\\n display: inline-block;\\r\\n vertical-align: middle;\\r\\n}\\r\\n\\r\\n.item-score::after {\\r\\n margin-left: 8px;\\r\\n}\\r\\n\\r\\n.item-title.skeleton::after,\\r\\n.item-score.skeleton::after {\\r\\n font-size: 0;\\r\\n content: 'loading';\\r\\n}\\r\\n\\r\\n.full-width {\\r\\n width: 100%;\\r\\n}\\r\\n\\r\\n.last-item {\\r\\n margin-top: 48px;\\r\\n}\\r\\n\\r\\nbutton.btn {\\r\\n border: 0;\\r\\n border-radius: 8px;\\r\\n height: 30px;\\r\\n color: var(--white);\\r\\n}\\r\\n\\r\\nbutton.primary {\\r\\n background: var(--red);\\r\\n}\\r\\n\\r\\n.item-card .skeleton {\\r\\n background: linear-gradient(-90deg, var(--gray), var(--light-gray), var(--gray), var(--light-gray));\\r\\n background-size: 400%;\\r\\n animation: skeleton-animation 5s infinite ease-out;\\r\\n border-radius: 8px;\\r\\n}\\r\\n\\r\\n@keyframes skeleton-animation {\\r\\n 0% {\\r\\n background-position: 0% 50%;\\r\\n }\\r\\n 50% {\\r\\n background-position: 100% 50%;\\r\\n }\\r\\n 100% {\\r\\n background-position: 0% 50%;\\r\\n }\\r\\n}\\r\\n\\r\\nheader {\\r\\n width: 100%;\\r\\n min-width: 1200px;\\r\\n height: 72px;\\r\\n background-color: var(--black);\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n padding: 0 20px;\\r\\n border-bottom: 1px solid var(--white);\\r\\n margin-bottom: 48px;\\r\\n\\r\\n position: fixed;\\r\\n top: 0;\\r\\n left: 0;\\r\\n z-index: 10;\\r\\n}\\r\\n\\r\\nheader h1 {\\r\\n cursor: pointer;\\r\\n user-select: none;\\r\\n font-size: 2rem;\\r\\n font-weight: bold;\\r\\n letter-spacing: -0.1rem;\\r\\n color: var(--red);\\r\\n}\\r\\n\\r\\n#home-button {\\r\\n background-color: transparent;\\r\\n border: none;\\r\\n}\\r\\n\\r\\nheader > .search-box {\\r\\n background: var(--white);\\r\\n padding: 8px;\\r\\n border-radius: 4px;\\r\\n}\\r\\n\\r\\nheader .search-box > input {\\r\\n border: 0;\\r\\n}\\r\\n\\r\\nheader .search-box > .search-button {\\r\\n width: 14px;\\r\\n border: 0;\\r\\n text-indent: -1000rem;\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \") transparent no-repeat 0 1px;\\r\\n background-size: contain;\\r\\n}\\r\\n\\r\\n@media only screen and (max-width: 834px) {\\r\\n .item-view {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: center;\\r\\n max-width: 674px;\\r\\n margin: 0 auto;\\r\\n }\\r\\n\\r\\n .item-list {\\r\\n display: grid;\\r\\n margin: 36px 0;\\r\\n grid-template-columns: repeat(3, 180px);\\r\\n grid-column-gap: 64px;\\r\\n grid-row-gap: 55px;\\r\\n }\\r\\n\\r\\n header {\\r\\n min-width: 674px;\\r\\n }\\r\\n}\\r\\n\\r\\n@media only screen and (max-width: 390px) {\\r\\n .item-view {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: center;\\r\\n max-width: 316px;\\r\\n margin: 0 auto;\\r\\n }\\r\\n\\r\\n .item-list {\\r\\n display: grid;\\r\\n margin: 24px 0;\\r\\n grid-template-columns: repeat(2, 140px);\\r\\n grid-column-gap: 36px;\\r\\n grid-row-gap: 32px;\\r\\n }\\r\\n\\r\\n .item-thumbnail {\\r\\n border-radius: 15px;\\r\\n width: 140px;\\r\\n height: 220px;\\r\\n background-size: contain;\\r\\n }\\r\\n}\\r\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/common.css?./node_modules/css-loader/dist/cjs.js"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js!./src/css/modal.css": +/*!*****************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./src/css/modal.css ***! + \*****************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/getUrl.js */ \"./node_modules/css-loader/dist/runtime/getUrl.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__);\n// Imports\n\n\n\nvar ___CSS_LOADER_URL_IMPORT_0___ = new URL(/* asset import */ __webpack_require__(/*! ../images/modal_close_button.png */ \"./src/images/modal_close_button.png\"), __webpack_require__.b);\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\nvar ___CSS_LOADER_URL_REPLACEMENT_0___ = _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default()(___CSS_LOADER_URL_IMPORT_0___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".modal {\\r\\n display: none;\\r\\n position: absolute;\\r\\n top: 0;\\r\\n left: 0;\\r\\n}\\r\\n\\r\\n.modal--open {\\r\\n display: block;\\r\\n}\\r\\n\\r\\n.modal-backdrop {\\r\\n position: fixed;\\r\\n top: 0;\\r\\n right: 0;\\r\\n bottom: 0;\\r\\n left: 0;\\r\\n\\r\\n background: rgba(0, 0, 0, 0.6);\\r\\n\\r\\n z-index: 100;\\r\\n}\\r\\n\\r\\n.modal-container {\\r\\n position: fixed;\\r\\n top: 50%;\\r\\n left: 50%;\\r\\n transform: translate(-50%, -50%);\\r\\n gap: 0px;\\r\\n width: 740px;\\r\\n height: 544px;\\r\\n\\r\\n border-radius: 8px;\\r\\n background-color: rgba(33, 33, 34, 1);\\r\\n\\r\\n z-index: 200;\\r\\n}\\r\\n\\r\\n.modal-header {\\r\\n display: flex;\\r\\n justify-content: center;\\r\\n align-items: center;\\r\\n width: 740px;\\r\\n height: 60px;\\r\\n\\r\\n border-bottom: 1px solid rgba(241, 241, 241, 0.25);\\r\\n}\\r\\n\\r\\n.detail-title {\\r\\n top: 18px;\\r\\n left: 32px;\\r\\n gap: 0px;\\r\\n\\r\\n width: 676px;\\r\\n height: 24px;\\r\\n}\\r\\n\\r\\n.modal-close-button {\\r\\n width: 36px;\\r\\n height: 36px;\\r\\n\\r\\n border: none;\\r\\n background-color: transparent;\\r\\n background-image: url(\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \");\\r\\n}\\r\\n\\r\\n.modal-body {\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n padding: 40px 32px;\\r\\n gap: 32px;\\r\\n\\r\\n width: 740px;\\r\\n height: 484px;\\r\\n}\\r\\n\\r\\n.detail-poster {\\r\\n position: fixed;\\r\\n top: 96px;\\r\\n left: 32px;\\r\\n gap: 0px;\\r\\n\\r\\n width: 260px;\\r\\n height: 400px;\\r\\n}\\r\\n\\r\\n.modal-contents {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n position: fixed;\\r\\n top: 96px;\\r\\n left: 324px;\\r\\n\\r\\n width: 385px;\\r\\n height: 400px;\\r\\n}\\r\\n\\r\\n.detail-text-container {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n gap: 16px;\\r\\n margin-bottom: auto;\\r\\n margin-top: 0;\\r\\n}\\r\\n\\r\\n.detail-text-top {\\r\\n display: flex;\\r\\n align-items: flex-start;\\r\\n gap: 16px;\\r\\n\\r\\n width: 100%;\\r\\n}\\r\\n\\r\\n.detail-genres {\\r\\n}\\r\\n\\r\\n.detail-vote_average {\\r\\n}\\r\\n\\r\\n.detail-overview {\\r\\n max-height: 280px;\\r\\n overflow-y: auto;\\r\\n}\\r\\n\\r\\n.my-vote {\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n padding: 0 18px;\\r\\n margin-top: auto;\\r\\n margin-bottom: 0;\\r\\n\\r\\n width: 384px;\\r\\n height: 64px;\\r\\n\\r\\n border-radius: 16px;\\r\\n background-color: rgba(56, 56, 57, 1);\\r\\n}\\r\\n\\r\\n.my-vote-title {\\r\\n margin-right: 10px;\\r\\n}\\r\\n\\r\\n.my-vote-body {\\r\\n display: flex;\\r\\n gap: 0;\\r\\n margin-right: 10px;\\r\\n\\r\\n width: 160px;\\r\\n}\\r\\n\\r\\n.my-vote-body button {\\r\\n padding: 0;\\r\\n\\r\\n border: none;\\r\\n background-color: transparent;\\r\\n}\\r\\n\\r\\n.my-vote-body img {\\r\\n width: 32px;\\r\\n height: 32px;\\r\\n}\\r\\n\\r\\n.my-vote-number {\\r\\n margin-right: 10px;\\r\\n}\\r\\n\\r\\n.my-vote-description {\\r\\n}\\r\\n\\r\\n@media only screen and (max-width: 390px) {\\r\\n .modal-container {\\r\\n position: fixed;\\r\\n top: auto;\\r\\n bottom: 0;\\r\\n left: 50%;\\r\\n transform: translateX(-50%);\\r\\n gap: 0px;\\r\\n width: 390px;\\r\\n height: 485px;\\r\\n border-radius: 8px;\\r\\n background-color: rgba(33, 33, 34, 1);\\r\\n z-index: 200;\\r\\n }\\r\\n\\r\\n .modal-header {\\r\\n display: flex;\\r\\n justify-content: center;\\r\\n align-items: center;\\r\\n width: 390px;\\r\\n height: 60px;\\r\\n\\r\\n border-bottom: 1px solid rgba(241, 241, 241, 0.25);\\r\\n }\\r\\n\\r\\n .detail-title {\\r\\n top: 18px;\\r\\n left: 32px;\\r\\n gap: 0px;\\r\\n\\r\\n width: 330px;\\r\\n height: 24px;\\r\\n }\\r\\n\\r\\n .modal-close-button {\\r\\n width: 36px;\\r\\n height: 36px;\\r\\n\\r\\n border: none;\\r\\n background-color: transparent;\\r\\n background-image: url(\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \");\\r\\n }\\r\\n\\r\\n .modal-body {\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n padding: 40px 32px;\\r\\n gap: 0px;\\r\\n\\r\\n width: 326px;\\r\\n height: 232px;\\r\\n }\\r\\n\\r\\n .detail-poster {\\r\\n display: none;\\r\\n width: 0px;\\r\\n height: 0px;\\r\\n }\\r\\n\\r\\n .modal-contents {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n margin-bottom: 36px;\\r\\n position: fixed;\\r\\n top: 92px;\\r\\n left: 32px;\\r\\n\\r\\n width: 326px;\\r\\n height: 232px;\\r\\n }\\r\\n\\r\\n .detail-text-container {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n gap: 16px;\\r\\n margin-bottom: 16px;\\r\\n margin-top: 0;\\r\\n }\\r\\n\\r\\n .detail-text-top {\\r\\n display: flex;\\r\\n align-items: flex-start;\\r\\n gap: 16px;\\r\\n\\r\\n width: 100%;\\r\\n }\\r\\n\\r\\n .detail-genres {\\r\\n }\\r\\n\\r\\n .detail-vote_average {\\r\\n }\\r\\n\\r\\n .detail-overview {\\r\\n max-height: 240px;\\r\\n overflow-y: auto;\\r\\n }\\r\\n\\r\\n .my-vote {\\r\\n display: flex;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n padding: 0 18px;\\r\\n margin-top: auto;\\r\\n margin-bottom: 0;\\r\\n\\r\\n width: 326px;\\r\\n height: 64px;\\r\\n\\r\\n border-radius: 12px;\\r\\n background-color: rgba(56, 56, 57, 1);\\r\\n }\\r\\n\\r\\n .my-vote-title {\\r\\n margin-right: 10px;\\r\\n }\\r\\n\\r\\n .my-vote-body {\\r\\n display: flex;\\r\\n gap: 0;\\r\\n margin-right: 10px;\\r\\n\\r\\n width: 160px;\\r\\n }\\r\\n\\r\\n .my-vote-body button {\\r\\n padding: 0;\\r\\n\\r\\n border: none;\\r\\n background-color: transparent;\\r\\n }\\r\\n\\r\\n .my-vote-body img {\\r\\n width: 32px;\\r\\n height: 32px;\\r\\n }\\r\\n\\r\\n .my-vote-number {\\r\\n margin-right: 10px;\\r\\n }\\r\\n\\r\\n .my-vote-description {\\r\\n display: none;\\r\\n }\\r\\n}\\r\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/modal.css?./node_modules/css-loader/dist/cjs.js"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js!./src/css/reset.css": +/*!*****************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./src/css/reset.css ***! + \*****************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"/* http://meyerweb.com/eric/tools/css/reset/\\r\\n v2.0 | 20110126\\r\\n License: none (public domain)\\r\\n*/\\r\\n\\r\\nhtml,\\r\\nbody,\\r\\ndiv,\\r\\nspan,\\r\\napplet,\\r\\nobject,\\r\\niframe,\\r\\nh1,\\r\\nh2,\\r\\nh3,\\r\\nh4,\\r\\nh5,\\r\\nh6,\\r\\np,\\r\\nblockquote,\\r\\npre,\\r\\na,\\r\\nabbr,\\r\\nacronym,\\r\\naddress,\\r\\nbig,\\r\\ncite,\\r\\ncode,\\r\\ndel,\\r\\ndfn,\\r\\nem,\\r\\nimg,\\r\\nins,\\r\\nkbd,\\r\\nq,\\r\\ns,\\r\\nsamp,\\r\\nsmall,\\r\\nstrike,\\r\\nstrong,\\r\\nsub,\\r\\nsup,\\r\\ntt,\\r\\nvar,\\r\\nb,\\r\\nu,\\r\\ni,\\r\\ncenter,\\r\\ndl,\\r\\ndt,\\r\\ndd,\\r\\nol,\\r\\nul,\\r\\nli,\\r\\nfieldset,\\r\\nform,\\r\\nlabel,\\r\\nlegend,\\r\\ntable,\\r\\ncaption,\\r\\ntbody,\\r\\ntfoot,\\r\\nthead,\\r\\ntr,\\r\\nth,\\r\\ntd,\\r\\narticle,\\r\\naside,\\r\\ncanvas,\\r\\ndetails,\\r\\nembed,\\r\\nfigure,\\r\\nfigcaption,\\r\\nfooter,\\r\\nheader,\\r\\nhgroup,\\r\\nmenu,\\r\\nnav,\\r\\noutput,\\r\\nruby,\\r\\nsection,\\r\\nsummary,\\r\\ntime,\\r\\nmark,\\r\\naudio,\\r\\nvideo {\\r\\n margin: 0;\\r\\n padding: 0;\\r\\n border: 0;\\r\\n font-size: 100%;\\r\\n font: inherit;\\r\\n vertical-align: baseline;\\r\\n}\\r\\n/* HTML5 display-role reset for older browsers */\\r\\narticle,\\r\\naside,\\r\\ndetails,\\r\\nfigcaption,\\r\\nfigure,\\r\\nfooter,\\r\\nheader,\\r\\nhgroup,\\r\\nmenu,\\r\\nnav,\\r\\nsection {\\r\\n display: block;\\r\\n}\\r\\nbody {\\r\\n line-height: 1;\\r\\n}\\r\\nol,\\r\\nul {\\r\\n list-style: none;\\r\\n}\\r\\nblockquote,\\r\\nq {\\r\\n quotes: none;\\r\\n}\\r\\nblockquote:before,\\r\\nblockquote:after,\\r\\nq:before,\\r\\nq:after {\\r\\n content: '';\\r\\n content: none;\\r\\n}\\r\\ntable {\\r\\n border-collapse: collapse;\\r\\n border-spacing: 0;\\r\\n}\\r\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/reset.css?./node_modules/css-loader/dist/cjs.js"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js!./src/css/theme.css": +/*!*****************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js!./src/css/theme.css ***! + \*****************************************************************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"/* Color ******************************************/\\r\\n:root {\\r\\n --white: #fff;\\r\\n --light-gray: #f0f0f0;\\r\\n --gray: #aaa;\\r\\n --black: #222;\\r\\n --red: #f33f3f;\\r\\n}\\r\\n\\r\\n/* Typography *************************************/\\r\\n.text-detail-title {\\r\\n font-size: 20px;\\r\\n font-weight: 600;\\r\\n line-height: 24px;\\r\\n letter-spacing: 0.15px;\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.text-detail-contents {\\r\\n font-size: 16px;\\r\\n font-weight: 400;\\r\\n line-height: 24px;\\r\\n letter-spacing: 0.5px;\\r\\n text-align: left;\\r\\n color: rgba(241, 241, 241, 1);\\r\\n}\\r\\n\\r\\n.text-detail-vote {\\r\\n font-size: 16px;\\r\\n font-weight: 700;\\r\\n line-height: 24px;\\r\\n letter-spacing: 0.5px;\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.text-detail-vote-contents {\\r\\n font-size: 16px;\\r\\n font-weight: 400;\\r\\n line-height: 24px;\\r\\n letter-spacing: 0.5px;\\r\\n text-align: center;\\r\\n}\\r\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/theme.css?./node_modules/css-loader/dist/cjs.js"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/api.js": +/*!*****************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/api.js ***! + \*****************************************************/ +/***/ ((module) => { + +eval("\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\nmodule.exports = function (cssWithMappingToString) {\n var list = [];\n\n // return the list of modules as css string\n list.toString = function toString() {\n return this.map(function (item) {\n var content = \"\";\n var needLayer = typeof item[5] !== \"undefined\";\n if (item[4]) {\n content += \"@supports (\".concat(item[4], \") {\");\n }\n if (item[2]) {\n content += \"@media \".concat(item[2], \" {\");\n }\n if (needLayer) {\n content += \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\");\n }\n content += cssWithMappingToString(item);\n if (needLayer) {\n content += \"}\";\n }\n if (item[2]) {\n content += \"}\";\n }\n if (item[4]) {\n content += \"}\";\n }\n return content;\n }).join(\"\");\n };\n\n // import a list of modules into the list\n list.i = function i(modules, media, dedupe, supports, layer) {\n if (typeof modules === \"string\") {\n modules = [[null, modules, undefined]];\n }\n var alreadyImportedModules = {};\n if (dedupe) {\n for (var k = 0; k < this.length; k++) {\n var id = this[k][0];\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n }\n for (var _k = 0; _k < modules.length; _k++) {\n var item = [].concat(modules[_k]);\n if (dedupe && alreadyImportedModules[item[0]]) {\n continue;\n }\n if (typeof layer !== \"undefined\") {\n if (typeof item[5] === \"undefined\") {\n item[5] = layer;\n } else {\n item[1] = \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\").concat(item[1], \"}\");\n item[5] = layer;\n }\n }\n if (media) {\n if (!item[2]) {\n item[2] = media;\n } else {\n item[1] = \"@media \".concat(item[2], \" {\").concat(item[1], \"}\");\n item[2] = media;\n }\n }\n if (supports) {\n if (!item[4]) {\n item[4] = \"\".concat(supports);\n } else {\n item[1] = \"@supports (\".concat(item[4], \") {\").concat(item[1], \"}\");\n item[4] = supports;\n }\n }\n list.push(item);\n }\n };\n return list;\n};\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/css-loader/dist/runtime/api.js?"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/getUrl.js": +/*!********************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/getUrl.js ***! + \********************************************************/ +/***/ ((module) => { + +eval("\n\nmodule.exports = function (url, options) {\n if (!options) {\n options = {};\n }\n if (!url) {\n return url;\n }\n url = String(url.__esModule ? url.default : url);\n\n // If url is already wrapped in quotes, remove them\n if (/^['\"].*['\"]$/.test(url)) {\n url = url.slice(1, -1);\n }\n if (options.hash) {\n url += options.hash;\n }\n\n // Should url be wrapped?\n // See https://drafts.csswg.org/css-values-3/#urls\n if (/[\"'() \\t\\n]|(%20)/.test(url) || options.needQuotes) {\n return \"\\\"\".concat(url.replace(/\"/g, '\\\\\"').replace(/\\n/g, \"\\\\n\"), \"\\\"\");\n }\n return url;\n};\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/css-loader/dist/runtime/getUrl.js?"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/runtime/noSourceMaps.js": +/*!**************************************************************!*\ + !*** ./node_modules/css-loader/dist/runtime/noSourceMaps.js ***! + \**************************************************************/ +/***/ ((module) => { + +eval("\n\nmodule.exports = function (i) {\n return i[1];\n};\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/css-loader/dist/runtime/noSourceMaps.js?"); + +/***/ }), + +/***/ "./src/css/common.css": +/*!****************************!*\ + !*** ./src/css/common.css ***! + \****************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleDomAPI.js */ \"./node_modules/style-loader/dist/runtime/styleDomAPI.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertBySelector.js */ \"./node_modules/style-loader/dist/runtime/insertBySelector.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ \"./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertStyleElement.js */ \"./node_modules/style-loader/dist/runtime/insertStyleElement.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleTagTransform.js */ \"./node_modules/style-loader/dist/runtime/styleTagTransform.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_common_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../node_modules/css-loader/dist/cjs.js!./common.css */ \"./node_modules/css-loader/dist/cjs.js!./src/css/common.css\");\n\n \n \n \n \n \n \n \n \n \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\n\n options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, \"head\");\n \noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_common_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"], options);\n\n\n\n\n /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_common_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"] && _node_modules_css_loader_dist_cjs_js_common_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals ? _node_modules_css_loader_dist_cjs_js_common_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals : undefined);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/common.css?"); + +/***/ }), + +/***/ "./src/css/modal.css": +/*!***************************!*\ + !*** ./src/css/modal.css ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleDomAPI.js */ \"./node_modules/style-loader/dist/runtime/styleDomAPI.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertBySelector.js */ \"./node_modules/style-loader/dist/runtime/insertBySelector.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ \"./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertStyleElement.js */ \"./node_modules/style-loader/dist/runtime/insertStyleElement.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleTagTransform.js */ \"./node_modules/style-loader/dist/runtime/styleTagTransform.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_modal_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../node_modules/css-loader/dist/cjs.js!./modal.css */ \"./node_modules/css-loader/dist/cjs.js!./src/css/modal.css\");\n\n \n \n \n \n \n \n \n \n \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\n\n options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, \"head\");\n \noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_modal_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"], options);\n\n\n\n\n /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_modal_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"] && _node_modules_css_loader_dist_cjs_js_modal_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals ? _node_modules_css_loader_dist_cjs_js_modal_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals : undefined);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/modal.css?"); + +/***/ }), + +/***/ "./src/css/reset.css": +/*!***************************!*\ + !*** ./src/css/reset.css ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleDomAPI.js */ \"./node_modules/style-loader/dist/runtime/styleDomAPI.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertBySelector.js */ \"./node_modules/style-loader/dist/runtime/insertBySelector.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ \"./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertStyleElement.js */ \"./node_modules/style-loader/dist/runtime/insertStyleElement.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleTagTransform.js */ \"./node_modules/style-loader/dist/runtime/styleTagTransform.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_reset_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../node_modules/css-loader/dist/cjs.js!./reset.css */ \"./node_modules/css-loader/dist/cjs.js!./src/css/reset.css\");\n\n \n \n \n \n \n \n \n \n \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\n\n options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, \"head\");\n \noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_reset_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"], options);\n\n\n\n\n /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_reset_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"] && _node_modules_css_loader_dist_cjs_js_reset_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals ? _node_modules_css_loader_dist_cjs_js_reset_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals : undefined);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/reset.css?"); + +/***/ }), + +/***/ "./src/css/theme.css": +/*!***************************!*\ + !*** ./src/css/theme.css ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleDomAPI.js */ \"./node_modules/style-loader/dist/runtime/styleDomAPI.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertBySelector.js */ \"./node_modules/style-loader/dist/runtime/insertBySelector.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ \"./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/insertStyleElement.js */ \"./node_modules/style-loader/dist/runtime/insertStyleElement.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../node_modules/style-loader/dist/runtime/styleTagTransform.js */ \"./node_modules/style-loader/dist/runtime/styleTagTransform.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_theme_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../node_modules/css-loader/dist/cjs.js!./theme.css */ \"./node_modules/css-loader/dist/cjs.js!./src/css/theme.css\");\n\n \n \n \n \n \n \n \n \n \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\n\n options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, \"head\");\n \noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_theme_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"], options);\n\n\n\n\n /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_theme_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"] && _node_modules_css_loader_dist_cjs_js_theme_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals ? _node_modules_css_loader_dist_cjs_js_theme_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals : undefined);\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/css/theme.css?"); + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js": +/*!****************************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***! + \****************************************************************************/ +/***/ ((module) => { + +eval("\n\nvar stylesInDOM = [];\n\nfunction getIndexByIdentifier(identifier) {\n var result = -1;\n\n for (var i = 0; i < stylesInDOM.length; i++) {\n if (stylesInDOM[i].identifier === identifier) {\n result = i;\n break;\n }\n }\n\n return result;\n}\n\nfunction modulesToDom(list, options) {\n var idCountMap = {};\n var identifiers = [];\n\n for (var i = 0; i < list.length; i++) {\n var item = list[i];\n var id = options.base ? item[0] + options.base : item[0];\n var count = idCountMap[id] || 0;\n var identifier = \"\".concat(id, \" \").concat(count);\n idCountMap[id] = count + 1;\n var indexByIdentifier = getIndexByIdentifier(identifier);\n var obj = {\n css: item[1],\n media: item[2],\n sourceMap: item[3],\n supports: item[4],\n layer: item[5]\n };\n\n if (indexByIdentifier !== -1) {\n stylesInDOM[indexByIdentifier].references++;\n stylesInDOM[indexByIdentifier].updater(obj);\n } else {\n var updater = addElementStyle(obj, options);\n options.byIndex = i;\n stylesInDOM.splice(i, 0, {\n identifier: identifier,\n updater: updater,\n references: 1\n });\n }\n\n identifiers.push(identifier);\n }\n\n return identifiers;\n}\n\nfunction addElementStyle(obj, options) {\n var api = options.domAPI(options);\n api.update(obj);\n\n var updater = function updater(newObj) {\n if (newObj) {\n if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) {\n return;\n }\n\n api.update(obj = newObj);\n } else {\n api.remove();\n }\n };\n\n return updater;\n}\n\nmodule.exports = function (list, options) {\n options = options || {};\n list = list || [];\n var lastIdentifiers = modulesToDom(list, options);\n return function update(newList) {\n newList = newList || [];\n\n for (var i = 0; i < lastIdentifiers.length; i++) {\n var identifier = lastIdentifiers[i];\n var index = getIndexByIdentifier(identifier);\n stylesInDOM[index].references--;\n }\n\n var newLastIdentifiers = modulesToDom(newList, options);\n\n for (var _i = 0; _i < lastIdentifiers.length; _i++) {\n var _identifier = lastIdentifiers[_i];\n\n var _index = getIndexByIdentifier(_identifier);\n\n if (stylesInDOM[_index].references === 0) {\n stylesInDOM[_index].updater();\n\n stylesInDOM.splice(_index, 1);\n }\n }\n\n lastIdentifiers = newLastIdentifiers;\n };\n};\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/insertBySelector.js": +/*!********************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/insertBySelector.js ***! + \********************************************************************/ +/***/ ((module) => { + +eval("\n\nvar memo = {};\n/* istanbul ignore next */\n\nfunction getTarget(target) {\n if (typeof memo[target] === \"undefined\") {\n var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself\n\n if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n try {\n // This will throw an exception if access to iframe is blocked\n // due to cross-origin restrictions\n styleTarget = styleTarget.contentDocument.head;\n } catch (e) {\n // istanbul ignore next\n styleTarget = null;\n }\n }\n\n memo[target] = styleTarget;\n }\n\n return memo[target];\n}\n/* istanbul ignore next */\n\n\nfunction insertBySelector(insert, style) {\n var target = getTarget(insert);\n\n if (!target) {\n throw new Error(\"Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.\");\n }\n\n target.appendChild(style);\n}\n\nmodule.exports = insertBySelector;\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/style-loader/dist/runtime/insertBySelector.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/insertStyleElement.js": +/*!**********************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/insertStyleElement.js ***! + \**********************************************************************/ +/***/ ((module) => { + +eval("\n\n/* istanbul ignore next */\nfunction insertStyleElement(options) {\n var element = document.createElement(\"style\");\n options.setAttributes(element, options.attributes);\n options.insert(element, options.options);\n return element;\n}\n\nmodule.exports = insertStyleElement;\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/style-loader/dist/runtime/insertStyleElement.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js": +/*!**********************************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js ***! + \**********************************************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("\n\n/* istanbul ignore next */\nfunction setAttributesWithoutAttributes(styleElement) {\n var nonce = true ? __webpack_require__.nc : 0;\n\n if (nonce) {\n styleElement.setAttribute(\"nonce\", nonce);\n }\n}\n\nmodule.exports = setAttributesWithoutAttributes;\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/styleDomAPI.js": +/*!***************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/styleDomAPI.js ***! + \***************************************************************/ +/***/ ((module) => { + +eval("\n\n/* istanbul ignore next */\nfunction apply(styleElement, options, obj) {\n var css = \"\";\n\n if (obj.supports) {\n css += \"@supports (\".concat(obj.supports, \") {\");\n }\n\n if (obj.media) {\n css += \"@media \".concat(obj.media, \" {\");\n }\n\n var needLayer = typeof obj.layer !== \"undefined\";\n\n if (needLayer) {\n css += \"@layer\".concat(obj.layer.length > 0 ? \" \".concat(obj.layer) : \"\", \" {\");\n }\n\n css += obj.css;\n\n if (needLayer) {\n css += \"}\";\n }\n\n if (obj.media) {\n css += \"}\";\n }\n\n if (obj.supports) {\n css += \"}\";\n }\n\n var sourceMap = obj.sourceMap;\n\n if (sourceMap && typeof btoa !== \"undefined\") {\n css += \"\\n/*# sourceMappingURL=data:application/json;base64,\".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), \" */\");\n } // For old IE\n\n /* istanbul ignore if */\n\n\n options.styleTagTransform(css, styleElement, options.options);\n}\n\nfunction removeStyleElement(styleElement) {\n // istanbul ignore if\n if (styleElement.parentNode === null) {\n return false;\n }\n\n styleElement.parentNode.removeChild(styleElement);\n}\n/* istanbul ignore next */\n\n\nfunction domAPI(options) {\n var styleElement = options.insertStyleElement(options);\n return {\n update: function update(obj) {\n apply(styleElement, options, obj);\n },\n remove: function remove() {\n removeStyleElement(styleElement);\n }\n };\n}\n\nmodule.exports = domAPI;\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/style-loader/dist/runtime/styleDomAPI.js?"); + +/***/ }), + +/***/ "./node_modules/style-loader/dist/runtime/styleTagTransform.js": +/*!*********************************************************************!*\ + !*** ./node_modules/style-loader/dist/runtime/styleTagTransform.js ***! + \*********************************************************************/ +/***/ ((module) => { + +eval("\n\n/* istanbul ignore next */\nfunction styleTagTransform(css, styleElement) {\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = css;\n } else {\n while (styleElement.firstChild) {\n styleElement.removeChild(styleElement.firstChild);\n }\n\n styleElement.appendChild(document.createTextNode(css));\n }\n}\n\nmodule.exports = styleTagTransform;\n\n//# sourceURL=webpack://javascript-movie-review/./node_modules/style-loader/dist/runtime/styleTagTransform.js?"); + +/***/ }), + +/***/ "./src/App.ts": +/*!********************!*\ + !*** ./src/App.ts ***! + \********************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ App)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ \"./src/constants.ts\");\n/* harmony import */ var _store_MovieStore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./store/MovieStore */ \"./src/store/MovieStore.ts\");\n/* harmony import */ var _store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./store/SearchMovieStore */ \"./src/store/SearchMovieStore.ts\");\n/* harmony import */ var _components_SearchBox__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/SearchBox */ \"./src/components/SearchBox.ts\");\n/* harmony import */ var _components_MovieCard__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/MovieCard */ \"./src/components/MovieCard.ts\");\n/* harmony import */ var _components_Modal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/Modal */ \"./src/components/Modal.ts\");\n/* harmony import */ var _images_logo_png__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./images/logo.png */ \"./src/images/logo.png\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar _App_instances, _App_pageType, _App_observer, _App_isLoading, _App_skeletonBySize, _App_insertLogo, _App_getSkeletonCount, _App_generateMovieList, _App_generateSearchMovieList, _App_generateItemList, _App_changeTitle, _App_appendMovieCard, _App_generateSkeletonUI, _App_removeSkeletonUI, _App_setupIntersectionObserver, _App_observeSentinel, _App_handleIntersection, _App_loadMoreMovies, _App_removePreviousError, _App_generateSearchBox, _App_addHomeButtonEvent, _App_renderAllMovieList, _App_initEventListeners, _App_handleMovieCardClick;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nclass App {\r\n constructor() {\r\n _App_instances.add(this);\r\n _App_pageType.set(this, 'popular');\r\n _App_observer.set(this, null);\r\n _App_isLoading.set(this, false);\r\n _App_skeletonBySize.set(this, _constants__WEBPACK_IMPORTED_MODULE_0__.SKELETON_UI_PC);\r\n _App_handleIntersection.set(this, (entries) => {\r\n entries.forEach((entry) => {\r\n if (entry.isIntersecting && entry.intersectionRatio >= 0.8 && !__classPrivateFieldGet(this, _App_isLoading, \"f\")) {\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_loadMoreMovies).call(this);\r\n }\r\n });\r\n });\r\n }\r\n run() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_insertLogo).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateMovieList).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateSearchBox).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_addHomeButtonEvent).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_initEventListeners).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_setupIntersectionObserver).call(this);\r\n });\r\n }\r\n}\r\n_App_pageType = new WeakMap(), _App_observer = new WeakMap(), _App_isLoading = new WeakMap(), _App_skeletonBySize = new WeakMap(), _App_handleIntersection = new WeakMap(), _App_instances = new WeakSet(), _App_insertLogo = function _App_insertLogo() {\r\n const homeButton = document.getElementById('home-button');\r\n const imgElement = document.createElement('img');\r\n imgElement.src = _images_logo_png__WEBPACK_IMPORTED_MODULE_6__;\r\n imgElement.alt = 'MovieList 로고';\r\n homeButton === null || homeButton === void 0 ? void 0 : homeButton.appendChild(imgElement);\r\n}, _App_getSkeletonCount = function _App_getSkeletonCount() {\r\n const width = window.innerWidth;\r\n let skeletonCount = __classPrivateFieldGet(this, _App_skeletonBySize, \"f\");\r\n if (width <= 390) {\r\n skeletonCount = _constants__WEBPACK_IMPORTED_MODULE_0__.SKELETON_UI_MOBILE;\r\n }\r\n else if (width <= 834) {\r\n skeletonCount = _constants__WEBPACK_IMPORTED_MODULE_0__.SKELETON_UI_TABLET;\r\n }\r\n return skeletonCount;\r\n}, _App_generateMovieList = function _App_generateMovieList() {\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateItemList).call(this, '지금 인기 있는 영화', () => __awaiter(this, void 0, void 0, function* () { return yield _store_MovieStore__WEBPACK_IMPORTED_MODULE_1__[\"default\"].getMovies(); }), _store_MovieStore__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\r\n}, _App_generateSearchMovieList = function _App_generateSearchMovieList() {\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateItemList).call(this, `\"${_store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"].query}\" 검색 결과`, () => __awaiter(this, void 0, void 0, function* () { return yield _store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"].searchMovies(); }), _store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\r\n}, _App_generateItemList = function _App_generateItemList(title, fetchData, store) {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_changeTitle).call(this, title);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_removePreviousError).call(this);\r\n const ulElement = document.querySelector('ul.item-list');\r\n if (ulElement) {\r\n const skeletonCount = __classPrivateFieldGet(this, _App_instances, \"m\", _App_getSkeletonCount).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateSkeletonUI).call(this, ulElement, skeletonCount);\r\n const newData = yield fetchData();\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_removeSkeletonUI).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_appendMovieCard).call(this, newData, ulElement);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_observeSentinel).call(this);\r\n }\r\n });\r\n}, _App_changeTitle = function _App_changeTitle(title) {\r\n const h2Element = document.querySelector('h2');\r\n if (h2Element) {\r\n h2Element.textContent = title;\r\n }\r\n}, _App_appendMovieCard = function _App_appendMovieCard(newData, ulElement) {\r\n newData.forEach((movieData) => {\r\n const card = new _components_MovieCard__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\r\n movie: movieData,\r\n });\r\n ulElement === null || ulElement === void 0 ? void 0 : ulElement.appendChild(card.element);\r\n });\r\n}, _App_generateSkeletonUI = function _App_generateSkeletonUI(ulElement, skeletonCount) {\r\n const fragment = new DocumentFragment();\r\n for (let i = 0; i < skeletonCount; i++) {\r\n const card = new _components_MovieCard__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\r\n classes: ['skeleton-container'],\r\n });\r\n fragment.appendChild(card.element);\r\n }\r\n ulElement === null || ulElement === void 0 ? void 0 : ulElement.appendChild(fragment);\r\n}, _App_removeSkeletonUI = function _App_removeSkeletonUI() {\r\n const skeletonElements = document.querySelectorAll('.skeleton-container');\r\n if (skeletonElements) {\r\n skeletonElements.forEach((skeletonElement) => {\r\n var _a;\r\n (_a = skeletonElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(skeletonElement);\r\n });\r\n }\r\n}, _App_setupIntersectionObserver = function _App_setupIntersectionObserver() {\r\n const options = {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0.8,\r\n };\r\n __classPrivateFieldSet(this, _App_observer, new IntersectionObserver(__classPrivateFieldGet(this, _App_handleIntersection, \"f\"), options), \"f\");\r\n const sentinel = document.createElement('li');\r\n sentinel.classList.add('sentinel');\r\n __classPrivateFieldGet(this, _App_observer, \"f\").observe(sentinel);\r\n}, _App_observeSentinel = function _App_observeSentinel() {\r\n const sentinel = document.querySelector('.sentinel');\r\n if (sentinel && __classPrivateFieldGet(this, _App_observer, \"f\")) {\r\n __classPrivateFieldGet(this, _App_observer, \"f\").observe(sentinel);\r\n }\r\n}, _App_loadMoreMovies = function _App_loadMoreMovies() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n if (_store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"].presentPage === _store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"].totalPages)\r\n return;\r\n __classPrivateFieldSet(this, _App_isLoading, true, \"f\");\r\n if (__classPrivateFieldGet(this, _App_pageType, \"f\") === 'popular') {\r\n yield _store_MovieStore__WEBPACK_IMPORTED_MODULE_1__[\"default\"].increasePageCount();\r\n yield __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateMovieList).call(this);\r\n }\r\n else {\r\n yield _store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"].increasePageCount();\r\n yield __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateSearchMovieList).call(this);\r\n }\r\n __classPrivateFieldSet(this, _App_isLoading, false, \"f\");\r\n });\r\n}, _App_removePreviousError = function _App_removePreviousError() {\r\n var _a;\r\n const previousError = document.getElementById('error-page');\r\n if (previousError) {\r\n (_a = previousError.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(previousError);\r\n }\r\n}, _App_generateSearchBox = function _App_generateSearchBox() {\r\n const header = document.querySelector('header');\r\n const ulElement = document.querySelector('ul.item-list');\r\n const searchBox = new _components_SearchBox__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\r\n searchInputSubmit: (query) => {\r\n if (ulElement)\r\n ulElement.innerHTML = '';\r\n __classPrivateFieldSet(this, _App_pageType, 'search', \"f\");\r\n _store_SearchMovieStore__WEBPACK_IMPORTED_MODULE_2__[\"default\"].query = query;\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_generateSearchMovieList).call(this);\r\n },\r\n });\r\n header === null || header === void 0 ? void 0 : header.appendChild(searchBox.element);\r\n}, _App_addHomeButtonEvent = function _App_addHomeButtonEvent() {\r\n const homeButton = document.getElementById('home-button');\r\n if (homeButton) {\r\n homeButton.addEventListener('click', () => {\r\n __classPrivateFieldSet(this, _App_pageType, 'popular', \"f\");\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_changeTitle).call(this, '지금 인기 있는 영화');\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_removePreviousError).call(this);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_renderAllMovieList).call(this);\r\n });\r\n }\r\n}, _App_renderAllMovieList = function _App_renderAllMovieList() {\r\n const movieDatas = _store_MovieStore__WEBPACK_IMPORTED_MODULE_1__[\"default\"].movies;\r\n if (movieDatas.length === 0)\r\n return;\r\n const ulElement = document.querySelector('ul.item-list');\r\n if (!ulElement)\r\n return;\r\n ulElement.innerHTML = '';\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_appendMovieCard).call(this, movieDatas, ulElement);\r\n __classPrivateFieldGet(this, _App_instances, \"m\", _App_observeSentinel).call(this);\r\n}, _App_initEventListeners = function _App_initEventListeners() {\r\n const itemList = document.querySelector('ul.item-list');\r\n if (itemList) {\r\n itemList.addEventListener('click', __classPrivateFieldGet(this, _App_instances, \"m\", _App_handleMovieCardClick).bind(this));\r\n }\r\n}, _App_handleMovieCardClick = function _App_handleMovieCardClick(event) {\r\n const clickedElement = event.target.closest('.item-card');\r\n if (clickedElement) {\r\n const movieId = Number(clickedElement.dataset.movieid);\r\n const modal = _components_Modal__WEBPACK_IMPORTED_MODULE_5__[\"default\"].getInstance(movieId);\r\n modal.openModal();\r\n }\r\n};\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/App.ts?"); + +/***/ }), + +/***/ "./src/components/ErrorRender.ts": +/*!***************************************!*\ + !*** ./src/components/ErrorRender.ts ***! + \***************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ErrorRender)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./src/constants.ts\");\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar _ErrorRender_instances, _ErrorRender_errorPageElement, _ErrorRender_status, _ErrorRender_renderNoResult, _ErrorRender_renderClientError, _ErrorRender_renderServerError;\r\n\r\nclass ErrorRender {\r\n constructor(status) {\r\n _ErrorRender_instances.add(this);\r\n _ErrorRender_errorPageElement.set(this, document.createElement('div'));\r\n _ErrorRender_status.set(this, '');\r\n __classPrivateFieldSet(this, _ErrorRender_status, status, \"f\");\r\n __classPrivateFieldGet(this, _ErrorRender_errorPageElement, \"f\").id = 'error-page';\r\n const itemView = document.querySelector('.item-view');\r\n if (itemView) {\r\n itemView.appendChild(__classPrivateFieldGet(this, _ErrorRender_errorPageElement, \"f\"));\r\n }\r\n }\r\n renderError() {\r\n if (__classPrivateFieldGet(this, _ErrorRender_status, \"f\")[0] === _constants__WEBPACK_IMPORTED_MODULE_0__.ERROR_2XX)\r\n __classPrivateFieldGet(this, _ErrorRender_instances, \"m\", _ErrorRender_renderNoResult).call(this);\r\n if (__classPrivateFieldGet(this, _ErrorRender_status, \"f\")[0] === _constants__WEBPACK_IMPORTED_MODULE_0__.ERROR_4XX)\r\n __classPrivateFieldGet(this, _ErrorRender_instances, \"m\", _ErrorRender_renderClientError).call(this);\r\n if (__classPrivateFieldGet(this, _ErrorRender_status, \"f\")[0] === _constants__WEBPACK_IMPORTED_MODULE_0__.ERROR_5XX)\r\n __classPrivateFieldGet(this, _ErrorRender_instances, \"m\", _ErrorRender_renderServerError).call(this);\r\n }\r\n}\r\n_ErrorRender_errorPageElement = new WeakMap(), _ErrorRender_status = new WeakMap(), _ErrorRender_instances = new WeakSet(), _ErrorRender_renderNoResult = function _ErrorRender_renderNoResult() {\r\n __classPrivateFieldGet(this, _ErrorRender_errorPageElement, \"f\").innerHTML = '

검색 결과가 없습니다.

';\r\n}, _ErrorRender_renderClientError = function _ErrorRender_renderClientError() {\r\n __classPrivateFieldGet(this, _ErrorRender_errorPageElement, \"f\").innerHTML = '

클라이언트 에러

';\r\n}, _ErrorRender_renderServerError = function _ErrorRender_renderServerError() {\r\n __classPrivateFieldGet(this, _ErrorRender_errorPageElement, \"f\").innerHTML = '

서버 에러

';\r\n};\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/components/ErrorRender.ts?"); + +/***/ }), + +/***/ "./src/components/Modal.ts": +/*!*********************************!*\ + !*** ./src/components/Modal.ts ***! + \*********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Modal)\n/* harmony export */ });\n/* harmony import */ var _store_API__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../store/API */ \"./src/store/API.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./src/constants.ts\");\n/* harmony import */ var _images_no_image_png__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../images/no-image.png */ \"./src/images/no-image.png\");\n/* harmony import */ var _images_star_filled_png__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../images/star_filled.png */ \"./src/images/star_filled.png\");\n/* harmony import */ var _images_star_empty_png__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../images/star_empty.png */ \"./src/images/star_empty.png\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar _Modal_isOpen, _Modal_modalElement, _Modal_movieId;\r\n\r\n\r\n\r\n\r\n\r\nclass Modal {\r\n constructor(movieId) {\r\n _Modal_isOpen.set(this, false);\r\n _Modal_modalElement.set(this, null);\r\n _Modal_movieId.set(this, void 0);\r\n __classPrivateFieldSet(this, _Modal_movieId, movieId, \"f\");\r\n }\r\n generateModal() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n if (__classPrivateFieldGet(this, _Modal_modalElement, \"f\")) {\r\n __classPrivateFieldGet(this, _Modal_modalElement, \"f\").remove();\r\n __classPrivateFieldSet(this, _Modal_modalElement, null, \"f\");\r\n }\r\n const movieDetail = yield (0,_store_API__WEBPACK_IMPORTED_MODULE_0__.fetchMovieDetail)(__classPrivateFieldGet(this, _Modal_movieId, \"f\"));\r\n const posterPath = movieDetail.poster_path ? `https://image.tmdb.org/t/p/w500${movieDetail.poster_path}` : _images_no_image_png__WEBPACK_IMPORTED_MODULE_2__;\r\n const genres = movieDetail.genres.map((genre) => genre.name).join(', ');\r\n const modalElement = document.createElement('div');\r\n modalElement.classList.add('modal', 'modal--open');\r\n const modalHTML = `\r\n
\r\n
\r\n
\r\n

${movieDetail.title}

\r\n \r\n
\r\n
\r\n \"포스터\r\n
\r\n
\r\n
\r\n

${genres}

\r\n

${movieDetail.vote_average.toFixed(2)}

\r\n
\r\n

${movieDetail.overview}

\r\n
\r\n
\r\n

내 별점

\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

0

\r\n

남겨주세요

\r\n
\r\n
\r\n
\r\n
\r\n `;\r\n modalElement.innerHTML = modalHTML;\r\n document.body.appendChild(modalElement);\r\n __classPrivateFieldSet(this, _Modal_modalElement, modalElement, \"f\");\r\n modalElement.addEventListener('click', (event) => {\r\n this.handleModalClick(event);\r\n const button = event.target;\r\n const starButtons = modalElement.querySelectorAll('.my-vote-body button img');\r\n const starIndex = Array.from(starButtons).findIndex((btn) => btn === button);\r\n if (starIndex !== -1) {\r\n this.handleStarClick(starIndex);\r\n }\r\n });\r\n });\r\n }\r\n openModal() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n if (__classPrivateFieldGet(this, _Modal_isOpen, \"f\"))\r\n return;\r\n yield this.generateModal();\r\n __classPrivateFieldSet(this, _Modal_isOpen, true, \"f\");\r\n });\r\n }\r\n closeModal() {\r\n if (!__classPrivateFieldGet(this, _Modal_isOpen, \"f\"))\r\n return;\r\n if (__classPrivateFieldGet(this, _Modal_modalElement, \"f\")) {\r\n __classPrivateFieldGet(this, _Modal_modalElement, \"f\").remove();\r\n __classPrivateFieldSet(this, _Modal_modalElement, null, \"f\");\r\n }\r\n __classPrivateFieldSet(this, _Modal_isOpen, false, \"f\");\r\n }\r\n handleModalClick(event) {\r\n if (!(event.target instanceof HTMLElement))\r\n return;\r\n const modalBackDrop = document.querySelector('.modal-backdrop');\r\n const modalCloseButton = event.target.closest('.modal-close-button');\r\n if (event.target === modalBackDrop || event.target === modalCloseButton) {\r\n this.closeModal();\r\n }\r\n }\r\n handleStarClick(starIndex) {\r\n var _a, _b, _c;\r\n const myVoteNumber = (_a = __classPrivateFieldGet(this, _Modal_modalElement, \"f\")) === null || _a === void 0 ? void 0 : _a.querySelector('.my-vote-number');\r\n const myVoteDescription = (_b = __classPrivateFieldGet(this, _Modal_modalElement, \"f\")) === null || _b === void 0 ? void 0 : _b.querySelector('.my-vote-description');\r\n if (!myVoteNumber || !myVoteDescription)\r\n return;\r\n const starButtons = (_c = __classPrivateFieldGet(this, _Modal_modalElement, \"f\")) === null || _c === void 0 ? void 0 : _c.querySelectorAll('.my-vote-body button img');\r\n if (!starButtons)\r\n return;\r\n starButtons.forEach((starButton, index) => {\r\n if (index <= starIndex) {\r\n starButton.setAttribute('src', _images_star_filled_png__WEBPACK_IMPORTED_MODULE_3__);\r\n }\r\n else {\r\n starButton.setAttribute('src', _images_star_empty_png__WEBPACK_IMPORTED_MODULE_4__);\r\n }\r\n });\r\n const myVoteKey = (starIndex + 1) * 2;\r\n myVoteNumber.textContent = myVoteKey.toString();\r\n myVoteDescription.textContent = _constants__WEBPACK_IMPORTED_MODULE_1__.VOTE[myVoteKey];\r\n }\r\n static getInstance(movieId) {\r\n if (!Modal.instance || __classPrivateFieldGet(Modal.instance, _Modal_movieId, \"f\") !== movieId) {\r\n Modal.instance = new Modal(movieId);\r\n }\r\n return Modal.instance;\r\n }\r\n}\r\n_Modal_isOpen = new WeakMap(), _Modal_modalElement = new WeakMap(), _Modal_movieId = new WeakMap();\r\nModal.instance = null;\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/components/Modal.ts?"); + +/***/ }), + +/***/ "./src/components/MovieCard.ts": +/*!*************************************!*\ + !*** ./src/components/MovieCard.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ MovieCard)\n/* harmony export */ });\n/* harmony import */ var _images_no_image_png__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../images/no-image.png */ \"./src/images/no-image.png\");\n/* harmony import */ var _images_star_filled_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../images/star_filled.png */ \"./src/images/star_filled.png\");\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar _MovieCard_instances, _MovieCard_liElement, _MovieCard_movieId, _MovieCard_movie, _MovieCard_generateMovieItem, _MovieCard_generateSkeletonMovieItem;\r\n\r\n\r\nclass MovieCard {\r\n constructor({ classes, movie }) {\r\n _MovieCard_instances.add(this);\r\n _MovieCard_liElement.set(this, document.createElement('li'));\r\n _MovieCard_movieId.set(this, void 0);\r\n _MovieCard_movie.set(this, void 0);\r\n if (classes)\r\n __classPrivateFieldGet(this, _MovieCard_liElement, \"f\").classList.add(...classes);\r\n if (movie) {\r\n __classPrivateFieldSet(this, _MovieCard_movie, movie, \"f\");\r\n __classPrivateFieldSet(this, _MovieCard_movieId, movie.id, \"f\");\r\n __classPrivateFieldGet(this, _MovieCard_instances, \"m\", _MovieCard_generateMovieItem).call(this, __classPrivateFieldGet(this, _MovieCard_movie, \"f\"));\r\n }\r\n else {\r\n __classPrivateFieldGet(this, _MovieCard_instances, \"m\", _MovieCard_generateSkeletonMovieItem).call(this);\r\n }\r\n }\r\n get element() {\r\n return __classPrivateFieldGet(this, _MovieCard_liElement, \"f\");\r\n }\r\n}\r\n_MovieCard_liElement = new WeakMap(), _MovieCard_movieId = new WeakMap(), _MovieCard_movie = new WeakMap(), _MovieCard_instances = new WeakSet(), _MovieCard_generateMovieItem = function _MovieCard_generateMovieItem(movie) {\r\n const posterPath = movie.poster_path\r\n ? `https://image.tmdb.org/t/p/w220_and_h330_face${movie.poster_path}`\r\n : _images_no_image_png__WEBPACK_IMPORTED_MODULE_0__;\r\n const element = `\r\n
\r\n
\r\n \r\n

${movie.title}

\r\n

${movie.vote_average.toFixed(2)}\"별점\"

\r\n
\r\n
\r\n `;\r\n __classPrivateFieldGet(this, _MovieCard_liElement, \"f\").innerHTML = element;\r\n}, _MovieCard_generateSkeletonMovieItem = function _MovieCard_generateSkeletonMovieItem() {\r\n const element = ` \r\n
\r\n
\r\n
\r\n
\r\n
\r\n `;\r\n __classPrivateFieldGet(this, _MovieCard_liElement, \"f\").innerHTML = element;\r\n};\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/components/MovieCard.ts?"); + +/***/ }), + +/***/ "./src/components/SearchBox.ts": +/*!*************************************!*\ + !*** ./src/components/SearchBox.ts ***! + \*************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SearchBox)\n/* harmony export */ });\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar _SearchBox_instances, _SearchBox_searchBoxElement, _SearchBox_searchInputSubmit, _SearchBox_generateInput, _SearchBox_generateButton, _SearchBox_handleSubmit, _SearchBox_addFormEvent;\r\nclass SearchBox {\r\n constructor({ searchInputSubmit }) {\r\n _SearchBox_instances.add(this);\r\n _SearchBox_searchBoxElement.set(this, document.createElement('form'));\r\n _SearchBox_searchInputSubmit.set(this, void 0);\r\n __classPrivateFieldSet(this, _SearchBox_searchInputSubmit, searchInputSubmit, \"f\");\r\n __classPrivateFieldGet(this, _SearchBox_searchBoxElement, \"f\").classList.add('search-box');\r\n __classPrivateFieldGet(this, _SearchBox_instances, \"m\", _SearchBox_generateInput).call(this);\r\n __classPrivateFieldGet(this, _SearchBox_instances, \"m\", _SearchBox_generateButton).call(this);\r\n __classPrivateFieldGet(this, _SearchBox_instances, \"m\", _SearchBox_addFormEvent).call(this);\r\n }\r\n get element() {\r\n return __classPrivateFieldGet(this, _SearchBox_searchBoxElement, \"f\");\r\n }\r\n}\r\n_SearchBox_searchBoxElement = new WeakMap(), _SearchBox_searchInputSubmit = new WeakMap(), _SearchBox_instances = new WeakSet(), _SearchBox_generateInput = function _SearchBox_generateInput() {\r\n const input = document.createElement('input');\r\n input.type = 'text';\r\n input.placeholder = '검색';\r\n input.name = 'query';\r\n __classPrivateFieldGet(this, _SearchBox_searchBoxElement, \"f\").appendChild(input);\r\n}, _SearchBox_generateButton = function _SearchBox_generateButton() {\r\n const button = document.createElement('button');\r\n button.classList.add('search-button');\r\n button.textContent = '검색';\r\n __classPrivateFieldGet(this, _SearchBox_searchBoxElement, \"f\").appendChild(button);\r\n}, _SearchBox_handleSubmit = function _SearchBox_handleSubmit(event) {\r\n event.preventDefault();\r\n const target = event.target;\r\n __classPrivateFieldGet(this, _SearchBox_searchInputSubmit, \"f\").call(this, target.query.value);\r\n}, _SearchBox_addFormEvent = function _SearchBox_addFormEvent() {\r\n __classPrivateFieldGet(this, _SearchBox_searchBoxElement, \"f\").addEventListener('submit', __classPrivateFieldGet(this, _SearchBox_instances, \"m\", _SearchBox_handleSubmit).bind(this));\r\n};\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/components/SearchBox.ts?"); + +/***/ }), + +/***/ "./src/constants.ts": +/*!**************************!*\ + !*** ./src/constants.ts ***! + \**************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ERROR_2XX\": () => (/* binding */ ERROR_2XX),\n/* harmony export */ \"ERROR_4XX\": () => (/* binding */ ERROR_4XX),\n/* harmony export */ \"ERROR_5XX\": () => (/* binding */ ERROR_5XX),\n/* harmony export */ \"SKELETON_UI_MOBILE\": () => (/* binding */ SKELETON_UI_MOBILE),\n/* harmony export */ \"SKELETON_UI_PC\": () => (/* binding */ SKELETON_UI_PC),\n/* harmony export */ \"SKELETON_UI_TABLET\": () => (/* binding */ SKELETON_UI_TABLET),\n/* harmony export */ \"VOTE\": () => (/* binding */ VOTE)\n/* harmony export */ });\nconst SKELETON_UI_PC = 8;\r\nconst SKELETON_UI_TABLET = 6;\r\nconst SKELETON_UI_MOBILE = 4;\r\nconst ERROR_2XX = '2';\r\nconst ERROR_4XX = '4';\r\nconst ERROR_5XX = '5';\r\nconst VOTE = {\r\n 2: '최악이예요',\r\n 4: '별로예요',\r\n 6: '보통이에요',\r\n 8: '재미있어요',\r\n 10: '명작이에요',\r\n};\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/constants.ts?"); + +/***/ }), + +/***/ "./src/index.js": +/*!**********************!*\ + !*** ./src/index.js ***! + \**********************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./App */ \"./src/App.ts\");\n/* harmony import */ var _css_reset_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./css/reset.css */ \"./src/css/reset.css\");\n/* harmony import */ var _css_theme_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./css/theme.css */ \"./src/css/theme.css\");\n/* harmony import */ var _css_common_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./css/common.css */ \"./src/css/common.css\");\n/* harmony import */ var _css_modal_css__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./css/modal.css */ \"./src/css/modal.css\");\n\r\n\r\n\r\n\r\n\r\nconst app = new _App__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\r\napp.run();\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/index.js?"); + +/***/ }), + +/***/ "./src/store/API.ts": +/*!**************************!*\ + !*** ./src/store/API.ts ***! + \**************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"fetchMovieDetail\": () => (/* binding */ fetchMovieDetail),\n/* harmony export */ \"fetchPopularMovies\": () => (/* binding */ fetchPopularMovies),\n/* harmony export */ \"fetchSearchMovies\": () => (/* binding */ fetchSearchMovies)\n/* harmony export */ });\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nconst BASE_URL = 'https://api.themoviedb.org/3';\r\nconst API_KEY = \"eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJmMDU4ZjVjNjhkNjdjMDBjNWIwMzhlZjBkNDFiZjZhNCIsInN1YiI6IjY1MGEwOTUzYWVkZTU5MDExYmU4MDA5YyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.ZRuD_W18pOuRGc_wiePuFmHrkcTvzF32PBQUFPHjhLc\";\r\nconst options = {\r\n method: 'GET',\r\n headers: {\r\n accept: 'application/json',\r\n Authorization: `Bearer ${API_KEY}`,\r\n },\r\n};\r\nfunction fetchPopularMovies(pageCount) {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n const response = yield fetch(`${BASE_URL}/movie/popular?language=ko&page=${pageCount}`, options);\r\n return response;\r\n });\r\n}\r\nfunction fetchSearchMovies(query, presentPage) {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n const response = yield fetch(`${BASE_URL}/search/movie?query=${query}&language=ko&page=${presentPage}`, options);\r\n return response;\r\n });\r\n}\r\nfunction fetchMovieDetail(movieId) {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n const response = yield fetch(`${BASE_URL}/movie/${movieId}?language=ko`, options);\r\n return response.json();\r\n });\r\n}\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/store/API.ts?"); + +/***/ }), + +/***/ "./src/store/MovieStore.ts": +/*!*********************************!*\ + !*** ./src/store/MovieStore.ts ***! + \*********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _API__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./API */ \"./src/store/API.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./src/constants.ts\");\n/* harmony import */ var _components_ErrorRender__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../components/ErrorRender */ \"./src/components/ErrorRender.ts\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar _MovieStore_instances, _MovieStore_moviesData, _MovieStore_pageCount, _MovieStore_fetchMoviesData, _MovieStore_pushNewData;\r\n\r\n\r\n\r\nclass MovieStore {\r\n constructor() {\r\n _MovieStore_instances.add(this);\r\n _MovieStore_moviesData.set(this, void 0);\r\n _MovieStore_pageCount.set(this, 1);\r\n __classPrivateFieldSet(this, _MovieStore_moviesData, [], \"f\");\r\n }\r\n getMovies() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n try {\r\n const responseData = yield __classPrivateFieldGet(this, _MovieStore_instances, \"m\", _MovieStore_fetchMoviesData).call(this);\r\n __classPrivateFieldGet(this, _MovieStore_instances, \"m\", _MovieStore_pushNewData).call(this, responseData);\r\n return responseData;\r\n }\r\n catch (error) {\r\n console.error(error);\r\n }\r\n });\r\n }\r\n increasePageCount() {\r\n __classPrivateFieldSet(this, _MovieStore_pageCount, __classPrivateFieldGet(this, _MovieStore_pageCount, \"f\") + 1, \"f\");\r\n }\r\n get movies() {\r\n return __classPrivateFieldGet(this, _MovieStore_moviesData, \"f\");\r\n }\r\n}\r\n_MovieStore_moviesData = new WeakMap(), _MovieStore_pageCount = new WeakMap(), _MovieStore_instances = new WeakSet(), _MovieStore_fetchMoviesData = function _MovieStore_fetchMoviesData() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n const response = yield (0,_API__WEBPACK_IMPORTED_MODULE_0__.fetchPopularMovies)(__classPrivateFieldGet(this, _MovieStore_pageCount, \"f\"));\r\n if (!response.ok) {\r\n throw new _components_ErrorRender__WEBPACK_IMPORTED_MODULE_2__[\"default\"](String(response.status)).renderError();\r\n }\r\n const responseJSON = yield response.json();\r\n if (String(response.status)[0] === _constants__WEBPACK_IMPORTED_MODULE_1__.ERROR_2XX && responseJSON.results.length === 0) {\r\n throw new _components_ErrorRender__WEBPACK_IMPORTED_MODULE_2__[\"default\"](String(response.status)).renderError();\r\n }\r\n return responseJSON.results;\r\n });\r\n}, _MovieStore_pushNewData = function _MovieStore_pushNewData(data) {\r\n if (data) {\r\n __classPrivateFieldGet(this, _MovieStore_moviesData, \"f\").push(...data);\r\n }\r\n};\r\nconst movieStore = new MovieStore();\r\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (movieStore);\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/store/MovieStore.ts?"); + +/***/ }), + +/***/ "./src/store/SearchMovieStore.ts": +/*!***************************************!*\ + !*** ./src/store/SearchMovieStore.ts ***! + \***************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _API__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./API */ \"./src/store/API.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./src/constants.ts\");\n/* harmony import */ var _components_ErrorRender__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../components/ErrorRender */ \"./src/components/ErrorRender.ts\");\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n};\r\nvar __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n};\r\nvar _SearchMovieStore_instances, _SearchMovieStore_searchMoviesData, _SearchMovieStore_totalPages, _SearchMovieStore_query, _SearchMovieStore_presentPage, _SearchMovieStore_fetchSearchData, _SearchMovieStore_pushNewData;\r\n\r\n\r\n\r\nclass SearchMovieStore {\r\n constructor() {\r\n _SearchMovieStore_instances.add(this);\r\n _SearchMovieStore_searchMoviesData.set(this, void 0);\r\n _SearchMovieStore_totalPages.set(this, 0);\r\n _SearchMovieStore_query.set(this, '');\r\n _SearchMovieStore_presentPage.set(this, 1);\r\n __classPrivateFieldSet(this, _SearchMovieStore_searchMoviesData, [], \"f\");\r\n }\r\n searchMovies() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n try {\r\n const responseData = yield __classPrivateFieldGet(this, _SearchMovieStore_instances, \"m\", _SearchMovieStore_fetchSearchData).call(this);\r\n const { results } = responseData;\r\n __classPrivateFieldSet(this, _SearchMovieStore_totalPages, responseData.total_pages, \"f\");\r\n __classPrivateFieldGet(this, _SearchMovieStore_instances, \"m\", _SearchMovieStore_pushNewData).call(this, results);\r\n return results;\r\n }\r\n catch (error) {\r\n console.error(error);\r\n }\r\n });\r\n }\r\n increasePageCount() {\r\n __classPrivateFieldSet(this, _SearchMovieStore_presentPage, __classPrivateFieldGet(this, _SearchMovieStore_presentPage, \"f\") + 1, \"f\");\r\n }\r\n get movies() {\r\n return __classPrivateFieldGet(this, _SearchMovieStore_searchMoviesData, \"f\");\r\n }\r\n get totalPages() {\r\n return __classPrivateFieldGet(this, _SearchMovieStore_totalPages, \"f\");\r\n }\r\n get presentPage() {\r\n return __classPrivateFieldGet(this, _SearchMovieStore_presentPage, \"f\");\r\n }\r\n get query() {\r\n return __classPrivateFieldGet(this, _SearchMovieStore_query, \"f\");\r\n }\r\n set query(query) {\r\n __classPrivateFieldSet(this, _SearchMovieStore_query, query, \"f\");\r\n __classPrivateFieldSet(this, _SearchMovieStore_presentPage, 1, \"f\");\r\n }\r\n}\r\n_SearchMovieStore_searchMoviesData = new WeakMap(), _SearchMovieStore_totalPages = new WeakMap(), _SearchMovieStore_query = new WeakMap(), _SearchMovieStore_presentPage = new WeakMap(), _SearchMovieStore_instances = new WeakSet(), _SearchMovieStore_fetchSearchData = function _SearchMovieStore_fetchSearchData() {\r\n return __awaiter(this, void 0, void 0, function* () {\r\n const response = yield (0,_API__WEBPACK_IMPORTED_MODULE_0__.fetchSearchMovies)(__classPrivateFieldGet(this, _SearchMovieStore_query, \"f\"), __classPrivateFieldGet(this, _SearchMovieStore_presentPage, \"f\"));\r\n if (!response.ok) {\r\n throw new _components_ErrorRender__WEBPACK_IMPORTED_MODULE_2__[\"default\"](String(response.status)).renderError();\r\n }\r\n const responseJSON = yield response.json();\r\n if (String(response.status)[0] === _constants__WEBPACK_IMPORTED_MODULE_1__.ERROR_2XX && responseJSON.results.length === 0) {\r\n throw new _components_ErrorRender__WEBPACK_IMPORTED_MODULE_2__[\"default\"](String(response.status)).renderError();\r\n }\r\n return responseJSON;\r\n });\r\n}, _SearchMovieStore_pushNewData = function _SearchMovieStore_pushNewData(data) {\r\n if (data) {\r\n __classPrivateFieldGet(this, _SearchMovieStore_searchMoviesData, \"f\").push(...data);\r\n }\r\n};\r\nconst searchMovieStore = new SearchMovieStore();\r\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (searchMovieStore);\r\n\n\n//# sourceURL=webpack://javascript-movie-review/./src/store/SearchMovieStore.ts?"); + +/***/ }), + +/***/ "./src/images/logo.png": +/*!*****************************!*\ + !*** ./src/images/logo.png ***! + \*****************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("module.exports = __webpack_require__.p + \"2e162b4fefb34cd7ed8d.png\";\n\n//# sourceURL=webpack://javascript-movie-review/./src/images/logo.png?"); + +/***/ }), + +/***/ "./src/images/modal_close_button.png": +/*!*******************************************!*\ + !*** ./src/images/modal_close_button.png ***! + \*******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("module.exports = __webpack_require__.p + \"e9a379619c759f886f7c.png\";\n\n//# sourceURL=webpack://javascript-movie-review/./src/images/modal_close_button.png?"); + +/***/ }), + +/***/ "./src/images/no-image.png": +/*!*********************************!*\ + !*** ./src/images/no-image.png ***! + \*********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("module.exports = __webpack_require__.p + \"06f0f15cfcb8d681b62c.png\";\n\n//# sourceURL=webpack://javascript-movie-review/./src/images/no-image.png?"); + +/***/ }), + +/***/ "./src/images/search_button.png": +/*!**************************************!*\ + !*** ./src/images/search_button.png ***! + \**************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("module.exports = __webpack_require__.p + \"f1bd4269f4446ceae306.png\";\n\n//# sourceURL=webpack://javascript-movie-review/./src/images/search_button.png?"); + +/***/ }), + +/***/ "./src/images/star_empty.png": +/*!***********************************!*\ + !*** ./src/images/star_empty.png ***! + \***********************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("module.exports = __webpack_require__.p + \"6c9611deedf4b85849c9.png\";\n\n//# sourceURL=webpack://javascript-movie-review/./src/images/star_empty.png?"); + +/***/ }), + +/***/ "./src/images/star_filled.png": +/*!************************************!*\ + !*** ./src/images/star_filled.png ***! + \************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +eval("module.exports = __webpack_require__.p + \"6328741810b732410eec.png\";\n\n//# sourceURL=webpack://javascript-movie-review/./src/images/star_filled.png?"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ id: moduleId, +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + ""; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName("script"); +/******/ if(scripts.length) scriptUrl = scripts[scripts.length - 1].src +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ __webpack_require__.b = document.baseURI || self.location.href; +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ "main": 0 +/******/ }; +/******/ +/******/ // no chunk on demand loading +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // no jsonp function +/******/ })(); +/******/ +/******/ /* webpack/runtime/nonce */ +/******/ (() => { +/******/ __webpack_require__.nc = undefined; +/******/ })(); +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module can't be inlined because the eval devtool is used. +/******/ var __webpack_exports__ = __webpack_require__("./src/index.js"); +/******/ +/******/ })() +; \ No newline at end of file diff --git a/dist/e9a379619c759f886f7c.png b/dist/e9a379619c759f886f7c.png new file mode 100644 index 0000000000000000000000000000000000000000..cbe1b680fd019bc5518f80aac9e818474e2530f9 GIT binary patch literal 856 zcmV-e1E>6nP)L`#><{y}pu3{;clFoMLNRAZBRIz_S(o+~W_R--~ zsmNKPFjYup(QtX^jw2UxAG>!L`z>HOW|xPV+1U?4imKIWW!tu22_dRP!mw@13PD-^ z4()L!L)LUUweax_Hs4Isv{c3yvW5U@;cbf{NI`(@;}5g}b}VHdX8;fbW?#@OQ#x7j z;Xxc&D3DmnR%y0F);OdokpV(4F&^JfvHp~l*>J$^Ye=^(`=zoxEc)XpCTqEq>M9X-2xSYWq9dC z%jfegEP^lNtYx7R!Z^aLyV6Rf(tEU@%5;c>N&~~fLVT?ii=}sH=VUvDL2=@yftev? z#m2_wFK<7iqNwSd494A0!9&GEN}xqgrG;U^F>4vRXTmHi?l2iCDlBBG#nUe@WZP&f zAIQHagVdhhVAckg_E)_swc+u8B%=bhP|*KsOAUpPzvR#p*-HSymQL29HK(i8lkJtW$OF))-M5)1I(0X{xV29D3p zs6-cR9iHcV?(&_N_;a6{Fga+9hI?zpbFVFZh~p?O^OA7|g`c7SplQ}E?}gZR1PKe_ z@(+(99*Otxqri3R*jLB*H^J@>9G{Ic{>hBw0N#Pwq;1H|#GwS_SS`qWcPx?$LAe4S z4dggnIa|@sPbV-2tRGDqsC%)|vw#VX(yG;7K#^Pr;`qV1yl#ZY(P&CSe6(g5}e|I&dvCq4ak^BucNuaCX3Oc?biR0=BUS4vg zO}V88r=M&}%;IRVp)i-mh2X%P!^zV0{}2g7MJUXraUqb2RpH_dAF2Z7jw-mWLMA>| zC07Ad1ws*q*fIV7R3;)v8>94RZC=>?KY2OuG4unlcMN*C*2SX&>B{dk@FeTQlkB z4{AMo_Hm$Hm^QB0Ohteln|lA^9-sf>c&T2-pAU2Wb@%2<-CbOITlS)DgD3=etFO^! zkChIVVp-(tE8BZ&sOxrH;wq>P&>)jcva^LhXJ%~{I+NnztV~}Rth$SP9!(sx17!%p zaFT?q^g*kQ>6udcpit?g!I08NX_D6JmYA$oYvK0ahG~L{V|9 zUAj&2kKIj(*OX`r0ryr(_EXa!8Vp6UU9I6{0nrn;c9nvtQu zlBEge2KD7l@DVtPFRl#v5^$Ejk&m91DFF{7IWoanU=Ycj$%1F>6w88q0tFaQ7m07*qoM6N<$g5-19p8x;= literal 0 HcmV?d00001 diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 000000000..d5b3daad9 --- /dev/null +++ b/dist/index.html @@ -0,0 +1,26 @@ + + + + + + + + 영화관 + + + +
+
+

+ +

+
+
+
+

+
    +
    +
    +
    + + diff --git a/docs/REQUIREMENTS.md b/docs/REQUIREMENTS.md index 79089188b..cd09544c8 100644 --- a/docs/REQUIREMENTS.md +++ b/docs/REQUIREMENTS.md @@ -4,7 +4,7 @@ - 실제 동작하는 API를 통한 비동기 통신 - UX 경험 개선을 위한 더 보기(페이징) 구현 -## 구현할 기능 목록 +## STEP1 구현할 기능 목록 ### 1. 🎬 영화 목록 조회 (인기순) @@ -32,3 +32,25 @@ - [x] 검색 결과가 없을 경우 (응답은 있으나) - [x] HTTP 4xx 오류일 때 (클라이언트 오류) - [x] HTTP 5xx 오류일 때 (서버 오류) + +## STEP2 구현할 기능 목록 + +### 1. 📺 영화 상세정보 조회 + +- [x] 영화 포스터나 제목을 클릭하면 자세한 예고편이나 줄거리 등의 정보를 보여준다. +- [x] API에서 제공하는 항목을 활용하여 상세 정보를 보여주는 모달 창을 구현한다. +- [x] 키보드의 ESC 키를 누르면 모달 창을 닫을 수 있는 등 사용성을 고려한다. + +### 2. ⭐️ 별점 매기기 + +- TMDB API 요청과는 관련 없습니다. +- [x] 사용자는 영화에 대해 별점을 줄 수 있다. + - [x] 새로고침하더라도 사용자가 남긴 별점은 유지되어야 한다. + - [x] 별점은 5개로 구성되어 있으며 한 개당 2점이며 1점 단위는 고려하지 않는다. + - 2점, 4점, 6점, 8점, 10점 + +### 3. 📐 UI⁄UX 개선하기 + +- [x] 영화 목록과 영화 상세 정보가 뜨는 모달창에 대한 반응형 레이아웃을 구성한다. +- [x] 영화 목록의 더보기 버튼을 무한 스크롤 방식으로 변경한다. + - 검색 결과 화면에서 사용자가 브라우저 화면의 끝에 도달하면 그 다음 20개의 목록을 서버에 요청하여 추가로 불러올 수 있다. diff --git a/index.html b/index.html index 288df3255..cc50e7242 100644 --- a/index.html +++ b/index.html @@ -5,16 +5,14 @@ - - - 영화관 +

    - +

    @@ -22,6 +20,7 @@

      +
      diff --git a/src/App.ts b/src/App.ts index ac9b44323..f96604892 100644 --- a/src/App.ts +++ b/src/App.ts @@ -1,22 +1,57 @@ import { Movie } from './index.d'; -import { SKELETON_UI_FIXED } from './constants'; +import { SKELETON_UI_PC, SKELETON_UI_TABLET, SKELETON_UI_MOBILE, MOBILE_SIZE, TABLET_SIZE } from './constants'; -import MoreButton from './components/MoreButton'; -import MovieCard from './components/MovieCard'; import movieStore from './store/MovieStore'; -import SearchBox from './components/SearchBox'; import searchMovieStore from './store/SearchMovieStore'; +import SearchBox from './components/SearchBox'; +import MovieCard from './components/MovieCard'; +import Modal from './components/Modal'; + +import Logo from './images/logo.png'; + type Tpage = 'popular' | 'search'; export default class App { #pageType: Tpage = 'popular'; + #observer: IntersectionObserver | null = null; + + #isLoading: boolean = false; + + #skeletonBySize: number = SKELETON_UI_PC; + async run() { + this.#insertLogo(); this.#generateMovieList(); this.#generateSearchBox(); this.#addHomeButtonEvent(); + this.#initEventListeners(); + this.#setupIntersectionObserver(); + this.#goToTop(); + } + + #insertLogo() { + const homeButton = document.getElementById('home-button'); + const imgElement = document.createElement('img'); + + imgElement.src = Logo; + imgElement.alt = 'MovieList 로고'; + + homeButton?.appendChild(imgElement); + } + + #getSkeletonCount() { + const width = window.innerWidth; + + if (width <= MOBILE_SIZE) { + return SKELETON_UI_MOBILE; + } + if (width <= TABLET_SIZE) { + return SKELETON_UI_TABLET; + } + return this.#skeletonBySize; } #generateMovieList() { @@ -35,14 +70,22 @@ export default class App { async #generateItemList(title: string, fetchData: () => Promise, store: any) { this.#changeTitle(title); this.#removePreviousError(); + const ulElement = document.querySelector('ul.item-list'); + if (!ulElement) return; - if (ulElement) { - this.#generateSkeletonUI(ulElement as HTMLElement); - const newData = await fetchData(); - this.#removeSkeletonUI(); - this.#appendMovieCard(newData, ulElement as HTMLElement); - } + const skeletonCount = this.#getSkeletonCount(); + this.#generateSkeletonUI(ulElement as HTMLElement, skeletonCount); + + const newData = await fetchData(); + + this.#removeSkeletonUI(); + + if (!newData) return; + + this.#appendMovieCard(newData, ulElement as HTMLElement); + + this.#observeSentinel(); } #changeTitle(title: string) { @@ -62,20 +105,16 @@ export default class App { ulElement?.appendChild(card.element); }); - this.#generateMoreButton(); + this.#addSentinel(); } - // eslint-disable-next-line max-lines-per-function - #generateSkeletonUI(ulElement: HTMLElement) { - this.#removeMoreButton(); - + #generateSkeletonUI(ulElement: HTMLElement, skeletonCount: number) { const fragment = new DocumentFragment(); - for (let i = 0; i < SKELETON_UI_FIXED; i++) { + for (let i = 0; i < skeletonCount; i++) { const card = new MovieCard({ classes: ['skeleton-container'], }); - fragment.appendChild(card.element); } @@ -92,36 +131,70 @@ export default class App { } } - /* eslint-disable max-lines-per-function */ - #generateMoreButton() { - this.#removeMoreButton(); + #setupIntersectionObserver() { + const options = { + root: null, + rootMargin: '0px', + threshold: 0.2, + }; - if (searchMovieStore.presentPage === searchMovieStore.totalPages) return; + this.#observer = new IntersectionObserver(this.#handleIntersection, options); - const itemView = document.querySelector('section.item-view'); - - const moreBtn = new MoreButton({ - onClick: () => { - if (this.#pageType === 'popular') { - movieStore.increasePageCount(); - this.#generateMovieList(); - } else { - searchMovieStore.increasePageCount(); - this.#generateSearchMovieList(); - } - }, - }); + this.#observeSentinel(); + } + + #addSentinel() { + const ulElement = document.querySelector('ul.item-list'); - itemView?.appendChild(moreBtn.element); + if (ulElement) { + const sentinel = document.createElement('li'); + sentinel.classList.add('sentinel'); + ulElement.appendChild(sentinel); + this.#observeSentinel(); + } } - #removeMoreButton() { - const moreButton = document.getElementById('more-button'); - if (moreButton) { - moreButton.parentNode?.removeChild(moreButton); + #removeSentinel() { + const sentinelElement = document.querySelector('li.sentinel'); + if (sentinelElement) { + sentinelElement.remove(); } } + #observeSentinel() { + const sentinel = document.querySelector('.sentinel'); + if (sentinel && this.#observer) { + this.#observer.observe(sentinel); + } + } + + #handleIntersection = (entries: IntersectionObserverEntry[]) => { + entries.forEach((entry) => { + if (entry.isIntersecting && entry.intersectionRatio >= 0.2 && !this.#isLoading) { + this.#loadMoreMovies(); + } + }); + }; + + // eslint-disable-next-line max-lines-per-function + async #loadMoreMovies() { + if (searchMovieStore.presentPage === searchMovieStore.totalPages) return; + + this.#removeSentinel(); + + this.#isLoading = true; + + if (this.#pageType === 'popular') { + await movieStore.increasePageCount(); + await this.#generateMovieList(); + } else { + await searchMovieStore.increasePageCount(); + await this.#generateSearchMovieList(); + } + + this.#isLoading = false; + } + #removePreviousError() { const previousError = document.getElementById('error-page'); @@ -130,6 +203,7 @@ export default class App { } } + // eslint-disable-next-line max-lines-per-function #generateSearchBox() { const header = document.querySelector('header'); const ulElement = document.querySelector('ul.item-list'); @@ -154,7 +228,6 @@ export default class App { this.#pageType = 'popular'; this.#changeTitle('지금 인기 있는 영화'); this.#removePreviousError(); - this.#removeMoreButton(); this.#renderAllMovieList(); }); } @@ -169,5 +242,34 @@ export default class App { ulElement.innerHTML = ''; this.#appendMovieCard(movieDatas, ulElement as HTMLElement); + this.#observeSentinel(); + } + + #initEventListeners() { + const itemList = document.querySelector('ul.item-list'); + + if (itemList) { + itemList.addEventListener('click', this.#handleMovieCardClick.bind(this)); + } + } + + #handleMovieCardClick(event: any) { + const clickedElement = event.target.closest('.item-card'); + + if (clickedElement) { + const movieId = Number(clickedElement.dataset.movieid); + const modal = Modal.getInstance(movieId); + modal.openModal(); + } + } + + #goToTop() { + const topButton = document.querySelector('#goToTop'); + + if (topButton) { + topButton.addEventListener('click', () => { + window.scrollTo(0, 0); + }); + } } } diff --git a/src/components/ErrorRender.ts b/src/components/ErrorRender.ts index 157d90361..5c2abbb8c 100644 --- a/src/components/ErrorRender.ts +++ b/src/components/ErrorRender.ts @@ -19,6 +19,7 @@ export default class ErrorRender { if (this.#status[0] === ERROR_2XX) this.#renderNoResult(); if (this.#status[0] === ERROR_4XX) this.#renderClientError(); if (this.#status[0] === ERROR_5XX) this.#renderServerError(); + return new Error('오류'); } #renderNoResult() { diff --git a/src/components/Modal.ts b/src/components/Modal.ts new file mode 100644 index 000000000..f235629c0 --- /dev/null +++ b/src/components/Modal.ts @@ -0,0 +1,107 @@ +import movieInfo from './MovieInfo'; +import VoteHandler from './VoteHandler'; + +export default class Modal { + #isOpen = false; + + #modalElement: HTMLElement | null = null; + + static instance: Modal | null = null; + + #movieId: number; + + #voteHandler: any; + + constructor(movieId: number) { + this.#movieId = movieId; + } + + // eslint-disable-next-line max-lines-per-function + async generateModal() { + this.#removeExistingModal(); + + const skeletonModalElement = movieInfo.generateSkeletonModal(); + + const movieDetail = await movieInfo.fetchMovieDetail(this.#movieId); + const modalContent = movieInfo.prepareModalContent(movieDetail); + const modalElement = movieInfo.createModalElement(modalContent); + + skeletonModalElement.remove(); + + document.body.appendChild(modalElement); + this.#modalElement = modalElement; + this.#setupModalEventListener(this.#modalElement); + + this.#voteHandler = new VoteHandler(this.#movieId, this.#modalElement); + } + + #removeExistingModal() { + if (!this.#modalElement) return; + + this.#modalElement.remove(); + this.#modalElement = null; + } + + // eslint-disable-next-line max-lines-per-function + #setupModalEventListener(modalElement: HTMLElement) { + modalElement.addEventListener('click', (event) => { + this.handleModalClick(event); + + const button = event.target; + const starButtons = modalElement.querySelectorAll('.my-vote-body button img'); + const starIndex = Array.from(starButtons).findIndex((btn) => btn === button); + + if (starIndex !== -1) { + this.#voteHandler.handleStarClick(starIndex); + } + }); + } + + async openModal() { + if (this.#isOpen) return; + + document.body.style.overflow = 'hidden'; + await this.generateModal(); + this.#voteHandler.VoteHandler(); + document.addEventListener('keydown', this.#handleKeyDown); + this.#isOpen = true; + } + + closeModal() { + if (!this.#isOpen) return; + + document.body.style.overflow = 'auto'; + this.removeKeydownEventListener(); + this.#removeExistingModal(); + this.#isOpen = false; + } + + #handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + this.closeModal(); + } + }; + + removeKeydownEventListener() { + document.removeEventListener('keydown', this.#handleKeyDown); + } + + handleModalClick(event: Event) { + if (!(event.target instanceof HTMLElement)) return; + + const modalBackDrop = document.querySelector('.modal-backdrop'); + const modalCloseButton = event.target.closest('.modal-close-button'); + + if (event.target === modalBackDrop || event.target === modalCloseButton) { + this.closeModal(); + } + } + + static getInstance(movieId: number) { + if (!Modal.instance || Modal.instance.#movieId !== movieId) { + Modal.instance = new Modal(movieId); + } + + return Modal.instance; + } +} diff --git a/src/components/MovieCard.ts b/src/components/MovieCard.ts index 8f0fe53ac..9fcd07c89 100644 --- a/src/components/MovieCard.ts +++ b/src/components/MovieCard.ts @@ -1,5 +1,8 @@ import { Movie } from '../index.d'; +import NoImage from '../images/no-image.png'; +import StarFilled from '../images/star_filled.png'; + interface Props { classes?: string[]; movie?: Movie; @@ -8,49 +11,57 @@ interface Props { export default class MovieCard { #liElement = document.createElement('li'); + #movieId!: number; + #movie; constructor({ classes, movie }: Props) { if (classes) this.#liElement.classList.add(...classes); + if (movie) { this.#movie = movie; + this.#movieId = movie.id; + this.#generateMovieItem(this.#movie); } else { this.#generateSkeletonMovieItem(); } } - /* eslint-disable max-lines-per-function */ #generateMovieItem(movie: Movie) { - const posterPath = movie.poster_path - ? `https:image.tmdb.org/t/p/w220_and_h330_face${movie.poster_path}` - : '../images/no-image.png'; + const thumbnail = movie.poster_path ? `https://image.tmdb.org/t/p/w220_and_h330_face${movie.poster_path}` : NoImage; + const { title } = movie; + const voteAverage = movie.vote_average.toFixed(2); + + this.#liElement.innerHTML = this.#createMovieItem(thumbnail, title, voteAverage); + } + + // eslint-disable-next-line max-lines-per-function + #createMovieItem(thumbnail: any, title: string, voteAverage: string) { const element = /* html */ ` - -
      - ${movie.title} -

      ${movie.title}

      -

      ${movie.vote_average.toFixed(2)}별점

      -
      -
      `; +
      + ${title} +

      ${title}

      +

      ${voteAverage}별점

      +
      + `; - this.#liElement.innerHTML = element; + return element; } #generateSkeletonMovieItem() { const element = /* html */ ` - -
      -
      -
      -
      -
      -
      `; +
      +
      +
      +
      +
      + `; this.#liElement.innerHTML = element; } diff --git a/src/components/MovieInfo.ts b/src/components/MovieInfo.ts new file mode 100644 index 000000000..e8140ab7b --- /dev/null +++ b/src/components/MovieInfo.ts @@ -0,0 +1,108 @@ +import { ModalContent } from '../index.d'; +import { fetchMovieDetail } from '../store/API'; + +import NoImage from '../images/no-image.png'; +import StarFilled from '../images/star_filled.png'; +import StarEmpty from '../images/star_empty.png'; + +class MovieInfo { + async fetchMovieDetail(movieId: number) { + const moviedetail = await fetchMovieDetail(movieId); + const movieDetail = await moviedetail.json(); + + return movieDetail; + } + + prepareModalContent(movieDetail: any) { + const { title, poster_path, genres, vote_average, overview } = movieDetail; + + return { + title, + posterPath: poster_path ? `https://image.tmdb.org/t/p/w500${poster_path}` : NoImage, + genres: genres.map((genre: any) => genre.name).join(', '), + voteAverage: vote_average.toFixed(2), + overview: overview || '해당 영화의 줄거리 정보가 없습니다.', + }; + } + + // eslint-disable-next-line max-lines-per-function + createModalElement(content: ModalContent) { + const { title, posterPath, genres, voteAverage, overview } = content; + const modalElement = document.createElement('div'); + modalElement.classList.add('modal', 'modal--open'); + + const modalHTML = /* html */ ` + + + `; + + modalElement.innerHTML = modalHTML; + return modalElement; + } + + generateSkeletonModal() { + const modalElement = this.createSkeletonModalElement(); + document.body.appendChild(modalElement); + + return modalElement; + } + + // eslint-disable-next-line max-lines-per-function + createSkeletonModalElement() { + const modalElement = document.createElement('div'); + modalElement.classList.add('modal', 'modal--open'); + + const modalHTML = /* html */ ` + + + `; + + modalElement.innerHTML = modalHTML; + return modalElement; + } +} + +const movieInfo = new MovieInfo(); +export default movieInfo; diff --git a/src/components/VoteHandler.ts b/src/components/VoteHandler.ts new file mode 100644 index 000000000..88afe2c7b --- /dev/null +++ b/src/components/VoteHandler.ts @@ -0,0 +1,83 @@ +import { VOTE } from '../constants'; + +import StarFilled from '../images/star_filled.png'; +import StarEmpty from '../images/star_empty.png'; + +export default class VoteHandler { + #movieId: number; + + #modalElement: HTMLElement | null = null; + + #myVoteResult: { [key: string]: number } = {}; + + constructor(movieId: number, modalElement: HTMLElement | null) { + this.#movieId = movieId; + this.#modalElement = modalElement; + + const savedVotes = localStorage.getItem('myVoteResult'); + if (savedVotes) { + this.#myVoteResult = JSON.parse(savedVotes); + } + } + + VoteHandler() { + const savedVotes = localStorage.getItem('myVoteResult'); + const voteForMovie = savedVotes ? JSON.parse(savedVotes)[this.#movieId] : null; + + if (voteForMovie) { + this.#updateVoteStar(voteForMovie); + this.#updateVoteText(voteForMovie); + } + } + + #updateVoteStar(voteForMovie: number) { + const starButtons = this.#modalElement?.querySelectorAll('.my-vote-body button img'); + + if (!starButtons) return; + + starButtons.forEach((starButton, index) => { + starButton.setAttribute('src', index < voteForMovie / 2 ? StarFilled : StarEmpty); + }); + } + + #updateVoteText(voteForMovie: number) { + const myVoteNumber = this.#modalElement?.querySelector('.my-vote-number'); + const myVoteDescription = this.#modalElement?.querySelector('.my-vote-description'); + + if (!myVoteNumber || !myVoteDescription) return; + + myVoteNumber.textContent = voteForMovie.toString(); + myVoteDescription.textContent = VOTE[voteForMovie]; + } + + handleStarClick(starIndex: number) { + const myVoteNumber = this.#modalElement?.querySelector('.my-vote-number'); + const myVoteDescription = this.#modalElement?.querySelector('.my-vote-description'); + + if (!myVoteNumber || !myVoteDescription) return; + + const starButtons = this.#modalElement?.querySelectorAll('.my-vote-body button img'); + if (!starButtons) return; + + this.updateStarButtons(starButtons, starIndex); + this.updateVoteInfo(myVoteNumber, myVoteDescription, starIndex); + } + + updateStarButtons(starButtons: NodeListOf, starIndex: number) { + starButtons.forEach((starButton, index) => { + starButton.setAttribute('src', index <= starIndex ? StarFilled : StarEmpty); + }); + } + + updateVoteInfo(myVoteNumber: Element, myVoteDescription: Element, starIndex: number) { + const newMyVoteNumber = myVoteNumber as HTMLElement; + const newMyVoteDescription = myVoteDescription as HTMLElement; + + const myVoteKey = (starIndex + 1) * 2; + newMyVoteNumber.textContent = myVoteKey.toString(); + newMyVoteDescription.textContent = VOTE[myVoteKey]; + + this.#myVoteResult[this.#movieId] = myVoteKey; + localStorage.setItem('myVoteResult', JSON.stringify(this.#myVoteResult)); + } +} diff --git a/src/constants.ts b/src/constants.ts index 9ac48cb7d..a0c1b28cf 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,19 @@ -export const SKELETON_UI_FIXED = 8; // 스켈레톤 UI 갯수 +export const SKELETON_UI_PC = 8; // 스켈레톤 UI 갯수 - pc +export const SKELETON_UI_TABLET = 6; // 스켈레톤 UI 갯수 - tablet +export const SKELETON_UI_MOBILE = 4; // 스켈레톤 UI 갯수 - mobile + +export const MOBILE_SIZE = 767; // mobile 사이즈 기준 +export const TABLET_SIZE = 1280; // tablet 사이즈 기준 export const ERROR_2XX = '2'; // 200번대 오류 export const ERROR_4XX = '4'; // 400번대 오류 export const ERROR_5XX = '5'; // 500번대 오류 + +export const VOTE: { [key: number]: string } = { + // 별점 + 2: '최악이예요', + 4: '별로예요', + 6: '보통이에요', + 8: '재미있어요', + 10: '명작이에요', +}; diff --git a/src/css/common.css b/src/css/common.css index 5f63384e0..dc16d59b2 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -3,8 +3,11 @@ } body { - font-size: 14px; + position: relative; background-color: var(--black); + + font-family: Roboto; + font-size: 14px; color: var(--white); } @@ -18,8 +21,9 @@ button { } #app { - margin-top: 150px; + margin-top: 120px; padding-bottom: 48px; + width: 100%; } *:focus { @@ -34,7 +38,8 @@ button { display: flex; flex-direction: column; justify-content: center; - width: 1200px; + max-width: 1200px; + margin: 0 auto; } @@ -59,6 +64,10 @@ button { flex-direction: column; } +.item-card:hover { + cursor: pointer; +} + .item-thumbnail { border-radius: 8px; width: 180px; @@ -66,6 +75,10 @@ button { background-size: contain; } +.item-thumbnail:hover { + box-shadow: 0px 0px 14px 5px rgba(255, 255, 255, 0.3); +} + .item-title { margin-top: 16px; font-size: 1.2rem; @@ -73,10 +86,12 @@ button { } .item-score { + display: flex; + align-items: center; + gap: 5px; margin-top: 16px; + font-size: 1.2rem; - display: inline-block; - vertical-align: middle; } .item-score::after { @@ -128,21 +143,22 @@ button.primary { } header { - width: 100%; - min-width: 1200px; - height: 72px; - background-color: var(--black); display: flex; justify-content: space-between; align-items: center; padding: 0 20px; - border-bottom: 1px solid var(--white); - margin-bottom: 48px; position: fixed; top: 0; left: 0; - z-index: 1000; + z-index: 10; + + border-bottom: 1px solid var(--white); + margin-bottom: 48px; + + width: 100vw; + height: 72px; + background-color: var(--black); } header h1 { @@ -165,6 +181,10 @@ header > .search-box { border-radius: 4px; } +header > .search-box:hover { + box-shadow: 0px 0px 8px 4px rgba(255, 255, 255, 0.3); +} + header .search-box > input { border: 0; } @@ -176,3 +196,151 @@ header .search-box > .search-button { background: url('../images/search_button.png') transparent no-repeat 0 1px; background-size: contain; } + +@media only screen and (min-width: 1280px) { + /* 1280px 이상: 피씨 스타일 */ + + .item-view { + display: flex; + flex-direction: column; + justify-content: center; + max-width: 1200px; + + margin: 0 auto; + } + + .item-view h2 { + font-size: 2rem; + font-weight: bold; + user-select: none; + } + + /* https://andrew.hedges.name/experiments/aspect_ratio/ */ + + .item-list { + display: grid; + margin: 48px 0; + grid-template-columns: repeat(4, 180px); + grid-column-gap: 160px; + grid-row-gap: 48px; + } +} + +@media only screen and (min-width: 768px) and (max-width: 1280px) { + /* 768px 이상 ~ 1280px 이하: 태블릿 스타일 */ + #app { + margin-top: 108px; + } + + .item-view { + display: flex; + flex-direction: column; + justify-content: center; + max-width: 674px; + margin: 0 auto; + } + + .item-list { + display: grid; + margin: 36px 0; + grid-template-columns: repeat(3, 180px); + grid-column-gap: 60px; + grid-row-gap: 55px; + } + + header { + min-width: 674px; + } +} + +@media only screen and (min-width: 390px) and (max-width: 767px) { + /* 390px 이상 ~ 768px 이하: 모바일 스타일 */ + #app { + margin-top: 100px; + } + + .item-view { + display: flex; + flex-direction: column; + justify-content: center; + max-width: 316px; + margin: 0 auto; + } + + .item-list { + display: grid; + margin: 24px 0; + grid-template-columns: repeat(2, 140px); + grid-column-gap: 50px; + grid-row-gap: 55px; + } + + .item-thumbnail { + border-radius: 15px; + width: 140px; + height: 220px; + background-size: contain; + } + + header { + min-width: 120px; + } +} + +@media only screen and (min-width: 320px) and (max-width: 390px) { + /* 320px 이상 ~ 390px 이하: 모바일 스타일 */ + #app { + margin-top: 100px; + } + + .item-view { + display: flex; + flex-direction: column; + justify-content: center; + max-width: 300px; + margin: 0 auto; + } + + .item-list { + display: grid; + margin: 24px 0; + grid-template-columns: repeat(2, 140px); + grid-column-gap: 24px; + grid-row-gap: 28px; + } + + .item-thumbnail { + border-radius: 15px; + width: 140px; + height: 220px; + background-size: contain; + } + + header { + min-width: 120px; + padding: 0 5px; + } + + header .search-box > input { + width: 150px; + } +} + +#goToTop { + position: fixed; + right: 20px; + bottom: 20px; + text-align: center; + + width: 50px; + height: 50px; + border: none; + border-radius: 25px; + + background-color: var(--red); +} + +#goToTop:hover { + box-shadow: 0px 0px 8px 4px rgba(255, 255, 255, 0.4); + cursor: pointer; +} diff --git a/src/css/modal.css b/src/css/modal.css new file mode 100644 index 000000000..53a6ee06b --- /dev/null +++ b/src/css/modal.css @@ -0,0 +1,365 @@ +.modal { + display: none; + position: absolute; + top: 0; + left: 0; +} + +.modal--open { + display: block; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + + background: rgba(0, 0, 0, 0.6); + + z-index: 100; +} + +.modal-backdrop:hover { + cursor: pointer; +} + +.modal-container { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + gap: 0px; + width: 740px; + height: 544px; + + border-radius: 8px; + background-color: rgba(33, 33, 34, 1); + + z-index: 200; +} + +.modal-header { + display: flex; + justify-content: center; + align-items: center; + width: 740px; + height: 60px; + + border-bottom: 1px solid rgba(241, 241, 241, 0.25); +} + +.detail-title { + top: 18px; + left: 32px; + gap: 0px; + + width: 676px; + height: 24px; +} + +.modal-close-button { + width: 36px; + height: 36px; + + border: none; + background-color: transparent; + background-image: url('../images/modal_close_button.png'); +} + +.modal-body { + display: flex; + justify-content: space-between; + align-items: center; + padding: 40px 32px; + gap: 32px; + + width: 740px; + height: 484px; +} + +.detail-poster { + position: fixed; + top: 96px; + left: 32px; + gap: 0px; + + width: 260px; + height: 400px; +} + +.modal-contents { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + position: fixed; + top: 96px; + left: 324px; + + width: 385px; + height: 400px; +} + +.detail-text-container { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + gap: 16px; + margin-bottom: auto; + margin-top: 0; + + width: 100%; +} + +.detail-text-top { + display: flex; + align-items: flex-start; + gap: 16px; + + width: 100%; +} + +.detail-genres { +} + +.detail-vote_average { + display: flex; + align-items: center; + gap: 5px; +} + +.detail-overview { + width: 100%; + max-height: 280px; + overflow-y: auto; +} + +.my-vote { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: auto; + margin-bottom: 0; + position: relative; + + width: 384px; + height: 64px; + + border-radius: 16px; + background-color: rgba(56, 56, 57, 1); +} + +.my-vote-title { + position: absolute; + left: 18px; +} + +.my-vote-body { + display: flex; + gap: 0; + position: absolute; + left: 80px; + + width: 160px; +} + +.my-vote-body button { + padding: 0; + + border: none; + background-color: transparent; +} + +.my-vote-body img { + width: 32px; + height: 32px; +} + +.my-vote-number { + position: absolute; + left: 250px; +} + +.my-vote-description { + position: absolute; + left: 278px; +} + +.detail-text-top.skeleton { + height: 24px; +} +.detail-overview.skeleton { + height: 240px; +} + +.detail-title.skeleton, +.detail-poster.skeleton, +.detail-text-top.skeleton, +.detail-overview.skeleton, +.my-vote.skeleton { + background: linear-gradient(-90deg, var(--gray), var(--light-gray), var(--gray), var(--light-gray)); + background-size: 400%; + animation: skeleton-animation 5s infinite ease-out; + border-radius: 8px; +} + +.detail-text-container.skeleton::after, +.detail-overview.skeleton::after { + font-size: 0; + content: 'loading'; +} + +@keyframes skeleton-animation { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +@media only screen and (max-width: 767px) { + .modal-container { + position: fixed; + top: auto; + bottom: 0; + left: 50%; + transform: translateX(-50%); + gap: 0px; + width: 100%; + height: 485px; + border-radius: 8px; + background-color: rgba(33, 33, 34, 1); + z-index: 200; + } + + .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 0 20px; + width: 100%; + height: 60px; + + border-bottom: 1px solid rgba(241, 241, 241, 0.25); + } + + .detail-title { + top: 18px; + left: 32px; + gap: 0px; + + width: 100%; + height: 24px; + } + + .modal-close-button { + width: 36px; + height: 36px; + + border: none; + background-color: transparent; + background-image: url('../images/modal_close_button.png'); + } + + .modal-body { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px; + gap: 0px; + + width: 100%; + height: 100%; + height: 420px; + } + + .detail-poster { + display: none; + width: 0px; + height: 0px; + } + + .modal-contents { + /* display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + margin-bottom: 36px; + position: fixed; + top: 92px; + left: 20px; + + width: 370px; + height: 232px; */ + + display: flex; + flex-direction: column; + justify-content: normal; + left: 20px; + + width: calc(100% - 40px); + height: calc(100% - 60px); + } + + .detail-text-container { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + gap: 16px; + margin-bottom: 16px; + margin-top: 0; + + width: 100%; + } + + .detail-text-top { + display: flex; + align-items: flex-start; + gap: 16px; + } + + .detail-genres { + } + + .detail-vote_average { + } + + .detail-overview { + height: 240px; + overflow-y: auto; + } + + .my-vote { + width: 100%; + margin-top: 0; + } + + .my-vote-title { + } + + .my-vote-body { + } + + .my-vote-body button { + } + + .my-vote-body img { + width: 32px; + height: 32px; + } + + .my-vote-number { + } + + .my-vote-description { + display: none; + } +} diff --git a/src/css/theme.css b/src/css/theme.css index 133e04bd6..1a1f7ba83 100644 --- a/src/css/theme.css +++ b/src/css/theme.css @@ -1,8 +1,42 @@ +/* Color ******************************************/ :root { - /* color */ --white: #fff; --light-gray: #f0f0f0; --gray: #aaa; --black: #222; --red: #f33f3f; } + +/* Typography *************************************/ +.text-detail-title { + font-size: 20px; + font-weight: 600; + line-height: 24px; + letter-spacing: 0.15px; + text-align: center; +} + +.text-detail-contents { + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.5px; + text-align: left; + color: rgba(241, 241, 241, 1); +} + +.text-detail-vote { + font-size: 16px; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.5px; + text-align: left; +} + +.text-detail-vote-contents { + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.5px; + text-align: center; +} \ No newline at end of file diff --git a/src/custom.d.ts b/src/custom.d.ts new file mode 100644 index 000000000..2c9b5d045 --- /dev/null +++ b/src/custom.d.ts @@ -0,0 +1,5 @@ +declare module '*.png'; +declare module '*.jpg'; +declare module '*.jpeg'; +declare module '*.gif'; +declare module '*.svg'; diff --git a/src/images/modal_close_button.png b/src/images/modal_close_button.png new file mode 100644 index 0000000000000000000000000000000000000000..cbe1b680fd019bc5518f80aac9e818474e2530f9 GIT binary patch literal 856 zcmV-e1E>6nP)L`#><{y}pu3{;clFoMLNRAZBRIz_S(o+~W_R--~ zsmNKPFjYup(QtX^jw2UxAG>!L`z>HOW|xPV+1U?4imKIWW!tu22_dRP!mw@13PD-^ z4()L!L)LUUweax_Hs4Isv{c3yvW5U@;cbf{NI`(@;}5g}b}VHdX8;fbW?#@OQ#x7j z;Xxc&D3DmnR%y0F);OdokpV(4F&^JfvHp~l*>J$^Ye=^(`=zoxEc)XpCTqEq>M9X-2xSYWq9dC z%jfegEP^lNtYx7R!Z^aLyV6Rf(tEU@%5;c>N&~~fLVT?ii=}sH=VUvDL2=@yftev? z#m2_wFK<7iqNwSd494A0!9&GEN}xqgrG;U^F>4vRXTmHi?l2iCDlBBG#nUe@WZP&f z new Promise((resolve) => setTimeout(resolve, ms)); - await delay(2000); } increasePageCount() { diff --git a/src/store/SearchMovieStore.ts b/src/store/SearchMovieStore.ts index 672a1ffae..4c7663234 100644 --- a/src/store/SearchMovieStore.ts +++ b/src/store/SearchMovieStore.ts @@ -1,18 +1,13 @@ import { Movie } from '../index.d'; + import { ERROR_2XX } from '../constants'; import ErrorRender from '../components/ErrorRender'; -const searchOptions = { - method: 'GET', - headers: { - accept: 'application/json', - Authorization: `Bearer ${process.env.TOKEN}`, - }, -}; +import { fetchSearchMovies } from './API'; class SearchMovieStore { - #searchMoviesData: any[]; + #searchMoviesData: Movie[]; #totalPages: number = 0; @@ -24,10 +19,7 @@ class SearchMovieStore { this.#searchMoviesData = []; } - /* eslint-disable max-lines-per-function */ async searchMovies() { - await this.#delay(); // Skeleton UI 확인을 위한 강제 delay - try { const responseData = await this.#fetchSearchData(); const { results } = responseData; @@ -39,29 +31,26 @@ class SearchMovieStore { } } - /* eslint-disable max-lines-per-function */ async #fetchSearchData() { - const response = await fetch( - `https://api.themoviedb.org/3/search/movie?query=${this.#query}&include_adult=false&language=ko&page=${this.#presentPage}`, - searchOptions, - ); + const response = await fetchSearchMovies(this.#query, this.#presentPage); + this.#handleResponseError(response); + + const responseJSON = await response.json(); + this.#handleResponseJSONError(response, responseJSON); + + return responseJSON; + } + #handleResponseError(response: Response) { if (!response.ok) { throw new ErrorRender(String(response.status)).renderError(); } + } - const responseJSON = await response.json(); - + #handleResponseJSONError(response: Response, responseJSON: any) { if (String(response.status)[0] === ERROR_2XX && responseJSON.results.length === 0) { throw new ErrorRender(String(response.status)).renderError(); } - - return responseJSON; - } - - async #delay() { - const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - await delay(2000); } increasePageCount() {