feat(playlists): single playlist view

This commit is contained in:
2024-12-02 23:20:27 +01:00
parent 19f8fde191
commit b5ace5ac28
16 changed files with 372 additions and 44 deletions

View File

@@ -0,0 +1,78 @@
<script lang="ts">
import { getLibraryState } from '$lib/library.svelte';
import { page } from '$app/stores';
import PlaylistCover from '$lib/components/groove/PlaylistCover.svelte';
import dayjs from 'dayjs';
import * as Table from '$lib/components/ui/table';
import duration from 'dayjs/plugin/duration';
import { getCoverUrl } from '$lib/covers';
import Play from 'virtual:icons/lucide/play';
import { getPlayerState } from '$lib/player.svelte';
import { Button } from '$lib/components/ui/button';
dayjs.extend(duration);
const library = getLibraryState();
const player = getPlayerState();
let playlist = $derived(library.playlists.find((p) => p.id === Number($page.params.id)));
let totalDuration = $derived<number>(
playlist?.tracks.reduce((acc, track) => acc + Number(track.duration), 0) ?? 0
);
</script>
{#if playlist}
<div class="flex w-full flex-col gap-8">
<div class="flex flex-row items-center justify-center gap-4">
<div class="relative w-56 overflow-hidden rounded-lg shadow-2xl shadow-primary/50">
<PlaylistCover tracks={playlist.tracks} />
</div>
<div class="flex flex-col">
<h4 class="text-xl font-semibold tracking-tight">{playlist.name}</h4>
<p class="text-sm text-muted-foreground">
{playlist.tracks.length} track{playlist.tracks.length !== 1 ? 's' : ''}
</p>
<p class="text-sm text-muted-foreground">
{dayjs.duration(totalDuration, 'milliseconds').format('HH:mm:ss')}
</p>
</div>
</div>
<div class="mx-4">
<div class="mb-2">
<Button size="icon" onclick={() => player.playPlaylist(playlist.id, fetch)}><Play /></Button
>
</div>
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head class="w-0">Position</Table.Head>
<Table.Head class="w-0">Track</Table.Head>
<Table.Head class="w-0"></Table.Head>
<Table.Head class="w-0">Artist</Table.Head>
<Table.Head class="text-right">Duration</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
<!-- formaction="/tracks/{track.hash}?/play" -->
{#each playlist.tracks as track, i}
<Table.Row class="select-none" ondblclick={() => player.playTrack(track.hash, fetch)}>
<Table.Cell class="text-center">{i + 1}</Table.Cell>
<Table.Cell class="w-0">
<img class="overflow-hidden rounded-md" src={getCoverUrl(track.hash)} alt="" />
</Table.Cell>
<Table.Cell class="text-nowrap">{track.name}</Table.Cell>
<Table.Cell class="w-fit text-nowrap">{track.artistName}</Table.Cell>
<Table.Cell class="text-right"
>{dayjs
.duration(Number(track.duration), 'milliseconds')
.format('mm:ss')}</Table.Cell
>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</div>
</div>
{:else}
404
{/if}