diff --git a/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationCreateModal.tsx b/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationCreateModal.tsx index 528795a5..3a5a434e 100644 --- a/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationCreateModal.tsx +++ b/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationCreateModal.tsx @@ -23,12 +23,14 @@ import React from 'react'; import {useForm} from 'react-hook-form'; import * as ModalActionCreators from '~/actions/ModalActionCreators'; import {Input} from '~/components/form/Input'; +import {Form} from '~/components/form/Form'; import * as Modal from '~/components/modals/Modal'; import styles from '~/components/modals/tabs/ApplicationsTab/ApplicationsTab.module.css'; import {Button} from '~/components/uikit/Button/Button'; import {Endpoints} from '~/Endpoints'; import HttpClient from '~/lib/HttpClient'; import type {DeveloperApplication} from '~/records/DeveloperApplicationRecord'; +import {useFormSubmit} from '~/hooks/useFormSubmit'; interface ApplicationCreateModalProps { onCreated: (application: DeveloperApplication) => void; @@ -40,50 +42,41 @@ interface CreateFormValues { export const ApplicationCreateModal: React.FC = observer(({onCreated}) => { const {t} = useLingui(); - const { - register, - handleSubmit, - formState: {errors}, - reset, - } = useForm({ + const form = useForm({ defaultValues: { name: '', }, }); - - const nameField = register('name', {required: true, maxLength: 100}); + const nameField = form.register('name', {required: true, maxLength: 100}); const nameInputRef = React.useRef(null); - const [creating, setCreating] = React.useState(false); - const [createError, setCreateError] = React.useState(null); - - const handleCancel = () => { - reset(); - setCreateError(null); + const handleCancel = React.useCallback(() => { + form.reset(); + form.clearErrors(); ModalActionCreators.pop(); - }; + }, [form]); - const onSubmit = handleSubmit(async (data) => { - setCreateError(null); - setCreating(true); - try { + const onSubmit = React.useCallback( + async (data: CreateFormValues) => { const response = await HttpClient.post(Endpoints.OAUTH_APPLICATIONS, { name: data.name.trim(), redirect_uris: [], }); onCreated(response.body); - reset(); + form.reset(); ModalActionCreators.pop(); - } catch (err) { - console.error('[ApplicationCreateModal] Failed to create application:', err); - setCreateError(t`Failed to create application. Please check your inputs and try again.`); - } finally { - setCreating(false); - } + }, + [form, onCreated], + ); + + const {handleSubmit, isSubmitting} = useFormSubmit({ + form, + onSubmit, + defaultErrorField: 'name', }); return ( -
+ = obs placeholder={t`My Application`} maxLength={100} required - disabled={creating} + disabled={isSubmitting} autoFocus + error={form.formState.errors.name?.message} /> - - {errors.name &&
{t`Application name is required`}
} - {createError &&
{createError}
}
- - - +
); }); diff --git a/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationDetail.tsx b/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationDetail.tsx index 681dacdd..85add8da 100644 --- a/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationDetail.tsx +++ b/fluxer_app/src/components/modals/tabs/ApplicationsTab/ApplicationDetail.tsx @@ -417,6 +417,7 @@ export const ApplicationDetail: React.FC = observer( } else { setBotToken(res.body.token ?? null); } + sudo.finalize(); ToastActionCreators.createToast({ type: 'success', children: diff --git a/fluxer_app/src/hooks/useSudo.ts b/fluxer_app/src/hooks/useSudo.ts index 5b5e7a15..b7b8a304 100644 --- a/fluxer_app/src/hooks/useSudo.ts +++ b/fluxer_app/src/hooks/useSudo.ts @@ -29,5 +29,9 @@ export const useSudo = () => { return await SudoPromptStore.requestVerification(); }, []); - return {require}; + const finalize = useCallback(() => { + SudoPromptStore.handleTokenReceived(null); + }, []); + + return {require, finalize}; };