jellytau/src/lib/components/library/PersonDetailView.svelte
Duncan Tourolle 3a9c126dfe
Some checks failed
🏗️ Build and Test JellyTau / Run Tests (push) Failing after 14s
🏗️ Build and Test JellyTau / Build Android APK (push) Has been skipped
Traceability Validation / Check Requirement Traces (push) Failing after 1s
Fix warnings and update tracability
2026-02-28 20:54:25 +01:00

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>