diff --git a/src/components/season/EpisodesList.js b/src/components/season/EpisodesList.js new file mode 100644 index 00000000..43243569 --- /dev/null +++ b/src/components/season/EpisodesList.js @@ -0,0 +1,59 @@ +import React from "react"; +import { Calendar } from "react-bytesize-icons"; +import Img from "react-cool-img"; +import { Link } from "react-router-dom"; +import { COVER_URL, FALLBACK_IMAGE } from "../../constants"; + +const EpisodesList = ({ showName, tvId, seasonNumber, episodes }) => + episodes && episodes.length > 0 ? ( +
+
Episodes
+
+ {episodes.map((episode, i) => { + const { name, overview, episode_number, still_path, air_date } = + episode; + return ( + +
+
+ {name} +
+
+
+ {name} + + + Aired {air_date} + + + Episode {episode_number} + +
+

{overview}

+
+
+ + ); + })} +
+
+ ) : ( + "" + ); + +export default EpisodesList; diff --git a/src/components/season/SeasonsList.js b/src/components/season/SeasonsList.js index 6a6aa12d..a5173e4e 100644 --- a/src/components/season/SeasonsList.js +++ b/src/components/season/SeasonsList.js @@ -32,7 +32,7 @@ const SeasonsList = ({ showName, tvId, seasons }) =>
{name} - + Aired {air_date}
-

{overview}

+

{overview}

diff --git a/src/containers/episode-item/index.js b/src/containers/episode-item/index.js new file mode 100644 index 00000000..61213923 --- /dev/null +++ b/src/containers/episode-item/index.js @@ -0,0 +1,171 @@ +import React, { Component } from "react"; +import { getItemTrailer } from "../../utils"; +import theMovieDb from "themoviedb-javascript-library"; +import isEmpty from "lodash/isEmpty"; +import NoDataFound from "../../components/shared/NoDataFound"; +import Loader from "../../components/shared/Loader"; +import Player from "../../components/item/Player"; +import ItemDetails from "../../components/item/ItemDetails"; +import GA from "react-ga"; + +class EpisodeItem extends Component { + constructor(props) { + super(props); + this.state = { + playing: false, + itemDetails: {}, + loading: true, + }; + } + + componentDidMount() { + const { id, number, episode } = this.props.match.params; + this.getItemById(id, number, episode); + } + + componentDidUpdate(prevProps) { + const { id, number, episode } = this.props.match.params; + if (id !== prevProps.match.params.id) { + this.getItemById(id, number, episode); + } + } + + getItemById = (id, season_number, episode_number) => { + theMovieDb.tvEpisodes.getById( + { + id, + season_number, + episode_number, + append_to_response: + "videos,recommendations,images&include_image_language=en,null", + }, + (data) => this.successCB(data, id, season_number, episode_number), + this.errorCB + ); + }; + + successCB = (data, id, season_number, episode_number) => { + const fetchedData = JSON.parse(data); + this.setState( + { + loading: false, + itemDetails: fetchedData, + }, + () => { + theMovieDb.tv.getCredits( + { id, season_number, episode_number }, + this.creditsSuccessCB, + this.errorCB + ); + } + ); + }; + + errorCB = (data) => { + if (data) { + this.setState({ + loading: false, + tmdbResponse: JSON.parse(data).status_message, + }); + } else { + this.setState({ + loading: false, + itemDetails: {}, + }); + } + }; + + creditsSuccessCB = (data) => { + const { itemDetails } = this.state; + const fetchedData = JSON.parse(data); + this.setState({ + itemDetails: { ...itemDetails, casts: fetchedData }, + }); + }; + + handlePlayerState = () => { + const { playing } = this.state; + this.setState( + { + playing: !playing, + }, + () => { + this.state.playing && + GA.event({ + category: "Player", + action: "Play trailer for tv episode", + }); + } + ); + }; + + render() { + const { playing, itemDetails, tmdbResponse, loading } = this.state; + const { + name, + status, + overview, + vote_average, + first_air_date, + still_path, + backdrop_path, + genres, + homepage, + budget, + revenue, + runtime, + imdb_id, + videos, + images, + production_companies, + } = itemDetails; + + if (!isEmpty(itemDetails)) { + var { stills } = images; + var { results } = videos; + } + + if (!isEmpty(itemDetails.casts)) { + var { cast, crew } = itemDetails.casts; + } + + return !isEmpty(itemDetails) ? ( + <> + {results.length > 0 && ( + + )} + + + ) : tmdbResponse ? ( + + ) : loading ? ( + + ) : null; + } +} + +export default EpisodeItem; diff --git a/src/containers/season-item/index.js b/src/containers/season-item/index.js index 7a22a3a8..ff8416ad 100644 --- a/src/containers/season-item/index.js +++ b/src/containers/season-item/index.js @@ -1,4 +1,4 @@ -import React, { Component, lazy } from "react"; +import React, { Component } from "react"; import { getItemTrailer } from "../../utils"; import theMovieDb from "themoviedb-javascript-library"; import isEmpty from "lodash/isEmpty"; @@ -6,6 +6,7 @@ import NoDataFound from "../../components/shared/NoDataFound"; import Loader from "../../components/shared/Loader"; import Player from "../../components/item/Player"; import ItemDetails from "../../components/item/ItemDetails"; +import EpisodesList from "../../components/season/EpisodesList"; import GA from "react-ga"; class SeasonItem extends Component { @@ -115,7 +116,7 @@ class SeasonItem extends Component { imdb_id, videos, images, - seasons, + episodes, production_companies, } = itemDetails; @@ -153,12 +154,18 @@ class SeasonItem extends Component { budget={budget} revenue={revenue} imdb={imdb_id} - seasons={seasons} backdrops={posters || backdrops} cast={cast} crew={crew} productionCompanies={production_companies} - /> + > + + ) : tmdbResponse ? ( diff --git a/src/routes/index.js b/src/routes/index.js index 8a4e24f6..bf82f69c 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -8,6 +8,7 @@ import MovieItem from "../containers/movie-item"; import TvShows from "../containers/tv-shows"; import TvItem from "../containers/tv-item"; import SeasonItem from "../containers/season-item"; +import EpisodeItem from "../containers/episode-item"; import Person from "../containers/person"; import Search from "../containers/search"; import Settings from "../containers/settings"; @@ -40,6 +41,11 @@ const MyRouter = () => ( path="/tv/:id/:name/seasons/:number" render={renderComponent(SeasonItem)} /> + {/* Other Features */}