cache user settings in cookie for faster modal loading
store granblueId and showCrewGamertag in cookie at login, use as initial values so modal opens instantly
This commit is contained in:
parent
362db1238f
commit
30128107fb
3 changed files with 20 additions and 59 deletions
|
|
@ -18,7 +18,9 @@ export function buildCookies(oauth: OAuthLoginResponse, info: UserInfoResponse)
|
||||||
element: info.avatar.element ?? '',
|
element: info.avatar.element ?? '',
|
||||||
language: info.language ?? 'en',
|
language: info.language ?? 'en',
|
||||||
gender: info.gender ?? 0,
|
gender: info.gender ?? 0,
|
||||||
theme: info.theme ?? 'system'
|
theme: info.theme ?? 'system',
|
||||||
|
granblueId: info.granblueId,
|
||||||
|
showCrewGamertag: info.showCrewGamertag
|
||||||
}
|
}
|
||||||
|
|
||||||
return { account, user, accessTokenExpiresAt, refresh: oauth.refresh_token }
|
return { account, user, accessTokenExpiresAt, refresh: oauth.refresh_token }
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ export interface UserInfoResponse {
|
||||||
language: string | null
|
language: string | null
|
||||||
gender: number | null
|
gender: number | null
|
||||||
theme: string | null
|
theme: string | null
|
||||||
|
granblueId?: string
|
||||||
|
showCrewGamertag?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function passwordGrantLogin(
|
export async function passwordGrantLogin(
|
||||||
|
|
|
||||||
|
|
@ -38,20 +38,19 @@
|
||||||
let theme = $state(user.theme)
|
let theme = $state(user.theme)
|
||||||
let bahamut = $state(user.bahamut ?? false)
|
let bahamut = $state(user.bahamut ?? false)
|
||||||
|
|
||||||
// Form state - fields from API (must wait for query to load)
|
// Form state - fields that are also in cookie (use cookie as initial value)
|
||||||
// Initialize as empty - will be set by $effect when API data loads
|
let granblueId = $state(user.granblueId ?? '')
|
||||||
let granblueId = $state('')
|
let showCrewGamertag = $state(user.showCrewGamertag ?? false)
|
||||||
let showCrewGamertag = $state(false)
|
|
||||||
let apiDataLoaded = $state(false)
|
|
||||||
|
|
||||||
let saving = $state(false)
|
let saving = $state(false)
|
||||||
let error = $state<string | null>(null)
|
let error = $state<string | null>(null)
|
||||||
|
|
||||||
// Fetch current user data from API (to get actual show_gamertag value from database)
|
// Fetch current user data from API (to sync with latest database values)
|
||||||
const currentUserQuery = createQuery(() => ({
|
const currentUserQuery = createQuery(() => ({
|
||||||
queryKey: ['currentUser', 'settings'],
|
queryKey: ['currentUser', 'settings'],
|
||||||
queryFn: () => userAdapter.getCurrentUser(),
|
queryFn: () => userAdapter.getCurrentUser(),
|
||||||
enabled: open // Only fetch when modal is open
|
enabled: open, // Only fetch when modal is open
|
||||||
|
staleTime: 5 * 60 * 1000 // Cache for 5 minutes
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Fetch current user's crew (for showing gamertag toggle)
|
// Fetch current user's crew (for showing gamertag toggle)
|
||||||
|
|
@ -62,21 +61,12 @@
|
||||||
|
|
||||||
const isInCrew = $derived(!!myCrewQuery.data)
|
const isInCrew = $derived(!!myCrewQuery.data)
|
||||||
const crewGamertag = $derived(myCrewQuery.data?.gamertag)
|
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)
|
// Sync form state when API returns fresher data than cookie
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (currentUserQuery.data) {
|
if (currentUserQuery.data) {
|
||||||
granblueId = currentUserQuery.data.granblueId ?? ''
|
granblueId = currentUserQuery.data.granblueId ?? ''
|
||||||
showCrewGamertag = currentUserQuery.data.showCrewGamertag ?? false
|
showCrewGamertag = currentUserQuery.data.showCrewGamertag ?? false
|
||||||
apiDataLoaded = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reset apiDataLoaded when modal closes so fresh data is fetched next time
|
|
||||||
$effect(() => {
|
|
||||||
if (!open) {
|
|
||||||
apiDataLoaded = false
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -252,12 +242,6 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Granblue ID -->
|
<!-- Granblue ID -->
|
||||||
{#if isLoadingApiData}
|
|
||||||
<div class="loading-field">
|
|
||||||
<span class="loading-label">Granblue ID</span>
|
|
||||||
<span class="loading-text">Loading...</span>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<Input
|
<Input
|
||||||
bind:value={granblueId}
|
bind:value={granblueId}
|
||||||
label="Granblue ID"
|
label="Granblue ID"
|
||||||
|
|
@ -265,18 +249,13 @@
|
||||||
contained
|
contained
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Show Crew Gamertag (only if in a crew with a gamertag) -->
|
<!-- Show Crew Gamertag (only if in a crew with a gamertag) -->
|
||||||
{#if isInCrew && crewGamertag}
|
{#if isInCrew && crewGamertag}
|
||||||
<div class="inline-switch">
|
<div class="inline-switch">
|
||||||
<label for="show-gamertag">
|
<label for="show-gamertag">
|
||||||
<span>Show crew tag on profile</span>
|
<span>Show crew tag on profile</span>
|
||||||
{#if isLoadingApiData}
|
|
||||||
<span class="loading-text">Loading...</span>
|
|
||||||
{:else}
|
|
||||||
<Switch bind:checked={showCrewGamertag} name="show-gamertag" element={element as 'wind' | 'fire' | 'water' | 'earth' | 'dark' | 'light' | undefined} />
|
<Switch bind:checked={showCrewGamertag} name="show-gamertag" element={element as 'wind' | 'fire' | 'water' | 'earth' | 'dark' | 'light' | undefined} />
|
||||||
{/if}
|
|
||||||
</label>
|
</label>
|
||||||
<p class="field-hint">Display "{crewGamertag}" next to your name</p>
|
<p class="field-hint">Display "{crewGamertag}" next to your name</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -391,28 +370,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-field {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: spacing.$unit-half;
|
|
||||||
|
|
||||||
.loading-label {
|
|
||||||
font-size: typography.$font-small;
|
|
||||||
font-weight: typography.$medium;
|
|
||||||
color: var(--text-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
font-size: typography.$font-regular;
|
|
||||||
color: var(--text-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
font-size: typography.$font-regular;
|
|
||||||
color: var(--text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picture-section {
|
.picture-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: spacing.$unit-3x;
|
gap: spacing.$unit-3x;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue