Skip to content

Commit 3d2ff20

Browse files
committed
feat: add loading state
1 parent 4419fc4 commit 3d2ff20

File tree

9 files changed

+123
-14
lines changed

9 files changed

+123
-14
lines changed

src/hooks/accounts.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { useShallow } from 'zustand/react/shallow'
22

3+
import {
4+
AddAccountsLoadingsState,
5+
useAddAccountsStore,
6+
} from '../state/accounts/add'
37
import { useAccountListStore } from '../state/accounts/list'
48

59
export function useGetSelectedAccount() {
@@ -25,3 +29,20 @@ export function useRemoveSelectedAccount() {
2529

2630
return { removeAccount }
2731
}
32+
33+
export function useAddAccountUpdateSubmittingState(
34+
type: keyof AddAccountsLoadingsState
35+
) {
36+
const { isSubmitting, updateLoadingStatus } = useAddAccountsStore(
37+
useShallow((state) => ({
38+
isSubmitting: state[type],
39+
updateLoadingStatus: state.updateLoadingStatus,
40+
}))
41+
)
42+
43+
const updateSubmittingState = (value: boolean) => {
44+
updateLoadingStatus(type, value)
45+
}
46+
47+
return { isSubmitting, updateSubmittingState }
48+
}

src/routes/accounts/add/(authorization-code)/-hooks.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
22
import { useForm } from 'react-hook-form'
33
import { z } from 'zod'
44

5+
import { useAddAccountUpdateSubmittingState } from '../../../../hooks/accounts'
56
import { useBaseSetupForm } from '../-hooks'
67

78
const formSchema = z.object({
@@ -11,6 +12,8 @@ const formSchema = z.object({
1112
})
1213

1314
export function useSetupForm() {
15+
const { isSubmitting, updateSubmittingState } =
16+
useAddAccountUpdateSubmittingState('authorizationCode')
1417
const form = useForm<z.infer<typeof formSchema>>({
1518
resolver: zodResolver(formSchema),
1619
defaultValues: {
@@ -20,12 +23,18 @@ export function useSetupForm() {
2023

2124
useBaseSetupForm({
2225
fetcher: window.electronAPI.responseAuthWithAuthorization,
26+
type: 'authorizationCode',
2327
})
2428

2529
const onSubmit = (values: z.infer<typeof formSchema>) => {
30+
if (isSubmitting) {
31+
return
32+
}
33+
34+
updateSubmittingState(true)
2635
window.electronAPI.createAuthWithAuthorization(values.code)
2736
form.reset()
2837
}
2938

30-
return { form, onSubmit }
39+
return { form, isSubmitting, onSubmit }
3140
}

src/routes/accounts/add/(authorization-code)/-page.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ExternalLinkIcon } from '@radix-ui/react-icons'
1+
import { ExternalLinkIcon, UpdateIcon } from '@radix-ui/react-icons'
22

33
import { exampleCode } from '../../../../config/constants/examples'
44
import {
@@ -35,7 +35,7 @@ import { useSetupForm } from './-hooks'
3535

3636
export function AuthorizationCodePage() {
3737
const { goToAuthorizationCodeURL, goToEpicGamesLogin } = useHandlers()
38-
const { form, onSubmit } = useSetupForm()
38+
const { form, isSubmitting, onSubmit } = useSetupForm()
3939

4040
return (
4141
<Form {...form}>
@@ -112,6 +112,7 @@ export function AuthorizationCodePage() {
112112
<FormMessage />
113113
</FormItem>
114114
)}
115+
disabled={isSubmitting}
115116
/>
116117
</CardContent>
117118
<CardFooter className="space-x-6">
@@ -131,8 +132,13 @@ export function AuthorizationCodePage() {
131132
<Button
132133
type="submit"
133134
className="w-full"
135+
disabled={isSubmitting}
134136
>
135-
Login
137+
{isSubmitting ? (
138+
<UpdateIcon className="animate-spin" />
139+
) : (
140+
'Login'
141+
)}
136142
</Button>
137143
</CardFooter>
138144
</Card>

src/routes/accounts/add/(device-auth)/-hooks.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
22
import { useForm } from 'react-hook-form'
33
import { z } from 'zod'
44

5+
import { useAddAccountUpdateSubmittingState } from '../../../../hooks/accounts'
56
import { useBaseSetupForm } from '../-hooks'
67

78
const formSchema = z.object({
@@ -17,6 +18,8 @@ const formSchema = z.object({
1718
})
1819

1920
export function useSetupForm() {
21+
const { isSubmitting, updateSubmittingState } =
22+
useAddAccountUpdateSubmittingState('deviceAuth')
2023
const form = useForm<z.infer<typeof formSchema>>({
2124
resolver: zodResolver(formSchema),
2225
defaultValues: {
@@ -28,12 +31,18 @@ export function useSetupForm() {
2831

2932
useBaseSetupForm({
3033
fetcher: window.electronAPI.responseAuthWithDevice,
34+
type: 'deviceAuth',
3135
})
3236

3337
const onSubmit = (values: z.infer<typeof formSchema>) => {
38+
if (isSubmitting) {
39+
return
40+
}
41+
42+
updateSubmittingState(true)
3443
window.electronAPI.createAuthWithDevice(values)
3544
form.reset()
3645
}
3746

38-
return { form, onSubmit }
47+
return { form, isSubmitting, onSubmit }
3948
}

src/routes/accounts/add/(device-auth)/-page.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { UpdateIcon } from '@radix-ui/react-icons'
2+
13
import { InputSecret } from '../../../../components/ui/extended/form/input-secret'
24
import { Button } from '../../../../components/ui/button'
35
import {
@@ -17,7 +19,7 @@ import {
1719
import { useSetupForm } from './-hooks'
1820

1921
export function DeviceAuthPage() {
20-
const { form, onSubmit } = useSetupForm()
22+
const { form, isSubmitting, onSubmit } = useSetupForm()
2123

2224
return (
2325
<Form {...form}>
@@ -39,6 +41,7 @@ export function DeviceAuthPage() {
3941
<FormMessage />
4042
</FormItem>
4143
)}
44+
disabled={isSubmitting}
4245
/>
4346
<FormField
4447
control={form.control}
@@ -52,6 +55,7 @@ export function DeviceAuthPage() {
5255
<FormMessage />
5356
</FormItem>
5457
)}
58+
disabled={isSubmitting}
5559
/>
5660
<FormField
5761
control={form.control}
@@ -65,14 +69,20 @@ export function DeviceAuthPage() {
6569
<FormMessage />
6670
</FormItem>
6771
)}
72+
disabled={isSubmitting}
6873
/>
6974
</CardContent>
7075
<CardFooter>
7176
<Button
7277
type="submit"
7378
className="w-full"
79+
disabled={isSubmitting}
7480
>
75-
Login
81+
{isSubmitting ? (
82+
<UpdateIcon className="animate-spin" />
83+
) : (
84+
'Login'
85+
)}
7686
</Button>
7787
</CardFooter>
7888
</Card>

src/routes/accounts/add/(exchange-code)/-hooks.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import { useEffect, useState } from 'react'
33
import { useForm } from 'react-hook-form'
44
import { z } from 'zod'
55

6-
import { useGetSelectedAccount } from '../../../../hooks/accounts'
6+
import {
7+
useAddAccountUpdateSubmittingState,
8+
useGetSelectedAccount,
9+
} from '../../../../hooks/accounts'
710
import { useBaseSetupForm } from '../-hooks'
811

912
import { toast } from '../../../../lib/notifications'
@@ -15,6 +18,8 @@ const formSchema = z.object({
1518
})
1619

1720
export function useSetupForm() {
21+
const { isSubmitting, updateSubmittingState } =
22+
useAddAccountUpdateSubmittingState('exchangeCode')
1823
const { selected } = useGetSelectedAccount()
1924
const form = useForm<z.infer<typeof formSchema>>({
2025
resolver: zodResolver(formSchema),
@@ -25,14 +30,20 @@ export function useSetupForm() {
2530

2631
useBaseSetupForm({
2732
fetcher: window.electronAPI.responseAuthWithExchange,
33+
type: 'exchangeCode',
2834
})
2935

3036
const onSubmit = (values: z.infer<typeof formSchema>) => {
37+
if (isSubmitting) {
38+
return
39+
}
40+
41+
updateSubmittingState(true)
3142
window.electronAPI.createAuthWithExchange(values.code)
3243
form.reset()
3344
}
3445

35-
return { form, selected, onSubmit }
46+
return { form, isSubmitting, selected, onSubmit }
3647
}
3748

3849
export function useGenerateHandlers() {

src/routes/accounts/add/(exchange-code)/-page.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { UpdateIcon } from '@radix-ui/react-icons'
2+
13
import { exampleCode } from '../../../../config/constants/examples'
24

35
import { InputSecret } from '../../../../components/ui/extended/form/input-secret'
@@ -22,7 +24,7 @@ import { GenerateExchangeCodePage } from './-generate'
2224
import { useSetupForm } from './-hooks'
2325

2426
export function ExchangeCodePage() {
25-
const { form, selected, onSubmit } = useSetupForm()
27+
const { form, isSubmitting, selected, onSubmit } = useSetupForm()
2628

2729
return (
2830
<div className="flex flex-col gap-8 justify-center max-w-sm w-full">
@@ -57,14 +59,20 @@ export function ExchangeCodePage() {
5759
<FormMessage />
5860
</FormItem>
5961
)}
62+
disabled={isSubmitting}
6063
/>
6164
</CardContent>
6265
<CardFooter>
6366
<Button
6467
type="submit"
6568
className="w-full"
69+
disabled={isSubmitting}
6670
>
67-
Login
71+
{isSubmitting ? (
72+
<UpdateIcon className="animate-spin" />
73+
) : (
74+
'Login'
75+
)}
6876
</Button>
6977
</CardFooter>
7078
</Card>

src/routes/accounts/add/-hooks.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import {
99
epicGamesLoginURL,
1010
} from '../../../config/fortnite/links'
1111

12+
import { useAddAccountUpdateSubmittingState } from '../../../hooks/accounts'
13+
14+
import { AddAccountsLoadingsState } from '../../../state/accounts/add'
1215
import { useAccountListStore } from '../../../state/accounts/list'
1316

1417
import { toast } from '../../../lib/notifications'
@@ -35,13 +38,17 @@ export function useHandlers() {
3538

3639
export function useBaseSetupForm({
3740
fetcher,
41+
type,
3842
}: {
3943
fetcher: (
4044
callback: (response: AuthCallbackResponseParam) => Promise<void>
4145
) => {
4246
removeListener: () => Electron.IpcRenderer
4347
}
48+
type: keyof AddAccountsLoadingsState
4449
}) {
50+
const { updateSubmittingState } =
51+
useAddAccountUpdateSubmittingState(type)
4552
const { changeSelected, register } = useAccountListStore(
4653
useShallow((state) => ({
4754
changeSelected: state.changeSelected,
@@ -62,14 +69,16 @@ export function useBaseSetupForm({
6269
changeSelected(accountsToArray[0].accountId)
6370
}
6471

65-
window.electronAPI.requestProviderAndAccessToken(
66-
data.currentAccount
67-
)
72+
// window.electronAPI.requestProviderAndAccessToken(
73+
// data.currentAccount
74+
// )
6875

6976
toast(`New account added: ${data.currentAccount.displayName}`)
7077
} else if (error) {
7178
toast(error ?? 'Unknown error :c')
7279
}
80+
81+
updateSubmittingState(false)
7382
})
7483

7584
return () => {

src/state/accounts/add.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { create } from 'zustand'
2+
3+
export type AddAccountsLoadingsState = {
4+
authorizationCode: boolean
5+
deviceAuth: boolean
6+
exchangeCode: boolean
7+
}
8+
9+
export type AddAccountsState = AddAccountsLoadingsState & {
10+
updateLoadingStatus: (
11+
type: keyof AddAccountsLoadingsState,
12+
value: boolean
13+
) => void
14+
}
15+
16+
export const useAddAccountsStore = create<AddAccountsState>()((set) => ({
17+
authorizationCode: false,
18+
deviceAuth: false,
19+
exchangeCode: false,
20+
21+
updateLoadingStatus: (type, value) => {
22+
set({
23+
[type]: value,
24+
})
25+
},
26+
}))

0 commit comments

Comments
 (0)