Skip to content

72 form updates#87

Merged
ArnavGupta23 merged 8 commits into
mainfrom
72-form-updates
May 19, 2026
Merged

72 form updates#87
ArnavGupta23 merged 8 commits into
mainfrom
72-form-updates

Conversation

@ArnavGupta23
Copy link
Copy Markdown
Member

@ArnavGupta23 ArnavGupta23 commented May 18, 2026

Pull Request

some form updates.

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Other (please describe):

Related Issues (put task name here from notion)

Screenshots (If it is a front end feature screenshot is required)

Additional Notes

Summary by CodeRabbit

  • New Features

    • Real-time, debounced (400ms) email uniqueness check with async validation on change and submit.
    • Base form URL now redirects to the consent step; an added catch-all form route forwards to consent.
    • Form is reset after successful submission to clear entered data.
  • Bug Fixes

    • Email addresses are normalized (trimmed, lowercased) everywhere before validation and save; duplicate submissions are prevented by server-side checks.
    • Local form storage is removed when the form is empty.

Review Change Stack

@ArnavGupta23 ArnavGupta23 self-assigned this May 18, 2026
@ArnavGupta23 ArnavGupta23 linked an issue May 18, 2026 that may be closed by this pull request
@ArnavGupta23 ArnavGupta23 marked this pull request as draft May 18, 2026 04:10
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6e0f893-ec2a-41e9-9191-f76ca0fca464

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5a832 and f8c91d2.

📒 Files selected for processing (1)
  • app/src/components/form/sections/GeneralInfo.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/components/form/sections/GeneralInfo.tsx

📝 Walkthrough

Walkthrough

Adds server-side email availability check and duplicate error, normalizes emails (trim + lowercase) across client submit and server persistence, enforces transaction-time duplicate checks, integrates async client-side uniqueness validation and normalized confirmation comparison, and updates routing and localStorage handling.

Changes

Family Email Duplicate Detection and Normalization

Layer / File(s) Summary
Email validation contract and server endpoint
app/src/server/functions/familyForm.ts
Exports DUPLICATE_FAMILY_EMAIL_MESSAGE and adds checkFamilyEmailAvailability POST endpoint that validates and normalizes input, queries families, and returns availability or throws the duplicate error.
Server submission with duplicate check and persistence
app/src/server/functions/familyForm.ts
submitFamilyForm normalizes data.generalInfo.email, performs a transaction-time duplicate check using the normalized email, and persists the normalized email in the created Family document.
Client-side async validation and submission
app/src/components/form/sections/GeneralInfo.tsx, app/src/hooks/mutations/useSubmitFamilyForm.ts
Adds validateUniqueFamilyEmail helper; wires debounced async validators into the email field (onChangeAsyncDebounceMs: 400, onChangeAsync, onSubmitAsync); updates emailConfirm to compare normalized values; normalizes email (trim().toLowerCase()) in the submission payload builder.
FormProvider localStorage empty-state handling
app/src/components/providers/FormProvider.tsx
Debounced localStorage effect removes family-form-${driveId} and returns early when formState is empty.
Generated route tree: add splat route
app/src/routeTree.gen.ts
Registers the new splat route '/family/drive/$driveId/form/$' (import, route constant, type maps, and module augmentation updates).
Route beforeLoad redirect and splat file
app/src/routes/family/drive/$driveId/form.tsx, app/src/routes/family/drive/$driveId/form/$.tsx
Adds beforeLoad on the base form route to redirect /form/form/consent and implements the splat route file that also redirects to /form/consent, preserving driveId.
Review route: reset form before navigation
app/src/routes/family/drive/$driveId/form/review.tsx
Extracts resetForm from useFormContext() and calls resetForm() before navigating to the thank-you route on successful submission.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant validateUniqueFamilyEmail
  participant checkFamilyEmailAvailability
  participant Firestore
  Client->>validateUniqueFamilyEmail: onChange/onSubmit (email)
  validateUniqueFamilyEmail->>checkFamilyEmailAvailability: POST normalized email
  checkFamilyEmailAvailability->>checkFamilyEmailAvailability: normalize + validate input
  checkFamilyEmailAvailability->>Firestore: query families where email == normalizedEmail
  alt duplicate found
    checkFamilyEmailAvailability-->>validateUniqueFamilyEmail: throw DUPLICATE_FAMILY_EMAIL_MESSAGE
    validateUniqueFamilyEmail-->>Client: validator error (duplicate)
  else available
    checkFamilyEmailAvailability->>validateUniqueFamilyEmail: { available: true }
    validateUniqueFamilyEmail-->>Client: validator passes
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • rk234

Poem

🐰 I trim and I lowercase, hop through each field,

