Add button to refresh the movie details

This commit is contained in:
Grégoire Delattre 2016-11-23 21:03:50 +01:00
parent 77da13200e
commit fa48dcac5d
3 changed files with 81 additions and 12 deletions

View File

@ -69,6 +69,13 @@ export function getUserInfos() {
) )
} }
export function getMovieDetails(imdb_id) {
return request(
'MOVIE_GET_DETAILS',
configureAxios().get(`/movies/${imdb_id}/get_details`)
)
}
export function fetchMovies(url) { export function fetchMovies(url) {
return request( return request(
'MOVIE_LIST_FETCH', 'MOVIE_LIST_FETCH',

View File

@ -64,29 +64,63 @@ function MovieDetails(props) {
return ( return (
<div className="col-xs-7 col-md-4"> <div className="col-xs-7 col-md-4">
<div className="movie-detail affix"> <div className="movie-detail affix">
<h1 className="hidden-xs">{props.data.title}</h1> <h1 className="hidden-xs">{props.movie.title}</h1>
<h3 className="visible-xs">{props.data.title}</h3> <h3 className="visible-xs">{props.movie.title}</h3>
<p> <p>
<i className="fa fa-clock-o"></i> <i className="fa fa-clock-o"></i>
{props.data.runtime} min {props.movie.runtime} min
</p> </p>
<p> <p>
<i className="fa fa-star-o"></i> <i className="fa fa-star-o"></i>
{props.data.rating} <small>({props.data.votes} counts)</small> {props.movie.rating} <small>({props.movie.votes} counts)</small>
</p> </p>
<p className="movie-plot">{props.data.plot}</p> <p className="movie-plot">{props.movie.plot}</p>
</div> </div>
<MovieButtons {...props} />
</div> </div>
); );
} }
class MovieButtons extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.props.getMovieDetails(this.props.movie.imdb_id);
}
render() {
const imdb_link = 'http://www.imdb.com/title/' + this.props.movie.imdb_id;
return (
<div className="hidden-xs movie-details-buttons btn-toolbar">
<a type="button" className="btn btn-default" onClick={this.handleClick}>
{this.props.fetching ||
<span>
<i className="fa fa-refresh"></i> Refresh
</span>
}
{this.props.fetching &&
<span>
<i className="fa fa-spin fa-refresh"></i> Refreshing
</span>
}
</a>
<a type="button" className="btn btn-warning" href="#">
<i className="fa fa-external-link"></i> IMDB
</a>
</div>
);
}
}
export default class MovieList extends React.Component { export default class MovieList extends React.Component {
componentWillMount() { componentWillMount() {
this.props.fetchMovies(this.props.moviesUrl); this.props.fetchMovies(this.props.moviesUrl);
} }
render() { render() {
const movies = this.props.movieStore.movies; const movies = this.props.movieStore.movies;
const index = this.props.movieStore.selectedMovieIndex; const index = this.props.movieStore.selectedMovie.index;
const selectedMovie = movies[index]; const selectedMovie = movies[index];
return ( return (
<div className="row" id="movie-library"> <div className="row" id="movie-library">
@ -96,7 +130,11 @@ export default class MovieList extends React.Component {
onClick={this.props.selectMovie} onClick={this.props.selectMovie}
/> />
{selectedMovie && {selectedMovie &&
<MovieDetails data={selectedMovie} /> <MovieDetails
movie={selectedMovie}
fetching={this.props.movieStore.selectedMovie.fetchingDetails}
getMovieDetails={this.props.getMovieDetails}
/>
} }
</div> </div>
); );

View File

@ -1,6 +1,9 @@
const defaultState = { const defaultState = {
movies: [], movies: [],
selectedMovieIndex: 0, selectedMovie: {
index: 0,
fetchingDetails: false,
},
}; };
export default function movieStore(state = defaultState, action) { export default function movieStore(state = defaultState, action) {
@ -9,11 +12,32 @@ export default function movieStore(state = defaultState, action) {
return Object.assign({}, state, { return Object.assign({}, state, {
movies: action.payload.data, movies: action.payload.data,
}) })
case 'MOVIE_LIST_FETCH_PENDING': case 'MOVIE_GET_DETAILS_PENDING':
return state
case 'SELECT_MOVIE':
return Object.assign({}, state, { return Object.assign({}, state, {
selectedMovieIndex: action.index, selectedMovie: Object.assign({}, state.selectedMovie, {
fetchingDetails: true,
}),
})
case 'MOVIE_GET_DETAILS_FULFILLED':
let movies = state.movies.slice();
movies[state.selectedMovie.index] = action.payload.data;
return Object.assign({}, state, {
movies: movies,
selectedMovie: Object.assign({}, state.selectedMovie, {
fetchingDetails: false,
}),
})
case 'SELECT_MOVIE':
// Don't select the movie if we're fetching another movie's details
if (state.selectedMovie.fetchingDetails) {
return state
}
const selectedMovie = Object.assign({}, state.selectedMovie, {
index: action.index,
})
return Object.assign({}, state, {
selectedMovie: selectedMovie,
}) })
default: default:
return state return state