From d11362ff572385b2d8950237b08e6ab6bc66b10f Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 3 Dec 2025 07:29:38 -0800 Subject: [PATCH] add weapons and summons collection routes with layout updates - Create weapons route with page, server load, and grid/list views - Create summons route with page, server load, and grid/list views - Enable weapons/summons tabs in collection layout (remove disabled) - Add dynamic "Add" button text based on active entity type - Pass entityType to AddToCollectionModal based on current route --- .../[username]/collection/+layout.svelte | 22 +- .../collection/summons/+page.server.ts | 12 + .../collection/summons/+page.svelte | 275 +++++++++++++++++ .../collection/weapons/+page.server.ts | 12 + .../collection/weapons/+page.svelte | 282 ++++++++++++++++++ 5 files changed, 599 insertions(+), 4 deletions(-) create mode 100644 src/routes/(app)/[username]/collection/summons/+page.server.ts create mode 100644 src/routes/(app)/[username]/collection/summons/+page.svelte create mode 100644 src/routes/(app)/[username]/collection/weapons/+page.server.ts create mode 100644 src/routes/(app)/[username]/collection/weapons/+page.svelte diff --git a/src/routes/(app)/[username]/collection/+layout.svelte b/src/routes/(app)/[username]/collection/+layout.svelte index 142962e7..236d29cd 100644 --- a/src/routes/(app)/[username]/collection/+layout.svelte +++ b/src/routes/(app)/[username]/collection/+layout.svelte @@ -21,6 +21,16 @@ return 'characters' }) + // Map entity type to singular form for modal + const modalEntityType = $derived.by(() => { + if (activeEntityType === 'weapons') return 'weapon' + if (activeEntityType === 'summons') return 'summon' + return 'character' + }) + + // Dynamic button text + const addButtonText = $derived(`Add ${activeEntityType}`) + const username = $derived(data.user?.username || $page.params.username) function handleTabChange(value: string) { @@ -50,8 +60,8 @@ size="small" > Characters - Weapons - Summons + Weapons + Summons {#if data.isOwner} @@ -62,7 +72,7 @@ icon="plus" iconPosition="left" > - Add characters + {addButtonText} {/if} @@ -73,7 +83,11 @@ {#if data.isOwner} - + {/if} diff --git a/src/routes/(app)/[username]/collection/weapons/+page.server.ts b/src/routes/(app)/[username]/collection/weapons/+page.server.ts new file mode 100644 index 00000000..e7cc668f --- /dev/null +++ b/src/routes/(app)/[username]/collection/weapons/+page.server.ts @@ -0,0 +1,12 @@ +import type { PageServerLoad } from './$types' + +export const load: PageServerLoad = async ({ parent }) => { + const { user, isOwner } = await parent() + + // User info comes from layout, collection data is fetched client-side via TanStack Query + // The unified API endpoint handles privacy checks server-side + return { + user, + isOwner + } +} diff --git a/src/routes/(app)/[username]/collection/weapons/+page.svelte b/src/routes/(app)/[username]/collection/weapons/+page.svelte new file mode 100644 index 00000000..fab55b7b --- /dev/null +++ b/src/routes/(app)/[username]/collection/weapons/+page.svelte @@ -0,0 +1,282 @@ + + +
+ +
+ +
+ + +
+ {#if isLoading} +
+ +

Loading collection...

+
+ {:else if isEmpty} +
+ {#if data.isOwner} + +

Your weapon collection is empty

+

Use the "Add weapons" button above to get started

+ {:else} + +

This collection is empty or private

+ {/if} +
+ {:else if currentViewMode === 'grid'} +
+ {#each allWeapons as weapon (weapon.id)} + openWeaponDetails(weapon)} + /> + {/each} +
+ {:else} +
+ {#each allWeapons as weapon (weapon.id)} + openWeaponDetails(weapon)} + /> + {/each} +
+ {/if} + + {#if !isLoading && !isEmpty} + {#if showSentinel} +
+ {/if} + + {#if collectionQuery.isFetchingNextPage} +
+ + Loading more... +
+ {/if} + + {#if !collectionQuery.hasNextPage && allWeapons.length > 0} +
+

+ {allWeapons.length} weapon{allWeapons.length === 1 ? '' : 's'} in {data.isOwner + ? 'your' + : 'this'} collection +

+
+ {/if} + {/if} +
+
+ +