I ask the server kindly if duplicates yield.
If none are found, I twirl with delight,
If one appears, I stop — hold on tight.
A tidy form, neat as a stitch — hooray for normalized mail and duplicate catch!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "72 form updates" is vague and generic, using a ticket number reference without describing the actual changes made in the changeset. Replace with a descriptive title that summarizes the main changes, such as "Add email validation, normalization, and form cleanup on submission" or "Implement family email uniqueness validation and improve form handling".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 72-form-updates

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/components/form/sections/GeneralInfo.tsx`:
- Around line 35-38: The catch block in GeneralInfo.tsx currently returns
error.message directly which can leak backend details; update the catch so it
only returns the raw DUPLICATE_FAMILY_EMAIL_MESSAGE when the caught error is an
Error AND its message exactly matches DUPLICATE_FAMILY_EMAIL_MESSAGE, otherwise
return a controlled generic validation message (e.g., "Unable to validate email
at this time") instead of error.message; change the logic around the existing
catch in the function handling family email validation to compare error.message
to DUPLICATE_FAMILY_EMAIL_MESSAGE and fallback to the safe generic string for
all other errors.

In `@app/src/server/functions/familyForm.ts`:
- Around line 97-107: The current non-transactional uniqueness check in
assertFamilyEmailAvailable allows races; move the uniqueness enforcement inside
the same database transaction that creates the family (the runTransaction block
that writes the family document with email: normalizedEmail) or implement an
atomic claim collection (e.g., create/claim a familyEmailClaims document keyed
by normalizedEmail inside runTransaction) so the transaction either
reads/creates the claim and then writes the family or fails if the claim exists;
update code paths that call assertFamilyEmailAvailable to instead perform the
check/claim within the transaction and remove the external pre-check to ensure
atomicity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e1f1dc4-0de3-46a8-818a-49de131ed08a

📥 Commits

Reviewing files that changed from the base of the PR and between cf3a86d and 2eebf9a.

📒 Files selected for processing (3)
  • app/src/components/form/sections/GeneralInfo.tsx
  • app/src/hooks/mutations/useSubmitFamilyForm.ts
  • app/src/server/functions/familyForm.ts

Comment thread app/src/components/form/sections/GeneralInfo.tsx Outdated
Comment thread app/src/server/functions/familyForm.ts
@ArnavGupta23 ArnavGupta23 marked this pull request as ready for review May 19, 2026 16:16
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/src/server/functions/familyForm.ts (1)

210-217: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Query-in-transaction still leaves a duplicate-email race.

This query only protects documents it actually reads. If the result is empty, two concurrent submissions can both observe “no family yet” and each create a different family with the same normalized email. Use a sentinel/claim document keyed by the normalized email (or the email itself as the document ID) and read/create that exact document inside the transaction.

In Cloud Firestore, if a transaction reads a query that currently returns no documents and then writes a new document that would match that query, can two concurrent transactions both commit? What do the official docs recommend for enforcing uniqueness?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/server/functions/familyForm.ts` around lines 210 - 217, The
transaction currently queries db.families.where(...) which can still race;
instead use a sentinel document keyed by the normalized email and read/create
that exact document inside the transaction: in the runTransaction block replace
the query-based check (existingFamily / db.families.where) with a transactional
read of db.families.doc(normalizedEmail) (or a dedicated claims collection like
familiesClaims.doc(normalizedEmail)), throw DUPLICATE_FAMILY_EMAIL_MESSAGE if
that doc exists, and create the sentinel/doc as part of the same transaction
before creating the family record so uniqueness is enforced atomically.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/components/form/sections/GeneralInfo.tsx`:
- Around line 19-44: Synchronous validators must use the same trim+lowercase
normalization as validateUniqueFamilyEmail to avoid false mismatches; update the
synchronous email validator to normalize the input (const normalized =
value?.trim().toLowerCase()) before empty and regex checks, and update the
emailConfirm comparison to compare normalized versions (normalize both email and
emailConfirm) so case-only or whitespace-only differences no longer cause
“invalid” or “Emails do not match” results; refer to validateUniqueFamilyEmail
and the email / emailConfirm validators (the comparison logic around lines
90-94) when making the changes.

---

Duplicate comments:
In `@app/src/server/functions/familyForm.ts`:
- Around line 210-217: The transaction currently queries db.families.where(...)
which can still race; instead use a sentinel document keyed by the normalized
email and read/create that exact document inside the transaction: in the
runTransaction block replace the query-based check (existingFamily /
db.families.where) with a transactional read of db.families.doc(normalizedEmail)
(or a dedicated claims collection like familiesClaims.doc(normalizedEmail)),
throw DUPLICATE_FAMILY_EMAIL_MESSAGE if that doc exists, and create the
sentinel/doc as part of the same transaction before creating the family record
so uniqueness is enforced atomically.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 720267a2-10f8-43b5-838e-ee1ea7ea5b09

📥 Commits

Reviewing files that changed from the base of the PR and between 2eebf9a and 7d5a832.

📒 Files selected for processing (8)
  • app/src/components/form/sections/GeneralInfo.tsx
  • app/src/components/providers/FormProvider.tsx
  • app/src/hooks/mutations/useSubmitFamilyForm.ts
  • app/src/routeTree.gen.ts
  • app/src/routes/family/drive/$driveId/form.tsx
  • app/src/routes/family/drive/$driveId/form/$.tsx
  • app/src/routes/family/drive/$driveId/form/review.tsx
  • app/src/server/functions/familyForm.ts
✅ Files skipped from review due to trivial changes (2)
  • app/src/routes/family/drive/$driveId/form/$.tsx
  • app/src/routeTree.gen.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/hooks/mutations/useSubmitFamilyForm.ts

Comment thread app/src/components/form/sections/GeneralInfo.tsx
@ArnavGupta23 ArnavGupta23 merged commit 3ebb8dc into main May 19, 2026
4 checks passed
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.

form updates and cleanups

1 participant