├── README.md ├── public ├── favicon.ico ├── manifest.json └── index.html ├── src ├── index.js ├── App.css ├── components │ ├── Navigation.js │ ├── Navigation.css │ ├── Movie.css │ └── Movie.js ├── routes │ ├── About.js │ ├── Detail.js │ ├── About.css │ ├── Home.css │ └── Home.js └── App.js ├── .gitignore └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # Movie App 2019 2 | 3 | React JS Fundamentals Course (2019 Update!) -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nomadcoders/movie_app_2019/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | 5 | ReactDOM.render(, document.getElementById("potato")); 6 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | margin: 0; 7 | padding: 0; 8 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, 9 | Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 10 | background-color: #eff3f7; 11 | height: 100%; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/Navigation.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import "./Navigation.css"; 4 | 5 | function Navigation() { 6 | return ( 7 |
8 | Home 9 | About 10 |
11 | ); 12 | } 13 | 14 | export default Navigation; 15 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/routes/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./About.css"; 3 | 4 | function About(props) { 5 | console.log(props); 6 | return ( 7 |
8 | 9 | “Freedom is the freedom to say that two plus two make four. If that is 10 | granted, all else follows.” 11 | 12 | − George Orwell, 1984 13 |
14 | ); 15 | } 16 | 17 | export default About; 18 | -------------------------------------------------------------------------------- /src/routes/Detail.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | class Detail extends React.Component { 4 | componentDidMount() { 5 | const { location, history } = this.props; 6 | if (location.state === undefined) { 7 | history.push("/"); 8 | } 9 | } 10 | render() { 11 | const { location } = this.props; 12 | if (location.state) { 13 | return {location.state.title}; 14 | } else { 15 | return null; 16 | } 17 | } 18 | } 19 | export default Detail; 20 | -------------------------------------------------------------------------------- /src/routes/About.css: -------------------------------------------------------------------------------- 1 | .about__container { 2 | box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25), 3 | 0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025); 4 | padding: 20px; 5 | border-radius: 5px; 6 | background-color: white; 7 | margin: 0 auto; 8 | margin-top: 100px; 9 | width: 100%; 10 | max-width: 400px; 11 | font-weight: 300; 12 | } 13 | 14 | .about__container span:first-child { 15 | font-size: 20px; 16 | } 17 | 18 | .about__container span:last-child { 19 | display: block; 20 | margin-top: 10px; 21 | } 22 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { HashRouter, Route } from "react-router-dom"; 3 | import Home from "./routes/Home"; 4 | import About from "./routes/About"; 5 | import Detail from "./routes/Detail"; 6 | import Navigation from "./components/Navigation"; 7 | import "./App.css"; 8 | 9 | function App() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /src/routes/Home.css: -------------------------------------------------------------------------------- 1 | .container { 2 | height: 100%; 3 | display: flex; 4 | justify-content: center; 5 | } 6 | 7 | .loader { 8 | width: 100%; 9 | height: 100vh; 10 | display: flex; 11 | justify-content: center; 12 | align-items: center; 13 | font-weight: 300; 14 | } 15 | 16 | .movies { 17 | display: grid; 18 | grid-template-columns: repeat(2, minmax(400px, 1fr)); 19 | grid-gap: 100px; 20 | padding: 50px; 21 | width: 80%; 22 | padding-top: 70px; 23 | } 24 | 25 | @media screen and (max-width: 1090px) { 26 | .movies { 27 | grid-template-columns: 1fr; 28 | width: 100%; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/components/Navigation.css: -------------------------------------------------------------------------------- 1 | .nav { 2 | z-index: 1; 3 | position: fixed; 4 | top: 50px; 5 | left: 10px; 6 | display: flex; 7 | flex-direction: column; 8 | background-color: white; 9 | padding: 10px 20px; 10 | box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25), 11 | 0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025); 12 | border-radius: 5px; 13 | } 14 | 15 | @media screen and (max-width: 1090px) { 16 | .nav { 17 | left: initial; 18 | top: initial; 19 | bottom: 0px; 20 | width: 100%; 21 | } 22 | } 23 | 24 | .nav a { 25 | text-decoration: none; 26 | color: #0008fc; 27 | text-transform: uppercase; 28 | font-size: 12px; 29 | text-align: center; 30 | font-weight: 600; 31 | } 32 | 33 | .nav a:not(:last-child) { 34 | margin-bottom: 20px; 35 | } 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "movie_app_2019", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "axios": "^0.19.0", 7 | "gh-pages": "^2.0.1", 8 | "prop-types": "^15.7.2", 9 | "react": "^16.8.6", 10 | "react-dom": "^16.8.6", 11 | "react-router-dom": "^5.1.2", 12 | "react-scripts": "3.0.1" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "deploy": "gh-pages -d build", 18 | "predeploy": "npm run build" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | }, 35 | "homepage": "https://nomadcoders.github.io/movie_app_2019/" 36 | } 37 | -------------------------------------------------------------------------------- /src/components/Movie.css: -------------------------------------------------------------------------------- 1 | .movies .movie { 2 | background-color: white; 3 | margin-bottom: 70px; 4 | font-weight: 300; 5 | padding: 20px; 6 | border-radius: 5px; 7 | color: #adaeb9; 8 | box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25), 9 | 0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025); 10 | } 11 | 12 | .movies .movie a { 13 | display: grid; 14 | grid-template-columns: minmax(150px, 1fr) 2fr; 15 | grid-gap: 20px; 16 | text-decoration: none; 17 | color: inherit; 18 | } 19 | 20 | .movie img { 21 | position: relative; 22 | top: -50px; 23 | max-width: 150px; 24 | width: 100%; 25 | margin-right: 30px; 26 | box-shadow: 0 30px 60px -12px rgba(50, 50, 93, 0.25), 27 | 0 18px 36px -18px rgba(0, 0, 0, 0.3), 0 -12px 36px -8px rgba(0, 0, 0, 0.025); 28 | } 29 | 30 | .movie .movie__title, 31 | .movie .movie__year { 32 | margin: 0; 33 | font-weight: 300; 34 | } 35 | 36 | .movie .movie__title { 37 | margin-bottom: 5px; 38 | font-size: 24px; 39 | color: #2c2c2c; 40 | } 41 | 42 | .movie .movie__genres { 43 | list-style: none; 44 | padding: 0; 45 | margin: 0; 46 | display: flex; 47 | flex-wrap: wrap; 48 | margin: 5px 0px; 49 | } 50 | 51 | .movie__genres li, 52 | .movie .movie__year { 53 | margin-right: 10px; 54 | font-size: 14px; 55 | } 56 | -------------------------------------------------------------------------------- /src/routes/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import axios from "axios"; 3 | import Movie from "../components/Movie"; 4 | import "./Home.css"; 5 | 6 | class Home extends React.Component { 7 | state = { 8 | isLoading: true, 9 | movies: [] 10 | }; 11 | getMovies = async () => { 12 | const { 13 | data: { 14 | data: { movies } 15 | } 16 | } = await axios.get( 17 | "https://yts-proxy.now.sh/list_movies.json?sort_by=rating" 18 | ); 19 | this.setState({ movies, isLoading: false }); 20 | }; 21 | componentDidMount() { 22 | this.getMovies(); 23 | } 24 | render() { 25 | const { isLoading, movies } = this.state; 26 | return ( 27 |
28 | {isLoading ? ( 29 |
30 | Loading... 31 |
32 | ) : ( 33 |
34 | {movies.map(movie => ( 35 | 44 | ))} 45 |
46 | )} 47 |
48 | ); 49 | } 50 | } 51 | 52 | export default Home; 53 | -------------------------------------------------------------------------------- /src/components/Movie.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import PropTypes from "prop-types"; 4 | import "./Movie.css"; 5 | 6 | function Movie({ id, year, title, summary, poster, genres }) { 7 | return ( 8 |
9 | 21 | {title} 22 |
23 |

{title}

24 |
{year}
25 |
    26 | {genres.map((genre, index) => ( 27 |
  • 28 | {genre} 29 |
  • 30 | ))} 31 |
32 |

{summary.slice(0, 180)}...

33 |
34 | 35 |
36 | ); 37 | } 38 | 39 | Movie.propTypes = { 40 | id: PropTypes.number.isRequired, 41 | year: PropTypes.number.isRequired, 42 | title: PropTypes.string.isRequired, 43 | summary: PropTypes.string.isRequired, 44 | poster: PropTypes.string.isRequired, 45 | genres: PropTypes.arrayOf(PropTypes.string).isRequired 46 | }; 47 | 48 | export default Movie; 49 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | Movie App 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | --------------------------------------------------------------------------------