Skip to content

refactor(onboarding): build the basic information schema once - #1430

Closed
gabrielseco wants to merge 3 commits into
mainfrom
refactor/onboarding-basic-information-schema
Closed

gabrielseco wants to merge 3 commits into
mainfrom
refactor/onboarding-basic-information-schema

Conversation

@gabrielseco

@gabrielseco gabrielseco commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The Onboarding basic information step now builds its form once instead of rebuilding it every time a value changes. Nothing changes for users: conditional fields still show from pre-filled data and from what the user types.

Why

Rebuilding the form on every change is the old pattern. It's also where #1195's money-unit regression came from, fixed in #1429. The jsf v1 contract details (FRA, ITA, DEU, ESP) already build once and rely on validation to show or hide fields. This moves basic information to the same pattern as a first, small step, to see what breaks before doing the other steps.

What changed

Toggle details
  • New useBasicInformationSchema in Onboarding/api.ts, modelled on useContractDetailsSchema: fetches employment_basic_information, builds the form once with {} and transformMoneyFields: false. useJSONSchemaForm is left untouched; it's still used for legacy contract details, ContractorOnboarding and JsonSchemaComparison.
  • checkFieldUpdates now runs handleValidation on basic information too, not only on jsf v1 contract details. The basic information branch of handleValidation forces a re-render like the v1 branch does, so newly visible fields appear.
  • OnboardingForm mount effect now always calls checkFieldUpdates(form.getValues()), not only when there's an employmentId. Every step after basic information already has an employmentId, so in practice this only adds basic information on a fresh onboarding (where initialValues can pre-fill it) and select country.
  • Rebuilds keep visibility. A new jsfModify reference (e.g. a partner passing options inline, then a parent re-render) rebuilds the form with every field back in its default visibility. The legacy path didn't have this problem because it rebuilt with the current values. The last validated values are now replayed onto the rebuilt form during render, so nothing flashes.
  • Read-only employments that jump straight to review never mount the basic information form. The review hides fields the schema marks invisible, so basic information is validated with its initial values before the review values are built. Without this, seniority_date disappeared from the review.

Public API: no signature changes. One behaviour to look at: a headless useOnboarding() consumer with a custom form that never calls checkFieldUpdates on mount would no longer get conditional fields resolved from pre-filled basic information values. The legacy path did it by rebuilding the form. The jsf v1 contract details already have this requirement today.

Known limitation: the mount validation runs in a useEffect, so visibility is corrected right after the first paint. The jsf v1 contract details behave the same.

Screenshots

N/A

Related Resources

Testing

New tests in OnboardingFlow.test.tsx (basic information conditional fields from pre-filled values), using Portugal's has_seniority_date → seniority_date conditional:

  • From scratch: seniority_date stays hidden.
  • initialValues prop on a fresh onboarding: seniority_date shows without typing.
  • employmentId with seniority data: seniority_date shows without typing.
  • Read-only employment going straight to review: seniority_date is in the review.
  • Parent re-render with a new inline options object: seniority_date stays visible (passes on the legacy path, failed on this PR before the replay fix).

Each fix was removed one at a time to confirm a test fails without it:

Removed Failing test
Mount call in OnboardingForm initialValues, employmentId
handleValidation in checkFieldUpdates for basic information initialValues, employmentId
Validation before jumping to review read-only review
Re-render after basic information validation existing "selects yes → seniority_date shows"
Replaying values onto a rebuilt form inline options re-render
  • Tested against the example/ app in a browser
  • Feature flag: N/A

🤖 Generated with Claude Code


Note

Medium Risk
Touches core onboarding form lifecycle (schema fetch, conditional visibility, auto-review navigation) for a high-traffic step; behavior is intended to be unchanged but custom headless consumers that never call checkFieldUpdates on mount may lose pre-filled conditional fields.

Overview
Onboarding basic information now follows the same “build schema once, drive visibility via validation” pattern as JSF v1 contract details, instead of rebuilding the headless form on every value change.

useBasicInformationSchema (in api.ts, modeled on useContractDetailsSchema) fetches employment_basic_information and calls createHeadlessForm with empty values and transformMoneyFields: false. useOnboarding wires that hook in place of the per-change useJSONSchema path.

To keep conditional fields correct without rebuilds: OnboardingForm always runs checkFieldUpdates on mount so pre-filled/initialValues data is validated before the user types; checkFieldUpdates also runs handleValidation on the basic information step (with a re-render bump like contract details v1). When options/jsfModify changes and the form is rebuilt, the last validated values are replayed from a ref so fields like seniority_date do not disappear. Read-only employments that skip straight to review validate basic information against initial values before building review meta so conditionally visible fields still appear on review.

New tests cover Portugal has_seniority_date → seniority_date for scratch, initialValues, employmentId, review skip, and inline options re-render.

Reviewed by Cursor Bugbot for commit de2efb7. Bugbot is set up for automated code reviews on this repo. Configure here.

