feat(forms): migrate auth forms to useAppForm

Move login, password-change, email-change, and name-change onto the shared
useAppForm wrapper — the last data-entry forms still on raw useForm. These were
already on react-hook-form's default timing (onSubmit + onChange revalidate), so
this is behavior-neutral: it only routes them through the single timing source
so none can later drift to eager validation, and keeps every form consistent.
Schemas and submit buttons (FormSubmitButton) are untouched, so the password
policy and login flow are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sergey Kozyrenko
2026-07-07 12:49:32 +07:00
co-authored by Claude Opus 4.8
parent d31c73d35a
commit a3f2a73ca0
4 changed files with 12 additions and 16 deletions
@@ -1,6 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import * as z from 'zod';
@@ -9,6 +7,7 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '
import { FormSubmitButton } from '@/components/ui/form-submit-button';
import { Input } from '@/components/ui/input';
import { InputPassword } from '@/components/ui/input-password';
import { useAppForm } from '@/hooks/use-app-form';
import { api, resolveApiErrorMessage } from '@/lib/axios';
import { useUser } from '@/providers/user-provider';
@@ -41,12 +40,12 @@ export function EmailChangeForm({ onCancel, onSuccess }: EmailChangeFormProps) {
const [error, setError] = useState<null | string>(null);
const { patchUser, refreshAuthInfo } = useUser();
const form = useForm<EmailChangeFormValues>({
const form = useAppForm<EmailChangeFormValues>({
defaultValues: {
currentPassword: '',
newEmail: '',
},
resolver: zodResolver(emailChangeSchema),
schema: emailChangeSchema,
});
const handleSubmit = async (values: EmailChangeFormValues) => {
@@ -1,6 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { z } from 'zod';
@@ -13,6 +11,7 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '
import { FormSubmitButton } from '@/components/ui/form-submit-button';
import { Input } from '@/components/ui/input';
import { InputPassword } from '@/components/ui/input-password';
import { useAppForm } from '@/hooks/use-app-form';
import { routes } from '@/lib/routes';
import { useUser } from '@/providers/user-provider';
@@ -63,12 +62,12 @@ interface LoginFormProps {
}
function LoginForm({ providers, returnUrl = routes.newFlow }: LoginFormProps) {
const form = useForm<z.infer<typeof formSchema>>({
const form = useAppForm<z.infer<typeof formSchema>>({
defaultValues: {
mail: '',
password: '',
},
resolver: zodResolver(formSchema),
schema: formSchema,
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState<null | string>(null);
@@ -1,6 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import * as z from 'zod';
@@ -8,6 +6,7 @@ import { Button } from '@/components/ui/button';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { FormSubmitButton } from '@/components/ui/form-submit-button';
import { Input } from '@/components/ui/input';
import { useAppForm } from '@/hooks/use-app-form';
import { api, resolveApiErrorMessage } from '@/lib/axios';
import { useUser } from '@/providers/user-provider';
@@ -35,11 +34,11 @@ export function NameChangeForm({ onCancel, onSuccess }: NameChangeFormProps) {
const [error, setError] = useState<null | string>(null);
const { authInfo, patchUser, refreshAuthInfo } = useUser();
const form = useForm<NameChangeFormValues>({
const form = useAppForm<NameChangeFormValues>({
defaultValues: {
name: authInfo?.user?.name ?? '',
},
resolver: zodResolver(nameChangeSchema),
schema: nameChangeSchema,
});
const handleSubmit = async (values: NameChangeFormValues) => {
@@ -1,6 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { type ComponentProps, useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import * as z from 'zod';
@@ -8,6 +6,7 @@ import { Button } from '@/components/ui/button';
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { FormSubmitButton } from '@/components/ui/form-submit-button';
import { InputPassword } from '@/components/ui/input-password';
import { useAppForm } from '@/hooks/use-app-form';
import { api, resolveApiErrorMessage } from '@/lib/axios';
import { cn } from '@/lib/utils';
@@ -74,13 +73,13 @@ export function PasswordChangeForm({
}: PasswordChangeFormProps) {
const [error, setError] = useState<null | string>(null);
const form = useForm<PasswordChangeFormValues>({
const form = useAppForm<PasswordChangeFormValues>({
defaultValues: {
confirmPassword: '',
currentPassword: '',
newPassword: '',
},
resolver: zodResolver(passwordChangeSchema),
schema: passwordChangeSchema,
});
const handleSubmit = async (values: PasswordChangeFormValues) => {