implemented redux for state management
This commit is contained in:
72
package-lock.json
generated
72
package-lock.json
generated
@@ -843,6 +843,21 @@
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.2.tgz",
|
||||
"integrity": "sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
|
||||
"integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz",
|
||||
@@ -10842,6 +10857,44 @@
|
||||
"scheduler": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.8.6",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
|
||||
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA=="
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.1.tgz",
|
||||
"integrity": "sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"invariant": "^2.2.4",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^16.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
|
||||
"integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
|
||||
"requires": {
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-router": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
|
||||
@@ -10984,6 +11037,20 @@
|
||||
"strip-indent": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"redux": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz",
|
||||
"integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"symbol-observable": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"redux-thunk": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
|
||||
"integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
|
||||
},
|
||||
"regenerate": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
|
||||
@@ -12495,6 +12562,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"symbol-observable": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
|
||||
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
|
||||
},
|
||||
"tapable": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz",
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
"author": "Andres Alcocer",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"express": "^4.16.4",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.6.1",
|
||||
"react-dom": "^16.6.1",
|
||||
"react-redux": "^6.0.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"express": "^4.16.4",
|
||||
"axios": "^0.18.0",
|
||||
"prop-types": "^15.6.2"
|
||||
"redux": "^4.0.1",
|
||||
"redux-thunk": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.1.5",
|
||||
|
||||
@@ -1,15 +1,37 @@
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react'
|
||||
|
||||
export default function MovieGenre(props) {
|
||||
let netflixUrl = false;
|
||||
if (props.url === "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
||||
netflixUrl = true;
|
||||
import Modal from '../components/UI/Modal';
|
||||
import MovieDetails from '../components/movie/MovieDetails';
|
||||
|
||||
export default class MovieGenre extends Component {
|
||||
state = {
|
||||
toggleModal: false
|
||||
}
|
||||
|
||||
return (
|
||||
<div onClick={props.movieDetailsModal}
|
||||
className={"movieShowcase__container--movie" + (netflixUrl ? "__netflix" : "")}>
|
||||
<img src={props.posterUrl} className="movieShowcase__container--movie-image" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
handleToggleModal = () => {
|
||||
this.setState({ toggleModal: true });
|
||||
}
|
||||
|
||||
closeModal = () => {
|
||||
this.setState({ toggleModal: false })
|
||||
}
|
||||
|
||||
render() {
|
||||
let netflixUrl = false;
|
||||
if (this.props.url === "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
||||
netflixUrl = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div onClick={() => this.handleToggleModal()}
|
||||
className={"movieShowcase__container--movie" + (netflixUrl ? "__netflix" : "")}>
|
||||
<img src={this.props.posterUrl} className="movieShowcase__container--movie-image" />
|
||||
</div>
|
||||
<Modal show={this.state.toggleModal} movie={this.props.movie} modalClosed={this.closeModal}>
|
||||
<MovieDetails movie={this.props.movie} />
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
41
src/containers/ActionMovies.js
Normal file
41
src/containers/ActionMovies.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { Component } from 'react'
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { fetchActionMovies } from '../store/actions/index';
|
||||
import { getMovieRows } from '../getMovie';
|
||||
|
||||
class ActionMovies extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchActionMovies();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.actionMovies.data) {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=28";
|
||||
movies = getMovieRows(this.props.actionMovies.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Action Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { actionMovies: state.action }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchActionMovies }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ActionMovies);
|
||||
42
src/containers/ComedyMovies.js
Normal file
42
src/containers/ComedyMovies.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { Component } from 'react';
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getMovieRows } from '../getMovie';
|
||||
import { fetchComedyMovies } from '../store/actions/index';
|
||||
|
||||
class ComedyMovies extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchComedyMovies();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.movies.data) {
|
||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=35';
|
||||
movies = getMovieRows(this.props.movies.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Comedy Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { movies: state.comedy }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchComedyMovies }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ComedyMovies);
|
||||
42
src/containers/Documentaries.js
Normal file
42
src/containers/Documentaries.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { Component } from 'react';
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getMovieRows } from '../getMovie';
|
||||
import { fetchDocumentaries } from '../store/actions/index';
|
||||
|
||||
class Documentaries extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchDocumentaries();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.movies.data) {
|
||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=99';
|
||||
movies = getMovieRows(this.props.movies.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Documentaries</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { movies: state.documentary }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchDocumentaries }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Documentaries);
|
||||
42
src/containers/HorrorMovies.js
Normal file
42
src/containers/HorrorMovies.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { Component } from 'react';
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getMovieRows } from '../getMovie';
|
||||
import { fetchHorrorMovies } from '../store/actions/index';
|
||||
|
||||
class HorrorMovies extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchHorrorMovies();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.movies.data) {
|
||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=27';
|
||||
movies = getMovieRows(this.props.movies.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Horror Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { movies: state.horror }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchHorrorMovies }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(HorrorMovies);
|
||||
@@ -1,9 +1,16 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios';
|
||||
import Header from '../components/Header';
|
||||
import MovieGenreRow from './MovieGenreRow';
|
||||
import Footer from '../components/Footer';
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
|
||||
import TrendingMovies from './TrendingMovies';
|
||||
import NetflixOriginals from './NetflixOriginals';
|
||||
import TopRated from './TopRated';
|
||||
import ActionMovies from './ActionMovies';
|
||||
import ComedyMovies from './ComedyMovies';
|
||||
import HorrorMovies from './HorrorMovies';
|
||||
import RomanceMovies from './RomanceMovies';
|
||||
import Documentaries from './Documentaries';
|
||||
|
||||
|
||||
class MainContent extends Component {
|
||||
@@ -36,13 +43,19 @@ class MainContent extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div className="container">
|
||||
<Header movie={this.state.selectedMovie} />
|
||||
<MovieGenreRow />
|
||||
<Footer />
|
||||
<div className="container">
|
||||
<Header movie={this.state.selectedMovie} />
|
||||
<div className="movieShowcase">
|
||||
<NetflixOriginals />
|
||||
<TrendingMovies />
|
||||
<TopRated />
|
||||
<ActionMovies />
|
||||
<ComedyMovies />
|
||||
<HorrorMovies />
|
||||
<Documentaries />
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import axios from '../axios-movies';
|
||||
import MovieGenre from '../components/MovieGenre';
|
||||
import Modal from "../components/UI/Modal";
|
||||
import MovieDetails from '../components/Movie/MovieDetails';
|
||||
|
||||
class MovieGenreRow extends Component {
|
||||
|
||||
/** Hold each genre movie row in an array */
|
||||
state = {
|
||||
trendingMovieRow: [],
|
||||
netflixOriginalsRow: [],
|
||||
topRatedRow: [],
|
||||
comedyMovieRow: [],
|
||||
horrorMovieRow: [],
|
||||
actionMovieRow: [],
|
||||
animatedMovieRow: [],
|
||||
documentaryRow: [],
|
||||
romanceMovieRow: [],
|
||||
movieOverview: {},
|
||||
toggleModal: false,
|
||||
}
|
||||
|
||||
/** Make all API calls as soon as our MovieGenreRow component mounts. */
|
||||
componentWillMount() {
|
||||
this.getTrending();
|
||||
this.getTopRated();
|
||||
this.getComedyMovies();
|
||||
this.getActionMovies();
|
||||
this.getHorrorMovies();
|
||||
this.getNetflixMovies();
|
||||
this.getRomanceMovies();
|
||||
this.getDocumentaries();
|
||||
this.getAnimatedMovies();
|
||||
}
|
||||
|
||||
/**
|
||||
Get the movie details for a single movie
|
||||
@param {object} movieObject - A single movie object
|
||||
*/
|
||||
getMovieDetails = (movieObject) => {
|
||||
console.log(movieObject);
|
||||
this.setState({ toggleModal: true });
|
||||
this.setState({ movieOverview: movieObject });
|
||||
|
||||
}
|
||||
|
||||
closeModal = () => {
|
||||
this.setState({ toggleModal: false })
|
||||
}
|
||||
|
||||
|
||||
/** Extract our movie data and pass it to our MovieGenre Component. */
|
||||
getMovieRows = (res, url) => {
|
||||
const results = res.data.results;
|
||||
let movieRows = [];
|
||||
|
||||
results.forEach((movie) => {
|
||||
let movieImageUrl = "https://image.tmdb.org/t/p/original/" + movie.backdrop_path;
|
||||
if (url === "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
||||
movieImageUrl = "https://image.tmdb.org/t/p/original/" + movie.poster_path;
|
||||
}
|
||||
|
||||
if (movie.poster_path && movie.backdrop_path !== null) {
|
||||
|
||||
const movieComponent = <MovieGenre
|
||||
movieDetailsModal={() => this.getMovieDetails(movie)}
|
||||
key={movie.id}
|
||||
url={url}
|
||||
posterUrl={movieImageUrl}
|
||||
movie={movie} />
|
||||
movieRows.push(movieComponent);
|
||||
}
|
||||
})
|
||||
|
||||
return movieRows;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send request for movies that are popular right now
|
||||
*/
|
||||
getTrending = () => {
|
||||
const url = "/trending/all/week?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&language=en-US";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ trendingMovieRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send request for movies that are top rated
|
||||
*/
|
||||
getTopRated = () => {
|
||||
const url = "/movie/top_rated?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&language=en-US";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ topRatedRow: movieRows });
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Netflix originals
|
||||
*/
|
||||
getNetflixMovies = () => {
|
||||
const url = "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ netflixOriginalsRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getActionMovies = () => {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=28";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ actionMovieRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getComedyMovies = () => {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=35";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ comedyMovieRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getHorrorMovies = () => {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=27";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ horrorMovieRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getRomanceMovies = () => {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=10749";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ romanceMovieRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getAnimatedMovies = () => {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=16";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ animatedMovieRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
getDocumentaries = () => {
|
||||
const url = "/discover/movie?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=99";
|
||||
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
const movieRows = this.getMovieRows(res, url);
|
||||
|
||||
this.setState({ documentaryRow: movieRows });
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div className="movieShowcase">
|
||||
<h1 className="movieShowcase__heading">NETFLIX ORIGINALS</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.netflixOriginalsRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Trending Now</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.trendingMovieRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Top Rated</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.topRatedRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Action Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.actionMovieRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Comedy Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.comedyMovieRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Horror Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.horrorMovieRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Romance Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.romanceMovieRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Animated Films</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.animatedMovieRow}
|
||||
</div>
|
||||
|
||||
<h1 className="movieShowcase__heading">Documentaries</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{this.state.documentaryRow}
|
||||
</div>
|
||||
|
||||
<Modal show={this.state.toggleModal} modalClosed={this.closeModal} movie={this.state.movieOverview}>
|
||||
<MovieDetails movie={this.state.movieOverview} />
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MovieGenreRow;
|
||||
42
src/containers/NetflixOriginals.js
Normal file
42
src/containers/NetflixOriginals.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { Component } from 'react';
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getMovieRows } from '../getMovie';
|
||||
import { fetchNetflixOriginals } from '../store/actions/index';
|
||||
|
||||
class NetflixOriginals extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchNetflixOriginals();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.movies.data) {
|
||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213';
|
||||
movies = getMovieRows(this.props.movies.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">NETFLIX ORIGINALS</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { movies: state.netflixOriginals }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchNetflixOriginals }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(NetflixOriginals);
|
||||
42
src/containers/RomanceMovies.js
Normal file
42
src/containers/RomanceMovies.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { Component } from 'react';
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getMovieRows } from '../getMovie';
|
||||
import { fetchRomanceMovies } from '../store/actions/index';
|
||||
|
||||
class RomanceMovies extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchRomanceMovies();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.movies.data) {
|
||||
const url = '/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_genres=10749';
|
||||
movies = getMovieRows(this.props.movies.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Romance Movies</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { movies: state.romance }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchRomanceMovies }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(RomanceMovies);
|
||||
41
src/containers/TopRated.js
Normal file
41
src/containers/TopRated.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { Component } from 'react'
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { fetchTopRated } from '../store/actions/index';
|
||||
import { getMovieRows } from '../getMovie';
|
||||
|
||||
class TopRated extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchTopRated();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.topRated.data) {
|
||||
const url = "/movie/top_rated?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&language=en-US";
|
||||
movies = getMovieRows(this.props.topRated.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Top Rated</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { topRated: state.topRated }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchTopRated }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TopRated);
|
||||
41
src/containers/TrendingMovies.js
Normal file
41
src/containers/TrendingMovies.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { Component } from 'react'
|
||||
import { bindActionCreators } from "redux";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { fetchTrending } from '../store/actions/index';
|
||||
import { getMovieRows } from '../getMovie';
|
||||
|
||||
class TrendingMovies extends Component {
|
||||
|
||||
componentWillMount() {
|
||||
this.props.fetchTrending();
|
||||
}
|
||||
|
||||
render() {
|
||||
let movies
|
||||
// Call getMoviesRows function only when we get the data back
|
||||
// from the API through redux
|
||||
if (this.props.trending.data) {
|
||||
const url = '/trending/all/week?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&language=en-US';
|
||||
movies = getMovieRows(this.props.trending.data, url);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">Trending Now</h1>
|
||||
<div className="movieShowcase__container">
|
||||
{movies}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { trending: state.trending }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators({ fetchTrending }, dispatch)
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TrendingMovies);
|
||||
23
src/getMovie.js
Normal file
23
src/getMovie.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import MovieGenre from './components/MovieGenre';
|
||||
import React from 'react';
|
||||
|
||||
export function getMovieRows(movies, url) {
|
||||
const movieRow = movies.map((movie) => {
|
||||
let movieImageUrl = "https://image.tmdb.org/t/p/original/" + movie.backdrop_path;
|
||||
if (url === "/discover/tv?api_key=224ce27b38a3805ecf6f6c36eb3ba9d0&with_networks=213") {
|
||||
movieImageUrl = "https://image.tmdb.org/t/p/original/" + movie.poster_path;
|
||||
}
|
||||
|
||||
if (movie.poster_path && movie.backdrop_path !== null) {
|
||||
const movieComponent = <MovieGenre
|
||||
key={movie.id}
|
||||
url={url}
|
||||
posterUrl={movieImageUrl}
|
||||
movie={movie} />
|
||||
|
||||
return movieComponent;
|
||||
}
|
||||
});
|
||||
|
||||
return movieRow
|
||||
}
|
||||
22
src/index.js
22
src/index.js
@@ -1,15 +1,23 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { Provider } from 'react-redux';
|
||||
import { createStore, applyMiddleware } from 'redux';
|
||||
import reducers from './store/reducers';
|
||||
import promise from 'redux-promise';
|
||||
|
||||
import App from './containers/App';
|
||||
import './static/sass/style.scss';
|
||||
import App from './containers/App';
|
||||
// Import main sass file to apply global styles
|
||||
import './static/sass/style.scss';
|
||||
|
||||
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
|
||||
|
||||
const app = (
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
);
|
||||
<Provider store={createStoreWithMiddleware(reducers)}>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
ReactDOM.render(app, document.getElementById('app'));
|
||||
84
src/store/actions/index.js
Normal file
84
src/store/actions/index.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import axios from '../../axios-movies';
|
||||
|
||||
export const FETCH_TRENDING = 'FETCH_TRENDING';
|
||||
export const FETCH_NETFLIX_ORIGINALS = 'FETCH_NETFLIX_ORIGINALS';
|
||||
export const FETCH_TOP_RATED = 'FETCH_TOP_RATED';
|
||||
export const FETCH_ACTION_MOVIES = 'FETCH_ACTION_MOVIES';
|
||||
export const FETCH_COMEDY_MOVIES = 'FETCH_COMEDY_MOVIES';
|
||||
export const FETCH_HORROR_MOVIES = 'FETCH_HORROR_MOVIES';
|
||||
export const FETCH_ROMANCE_MOVIES = 'FETCH_ROMANCE_MOVIES';
|
||||
export const FETCH_DOCUMENTARIES = 'FETCH_DOCUMENTARIES';
|
||||
|
||||
const API_KEY = '224ce27b38a3805ecf6f6c36eb3ba9d0';
|
||||
|
||||
export function fetchTrending() {
|
||||
const request = axios.get(`/trending/all/week?api_key=${API_KEY}&language=en-US`);
|
||||
|
||||
return {
|
||||
type: FETCH_TRENDING,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchNetflixOriginals() {
|
||||
const request = axios.get(`/discover/tv?api_key=${API_KEY}&with_networks=213`);
|
||||
|
||||
return {
|
||||
type: FETCH_NETFLIX_ORIGINALS,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchTopRated() {
|
||||
const request = axios.get(`/movie/top_rated?api_key=${API_KEY}&language=en-US`)
|
||||
|
||||
return {
|
||||
type: FETCH_TOP_RATED,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchActionMovies() {
|
||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=28`)
|
||||
|
||||
return {
|
||||
type: FETCH_ACTION_MOVIES,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchComedyMovies() {
|
||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=35`)
|
||||
|
||||
return {
|
||||
type: FETCH_COMEDY_MOVIES,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchHorrorMovies() {
|
||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=27`)
|
||||
|
||||
return {
|
||||
type: FETCH_HORROR_MOVIES,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchRomanceMovies() {
|
||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=10749`)
|
||||
|
||||
return {
|
||||
type: FETCH_ROMANCE_MOVIES,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchDocumentaries() {
|
||||
const request = axios.get(`/discover/movie?api_key=${API_KEY}&with_genres=99`)
|
||||
|
||||
return {
|
||||
type: FETCH_DOCUMENTARIES,
|
||||
payload: request
|
||||
}
|
||||
}
|
||||
23
src/store/reducers/index.js
Normal file
23
src/store/reducers/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import TrendingReducer from './reducerTrending';
|
||||
import NetflixOriginalsReducer from './reducerNetflixOriginals';
|
||||
import TopRatedReducer from './reducerTopRated';
|
||||
import ActionMoviesReducer from './reducerActionMovies';
|
||||
import ComedyMoviesReducer from './reducerComedyMovies';
|
||||
import HorrorMoviesReducer from './reducerHorrorMovies';
|
||||
import RomanceMoviesReducer from './reducerRomanceMovies';
|
||||
import DocumentaryReducer from './reducerDocumentary';
|
||||
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
trending: TrendingReducer,
|
||||
netflixOriginals: NetflixOriginalsReducer,
|
||||
topRated: TopRatedReducer,
|
||||
action: ActionMoviesReducer,
|
||||
comedy: ComedyMoviesReducer,
|
||||
horror: HorrorMoviesReducer,
|
||||
romance: RomanceMoviesReducer,
|
||||
documentary: DocumentaryReducer
|
||||
});
|
||||
|
||||
export default rootReducer;
|
||||
11
src/store/reducers/reducerActionMovies.js
Normal file
11
src/store/reducers/reducerActionMovies.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_ACTION_MOVIES } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_ACTION_MOVIES:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerComedyMovies.js
Normal file
11
src/store/reducers/reducerComedyMovies.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_COMEDY_MOVIES } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_COMEDY_MOVIES:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerDocumentary.js
Normal file
11
src/store/reducers/reducerDocumentary.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_DOCUMENTARIES } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_DOCUMENTARIES:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerHorrorMovies.js
Normal file
11
src/store/reducers/reducerHorrorMovies.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_HORROR_MOVIES } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_HORROR_MOVIES:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerNetflixOriginals.js
Normal file
11
src/store/reducers/reducerNetflixOriginals.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_NETFLIX_ORIGINALS } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_NETFLIX_ORIGINALS:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerRomanceMovies.js
Normal file
11
src/store/reducers/reducerRomanceMovies.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_ROMANCE_MOVIES } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_ROMANCE_MOVIES:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerTopRated.js
Normal file
11
src/store/reducers/reducerTopRated.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_TOP_RATED } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_TOP_RATED:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
11
src/store/reducers/reducerTrending.js
Normal file
11
src/store/reducers/reducerTrending.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { FETCH_TRENDING } from '../actions/index';
|
||||
|
||||
export default function (state = {}, action) {
|
||||
switch (action.type) {
|
||||
case FETCH_TRENDING:
|
||||
const data = action.payload.data.results;
|
||||
return { ...state, data }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user