Archived
new merge
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
client/dist/
|
||||||
|
node_modules/
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"commonjs": true,
|
||||||
|
"es6": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react",
|
||||||
|
"react-hooks"
|
||||||
|
],
|
||||||
|
"extends": ["eslint:recommended", "plugin:react/recommended", "plugin:prettier/recommended"],
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "module",
|
||||||
|
"ecmaVersion": 2018
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"linebreak-style": ["error", "unix"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package-lock.json
|
||||||
|
.next
|
||||||
|
node_modules/
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
@@ -11,6 +11,11 @@ This project is a simplified front end clone of Netflix. It was created with Rea
|
|||||||
- Sass (grid & flexbox)
|
- Sass (grid & flexbox)
|
||||||
- Media queries
|
- Media queries
|
||||||
|
|
||||||
|
### Runing Project Locally
|
||||||
|
- Install dependencies: run `npm install` in root project
|
||||||
|
- Get API key from [here](https://www.themoviedb.org/documentation/api)
|
||||||
|
- Create .env file in root project and add: `API_KEY=YOUR_API_KEY_HERE`
|
||||||
|
- Run project: `npm run dev`
|
||||||
|
|
||||||
### User Stories:
|
### User Stories:
|
||||||
|
|
||||||
@@ -27,3 +32,4 @@ This project is a simplified front end clone of Netflix. It was created with Rea
|
|||||||
|
|
||||||
|
|
||||||
Please feel free to create a pull request and submit any issues!
|
Please feel free to create a pull request and submit any issues!
|
||||||
|
Currently looking for backend developers. If you would to contribute to support a backend, reach out, all ideas are welcomed!
|
||||||
Generated
+5183
-2189
File diff suppressed because it is too large
Load Diff
+22
-8
@@ -4,17 +4,20 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack-dev-server --open --mode development",
|
"dev": "webpack-dev-server --mode development --config webpack.config.js --open",
|
||||||
"build": "webpack -p"
|
"build": "webpack -p",
|
||||||
|
"lint": "eslint --fix . && echo 'Lint complete.'"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "10.1.0",
|
"node": "10.1.0",
|
||||||
"npm": "6.4.1"
|
"npm": "6.4.1",
|
||||||
|
"watch": "watch 'clear && npm run -s test | tap-nirvana && npm run -s lint' src"
|
||||||
},
|
},
|
||||||
"author": "Andres Alcocer",
|
"author": "Andres Alcocer",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.1",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.6.1",
|
"react": "^16.6.1",
|
||||||
"react-dom": "^16.6.1",
|
"react-dom": "^16.6.1",
|
||||||
@@ -38,21 +41,32 @@
|
|||||||
"copy-webpack-plugin": "^4.6.0",
|
"copy-webpack-plugin": "^4.6.0",
|
||||||
"css-loader": "^1.0.1",
|
"css-loader": "^1.0.1",
|
||||||
"dotenv": "^6.2.0",
|
"dotenv": "^6.2.0",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-config-airbnb": "^18.1.0",
|
||||||
|
"eslint-config-prettier": "^6.11.0",
|
||||||
|
"eslint-plugin-import": "^2.20.2",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
|
"eslint-plugin-prettier": "^3.1.3",
|
||||||
|
"eslint-plugin-react": "^7.20.0",
|
||||||
|
"eslint-plugin-react-hooks": "^2.5.1",
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"file-loader": "^2.0.0",
|
"file-loader": "^2.0.0",
|
||||||
"html-loader": "^0.5.5",
|
"html-loader": "^0.5.5",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"image-webpack-loader": "^4.5.0",
|
"image-webpack-loader": "^4.5.0",
|
||||||
"mini-css-extract-plugin": "^0.4.4",
|
"mini-css-extract-plugin": "^0.4.4",
|
||||||
"node-sass": "^4.10.0",
|
"node-sass": "^4.14.1",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||||
|
"prettier": "^2.0.5",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"style-loader": "^0.23.1",
|
"style-loader": "^0.23.1",
|
||||||
"svg-inline-loader": "^0.8.0",
|
"svg-inline-loader": "^0.8.0",
|
||||||
"svg-react-loader": "^0.4.6",
|
"svg-react-loader": "^0.4.6",
|
||||||
|
"tap-nirvana": "^1.1.0",
|
||||||
"uglifyjs-webpack-plugin": "^2.0.1",
|
"uglifyjs-webpack-plugin": "^2.0.1",
|
||||||
"webpack": "^4.25.1",
|
"watch": "^1.0.2",
|
||||||
"webpack-cli": "^3.1.2",
|
"webpack": "^4.43.0",
|
||||||
"webpack-dev-server": "^3.1.10"
|
"webpack-cli": "^3.3.12",
|
||||||
|
"webpack-dev-server": "^3.11.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import axios from 'axios';
|
|||||||
|
|
||||||
/** base url to make requests to the the movie database */
|
/** base url to make requests to the the movie database */
|
||||||
const instance = axios.create({
|
const instance = axios.create({
|
||||||
baseURL: "https://api.themoviedb.org/3"
|
baseURL: 'https://api.themoviedb.org/3',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default instance;
|
export default instance;
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
|
||||||
const dropdownContent = () => (
|
const dropdownContent = () => (
|
||||||
|
|
||||||
<div className="dropdownContainer">
|
<div className="dropdownContainer">
|
||||||
<div className="navigation__container--userLogo">
|
<div className="navigation__container--userLogo">
|
||||||
<div className="dropdownContent">
|
<div className="dropdownContent">
|
||||||
@@ -19,7 +17,6 @@ const dropdownContent = () => (
|
|||||||
<p className="dropdownContent--user-text">Luis</p>
|
<p className="dropdownContent--user-text">Luis</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="dropdownContent-text">Manage Profiles</p>
|
<p className="dropdownContent-text">Manage Profiles</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdownContent dropdownContent--2">
|
<div className="dropdownContent dropdownContent--2">
|
||||||
<p className="dropdownContent-textOutside">Account</p>
|
<p className="dropdownContent-textOutside">Account</p>
|
||||||
@@ -31,4 +28,3 @@ const dropdownContent = () => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default dropdownContent;
|
export default dropdownContent;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const footer = () => (
|
const footer = () => (
|
||||||
|
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<div className="footer__copyright">
|
<div className="footer__copyright">
|
||||||
© 2018 Made with ❤️ by <a className="footer__copyright--link" href="http://andresio.com"> Andres Alcocer</a></div>
|
© 2018 Made with ❤️ by{' '}
|
||||||
|
<a className="footer__copyright--link" href="http://andresio.com">
|
||||||
|
{' '}
|
||||||
|
Andres Alcocer
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -3,19 +3,21 @@ import React from 'react';
|
|||||||
import PlayLogo from '../static/images/play-button.svg';
|
import PlayLogo from '../static/images/play-button.svg';
|
||||||
import AddLogo from '../static/images/add.svg';
|
import AddLogo from '../static/images/add.svg';
|
||||||
|
|
||||||
|
|
||||||
export default function Header(props) {
|
export default function Header(props) {
|
||||||
const backgroundStyle = {
|
const backgroundStyle = {
|
||||||
backgroundSize: "cover",
|
backgroundSize: 'cover',
|
||||||
backgroundImage: `url(https://image.tmdb.org/t/p/original/${props.movie.backdrop_path})`,
|
backgroundImage: `url(https://image.tmdb.org/t/p/original/${props.movie.backdrop_path})`,
|
||||||
backgroundPosition: "center",
|
backgroundPosition: 'center',
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header style={backgroundStyle} className="header">
|
<header style={backgroundStyle} className="header">
|
||||||
<div className="header__container">
|
<div className="header__container">
|
||||||
<h1 className="header__container-heading">{props.movie.name}</h1>
|
<h1 className="header__container-heading">{props.movie.name}</h1>
|
||||||
<button onClick={() => alert("not a movie!")} className="header__container-btnPlay">
|
<button
|
||||||
|
onClick={() => alert('not a movie!')}
|
||||||
|
className="header__container-btnPlay"
|
||||||
|
>
|
||||||
<PlayLogo className="header__container-btnMyList-play" />
|
<PlayLogo className="header__container-btnMyList-play" />
|
||||||
Play
|
Play
|
||||||
</button>
|
</button>
|
||||||
@@ -28,5 +30,5 @@ export default function Header(props) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="header--fadeBottom"></div>
|
<div className="header--fadeBottom"></div>
|
||||||
</header>
|
</header>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@@ -13,13 +13,18 @@ export default function MovieDetails(props) {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className="modal__info">
|
<p className="modal__info">
|
||||||
<span className="modal__rating">
|
<span className="modal__rating">
|
||||||
Rating: {props.movie.vote_average * 10}%{" "}
|
Rating: {props.movie.vote_average * 10}%{' '}
|
||||||
</span>
|
</span>
|
||||||
Release date: {props.movie.release_date || props.movie.first_air_date} Runtime: {props.movie.runtime || props.movie.episode_run_time}m
|
Release date: {props.movie.release_date || props.movie.first_air_date}{' '}
|
||||||
|
Runtime: {props.movie.runtime || props.movie.episode_run_time}m
|
||||||
</p>
|
</p>
|
||||||
<p className="modal__episode">
|
<p className="modal__episode">
|
||||||
{props.movie.number_of_episodes ? " Episodes: " + props.movie.number_of_episodes : ""}
|
{props.movie.number_of_episodes
|
||||||
{props.movie.number_of_seasons ? " Seasons: " + props.movie.number_of_seasons : ""}
|
? ' Episodes: ' + props.movie.number_of_episodes
|
||||||
|
: ''}
|
||||||
|
{props.movie.number_of_seasons
|
||||||
|
? ' Seasons: ' + props.movie.number_of_seasons
|
||||||
|
: ''}
|
||||||
</p>
|
</p>
|
||||||
<p className="modal__overview">{props.movie.overview}</p>
|
<p className="modal__overview">{props.movie.overview}</p>
|
||||||
<button className="modal__btn modal__btn--red">
|
<button className="modal__btn modal__btn--red">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default class MovieGenre extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let netflixUrl = false;
|
let netflixUrl = false;
|
||||||
if (this.props.url === "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
if (this.props.url === `/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`) {
|
||||||
netflixUrl = true;
|
netflixUrl = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
|
|
||||||
export default function MovieGenreImage(props) {
|
export default function MovieGenreImage(props) {
|
||||||
let netflixUrl = false;
|
let netflixUrl = false;
|
||||||
|
|
||||||
if (props.url === "https://api.themoviedb.org/3/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
if (
|
||||||
|
props.url ===
|
||||||
|
`https://api.themoviedb.org/3/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`
|
||||||
|
) {
|
||||||
netflixUrl = true;
|
netflixUrl = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={props.movieDetailsModal}
|
<div
|
||||||
className={"movieShowcase__container--movie" + (netflixUrl ? "__netflix" : "")}>
|
onClick={props.movieDetailsModal}
|
||||||
<img src={props.posterUrl} className="movieShowcase__container--movie-image" />
|
className={
|
||||||
|
'movieShowcase__container--movie' + (netflixUrl ? '__netflix' : '')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={props.posterUrl}
|
||||||
|
className="movieShowcase__container--movie-image"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
import React from 'react';
|
// import React from 'react';
|
||||||
import { NavLink } from 'react-router-dom';
|
// import { NavLink } from 'react-router-dom';
|
||||||
|
|
||||||
const navigationItem = (props) => (
|
// const navigationItem = (props) => (
|
||||||
<NavLink className="navigation__container-link" exact={props.exact}
|
// <NavLink
|
||||||
to={props.link}>{props.children}</NavLink>
|
// // className="navigation__container-link"
|
||||||
)
|
// exact={props.exact}
|
||||||
|
// to={props.link}
|
||||||
|
// >
|
||||||
|
// {props.children}
|
||||||
|
// </NavLink>
|
||||||
|
// );
|
||||||
|
|
||||||
export default navigationItem;
|
// export default navigationItem;
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const backdrop = (props) => (
|
const backdrop = (props) =>
|
||||||
props.show ? <div
|
props.show ? (
|
||||||
onClick={props.toggleBackdrop}
|
<div onClick={props.toggleBackdrop} className="backdrop"></div>
|
||||||
className="backdrop"></div> : null
|
) : null;
|
||||||
);
|
|
||||||
|
|
||||||
export default backdrop;
|
export default backdrop;
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
|
|
||||||
import Aux from '../../hoc/Aux';
|
import Aux from '../../hoc/Aux';
|
||||||
import Backdrop from './Backdrop'
|
import Backdrop from './Backdrop';
|
||||||
|
|
||||||
|
|
||||||
export default function Modal(props) {
|
export default function Modal(props) {
|
||||||
const backgroundStyle = {
|
const backgroundStyle = {
|
||||||
backgroundSize: "cover",
|
backgroundSize: 'cover',
|
||||||
backgroundImage: `url(https://image.tmdb.org/t/p/original/${props.movie.backdrop_path || props.movie.poster_path})`,
|
backgroundImage: `url(https://image.tmdb.org/t/p/original/${
|
||||||
}
|
props.movie.backdrop_path || props.movie.poster_path
|
||||||
|
})`,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Aux>
|
<Aux>
|
||||||
<Backdrop show={props.show} toggleBackdrop={props.modalClosed} />
|
<Backdrop show={props.show} toggleBackdrop={props.modalClosed} />
|
||||||
<div
|
<div
|
||||||
style={backgroundStyle}
|
style={backgroundStyle}
|
||||||
className={(props.show ? "modal show" : "modal hide")}>
|
className={props.show ? 'modal show' : 'modal hide'}
|
||||||
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
</Aux>
|
</Aux>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,38 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { fetchActionMovies } from '../store/actions/index';
|
import { fetchActionMovies } from '../store/actions/index';
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
|
|
||||||
class ActionMovies extends Component {
|
class ActionMovies extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchActionMovies();
|
this.props.fetchActionMovies();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.actionMovies.data) {
|
if (this.props.actionMovies.data) {
|
||||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=28";
|
const url = `/discover/movie?api_key=${process.env.API_KEY}&with_genres=28`;
|
||||||
movies = getMovieRows(this.props.actionMovies.data, url);
|
movies = getMovieRows(this.props.actionMovies.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Action Movies</h1>
|
<h1 className="movieShowcase__heading">Action Movies</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { actionMovies: state.action }
|
return { actionMovies: state.action };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchActionMovies }, dispatch)
|
return bindActionCreators({ fetchActionMovies }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ActionMovies);
|
export default connect(mapStateToProps, mapDispatchToProps)(ActionMovies);
|
||||||
+3
-12
@@ -1,14 +1,5 @@
|
|||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import Layout from './Layout';
|
import AppRouter from './AppRouter';
|
||||||
|
|
||||||
|
|
||||||
class App extends Component {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Layout />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const App = () => <AppRouter />;
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
|
import Home from './Home';
|
||||||
|
import NotFound from './NotFound';
|
||||||
|
import Search from './Search';
|
||||||
|
import Navbar from './Navbar';
|
||||||
|
|
||||||
|
const AppRouter = () => (
|
||||||
|
<BrowserRouter>
|
||||||
|
<>
|
||||||
|
<Navbar />
|
||||||
|
<Switch>
|
||||||
|
<Route path="/" exact component={Home} />
|
||||||
|
<Route path="/search" component={Search} />
|
||||||
|
<Route component={NotFound} />
|
||||||
|
</Switch>
|
||||||
|
</>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default AppRouter;
|
||||||
@@ -1,42 +1,38 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
import { fetchComedyMovies } from '../store/actions/index';
|
import { fetchComedyMovies } from '../store/actions/index';
|
||||||
|
|
||||||
class ComedyMovies extends Component {
|
class ComedyMovies extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchComedyMovies();
|
this.props.fetchComedyMovies();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.movies.data) {
|
if (this.props.movies.data) {
|
||||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=35';
|
const url = `/discover/tv?api_key=${process.env.API_KEY}&with_genres=35`;
|
||||||
movies = getMovieRows(this.props.movies.data, url);
|
movies = getMovieRows(this.props.movies.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Comedy Movies</h1>
|
<h1 className="movieShowcase__heading">Comedy Movies</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { movies: state.comedy }
|
return { movies: state.comedy };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchComedyMovies }, dispatch)
|
return bindActionCreators({ fetchComedyMovies }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ComedyMovies);
|
export default connect(mapStateToProps, mapDispatchToProps)(ComedyMovies);
|
||||||
@@ -1,42 +1,38 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
import { fetchDocumentaries } from '../store/actions/index';
|
import { fetchDocumentaries } from '../store/actions/index';
|
||||||
|
|
||||||
class Documentaries extends Component {
|
class Documentaries extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchDocumentaries();
|
this.props.fetchDocumentaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.movies.data) {
|
if (this.props.movies.data) {
|
||||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=99';
|
const url = `/discover/tv?api_key=${process.env.API_KEY}&with_genres=99`;
|
||||||
movies = getMovieRows(this.props.movies.data, url);
|
movies = getMovieRows(this.props.movies.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Documentaries</h1>
|
<h1 className="movieShowcase__heading">Documentaries</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { movies: state.documentary }
|
return { movies: state.documentary };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchDocumentaries }, dispatch)
|
return bindActionCreators({ fetchDocumentaries }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Documentaries);
|
export default connect(mapStateToProps, mapDispatchToProps)(Documentaries);
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import axios from "../axios-movies";
|
||||||
|
|
||||||
|
import Navbar from './Navbar';
|
||||||
|
import MainContent from './MainContent';
|
||||||
|
import Movie from '../components/Movie/Movie';
|
||||||
|
import Modal from '../components/UI/Modal';
|
||||||
|
import MovieDetails from '../components/Movie/MovieDetails';
|
||||||
|
|
||||||
|
class Home extends Component {
|
||||||
|
state = {
|
||||||
|
/** Toggles the movie list when the user starts typing. */
|
||||||
|
toggleMovieList: true,
|
||||||
|
/** An array that will hold all of our movie Components. */
|
||||||
|
// MovieList: [],
|
||||||
|
/** Toggles the modal when a movie is clicked. */
|
||||||
|
toggleModal: false,
|
||||||
|
/** Holds the movie information for a single movie. */
|
||||||
|
movieOverview: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the appropriate details for a specific movie that was clicked */
|
||||||
|
selectMovieHandler = (movie) => {
|
||||||
|
this.setState({ toggleModal: true });
|
||||||
|
|
||||||
|
let url;
|
||||||
|
/** Make the appropriate API call to get the details for a single movie or tv show. */
|
||||||
|
if (movie.media_type === "movie") {
|
||||||
|
const movieId = movie.id;
|
||||||
|
url = `https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.API_KEY}`;
|
||||||
|
|
||||||
|
} else if (movie.media_type === "tv") {
|
||||||
|
const tvId = movie.id
|
||||||
|
url = `https://api.themoviedb.org/3/tv/${tvId}?api_key=${process.env.API_KEY}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.get(url)
|
||||||
|
.then(res => {
|
||||||
|
const movieData = res.data;
|
||||||
|
this.setState({ movieOverview: movieData });
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal = () => {
|
||||||
|
this.setState({ toggleModal: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<MainContent />
|
||||||
|
<Modal show={this.state.toggleModal}
|
||||||
|
modalClosed={this.closeModal}
|
||||||
|
movie={this.state.movieOverview}>
|
||||||
|
<MovieDetails movie={this.state.movieOverview} />
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home;
|
||||||
@@ -1,42 +1,38 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
import { fetchHorrorMovies } from '../store/actions/index';
|
import { fetchHorrorMovies } from '../store/actions/index';
|
||||||
|
|
||||||
class HorrorMovies extends Component {
|
class HorrorMovies extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchHorrorMovies();
|
this.props.fetchHorrorMovies();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.movies.data) {
|
if (this.props.movies.data) {
|
||||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=27';
|
const url = `/discover/tv?api_key=${process.env.API_KEY}&with_genres=27`;
|
||||||
movies = getMovieRows(this.props.movies.data, url);
|
movies = getMovieRows(this.props.movies.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Horror Movies</h1>
|
<h1 className="movieShowcase__heading">Horror Movies</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { movies: state.horror }
|
return { movies: state.horror };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchHorrorMovies }, dispatch)
|
return bindActionCreators({ fetchHorrorMovies }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(HorrorMovies);
|
export default connect(mapStateToProps, mapDispatchToProps)(HorrorMovies);
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
import Navbar from './Navbar';
|
|
||||||
import MainContent from './MainContent';
|
|
||||||
import Movie from '../components/Movie/Movie';
|
|
||||||
import Modal from '../components/UI/Modal';
|
|
||||||
import MovieDetails from '../components/Movie/MovieDetails';
|
|
||||||
|
|
||||||
class Layout extends Component {
|
|
||||||
|
|
||||||
state = {
|
|
||||||
/** Toggles the movie list when the user starts typing. */
|
|
||||||
toggleMovieList: true,
|
|
||||||
/** An array that will hold all of our movie Components. */
|
|
||||||
MovieList: [],
|
|
||||||
/** Toggles the modal when a movie is clicked. */
|
|
||||||
toggleModal: false,
|
|
||||||
/** Holds the movie information for a single movie. */
|
|
||||||
movieOverview: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Make API call as soon as the user starts typing. */
|
|
||||||
makeAipCall = (searchItem) => {
|
|
||||||
const url = `https://api.themoviedb.org/3/search/multi?api_key=9ea839ec7891591994ec0f540b4b199f&language=en-US&include_adult=false&query=${searchItem}`;
|
|
||||||
|
|
||||||
axios.get(url)
|
|
||||||
.then(res => {
|
|
||||||
const results = res.data.results;
|
|
||||||
let movieImageUrl;
|
|
||||||
/** Will hold all our movies Components */
|
|
||||||
let movieRows = [];
|
|
||||||
|
|
||||||
/** Loop through all the movies */
|
|
||||||
results.forEach((movie) => {
|
|
||||||
/** Manually build our image url and set it on the Movie component. */
|
|
||||||
if (movie.poster_path !== null && movie.media_type !== "person") {
|
|
||||||
movieImageUrl = "https://image.tmdb.org/t/p/w500" + movie.poster_path;
|
|
||||||
|
|
||||||
/** Set the movie object to our Movie component */
|
|
||||||
const movieComponent = <Movie
|
|
||||||
movieDetails={() => this.selectMovieHandler(movie)}
|
|
||||||
key={movie.id}
|
|
||||||
movieImage={movieImageUrl}
|
|
||||||
movie={movie} />
|
|
||||||
|
|
||||||
/** Push our movie component to our movieRows array */
|
|
||||||
movieRows.push(movieComponent);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
/** Set our MovieList array to the movieRows array */
|
|
||||||
this.setState({ MovieList: movieRows });
|
|
||||||
}).catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the user input */
|
|
||||||
onSearchHandler = (event) => {
|
|
||||||
/** Display the movie list. */
|
|
||||||
this.setState({
|
|
||||||
toggleMovieList: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const userInput = event.target.value;
|
|
||||||
/** Pass in the user input to make the API call. */
|
|
||||||
this.makeAipCall(userInput);
|
|
||||||
|
|
||||||
/** If the input is empty don't display the movie list. */
|
|
||||||
if (userInput === "") {
|
|
||||||
this.setState({
|
|
||||||
toggleMovieList: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the appropriate details for a specific movie that was clicked */
|
|
||||||
selectMovieHandler = (movie) => {
|
|
||||||
this.setState({ toggleModal: true });
|
|
||||||
|
|
||||||
let url;
|
|
||||||
/** Make the appropriate API call to get the details for a single movie or tv show. */
|
|
||||||
if (movie.media_type === "movie") {
|
|
||||||
const movieId = movie.id;
|
|
||||||
url = `https://api.themoviedb.org/3/movie/${movieId}?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0`;
|
|
||||||
|
|
||||||
} else if (movie.media_type === "tv") {
|
|
||||||
const tvId = movie.id
|
|
||||||
url = `https://api.themoviedb.org/3/tv/${tvId}?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0`;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.get(url)
|
|
||||||
.then(res => {
|
|
||||||
const movieData = res.data;
|
|
||||||
|
|
||||||
this.setState({ movieOverview: movieData });
|
|
||||||
}).catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
closeModal = () => {
|
|
||||||
this.setState({ toggleModal: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Navbar showMovies={this.onSearchHandler} />
|
|
||||||
{
|
|
||||||
this.state.toggleMovieList ? <MainContent /> : <div
|
|
||||||
className="search-container">{this.state.MovieList}</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<Modal show={this.state.toggleModal}
|
|
||||||
modalClosed={this.closeModal}
|
|
||||||
movie={this.state.movieOverview}>
|
|
||||||
|
|
||||||
<MovieDetails movie={this.state.movieOverview} />
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Layout;
|
|
||||||
@@ -8,8 +8,6 @@ import NetflixOriginals from './NetflixOriginals';
|
|||||||
import TopRated from './TopRated';
|
import TopRated from './TopRated';
|
||||||
import ActionMovies from './ActionMovies';
|
import ActionMovies from './ActionMovies';
|
||||||
import ComedyMovies from './ComedyMovies';
|
import ComedyMovies from './ComedyMovies';
|
||||||
import HorrorMovies from './HorrorMovies';
|
|
||||||
import RomanceMovies from './RomanceMovies';
|
|
||||||
import Documentaries from './Documentaries';
|
import Documentaries from './Documentaries';
|
||||||
|
|
||||||
|
|
||||||
@@ -29,7 +27,7 @@ class MainContent extends Component {
|
|||||||
/** Movie Id for the Narcos series */
|
/** Movie Id for the Narcos series */
|
||||||
const movieId = 63351;
|
const movieId = 63351;
|
||||||
/** Make Api call to retrieve the details for a single movie */
|
/** Make Api call to retrieve the details for a single movie */
|
||||||
const url = `https://api.themoviedb.org/3/tv/${movieId}?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0`;
|
const url = `https://api.themoviedb.org/3/tv/${movieId}?api_key=${process.env.API_KEY}`;
|
||||||
axios
|
axios
|
||||||
.get(url)
|
.get(url)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
@@ -51,7 +49,6 @@ class MainContent extends Component {
|
|||||||
<TopRated />
|
<TopRated />
|
||||||
<ActionMovies />
|
<ActionMovies />
|
||||||
<ComedyMovies />
|
<ComedyMovies />
|
||||||
{/* <HorrorMovies /> */}
|
|
||||||
<Documentaries />
|
<Documentaries />
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
+73
-13
@@ -1,15 +1,26 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import NavigationItem from '../components/NavigationItem'
|
import { NavLink } from 'react-router-dom';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
import axios from '../axios-movies';
|
||||||
|
import Movie from '../components/Movie/Movie';
|
||||||
|
|
||||||
import SearchLogo from '../static/images/search-icon.svg';
|
import SearchLogo from '../static/images/search-icon.svg';
|
||||||
import NetflixLogo from '../static/images/Netflix_Logo_RGB.png';
|
import NetflixLogo from '../static/images/Netflix_Logo_RGB.png';
|
||||||
import BellLogo from '../static/images/bell-logo.svg';
|
import BellLogo from '../static/images/bell-logo.svg';
|
||||||
import DropdownArrow from '../static/images/drop-down-arrow.svg';
|
import DropdownArrow from '../static/images/drop-down-arrow.svg';
|
||||||
import DropdownContent from "../components/DropdownContent";
|
import DropdownContent from "../components/DropdownContent";
|
||||||
|
|
||||||
|
class Navbar extends Component {
|
||||||
class navigation extends Component {
|
constructor(props) {
|
||||||
state = {
|
super(props)
|
||||||
scrolling: false
|
this.state = {
|
||||||
|
scrolling: false,
|
||||||
|
movieList: [],
|
||||||
|
userInput: ''
|
||||||
|
}
|
||||||
|
// use to debounce api call
|
||||||
|
this.makeAipCall = _.debounce(this.makeAipCall, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -30,15 +41,67 @@ class navigation extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChange = async (event) => {
|
||||||
|
await this.setState({ userInput: event.target.value })
|
||||||
|
const { userInput } = this.state
|
||||||
|
|
||||||
|
await this.makeAipCall(userInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Make API call as soon as the user starts typing. */
|
||||||
|
makeAipCall = async (searchItem) => {
|
||||||
|
if (searchItem.length === 0) {
|
||||||
|
this.props.history.push('/')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `/search/multi?api_key=${process.env.API_KEY}&language=en-US&include_adult=false&query=${searchItem}`;
|
||||||
|
const response = await axios.get(url);
|
||||||
|
const results = response.data.results;
|
||||||
|
let movieImageUrl;
|
||||||
|
/** Will hold all our movies Components */
|
||||||
|
let movieRows = [];
|
||||||
|
|
||||||
|
/** Loop through all the movies */
|
||||||
|
results.forEach((movie) => {
|
||||||
|
/** Manually build our image url and set it on the Movie component. */
|
||||||
|
if (movie.poster_path !== null && movie.media_type !== "person") {
|
||||||
|
movieImageUrl = "https://image.tmdb.org/t/p/w500" + movie.poster_path;
|
||||||
|
|
||||||
|
/** Set the movie object to our Movie component */
|
||||||
|
const movieComponent = <Movie
|
||||||
|
movieDetails={() => this.selectMovieHandler(movie)}
|
||||||
|
key={movie.id}
|
||||||
|
movieImage={movieImageUrl}
|
||||||
|
movie={movie} />
|
||||||
|
|
||||||
|
/** Push our movie component to our movieRows array */
|
||||||
|
movieRows.push(movieComponent);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
/** Set our MovieList array to the movieRows array */
|
||||||
|
await this.setState({ movieList: movieRows });
|
||||||
|
this.props.history.push({
|
||||||
|
pathname: '/search',
|
||||||
|
movieRows: this.state.movieList,
|
||||||
|
userInput: searchItem
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onLogoClick = () => {
|
||||||
|
// reset state
|
||||||
|
this.setState({ userInput: '' })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { scrolling } = this.state;
|
const { scrolling } = this.state;
|
||||||
const { showMovies } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className={"navigation " + (scrolling ? "black" : "")} >
|
<nav className={"navigation " + (scrolling ? "black" : "")} >
|
||||||
<ul className="navigation__container">
|
<ul className="navigation__container">
|
||||||
<NavigationItem link="/" exact><img className="navigation__container--logo" src={NetflixLogo} alt="" /></NavigationItem>
|
<NavLink to="/" onClick={() => this.onLogoClick()}>
|
||||||
|
<img className="navigation__container--logo" src={NetflixLogo} alt="" />
|
||||||
|
</NavLink>
|
||||||
<DropdownArrow className="navigation__container--downArrow-2"></DropdownArrow>
|
<DropdownArrow className="navigation__container--downArrow-2"></DropdownArrow>
|
||||||
<div className="navigation__container-link pseudo-link">Home</div>
|
<div className="navigation__container-link pseudo-link">Home</div>
|
||||||
<div className="navigation__container-link pseudo-link">TV Shows</div>
|
<div className="navigation__container-link pseudo-link">TV Shows</div>
|
||||||
@@ -46,16 +109,14 @@ class navigation extends Component {
|
|||||||
<div className="navigation__container-link pseudo-link">Recently Added</div>
|
<div className="navigation__container-link pseudo-link">Recently Added</div>
|
||||||
<div className="navigation__container-link pseudo-link">My List</div>
|
<div className="navigation__container-link pseudo-link">My List</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="navigation__container--left">
|
<div className="navigation__container--left">
|
||||||
<SearchLogo className="logo" />
|
<SearchLogo className="logo" />
|
||||||
|
|
||||||
<input
|
<input
|
||||||
onChange={showMovies}
|
value={this.state.userInput}
|
||||||
|
onChange={() => this.onChange(event)}
|
||||||
className="navigation__container--left__input"
|
className="navigation__container--left__input"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Title, genres, people" />
|
placeholder="Title, genres, people" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="navigation__container-link pseudo-link">KIDS</div>
|
<div className="navigation__container-link pseudo-link">KIDS</div>
|
||||||
@@ -64,11 +125,10 @@ class navigation extends Component {
|
|||||||
|
|
||||||
<DropdownContent />
|
<DropdownContent />
|
||||||
<DropdownArrow className="navigation__container--downArrow" />
|
<DropdownArrow className="navigation__container--downArrow" />
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default navigation;
|
export default withRouter(Navbar);
|
||||||
|
|||||||
@@ -1,42 +1,38 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
import { fetchNetflixOriginals } from '../store/actions/index';
|
import { fetchNetflixOriginals } from '../store/actions/index';
|
||||||
|
|
||||||
class NetflixOriginals extends Component {
|
class NetflixOriginals extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchNetflixOriginals();
|
this.props.fetchNetflixOriginals();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.movies.data) {
|
if (this.props.movies.data) {
|
||||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213';
|
const url = `/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`;
|
||||||
movies = getMovieRows(this.props.movies.data, url);
|
movies = getMovieRows(this.props.movies.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">NETFLIX ORIGINALS</h1>
|
<h1 className="movieShowcase__heading">NETFLIX ORIGINALS</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { movies: state.netflixOriginals }
|
return { movies: state.netflixOriginals };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchNetflixOriginals }, dispatch)
|
return bindActionCreators({ fetchNetflixOriginals }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(NetflixOriginals);
|
export default connect(mapStateToProps, mapDispatchToProps)(NetflixOriginals);
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function NotFound() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>NOT FOUND</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,42 +1,38 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
import { fetchRomanceMovies } from '../store/actions/index';
|
import { fetchRomanceMovies } from '../store/actions/index';
|
||||||
|
|
||||||
class RomanceMovies extends Component {
|
class RomanceMovies extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchRomanceMovies();
|
this.props.fetchRomanceMovies();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.movies.data) {
|
if (this.props.movies.data) {
|
||||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=10749';
|
const url = `/discover/tv?api_key=${process.env.API_KEY}&with_genres=10749`;
|
||||||
movies = getMovieRows(this.props.movies.data, url);
|
movies = getMovieRows(this.props.movies.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Romance Movies</h1>
|
<h1 className="movieShowcase__heading">Romance Movies</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { movies: state.romance }
|
return { movies: state.romance };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchRomanceMovies }, dispatch)
|
return bindActionCreators({ fetchRomanceMovies }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(RomanceMovies);
|
export default connect(mapStateToProps, mapDispatchToProps)(RomanceMovies);
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export default class Search extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
movies: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount = async () => {
|
||||||
|
const { movieRows } = this.props.history.location;
|
||||||
|
if (movieRows)
|
||||||
|
await this.setState({ movies: movieRows });
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate = async (prevProps) => {
|
||||||
|
if (
|
||||||
|
prevProps.location.movieRows.length !==
|
||||||
|
this.props.location.movieRows.length
|
||||||
|
) {
|
||||||
|
await this.setState({ movies: this.props.location.movieRows });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { movies } = this.state
|
||||||
|
const { userInput } = this.props.location
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
this.state.movies.length > 0 ? (
|
||||||
|
<div className="search-container">
|
||||||
|
{this.state.movies}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="no-results">
|
||||||
|
<div className="no-results__text">
|
||||||
|
<p>Your search for "{userInput}" did not have any matches.</p>
|
||||||
|
<p>Suggestions:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Try different keywords</li>
|
||||||
|
<li>Looking for a movie or TV show?</li>
|
||||||
|
<li>Try using a movie, TV show title, an actor or director</li>
|
||||||
|
<li>Try a genre, like comedy, romance, sports, or drama</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-13
@@ -1,41 +1,38 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { fetchTopRated } from '../store/actions/index';
|
import { fetchTopRated } from '../store/actions/index';
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
|
|
||||||
class TopRated extends Component {
|
class TopRated extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchTopRated();
|
this.props.fetchTopRated();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.topRated.data) {
|
if (this.props.topRated.data) {
|
||||||
const url = "/movie/top_rated?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&language=en-US";
|
const url = `/movie/top_rated?api_key=${process.env.API_KEY}&language=en-US`;
|
||||||
movies = getMovieRows(this.props.topRated.data, url);
|
movies = getMovieRows(this.props.topRated.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Top Rated</h1>
|
<h1 className="movieShowcase__heading">Top Rated</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { topRated: state.topRated }
|
return { topRated: state.topRated };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchTopRated }, dispatch)
|
return bindActionCreators({ fetchTopRated }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(TopRated);
|
export default connect(mapStateToProps, mapDispatchToProps)(TopRated);
|
||||||
@@ -1,41 +1,38 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react';
|
||||||
import { bindActionCreators } from "redux";
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { fetchTrending } from '../store/actions/index';
|
import { fetchTrending } from '../store/actions/index';
|
||||||
import { getMovieRows } from '../getMovie';
|
import { getMovieRows } from '../getMovie';
|
||||||
|
|
||||||
class TrendingMovies extends Component {
|
class TrendingMovies extends Component {
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.fetchTrending();
|
this.props.fetchTrending();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let movies
|
let movies;
|
||||||
// Call getMoviesRows function only when we get the data back
|
// Call getMoviesRows function only when we get the data back
|
||||||
// from the API through redux
|
// from the API through redux
|
||||||
if (this.props.trending.data) {
|
if (this.props.trending.data) {
|
||||||
const url = '/trending/all/week?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&language=en-US';
|
const url = `/trending/all/week?api_key=${process.env.API_KEY}&language=en-US`;
|
||||||
movies = getMovieRows(this.props.trending.data, url);
|
movies = getMovieRows(this.props.trending.data, url);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="movieShowcase__heading">Trending Now</h1>
|
<h1 className="movieShowcase__heading">Trending Now</h1>
|
||||||
<div className="movieShowcase__container">
|
<div className="movieShowcase__container">{movies}</div>
|
||||||
{movies}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return { trending: state.trending }
|
return { trending: state.trending };
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return bindActionCreators({ fetchTrending }, dispatch)
|
return bindActionCreators({ fetchTrending }, dispatch);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(TrendingMovies);
|
export default connect(mapStateToProps, mapDispatchToProps)(TrendingMovies);
|
||||||
|
|||||||
+13
-6
@@ -3,21 +3,28 @@ import React from 'react';
|
|||||||
|
|
||||||
export function getMovieRows(movies, url) {
|
export function getMovieRows(movies, url) {
|
||||||
const movieRow = movies.map((movie) => {
|
const movieRow = movies.map((movie) => {
|
||||||
let movieImageUrl = "https://image.tmdb.org/t/p/w500/" + movie.backdrop_path;
|
let movieImageUrl =
|
||||||
if (url === "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
'https://image.tmdb.org/t/p/w500/' + movie.backdrop_path;
|
||||||
movieImageUrl = "https://image.tmdb.org/t/p/original/" + movie.poster_path;
|
if (
|
||||||
|
url === `/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`
|
||||||
|
) {
|
||||||
|
movieImageUrl =
|
||||||
|
'https://image.tmdb.org/t/p/original/' + movie.poster_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movie.poster_path && movie.backdrop_path !== null) {
|
if (movie.poster_path && movie.backdrop_path !== null) {
|
||||||
const movieComponent = <MovieGenre
|
const movieComponent = (
|
||||||
|
<MovieGenre
|
||||||
key={movie.id}
|
key={movie.id}
|
||||||
url={url}
|
url={url}
|
||||||
posterUrl={movieImageUrl}
|
posterUrl={movieImageUrl}
|
||||||
movie={movie} />
|
movie={movie}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return movieComponent;
|
return movieComponent;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return movieRow
|
return movieRow;
|
||||||
}
|
}
|
||||||
+5
-3
@@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { BrowserRouter } from "react-router-dom";
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { createStore, applyMiddleware } from 'redux';
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
import reducers from './store/reducers';
|
import reducers from './store/reducers';
|
||||||
import promise from 'redux-promise';
|
import promise from 'redux-promise';
|
||||||
|
import '@babel/polyfill';
|
||||||
|
|
||||||
import App from './containers/App';
|
import App from './containers/App';
|
||||||
// Import main sass file to apply global styles
|
// Import main sass file to apply global styles
|
||||||
@@ -12,11 +12,13 @@ import './static/sass/style.scss';
|
|||||||
|
|
||||||
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
|
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// - fix styling issue
|
||||||
|
// - implement carousel
|
||||||
|
// - fix modal backdrop bug
|
||||||
const app = (
|
const app = (
|
||||||
<Provider store={createStoreWithMiddleware(reducers)}>
|
<Provider store={createStoreWithMiddleware(reducers)}>
|
||||||
<BrowserRouter>
|
|
||||||
<App />
|
<App />
|
||||||
</BrowserRouter>
|
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -9,3 +9,31 @@
|
|||||||
padding-bottom: 10rem;
|
padding-bottom: 10rem;
|
||||||
padding-left: 4rem;
|
padding-left: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-results {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
color: #c5c5c5;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 25rem;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
|
||||||
|
&>* {
|
||||||
|
padding-bottom: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&>ul {
|
||||||
|
// color: red;
|
||||||
|
padding-left: 6.5rem;
|
||||||
|
list-style: disc;
|
||||||
|
|
||||||
|
&>* {
|
||||||
|
padding-bottom: 0.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+40
-26
@@ -9,76 +9,90 @@ export const FETCH_HORROR_MOVIES = 'FETCH_HORROR_MOVIES';
|
|||||||
export const FETCH_ROMANCE_MOVIES = 'FETCH_ROMANCE_MOVIES';
|
export const FETCH_ROMANCE_MOVIES = 'FETCH_ROMANCE_MOVIES';
|
||||||
export const FETCH_DOCUMENTARIES = 'FETCH_DOCUMENTARIES';
|
export const FETCH_DOCUMENTARIES = 'FETCH_DOCUMENTARIES';
|
||||||
|
|
||||||
const API_KEY = '224ce27b38a3805ecf6f6c36eb3ba9d0';
|
|
||||||
|
|
||||||
export function fetchTrending() {
|
export function fetchTrending() {
|
||||||
const request = axios.get(`/trending/all/week?api_key=${API_KEY}&language=en-US`);
|
const request = axios.get(
|
||||||
|
`/trending/all/week?api_key=${process.env.API_KEY}&language=en-US`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_TRENDING,
|
type: FETCH_TRENDING,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchNetflixOriginals() {
|
export function fetchNetflixOriginals() {
|
||||||
const request = axios.get(`/discover/tv?api_key=${API_KEY}&with_networks=213`);
|
const request = axios.get(
|
||||||
|
`/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_NETFLIX_ORIGINALS,
|
type: FETCH_NETFLIX_ORIGINALS,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchTopRated() {
|
export function fetchTopRated() {
|
||||||
const request = axios.get(`/movie/top_rated?api_key=${API_KEY}&language=en-US`)
|
const request = axios.get(
|
||||||
|
`/movie/top_rated?api_key=${process.env.API_KEY}&language=en-US`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_TOP_RATED,
|
type: FETCH_TOP_RATED,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchActionMovies() {
|
export function fetchActionMovies() {
|
||||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=28`)
|
const request = axios.get(
|
||||||
|
`/discover/movie?api_key=${process.env.API_KEY}&with_genres=28`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_ACTION_MOVIES,
|
type: FETCH_ACTION_MOVIES,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchComedyMovies() {
|
export function fetchComedyMovies() {
|
||||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=35`)
|
const request = axios.get(
|
||||||
|
`/discover/movie?api_key=${process.env.API_KEY}&with_genres=35`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_COMEDY_MOVIES,
|
type: FETCH_COMEDY_MOVIES,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchHorrorMovies() {
|
export function fetchHorrorMovies() {
|
||||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=27`)
|
const request = axios.get(
|
||||||
|
`/discover/movie?api_key=${process.env.API_KEY}&with_genres=27`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_HORROR_MOVIES,
|
type: FETCH_HORROR_MOVIES,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchRomanceMovies() {
|
export function fetchRomanceMovies() {
|
||||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=10749`)
|
const request = axios.get(
|
||||||
|
`/discover/movie?api_key=${process.env.API_KEY}&with_genres=10749`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_ROMANCE_MOVIES,
|
type: FETCH_ROMANCE_MOVIES,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchDocumentaries() {
|
export function fetchDocumentaries() {
|
||||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=99`)
|
const request = axios.get(
|
||||||
|
`/discover/movie?api_key=${process.env.API_KEY}&with_genres=99`
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: FETCH_DOCUMENTARIES,
|
type: FETCH_DOCUMENTARIES,
|
||||||
payload: request
|
payload: request,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,6 @@ import HorrorMoviesReducer from './reducerHorrorMovies';
|
|||||||
import RomanceMoviesReducer from './reducerRomanceMovies';
|
import RomanceMoviesReducer from './reducerRomanceMovies';
|
||||||
import DocumentaryReducer from './reducerDocumentary';
|
import DocumentaryReducer from './reducerDocumentary';
|
||||||
|
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
trending: TrendingReducer,
|
trending: TrendingReducer,
|
||||||
netflixOriginals: NetflixOriginalsReducer,
|
netflixOriginals: NetflixOriginalsReducer,
|
||||||
@@ -17,7 +16,7 @@ const rootReducer = combineReducers({
|
|||||||
comedy: ComedyMoviesReducer,
|
comedy: ComedyMoviesReducer,
|
||||||
horror: HorrorMoviesReducer,
|
horror: HorrorMoviesReducer,
|
||||||
romance: RomanceMoviesReducer,
|
romance: RomanceMoviesReducer,
|
||||||
documentary: DocumentaryReducer
|
documentary: DocumentaryReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rootReducer;
|
export default rootReducer;
|
||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_ACTION_MOVIES:
|
case FETCH_ACTION_MOVIES:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_COMEDY_MOVIES:
|
case FETCH_COMEDY_MOVIES:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_DOCUMENTARIES:
|
case FETCH_DOCUMENTARIES:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_HORROR_MOVIES:
|
case FETCH_HORROR_MOVIES:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_NETFLIX_ORIGINALS:
|
case FETCH_NETFLIX_ORIGINALS:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_ROMANCE_MOVIES:
|
case FETCH_ROMANCE_MOVIES:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_TOP_RATED:
|
case FETCH_TOP_RATED:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function (state = {}, action) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FETCH_TRENDING:
|
case FETCH_TRENDING:
|
||||||
const data = action.payload.data.results;
|
const data = action.payload.data.results;
|
||||||
return { ...state, data }
|
return { ...state, data };
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-23
@@ -1,14 +1,29 @@
|
|||||||
const HtmlWebPackPlugin = require("html-webpack-plugin");
|
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||||
|
const dotenv = require('dotenv');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
// call dotenv and it will return an Object with a parsed key
|
||||||
|
const env = dotenv.config().parsed;
|
||||||
|
|
||||||
module.exports = {
|
// reduce env variables to an oject
|
||||||
|
const envKeys = Object.keys(env).reduce((prev, next) => {
|
||||||
|
prev[`process.env.${next}`] = JSON.stringify(env[next]);
|
||||||
|
return prev;
|
||||||
|
}, {});
|
||||||
|
|
||||||
entry: "./src/index.js",
|
console.log('keys', envKeys);
|
||||||
|
|
||||||
|
return {
|
||||||
|
entry: './src/index.js',
|
||||||
output: {
|
output: {
|
||||||
filename: "bundle.js",
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
filename: 'bundle.js',
|
||||||
|
publicPath: '/',
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
@@ -16,16 +31,15 @@ module.exports = {
|
|||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: {
|
use: {
|
||||||
loader: "babel-loader"
|
loader: 'babel-loader',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: {
|
use: {
|
||||||
loader: 'svg-react-loader'
|
loader: 'svg-react-loader',
|
||||||
}
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.scss$/,
|
test: /\.scss$/,
|
||||||
@@ -33,12 +47,12 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
loader: MiniCssExtractPlugin.loader,
|
loader: MiniCssExtractPlugin.loader,
|
||||||
options: {
|
options: {
|
||||||
publicPath: '../'
|
publicPath: '../',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
'css-loader',
|
'css-loader',
|
||||||
'sass-loader'
|
'sass-loader',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(gif|png|jpe?g)$/i,
|
test: /\.(gif|png|jpe?g)$/i,
|
||||||
@@ -52,23 +66,30 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
historyApiFallback: true,
|
||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
fs: "empty"
|
fs: 'empty',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
new webpack.DefinePlugin(envKeys),
|
||||||
new HtmlWebPackPlugin({
|
new HtmlWebPackPlugin({
|
||||||
template: "./src/index.html",
|
template: './src/index.html',
|
||||||
filename: "./index.html"
|
filename: './index.html',
|
||||||
}),
|
}),
|
||||||
new CopyWebpackPlugin([{ from: 'src/static/images', to: 'static/images' }]),
|
new CopyWebpackPlugin([
|
||||||
|
{ from: 'src/static/images', to: 'static/images' },
|
||||||
|
]),
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
// Options similar to the same options in webpackOptions.output
|
// Options similar to the same options in webpackOptions.output
|
||||||
// both options are optional
|
// both options are optional
|
||||||
filename: "main.css"
|
filename: 'main.css',
|
||||||
}),
|
}),
|
||||||
new CleanWebpackPlugin(['dist']),
|
new CleanWebpackPlugin(['dist']),
|
||||||
]
|
],
|
||||||
|
};
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user