From c54c959522292f20010c3e0b1d62e72c98a2fbd8 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 13 Dec 2025 20:02:25 -0800 Subject: [PATCH] rework ModalFooter to use action props - onCancel callback with fixed "Nevermind" label - optional primaryAction object (label, onclick, destructive, disabled) - optional left snippet for custom content --- src/lib/components/UserSettingsModal.svelte | 159 ++++++++++++++++-- .../collection/AddToCollectionModal.svelte | 80 +++------ .../components/crew/InviteUserModal.svelte | 18 +- src/lib/components/crew/ScoutUserModal.svelte | 24 ++- .../components/dialogs/ConflictDialog.svelte | 20 +-- src/lib/components/ui/ModalFooter.svelte | 47 +++++- src/routes/(app)/crew/+page.svelte | 59 +++---- .../crew/events/[eventNumber]/+page.svelte | 25 ++- src/routes/(app)/crew/members/+page.svelte | 68 +++----- .../components/ui/Dialog.stories.svelte | 56 +++--- 10 files changed, 333 insertions(+), 223 deletions(-) diff --git a/src/lib/components/UserSettingsModal.svelte b/src/lib/components/UserSettingsModal.svelte index adfd5bce..5d4a8eb2 100644 --- a/src/lib/components/UserSettingsModal.svelte +++ b/src/lib/components/UserSettingsModal.svelte @@ -8,11 +8,15 @@ import Select from './ui/Select.svelte' import Switch from './ui/switch/Switch.svelte' import Button from './ui/Button.svelte' + import Input from './ui/Input.svelte' import { pictureData, type Picture } from '$lib/utils/pictureData' import { users } from '$lib/api/resources/users' import type { UserCookie } from '$lib/types/UserCookie' import { setUserCookie } from '$lib/auth/cookies' import { invalidateAll } from '$app/navigation' + import { createQuery } from '@tanstack/svelte-query' + import { crewQueries } from '$lib/api/queries/crew.queries' + import { userAdapter } from '$lib/api/adapters/user.adapter' interface Props { open: boolean @@ -25,7 +29,7 @@ let { open = $bindable(false), onOpenChange, username, userId, user, role }: Props = $props() - // Form state + // Form state - fields from cookie (can use immediately) let picture = $state(user.picture) let element = $state(user.element) let gender = $state(user.gender) @@ -33,9 +37,48 @@ let theme = $state(user.theme) let bahamut = $state(user.bahamut ?? false) + // Form state - fields from API (must wait for query to load) + // Initialize as empty - will be set by $effect when API data loads + let granblueId = $state('') + let showCrewGamertag = $state(false) + let apiDataLoaded = $state(false) + let saving = $state(false) let error = $state(null) + // Fetch current user data from API (to get actual show_gamertag value from database) + const currentUserQuery = createQuery(() => ({ + queryKey: ['currentUser', 'settings'], + queryFn: () => userAdapter.getCurrentUser(), + enabled: open // Only fetch when modal is open + })) + + // Fetch current user's crew (for showing gamertag toggle) + const myCrewQuery = createQuery(() => ({ + ...crewQueries.myCrew(), + enabled: open // Only fetch when modal is open + })) + + const isInCrew = $derived(!!myCrewQuery.data) + const crewGamertag = $derived(myCrewQuery.data?.gamertag) + const isLoadingApiData = $derived(currentUserQuery.isLoading || currentUserQuery.isPending) + + // Update form state when API data loads (to get actual values from database) + $effect(() => { + if (currentUserQuery.data) { + granblueId = currentUserQuery.data.granblueId ?? '' + showCrewGamertag = currentUserQuery.data.showCrewGamertag ?? false + apiDataLoaded = true + } + }) + + // Reset apiDataLoaded when modal closes so fresh data is fetched next time + $effect(() => { + if (!open) { + apiDataLoaded = false + } + }) + // Get current locale from user settings const locale = $derived(user.language as 'en' | 'ja') @@ -107,7 +150,9 @@ element, gender, language, - theme + theme, + granblueId: granblueId || undefined, + showCrewGamertag } // Call API to update user settings @@ -120,7 +165,9 @@ language: response.language, gender: response.gender, theme: response.theme, - bahamut + bahamut, + granblueId: response.granblueId, + showCrewGamertag: response.showCrewGamertag } // Save to cookie (we'll need to handle this server-side) @@ -137,7 +184,7 @@ body: JSON.stringify(updatedUser) }) - // If language or theme changed, we need a full page reload + // If language, theme, or bahamut mode changed, we need a full page reload if (user.language !== language || user.theme !== theme || user.bahamut !== bahamut) { await invalidateAll() window.location.reload() @@ -203,6 +250,39 @@ contained /> + + {#if isLoadingApiData} +
+ Granblue ID + Loading... +
+ {:else} + + {/if} + + + {#if isInCrew && crewGamertag} +
+ +

Display "{crewGamertag}" next to your name

+
+ {/if} + +
+ - - - - + (isCumulative && !cumulativeScore) + }} + />