Files
Musify/web-player/src/routes/(app)/albums/[id]/+page.svelte
T

126 lines
3.7 KiB
Svelte

<script lang="ts">
import { albumCover } from '$lib/utils/hrefs';
import { player } from '$lib/player/player.svelte';
import PlayAllButton from '$lib/components/music/PlayAllButton.svelte';
import X from '@lucide/svelte/icons/x';
import Plus from '@lucide/svelte/icons/plus';
import Page from '$lib/components/ui/layout/Page.svelte';
import PageHeader from '$lib/components/ui/layout/PageHeader.svelte';
import Modal from '$lib/components/ui/overlay/Modal.svelte';
import ConfirmDialog from '$lib/components/ui/overlay/ConfirmDialog.svelte';
import Alert from '$lib/components/ui/primitives/Alert.svelte';
import Artwork from '$lib/components/ui/media/Artwork.svelte';
import AlbumForm from '$lib/components/ui/forms/AlbumForm.svelte';
import Button from '$lib/components/ui/primitives/Button.svelte';
import BackLink from '$lib/components/ui/primitives/BackLink.svelte';
import SectionHeading from '$lib/components/ui/layout/SectionHeading.svelte';
import TrackList from '$lib/components/music/TrackList.svelte';
import { albumMeta } from '$lib/utils/format';
let { data, form } = $props();
const album = $derived(data.album);
const tracks = $derived(data.tracks);
const library = $derived(data.library);
const isOwner = $derived(data.isOwner);
let editing = $state(false);
let confirmingDelete = $state(false);
function playTrackFrom(index: number) {
player.playOrToggle(tracks, index);
}
function playLibraryFrom(index: number) {
player.playOrToggle(library, index);
}
</script>
<svelte:head>
<title>{album.title}</title>
<meta name="description" content="Álbum {album.title}." />
</svelte:head>
<Page>
<BackLink
href={isOwner ? '/albums' : '/'}
label={isOwner ? 'Volver a tus álbumes' : 'Volver al inicio'}
/>
<PageHeader
eyebrow="Álbum"
title={album.title}
description={album.description ?? undefined}
meta={albumMeta(album.releaseYear, tracks.length)}
>
{#snippet cover()}
<Artwork
src={albumCover(album.id, 'large')}
trackIds={tracks.map((track) => track.id)}
size="hero"
alt={album.title}
class="shrink-0"
/>
{/snippet}
{#snippet actions()}
<PlayAllButton items={tracks} />
{#if isOwner}
<Button size="sm" variant="secondary" onclick={() => (editing = true)}>Editar</Button>
<Button size="sm" variant="secondary" onclick={() => (confirmingDelete = true)}>
Eliminar
</Button>
{/if}
{/snippet}
</PageHeader>
{#if form?.message}
<Alert tone="danger" class="mb-6">{form.message}</Alert>
{/if}
{#if tracks.length > 0}
<TrackList
{tracks}
onPlay={playTrackFrom}
rowAction={isOwner
? { action: '?/removeTrack', icon: X, label: 'Quitar del álbum' }
: undefined}
/>
{/if}
{#if isOwner && library.length > 0}
<div class="mt-10 sm:mt-12">
<SectionHeading title="Tus canciones subidas" />
<TrackList
tracks={library}
index={false}
onPlay={playLibraryFrom}
rowAction={{ action: '?/addTrack', icon: Plus, label: 'Añadir al álbum' }}
/>
</div>
{/if}
</Page>
<Modal open={editing} onClose={() => (editing = false)} title="Editar álbum">
<AlbumForm
action="?/edit"
initialTitle={album.title}
initialDescription={album.description ?? ''}
initialReleaseYear={album.releaseYear ?? undefined}
coverFallbackUrl={albumCover(album.id, 'medium')}
formMessage={form?.message}
submitLabel="Guardar"
submittingLabel="Guardando…"
onCancel={() => (editing = false)}
onSuccess={() => (editing = false)}
/>
</Modal>
<ConfirmDialog
open={confirmingDelete}
onClose={() => (confirmingDelete = false)}
title="¿Eliminar «{album.title}»?"
description="Esta acción no se puede deshacer. Las canciones que contiene seguirán en tu biblioteca."
confirmLabel="Eliminar"
action="?/delete"
/>