diff --git a/react/netflix-app/src/App.css b/react/netflix-app/src/App.css index e69de29b..58e979f7 100644 --- a/react/netflix-app/src/App.css +++ b/react/netflix-app/src/App.css @@ -0,0 +1,6 @@ +* { + margin: 0; +} +.app { + background: #111; +} diff --git a/react/netflix-app/src/App.js b/react/netflix-app/src/App.js index 4851b3e8..6a1be2ca 100644 --- a/react/netflix-app/src/App.js +++ b/react/netflix-app/src/App.js @@ -1,12 +1,36 @@ +import requests from "./api/requests"; import "./App.css"; import Banner from "./components/Banner"; +import Footer from "./components/Footer"; import Nav from "./components/Nav"; +import Row from "./components/Row"; const App = () => { return ( -
+
); }; diff --git a/react/netflix-app/src/components/Footer.js b/react/netflix-app/src/components/Footer.js index e69de29b..c8d9139a 100644 --- a/react/netflix-app/src/components/Footer.js +++ b/react/netflix-app/src/components/Footer.js @@ -0,0 +1,107 @@ +import React from "react"; +import styled from "styled-components"; + +const Footer = () => { + return ( + + + + 넷플릭스 대한민국 + + + + 넷플릭스 소개 + + + 고객 센터 + + + 미디어 센터 + + + 이용 약관 + + + + + @ Netflix Rights Reserved. + + + + + ); +}; + +const FooterContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + padding: 40px 0; + border-top: 1px solid rgb(25, 25, 25); + width: 100%; + position: relative; + z-index: 100; + + @media (max-width: 768px) { + padding: 20px 20px; + padding-bottom: 30px; + } +`; + +const FooterContent = styled.div``; + +const FooterLinkContainer = styled.div` + width: 500px; + + @media (max-width: 768px) { + width: 100%; + } +`; + +const FooterLinkTitle = styled.h1` + color: gray; + font-size: 17px; +`; + +const FooterLinkContent = styled.div` + display: flex; + justify-content: space-between; + flex-wrap: wrap; + margin-top: 35px; + + @media (max-width: 768px) { + margin-top: 26px; + } +`; + +const FooterLink = styled.a` + color: gray; + font-size: 14px; + width: 110px; + margin-bottom: 21px; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + + @media (max-width: 768px) { + margin-bottom: 16px; + } +`; + +const FooterDescContainer = styled.div` + margin-top: 30px; + + @media (max-width: 768px) { + margin-top: 20px; + } +`; + +const FooterDescRights = styled.h2` + color: white; + font-size: 14px; + text-align: center; +`; + +export default Footer; diff --git a/react/netflix-app/src/components/Nav.css b/react/netflix-app/src/components/Nav.css index 9280cc6c..398c5924 100644 --- a/react/netflix-app/src/components/Nav.css +++ b/react/netflix-app/src/components/Nav.css @@ -29,3 +29,14 @@ width: 30px; object-fit: contain; } + +.nav__input { + position: fixed; + left: 50%; + transform: translate(-50%, 0); + background-color: rgba(0, 0, 0, 0.582); + border-radius: 5px; + color: white; + padding: 5px; + border: none; +} diff --git a/react/netflix-app/src/components/Row.css b/react/netflix-app/src/components/Row.css index e69de29b..fc9abc7e 100644 --- a/react/netflix-app/src/components/Row.css +++ b/react/netflix-app/src/components/Row.css @@ -0,0 +1,160 @@ +.row { + margin-left: 20px; + color: white; +} +h2 { + padding-left: 20px; +} +.slider { + position: relative; +} +.slider__arrow-left { + background-clip: content-box; + padding: 20px 0; + box-sizing: border-box; + transition: 400ms all ease-in-out; + cursor: pointer; + width: 80px; + z-index: 1000; + position: absolute; + left: 0; + top: 0; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + visibility: hidden; +} +.slider__arrow-right { + padding: 20px 0; + background-clip: content-box; + box-sizing: border-box; + transition: 400ms all ease-in-out; + cursor: pointer; + width: 80px; + z-index: 1000; + position: absolute; + right: 0; + top: 0; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + visibility: hidden; +} +.arrow { + transition: 400ms all ease-in-out; +} +.arrow:hover { + transition: 400ms all ease-in-out; + transform: scale(1.5); +} +.slider:hover .slider__arrow-left { + transition: 400ms all ease-in-out; + visibility: visible; +} +.slider:hover .slider__arrow-right { + transition: 400ms all ease-in-out; + visibility: visible; +} +.slider__arrow-left:hover { + background: rgba(20, 20, 20, 0.5); + transition: 400ms all ease-in-out; +} +.slider__arrow-right:hover { + background: rgba(20, 20, 20, 0.5); + transition: 400ms all ease-in-out; +} + +.row__posters { + display: flex; + overflow-y: hidden; + overflow-x: scroll; + padding: 20px 0 20px 20px; + scroll-behavior: smooth; +} +.row__posters::-webkit-scrollbar { + display: none; +} +.row__poster { + object-fit: contain; + width: 100%; + max-height: 144px; + margin-right: 10px; + transition: transform 450ms; + border-radius: 4px; +} +.row__poster:hover { + transform: scale(1.08); +} +.row__posterLarge { + max-height: 320px; +} +.row__posterLarge:hover { + transform: scale(1.1); + opacity: 1; +} + +.row__arrow-left { + position: absolute; + top: 0; + left: 20px; + height: 100%; + width: 32px; + background: rgba(0, 0, 0, 0.2); + display: flex; + align-items: center; +} +.row__arrow-right { + position: absolute; + top: 0; + right: 0px; + height: 100%; + width: 32px; + background: rgba(0, 0, 0, 0.2); + display: flex; + align-items: center; +} +@media screen and (min-width: 1200px) { + .row__poster { + max-height: 160px; + } + .row__posterLarge { + max-height: 360px; + } +} +@media screen and (max-width: 768px) { + .row__poster { + max-height: 100px; + } + .row__posterLarge { + max-height: 280px; + } +} + +.swiper-pagination { + text-align: right !important; +} + +.swiper-pagination-bullet { + background: gray !important; + opacity: 1 !important; +} + +.swiper-pagination-bullet-active { + background: white !important; +} + +.swiper-button-prev { + color: white !important; +} + +.swiper-button-next { + color: white !important; +} + +.swiper-button-next:after, +.swiper-button-prev:after { + font-size: 1.3rem !important; + font-weight: 600 !important; +} diff --git a/react/netflix-app/src/components/Row.js b/react/netflix-app/src/components/Row.js index e69de29b..4bba40c5 100644 --- a/react/netflix-app/src/components/Row.js +++ b/react/netflix-app/src/components/Row.js @@ -0,0 +1,70 @@ +import axios from "../api/axios"; +import React, { useEffect, useState } from "react"; +import "./Row.css"; +import MovieModal from "./modal"; + +const Row = ({ title, id, fetchUrl, isLargeRow }) => { + const [movies, setMovies] = useState([]); + const [modalOpen, setModalOpen] = useState(false); + const [movieSelected, setMovieSelected] = useState({}); + + useEffect(() => { + fetchMovieData(); + }, []); + + const fetchMovieData = async () => { + const request = await axios.get(fetchUrl); + + setMovies(request.data.results); + }; + + const handleClick = (movie) => { + setModalOpen(true); + setMovieSelected(movie); + }; + + return ( +
+

{title}

+
+
{ + document.getElementById(id).scrollLeft -= window.innerWidth - 80; + }} + > + {"<"} +
+ +
+ {movies.map((movie) => ( + {movie.name} handleClick(movie)} + /> + ))} +
+ +
{ + document.getElementById(id).scrollLeft += window.innerWidth - 80; + }} + > + {">"} +
+
+ + {modalOpen && ( + + )} +
+ ); +}; + +export default Row; diff --git a/react/netflix-app/src/components/modal/MovieModal.css b/react/netflix-app/src/components/modal/MovieModal.css new file mode 100644 index 00000000..f59225ce --- /dev/null +++ b/react/netflix-app/src/components/modal/MovieModal.css @@ -0,0 +1,98 @@ +.modal { + position: relative; + max-width: 800px; + box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), + 0px 5px 8px 0px rgba(0, 0, 0, 0.14), 0px 1px 14px 0px rgba(0, 0, 0, 0.12); + background: #111; + overflow: hidden; + border-radius: 8px; + transition: all 400ms ease-in-out 2s; + animation: fadeIn 400ms; +} +.modal__poster-img { + width: 100%; + height: auto; +} +.modal__content { + padding: 40px; + color: white; +} +.modal__title { + padding: 0; + font-size: 40px; + margin: 16px 0; +} +.modal__details { + font-weight: 600; + font-size: 18px; +} +.modal__overview { + font-size: 20px; + line-height: 1.5; +} +.modal__user-perc { + color: #46d369; +} +.modal::-webkit-scrollbar { + display: none; + visibility: hidden; +} + +/* Hide scrollbar for IE, Edge and Firefox */ +.modal { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ +} +.wrapper-modal { + position: fixed; + inset: 0px; + background-color: rgb(0 0 0 / 71%); + -webkit-tap-highlight-color: transparent; + display: flex; + justify-content: center; +} +.presentation { + z-index: 1200; + position: absolute; +} +.modal-close { + position: absolute; + right: 20px; + top: 20px; + cursor: pointer; + z-index: 1000; + color: white; +} +@media screen and (max-height: 768px) { + .wrapper-modal { + align-items: unset; + padding-top: 2rem; + } + .modal { + overflow-y: scroll; + } +} +@media screen and (max-width: 768px) { + .modal__overview { + font-size: 16px; + } + .modal__details { + font-size: 16px; + } + .wrapper-modal { + padding: 0; + } + .modal { + overflow-y: scroll !important; + } +} +@keyframes fadeIn { + from { + opacity: 0; + transform: scale(0.5); + } + to { + opacity: 1; + transform: scale(1); + } +} diff --git a/react/netflix-app/src/components/modal/index.js b/react/netflix-app/src/components/modal/index.js new file mode 100644 index 00000000..bf827512 --- /dev/null +++ b/react/netflix-app/src/components/modal/index.js @@ -0,0 +1,45 @@ +import React from "react"; +import "./MovieModal.css"; + +const MovieModal = ({ + backdrop_path, + title, + overview, + name, + release_date, + first_air_date, + vote_averate, + setModalOpen, +}) => { + return ( +
+
+
+ setModalOpen(false)}> + X + + + modal__poster-img + +
+

+ 100% for you + + {release_date ? release_date : first_air_date} +

+ +

{title ? title : name}

+

평점 : {vote_averate}

+

{overview}

+
+
+
+
+ ); +}; + +export default MovieModal; diff --git a/react/netflix-app/src/index.css b/react/netflix-app/src/index.css index ea1e941c..4a1df4db 100644 --- a/react/netflix-app/src/index.css +++ b/react/netflix-app/src/index.css @@ -1,4 +1,13 @@ body { margin: 0; - padding: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; }