From 765d743b21d1ef3faacb8ead8ecc08693b8ead76 Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Mon, 18 May 2026 23:12:47 +0700 Subject: [PATCH] refactor(frontend): inline API token forms on RHF + zod MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the two ad-hoc useState form objects (createFormData / editFormData) in settings-api-tokens.tsx with parent-level useForm hooks per inline row, each backed by a zod schema. Controller in each DataTable cell re-subscribes to the parent form state on remount, so subscription-driven row remounts no longer drop user input — same root cause that 04c6825 fixed, but solved at the architectural level instead of controlling each Input manually. - tokenNameSchema (trim + max 255), createTokenFormSchema with required expiresAt via refine, editTokenFormSchema with status. - , - setCreateFormData((prev) => ({ ...prev, name: event.target.value })) - } - placeholder="Token name (optional)" - value={createFormData.name} + ( + + )} /> ); } if (isEditing) { return ( - setEditFormData((prev) => ({ ...prev, name: event.target.value }))} - placeholder="Token name (optional)" - value={editFormData.name} + ( + + )} /> ); } @@ -464,22 +586,26 @@ function SettingsAPITokens() { } return ( - + ( + + )} + /> ); } @@ -507,37 +633,37 @@ function SettingsAPITokens() { tomorrow.setHours(0, 0, 0, 0); return ( - - - - - - { - setCreateFormData((prev) => ({ ...prev, expiresAt: date || null })); - }} - selected={createFormData.expiresAt || undefined} - /> - - + ( + + + + + + field.onChange(date ?? null)} + selected={field.value ?? undefined} + /> + + + )} + /> ); } @@ -615,49 +741,23 @@ function SettingsAPITokens() { if (isCreating) { return ( -
- - -
+ ); } if (isEditing) { return ( -
- - -
+ handleSave(token.tokenId)} + /> ); } @@ -712,12 +812,10 @@ function SettingsAPITokens() { }, ], [ - createFormData.expiresAt, - createFormData.name, + createForm.control, createNameFieldId, deletingToken, - editFormData.name, - editFormData.status, + editForm.control, editNameFieldId, editingTokenId, handleCancelCreate, @@ -902,4 +1000,7 @@ function SettingsAPITokens() { ); } +// Helper subcomponents so we can use useFormState/useWatch without subscribing +// the whole table to every keystroke. Each watches its own form's validity. + export default SettingsAPITokens;