fix(auth): surface validation errors in email login/register forms
Validation failure was previously silent — the form's submit() returned
without dispatching or showing anything on screen, so users could not tell
why the login/register button appeared to do nothing.
Changes:
- Add validationError local state in EmailLoginForm and EmailRegisterForm
- Display first validation error via AuthErrorMessage, prioritised over
the server's globalError (validation errors feel more immediate)
- Clear validation error on field change (standard "error fades as you
fix it" UX) — implemented as onChange handlers, not useEffect, to
avoid React's cascading-render anti-pattern
- Add observability to the entire email flow (was previously silent end
to end): form submit ENTRY, validator rejection, actor ENTRY, actor
DONE — mirrors the logging style already used by guestLoginActor
- Add entry: assign({ errorMessage: null }) to loadingEmailLogin and
loadingEmailRegister so stale errors clear on transition into the
loading state (matches loadingGuestLogin)
This commit is contained in:
@@ -25,8 +25,22 @@ const authRepo: IAuthRepository = authRepository;
|
||||
|
||||
export const emailLoginActor = fromPromise<LoginStatus, { email: string; password: string }>(
|
||||
async ({ input }) => {
|
||||
console.log("[auth-machine] emailLoginActor ENTRY", {
|
||||
emailLength: input.email.length,
|
||||
emailPreview: input.email.slice(0, 8),
|
||||
passwordLength: input.password.length,
|
||||
});
|
||||
const guestId = await readGuestId();
|
||||
console.log("[auth-machine] emailLoginActor calling authRepo.emailLogin", {
|
||||
hasGuestId: !!guestId,
|
||||
});
|
||||
const result = await authRepo.emailLogin({ ...input, guestId });
|
||||
console.log("[auth-machine] emailLoginActor authRepo.emailLogin DONE", {
|
||||
success: result.success,
|
||||
hasData: result.success ? !!result.data : null,
|
||||
errorName: result.success ? null : result.error?.name,
|
||||
errorMessage: result.success ? null : result.error?.message,
|
||||
});
|
||||
if (Result.isErr(result)) throw result.error;
|
||||
return "email" as LoginStatus;
|
||||
},
|
||||
@@ -36,17 +50,40 @@ export const emailRegisterThenLoginActor = fromPromise<
|
||||
LoginStatus,
|
||||
{ email: string; password: string; username: string; confirmPassword: string }
|
||||
>(async ({ input }) => {
|
||||
console.log("[auth-machine] emailRegisterThenLoginActor ENTRY", {
|
||||
emailLength: input.email.length,
|
||||
usernameLength: input.username.length,
|
||||
passwordLength: input.password.length,
|
||||
confirmPasswordLength: input.confirmPassword.length,
|
||||
});
|
||||
const guestId = await readGuestId();
|
||||
|
||||
console.log("[auth-machine] emailRegisterThenLoginActor calling authRepo.register");
|
||||
const registerResult = await authRepo.register({ ...input, guestId });
|
||||
console.log("[auth-machine] emailRegisterThenLoginActor authRepo.register DONE", {
|
||||
success: registerResult.success,
|
||||
errorName: registerResult.success ? null : registerResult.error?.name,
|
||||
errorMessage: registerResult.success ? null : registerResult.error?.message,
|
||||
});
|
||||
if (Result.isErr(registerResult)) throw registerResult.error;
|
||||
|
||||
// 注册后自动登录(对齐 Dart 行为)
|
||||
console.log(
|
||||
"[auth-machine] emailRegisterThenLoginActor calling authRepo.emailLogin (post-register)",
|
||||
);
|
||||
const loginResult = await authRepo.emailLogin({
|
||||
email: input.email,
|
||||
password: input.password,
|
||||
guestId,
|
||||
});
|
||||
console.log(
|
||||
"[auth-machine] emailRegisterThenLoginActor authRepo.emailLogin DONE",
|
||||
{
|
||||
success: loginResult.success,
|
||||
errorName: loginResult.success ? null : loginResult.error?.name,
|
||||
errorMessage: loginResult.success ? null : loginResult.error?.message,
|
||||
},
|
||||
);
|
||||
if (Result.isErr(loginResult)) throw loginResult.error;
|
||||
return "email" as LoginStatus;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user