feat: Add recommendations, cast and more info to movie page
This commit is contained in:
@@ -194,22 +194,37 @@ export class TmdbApi implements Api<paths> {
|
||||
.then((res) => res.data);
|
||||
|
||||
getPopularSeries = () =>
|
||||
TmdbApiOpen.GET('/3/tv/popular', {
|
||||
this.getClient()
|
||||
.GET('/3/tv/popular', {
|
||||
params: {
|
||||
query: {
|
||||
language: get(settings)?.language
|
||||
}
|
||||
}
|
||||
}).then((res) => res.data?.results || []);
|
||||
})
|
||||
.then((res) => res.data?.results || []);
|
||||
|
||||
getSeriesRecommendations = (tmdbId: number) =>
|
||||
TmdbApiOpen.GET('/3/tv/{series_id}/recommendations', {
|
||||
this.getClient()
|
||||
.GET('/3/tv/{series_id}/recommendations', {
|
||||
params: {
|
||||
path: {
|
||||
series_id: tmdbId
|
||||
}
|
||||
}
|
||||
}).then((res) => res.data?.results || []);
|
||||
})
|
||||
.then((res) => res.data?.results || []);
|
||||
|
||||
getMovieRecommendations = (tmdbId: number) =>
|
||||
this.getClient()
|
||||
.GET('/3/movie/{movie_id}/recommendations', {
|
||||
params: {
|
||||
path: {
|
||||
movie_id: tmdbId
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((res) => res.data?.results || []);
|
||||
|
||||
getEpisode = (
|
||||
seriesId: number,
|
||||
|
||||
@@ -12,10 +12,15 @@
|
||||
import DetachedPage from '../components/DetachedPage/DetachedPage.svelte';
|
||||
import { openMovieMediaManager } from '../components/Modal/modal.store';
|
||||
import { playerState } from '../components/VideoPlayer/VideoPlayer';
|
||||
import { scrollIntoView } from '../selectable';
|
||||
import Carousel from '../components/Carousel/Carousel.svelte';
|
||||
import TmdbPersonCard from '../components/PersonCard/TmdbPersonCard.svelte';
|
||||
import TmdbCard from '../components/Card/TmdbCard.svelte';
|
||||
|
||||
export let id: string;
|
||||
|
||||
const { promise: movieDataP } = useRequest(tmdbApi.getTmdbMovie, Number(id));
|
||||
$: recommendations = tmdbApi.getMovieRecommendations(Number(id));
|
||||
const { promise: jellyfinItemP } = useRequest(
|
||||
(id: string) => jellyfinApi.getLibraryItemFromTmdbId(id),
|
||||
id
|
||||
@@ -32,7 +37,11 @@
|
||||
</script>
|
||||
|
||||
<DetachedPage let:handleGoBack let:registrar>
|
||||
<div class="min-h-screen flex flex-col py-12 px-20 relative">
|
||||
<div class="relative">
|
||||
<Container
|
||||
class="h-[calc(100vh-4rem)] flex flex-col py-16 px-32"
|
||||
on:enter={scrollIntoView({ top: 999 })}
|
||||
>
|
||||
<HeroCarousel
|
||||
urls={$movieDataP.then(
|
||||
(movie) =>
|
||||
@@ -83,7 +92,7 @@
|
||||
class="flex mt-8"
|
||||
focusOnMount
|
||||
on:back={handleGoBack}
|
||||
{registrar}
|
||||
on:mount={registrar}
|
||||
>
|
||||
{#if jellyfinItem}
|
||||
<Button
|
||||
@@ -128,5 +137,69 @@
|
||||
{/await}
|
||||
</div>
|
||||
</HeroCarousel>
|
||||
</Container>
|
||||
<Container on:enter={scrollIntoView({ top: 0 })} class="">
|
||||
{#await $movieDataP then movie}
|
||||
<Carousel scrollClass="px-32" class="mb-8">
|
||||
<div slot="header">Show Cast</div>
|
||||
{#each movie?.credits?.cast?.slice(0, 15) || [] as credit}
|
||||
<TmdbPersonCard on:enter={scrollIntoView({ horizontal: 128 })} tmdbCredit={credit} />
|
||||
{/each}
|
||||
</Carousel>
|
||||
{/await}
|
||||
{#await recommendations then recommendations}
|
||||
<Carousel scrollClass="px-32" class="mb-8">
|
||||
<div slot="header">Recommendations</div>
|
||||
{#each recommendations || [] as recommendation}
|
||||
<TmdbCard item={recommendation} on:enter={scrollIntoView({ horizontal: 128 })} />
|
||||
{/each}
|
||||
</Carousel>
|
||||
{/await}
|
||||
</Container>
|
||||
{#await $movieDataP then movie}
|
||||
<Container class="flex-1 bg-secondary-950 pt-8 px-32" on:enter={scrollIntoView({ top: 0 })}>
|
||||
<h1 class="font-medium tracking-wide text-2xl text-zinc-300 mb-8">More Information</h1>
|
||||
<div class="text-zinc-300 font-medium text-lg flex flex-wrap">
|
||||
<div class="flex-1">
|
||||
<div class="mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Directed By</h2>
|
||||
<div>
|
||||
{movie?.credits.crew
|
||||
?.filter((c) => c.job === 'Director')
|
||||
?.map((c) => c.name)
|
||||
.join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Written By</h2>
|
||||
<div>
|
||||
{movie?.credits.crew
|
||||
?.filter((c) => c.job === 'Writer')
|
||||
?.map((c) => c.name)
|
||||
.join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Languages</h2>
|
||||
<div>
|
||||
{movie?.spoken_languages?.map((language) => language.name).join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Release Date</h2>
|
||||
<div>
|
||||
{new Date(movie?.release_date || 0).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
{/await}
|
||||
</div>
|
||||
</DetachedPage>
|
||||
|
||||
Reference in New Issue
Block a user