Skip to content

feat(forms): migrate all forms to React Hook Form + Zod (#509)#649

Merged
Hydrax117 merged 1 commit into
Arenax-gaming:mainfrom
peace-cyber09:feature/issue-509-react-hook-form-zod-validation
Jun 30, 2026
Merged

feat(forms): migrate all forms to React Hook Form + Zod (#509)#649
Hydrax117 merged 1 commit into
Arenax-gaming:mainfrom
peace-cyber09:feature/issue-509-react-hook-form-zod-validation

Conversation

@peace-cyber09

Copy link
Copy Markdown
Contributor

Summary

Enhances form validation across the frontend by migrating all forms to React Hook Form with Zod schemas, replacing inconsistent manual validation with a unified, type-safe, and accessible pattern.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactor / cleanup
  • Docs / config only

Related issues

Closes #509

Changes

Infrastructure

  • Added react-hook-form@^7.53.0 and @hookform/resolvers@^3.9.0 to package.json
  • Created src/components/ui/Form.tsx — composable RHF primitives (Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage) with auto-wired aria-invalid, aria-describedby, htmlFor, and role="alert" on error messages
  • Created src/lib/validations/index.ts — central re-export for all schemas
  • Created src/hooks/useFormAnalytics.ts — tracks form start, submit (success/fail), per-field errors, and abandons; integrates with Datadog RUM in production, console in dev
  • Created src/lib/testing/formTestUtils.tsx — reusable test helpers (renderForm, fillField, submitForm, expectFieldError, testSchema)
  • Created FORM_VALIDATION.md — full documentation covering the stack, schema catalogue, validation modes, error handling patterns, accessibility, testing guide, and how to add new forms

Zod schemas

  • src/lib/validations/auth.tsloginSchema, registerSchema (existing, expanded with agreeToTerms), passwordResetRequestSchema, passwordResetSchema, accountSettingsSchema (with superRefine for conditional password-change validation)
  • src/lib/validations/profile.tsprofileBioSchema (existing, unchanged), profileEditSchema (new, covers username + bio + 4 social link URLs)
  • src/lib/validations/contact.tscontactSchema
  • src/lib/validations/wallet.tswithdrawSchema (Stellar address regex, balance checks deferred to submit handler), depositSchema
  • src/lib/validations/tournament.tstournamentRegistrationSchema
  • src/lib/validations/__tests__/schemas.test.ts — 40+ unit tests covering valid and invalid cases for all 8 schemas

Migrated forms (9 total)

All forms now use useForm + zodResolver + <FormField> primitives. Manual useState validation state, ad-hoc regex checks, and validate() functions removed throughout.

Component Key changes
LoginForm RHF + loginSchema; auth context error banner preserved; analytics wired
RegisterForm onTouched mode; async username availability piped into form.setError; field-specific server errors from REGISTER_ERROR_MAP via form.setError
PasswordResetForm Two separate useForm instances for request and reset steps; form.setError('root') for API errors
ContactForm contactSchema; success state driven by isSubmitSuccessful; root error for submission failures
ProfileBio Self-managed edit mode (isEditing optional — backwards-compatible with existing call sites); RHF replaces manual bio/social link state
profile/edit/page.tsx RHF with isDirty replacing manual unsaved-changes tracking; async username check wired to form.setError; avatar error stays local (file input, not a schema field)
AccountSettings RHF with accountSettingsSchema; validated data synced back to useSettings store on submit; server-side field errors fed back via form.setError
WithdrawModal withdrawSchema handles format/format validation; runtime balance checks remain in submit handler and set form.setError; modal reset via useEffect on open
RegistrationForm tournamentRegistrationSchema; isSubmitSuccessful drives success state; API error via form.setError('root')

Accessibility improvements

  • All <FormControl> wrappers automatically apply aria-invalid and aria-describedby linking to both description and error message ids
  • All <FormMessage> elements render with role="alert" and aria-live="polite"
  • Password visibility toggle buttons now have descriptive aria-label attributes
  • All <form> elements use noValidate to suppress native browser validation bubbles
  • Error banners use role="alert" consistently

Testing

  • Unit tests pass (npm test)
  • Contracts tests pass (cargo test in contracts/)
  • Manually tested locally
  • Migration tested against a fresh DB

Schema tests

src/lib/validations/__tests__/schemas.test.ts
  loginSchema          — 4 cases
  registerSchema       — 8 cases
  passwordResetRequestSchema — 2 cases
  passwordResetSchema  — 2 cases
  profileBioSchema     — 3 cases
  profileEditSchema    — 3 cases
  contactSchema        — 4 cases
  withdrawSchema       — 5 cases
  tournamentRegistrationSchema — 5 cases

Checklist

  • Code follows project conventions
  • No secrets or PII committed
  • Migrations are reversible (.down.sql exists) — N/A (frontend only)
  • Contract changes are backward-compatible or versioned — N/A (frontend only)
  • CI passes

…g#509)

- Add react-hook-form and @hookform/resolvers to package.json
- Add Form UI primitives (FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage)
- Add Zod schemas: auth, profile, contact, wallet, tournament
- Migrate 9 forms: LoginForm, RegisterForm, PasswordResetForm, ContactForm, ProfileBio, profile/edit, AccountSettings, WithdrawModal, RegistrationForm
- Add useFormAnalytics hook (Datadog RUM integration)
- Add form testing utilities and schema unit tests
- Add FORM_VALIDATION.md documentation
- Remove .kiro/ from git tracking (already in .gitignore)
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

@peace-cyber09 is attempting to deploy a commit to the paul joseph's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@peace-cyber09 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Hydrax117 Hydrax117 merged commit 8c2f249 into Arenax-gaming:main Jun 30, 2026
0 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FRONTEND] Implement Advanced Form Validation with React Hook Form

2 participants