├── README.md ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── src ├── index.js ├── components │ ├── MovieListHeading.js │ ├── SearchBox.js │ ├── AddFavourites.js │ ├── MovieList.js │ └── RemoveFavourites.js ├── App.css └── App.js ├── .gitignore └── package.json /README.md: -------------------------------------------------------------------------------- 1 | Source code for https://www.youtube.com/watch?v=jc9_Bqzy2YQ&feature=youtu.be 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisblakely01/react-movie-app/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisblakely01/react-movie-app/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisblakely01/react-movie-app/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/MovieListHeading.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const MovieListHeading = (props) => { 4 | return ( 5 |
6 |

{props.heading}

7 |
8 | ); 9 | }; 10 | 11 | export default MovieListHeading; 12 | -------------------------------------------------------------------------------- /src/components/SearchBox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SearchBox = (props) => { 4 | return ( 5 |
6 | props.setSearchValue(event.target.value)} 10 | placeholder='Type to search...' 11 | > 12 |
13 | ); 14 | }; 15 | 16 | export default SearchBox; 17 | -------------------------------------------------------------------------------- /.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/components/AddFavourites.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const AddFavourite = () => { 4 | return ( 5 | <> 6 | Add to Favourites 7 | 15 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default AddFavourite; 25 | -------------------------------------------------------------------------------- /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 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #141414; 3 | color: #ffffff; 4 | } 5 | 6 | .movie-app > .row { 7 | overflow-x: auto; 8 | flex-wrap: nowrap; 9 | } 10 | 11 | .image-container { 12 | position: relative; 13 | transition: transform 0.2s; 14 | } 15 | 16 | .image-container:hover { 17 | cursor: pointer; 18 | transform: scale(1.1); 19 | } 20 | 21 | .image-container:hover .overlay { 22 | opacity: 1; 23 | } 24 | 25 | .overlay { 26 | position: absolute; 27 | background: rgba(0, 0, 0, 0.8); 28 | width: 100%; 29 | transition: 0.5s ease; 30 | opacity: 0; 31 | bottom: 0; 32 | font-size: 20px; 33 | padding: 20px; 34 | text-align: center; 35 | } 36 | -------------------------------------------------------------------------------- /src/components/MovieList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const MovieList = (props) => { 4 | const FavouriteComponent = props.favouriteComponent; 5 | 6 | return ( 7 | <> 8 | {props.movies.map((movie, index) => ( 9 |
10 | movie 11 |
props.handleFavouritesClick(movie)} 13 | className='overlay d-flex align-items-center justify-content-center' 14 | > 15 | 16 |
17 |
18 | ))} 19 | 20 | ); 21 | }; 22 | 23 | export default MovieList; 24 | -------------------------------------------------------------------------------- /src/components/RemoveFavourites.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const RemoveFavourites = () => { 4 | return ( 5 | <> 6 | Remove from favourites 7 | 15 | 19 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default RemoveFavourites; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "movie-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "bootstrap": "^4.5.3", 10 | "react": "^17.0.1", 11 | "react-dom": "^17.0.1", 12 | "react-scripts": "4.0.0", 13 | "web-vitals": "^0.2.4" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import 'bootstrap/dist/css/bootstrap.min.css'; 3 | import './App.css'; 4 | import MovieList from './components/MovieList'; 5 | import MovieListHeading from './components/MovieListHeading'; 6 | import SearchBox from './components/SearchBox'; 7 | import AddFavourites from './components/AddFavourites'; 8 | import RemoveFavourites from './components/RemoveFavourites'; 9 | 10 | const App = () => { 11 | const [movies, setMovies] = useState([]); 12 | const [favourites, setFavourites] = useState([]); 13 | const [searchValue, setSearchValue] = useState(''); 14 | 15 | const getMovieRequest = async (searchValue) => { 16 | const url = `http://www.omdbapi.com/?s=${searchValue}&apikey=263d22d8`; 17 | 18 | const response = await fetch(url); 19 | const responseJson = await response.json(); 20 | 21 | if (responseJson.Search) { 22 | setMovies(responseJson.Search); 23 | } 24 | }; 25 | 26 | useEffect(() => { 27 | getMovieRequest(searchValue); 28 | }, [searchValue]); 29 | 30 | useEffect(() => { 31 | const movieFavourites = JSON.parse( 32 | localStorage.getItem('react-movie-app-favourites') 33 | ); 34 | 35 | if (movieFavourites) { 36 | setFavourites(movieFavourites); 37 | } 38 | }, []); 39 | 40 | const saveToLocalStorage = (items) => { 41 | localStorage.setItem('react-movie-app-favourites', JSON.stringify(items)); 42 | }; 43 | 44 | const addFavouriteMovie = (movie) => { 45 | const newFavouriteList = [...favourites, movie]; 46 | setFavourites(newFavouriteList); 47 | saveToLocalStorage(newFavouriteList); 48 | }; 49 | 50 | const removeFavouriteMovie = (movie) => { 51 | const newFavouriteList = favourites.filter( 52 | (favourite) => favourite.imdbID !== movie.imdbID 53 | ); 54 | 55 | setFavourites(newFavouriteList); 56 | saveToLocalStorage(newFavouriteList); 57 | }; 58 | 59 | return ( 60 |
61 |
62 | 63 | 64 |
65 |
66 | 71 |
72 |
73 | 74 |
75 |
76 | 81 |
82 |
83 | ); 84 | }; 85 | 86 | export default App; 87 | --------------------------------------------------------------------------------