Skip to content

MPDX-9766 - Enforce error deferment until fields are touched in useAutosave#1851

Merged
zweatshirt merged 3 commits into
mainfrom
defer-errors
Jun 18, 2026
Merged

MPDX-9766 - Enforce error deferment until fields are touched in useAutosave#1851
zweatshirt merged 3 commits into
mainfrom
defer-errors

Conversation

@zweatshirt

@zweatshirt zweatshirt commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Description

  • This improves UX when going through the NSO form and other forms, making it so users are not bombarded with errors upon rendering each step's view. The default functionality in useAutosave remains the same.
    https://jira.cru.org/browse/MPDX-9766

Testing

  • Go to NSO Questionnaire, and test that the behavior works as expected.
    • Continue button should remain disabled, but the fields are still required.

Considerations:

  • We may still want a way to make it apparent to users that all fields in a step are required, since we no longer have the clear indication of immediate errors.

Checklist:

  • I have given my PR a title with the format "MPDX-(JIRA#) (summary sentence max 80 chars)"
  • I have applied the appropriate labels (Add the label "Preview" to automatically create a preview environment)
  • I have run the Claude Code /pr-review command locally and fixed any relevant suggestions
  • I have requested a review from another person on the project
  • I have tested my changes in preview or in staging
  • I have cleaned up my commit history

@zweatshirt zweatshirt self-assigned this Jun 18, 2026
@zweatshirt zweatshirt added the Preview Environment Add this label to create an Amplify Preview label Jun 18, 2026
@zweatshirt zweatshirt marked this pull request as ready for review June 18, 2026 13:33
@github-actions

Copy link
Copy Markdown
Contributor

Preview branch generated at https://defer-errors.d3dytjb8adxkk5.amplifyapp.com

@github-actions

Copy link
Copy Markdown
Contributor

Bundle sizes [mpdx-react]

Compared against 9075fd9

No significant changes found

@zweatshirt zweatshirt left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🤖 Multi-Agent Code Review — Verdict: ✅ CLEAN

Risk: 6/10 (MEDIUM) · standard mode · agents across the review: Architecture, Testing, Standards, Data Integrity, UX, Financial + dependency analysis

No blockers, no Important findings — only two sub-5 suggestions (inline). The feature is sound and independently verified.

What this PR does

Adds an opt-in deferErrorsUntilTouched flag to the shared useAutoSave hook (default false), enabled in the questionnaire wrapper so validation errors stay hidden until a field is touched — avoiding a wall of errors on arrival. Every questionnaire field is also marked required (asterisk + aria-required) so mandatory-ness stays visible even while errors are deferred.

Verified safe

  • Validity gating preserved (Data Integrity, High confidence): error display is deferred, but markValid/markInvalid is unchanged and independent of touched — a user cannot Continue past hidden-but-invalid fields. Only the visual error is gated.
  • Backward compatible (dependency analysis): useAutoSave has 5 consumers; only the questionnaire wrapper opts in. With the flag defaulting false, the 4 other forms (PdsGoalCalculator, SalaryCalculator, GoalCalculator ×2) are byte-identical in behavior. showError reduces exactly to the original condition when the flag is off.
  • Accessibility (UX, High confidence): aria-required is valid on role=radiogroup and necessary (MUI's FormControl required does not propagate it to the group). The required work resolves the earlier concern that deferring errors left untouched required fields with no programmatic signal.
  • Standards: clean pass — named exports, localization, no any, no unused imports, MUI sx conventions.

Suggestions (severity < 5 — informational, non-blocking)

See inline comments. In brief: (1) the two MinistryDetails selects have required but no explicit test assertion; (2) minor display caveats of the touched-state flag. Neither blocks merge.

<Stack spacing={4}>
<TextField
select
required

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[Suggestion] The ministry and city `select` fields now set `required`, but unlike the location field (`toBeRequired`) and the `RadioQuestion`/`NumberQuestion` components (which own and test their own required state), the two selects have no explicit test asserting their required/`aria-required` state. Optional: add one assertion on the ministry combobox to regression-guard the `required` prop on selects. Non-blocking.

schema: yup.Schema;
disabled?: boolean;
saveOnChange?: boolean;
deferErrorsUntilTouched?: boolean;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[Suggestion] Two display-only caveats of the touched flag, both intentional/acceptable, noted for awareness: (1) `touched` is set on the first `onChange`, so a blur-saved number field can briefly flash an error mid-typing (this matches pre-change behavior, not a regression — but setting `touched` only `onBlur` for non-`saveOnChange` fields would be smoother); (2) `touched` never resets if the field value is reset externally — irrelevant for the questionnaire's in-memory state, and display-only regardless. No action required.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI Review Auto-Approval

Risk Level: MEDIUM (6/10)
Verdict: CLEAN (no issues found)

This PR was auto-approved because:

  • The multi-agent AI review determined it is medium risk
  • No blocking issues were found

If you believe this PR needs human review, dismiss this approval and request a review manually.

@zweatshirt zweatshirt requested a review from canac June 18, 2026 14:11

@canac canac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A couple minor thoughts, but thanks for noticing this issue and improving it!

Comment thread src/components/Shared/Autosave/useAutosave.ts Outdated
Comment thread src/components/Shared/Autosave/useAutosave.ts Outdated
label={question}
helperText={error ? errorText : helperText}
error={error}
required

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question: Are all number fields required? Like debt?

@zweatshirt zweatshirt Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I assumed if they are displayed to the user, then yes, unless we would prefer to populate empty field values with 0 even if displayed? I tend to lean toward required in general because it makes the user think through each question rather than rush through forms, but I can change this if we'd like. Maybe it's to refer to follow the original Google Form?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You're right, the Google Form makes them required (if they said they have debt) and tells them to input 0. The "If you are a parent with children in Childcare, please enter the number as a value between 0 and 9" question isn't required though. It's the only non-required question I see.

Screenshot 2026-06-18 at 9 52 37 AM

@zweatshirt zweatshirt changed the title MPDX-9766 - Optionally allow error deferment until fields are touched in useAutosave MPDX-9766 - Enforce error deferment until fields are touched in useAutosave Jun 18, 2026
@zweatshirt

zweatshirt commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@canac I realized from working on this that Nearest Geographic Multiplier Location and the MHA inputs in "Your Information" step of Salary Calculator aren't strictly enforced/required in the UI (even before this PR). I'm thinking we probably want both of these enforced. I've made a follow up ticket in the backlog.

@zweatshirt zweatshirt merged commit 8387c2f into main Jun 18, 2026
23 of 24 checks passed
@zweatshirt zweatshirt deleted the defer-errors branch June 18, 2026 20:30
@canac

canac commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

I realized from working on this that Nearest Geographic Multiplier Location and the MHA inputs in "Your Information" step of Salary Calculator aren't strictly enforced/required in the UI

Are you pointing out that they're optional fields? I believe the calculations treat missing a geo multiplier as None and missing MHA as 0 (which is a valid choice). Do stakeholders want us to force people to choose a value as opposed to leaving them blank?

@zweatshirt

Copy link
Copy Markdown
Contributor Author

@canac Ah if they truly are optional, that makes sense, the MHA Request section is a quick change then. The fields display an asterisk (hinting required). Will be a quick no-jira.

@canac

canac commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Yeah, I think removing the asterisk is a good call. Unless we want to make the MHA fields required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Preview Environment Add this label to create an Amplify Preview

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants