Skip to content

feat(form/auth): validate existing email and surface mapped field errors#21

Merged
kegren merged 2 commits intomainfrom
feat/auth-show-mapped-email-errors
Jan 4, 2026
Merged

feat(form/auth): validate existing email and surface mapped field errors#21
kegren merged 2 commits intomainfrom
feat/auth-show-mapped-email-errors

Conversation

@kegren
Copy link
Owner

@kegren kegren commented Jan 4, 2026

  • TextField: aggregate validation messages from both meta.errors
    and meta.errorMap, compute isInvalid from the combined list,
    and pass unified allErrors to FieldError so mapped errors are shown
    alongside standard errors.
  • SignUpForm: make submit handler async and check whether the provided
    email already exists before mutating; if it does, set a field
    meta.errorMap entry ("onSubmit") for the email field to halt submit
    and show the specific server-side validation error.
  • Auth actions: add checkEmailExists server function with input
    validation (zod) and a db lookup to indicate if an email is already
    registered. Exported alongside existing auth helpers.

Why:

  • Ensure server-side or mapped validation messages are surfaced in the
    UI (previously only meta.errors were shown) so users see accurate
    feedback.
  • Prevent duplicate registrations by checking email existence during
    sign-up and providing a clear field-level error instead of failing
    silently or returning a generic error.

- TextField: aggregate validation messages from both meta.errors
  and meta.errorMap, compute isInvalid from the combined list,
  and pass unified allErrors to FieldError so mapped errors are shown
  alongside standard errors.
- SignUpForm: make submit handler async and check whether the provided
  email already exists before mutating; if it does, set a field
  meta.errorMap entry ("onSubmit") for the email field to halt submit
  and show the specific server-side validation error.
- Auth actions: add checkEmailExists server function with input
  validation (zod) and a db lookup to indicate if an email is already
  registered. Exported alongside existing auth helpers.

Why:
- Ensure server-side or mapped validation messages are surfaced in the
  UI (previously only meta.errors were shown) so users see accurate
  feedback.
- Prevent duplicate registrations by checking email existence during
  sign-up and providing a clear field-level error instead of failing
  silently or returning a generic error.
@greptile-apps
Copy link

greptile-apps bot commented Jan 4, 2026

Greptile Summary

Enhanced form validation to surface server-side and mapped errors alongside standard validation errors, and added duplicate email detection during sign-up.

Key changes:

  • TextField now aggregates errors from both meta.errors and meta.errorMap to ensure all validation messages are displayed to users
  • Added checkEmailExists server function with input validation to check if an email is already registered before attempting sign-up
  • Sign-up form now performs async server-side email validation and displays field-level error when duplicate email is detected

Confidence Score: 4/5

  • This PR is safe to merge with minor optimization opportunity
  • The implementation correctly adds error aggregation and server-side email validation. The logic is sound and properly handles edge cases. Score reduced by 1 point due to redundant validation in sign-up-form.tsx (lines 73-74) that could be simplified.
  • The redundant validation in src/features/auth/components/sign-up-form.tsx could be simplified, but this is a minor style issue that doesn't affect functionality

Important Files Changed

Filename Overview
src/components/form/text-field.tsx Added error aggregation from both meta.errors and meta.errorMap to display all validation messages
src/features/auth/api/auth-actions.ts Added checkEmailExists server function with input validation to check for duplicate emails
src/features/auth/components/sign-up-form.tsx Made submit handler async and added server-side email existence check with field-level error feedback; contains redundant validation

Sequence Diagram

sequenceDiagram
    participant User
    participant SignUpForm
    participant TextField
    participant checkEmailExists
    participant Database
    participant authClient

    User->>SignUpForm: Fill form & submit
    SignUpForm->>SignUpForm: Validate with signUpSchema
    alt Validation fails
        SignUpForm->>TextField: Show meta.errors
        TextField->>User: Display validation errors
    else Validation passes
        SignUpForm->>checkEmailExists: Check email existence
        checkEmailExists->>checkEmailExists: Validate input (z.email())
        checkEmailExists->>Database: Query user by email
        Database-->>checkEmailExists: Return user or null
        alt Email exists
            checkEmailExists-->>SignUpForm: { exists: true }
            SignUpForm->>SignUpForm: Set errorMap["onSubmit"]
            SignUpForm->>TextField: Update with errorMap
            TextField->>TextField: Aggregate meta.errors + errorMap
            TextField->>User: Display "Email already registered"
        else Email available
            checkEmailExists-->>SignUpForm: { exists: false }
            SignUpForm->>authClient: signUp.email()
            authClient-->>SignUpForm: Success/Error
            alt Success
                SignUpForm->>User: Navigate to dashboard
            else Error
                SignUpForm->>User: Show toast error
            end
        end
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 73 to 74
const parsedValue = signUpSchema.safeParse(value);
const email = parsedValue.data?.email;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Redundant validation - the form already validates with signUpSchema on line 66, so value is guaranteed to be valid here. You can directly use value.email instead of calling safeParse again.

Suggested change
const parsedValue = signUpSchema.safeParse(value);
const email = parsedValue.data?.email;
const email = value.email;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/features/auth/components/sign-up-form.tsx
Line: 73:74

Comment:
**style:** Redundant validation - the form already validates with `signUpSchema` on line 66, so `value` is guaranteed to be valid here. You can directly use `value.email` instead of calling `safeParse` again.

```suggestion
      const email = value.email;
```

How can I resolve this? If you propose a fix, please make it concise.

@kegren kegren force-pushed the feat/auth-show-mapped-email-errors branch from a50c2d4 to d331e62 Compare January 4, 2026 12:20
@kegren kegren merged commit 802bfae into main Jan 4, 2026
1 check passed
@kegren kegren deleted the feat/auth-show-mapped-email-errors branch January 4, 2026 12:21
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.

1 participant