Skip to content

Commit

Permalink
move to using hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
Gil Teitelbaum committed Sep 17, 2020
1 parent d9871bd commit 61ed1d2
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 116 deletions.
27 changes: 8 additions & 19 deletions src/components/movieDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Row, Col } from "react-bootstrap";
import { Link } from "react-router-dom";
import TitleAndContent from "./titleAndContent";


class MovieDetails extends Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -59,31 +58,23 @@ class MovieDetails extends Component {
</Col>
<Col md={6} sm={12} >
<Row>
<Col className="description">
{movie.Rated}
</Col>
<Col className="description">
{movie.Runtime}
</Col>
<Col className="description">
{movie.Genre}
</Col>
<Col className="description">{movie.Rated}</Col>
<Col className="description">{movie.Runtime}</Col>
<Col className="description">{movie.Genre}</Col>
</Row>
<hr></hr>
<Row>
<Col className="description">
{movie.Plot}
</Col>
<Col className="description">{movie.Plot}</Col>
</Row>
{this.displayTitledDataWithLine("Writer:", movie.Writer)}
<TitleAndContent displayLine="true" title="Writer:" content={movie.Writer}></TitleAndContent>
<TitleAndContent title="Actors:" content={movie.Actors}></TitleAndContent>
<TitleAndContent title="Director:" content={movie.Director}></TitleAndContent>
<TitleAndContent title="Country:" content={movie.Country}></TitleAndContent>
{this.displayTitledDataWithLine("Awards:", movie.Awards)}
<TitleAndContent displayLine="true" title="Awards:" content={movie.Awards}></TitleAndContent>
<TitleAndContent title="Metascore:" content={movie.Metascore}></TitleAndContent>
<TitleAndContent title="Imdb Rating:" content={movie.imdbRating}></TitleAndContent>
<TitleAndContent title="Imdb Votes:" content={movie.imdbVotes}></TitleAndContent>
{this.displayTitledDataWithLine("Box Office:", movie.BoxOffice)}
<TitleAndContent displayLine="true" title="Box Office:" content={movie.BoxOffice}></TitleAndContent>
<TitleAndContent title="Production:" content={movie.Production}></TitleAndContent>
</Col>
</Row>
Expand All @@ -94,8 +85,6 @@ class MovieDetails extends Component {
</>
);
}

}

export default MovieDetails;

export default MovieDetails;
135 changes: 63 additions & 72 deletions src/components/movies.jsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,91 @@
import React, { Component } from "react";
import React, { Component, useState } from "react";
import MoviesTable from "./moviesTable";
import restService from '../services/restService';
import config from "../config.json";
import { Form, Row, Col } from "react-bootstrap";
import { toast } from 'react-toastify';


