flesh out anime page
This commit is contained in:
@@ -30,6 +30,7 @@ export async function getAnimeList(db: ClientDb, limit = DEFAULT_LIST_LIMIT) {
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
malId: anime.malId,
|
||||
aniListId: anime.aniListId,
|
||||
})
|
||||
.from(anime)
|
||||
.orderBy(desc(anime.year), desc(anime.seasonId), desc(anime.annId))
|
||||
@@ -60,6 +61,7 @@ export async function searchAnimeByName(
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
malId: anime.malId,
|
||||
aniListId: anime.aniListId,
|
||||
})
|
||||
.from(anime)
|
||||
.where(like(anime.mainName, pattern))
|
||||
@@ -84,6 +86,7 @@ export async function getAnimeWithSongsByAnnId(db: ClientDb, annId: number) {
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
malId: anime.malId,
|
||||
aniListId: anime.aniListId,
|
||||
})
|
||||
.from(anime)
|
||||
.where(eq(anime.annId, annId))
|
||||
@@ -142,6 +145,7 @@ export async function getSongsForMalAnimeIds(
|
||||
.select({
|
||||
annId: anime.annId,
|
||||
malId: anime.malId,
|
||||
aniListId: anime.aniListId,
|
||||
animeName: anime.mainName,
|
||||
year: anime.year,
|
||||
seasonId: anime.seasonId,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import { invalidate } from "$app/navigation";
|
||||
import SongEntry from "$lib/components/SongEntry.svelte";
|
||||
import { db as clientDb } from "$lib/db/client-db";
|
||||
import { addAllToQueue, playAllNext } from "$lib/player/player.svelte";
|
||||
import { trackFromSongRow } from "$lib/player/types";
|
||||
import { seasonName } from "$lib/utils/amq";
|
||||
import type { PageData } from "./$types";
|
||||
|
||||
@@ -21,6 +23,31 @@
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
function playableTracks() {
|
||||
const rows = data.animeWithSongs?.songs ?? [];
|
||||
return rows
|
||||
.map((s) =>
|
||||
trackFromSongRow({
|
||||
annSongId: s.annSongId,
|
||||
animeName: data.animeWithSongs?.anime.mainName ?? "Unknown Anime",
|
||||
type: s.type,
|
||||
number: s.number,
|
||||
songName: s.songName,
|
||||
artistName: s.artistName,
|
||||
fileName: s.fileName ?? null,
|
||||
}),
|
||||
)
|
||||
.filter((t) => t !== null);
|
||||
}
|
||||
|
||||
function queueAll() {
|
||||
addAllToQueue(playableTracks());
|
||||
}
|
||||
|
||||
function playAllNextFromAnime() {
|
||||
playAllNext(playableTracks());
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !clientDb}
|
||||
@@ -36,19 +63,90 @@
|
||||
{:else if !data.animeWithSongs}
|
||||
<p class="mt-3 text-sm text-muted-foreground">Loading anime…</p>
|
||||
{:else}
|
||||
<header class="mt-2 space-y-1">
|
||||
<header class="mt-2 space-y-2">
|
||||
<h1 class="text-2xl font-semibold">{data.animeWithSongs.anime.mainName}</h1>
|
||||
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{data.animeWithSongs.anime.year}{seasonName(
|
||||
Number(data.animeWithSongs.anime.seasonId),
|
||||
)} • ANN {data.animeWithSongs.anime.annId} • MAL {data.animeWithSongs
|
||||
.anime.malId}
|
||||
{data.animeWithSongs.anime.year}
|
||||
{seasonName(Number(data.animeWithSongs.anime.seasonId))}
|
||||
</p>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2 text-sm">
|
||||
<a
|
||||
class="underline underline-offset-4 hover:no-underline text-muted-foreground hover:text-foreground"
|
||||
href={`https://www.animenewsnetwork.com/encyclopedia/anime.php?id=${data.animeWithSongs.anime.annId}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
ANN
|
||||
</a>
|
||||
|
||||
{#if data.animeWithSongs.anime.malId != null}
|
||||
<a
|
||||
class="underline underline-offset-4 hover:no-underline text-muted-foreground hover:text-foreground"
|
||||
href={`https://myanimelist.net/anime/${data.animeWithSongs.anime.malId}/`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
MAL
|
||||
</a>
|
||||
{:else}
|
||||
<span
|
||||
class="cursor-not-allowed select-none text-muted-foreground/60 underline underline-offset-4 decoration-dotted"
|
||||
title="MAL link unavailable (missing MAL id)"
|
||||
aria-disabled="true"
|
||||
>
|
||||
MAL
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if data.animeWithSongs.anime.aniListId != null}
|
||||
<a
|
||||
class="underline underline-offset-4 hover:no-underline text-muted-foreground hover:text-foreground"
|
||||
href={`https://anilist.co/anime/${data.animeWithSongs.anime.aniListId}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
AniList
|
||||
</a>
|
||||
{:else}
|
||||
<span
|
||||
class="cursor-not-allowed select-none text-muted-foreground/60 underline underline-offset-4 decoration-dotted"
|
||||
title="AniList link unavailable (missing AniList id)"
|
||||
aria-disabled="true"
|
||||
>
|
||||
AniList
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="mt-6">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<h2 class="text-lg font-semibold">Songs</h2>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex h-9 items-center justify-center rounded-md border px-3 text-sm font-medium hover:bg-accent hover:text-accent-foreground disabled:opacity-50"
|
||||
onclick={queueAll}
|
||||
disabled={data.animeWithSongs.songs.length === 0}
|
||||
title="Add all playable songs from this anime to the end of the queue"
|
||||
>
|
||||
Queue all
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex h-9 items-center justify-center rounded-md border px-3 text-sm font-medium hover:bg-accent hover:text-accent-foreground disabled:opacity-50"
|
||||
onclick={playAllNextFromAnime}
|
||||
disabled={data.animeWithSongs.songs.length === 0}
|
||||
title="Insert all playable songs from this anime right after the current track"
|
||||
>
|
||||
Play all next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if data.animeWithSongs.songs.length === 0}
|
||||
<p class="mt-2 text-sm text-muted-foreground">
|
||||
No linked songs found for this anime.
|
||||
|
||||
Reference in New Issue
Block a user