106 lines
2.6 KiB
Svelte
106 lines
2.6 KiB
Svelte
<!-- TRACES: UR-036 | JA-030, JA-031 | DR-041 -->
|
|
<script lang="ts">
|
|
import type { MediaItem, Library } from "$lib/api/types";
|
|
import { auth } from "$lib/stores/auth";
|
|
import { onMount } from "svelte";
|
|
import LibraryGrid from "./LibraryGrid.svelte";
|
|
import CachedImage from "$lib/components/common/CachedImage.svelte";
|
|
import { goto } from "$app/navigation";
|
|
|
|
interface Props {
|
|
person: MediaItem;
|
|
}
|
|
|
|
let { person }: Props = $props();
|
|
|
|
let movies = $state<MediaItem[]>([]);
|
|
let series = $state<MediaItem[]>([]);
|
|
let loading = $state(true);
|
|
|
|
onMount(async () => {
|
|
await loadFilmography();
|
|
});
|
|
|
|
async function loadFilmography() {
|
|
loading = true;
|
|
try {
|
|
const repo = auth.getRepository();
|
|
const result = await repo.getItemsByPerson(person.id, {
|
|
limit: 100,
|
|
includeItemTypes: ["Movie", "Series"],
|
|
});
|
|
|
|
// Separate movies and series
|
|
movies = result.items.filter(item => item.type === "Movie");
|
|
series = result.items.filter(item => item.type === "Series");
|
|
} catch (e) {
|
|
console.error("Failed to load filmography:", e);
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
|
|
function handleItemClick(item: MediaItem | Library) {
|
|
goto(`/library/${item.id}`);
|
|
}
|
|
</script>
|
|
|
|
<div class="space-y-8">
|
|
<!-- Person header -->
|
|
<div class="flex gap-6 pt-4">
|
|
<!-- Profile image -->
|
|
<div class="flex-shrink-0 w-48">
|
|
<CachedImage
|
|
itemId={person.id}
|
|
imageType="Primary"
|
|
tag={person.primaryImageTag}
|
|
maxWidth={400}
|
|
alt={person.name}
|
|
class="w-full rounded-lg shadow-lg"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Info -->
|
|
<div class="flex-1 space-y-4">
|
|
<h1 class="text-3xl font-bold text-white">{person.name}</h1>
|
|
|
|
<span class="inline-block px-2 py-1 bg-[var(--color-surface)] rounded text-sm text-gray-400">
|
|
Person
|
|
</span>
|
|
|
|
{#if person.overview}
|
|
<p class="text-gray-300 leading-relaxed max-w-2xl">{person.overview}</p>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filmography - separated by type -->
|
|
<div class="space-y-8">
|
|
{#if movies.length > 0}
|
|
<LibraryGrid
|
|
title="Movies"
|
|
items={movies}
|
|
{loading}
|
|
showViewToggle={false}
|
|
onItemClick={handleItemClick}
|
|
/>
|
|
{/if}
|
|
|
|
{#if series.length > 0}
|
|
<LibraryGrid
|
|
title="TV Series"
|
|
items={series}
|
|
{loading}
|
|
showViewToggle={false}
|
|
onItemClick={handleItemClick}
|
|
/>
|
|
{/if}
|
|
|
|
{#if !loading && movies.length === 0 && series.length === 0}
|
|
<div class="text-center py-12 text-gray-400">
|
|
<p>No filmography found</p>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|