class Movies extends Component {
constructor(props) {
super(props);
this.state = {
movies: [],
totalMovies: 0,
isLoading: false,
didSearch: false,
movieSearchName: null,
movieYear: null,
lastPage: 1,
errors: {}
}
}
export default function Movies(props) {
const [movies, setMovies] = useState([]);
const [totalMovies, setTotalMovies] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const [didSearch, setDidSearch] = useState(false);
const [movieSearchName, setMovieSearchName] = useState(null);
const [movieYear, setMovieYear] = useState(null);
const [lastPage, setLastPage] = useState(1);
const [errors, setErrors] = useState([]);

validate() {
const errors = {};
const { movieSearchName, movieYear } = this.state;
function validate() {
const validationErrors = {};

if (movieSearchName.trim() === '')
errors.movieSearchName = "Name of movie is required";
if (!movieSearchName || movieSearchName.trim() === '')
validationErrors.movieSearchName = "Name of movie is required";
if (movieYear && movieYear.trim().length > 0 && isNaN(parseInt(movieYear.trim()))) {
errors.movieYear = "Year is invalid";
validationErrors.movieYear = "Year is invalid";
}
return errors;

return validationErrors;
}

handleSubmit = event => {
const handleSubmit = event => {
event.preventDefault();
const errors = this.validate();
this.setState({ errors });
for (let key in errors) {
toast.error(errors[key]);
const validationErrors = validate();
setErrors(validationErrors);
for (let key in validationErrors) {
toast.error(validationErrors[key]);
return; // return on first error
}

if (this.state.movieSearchName) {
this.performSearch(1)
if (movieSearchName) {
performSearch(1)
}
}

getMoreMovies = event => {
this.performSearch(this.state.lastPage + 1);
const getMoreMovies = event => {
performSearch(lastPage + 1);
}

getUrl(page) {
let url = config.endpointBase + '&s=' + this.state.movieSearchName;
if (this.state.movieYear)
url += "&y=" + this.state.movieYear;
function getUrl(page) {
let url = config.endpointBase + '&s=' + movieSearchName;
if (movieYear)
url += "&y=" + movieYear;
if (page > 1)
url += "&page=" + page;
return url;
}


async performSearch(page) {
async function performSearch(page) {
try {
this.setState({ isLoading: true });
const moviesRetrieved = await restService.get(this.getUrl(page));
if (page > 1)
this.setState({ movies: this.state.movies.concat(moviesRetrieved.data.Search), totalMovies: moviesRetrieved.data.totalResults });
setIsLoading(true);
const moviesRetrieved = await restService.get(getUrl(page));
if (page > 1) {
let holdMovies = movies.concat(moviesRetrieved.data.Search);
setMovies(holdMovies);
}
else
this.setState({ movies: moviesRetrieved.data.Search, totalMovies: moviesRetrieved.data.totalResults });
this.setState({ isLoading: false, lastPage: page, didSearch: true });
setMovies(moviesRetrieved.data.Search);
setTotalMovies(moviesRetrieved.data.totalResults);
setIsLoading(false);
setDidSearch(true);
setLastPage(page);
} catch (ex) {
this.setState({ isLoading: false });
setIsLoading(false);
if (ex.response && ex.response.status === 404) {
alert("not found")
}
}
}

handleChange = event => {
const { id, value } = event.target;
this.setState(prevState => ({
...prevState,
[id]: value
}));
const handleTitleChange = event => {
setMovieSearchName(event.target.value);
}

showMovies() {
const { totalMovies, movies } = this.state;
const handleYearChange = event => {
setMovieYear(event.target.value);
}

function showMovies() {
return (
<div className="row margin-top-40">
<div className="col">
Expand All @@ -99,24 +96,18 @@ class Movies extends Component {
);
}

render() {
const { isLoading, movies, totalMovies, movieSearchName, movieYear } = this.state;

return (
<>
{isLoading && <p>Loading...</p>}
<Form onSubmit={this.handleSubmit}>
<Row>
<Col className="searchControl" md={8} sm={6} xs={8}><Form.Control id="movieSearchName" onChange={this.handleChange} value={movieSearchName || ""} placeholder="Search for any movie" /></Col>
<Col className="searchControl" md={2} sm={3} xs={4}><Form.Control id="movieYear" onChange={this.handleChange} value={movieYear || ""} placeholder="Year" /></Col>
<Col className="searchControlButton" md={2} sm={3} xs={12}><button disabled={isLoading || !(movieSearchName && movieSearchName.length)} className=" btn-custom wideButton" type="submit">Search</button></Col>
</Row>
</Form >
{this.state.didSearch ? this.showMovies() : null}
{movies && movies.length > 0 && movies.length < totalMovies ? <button className="btn-custom margin-top-10" onClick={this.getMoreMovies}>Show More Movies</button> : null}
</>
);
}
return (
<>
{isLoading && <p>Loading...</p>}
<Form onSubmit={handleSubmit}>
<Row>
<Col className="searchControl" md={8} sm={6} xs={8}><Form.Control id="movieSearchName" onChange={handleTitleChange} value={movieSearchName || ""} placeholder="Search for any movie" /></Col>
<Col className="searchControl" md={2} sm={3} xs={4}><Form.Control id="movieYear" onChange={handleYearChange} value={movieYear || ""} placeholder="Year" /></Col>
<Col className="searchControlButton" md={2} sm={3} xs={12}><button disabled={isLoading || !(movieSearchName && movieSearchName.length)} className=" btn-custom wideButton" type="submit">Search</button></Col>
</Row>
</Form >
{didSearch ? showMovies() : null}
{movies && movies.length > 0 && movies.length < totalMovies ? <button className="btn-custom margin-top-10" onClick={getMoreMovies}>Show More Movies</button> : null}
</>
);
}

export default Movies;
39 changes: 17 additions & 22 deletions src/components/moviesTable.jsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import React, { Component } from "react";
import React from "react";
import { Link } from "react-router-dom";

class MoviesTable extends Component {
render() {
const { movies } = this.props;

return (
<div className="row">
{movies.map(movie => (
<div key={movie.imdbID} className="col-xs-12 col-sm-6 col-md-4 col-lg-3 movieListEntry">
<Link to={'/movies/' + movie.imdbID}>
<img loading="lazy" onError={this.setDefaultSource} className="movieListImage" src={movie.Poster} alt={"Movie poster for " + movie.Title}></img>
<h4 className="movieListTitle">{movie.Title} {"(" + movie.Year + ")"}</h4>
</Link>
</div>
))}
</div>
);
}

setDefaultSource(event) {
export default function MoviesTable(props) {
function setDefaultSource(event) {
event.target.src = "../../noimage.png";
}
}
const { movies } = props;

export default MoviesTable;
return (
<div className="row">
{movies.map(movie => (
<div key={movie.imdbID} className="col-xs-12 col-sm-6 col-md-4 col-lg-3 movieListEntry">
<Link to={'/movies/' + movie.imdbID}>
<img loading="lazy" onError={setDefaultSource} className="movieListImage" src={movie.Poster} alt={"Movie poster for " + movie.Title}></img>
<h4 className="movieListTitle">{movie.Title} {"(" + movie.Year + ")"}</h4>
</Link>
</div>
))}
</div>
);
}
2 changes: 1 addition & 1 deletion src/components/titleAndContent.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react";
import { Row, Col } from "react-bootstrap";


export default function TitleAndContent(props) {
return (
<>
{props.displayLine && <hr></hr>}
<Row>
<Col lg={3} md={4} xs={6} className="title">
{props.title}
Expand Down
4 changes: 2 additions & 2 deletions src/services/restService.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import axios from 'axios';
import { toast } from 'react-toastify';
import logger from "./loggerService";
import { error } from "./loggerService";

axios.interceptors.response.use(null, error => {
if (!error.response || error.response.status < 400 || error.response.status >= 500) {
logger.error("Error getting movies from server - " + error);
error("Error getting movies from server - " + error);
toast.error("an unexpected error happened");
}
return Promise.reject(error);
Expand Down

0 comments on commit 61ed1d2

Please sign in to comment.