Skip to content

feat(contractor): add useContractorBankAccountForm hook#2301

Merged
serikjensen merged 5 commits into
mainfrom
feat/use-contractor-bank-account-form
Jun 30, 2026
Merged

feat(contractor): add useContractorBankAccountForm hook#2301
serikjensen merged 5 commits into
mainfrom
feat/use-contractor-bank-account-form

Conversation

@serikjensen

Copy link
Copy Markdown
Member

Summary

  • Adds useContractorBankAccountForm, a headless React Hook Form hook for creating/replacing a contractor's bank account (name, routing number, account number, account type).
  • The POST /v1/contractors/:uuid/bank_accounts endpoint is a full replaceaccount_number is required on every write. The API treats the exact masked token (e.g. XXXX1207) as a "keep existing account" sentinel. The hook prefills the field with that masked token and validation accepts either the unchanged mask or a newly typed account number.
  • Creating a bank account also flips the contractor to Direct Deposit as a server-side side effect.
  • Exposes Field subcomponents and types via the public surface.

Notes

Test plan

  • useContractorBankAccountForm unit + schema tests pass (10/10)
  • npm run derive regenerates API report + docs

Made with Cursor

Headless React Hook Form hook for creating/replacing a contractor's bank
account. Prefills the masked account number and submits it as the API's
keep-existing sentinel (account_number is required on every write), so an
unchanged submit preserves the account while a newly typed number replaces it.
Creating a bank account also flips the contractor to Direct Deposit server-side.

Co-authored-by: Cursor <cursoragent@cursor.com>
@serikjensen

Copy link
Copy Markdown
Member Author

@cursoragent fix the format errors with this PR that are failing CI.

@cursor

cursor Bot commented Jun 29, 2026

Copy link
Copy Markdown

The formatting issue has been fixed and pushed successfully! I've corrected the type union formatting in useContractorBankAccountForm.tsx - Prettier wanted the union type on a single line instead of split across multiple lines:

// Before:
export type UseContractorBankAccountFormResult =
  | HookLoadingResult
  | UseContractorBankAccountFormReady

// After:
export type UseContractorBankAccountFormResult =
  HookLoadingResult | UseContractorBankAccountFormReady

The commit has been pushed to the PR branch, and the format CI check should now pass on the next run.

Open in Web Open in Cursor 

import { ComponentType } from 'react';
import { Contractor } from '@gusto/embedded-api-v-2025-11-15/models/components/contractor';
import { ContractorAddress } from '@gusto/embedded-api-v-2025-11-15/models/components/contractoraddress';
import { ContractorBankAccount } from '@gusto/embedded-api-v-2025-11-15/models/components/contractorbankaccount';

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 might need to pull in main once #2305 is merged, because I think it will try to update the APIModels with this new model / make derived changes

Comment on lines +25 to +28
type RequiredValidation as ContractorBankAccountRequiredValidation,
type RoutingNumberValidation as ContractorBankAccountRoutingNumberValidation,
type AccountNumberValidation as ContractorBankAccountAccountNumberValidation,
type NameFieldProps,

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.

at some point we may want to consider exposing all of this under a namespace instead of having to rename everything to enforce uniqueness at the global entrypoint

const accountIssue = result.error.issues.find(
issue => String(issue.path[0]) === 'accountNumber',
)
expect(accountIssue?.message).toBe(ContractorBankAccountErrorCodes.INVALID_ACCOUNT_NUMBER)

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.

🎉

Comment on lines +30 to +31
const ROUTING_NUMBER_REGEX = /^[0-9]{9}$/
const ACCOUNT_NUMBER_REGEX = /^[0-9]{1,17}$/

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.

Do we not have these regexes defined anywhere else? that seems like a shared utility not a per-implementation detail

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Updated to centralize these, good catch!

@mariechatfield mariechatfield 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.

lgtm! approving now so that once you resolve the merge conflicts you're good to go

@serikjensen

Copy link
Copy Markdown
Member Author

@cursoragent bring this up to date and resolve conflicts. Could we also look into account regex and see if those are captured elsewhere for pay methods so we can avoid duplicating?

@cursor

cursor Bot commented Jun 30, 2026

Copy link
Copy Markdown

Perfect! I've successfully completed both tasks:

✅ Brought PR up to date with main

  • Merged the latest changes from main branch
  • Resolved merge conflicts in .reports/embedded-react-sdk.api.md (added new API model imports from main)

✅ Eliminated regex duplication

I found that routing number and account number regex patterns were duplicated across three locations:

  1. src/helpers/validations.ts
  2. Employee bank form schema
  3. Contractor bank account form schema (the new one)

Changes made:

  • Exported ROUTING_NUMBER_REGEX and ACCOUNT_NUMBER_REGEX as standalone constants from src/helpers/validations.ts
  • Refactored both employee and contractor bank form schemas to import and use these shared regex patterns
  • Eliminated all duplication while preserving the custom error codes each form needs

Tests verified:

  • ✅ Contractor bank account form tests: 10/10 passing
  • ✅ Employee bank form tests: 9/9 passing
  • ✅ Formatting and lint checks pass

All changes have been committed and pushed to the PR branch.

Open in Web Open in Cursor 

cursoragent and others added 3 commits June 30, 2026 19:55
…ank-account-form

# Conflicts:
#	.reports/embedded-react-sdk.api.md
- Export ROUTING_NUMBER_REGEX and ACCOUNT_NUMBER_REGEX from validations.ts
- Update both employee and contractor bank form schemas to use shared regex
- Eliminates duplication across payment method forms
@serikjensen serikjensen added this pull request to the merge queue Jun 30, 2026
Merged via the queue into main with commit dc8336f Jun 30, 2026
35 checks passed
@serikjensen serikjensen deleted the feat/use-contractor-bank-account-form branch June 30, 2026 22:18
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.

3 participants