Separate responsibilities: start-listening command, API-side JSON converters, bulk track endpoints, mix kinds

This commit is contained in:
2026-09-24 12:14:53 +02:00
parent 75d0c0817e
commit 0fa033faff
64 changed files with 2903 additions and 651 deletions
@@ -54,8 +54,9 @@ export const actions: Actions = {
if (!trackId) return fail(400, { message: 'Falta la canción.' });
const api = createApiClient({ fetch, accessToken });
const result = await api.POST('/albums/{albumId}/tracks/{trackId}', {
params: { path: { albumId: params.id, trackId } }
const result = await api.POST('/albums/{id}/tracks', {
params: { path: { id: params.id } },
body: { trackIds: [trackId] }
});
const failure = unwrapOrFail(result, 'No se pudo añadir la canción.');
if (failure) return failure;
@@ -18,11 +18,12 @@
import ContextMenu from '$lib/components/ui/overlay/ContextMenu.svelte';
import ListPlus from '@lucide/svelte/icons/list-plus';
import { createTrackMenu } from '$lib/state/menus.svelte';
import { mixItemTrack } from '$lib/data/mixes';
import { mixItemTrack, mixText } from '$lib/data/mixes';
let { data, form } = $props();
const mix = $derived(data.mix);
const text = $derived(mixText(mix));
const items = $derived(mix.items);
const tracks = $derived(items.map(mixItemTrack));
const queue = $derived(tracks.map(toQueueItem));
@@ -49,8 +50,8 @@
</script>
<svelte:head>
<title>{mix.title}</title>
<meta name="description" content="Mezcla {mix.title}, hecha para ti." />
<title>{text.title}</title>
<meta name="description" content="Mezcla {text.title}, hecha para ti." />
</svelte:head>
<Page>
@@ -58,15 +59,15 @@
<PageHeader
eyebrow="Mezcla"
title={mix.title}
description={mix.subtitle ?? undefined}
title={text.title}
description={text.subtitle}
meta="{plural(items.length, 'canción', 'canciones')} · {fmtTime(totalSeconds)}"
>
{#snippet cover()}
<Artwork
trackIds={items.map((item) => item.trackId)}
size="hero"
alt={mix.title}
alt={text.title}
class="shrink-0"
/>
{/snippet}