4412a4af0c
Add Artists and Albums nav entries, rename root label from Library to Home. Migrate all three ArtistRow call sites (search, search/artists, library/liked) to ArtistCard with grid wrapper; delete ArtistRow component and its test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
3.5 KiB
Svelte
100 lines
3.5 KiB
Svelte
<script lang="ts">
|
|
import {
|
|
createLikedTracksInfiniteQuery,
|
|
createLikedAlbumsInfiniteQuery,
|
|
createLikedArtistsInfiniteQuery
|
|
} from '$lib/api/likes';
|
|
import ArtistCard from '$lib/components/ArtistCard.svelte';
|
|
import AlbumCard from '$lib/components/AlbumCard.svelte';
|
|
import TrackRow from '$lib/components/TrackRow.svelte';
|
|
|
|
const artistsStore = $derived(createLikedArtistsInfiniteQuery());
|
|
const albumsStore = $derived(createLikedAlbumsInfiniteQuery());
|
|
const tracksStore = $derived(createLikedTracksInfiniteQuery());
|
|
|
|
const artistsQuery = $derived($artistsStore);
|
|
const albumsQuery = $derived($albumsStore);
|
|
const tracksQuery = $derived($tracksStore);
|
|
|
|
const artists = $derived(artistsQuery?.data?.pages?.flatMap((p) => p.items) ?? []);
|
|
const albums = $derived(albumsQuery?.data?.pages?.flatMap((p) => p.items) ?? []);
|
|
const tracks = $derived(tracksQuery?.data?.pages?.flatMap((p) => p.items) ?? []);
|
|
|
|
const artistsTotal = $derived(artistsQuery?.data?.pages?.[0]?.total ?? 0);
|
|
const albumsTotal = $derived(albumsQuery?.data?.pages?.[0]?.total ?? 0);
|
|
const tracksTotal = $derived(tracksQuery?.data?.pages?.[0]?.total ?? 0);
|
|
</script>
|
|
|
|
<div class="space-y-6">
|
|
<h1 class="text-2xl font-semibold">Liked</h1>
|
|
|
|
<section>
|
|
<h2 class="mb-2 text-lg font-semibold">Artists</h2>
|
|
{#if artistsTotal === 0}
|
|
<p class="text-text-secondary">No liked artists yet.</p>
|
|
{:else}
|
|
<div class="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
|
|
{#each artists as a (a.id)}
|
|
<ArtistCard artist={a} />
|
|
{/each}
|
|
</div>
|
|
{#if artistsQuery?.hasNextPage}
|
|
<button
|
|
type="button"
|
|
class="mt-2 w-full rounded bg-surface py-2 text-sm hover:bg-surface-hover disabled:opacity-60"
|
|
disabled={artistsQuery.isFetchingNextPage}
|
|
onclick={() => artistsQuery.fetchNextPage()}
|
|
>
|
|
{artistsQuery.isFetchingNextPage ? 'Loading…' : 'Load more'}
|
|
</button>
|
|
{/if}
|
|
{/if}
|
|
</section>
|
|
|
|
<section>
|
|
<h2 class="mb-2 text-lg font-semibold">Albums</h2>
|
|
{#if albumsTotal === 0}
|
|
<p class="text-text-secondary">No liked albums yet.</p>
|
|
{:else}
|
|
<div class="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
|
|
{#each albums as al (al.id)}
|
|
<AlbumCard album={al} />
|
|
{/each}
|
|
</div>
|
|
{#if albumsQuery?.hasNextPage}
|
|
<button
|
|
type="button"
|
|
class="mt-2 w-full rounded bg-surface py-2 text-sm hover:bg-surface-hover disabled:opacity-60"
|
|
disabled={albumsQuery.isFetchingNextPage}
|
|
onclick={() => albumsQuery.fetchNextPage()}
|
|
>
|
|
{albumsQuery.isFetchingNextPage ? 'Loading…' : 'Load more'}
|
|
</button>
|
|
{/if}
|
|
{/if}
|
|
</section>
|
|
|
|
<section>
|
|
<h2 class="mb-2 text-lg font-semibold">Tracks</h2>
|
|
{#if tracksTotal === 0}
|
|
<p class="text-text-secondary">No liked tracks yet.</p>
|
|
{:else}
|
|
<div class="overflow-hidden rounded border border-border">
|
|
{#each tracks as t, i (t.id)}
|
|
<TrackRow tracks={tracks} index={i} />
|
|
{/each}
|
|
</div>
|
|
{#if tracksQuery?.hasNextPage}
|
|
<button
|
|
type="button"
|
|
class="mt-2 w-full rounded bg-surface py-2 text-sm hover:bg-surface-hover disabled:opacity-60"
|
|
disabled={tracksQuery.isFetchingNextPage}
|
|
onclick={() => tracksQuery.fetchNextPage()}
|
|
>
|
|
{tracksQuery.isFetchingNextPage ? 'Loading…' : 'Load more'}
|
|
</button>
|
|
{/if}
|
|
{/if}
|
|
</section>
|
|
</div>
|