updated folder structure
This commit is contained in:
106
src/components/DisplayMovieRow.js
Normal file
106
src/components/DisplayMovieRow.js
Normal file
@@ -0,0 +1,106 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from 'swiper';
|
||||
|
||||
// install Swiper components
|
||||
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y]);
|
||||
|
||||
export default class DisplayMovieRow extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
width: window.innerWidth,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
}
|
||||
|
||||
componentWillUnMount() {
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
}
|
||||
|
||||
handleResize = (e) => {
|
||||
this.setState({ width: window.innerWidth });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { width } = this.state;
|
||||
let netflixUrl = false;
|
||||
if (
|
||||
this.props.url ===
|
||||
`/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`
|
||||
) {
|
||||
netflixUrl = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="movieShowcase__heading">{this.props.title}</h1>
|
||||
<Swiper
|
||||
className="movieShowcase__container"
|
||||
navigation={true}
|
||||
grabCursor={false}
|
||||
draggable={false}
|
||||
loop={true}
|
||||
loopAdditionalSlides={
|
||||
width >= 1378 ? 4 : width >= 998 ? 3 : width >= 625 ? 2 : 2
|
||||
}
|
||||
breakpoints={{
|
||||
1378: {
|
||||
slidesPerView: 5,
|
||||
slidesPerGroup: 5,
|
||||
},
|
||||
998: {
|
||||
slidesPerView: 4,
|
||||
slidesPerGroup: 4,
|
||||
},
|
||||
625: {
|
||||
slidesPerView: 3,
|
||||
slidesPerGroup: 3,
|
||||
},
|
||||
0: {
|
||||
slidesPerView: 2,
|
||||
slidesPerGroup: 2,
|
||||
},
|
||||
}}
|
||||
preventClicksPropagation={true}
|
||||
preventClicks={true}
|
||||
scrollbar={{ draggable: false, hide: true }}
|
||||
slideToClickedSlide={false}
|
||||
pagination={{ clickable: true }}
|
||||
>
|
||||
{this.props.movies.map((movie, idx) => {
|
||||
let movieImageUrl =
|
||||
'https://image.tmdb.org/t/p/w500/' + movie.backdrop_path;
|
||||
if (
|
||||
this.props.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) {
|
||||
return (
|
||||
<SwiperSlide
|
||||
onClick={() => this.props.selectMovieHandler(movie)}
|
||||
key={idx}
|
||||
className={
|
||||
'movieShowcase__container--movie' +
|
||||
(netflixUrl ? '__netflix' : '')
|
||||
}
|
||||
>
|
||||
<img
|
||||
src={movieImageUrl}
|
||||
className="movieShowcase__container--movie-image"
|
||||
/>
|
||||
</SwiperSlide>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</Swiper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
167
src/components/MainContent.js
Normal file
167
src/components/MainContent.js
Normal file
@@ -0,0 +1,167 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import Header from './Header';
|
||||
import Footer from './Footer';
|
||||
import {
|
||||
fetchNetflixOriginals,
|
||||
fetchTrending,
|
||||
fetchTopRated,
|
||||
fetchActionMovies,
|
||||
fetchComedyMovies,
|
||||
fetchDocumentaries,
|
||||
fetchHorrorMovies,
|
||||
} from '../store/actions/index';
|
||||
import DisplayMovieRow from './DisplayMovieRow';
|
||||
|
||||
class MainContent extends Component {
|
||||
state = {
|
||||
/** Will hold our chosen movie to display on the header */
|
||||
selectedMovie: {},
|
||||
movieInfo: [
|
||||
{
|
||||
title: 'Netflix Originals',
|
||||
url: `/discover/tv?api_key=${process.env.API_KEY}&with_networks=213`,
|
||||
movies: [],
|
||||
},
|
||||
{
|
||||
title: 'Trending Now',
|
||||
url: `/trending/all/week?api_key=${process.env.API_KEY}&language=en-US`,
|
||||
movies: [],
|
||||
},
|
||||
{
|
||||
title: 'Top Rated',
|
||||
url: `/movie/top_rated?api_key=${process.env.API_KEY}&language=en-US`,
|
||||
movies: [],
|
||||
},
|
||||
{
|
||||
title: 'Action Movies',
|
||||
url: `/discover/movie?api_key=${process.env.API_KEY}&with_genres=28`,
|
||||
movies: [],
|
||||
},
|
||||
{
|
||||
title: 'Comedy Movies',
|
||||
url: `/discover/tv?api_key=${process.env.API_KEY}&with_genres=35`,
|
||||
movies: [],
|
||||
},
|
||||
{
|
||||
title: 'Horror Movies',
|
||||
url: `/discover/tv?api_key=${process.env.API_KEY}&with_genres=27`,
|
||||
movies: [],
|
||||
},
|
||||
{
|
||||
title: 'Documentaries',
|
||||
url: `/discover/tv?api_key=${process.env.API_KEY}&with_genres=99`,
|
||||
movies: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
componentDidMount = async () => {
|
||||
await this.getMovie();
|
||||
await this.props.fetchNetflixOriginals();
|
||||
await this.props.fetchTrending();
|
||||
await this.props.fetchTopRated();
|
||||
await this.props.fetchActionMovies();
|
||||
await this.props.fetchComedyMovies();
|
||||
await this.props.fetchDocumentaries();
|
||||
await this.props.fetchHorrorMovies();
|
||||
|
||||
const newMoviesArray = this.state.movieInfo.map((movie) => {
|
||||
if (movie.title === 'Netflix Originals') {
|
||||
movie.movies.push(...this.props.netflixOriginals.data);
|
||||
}
|
||||
if (movie.title === 'Trending Now') {
|
||||
movie.movies.push(...this.props.trending.data);
|
||||
}
|
||||
if (movie.title === 'Top Rated') {
|
||||
movie.movies.push(...this.props.topRated.data);
|
||||
}
|
||||
if (movie.title === 'Action Movies') {
|
||||
movie.movies.push(...this.props.actionMovies.data);
|
||||
}
|
||||
if (movie.title === 'Comedy Movies') {
|
||||
movie.movies.push(...this.props.comedyMovies.data);
|
||||
}
|
||||
if (movie.title === 'Documentaries') {
|
||||
movie.movies.push(...this.props.documentaries.data);
|
||||
}
|
||||
if (movie.title === 'Horror Movies') {
|
||||
movie.movies.push(...this.props.horrorMovies.data);
|
||||
}
|
||||
return movie;
|
||||
});
|
||||
await this.setState({ movieInfo: newMoviesArray });
|
||||
};
|
||||
|
||||
getMovie = () => {
|
||||
/** Movie Id for the Narcos series */
|
||||
const movieId = 63351;
|
||||
/** Make Api call to retrieve the details for a single movie */
|
||||
const url = `https://api.themoviedb.org/3/tv/${movieId}?api_key=${process.env.API_KEY}`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((res) => {
|
||||
const movieData = res.data;
|
||||
this.setState({ selectedMovie: movieData });
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="container">
|
||||
<Header movie={this.state.selectedMovie} />
|
||||
<div className="movieShowcase">
|
||||
{this.state.movieInfo.map((info) => {
|
||||
if (info.movies.length > 0) {
|
||||
return (
|
||||
<DisplayMovieRow
|
||||
selectMovieHandler={this.props.selectMovieHandler}
|
||||
key={info.title}
|
||||
title={info.title}
|
||||
url={info.url}
|
||||
movies={info.movies}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
netflixOriginals: state.netflixOriginals,
|
||||
trending: state.trending,
|
||||
topRated: state.topRated,
|
||||
actionMovies: state.action,
|
||||
comedyMovies: state.comedy,
|
||||
documentaries: state.documentary,
|
||||
horrorMovies: state.horror,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return bindActionCreators(
|
||||
{
|
||||
fetchNetflixOriginals,
|
||||
fetchTrending,
|
||||
fetchTopRated,
|
||||
fetchActionMovies,
|
||||
fetchComedyMovies,
|
||||
fetchDocumentaries,
|
||||
fetchHorrorMovies,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MainContent);
|
||||
108
src/components/Navbar.js
Normal file
108
src/components/Navbar.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import React, { Component } from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import _ from 'lodash';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import axios from '../axios-movies';
|
||||
import SearchLogo from '../static/images/search-icon.svg';
|
||||
import NetflixLogo from '../static/images/Netflix_Logo_RGB.png';
|
||||
import BellLogo from '../static/images/bell-logo.svg';
|
||||
import DropdownArrow from '../static/images/drop-down-arrow.svg';
|
||||
import DropdownContent from "../components/DropdownContent";
|
||||
|
||||
class Navbar extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
scrolling: false,
|
||||
userInput: ''
|
||||
}
|
||||
// use to debounce api call
|
||||
this.makeAipCall = _.debounce(this.makeAipCall, 1000)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('scroll', this.handleScroll);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('scroll', this.handleScroll);
|
||||
}
|
||||
|
||||
/** changes the scrolling state depending on the Y-position */
|
||||
handleScroll = () => {
|
||||
if (window.scrollY === 0) {
|
||||
this.setState({ scrolling: false });
|
||||
}
|
||||
else if (window.scrollY > 50) {
|
||||
this.setState({ scrolling: true });
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
this.props.history.push({
|
||||
pathname: '/search',
|
||||
movieRows: results,
|
||||
userInput: searchItem
|
||||
});
|
||||
}
|
||||
|
||||
onLogoClick = () => {
|
||||
// reset input state
|
||||
this.setState({ userInput: '' })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { scrolling } = this.state;
|
||||
|
||||
return (
|
||||
<nav className={"navigation " + (scrolling ? "black" : "")} >
|
||||
<ul className="navigation__container">
|
||||
<NavLink to="/" onClick={() => this.onLogoClick()}>
|
||||
<img className="navigation__container--logo" src={NetflixLogo} alt="" />
|
||||
</NavLink>
|
||||
<DropdownArrow className="navigation__container--downArrow-2"></DropdownArrow>
|
||||
<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">Movies</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--left">
|
||||
<SearchLogo className="logo" />
|
||||
<input
|
||||
value={this.state.userInput}
|
||||
onChange={() => this.onChange(event)}
|
||||
className="navigation__container--left__input"
|
||||
type="text"
|
||||
placeholder="Title, genres, people" />
|
||||
</div>
|
||||
|
||||
<div className="navigation__container-link pseudo-link">KIDS</div>
|
||||
<div className="navigation__container-link pseudo-link">DVD</div>
|
||||
<BellLogo className="navigation__container--bellLogo" />
|
||||
|
||||
<DropdownContent />
|
||||
<DropdownArrow className="navigation__container--downArrow" />
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(Navbar);
|
||||
Reference in New Issue
Block a user