List the action's rejected fields above the register form

This commit is contained in:
Aaron Po
2026-10-13 01:32:59 -04:00
parent e6240bc889
commit fffbe68dc2
2 changed files with 25 additions and 2 deletions

View File

@@ -1,10 +1,20 @@
interface AuthErrorAlertProps { interface AuthErrorAlertProps {
message: string; message: string;
/** Per-field messages to list beneath the summary. */
details?: readonly string[];
} }
const AuthErrorAlert = ({ message }: AuthErrorAlertProps) => ( const AuthErrorAlert = ({ message, details }: AuthErrorAlertProps) => (
<div role="alert" className="alert alert-error alert-soft"> <div role="alert" className="alert alert-error alert-soft flex-col items-start">
<span>{message}</span> <span>{message}</span>
{details?.length ? (
<ul className="list-inside list-disc text-sm">
{details.map((detail) => (
<li key={detail}>{detail}</li>
))}
</ul>
) : null}
</div> </div>
); );

View File

@@ -51,6 +51,12 @@ const Register = ({ actionData }: Route.ComponentProps) => {
submit(data, { method: 'post' }); submit(data, { method: 'post' });
}); });
// A request that reached the action without passing client validation, so the
// rejected fields may well sit on a step other than the one on screen.
const rejectedFields = Object.values(actionData?.fieldErrors ?? {}).flatMap(
(messages) => messages ?? [],
);
useActionErrorToast(actionData?.error); useActionErrorToast(actionData?.error);
return ( return (
@@ -68,6 +74,13 @@ const Register = ({ actionData }: Route.ComponentProps) => {
{actionData?.error && <AuthErrorAlert message={actionData.error} />} {actionData?.error && <AuthErrorAlert message={actionData.error} />}
{rejectedFields.length > 0 && (
<AuthErrorAlert
message="Check these details before creating your account."
details={rejectedFields}
/>
)}
<RegisterForm wizard={wizard} submitting={isSubmitting} /> <RegisterForm wizard={wizard} submitting={isSubmitting} />
<AuthSwitchPrompt lead="Already have an account?" to="/login" label="Sign in" /> <AuthSwitchPrompt lead="Already have an account?" to="/login" label="Sign in" />