diff --git a/src/api/models/Episode.ts b/src/api/models/Episode.ts index 4afedae6c81eb53b89790e8a6447cea595829fed..2463d618b0b08a7f12d3076cd68cbfaed0a42241 100644 --- a/src/api/models/Episode.ts +++ b/src/api/models/Episode.ts @@ -1,8 +1,8 @@ import {Title} from "./Title"; export interface Episode { - seasonNumber: string | null, - episodeNumber: string | null, + season: string | null, + episode: string | null, airDate: string | null, title: Title } diff --git a/src/api/models/dto/TitleMeta.ts b/src/api/models/dto/TitleMeta.ts index d81fb592959a9b053764dcc574ab3946f95fe809..a6883fb70a96d35d8fd779e125dabed346fa3b46 100644 --- a/src/api/models/dto/TitleMeta.ts +++ b/src/api/models/dto/TitleMeta.ts @@ -1,7 +1,7 @@ +import {Episode} from "../Episode"; import {Title} from "../Title"; export interface TitleMeta { title: Title, - show: Title | null, - episodes: Title[], + show: Episode | null, } diff --git a/src/routes/main/MainPage.tsx b/src/routes/main/MainPage.tsx index e02075f1af5450e715cd0bee86d83623be00ac18..5b3d18a4b11c8bebdf176a9c8328d76792f6ac3e 100644 --- a/src/routes/main/MainPage.tsx +++ b/src/routes/main/MainPage.tsx @@ -2,6 +2,7 @@ import React, {useEffect, useState} from "react"; import {createUseStyles} from "react-jss"; import {Link} from "react-router-dom"; import {useApiClient} from "../../api/ApiClientContext"; +import {Episode} from "../../api/models/Episode"; import {getLocalizedDescription, getLocalizedName, getLocalizedRating, Title} from "../../api/models/Title"; import {Locale} from "../../util/locale/Locale"; import {sortLexicallyAsc} from "../../util/sort/sortLexically"; @@ -20,6 +21,16 @@ export function MainPage(props: Props) { language: "en", region: "DE", }; + const [episodes, setEpisodes] = useState<{ [key: string]: Episode[] }>({}); + const titlesToLoad = data?.filter(it => it.kind === "show" && episodes[it.ids.uuid] === undefined); + useEffect(() => { + if (titlesToLoad?.length !== undefined && titlesToLoad.length > 0) { + const titlesBeingLoaded = Object.fromEntries(titlesToLoad?.map(it => [it.ids.uuid, []]) || []); + setEpisodes({...titlesBeingLoaded, ...episodes}); + Promise.all(titlesToLoad?.map(it => apiClient.listEpisodes(it.ids.uuid).then(eps => [it.ids.uuid, eps])) || []) + .then(it => setEpisodes({...Object.fromEntries(it), ...episodes})); + } + }, [apiClient, episodes, titlesToLoad]); const classes = useStyles(); @@ -39,9 +50,32 @@ export function MainPage(props: Props) { <p><strong>{rating?.certification}</strong></p> <p><strong>{description?.tagline}</strong></p> <p>{description?.overview}</p> - <p> - <Link to={"/player/" + item.ids.uuid}>Play</Link> - </p> + {item.kind === "movie" && ( + <p> + <Link to={"/player/" + item.ids.uuid}>Play</Link> + </p> + )} + {item.kind === "show" && ( + <ul> + {episodes[item.ids.uuid]?.map(episode => { + const episodeTitle = getLocalizedName(episode.title, locale); + const episodeDescription = getLocalizedDescription(episode.title, locale); + return ( + <li> + <p> + <strong>S{episode.season}E{episode.episode}</strong> – {episode.airDate} + </p> + <p><strong>{episodeTitle?.name}</strong></p> + <p><strong>{episodeDescription?.tagline}</strong></p> + <p>{episodeDescription?.overview}</p> + <p> + <Link to={"/player/" + episode.title.ids.uuid}>Play</Link> + </p> + </li> + ) + })} + </ul> + )} {poster && ( <img className={classes.poster} diff --git a/src/routes/player/Player.tsx b/src/routes/player/Player.tsx index 56e6aaa01c99ed47a1e4d4d25dca7d2f1ce525c9..59055a6b74cbf9843557fc6f8ca49719b78b3fba 100644 --- a/src/routes/player/Player.tsx +++ b/src/routes/player/Player.tsx @@ -17,7 +17,7 @@ interface Props { export function Player(props: Props) { const {media} = props; - const {title, show, episodes} = props.title; + const {title, show} = props.title; const classes = useStyles(); const locale = useLocale(); @@ -44,6 +44,7 @@ export function Player(props: Props) { <div> <Link to="/">Back</Link> <p>{name?.name}</p> + <p>{show && getLocalizedName(show.title, locale)?.name}</p> {video} <p style={{fontVariant: "tabular-nums"}}>{formatDuration(position)} / {formatDuration(duration)}</p> <SeekBar