Basic information no longer rebuilds its headless form from the current
values on every change. The form is built once and conditional fields
are resolved through handleValidation, the same way the jsf v1 contract
details already work.

Pre-filled values (employment data or the initialValues prop) are
validated when the step mounts, and before a read-only employment jumps
straight to review, so conditional fields such as seniority_date still
show without the user typing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

Metric Current Previous Change Status
Total (gzip) 167.42 kB 167.25 kB +178 B (+0.1%) 🔴
Total (raw) 560.13 kB 559.22 kB +914 B (+0.2%) 🔴
CSS (gzip) 21.94 kB 21.94 kB 0 B (0%) 🟢
CSS (raw) 114.43 kB 114.43 kB 0 B (0%) 🟢

Size Limits

  • ✅ Total gzipped: 167.42 kB / 350 kB (47.8%)
  • ✅ Total raw: 560.13 kB / 850 kB (65.9%)
  • ✅ CSS gzipped: 21.94 kB / 25 kB (87.8%)

Largest Files (Top 5)

  1. CheckBoxField-CBXcXbix.js - 24.61 kB (0 B (0%))
  2. ContractorOnboarding-CyRnCPjP.js - 13.54 kB (new)
  3. Onboarding-BYAoXq1J.js - 11.39 kB (new)
  4. Termination-DajMayYi.js - 11.08 kB (new)
  5. styles.css - 10.97 kB (0 B (0%))
View All Files (75 total)
File Size (gzip) Change
CheckBoxField-CBXcXbix.js 24.61 kB 0 B (0%)
ContractorOnboarding-CyRnCPjP.js 13.54 kB new
Onboarding-BYAoXq1J.js 11.39 kB new
Termination-DajMayYi.js 11.08 kB new
styles.css 10.97 kB 0 B (0%)
index.css 10.97 kB 0 B (0%)
CostCalculator-BIwRFJJA.js 10.68 kB new
internals-CZZtO7dG.js 8.23 kB new
index.js 5.04 kB -1 B (-0.0%)
JSONSchemaForm-I1mWdIp7.js 4.92 kB 0 B (0%)

✅ Bundle size check passed

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Deploy preview for remote-flows ready!

Project:remote-flows
Status: ✅  Deploy successful!
Preview URL:https://remote-flows-6nqsoonnd-remotecom.vercel.app
Latest Commit:de2efb7

Deployed with vercel-action

…ebuilt

A new jsfModify reference, for example options passed inline and a parent
re-render, rebuilds the basic information form with every field back in
its default visibility. Replay the last validated values onto the new
form so conditional fields such as seniority_date stay visible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Deploy preview for adp-cost-calculator ready!

Project:adp-cost-calculator
Status: ✅  Deploy successful!
Preview URL:https://adp-cost-calculator-g6gh7g44x-remotecom.vercel.app
Latest Commit:189bda9

Deployed with vercel-action

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

📊 Coverage Report

✅ Coverage increased! 🎉

Metric Current Previous Change Status
Lines 86.42% 86.36% +0.06% 🟢
Statements 86.00% 85.93% +0.07% 🟢
Functions 85.00% 84.92% +0.08% 🟢
Branches 77.79% 77.80% -0.02% 🔴

Detailed Breakdown

Lines Coverage
  • Covered: 4881 / 5648
  • Coverage: 86.42%
  • Change: +0.06% (31 lines)
Statements Coverage
  • Covered: 4969 / 5778
  • Coverage: 86.00%
  • Change: +0.07% (35 statements)
Functions Coverage
  • Covered: 1298 / 1527
  • Coverage: 85.00%
  • Change: +0.08% (8 functions)
Branches Coverage
  • Covered: 3015 / 3876
  • Coverage: 77.79%
  • Change: -0.02% (11 branches)

✅ Coverage check passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit de2efb7. Configure here.

);
return basicInformationForm?.handleValidation(parsedValues);
lastBasicInformationValuesRef.current = parsedValues;
const result = basicInformationForm?.handleValidation(parsedValues);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stripped values hide nested conditionals

Medium Severity

Visibility for basic information now depends on handleValidation, but values are parsed with isPartialValidation: false and then stored in lastBasicInformationValuesRef. That drops currently hidden fields, so a nested conditional cannot see the parent value it needs on mount or after a form rebuild. The v1 contract-details path keeps invisible values for this reason, and the new review jump already uses isPartialValidation: true.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit de2efb7. Configure here.

onboardingBag?.checkFieldUpdates(form.getValues());
}
// Pre-filled values need to reach useStepState and be validated so conditional
// fields show before the user types.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Multi-line implementation comment

Low Severity

The new comment in OnboardingForm spans two lines. Implementation comments are limited to a single short line that explains why, with no multi-line blocks.

Fix in Cursor Fix in Web

Triggered by project rule: Code Review Guidelines

Reviewed by Cursor Bugbot for commit de2efb7. Configure here.

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