├── 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 |
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 |

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 |
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 |
--------------------------------------------------------------------------------