refactor(ui): migrate console forms to react-hook-form (team#152)#6619
refactor(ui): migrate console forms to react-hook-form (team#152)#6619luannmoreira wants to merge 13 commits into
Conversation
|
Claude finished @luannmoreira's task in 8m 26s —— View job Code Review CompleteReviewed 17 files across code quality, security, testing, language patterns, and architecture. 1 inline issue posted (1 medium). Additional notes
Otherwise the migration is solid: the resolver If you've addressed the feedback and want a new review, tag |
70c7ed4 to
443179b
Compare
|
/review |
|
Claude finished @otavio's task in 19m 54s —— View job Code Review CompleteReviewed the current PR head (
Findings posted inline:
Additional notes
If you've addressed the feedback and want a new review, tag |
c9b603e to
34f31d7
Compare
- Restore the positive-integer rule for firewall priority (reject 0 and negatives), matching the field hint and pre-migration behavior. - Validate on clearing the secure-vault passphrase so isValid/errors stay in sync when swapping in a different encrypted key. - Rework the firewall tags test to verify the 3-tag selector cap instead of passing on a valid 3-tag selection.
34f31d7 to
797df19
Compare
|
/review |
|
Claude finished @otavio's task in 12m 43s —— View job Code Review CompleteReviewed 69 files across code quality, security, testing, TypeScript/React patterns, and architecture/cross-repo — no new issues found. The code looks good as-is. The four issues from the previous review rounds are all confirmed fixed in
Spot-checks that came back clean: removed symbols ( If you push additional changes and want a new review, tag |
…rimitives Introduce the shared foundation for the console form standardization (shellhub-io/team#152): FormDrawer owns the Drawer, form element, and Cancel/Submit footer; useDrawerForm wraps useForm with zodResolver and reset-on-open; FormRootError renders form-level server errors; and the react-hook-form field wrappers (FormNumericInput, FormRadioGroupField, FormTagsSelector, FormTextareaField, FormToggleField) bridge useController over the design-system inputs. Adds the react-hook-form and zod dependencies.
Migrate the edit-profile and change-password drawers to the shared react-hook-form + zod architecture (shellhub-io/team#152). Validation moves into editProfileSchema.ts and changePasswordSchema.ts as the single source of truth; required fields validate unconditionally and the recovery email stays optional with its cross-field rule re-running when the primary email changes. Form-level server errors use RHF root errors.
Migrate the Settings rename-namespace drawer to react-hook-form + zod (shellhub-io/team#152). The namespace-name rule lives in namespaceRenameSchema.ts and the rename error surfaces through an RHF root error. The session-recording and device-auto-accept toggles and the delete/leave dialogs are left as-is.
Migrate the admin SAML configuration drawer to react-hook-form + zod (shellhub-io/team#152). All business logic (certificate normalization, payload shaping) moves into samlSchema.ts, with the drawer reduced to field wrappers over the schema.
Migrate the firewall rule drawer to react-hook-form + zod (shellhub-io/team#152). ruleSchema.ts replaces the hand-rolled resolver as the single source of truth, and the drawer composes FormDrawer with the shared field wrappers.
Migrate the public key drawer to react-hook-form + zod (shellhub-io/team#152). keySchema.ts owns validation and payload shaping; the drawer composes FormDrawer with the shared field wrappers.
Migrate the secure vault key drawer to react-hook-form + zod (shellhub-io/team#152). vaultKeySchema.ts owns validation, and the drawer composes FormDrawer with the shared field wrappers.
Migrate the admin create/edit user drawers to react-hook-form + zod (shellhub-io/team#152). userSchema.ts becomes the single source of truth and the bespoke useUserForm hook is removed; the drawers compose FormDrawer with the shared field wrappers.
…m + zod Migrate the admin edit-namespace drawer to react-hook-form + zod (shellhub-io/team#152). editNamespaceSchema.ts owns validation; the drawer composes FormDrawer with the shared field wrappers.
…+ zod Migrate the New / Edit announcement full-page forms to react-hook-form + zod (shellhub-io/team#152). announcementSchema.ts owns validation; the pages use useForm with zodResolver directly rather than FormDrawer.
…+ zod Migrate the add-member and edit-member-role drawers to react-hook-form + zod (shellhub-io/team#152). The add-member and edit-role schemas live in team/schemas.ts, and constants.tsx gains FormRoleSelector — a react-hook-form binding over the shared RoleSelector used across the team drawers.
Migrate the send-invitation and edit-invitation drawers to react-hook-form + zod (shellhub-io/team#152). The invitation and edit-role schemas live in team/schemas.ts. The send-invitation drawer swaps to a result view after submit, so it composes useDrawerForm + field wrappers + FormRootError under a raw Drawer rather than FormDrawer.
…-form + zod Migrate the generate-key and edit-key drawers to react-hook-form + zod (shellhub-io/team#152). The generate-key and edit-key schemas live in team/schemas.ts, including the string-bound expiry that is converted to the numeric API value in buildGenerateKeyBody. The generate-key drawer swaps to a result view after submit, so it composes useDrawerForm + field wrappers + FormRootError under a raw Drawer rather than FormDrawer.
797df19 to
3aafeb6
Compare
|
/review |
|
Claude finished @otavio's task in 6m 39s —— View job Code Review CompleteReviewed 69 files across code quality, security, testing, TypeScript/React patterns, and architecture/cross-repo — no new issues found. The code looks good as-is. All four issues from previous review rounds remain resolved at the current head (
Spot-checks that came back clean:
If you push additional changes and want a new review, tag |
3aafeb6 to
5a16b59
Compare
What
Migrates every console form to a single react-hook-form + Zod reference
architecture (tracked in shellhub-io/team#152). What began as an incremental
RHF migration is now a full standardization: all in-scope forms share one
validation, submit, reset, and error-handling model, and the legacy
makeRhfResolveradapter is gone.The pilot (SignUp) and the auth/onboarding forms were merged separately and are
intentionally left on their existing resolvers (converted in a later PR).
Architecture — four layers
components/common/fields/rhf/*) — thinuseControllerbridges over the design-system inputs (
FormInputField,FormPasswordField,FormNumericInput,FormCheckboxField,FormRadioGroupField,FormTextareaField,FormToggleField).FormToggleFieldnow renders itsvalidation error like the other fields.
*Schema.tsper form as thesingle source of truth: a Zod schema (a
schema(mode)factory where rules aremode-dependent),
type X = z.infer<...>,buildXDefaults, andbuildXBody.All business logic (trimming,
parseInt, payload shaping, SAML certnormalization) lives here, not in components.
useDrawerForm(open, schema, defaults)wrapsuseForm({ resolver: zodResolver(schema), mode: "onChange" })and standardizesreset-on-open.
FormDrawerowns theDrawer,<form>, Cancel/Submitfooter (disabled on
!isValid || isSubmitting, optionalrequireDirty), andthe shared
FormRootError.A new form = write
xSchema.ts+ a drawer that callsuseDrawerFormand renders<FormDrawer>with field wrappers. No hand-rolled resolver, reset, submit, orroot-error code. This is documented in
components/common/fields/rhf/README.md.Migrated (team#152 checklist)
Account & settings
samlSchema.ts)Resources
Admin
useUserFormhook removed)useForm+zodResolverdirectly, no
FormDrawer)Team
Two dual-mode drawers (Invitation, Generate Key) swap to a result view after
submit, so they compose
useDrawerForm+ field wrappers +FormRootErrorundera raw
Drawerrather thanFormDrawer.Cleanup
makeRhfResolverand its test, and the per-form resolver adapters —zodResolver(schema)insideuseDrawerFormis now the only resolver.schema.safeParsetests with equivalentcoverage.
Behavior change
FormDrawergates the submit button onisValid, so an invalid form now keepssubmit disabled rather than enabled-but-blocked-on-click — a stronger
guarantee. A few drawer/page assertions were updated accordingly (async enable
via
waitFor; the invitation email field flags itself invalid inline as typed).Testing
npm run build(tsc + vite),npm run lint(0 errors), and the fullvitestconsole suite (2894 tests) all green in the
uicontainer.