@gusto/embedded-react-sdk 0.49.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/components/Base/createCompoundContext.d.ts +1 -1
- package/dist/components/Base/createCompoundContext.js.map +1 -1
- package/dist/components/Common/UI/Breadcrumbs/Breadcrumbs.js +1 -1
- package/dist/components/Common/UI/CalendarPreview/CalendarLegend.d.ts +1 -1
- package/dist/components/Common/UI/CalendarPreview/CalendarLegend.js.map +1 -1
- package/dist/components/Common/UI/FileInput/FileInput.js +1 -1
- package/dist/components/Common/UI/ProgressBar/ProgressBar.js +4 -4
- package/dist/components/Company/AssignSignatory/CreateSignatory/useCreateSignatory.js +5 -3
- package/dist/components/Company/AssignSignatory/CreateSignatory/useCreateSignatory.js.map +1 -1
- package/dist/components/Company/AssignSignatory/InviteSignatory/useInviteSignatory.js +5 -3
- package/dist/components/Company/AssignSignatory/InviteSignatory/useInviteSignatory.js.map +1 -1
- package/dist/components/Company/AssignSignatory/useAssignSignatory.js +7 -5
- package/dist/components/Company/AssignSignatory/useAssignSignatory.js.map +1 -1
- package/dist/components/Company/BankAccount/BankAccountForm/context.js +5 -3
- package/dist/components/Company/BankAccount/BankAccountForm/context.js.map +1 -1
- package/dist/components/Company/DocumentSigner/DocumentList/useDocumentList.js +5 -3
- package/dist/components/Company/DocumentSigner/DocumentList/useDocumentList.js.map +1 -1
- package/dist/components/Company/DocumentSigner/shared/useSignCompanyForm/signCompanyFormSchema.d.ts +1 -0
- package/dist/components/Company/DocumentSigner/shared/useSignCompanyForm/signCompanyFormSchema.js.map +1 -1
- package/dist/components/Company/FederalTaxes/useFederalTaxes.js +10 -8
- package/dist/components/Company/FederalTaxes/useFederalTaxes.js.map +1 -1
- package/dist/components/Company/Industry/Context.js +8 -6
- package/dist/components/Company/Industry/Context.js.map +1 -1
- package/dist/components/Company/Locations/LocationForm/useLocationForm.js +5 -3
- package/dist/components/Company/Locations/LocationForm/useLocationForm.js.map +1 -1
- package/dist/components/Company/Locations/LocationsList/useLocationsList.js +5 -3
- package/dist/components/Company/Locations/LocationsList/useLocationsList.js.map +1 -1
- package/dist/components/Company/OnboardingFlow/OnboardingFlow.d.ts +1 -1
- package/dist/components/Company/OnboardingFlow/OnboardingFlow.js.map +1 -1
- package/dist/components/Company/OnboardingOverview/context.js +5 -3
- package/dist/components/Company/OnboardingOverview/context.js.map +1 -1
- package/dist/components/Company/PaySchedule/shared/usePayScheduleForm/payScheduleSchema.d.ts +1 -0
- package/dist/components/Company/PaySchedule/shared/usePayScheduleForm/payScheduleSchema.js.map +1 -1
- package/dist/components/Company/StateTaxes/StateTaxesForm/context.js +5 -3
- package/dist/components/Company/StateTaxes/StateTaxesForm/context.js.map +1 -1
- package/dist/components/Company/StateTaxes/StateTaxesList/context.js +5 -3
- package/dist/components/Company/StateTaxes/StateTaxesList/context.js.map +1 -1
- package/dist/components/Contractor/Address/shared/useContractorAddressForm/contractorAddressSchema.d.ts +1 -0
- package/dist/components/Contractor/Address/shared/useContractorAddressForm/contractorAddressSchema.js.map +1 -1
- package/dist/components/Contractor/Address/shared/useContractorAddressForm/useContractorAddressForm.d.ts +38 -0
- package/dist/components/Contractor/Address/shared/useContractorAddressForm/useContractorAddressForm.js.map +1 -1
- package/dist/components/Contractor/Documents/DocumentsList/useContractorDocumentsList/useContractorDocumentsList.d.ts +1 -0
- package/dist/components/Contractor/Documents/DocumentsList/useContractorDocumentsList/useContractorDocumentsList.js.map +1 -1
- package/dist/components/Contractor/OnboardingFlow/OnboardingFlow.d.ts +3 -3
- package/dist/components/Contractor/OnboardingFlow/OnboardingFlow.js.map +1 -1
- package/dist/components/Contractor/PaymentMethod/PaymentMethod.d.ts +5 -5
- package/dist/components/Contractor/PaymentMethod/PaymentMethod.js +105 -108
- package/dist/components/Contractor/PaymentMethod/PaymentMethod.js.map +1 -1
- package/dist/components/Contractor/PaymentMethod/PaymentMethod.module.scss.js +8 -0
- package/dist/components/Contractor/PaymentMethod/PaymentMethod.module.scss.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/shared/index.d.ts +2 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/fields.d.ts +93 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/fields.js +22 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/fields.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/index.d.ts +5 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/useContractorBankAccountForm.d.ts +127 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/useContractorBankAccountForm.js +109 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/useContractorBankAccountForm.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/useContractorBankAccountFormSchema.d.ts +83 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/useContractorBankAccountFormSchema.js +42 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorBankAccountForm/useContractorBankAccountFormSchema.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/contractorPaymentMethodSchema.d.ts +58 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/contractorPaymentMethodSchema.js +21 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/contractorPaymentMethodSchema.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/fields.d.ts +20 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/fields.js +9 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/fields.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/index.d.ts +5 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/useContractorPaymentMethodForm.d.ts +117 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/useContractorPaymentMethodForm.js +91 -0
- package/dist/components/Contractor/PaymentMethod/shared/useContractorPaymentMethodForm/useContractorPaymentMethodForm.js.map +1 -0
- package/dist/components/Contractor/PaymentMethod/types.d.ts +0 -5
- package/dist/components/Contractor/Payments/PaymentFlow/PaymentFlow.d.ts +2 -2
- package/dist/components/Contractor/Payments/PaymentFlow/PaymentFlow.js.map +1 -1
- package/dist/components/Contractor/Profile/shared/useContractorDetailsForm/contractorDetailsSchema.d.ts +1 -0
- package/dist/components/Contractor/Profile/shared/useContractorDetailsForm/contractorDetailsSchema.js.map +1 -1
- package/dist/components/Contractor/Profile/shared/useContractorDetailsForm/useContractorDetailsForm.d.ts +45 -0
- package/dist/components/Contractor/Profile/shared/useContractorDetailsForm/useContractorDetailsForm.js.map +1 -1
- package/dist/components/Employee/Compensation/shared/useCompensationForm/compensationSchema.d.ts +1 -0
- package/dist/components/Employee/Compensation/shared/useCompensationForm/compensationSchema.js.map +1 -1
- package/dist/components/Employee/Dashboard/DashboardFlow.d.ts +1 -1
- package/dist/components/Employee/Dashboard/DashboardFlow.js.map +1 -1
- package/dist/components/Employee/Deductions/shared/useChildSupportGarnishmentForm/childSupportGarnishmentFormSchema.d.ts +1 -0
- package/dist/components/Employee/Deductions/shared/useChildSupportGarnishmentForm/childSupportGarnishmentFormSchema.js.map +1 -1
- package/dist/components/Employee/Deductions/shared/useDeductionForm/deductionFormSchema.d.ts +1 -0
- package/dist/components/Employee/Deductions/shared/useDeductionForm/deductionFormSchema.js.map +1 -1
- package/dist/components/Employee/Documents/onboarding/DocumentSigner/DocumentList/useDocumentList.js +5 -3
- package/dist/components/Employee/Documents/onboarding/DocumentSigner/DocumentList/useDocumentList.js.map +1 -1
- package/dist/components/Employee/Documents/shared/useSignEmployeeForm/signEmployeeFormSchema.d.ts +1 -0
- package/dist/components/Employee/Documents/shared/useSignEmployeeForm/signEmployeeFormSchema.js.map +1 -1
- package/dist/components/Employee/EmployeeListFlow/EmployeeListFlow.d.ts +2 -2
- package/dist/components/Employee/EmployeeListFlow/EmployeeListFlow.js.map +1 -1
- package/dist/components/Employee/FederalTaxes/shared/FederalTaxesView.js +1 -1
- package/dist/components/Employee/FederalTaxes/shared/useFederalTaxesForm/federalTaxesSchema.d.ts +1 -0
- package/dist/components/Employee/FederalTaxes/shared/useFederalTaxesForm/federalTaxesSchema.js.map +1 -1
- package/dist/components/Employee/OnboardingExecutionFlow/OnboardingExecutionFlow.d.ts +2 -2
- package/dist/components/Employee/OnboardingExecutionFlow/OnboardingExecutionFlow.js.map +1 -1
- package/dist/components/Employee/OnboardingFlow/OnboardingFlow.d.ts +3 -3
- package/dist/components/Employee/OnboardingFlow/OnboardingFlow.js.map +1 -1
- package/dist/components/Employee/PaymentMethod/shared/useBankForm/useBankForm.d.ts +4 -4
- package/dist/components/Employee/PaymentMethod/shared/useBankForm/useBankForm.js.map +1 -1
- package/dist/components/Employee/PaymentMethod/shared/useBankForm/useBankFormSchema.d.ts +1 -0
- package/dist/components/Employee/PaymentMethod/shared/useBankForm/useBankFormSchema.js +7 -6
- package/dist/components/Employee/PaymentMethod/shared/useBankForm/useBankFormSchema.js.map +1 -1
- package/dist/components/Employee/PaymentMethod/shared/usePaymentMethodForm/usePaymentMethodForm.d.ts +1 -1
- package/dist/components/Employee/PaymentMethod/shared/usePaymentMethodForm/usePaymentMethodForm.js.map +1 -1
- package/dist/components/Employee/PaymentMethod/shared/usePaymentMethodForm/usePaymentMethodFormSchema.d.ts +1 -0
- package/dist/components/Employee/PaymentMethod/shared/usePaymentMethodForm/usePaymentMethodFormSchema.js.map +1 -1
- package/dist/components/Employee/PaymentMethod/shared/useSplitPaymentsForm/useSplitPaymentsForm.d.ts +2 -2
- package/dist/components/Employee/PaymentMethod/shared/useSplitPaymentsForm/useSplitPaymentsForm.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/employeeDetailsSchema.d.ts +1 -0
- package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/employeeDetailsSchema.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.d.ts +11 -12
- package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useHomeAddressForm/homeAddressSchema.d.ts +1 -0
- package/dist/components/Employee/Profile/shared/useHomeAddressForm/homeAddressSchema.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useHomeAddressForm/useHomeAddressForm.d.ts +36 -0
- package/dist/components/Employee/Profile/shared/useHomeAddressForm/useHomeAddressForm.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useWorkAddressForm/useWorkAddressForm.d.ts +31 -0
- package/dist/components/Employee/Profile/shared/useWorkAddressForm/useWorkAddressForm.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useWorkAddressForm/workAddressSchema.d.ts +1 -0
- package/dist/components/Employee/Profile/shared/useWorkAddressForm/workAddressSchema.js.map +1 -1
- package/dist/components/Employee/SelfOnboardingFlow/SelfOnboardingFlow.d.ts +2 -2
- package/dist/components/Employee/SelfOnboardingFlow/SelfOnboardingFlow.js.map +1 -1
- package/dist/components/Employee/StateTaxes/shared/useEmployeeStateTaxesForm/fieldProps.d.ts +36 -18
- package/dist/components/Employee/StateTaxes/shared/useEmployeeStateTaxesForm/fields.d.ts +113 -13
- package/dist/components/Employee/StateTaxes/shared/useEmployeeStateTaxesForm/fields.js.map +1 -1
- package/dist/components/Employee/StateTaxes/shared/useEmployeeStateTaxesForm/index.d.ts +1 -1
- package/dist/components/Employee/StateTaxes/shared/useEmployeeStateTaxesForm/useEmployeeStateTaxesForm.d.ts +2 -7
- package/dist/components/Employee/StateTaxes/shared/useEmployeeStateTaxesForm/useEmployeeStateTaxesForm.js.map +1 -1
- package/dist/components/Flow/Flow.js +1 -1
- package/dist/components/InformationRequests/InformationRequests.d.ts +3 -3
- package/dist/components/InformationRequests/InformationRequests.js.map +1 -1
- package/dist/components/Payroll/usePreparedPayrollData.js +10 -8
- package/dist/components/Payroll/usePreparedPayrollData.js.map +1 -1
- package/dist/helpers/validations.d.ts +12 -0
- package/dist/helpers/validations.js +6 -4
- package/dist/helpers/validations.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +247 -237
- package/dist/index.js.map +1 -1
- package/dist/models/external.d.ts +6 -0
- package/dist/style.css +1 -1
- package/dist/types/sdkError.js +13 -6
- package/dist/types/sdkError.js.map +1 -1
- package/package.json +7 -7
- package/dist/components/Contractor/PaymentMethod/BankAccountForm.d.ts +0 -3
- package/dist/components/Contractor/PaymentMethod/BankAccountForm.js +0 -56
- package/dist/components/Contractor/PaymentMethod/BankAccountForm.js.map +0 -1
- package/dist/components/Contractor/PaymentMethod/PaymentTypeForm.d.ts +0 -2
- package/dist/components/Contractor/PaymentMethod/PaymentTypeForm.js +0 -33
- package/dist/components/Contractor/PaymentMethod/PaymentTypeForm.js.map +0 -1
- /package/docs/{appendix → guides}/endpoint-inventory.json +0 -0
package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/employeeDetailsSchema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"employeeDetailsSchema.js","sources":["../../../../../../src/components/Employee/Profile/shared/useEmployeeDetailsForm/employeeDetailsSchema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n buildFormSchema,\n type RequiredFieldConfig,\n type OptionalFieldsToRequire,\n} from '@/partner-hook-utils/form/buildFormSchema'\nimport { SSN_REGEX, NAME_REGEX } from '@/helpers/validations'\n\n// ── Error codes ────────────────────────────────────────────────────────\n\n/**\n * Validation error codes emitted by the employee details form schema. Map\n * these codes to localized copy in `validationMessages` when composing the\n * hook.\n *\n * @public\n */\nexport const EmployeeDetailsErrorCodes = {\n REQUIRED: 'REQUIRED',\n INVALID_NAME: 'INVALID_NAME',\n INVALID_EMAIL: 'INVALID_EMAIL',\n INVALID_SSN: 'INVALID_SSN',\n EMAIL_REQUIRED_FOR_SELF_ONBOARDING: 'EMAIL_REQUIRED_FOR_SELF_ONBOARDING',\n} as const\n\n/**\n * Union of validation error code strings emitted by the employee details form\n * schema.\n *\n * @public\n */\nexport type EmployeeDetailsErrorCode =\n (typeof EmployeeDetailsErrorCodes)[keyof typeof EmployeeDetailsErrorCodes]\n\n// ── Field validators ───────────────────────────────────────────────────\n\nconst fieldValidators = {\n firstName: z\n .string()\n .min(1, { message: EmployeeDetailsErrorCodes.REQUIRED })\n .regex(NAME_REGEX, { message: EmployeeDetailsErrorCodes.INVALID_NAME }),\n middleInitial: z.string(),\n lastName: z\n .string()\n .min(1, { message: EmployeeDetailsErrorCodes.REQUIRED })\n .regex(NAME_REGEX, { message: EmployeeDetailsErrorCodes.INVALID_NAME }),\n email: z.email({\n error: issue =>\n typeof issue.input === 'string' && issue.input.length === 0\n ? EmployeeDetailsErrorCodes.REQUIRED\n : EmployeeDetailsErrorCodes.INVALID_EMAIL,\n }),\n dateOfBirth: z.iso.date({ error: () => EmployeeDetailsErrorCodes.REQUIRED }),\n ssn: z\n .string({ error: () => EmployeeDetailsErrorCodes.REQUIRED })\n .refine((v: string) => SSN_REGEX.test(v.replace(/\\D/g, '')), {\n message: EmployeeDetailsErrorCodes.INVALID_SSN,\n }),\n selfOnboarding: z.boolean(),\n}\n\n/**\n * Field names accepted by the employee details form.\n *\n * @public\n */\nexport type EmployeeDetailsField = Exclude<keyof typeof fieldValidators, 'selfOnboarding'>\n\n/**\n * Shape of the values managed by the employee details form.\n *\n * @public\n */\nexport type EmployeeDetailsFormData = {\n [K in keyof typeof fieldValidators]: z.infer<(typeof fieldValidators)[K]>\n}\n/**\n * Shape of the validated values produced by the employee details form on\n * submit.\n *\n * @public\n */\nexport type EmployeeDetailsFormOutputs = EmployeeDetailsFormData\n\n// ── Required fields config ─────────────────────────────────────────────\n\nconst requiredFieldsConfig = {\n firstName: 'create',\n lastName: 'create',\n middleInitial: 'never',\n email: 'never',\n dateOfBirth: 'never',\n ssn: 'never',\n} satisfies RequiredFieldConfig<typeof fieldValidators>\n\n// ── Schema factory ─────────────────────────────────────────────────────\n\n/**\n * Keys of optional employee details fields that can be promoted to required\n * via the hook's `optionalFieldsToRequire` option.\n *\n * @public\n */\nexport type EmployeeDetailsOptionalFieldsToRequire = OptionalFieldsToRequire<\n typeof requiredFieldsConfig\n>\n\n/** @internal */\ninterface EmployeeDetailsSchemaOptions {\n mode?: 'create' | 'update'\n optionalFieldsToRequire?: EmployeeDetailsOptionalFieldsToRequire\n hasSsn?: boolean\n}\n\n/** @internal */\nexport function createEmployeeDetailsSchema(options: EmployeeDetailsSchemaOptions = {}) {\n const { mode = 'create', optionalFieldsToRequire, hasSsn = false } = options\n\n return buildFormSchema(fieldValidators, {\n requiredFieldsConfig,\n requiredErrorCode: EmployeeDetailsErrorCodes.REQUIRED,\n mode,\n optionalFieldsToRequire,\n fieldsWithRedactedValues: hasSsn ? ['ssn'] : [],\n superRefine:\n mode === 'create'\n ? (data, ctx) => {\n if (data.selfOnboarding && (!data.email || data.email.trim() === '')) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['email'],\n message: EmployeeDetailsErrorCodes.EMAIL_REQUIRED_FOR_SELF_ONBOARDING,\n })\n }\n }\n : undefined,\n })\n}\n"],"names":["EmployeeDetailsErrorCodes","fieldValidators","z","NAME_REGEX","issue","v","SSN_REGEX","requiredFieldsConfig","createEmployeeDetailsSchema","options","mode","optionalFieldsToRequire","hasSsn","buildFormSchema","data","ctx"],"mappings":";;;AAiBO,MAAMA,IAA4B;AAAA,EACvC,UAAU;AAAA,EACV,cAAc;AAAA,EACd,eAAe;AAAA,EACf,aAAa;AAAA,EACb,oCAAoC;AACtC,GAaMC,IAAkB;AAAA,EACtB,WAAWC,EACR,OAAA,EACA,IAAI,GAAG,EAAE,SAASF,EAA0B,SAAA,CAAU,EACtD,MAAMG,GAAY,EAAE,SAASH,EAA0B,cAAc;AAAA,EACxE,eAAeE,EAAE,OAAA;AAAA,EACjB,UAAUA,EACP,OAAA,EACA,IAAI,GAAG,EAAE,SAASF,EAA0B,SAAA,CAAU,EACtD,MAAMG,GAAY,EAAE,SAASH,EAA0B,cAAc;AAAA,EACxE,OAAOE,EAAE,MAAM;AAAA,IACb,OAAO,CAAAE,MACL,OAAOA,EAAM,SAAU,YAAYA,EAAM,MAAM,WAAW,IACtDJ,EAA0B,WAC1BA,EAA0B;AAAA,EAAA,CACjC;AAAA,EACD,aAAaE,EAAE,IAAI,KAAK,EAAE,OAAO,MAAMF,EAA0B,UAAU;AAAA,EAC3E,KAAKE,EACF,OAAO,EAAE,OAAO,MAAMF,EAA0B,UAAU,EAC1D,OAAO,CAACK,MAAcC,EAAU,KAAKD,EAAE,QAAQ,OAAO,EAAE,CAAC,GAAG;AAAA,IAC3D,SAASL,EAA0B;AAAA,EAAA,CACpC;AAAA,EACH,gBAAgBE,EAAE,QAAA;AACpB,
|
|
1
|
+
{"version":3,"file":"employeeDetailsSchema.js","sources":["../../../../../../src/components/Employee/Profile/shared/useEmployeeDetailsForm/employeeDetailsSchema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n buildFormSchema,\n type RequiredFieldConfig,\n type OptionalFieldsToRequire,\n} from '@/partner-hook-utils/form/buildFormSchema'\nimport { SSN_REGEX, NAME_REGEX } from '@/helpers/validations'\n\n// ── Error codes ────────────────────────────────────────────────────────\n\n/**\n * Validation error codes emitted by the employee details form schema. Map\n * these codes to localized copy in `validationMessages` when composing the\n * hook.\n *\n * @public\n */\nexport const EmployeeDetailsErrorCodes = {\n REQUIRED: 'REQUIRED',\n INVALID_NAME: 'INVALID_NAME',\n INVALID_EMAIL: 'INVALID_EMAIL',\n INVALID_SSN: 'INVALID_SSN',\n EMAIL_REQUIRED_FOR_SELF_ONBOARDING: 'EMAIL_REQUIRED_FOR_SELF_ONBOARDING',\n} as const\n\n/**\n * Union of validation error code strings emitted by the employee details form\n * schema.\n *\n * @public\n */\nexport type EmployeeDetailsErrorCode =\n (typeof EmployeeDetailsErrorCodes)[keyof typeof EmployeeDetailsErrorCodes]\n\n// ── Field validators ───────────────────────────────────────────────────\n\nconst fieldValidators = {\n firstName: z\n .string()\n .min(1, { message: EmployeeDetailsErrorCodes.REQUIRED })\n .regex(NAME_REGEX, { message: EmployeeDetailsErrorCodes.INVALID_NAME }),\n middleInitial: z.string(),\n lastName: z\n .string()\n .min(1, { message: EmployeeDetailsErrorCodes.REQUIRED })\n .regex(NAME_REGEX, { message: EmployeeDetailsErrorCodes.INVALID_NAME }),\n email: z.email({\n error: issue =>\n typeof issue.input === 'string' && issue.input.length === 0\n ? EmployeeDetailsErrorCodes.REQUIRED\n : EmployeeDetailsErrorCodes.INVALID_EMAIL,\n }),\n dateOfBirth: z.iso.date({ error: () => EmployeeDetailsErrorCodes.REQUIRED }),\n ssn: z\n .string({ error: () => EmployeeDetailsErrorCodes.REQUIRED })\n .refine((v: string) => SSN_REGEX.test(v.replace(/\\D/g, '')), {\n message: EmployeeDetailsErrorCodes.INVALID_SSN,\n }),\n selfOnboarding: z.boolean(),\n}\n\n/**\n * Field names accepted by the employee details form.\n *\n * @public\n */\nexport type EmployeeDetailsField = Exclude<keyof typeof fieldValidators, 'selfOnboarding'>\n\n/**\n * Shape of the values managed by the employee details form.\n *\n * @public\n * @interface\n */\nexport type EmployeeDetailsFormData = {\n [K in keyof typeof fieldValidators]: z.infer<(typeof fieldValidators)[K]>\n}\n/**\n * Shape of the validated values produced by the employee details form on\n * submit.\n *\n * @public\n */\nexport type EmployeeDetailsFormOutputs = EmployeeDetailsFormData\n\n// ── Required fields config ─────────────────────────────────────────────\n\nconst requiredFieldsConfig = {\n firstName: 'create',\n lastName: 'create',\n middleInitial: 'never',\n email: 'never',\n dateOfBirth: 'never',\n ssn: 'never',\n} satisfies RequiredFieldConfig<typeof fieldValidators>\n\n// ── Schema factory ─────────────────────────────────────────────────────\n\n/**\n * Keys of optional employee details fields that can be promoted to required\n * via the hook's `optionalFieldsToRequire` option.\n *\n * @public\n */\nexport type EmployeeDetailsOptionalFieldsToRequire = OptionalFieldsToRequire<\n typeof requiredFieldsConfig\n>\n\n/** @internal */\ninterface EmployeeDetailsSchemaOptions {\n mode?: 'create' | 'update'\n optionalFieldsToRequire?: EmployeeDetailsOptionalFieldsToRequire\n hasSsn?: boolean\n}\n\n/** @internal */\nexport function createEmployeeDetailsSchema(options: EmployeeDetailsSchemaOptions = {}) {\n const { mode = 'create', optionalFieldsToRequire, hasSsn = false } = options\n\n return buildFormSchema(fieldValidators, {\n requiredFieldsConfig,\n requiredErrorCode: EmployeeDetailsErrorCodes.REQUIRED,\n mode,\n optionalFieldsToRequire,\n fieldsWithRedactedValues: hasSsn ? ['ssn'] : [],\n superRefine:\n mode === 'create'\n ? (data, ctx) => {\n if (data.selfOnboarding && (!data.email || data.email.trim() === '')) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['email'],\n message: EmployeeDetailsErrorCodes.EMAIL_REQUIRED_FOR_SELF_ONBOARDING,\n })\n }\n }\n : undefined,\n })\n}\n"],"names":["EmployeeDetailsErrorCodes","fieldValidators","z","NAME_REGEX","issue","v","SSN_REGEX","requiredFieldsConfig","createEmployeeDetailsSchema","options","mode","optionalFieldsToRequire","hasSsn","buildFormSchema","data","ctx"],"mappings":";;;AAiBO,MAAMA,IAA4B;AAAA,EACvC,UAAU;AAAA,EACV,cAAc;AAAA,EACd,eAAe;AAAA,EACf,aAAa;AAAA,EACb,oCAAoC;AACtC,GAaMC,IAAkB;AAAA,EACtB,WAAWC,EACR,OAAA,EACA,IAAI,GAAG,EAAE,SAASF,EAA0B,SAAA,CAAU,EACtD,MAAMG,GAAY,EAAE,SAASH,EAA0B,cAAc;AAAA,EACxE,eAAeE,EAAE,OAAA;AAAA,EACjB,UAAUA,EACP,OAAA,EACA,IAAI,GAAG,EAAE,SAASF,EAA0B,SAAA,CAAU,EACtD,MAAMG,GAAY,EAAE,SAASH,EAA0B,cAAc;AAAA,EACxE,OAAOE,EAAE,MAAM;AAAA,IACb,OAAO,CAAAE,MACL,OAAOA,EAAM,SAAU,YAAYA,EAAM,MAAM,WAAW,IACtDJ,EAA0B,WAC1BA,EAA0B;AAAA,EAAA,CACjC;AAAA,EACD,aAAaE,EAAE,IAAI,KAAK,EAAE,OAAO,MAAMF,EAA0B,UAAU;AAAA,EAC3E,KAAKE,EACF,OAAO,EAAE,OAAO,MAAMF,EAA0B,UAAU,EAC1D,OAAO,CAACK,MAAcC,EAAU,KAAKD,EAAE,QAAQ,OAAO,EAAE,CAAC,GAAG;AAAA,IAC3D,SAASL,EAA0B;AAAA,EAAA,CACpC;AAAA,EACH,gBAAgBE,EAAE,QAAA;AACpB,GA4BMK,IAAuB;AAAA,EAC3B,WAAW;AAAA,EACX,UAAU;AAAA,EACV,eAAe;AAAA,EACf,OAAO;AAAA,EACP,aAAa;AAAA,EACb,KAAK;AACP;AAsBO,SAASC,EAA4BC,IAAwC,IAAI;AACtF,QAAM,EAAE,MAAAC,IAAO,UAAU,yBAAAC,GAAyB,QAAAC,IAAS,OAAUH;AAErE,SAAOI,EAAgBZ,GAAiB;AAAA,IACtC,sBAAAM;AAAA,IACA,mBAAmBP,EAA0B;AAAA,IAC7C,MAAAU;AAAA,IACA,yBAAAC;AAAA,IACA,0BAA0BC,IAAS,CAAC,KAAK,IAAI,CAAA;AAAA,IAC7C,aACEF,MAAS,WACL,CAACI,GAAMC,MAAQ;AACb,MAAID,EAAK,mBAAmB,CAACA,EAAK,SAASA,EAAK,MAAM,WAAW,OAC/DC,EAAI,SAAS;AAAA,QACX,MAAMb,EAAE,aAAa;AAAA,QACrB,MAAM,CAAC,OAAO;AAAA,QACd,SAASF,EAA0B;AAAA,MAAA,CACpC;AAAA,IAEL,IACA;AAAA,EAAA,CACP;AACH;"}
|
package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type { EmployeeDetailsOptionalFieldsToRequire } from './employeeDetailsSc
|
|
|
14
14
|
* switch changes the employee's onboarding status as part of an update.
|
|
15
15
|
*
|
|
16
16
|
* @public
|
|
17
|
+
* @group Utility Types
|
|
17
18
|
*/
|
|
18
19
|
export interface EmployeeDetailsSubmitCallbacks {
|
|
19
20
|
/** Fired after a new employee is successfully created. */
|
|
@@ -49,6 +50,7 @@ export type UseEmployeeDetailsFormSharedProps = {
|
|
|
49
50
|
* `companyId`).
|
|
50
51
|
*
|
|
51
52
|
* @public
|
|
53
|
+
* @group Utility Types
|
|
52
54
|
*/
|
|
53
55
|
export type UseEmployeeDetailsFormProps = (UseEmployeeDetailsFormSharedProps & {
|
|
54
56
|
companyId: string;
|
|
@@ -61,28 +63,25 @@ export type UseEmployeeDetailsFormProps = (UseEmployeeDetailsFormSharedProps & {
|
|
|
61
63
|
* The Field components exposed by {@link useEmployeeDetailsForm} as `form.Fields`.
|
|
62
64
|
*
|
|
63
65
|
* @remarks
|
|
64
|
-
* Each entry is a component bound to a specific form field
|
|
65
|
-
*
|
|
66
|
-
* {@link EmailField}, {@link DateOfBirthField}, {@link SsnField}, and
|
|
67
|
-
* {@link SelfOnboardingField}. `SelfOnboarding` may be `undefined` when
|
|
68
|
-
* the field is not toggleable.
|
|
66
|
+
* Each entry is a component bound to a specific form field. `SelfOnboarding`
|
|
67
|
+
* may be `undefined` when the field is not toggleable.
|
|
69
68
|
*
|
|
70
69
|
* @public
|
|
71
70
|
*/
|
|
72
71
|
export interface EmployeeDetailsFields {
|
|
73
|
-
/** Text input bound to `firstName`.
|
|
72
|
+
/** Text input bound to `firstName`. */
|
|
74
73
|
FirstName: typeof FirstNameField;
|
|
75
|
-
/** Text input bound to `middleInitial`.
|
|
74
|
+
/** Text input bound to `middleInitial`. */
|
|
76
75
|
MiddleInitial: typeof MiddleInitialField;
|
|
77
|
-
/** Text input bound to `lastName`.
|
|
76
|
+
/** Text input bound to `lastName`. */
|
|
78
77
|
LastName: typeof LastNameField;
|
|
79
|
-
/** Text input bound to `email`.
|
|
78
|
+
/** Text input bound to `email`. */
|
|
80
79
|
Email: typeof EmailField;
|
|
81
|
-
/** Date picker bound to `dateOfBirth`.
|
|
80
|
+
/** Date picker bound to `dateOfBirth`. */
|
|
82
81
|
DateOfBirth: typeof DateOfBirthField;
|
|
83
|
-
/** Text input bound to `ssn`.
|
|
82
|
+
/** Text input bound to `ssn`. */
|
|
84
83
|
Ssn: typeof SsnField;
|
|
85
|
-
/** Switch bound to `selfOnboarding`, or `undefined` when the field is not toggleable.
|
|
84
|
+
/** Switch bound to `selfOnboarding`, or `undefined` when the field is not toggleable. */
|
|
86
85
|
SelfOnboarding: typeof SelfOnboardingField | undefined;
|
|
87
86
|
}
|
|
88
87
|
/**
|
package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEmployeeDetailsForm.js","sources":["../../../../../../src/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useForm } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport type { Employee } from '@gusto/embedded-api-v-2025-11-15/models/components/employee'\nimport { useEmployeesGet } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesGet'\nimport { useEmployeesCreateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesCreate'\nimport { useEmployeesUpdateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesUpdate'\nimport { useEmployeesUpdateOnboardingStatusMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesUpdateOnboardingStatus'\nimport { RFCDate } from '@gusto/embedded-api-v-2025-11-15/types/rfcdate'\nimport {\n createEmployeeDetailsSchema,\n type EmployeeDetailsOptionalFieldsToRequire,\n type EmployeeDetailsFormData,\n type EmployeeDetailsFormOutputs,\n} from './employeeDetailsSchema'\nimport {\n FirstNameField,\n MiddleInitialField,\n LastNameField,\n EmailField,\n DateOfBirthField,\n SsnField,\n SelfOnboardingField,\n} from './fields'\nimport { normalizeToISOString } from '@/helpers/dateFormatting'\nimport { useDeriveFieldsMetadata } from '@/partner-hook-utils/form/useDeriveFieldsMetadata'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldsMetadata,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { EmployeeOnboardingStatus } from '@/shared/constants'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\nimport { removeNonDigits } from '@/helpers/formattedStrings'\n\nexport type { EmployeeDetailsOptionalFieldsToRequire } from './employeeDetailsSchema'\n\n/**\n * Optional callbacks passed to {@link UseEmployeeDetailsFormReady.actions.onSubmit | onSubmit}.\n *\n * @remarks\n * Only the callback matching the submit mode fires —\n * `onEmployeeCreated` on create, `onEmployeeUpdated` on update.\n * `onOnboardingStatusUpdated` fires when toggling the self-onboarding\n * switch changes the employee's onboarding status as part of an update.\n *\n * @public\n */\nexport interface EmployeeDetailsSubmitCallbacks {\n /** Fired after a new employee is successfully created. */\n onEmployeeCreated?: (employee: Employee) => void\n /** Fired after an existing employee is successfully updated. */\n onEmployeeUpdated?: (employee: Employee) => void\n /** Fired when an update toggles self-onboarding and the employee's onboarding status changes. */\n onOnboardingStatusUpdated?: (status: unknown) => void\n}\n\n/**\n * Shared options merged into both branches of {@link UseEmployeeDetailsFormProps}.\n *\n * @public\n */\nexport type UseEmployeeDetailsFormSharedProps = {\n /** Whether to expose the self-onboarding toggle as `form.Fields.SelfOnboarding`. Defaults to `true`. */\n withSelfOnboardingField?: boolean\n /** Fields that are optional by default but should be promoted to required for this form instance. */\n optionalFieldsToRequire?: EmployeeDetailsOptionalFieldsToRequire\n /** Initial values applied before any employee data loads. */\n defaultValues?: Partial<EmployeeDetailsFormData>\n /** When validation runs. Forwarded to react-hook-form's `mode`. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Whether react-hook-form should focus the first error on validation failure. Defaults to `true`. */\n shouldFocusError?: boolean\n}\n\n/**\n * Options for {@link useEmployeeDetailsForm}.\n *\n * @remarks\n * Discriminated by mode: in create mode supply `companyId` and omit\n * `employeeId`; in update mode supply `employeeId` (and optionally\n * `companyId`).\n *\n * @public\n */\nexport type UseEmployeeDetailsFormProps =\n | (UseEmployeeDetailsFormSharedProps & { companyId: string; employeeId?: never })\n | (UseEmployeeDetailsFormSharedProps & { employeeId: string; companyId?: string })\n\n/**\n * The Field components exposed by {@link useEmployeeDetailsForm} as `form.Fields`.\n *\n * @remarks\n * Each entry is a component bound to a specific form field — see\n * {@link FirstNameField}, {@link MiddleInitialField}, {@link LastNameField},\n * {@link EmailField}, {@link DateOfBirthField}, {@link SsnField}, and\n * {@link SelfOnboardingField}. `SelfOnboarding` may be `undefined` when\n * the field is not toggleable.\n *\n * @public\n */\nexport interface EmployeeDetailsFields {\n /** Text input bound to `firstName`. See {@link FirstNameField}. */\n FirstName: typeof FirstNameField\n /** Text input bound to `middleInitial`. See {@link MiddleInitialField}. */\n MiddleInitial: typeof MiddleInitialField\n /** Text input bound to `lastName`. See {@link LastNameField}. */\n LastName: typeof LastNameField\n /** Text input bound to `email`. See {@link EmailField}. */\n Email: typeof EmailField\n /** Date picker bound to `dateOfBirth`. See {@link DateOfBirthField}. */\n DateOfBirth: typeof DateOfBirthField\n /** Text input bound to `ssn`. See {@link SsnField}. */\n Ssn: typeof SsnField\n /** Switch bound to `selfOnboarding`, or `undefined` when the field is not toggleable. See {@link SelfOnboardingField}. */\n SelfOnboarding: typeof SelfOnboardingField | undefined\n}\n\n/**\n * The ready-state result returned by {@link useEmployeeDetailsForm} once data has loaded.\n *\n * @remarks\n * Provides the form's `data` snapshot, pending `status`, submit `actions`,\n * error handling, and the `form.Fields` map.\n *\n * @public\n */\nexport interface UseEmployeeDetailsFormReady extends BaseFormHookReady<\n FieldsMetadata,\n EmployeeDetailsFormData,\n EmployeeDetailsFields\n> {\n /** The loaded employee data, or `null` in create mode. */\n data: {\n /** The employee being edited, or `null` in create mode. */\n employee: Employee | null\n }\n /** Submit status and form mode. */\n status: {\n /** `true` while the create, update, or onboarding-status mutation is in flight. */\n isPending: boolean\n /** `'create'` when no `employeeId` was supplied, `'update'` otherwise. */\n mode: 'create' | 'update'\n }\n /** Submit and related actions. */\n actions: {\n /** Validates the form and submits the changes. Returns the created or updated employee, or `undefined` when validation fails. */\n onSubmit: (\n callbacks?: EmployeeDetailsSubmitCallbacks,\n ) => Promise<HookSubmitResult<Employee> | undefined>\n }\n}\n\nconst isCurrentlySelfOnboarding = (employee?: Employee) => {\n if (!employee?.onboardingStatus) return false\n const selfOnboardingStatuses: string[] = [\n EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE,\n EmployeeOnboardingStatus.SELF_ONBOARDING_INVITED,\n EmployeeOnboardingStatus.SELF_ONBOARDING_INVITED_STARTED,\n EmployeeOnboardingStatus.SELF_ONBOARDING_INVITED_OVERDUE,\n EmployeeOnboardingStatus.SELF_ONBOARDING_COMPLETED_BY_EMPLOYEE,\n EmployeeOnboardingStatus.SELF_ONBOARDING_AWAITING_ADMIN_REVIEW,\n ]\n return selfOnboardingStatuses.includes(employee.onboardingStatus)\n}\n\nconst canToggleSelfOnboarding = (employee?: Employee) => {\n if (!employee) return true\n return (\n employee.onboardingStatus === EmployeeOnboardingStatus.ADMIN_ONBOARDING_INCOMPLETE ||\n employee.onboardingStatus === EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE\n )\n}\n\n/**\n * Headless hook for creating or updating an employee's profile details — name, email, SSN, date of birth, and self-onboarding preference.\n *\n * @remarks\n * Returns a discriminated union: a loading variant while the underlying\n * employee fetch resolves, and a ready variant exposing the form's data,\n * pending status, submit action, error handling, and bound `Fields`.\n * Self-onboarding is only toggleable when the employee's onboarding status\n * allows it; otherwise `form.Fields.SelfOnboarding` is `undefined`.\n *\n * @param input - See {@link UseEmployeeDetailsFormProps}.\n * @returns A {@link HookLoadingResult} while loading, or a {@link UseEmployeeDetailsFormReady} once ready.\n * @public\n *\n * @example\n * ```tsx\n * import {\n * useEmployeeDetailsForm,\n * SDKFormProvider,\n * type UseEmployeeDetailsFormReady,\n * } from '@gusto/embedded-react-sdk'\n *\n * function EmployeeDetailsPage({ companyId, employeeId }: { companyId: string; employeeId?: string }) {\n * const employeeDetails = useEmployeeDetailsForm({ companyId, employeeId })\n *\n * if (employeeDetails.isLoading) return <div>Loading...</div>\n *\n * return <EmployeeDetailsReady employeeDetails={employeeDetails} />\n * }\n *\n * function EmployeeDetailsReady({ employeeDetails }: { employeeDetails: UseEmployeeDetailsFormReady }) {\n * const { Fields } = employeeDetails.form\n *\n * const handleSubmit = async () => {\n * await employeeDetails.actions.onSubmit({\n * onEmployeeCreated: emp => console.log('Created:', emp.uuid),\n * onEmployeeUpdated: emp => console.log('Updated:', emp.uuid),\n * })\n * }\n *\n * return (\n * <SDKFormProvider formHookResult={employeeDetails}>\n * <form onSubmit={e => { e.preventDefault(); void handleSubmit() }}>\n * <Fields.FirstName label=\"First name\" />\n * <Fields.LastName label=\"Last name\" />\n * <Fields.Email label=\"Personal email\" />\n * <Fields.DateOfBirth label=\"Date of birth\" />\n * <Fields.Ssn label=\"Social Security number\" />\n * <button type=\"submit\" disabled={employeeDetails.status.isPending}>Save</button>\n * </form>\n * </SDKFormProvider>\n * )\n * }\n * ```\n */\nexport function useEmployeeDetailsForm({\n companyId,\n employeeId,\n withSelfOnboardingField = true,\n optionalFieldsToRequire,\n defaultValues: partnerDefaults,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n}: UseEmployeeDetailsFormProps): HookLoadingResult | UseEmployeeDetailsFormReady {\n const employeeQuery = useEmployeesGet({ employeeId: employeeId ?? '' }, { enabled: !!employeeId })\n\n const employee = employeeQuery.data?.employee\n\n const isCreateMode = !employeeId\n const isSelfOnboardingToggleable = canToggleSelfOnboarding(employee)\n\n const mode = isCreateMode ? 'create' : 'update'\n\n const [schema, metadataConfig] = useMemo(\n () => createEmployeeDetailsSchema({ mode, optionalFieldsToRequire, hasSsn: employee?.hasSsn }),\n [mode, optionalFieldsToRequire, employee?.hasSsn],\n )\n\n const resolvedDefaults: EmployeeDetailsFormData = {\n firstName: employee?.firstName ?? partnerDefaults?.firstName ?? '',\n middleInitial: employee?.middleInitial ?? partnerDefaults?.middleInitial ?? '',\n lastName: employee?.lastName ?? partnerDefaults?.lastName ?? '',\n email: employee?.email ?? partnerDefaults?.email ?? '',\n dateOfBirth: employee?.dateOfBirth ?? normalizeToISOString(partnerDefaults?.dateOfBirth),\n ssn: partnerDefaults?.ssn ?? '',\n selfOnboarding: partnerDefaults?.selfOnboarding ?? isCurrentlySelfOnboarding(employee),\n }\n\n const formMethods = useForm<EmployeeDetailsFormData, unknown, EmployeeDetailsFormOutputs>({\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n })\n\n const createEmployeeMutation = useEmployeesCreateMutation()\n const updateEmployeeMutation = useEmployeesUpdateMutation()\n const updateOnboardingStatusMutation = useEmployeesUpdateOnboardingStatusMutation()\n\n const isPending =\n createEmployeeMutation.isPending ||\n updateEmployeeMutation.isPending ||\n updateOnboardingStatusMutation.isPending\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('EmployeeDetailsForm')\n\n const queries = employeeId ? [employeeQuery] : []\n const errorHandling = composeErrorHandler(queries, { submitError, setSubmitError })\n\n const fieldsMetadata = useDeriveFieldsMetadata(metadataConfig, formMethods.control)\n\n const onSubmit = async (\n callbacks?: EmployeeDetailsSubmitCallbacks,\n ): Promise<HookSubmitResult<Employee> | undefined> => {\n let submitResult: HookSubmitResult<Employee> | undefined\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async (data: EmployeeDetailsFormOutputs) => {\n await baseSubmitHandler(data, async payload => {\n const { selfOnboarding, dateOfBirth, ssn, ...body } = payload\n\n const cleanedSsn = ssn ? removeNonDigits(ssn) : undefined\n const hasSsnInput = cleanedSsn && cleanedSsn.length > 0\n\n let updatedEmployee: Employee\n\n if (isCreateMode) {\n if (!companyId) {\n throw new SDKInternalError('companyId is required to create an employee')\n }\n const result = await createEmployeeMutation.mutateAsync({\n request: {\n companyId,\n requestBody: {\n ...body,\n selfOnboarding,\n dateOfBirth: dateOfBirth ? new RFCDate(new Date(dateOfBirth)) : undefined,\n ssn: hasSsnInput ? cleanedSsn : undefined,\n },\n },\n })\n\n if (!result.employee) {\n throw new SDKInternalError('Employee creation failed')\n }\n\n updatedEmployee = result.employee\n callbacks?.onEmployeeCreated?.(updatedEmployee)\n } else {\n if (!employee) {\n throw new SDKInternalError('Employee data is not available')\n }\n\n if (isSelfOnboardingToggleable) {\n const currentIsSelfOnboarding =\n employee.onboardingStatus ===\n EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE\n\n if (selfOnboarding !== currentIsSelfOnboarding) {\n const { employeeOnboardingStatus } =\n await updateOnboardingStatusMutation.mutateAsync({\n request: {\n employeeId: employee.uuid,\n requestBody: {\n onboardingStatus: selfOnboarding\n ? EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE\n : EmployeeOnboardingStatus.ADMIN_ONBOARDING_INCOMPLETE,\n },\n },\n })\n\n callbacks?.onOnboardingStatusUpdated?.(employeeOnboardingStatus)\n }\n }\n\n const result = await updateEmployeeMutation.mutateAsync({\n request: {\n employeeId: employee.uuid,\n requestBody: {\n version: employee.version as string,\n ...body,\n dateOfBirth: dateOfBirth || undefined,\n ssn: hasSsnInput ? cleanedSsn : undefined,\n },\n },\n })\n\n if (!result.employee) {\n throw new SDKInternalError('Employee update failed')\n }\n\n updatedEmployee = result.employee\n callbacks?.onEmployeeUpdated?.(updatedEmployee)\n }\n\n submitResult = {\n mode: isCreateMode ? 'create' : 'update',\n data: updatedEmployee,\n }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n const isDataLoading = employeeId ? employeeQuery.isLoading : false\n\n if (isDataLoading || (employeeId && !employee)) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n employee: employee ?? null,\n },\n status: {\n isPending,\n mode: isCreateMode ? ('create' as const) : ('update' as const),\n },\n actions: { onSubmit },\n errorHandling,\n form: {\n Fields: {\n FirstName: FirstNameField,\n MiddleInitial: MiddleInitialField,\n LastName: LastNameField,\n Email: EmailField,\n DateOfBirth: DateOfBirthField,\n Ssn: SsnField,\n SelfOnboarding:\n withSelfOnboardingField && isSelfOnboardingToggleable ? SelfOnboardingField : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n },\n }\n}\n\n/**\n * Return type of {@link useEmployeeDetailsForm}.\n *\n * @public\n */\nexport type UseEmployeeDetailsFormResult = HookLoadingResult | UseEmployeeDetailsFormReady\n\n/**\n * Shape of `form.fieldsMetadata` returned by {@link useEmployeeDetailsForm}.\n *\n * @public\n */\nexport type EmployeeDetailsFieldsMetadata = UseEmployeeDetailsFormReady['form']['fieldsMetadata']\n\n/**\n * Shape of `form.Fields` returned by {@link useEmployeeDetailsForm}.\n *\n * @public\n */\nexport type EmployeeDetailsFormFields = UseEmployeeDetailsFormReady['form']['Fields']\n"],"names":["isCurrentlySelfOnboarding","employee","EmployeeOnboardingStatus","canToggleSelfOnboarding","useEmployeeDetailsForm","companyId","employeeId","withSelfOnboardingField","optionalFieldsToRequire","partnerDefaults","validationMode","shouldFocusError","employeeQuery","useEmployeesGet","isCreateMode","isSelfOnboardingToggleable","mode","schema","metadataConfig","useMemo","createEmployeeDetailsSchema","resolvedDefaults","normalizeToISOString","formMethods","useForm","zodResolver","createEmployeeMutation","useEmployeesCreateMutation","updateEmployeeMutation","useEmployeesUpdateMutation","updateOnboardingStatusMutation","useEmployeesUpdateOnboardingStatusMutation","isPending","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","errorHandling","composeErrorHandler","fieldsMetadata","useDeriveFieldsMetadata","onSubmit","callbacks","submitResult","resolve","data","payload","selfOnboarding","dateOfBirth","ssn","body","cleanedSsn","removeNonDigits","hasSsnInput","updatedEmployee","SDKInternalError","result","RFCDate","currentIsSelfOnboarding","employeeOnboardingStatus","hookFormInternals","useHookFormInternals","FirstNameField","MiddleInitialField","LastNameField","EmailField","DateOfBirthField","SsnField","SelfOnboardingField","createGetFormSubmissionValues"],"mappings":";;;;;;;;;;;;;;;;;;;AA+JA,MAAMA,KAA4B,CAACC,MAC5BA,GAAU,mBAC0B;AAAA,EACvCC,EAAyB;AAAA,EACzBA,EAAyB;AAAA,EACzBA,EAAyB;AAAA,EACzBA,EAAyB;AAAA,EACzBA,EAAyB;AAAA,EACzBA,EAAyB;AAAA,EAEG,SAASD,EAAS,gBAAgB,IATxB,IAYpCE,KAA0B,CAACF,MAC1BA,IAEHA,EAAS,qBAAqBC,EAAyB,+BACvDD,EAAS,qBAAqBC,EAAyB,iCAHnC;AA8DjB,SAASE,GAAuB;AAAA,EACrC,WAAAC;AAAA,EACA,YAAAC;AAAA,EACA,yBAAAC,IAA0B;AAAA,EAC1B,yBAAAC;AAAA,EACA,eAAeC;AAAA,EACf,gBAAAC,IAAiB;AAAA,EACjB,kBAAAC,IAAmB;AACrB,GAAiF;AAC/E,QAAMC,IAAgBC,EAAgB,EAAE,YAAYP,KAAc,GAAA,GAAM,EAAE,SAAS,CAAC,CAACA,GAAY,GAE3FL,IAAWW,EAAc,MAAM,UAE/BE,IAAe,CAACR,GAChBS,IAA6BZ,GAAwBF,CAAQ,GAE7De,IAAOF,IAAe,WAAW,UAEjC,CAACG,GAAQC,CAAc,IAAIC;AAAA,IAC/B,MAAMC,EAA4B,EAAE,MAAAJ,GAAM,yBAAAR,GAAyB,QAAQP,GAAU,QAAQ;AAAA,IAC7F,CAACe,GAAMR,GAAyBP,GAAU,MAAM;AAAA,EAAA,GAG5CoB,IAA4C;AAAA,IAChD,WAAWpB,GAAU,aAAaQ,GAAiB,aAAa;AAAA,IAChE,eAAeR,GAAU,iBAAiBQ,GAAiB,iBAAiB;AAAA,IAC5E,UAAUR,GAAU,YAAYQ,GAAiB,YAAY;AAAA,IAC7D,OAAOR,GAAU,SAASQ,GAAiB,SAAS;AAAA,IACpD,aAAaR,GAAU,eAAeqB,GAAqBb,GAAiB,WAAW;AAAA,IACvF,KAAKA,GAAiB,OAAO;AAAA,IAC7B,gBAAgBA,GAAiB,kBAAkBT,GAA0BC,CAAQ;AAAA,EAAA,GAGjFsB,IAAcC,EAAsE;AAAA,IACxF,UAAUC,EAAYR,CAAM;AAAA,IAC5B,MAAMP;AAAA,IACN,kBAAAC;AAAA,IACA,eAAeU;AAAA,IACf,QAAQA;AAAA,IACR,cAAc,EAAE,iBAAiB,GAAA;AAAA,EAAK,CACvC,GAEKK,IAAyBC,EAAA,GACzBC,IAAyBC,EAAA,GACzBC,IAAiCC,EAAA,GAEjCC,IACJN,EAAuB,aACvBE,EAAuB,aACvBE,EAA+B,WAE3B;AAAA,IACJ,mBAAAG;AAAA,IACA,OAAOC;AAAA,IACP,UAAUC;AAAA,EAAA,IACRC,GAAc,qBAAqB,GAGjCC,IAAgBC,GADNhC,IAAa,CAACM,CAAa,IAAI,CAAA,GACI,EAAE,aAAAsB,GAAa,gBAAAC,GAAgB,GAE5EI,IAAiBC,GAAwBtB,GAAgBK,EAAY,OAAO,GAE5EkB,IAAW,OACfC,MACoD;AACpD,QAAIC;AAEJ,iBAAM,IAAI,QAAc,CAAAC,MAAW;AACjC,MAAKrB,EAAY;AAAA,QACf,OAAOsB,MAAqC;AAC1C,gBAAMZ,EAAkBY,GAAM,OAAMC,MAAW;AAC7C,kBAAM,EAAE,gBAAAC,GAAgB,aAAAC,GAAa,KAAAC,GAAK,GAAGC,MAASJ,GAEhDK,IAAaF,IAAMG,GAAgBH,CAAG,IAAI,QAC1CI,IAAcF,KAAcA,EAAW,SAAS;AAEtD,gBAAIG;AAEJ,gBAAIxC,GAAc;AAChB,kBAAI,CAACT;AACH,sBAAM,IAAIkD,EAAiB,6CAA6C;AAE1E,oBAAMC,IAAS,MAAM9B,EAAuB,YAAY;AAAA,gBACtD,SAAS;AAAA,kBACP,WAAArB;AAAA,kBACA,aAAa;AAAA,oBACX,GAAG6C;AAAA,oBACH,gBAAAH;AAAA,oBACA,aAAaC,IAAc,IAAIS,EAAQ,IAAI,KAAKT,CAAW,CAAC,IAAI;AAAA,oBAChE,KAAKK,IAAcF,IAAa;AAAA,kBAAA;AAAA,gBAClC;AAAA,cACF,CACD;AAED,kBAAI,CAACK,EAAO;AACV,sBAAM,IAAID,EAAiB,0BAA0B;AAGvD,cAAAD,IAAkBE,EAAO,UACzBd,GAAW,oBAAoBY,CAAe;AAAA,YAChD,OAAO;AACL,kBAAI,CAACrD;AACH,sBAAM,IAAIsD,EAAiB,gCAAgC;AAG7D,kBAAIxC,GAA4B;AAC9B,sBAAM2C,IACJzD,EAAS,qBACTC,EAAyB;AAE3B,oBAAI6C,MAAmBW,GAAyB;AAC9C,wBAAM,EAAE,0BAAAC,EAAA,IACN,MAAM7B,EAA+B,YAAY;AAAA,oBAC/C,SAAS;AAAA,sBACP,YAAY7B,EAAS;AAAA,sBACrB,aAAa;AAAA,wBACX,kBAAkB8C,IACd7C,EAAyB,iCACzBA,EAAyB;AAAA,sBAAA;AAAA,oBAC/B;AAAA,kBACF,CACD;AAEH,kBAAAwC,GAAW,4BAA4BiB,CAAwB;AAAA,gBACjE;AAAA,cACF;AAEA,oBAAMH,IAAS,MAAM5B,EAAuB,YAAY;AAAA,gBACtD,SAAS;AAAA,kBACP,YAAY3B,EAAS;AAAA,kBACrB,aAAa;AAAA,oBACX,SAASA,EAAS;AAAA,oBAClB,GAAGiD;AAAA,oBACH,aAAaF,KAAe;AAAA,oBAC5B,KAAKK,IAAcF,IAAa;AAAA,kBAAA;AAAA,gBAClC;AAAA,cACF,CACD;AAED,kBAAI,CAACK,EAAO;AACV,sBAAM,IAAID,EAAiB,wBAAwB;AAGrD,cAAAD,IAAkBE,EAAO,UACzBd,GAAW,oBAAoBY,CAAe;AAAA,YAChD;AAEA,YAAAX,IAAe;AAAA,cACb,MAAM7B,IAAe,WAAW;AAAA,cAChC,MAAMwC;AAAA,YAAA;AAAA,UAEV,CAAC,GACDV,EAAA;AAAA,QACF;AAAA,QACA,MAAM;AACJ,UAAAA,EAAA;AAAA,QACF;AAAA,MAAA,EACF;AAAA,IACF,CAAC,GAEMD;AAAA,EACT,GAEMiB,IAAoBC,GAAqBtC,CAAW;AAI1D,UAFsBjB,IAAaM,EAAc,YAAY,OAEvCN,KAAc,CAACL,IAC5B,EAAE,WAAW,IAAe,eAAAoC,EAAA,IAG9B;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,MACJ,UAAUpC,KAAY;AAAA,IAAA;AAAA,IAExB,QAAQ;AAAA,MACN,WAAA+B;AAAA,MACA,MAAMlB,IAAgB,WAAsB;AAAA,IAAA;AAAA,IAE9C,SAAS,EAAE,UAAA2B,EAAA;AAAA,IACX,eAAAJ;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ;AAAA,QACN,WAAWyB;AAAA,QACX,eAAeC;AAAA,QACf,UAAUC;AAAA,QACV,OAAOC;AAAA,QACP,aAAaC;AAAA,QACb,KAAKC;AAAA,QACL,gBACE5D,KAA2BQ,IAA6BqD,IAAsB;AAAA,MAAA;AAAA,MAElF,gBAAA7B;AAAA,MACA,mBAAAqB;AAAA,MACA,yBAAyBS,GAA8B9C,GAAaN,CAAM;AAAA,IAAA;AAAA,EAC5E;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"useEmployeeDetailsForm.js","sources":["../../../../../../src/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useForm } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport type { Employee } from '@gusto/embedded-api-v-2025-11-15/models/components/employee'\nimport { useEmployeesGet } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesGet'\nimport { useEmployeesCreateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesCreate'\nimport { useEmployeesUpdateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesUpdate'\nimport { useEmployeesUpdateOnboardingStatusMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeesUpdateOnboardingStatus'\nimport { RFCDate } from '@gusto/embedded-api-v-2025-11-15/types/rfcdate'\nimport {\n createEmployeeDetailsSchema,\n type EmployeeDetailsOptionalFieldsToRequire,\n type EmployeeDetailsFormData,\n type EmployeeDetailsFormOutputs,\n} from './employeeDetailsSchema'\nimport {\n FirstNameField,\n MiddleInitialField,\n LastNameField,\n EmailField,\n DateOfBirthField,\n SsnField,\n SelfOnboardingField,\n} from './fields'\nimport { normalizeToISOString } from '@/helpers/dateFormatting'\nimport { useDeriveFieldsMetadata } from '@/partner-hook-utils/form/useDeriveFieldsMetadata'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldsMetadata,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { EmployeeOnboardingStatus } from '@/shared/constants'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\nimport { removeNonDigits } from '@/helpers/formattedStrings'\n\nexport type { EmployeeDetailsOptionalFieldsToRequire } from './employeeDetailsSchema'\n\n/**\n * Optional callbacks passed to {@link UseEmployeeDetailsFormReady.actions.onSubmit | onSubmit}.\n *\n * @remarks\n * Only the callback matching the submit mode fires —\n * `onEmployeeCreated` on create, `onEmployeeUpdated` on update.\n * `onOnboardingStatusUpdated` fires when toggling the self-onboarding\n * switch changes the employee's onboarding status as part of an update.\n *\n * @public\n * @group Utility Types\n */\nexport interface EmployeeDetailsSubmitCallbacks {\n /** Fired after a new employee is successfully created. */\n onEmployeeCreated?: (employee: Employee) => void\n /** Fired after an existing employee is successfully updated. */\n onEmployeeUpdated?: (employee: Employee) => void\n /** Fired when an update toggles self-onboarding and the employee's onboarding status changes. */\n onOnboardingStatusUpdated?: (status: unknown) => void\n}\n\n/**\n * Shared options merged into both branches of {@link UseEmployeeDetailsFormProps}.\n *\n * @public\n */\nexport type UseEmployeeDetailsFormSharedProps = {\n /** Whether to expose the self-onboarding toggle as `form.Fields.SelfOnboarding`. Defaults to `true`. */\n withSelfOnboardingField?: boolean\n /** Fields that are optional by default but should be promoted to required for this form instance. */\n optionalFieldsToRequire?: EmployeeDetailsOptionalFieldsToRequire\n /** Initial values applied before any employee data loads. */\n defaultValues?: Partial<EmployeeDetailsFormData>\n /** When validation runs. Forwarded to react-hook-form's `mode`. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Whether react-hook-form should focus the first error on validation failure. Defaults to `true`. */\n shouldFocusError?: boolean\n}\n\n/**\n * Options for {@link useEmployeeDetailsForm}.\n *\n * @remarks\n * Discriminated by mode: in create mode supply `companyId` and omit\n * `employeeId`; in update mode supply `employeeId` (and optionally\n * `companyId`).\n *\n * @public\n * @group Utility Types\n */\nexport type UseEmployeeDetailsFormProps =\n | (UseEmployeeDetailsFormSharedProps & { companyId: string; employeeId?: never })\n | (UseEmployeeDetailsFormSharedProps & { employeeId: string; companyId?: string })\n\n/**\n * The Field components exposed by {@link useEmployeeDetailsForm} as `form.Fields`.\n *\n * @remarks\n * Each entry is a component bound to a specific form field. `SelfOnboarding`\n * may be `undefined` when the field is not toggleable.\n *\n * @public\n */\nexport interface EmployeeDetailsFields {\n /** Text input bound to `firstName`. */\n FirstName: typeof FirstNameField\n /** Text input bound to `middleInitial`. */\n MiddleInitial: typeof MiddleInitialField\n /** Text input bound to `lastName`. */\n LastName: typeof LastNameField\n /** Text input bound to `email`. */\n Email: typeof EmailField\n /** Date picker bound to `dateOfBirth`. */\n DateOfBirth: typeof DateOfBirthField\n /** Text input bound to `ssn`. */\n Ssn: typeof SsnField\n /** Switch bound to `selfOnboarding`, or `undefined` when the field is not toggleable. */\n SelfOnboarding: typeof SelfOnboardingField | undefined\n}\n\n/**\n * The ready-state result returned by {@link useEmployeeDetailsForm} once data has loaded.\n *\n * @remarks\n * Provides the form's `data` snapshot, pending `status`, submit `actions`,\n * error handling, and the `form.Fields` map.\n *\n * @public\n */\nexport interface UseEmployeeDetailsFormReady extends BaseFormHookReady<\n FieldsMetadata,\n EmployeeDetailsFormData,\n EmployeeDetailsFields\n> {\n /** The loaded employee data, or `null` in create mode. */\n data: {\n /** The employee being edited, or `null` in create mode. */\n employee: Employee | null\n }\n /** Submit status and form mode. */\n status: {\n /** `true` while the create, update, or onboarding-status mutation is in flight. */\n isPending: boolean\n /** `'create'` when no `employeeId` was supplied, `'update'` otherwise. */\n mode: 'create' | 'update'\n }\n /** Submit and related actions. */\n actions: {\n /** Validates the form and submits the changes. Returns the created or updated employee, or `undefined` when validation fails. */\n onSubmit: (\n callbacks?: EmployeeDetailsSubmitCallbacks,\n ) => Promise<HookSubmitResult<Employee> | undefined>\n }\n}\n\nconst isCurrentlySelfOnboarding = (employee?: Employee) => {\n if (!employee?.onboardingStatus) return false\n const selfOnboardingStatuses: string[] = [\n EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE,\n EmployeeOnboardingStatus.SELF_ONBOARDING_INVITED,\n EmployeeOnboardingStatus.SELF_ONBOARDING_INVITED_STARTED,\n EmployeeOnboardingStatus.SELF_ONBOARDING_INVITED_OVERDUE,\n EmployeeOnboardingStatus.SELF_ONBOARDING_COMPLETED_BY_EMPLOYEE,\n EmployeeOnboardingStatus.SELF_ONBOARDING_AWAITING_ADMIN_REVIEW,\n ]\n return selfOnboardingStatuses.includes(employee.onboardingStatus)\n}\n\nconst canToggleSelfOnboarding = (employee?: Employee) => {\n if (!employee) return true\n return (\n employee.onboardingStatus === EmployeeOnboardingStatus.ADMIN_ONBOARDING_INCOMPLETE ||\n employee.onboardingStatus === EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE\n )\n}\n\n/**\n * Headless hook for creating or updating an employee's profile details — name, email, SSN, date of birth, and self-onboarding preference.\n *\n * @remarks\n * Returns a discriminated union: a loading variant while the underlying\n * employee fetch resolves, and a ready variant exposing the form's data,\n * pending status, submit action, error handling, and bound `Fields`.\n * Self-onboarding is only toggleable when the employee's onboarding status\n * allows it; otherwise `form.Fields.SelfOnboarding` is `undefined`.\n *\n * @param input - See {@link UseEmployeeDetailsFormProps}.\n * @returns A {@link HookLoadingResult} while loading, or a {@link UseEmployeeDetailsFormReady} once ready.\n * @public\n *\n * @example\n * ```tsx\n * import {\n * useEmployeeDetailsForm,\n * SDKFormProvider,\n * type UseEmployeeDetailsFormReady,\n * } from '@gusto/embedded-react-sdk'\n *\n * function EmployeeDetailsPage({ companyId, employeeId }: { companyId: string; employeeId?: string }) {\n * const employeeDetails = useEmployeeDetailsForm({ companyId, employeeId })\n *\n * if (employeeDetails.isLoading) return <div>Loading...</div>\n *\n * return <EmployeeDetailsReady employeeDetails={employeeDetails} />\n * }\n *\n * function EmployeeDetailsReady({ employeeDetails }: { employeeDetails: UseEmployeeDetailsFormReady }) {\n * const { Fields } = employeeDetails.form\n *\n * const handleSubmit = async () => {\n * await employeeDetails.actions.onSubmit({\n * onEmployeeCreated: emp => console.log('Created:', emp.uuid),\n * onEmployeeUpdated: emp => console.log('Updated:', emp.uuid),\n * })\n * }\n *\n * return (\n * <SDKFormProvider formHookResult={employeeDetails}>\n * <form onSubmit={e => { e.preventDefault(); void handleSubmit() }}>\n * <Fields.FirstName label=\"First name\" />\n * <Fields.LastName label=\"Last name\" />\n * <Fields.Email label=\"Personal email\" />\n * <Fields.DateOfBirth label=\"Date of birth\" />\n * <Fields.Ssn label=\"Social Security number\" />\n * <button type=\"submit\" disabled={employeeDetails.status.isPending}>Save</button>\n * </form>\n * </SDKFormProvider>\n * )\n * }\n * ```\n */\nexport function useEmployeeDetailsForm({\n companyId,\n employeeId,\n withSelfOnboardingField = true,\n optionalFieldsToRequire,\n defaultValues: partnerDefaults,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n}: UseEmployeeDetailsFormProps): HookLoadingResult | UseEmployeeDetailsFormReady {\n const employeeQuery = useEmployeesGet({ employeeId: employeeId ?? '' }, { enabled: !!employeeId })\n\n const employee = employeeQuery.data?.employee\n\n const isCreateMode = !employeeId\n const isSelfOnboardingToggleable = canToggleSelfOnboarding(employee)\n\n const mode = isCreateMode ? 'create' : 'update'\n\n const [schema, metadataConfig] = useMemo(\n () => createEmployeeDetailsSchema({ mode, optionalFieldsToRequire, hasSsn: employee?.hasSsn }),\n [mode, optionalFieldsToRequire, employee?.hasSsn],\n )\n\n const resolvedDefaults: EmployeeDetailsFormData = {\n firstName: employee?.firstName ?? partnerDefaults?.firstName ?? '',\n middleInitial: employee?.middleInitial ?? partnerDefaults?.middleInitial ?? '',\n lastName: employee?.lastName ?? partnerDefaults?.lastName ?? '',\n email: employee?.email ?? partnerDefaults?.email ?? '',\n dateOfBirth: employee?.dateOfBirth ?? normalizeToISOString(partnerDefaults?.dateOfBirth),\n ssn: partnerDefaults?.ssn ?? '',\n selfOnboarding: partnerDefaults?.selfOnboarding ?? isCurrentlySelfOnboarding(employee),\n }\n\n const formMethods = useForm<EmployeeDetailsFormData, unknown, EmployeeDetailsFormOutputs>({\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n })\n\n const createEmployeeMutation = useEmployeesCreateMutation()\n const updateEmployeeMutation = useEmployeesUpdateMutation()\n const updateOnboardingStatusMutation = useEmployeesUpdateOnboardingStatusMutation()\n\n const isPending =\n createEmployeeMutation.isPending ||\n updateEmployeeMutation.isPending ||\n updateOnboardingStatusMutation.isPending\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('EmployeeDetailsForm')\n\n const queries = employeeId ? [employeeQuery] : []\n const errorHandling = composeErrorHandler(queries, { submitError, setSubmitError })\n\n const fieldsMetadata = useDeriveFieldsMetadata(metadataConfig, formMethods.control)\n\n const onSubmit = async (\n callbacks?: EmployeeDetailsSubmitCallbacks,\n ): Promise<HookSubmitResult<Employee> | undefined> => {\n let submitResult: HookSubmitResult<Employee> | undefined\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async (data: EmployeeDetailsFormOutputs) => {\n await baseSubmitHandler(data, async payload => {\n const { selfOnboarding, dateOfBirth, ssn, ...body } = payload\n\n const cleanedSsn = ssn ? removeNonDigits(ssn) : undefined\n const hasSsnInput = cleanedSsn && cleanedSsn.length > 0\n\n let updatedEmployee: Employee\n\n if (isCreateMode) {\n if (!companyId) {\n throw new SDKInternalError('companyId is required to create an employee')\n }\n const result = await createEmployeeMutation.mutateAsync({\n request: {\n companyId,\n requestBody: {\n ...body,\n selfOnboarding,\n dateOfBirth: dateOfBirth ? new RFCDate(new Date(dateOfBirth)) : undefined,\n ssn: hasSsnInput ? cleanedSsn : undefined,\n },\n },\n })\n\n if (!result.employee) {\n throw new SDKInternalError('Employee creation failed')\n }\n\n updatedEmployee = result.employee\n callbacks?.onEmployeeCreated?.(updatedEmployee)\n } else {\n if (!employee) {\n throw new SDKInternalError('Employee data is not available')\n }\n\n if (isSelfOnboardingToggleable) {\n const currentIsSelfOnboarding =\n employee.onboardingStatus ===\n EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE\n\n if (selfOnboarding !== currentIsSelfOnboarding) {\n const { employeeOnboardingStatus } =\n await updateOnboardingStatusMutation.mutateAsync({\n request: {\n employeeId: employee.uuid,\n requestBody: {\n onboardingStatus: selfOnboarding\n ? EmployeeOnboardingStatus.SELF_ONBOARDING_PENDING_INVITE\n : EmployeeOnboardingStatus.ADMIN_ONBOARDING_INCOMPLETE,\n },\n },\n })\n\n callbacks?.onOnboardingStatusUpdated?.(employeeOnboardingStatus)\n }\n }\n\n const result = await updateEmployeeMutation.mutateAsync({\n request: {\n employeeId: employee.uuid,\n requestBody: {\n version: employee.version as string,\n ...body,\n dateOfBirth: dateOfBirth || undefined,\n ssn: hasSsnInput ? cleanedSsn : undefined,\n },\n },\n })\n\n if (!result.employee) {\n throw new SDKInternalError('Employee update failed')\n }\n\n updatedEmployee = result.employee\n callbacks?.onEmployeeUpdated?.(updatedEmployee)\n }\n\n submitResult = {\n mode: isCreateMode ? 'create' : 'update',\n data: updatedEmployee,\n }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n const isDataLoading = employeeId ? employeeQuery.isLoading : false\n\n if (isDataLoading || (employeeId && !employee)) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n employee: employee ?? null,\n },\n status: {\n isPending,\n mode: isCreateMode ? ('create' as const) : ('update' as const),\n },\n actions: { onSubmit },\n errorHandling,\n form: {\n Fields: {\n FirstName: FirstNameField,\n MiddleInitial: MiddleInitialField,\n LastName: LastNameField,\n Email: EmailField,\n DateOfBirth: DateOfBirthField,\n Ssn: SsnField,\n SelfOnboarding:\n withSelfOnboardingField && isSelfOnboardingToggleable ? SelfOnboardingField : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n },\n }\n}\n\n/**\n * Return type of {@link useEmployeeDetailsForm}.\n *\n * @public\n */\nexport type UseEmployeeDetailsFormResult = HookLoadingResult | UseEmployeeDetailsFormReady\n\n/**\n * Shape of `form.fieldsMetadata` returned by {@link useEmployeeDetailsForm}.\n *\n * @public\n */\nexport type EmployeeDetailsFieldsMetadata = UseEmployeeDetailsFormReady['form']['fieldsMetadata']\n\n/**\n * Shape of `form.Fields` returned by {@link useEmployeeDetailsForm}.\n *\n * @public\n */\nexport type EmployeeDetailsFormFields = UseEmployeeDetailsFormReady['form']['Fields']\n"],"names":["isCurrentlySelfOnboarding","employee","EmployeeOnboardingStatus","canToggleSelfOnboarding","useEmployeeDetailsForm","companyId","employeeId","withSelfOnboardingField","optionalFieldsToRequire","partnerDefaults","validationMode","shouldFocusError","employeeQuery","useEmployeesGet","isCreateMode","isSelfOnboardingToggleable","mode","schema","metadataConfig","useMemo","createEmployeeDetailsSchema","resolvedDefaults","normalizeToISOString","formMethods","useForm","zodResolver","createEmployeeMutation","useEmployeesCreateMutation","updateEmployeeMutation","useEmployeesUpdateMutation","updateOnboardingStatusMutation","useEmployeesUpdateOnboardingStatusMutation","isPending","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","errorHandling","composeErrorHandler","fieldsMetadata","useDeriveFieldsMetadata","onSubmit","callbacks","submitResult","resolve","data","payload","selfOnboarding","dateOfBirth","ssn","body","cleanedSsn","removeNonDigits","hasSsnInput","updatedEmployee","SDKInternalError","result","RFCDate","currentIsSelfOnboarding","employeeOnboardingStatus","hookFormInternals","useHookFormInternals","FirstNameField","MiddleInitialField","LastNameField","EmailField","DateOfBirthField","SsnField","SelfOnboardingField","createGetFormSubmissionValues"],"mappings":"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"}
|
|
@@ -27,6 +27,7 @@ export type HomeAddressField = "street1" | "street2" | "city" | "state" | "zip"
|
|
|
27
27
|
* Shape of the values managed by the home address form.
|
|
28
28
|
*
|
|
29
29
|
* @public
|
|
30
|
+
* @interface
|
|
30
31
|
*/
|
|
31
32
|
export type HomeAddressFormData = { street1: string; street2: string; city: string; state: string; zip: string; courtesyWithholding: boolean; effectiveDate: string; };
|
|
32
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"homeAddressSchema.js","sources":["../../../../../../src/components/Employee/Profile/shared/useHomeAddressForm/homeAddressSchema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n buildFormSchema,\n type RequiredFieldConfig,\n type OptionalFieldsToRequire,\n} from '@/partner-hook-utils/form/buildFormSchema'\n\n// ── Error codes ────────────────────────────────────────────────────────\n\n/**\n * Validation error codes emitted by the home address form schema. Map these\n * codes to localized copy in `validationMessages` when composing the hook.\n *\n * @public\n */\nexport const HomeAddressErrorCodes = {\n REQUIRED: 'REQUIRED',\n INVALID_ZIP: 'INVALID_ZIP',\n} as const\n\n/**\n * Union of validation error code strings emitted by the home address form\n * schema.\n *\n * @public\n */\nexport type HomeAddressErrorCode =\n (typeof HomeAddressErrorCodes)[keyof typeof HomeAddressErrorCodes]\n\n// ── Field validators ───────────────────────────────────────────────────\n\nconst ZIP_REGEX = /(^\\d{5}$)|(^\\d{5}-\\d{4}$)/\n\nconst fieldValidators = {\n street1: z.string(),\n street2: z.string(),\n city: z.string(),\n state: z.string(),\n zip: z.string().regex(ZIP_REGEX, { message: HomeAddressErrorCodes.INVALID_ZIP }),\n courtesyWithholding: z.boolean(),\n effectiveDate: z.iso.date({ error: () => HomeAddressErrorCodes.REQUIRED }),\n}\n\n/**\n * Field names accepted by the home address form.\n *\n * @public\n */\nexport type HomeAddressField = keyof typeof fieldValidators\n\n/**\n * Shape of the values managed by the home address form.\n *\n * @public\n */\nexport type HomeAddressFormData = {\n [K in keyof typeof fieldValidators]: z.infer<(typeof fieldValidators)[K]>\n}\n/**\n * Shape of the validated values produced by the home address form on submit.\n *\n * @public\n */\nexport type HomeAddressFormOutputs = HomeAddressFormData\n\n// ── Required fields config ─────────────────────────────────────────────\n\nconst requiredFieldsConfig = {\n street2: 'never',\n} satisfies RequiredFieldConfig<typeof fieldValidators>\n\n// ── Schema factory ─────────────────────────────────────────────────────\n\n/**\n * Keys of optional home address fields that can be promoted to required via\n * the hook's `optionalFieldsToRequire` option.\n *\n * @public\n */\nexport type HomeAddressOptionalFieldsToRequire = OptionalFieldsToRequire<\n typeof requiredFieldsConfig\n>\n\n/** @internal */\ninterface HomeAddressSchemaOptions {\n mode?: 'create' | 'update'\n optionalFieldsToRequire?: HomeAddressOptionalFieldsToRequire\n withEffectiveDateField?: boolean\n}\n\n/** @internal */\nexport function createHomeAddressSchema(options: HomeAddressSchemaOptions = {}) {\n const { mode = 'create', optionalFieldsToRequire, withEffectiveDateField = true } = options\n\n return buildFormSchema(fieldValidators, {\n requiredFieldsConfig,\n requiredErrorCode: HomeAddressErrorCodes.REQUIRED,\n mode,\n optionalFieldsToRequire,\n excludeFields: withEffectiveDateField ? [] : ['effectiveDate'],\n })\n}\n"],"names":["HomeAddressErrorCodes","ZIP_REGEX","fieldValidators","z","requiredFieldsConfig","createHomeAddressSchema","options","mode","optionalFieldsToRequire","withEffectiveDateField","buildFormSchema"],"mappings":";;AAeO,MAAMA,IAAwB;AAAA,EACnC,UAAU;AAAA,EACV,aAAa;AACf,GAaMC,IAAY,6BAEZC,IAAkB;AAAA,EACtB,SAASC,EAAE,OAAA;AAAA,EACX,SAASA,EAAE,OAAA;AAAA,EACX,MAAMA,EAAE,OAAA;AAAA,EACR,OAAOA,EAAE,OAAA;AAAA,EACT,KAAKA,EAAE,OAAA,EAAS,MAAMF,GAAW,EAAE,SAASD,EAAsB,aAAa;AAAA,EAC/E,qBAAqBG,EAAE,QAAA;AAAA,EACvB,eAAeA,EAAE,IAAI,KAAK,EAAE,OAAO,MAAMH,EAAsB,SAAA,CAAU;AAC3E,
|
|
1
|
+
{"version":3,"file":"homeAddressSchema.js","sources":["../../../../../../src/components/Employee/Profile/shared/useHomeAddressForm/homeAddressSchema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n buildFormSchema,\n type RequiredFieldConfig,\n type OptionalFieldsToRequire,\n} from '@/partner-hook-utils/form/buildFormSchema'\n\n// ── Error codes ────────────────────────────────────────────────────────\n\n/**\n * Validation error codes emitted by the home address form schema. Map these\n * codes to localized copy in `validationMessages` when composing the hook.\n *\n * @public\n */\nexport const HomeAddressErrorCodes = {\n REQUIRED: 'REQUIRED',\n INVALID_ZIP: 'INVALID_ZIP',\n} as const\n\n/**\n * Union of validation error code strings emitted by the home address form\n * schema.\n *\n * @public\n */\nexport type HomeAddressErrorCode =\n (typeof HomeAddressErrorCodes)[keyof typeof HomeAddressErrorCodes]\n\n// ── Field validators ───────────────────────────────────────────────────\n\nconst ZIP_REGEX = /(^\\d{5}$)|(^\\d{5}-\\d{4}$)/\n\nconst fieldValidators = {\n street1: z.string(),\n street2: z.string(),\n city: z.string(),\n state: z.string(),\n zip: z.string().regex(ZIP_REGEX, { message: HomeAddressErrorCodes.INVALID_ZIP }),\n courtesyWithholding: z.boolean(),\n effectiveDate: z.iso.date({ error: () => HomeAddressErrorCodes.REQUIRED }),\n}\n\n/**\n * Field names accepted by the home address form.\n *\n * @public\n */\nexport type HomeAddressField = keyof typeof fieldValidators\n\n/**\n * Shape of the values managed by the home address form.\n *\n * @public\n * @interface\n */\nexport type HomeAddressFormData = {\n [K in keyof typeof fieldValidators]: z.infer<(typeof fieldValidators)[K]>\n}\n/**\n * Shape of the validated values produced by the home address form on submit.\n *\n * @public\n */\nexport type HomeAddressFormOutputs = HomeAddressFormData\n\n// ── Required fields config ─────────────────────────────────────────────\n\nconst requiredFieldsConfig = {\n street2: 'never',\n} satisfies RequiredFieldConfig<typeof fieldValidators>\n\n// ── Schema factory ─────────────────────────────────────────────────────\n\n/**\n * Keys of optional home address fields that can be promoted to required via\n * the hook's `optionalFieldsToRequire` option.\n *\n * @public\n */\nexport type HomeAddressOptionalFieldsToRequire = OptionalFieldsToRequire<\n typeof requiredFieldsConfig\n>\n\n/** @internal */\ninterface HomeAddressSchemaOptions {\n mode?: 'create' | 'update'\n optionalFieldsToRequire?: HomeAddressOptionalFieldsToRequire\n withEffectiveDateField?: boolean\n}\n\n/** @internal */\nexport function createHomeAddressSchema(options: HomeAddressSchemaOptions = {}) {\n const { mode = 'create', optionalFieldsToRequire, withEffectiveDateField = true } = options\n\n return buildFormSchema(fieldValidators, {\n requiredFieldsConfig,\n requiredErrorCode: HomeAddressErrorCodes.REQUIRED,\n mode,\n optionalFieldsToRequire,\n excludeFields: withEffectiveDateField ? [] : ['effectiveDate'],\n })\n}\n"],"names":["HomeAddressErrorCodes","ZIP_REGEX","fieldValidators","z","requiredFieldsConfig","createHomeAddressSchema","options","mode","optionalFieldsToRequire","withEffectiveDateField","buildFormSchema"],"mappings":";;AAeO,MAAMA,IAAwB;AAAA,EACnC,UAAU;AAAA,EACV,aAAa;AACf,GAaMC,IAAY,6BAEZC,IAAkB;AAAA,EACtB,SAASC,EAAE,OAAA;AAAA,EACX,SAASA,EAAE,OAAA;AAAA,EACX,MAAMA,EAAE,OAAA;AAAA,EACR,OAAOA,EAAE,OAAA;AAAA,EACT,KAAKA,EAAE,OAAA,EAAS,MAAMF,GAAW,EAAE,SAASD,EAAsB,aAAa;AAAA,EAC/E,qBAAqBG,EAAE,QAAA;AAAA,EACvB,eAAeA,EAAE,IAAI,KAAK,EAAE,OAAO,MAAMH,EAAsB,SAAA,CAAU;AAC3E,GA2BMI,IAAuB;AAAA,EAC3B,SAAS;AACX;AAsBO,SAASC,EAAwBC,IAAoC,IAAI;AAC9E,QAAM,EAAE,MAAAC,IAAO,UAAU,yBAAAC,GAAyB,wBAAAC,IAAyB,OAASH;AAEpF,SAAOI,EAAgBR,GAAiB;AAAA,IACtC,sBAAAE;AAAA,IACA,mBAAmBJ,EAAsB;AAAA,IACzC,MAAAO;AAAA,IACA,yBAAAC;AAAA,IACA,eAAeC,IAAyB,CAAA,IAAK,CAAC,eAAe;AAAA,EAAA,CAC9D;AACH;"}
|
|
@@ -109,6 +109,42 @@ export interface UseHomeAddressFormReady extends BaseFormHookReady<FieldsMetadat
|
|
|
109
109
|
* @param props - See {@link UseHomeAddressFormProps}.
|
|
110
110
|
* @returns A {@link HookLoadingResult} while loading, or a {@link UseHomeAddressFormReady} once ready.
|
|
111
111
|
* @public
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```tsx
|
|
115
|
+
* import {
|
|
116
|
+
* useHomeAddressForm,
|
|
117
|
+
* SDKFormProvider,
|
|
118
|
+
* type UseHomeAddressFormReady,
|
|
119
|
+
* } from '@gusto/embedded-react-sdk'
|
|
120
|
+
*
|
|
121
|
+
* function HomeAddressPage({ employeeId }: { employeeId: string }) {
|
|
122
|
+
* const homeAddress = useHomeAddressForm({ employeeId })
|
|
123
|
+
*
|
|
124
|
+
* if (homeAddress.isLoading) return <div>Loading...</div>
|
|
125
|
+
*
|
|
126
|
+
* return <HomeAddressReady homeAddress={homeAddress} />
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* function HomeAddressReady({ homeAddress }: { homeAddress: UseHomeAddressFormReady }) {
|
|
130
|
+
* const { Fields } = homeAddress.form
|
|
131
|
+
*
|
|
132
|
+
* return (
|
|
133
|
+
* <SDKFormProvider formHookResult={homeAddress}>
|
|
134
|
+
* <form onSubmit={e => { e.preventDefault(); void homeAddress.actions.onSubmit() }}>
|
|
135
|
+
* <Fields.Street1 label="Street address" />
|
|
136
|
+
* <Fields.Street2 label="Apt, suite, etc. (optional)" />
|
|
137
|
+
* <Fields.City label="City" />
|
|
138
|
+
* <Fields.State label="State" />
|
|
139
|
+
* <Fields.Zip label="ZIP code" />
|
|
140
|
+
* <Fields.CourtesyWithholding label="Courtesy withholding" />
|
|
141
|
+
* {Fields.EffectiveDate && <Fields.EffectiveDate label="Effective date" />}
|
|
142
|
+
* <button type="submit" disabled={homeAddress.status.isPending}>Save</button>
|
|
143
|
+
* </form>
|
|
144
|
+
* </SDKFormProvider>
|
|
145
|
+
* )
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
112
148
|
*/
|
|
113
149
|
export declare function useHomeAddressForm({ employeeId, homeAddressUuid, initialAddress, withEffectiveDateField, optionalFieldsToRequire, defaultValues: partnerDefaults, validationMode, shouldFocusError, }: UseHomeAddressFormProps): HookLoadingResult | UseHomeAddressFormReady;
|
|
114
150
|
/**
|
package/dist/components/Employee/Profile/shared/useHomeAddressForm/useHomeAddressForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHomeAddressForm.js","sources":["../../../../../../src/components/Employee/Profile/shared/useHomeAddressForm/useHomeAddressForm.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useForm } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport type { EmployeeAddress } from '@gusto/embedded-api-v-2025-11-15/models/components/employeeaddress'\nimport { useEmployeeAddressesRetrieveHomeAddress } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesRetrieveHomeAddress'\nimport { useEmployeeAddressesCreateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesCreate'\nimport { useEmployeeAddressesUpdateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesUpdate'\nimport { RFCDate } from '@gusto/embedded-api-v-2025-11-15/types/rfcdate'\nimport {\n createHomeAddressSchema,\n type HomeAddressOptionalFieldsToRequire,\n type HomeAddressFormData,\n type HomeAddressFormOutputs,\n} from './homeAddressSchema'\nimport {\n Street1Field,\n Street2Field,\n CityField,\n StateField,\n ZipField,\n CourtesyWithholdingField,\n EffectiveDateField,\n} from './fields'\nimport { useDeriveFieldsMetadata } from '@/partner-hook-utils/form/useDeriveFieldsMetadata'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport { withOptions } from '@/partner-hook-utils/form/withOptions'\nimport { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldsMetadata,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\nimport { STATES_ABBR } from '@/shared/constants'\n\nexport type { HomeAddressOptionalFieldsToRequire } from './homeAddressSchema'\n\n/**\n * Optional overrides passed to {@link UseHomeAddressFormReady.actions.onSubmit | onSubmit}.\n *\n * @public\n */\nexport interface HomeAddressSubmitOptions {\n /** Override the employee identifier supplied to the hook (e.g. after creating a new employee in the same flow). */\n employeeId?: string\n /** Override the effective date submitted with the address. When omitted on update without an effective-date field, the row's `effectiveDate` from the fetched address is used. */\n effectiveDate?: string\n}\n\n/**\n * Configuration options for {@link useHomeAddressForm}.\n *\n * @remarks\n * Presence or absence of `homeAddressUuid` selects the API verb — see the\n * `homeAddressUuid` field description.\n *\n * @public\n */\nexport interface UseHomeAddressFormProps {\n /** UUID of the employee whose home address is being created or edited. */\n employeeId: string\n /**\n * When set, loads that home address via GET `/v1/home_addresses/{uuid}` and updates it (PUT).\n * When omitted, the form is in create mode (POST).\n */\n homeAddressUuid?: string\n /**\n * Pre-loaded address matching `homeAddressUuid`. When supplied, the form uses it directly\n * instead of issuing a GET — useful when the parent already has the row from a list query.\n */\n initialAddress?: EmployeeAddress\n /** When `true`, renders `Fields.EffectiveDate`; otherwise it is `undefined`. Defaults to `true`. */\n withEffectiveDateField?: boolean\n /** Override fields that are optional on a given mode to be required. See `HomeAddressOptionalFieldsToRequire`. */\n optionalFieldsToRequire?: HomeAddressOptionalFieldsToRequire\n /** Pre-fill form values. Server data takes precedence on update. */\n defaultValues?: Partial<HomeAddressFormData>\n /** Passed through to react-hook-form. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Auto-focus the first invalid field on submit. Set to `false` when using `composeSubmitHandler` so submit-time focus is coordinated across multiple forms. Defaults to `true`. */\n shouldFocusError?: boolean\n}\n\n/**\n * Pre-bound field components exposed on `useHomeAddressForm().form.Fields`.\n *\n * @remarks\n * `EffectiveDate` is `undefined` when `withEffectiveDateField` is `false`.\n * Always null-check it before rendering.\n *\n * @public\n */\nexport interface HomeAddressFields {\n /** Street address line 1 text input. Always available. */\n Street1: typeof Street1Field\n /** Street address line 2 text input. Always available. */\n Street2: typeof Street2Field\n /** City text input. Always available. */\n City: typeof CityField\n /** State selector. Always available. */\n State: typeof StateField\n /** ZIP code text input. Always available. */\n Zip: typeof ZipField\n /** Courtesy withholding checkbox. Always available. */\n CourtesyWithholding: typeof CourtesyWithholdingField\n /** Effective-date picker. Only available when `withEffectiveDateField` is `true`. */\n EffectiveDate: typeof EffectiveDateField | undefined\n}\n\n/**\n * Ready-state shape returned by {@link useHomeAddressForm} once data has loaded.\n *\n * @remarks\n * Discriminated by `isLoading: false`. Extends {@link BaseFormHookReady} with\n * the home-address-specific `data`, `status`, `actions`, and `form.Fields` shape.\n *\n * @public\n */\nexport interface UseHomeAddressFormReady extends BaseFormHookReady<\n FieldsMetadata,\n HomeAddressFormData,\n HomeAddressFields\n> {\n /** Static entity data resolved from the API. */\n data: {\n /** The address row loaded for update; `null` in create mode. */\n homeAddress: EmployeeAddress | null\n }\n /** Reactive status flags. */\n status: { isPending: boolean; mode: 'create' | 'update' }\n /** Available actions. */\n actions: {\n onSubmit: (\n options?: HomeAddressSubmitOptions,\n ) => Promise<HookSubmitResult<EmployeeAddress> | undefined>\n }\n}\n\n/**\n * Form hook for creating or editing an employee's home address.\n *\n * @remarks\n * When `homeAddressUuid` is supplied the hook loads that address and issues a PUT on submit;\n * when omitted it operates in create mode and issues a POST. Pass `initialAddress` to\n * skip the fetch when the parent already holds the row.\n *\n * @param props - See {@link UseHomeAddressFormProps}.\n * @returns A {@link HookLoadingResult} while loading, or a {@link UseHomeAddressFormReady} once ready.\n * @public\n */\nexport function useHomeAddressForm({\n employeeId,\n homeAddressUuid,\n initialAddress,\n withEffectiveDateField = true,\n optionalFieldsToRequire,\n defaultValues: partnerDefaults,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n}: UseHomeAddressFormProps): HookLoadingResult | UseHomeAddressFormReady {\n const hasInitialAddressMatch = !!homeAddressUuid && initialAddress?.uuid === homeAddressUuid\n\n const retrieveHomeAddressQuery = useEmployeeAddressesRetrieveHomeAddress(\n { homeAddressUuid: homeAddressUuid ?? '' },\n { enabled: !!homeAddressUuid && !hasInitialAddressMatch },\n )\n\n const isCreateMode = !homeAddressUuid\n\n const fetchedHomeAddress = homeAddressUuid\n ? hasInitialAddressMatch\n ? initialAddress\n : retrieveHomeAddressQuery.data?.employeeAddress\n : undefined\n\n const schemaMode = isCreateMode ? 'create' : 'update'\n\n const [schema, metadataConfig] = useMemo(\n () =>\n createHomeAddressSchema({\n mode: schemaMode,\n optionalFieldsToRequire,\n withEffectiveDateField,\n }),\n [schemaMode, optionalFieldsToRequire, withEffectiveDateField],\n )\n\n const resolvedDefaults: HomeAddressFormData = useMemo(\n () => ({\n street1: fetchedHomeAddress?.street1 ?? partnerDefaults?.street1 ?? '',\n street2: fetchedHomeAddress?.street2 ?? partnerDefaults?.street2 ?? '',\n city: fetchedHomeAddress?.city ?? partnerDefaults?.city ?? '',\n state: fetchedHomeAddress?.state ?? partnerDefaults?.state ?? '',\n zip: fetchedHomeAddress?.zip ?? partnerDefaults?.zip ?? '',\n courtesyWithholding:\n fetchedHomeAddress?.courtesyWithholding ?? partnerDefaults?.courtesyWithholding ?? false,\n effectiveDate:\n fetchedHomeAddress?.effectiveDate?.toString() ?? partnerDefaults?.effectiveDate ?? '',\n }),\n [fetchedHomeAddress, partnerDefaults],\n )\n\n const formMethods = useForm<HomeAddressFormData, unknown, HomeAddressFormOutputs>({\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n })\n\n const createHomeAddressMutation = useEmployeeAddressesCreateMutation()\n const updateHomeAddressMutation = useEmployeeAddressesUpdateMutation()\n\n const isPending = createHomeAddressMutation.isPending || updateHomeAddressMutation.isPending\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('HomeAddressForm')\n\n const queriesForErrors = homeAddressUuid ? [retrieveHomeAddressQuery] : []\n const errorHandling = composeErrorHandler(queriesForErrors, { submitError, setSubmitError })\n\n const stateOptions = STATES_ABBR.map(abbr => ({\n value: abbr,\n label: abbr,\n }))\n\n const baseMetadata = useDeriveFieldsMetadata(metadataConfig, formMethods.control)\n const fieldsMetadata = {\n street1: baseMetadata.street1,\n street2: baseMetadata.street2,\n city: baseMetadata.city,\n state: withOptions(baseMetadata.state, stateOptions, STATES_ABBR),\n zip: baseMetadata.zip,\n courtesyWithholding: baseMetadata.courtesyWithholding,\n effectiveDate: baseMetadata.effectiveDate,\n }\n\n const onSubmit = async (\n options?: HomeAddressSubmitOptions,\n ): Promise<HookSubmitResult<EmployeeAddress> | undefined> => {\n let submitResult: HookSubmitResult<EmployeeAddress> | undefined\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async (data: HomeAddressFormOutputs) => {\n await baseSubmitHandler(data, async payload => {\n const resolvedEmployeeId = options?.employeeId ?? employeeId\n\n const resolvedEffectiveDate =\n withEffectiveDateField && payload.effectiveDate\n ? payload.effectiveDate\n : (options?.effectiveDate ??\n (!withEffectiveDateField && !isCreateMode\n ? fetchedHomeAddress?.effectiveDate?.toString()\n : undefined))\n\n const effectiveDateParam = resolvedEffectiveDate\n ? new RFCDate(new Date(resolvedEffectiveDate))\n : undefined\n\n let updatedHomeAddress: EmployeeAddress\n\n if (isCreateMode) {\n const result = await createHomeAddressMutation.mutateAsync({\n request: {\n employeeId: resolvedEmployeeId,\n requestBody: {\n street1: payload.street1,\n street2: payload.street2 || undefined,\n city: payload.city,\n state: payload.state,\n zip: payload.zip,\n courtesyWithholding: payload.courtesyWithholding,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeAddress) {\n throw new SDKInternalError('Home address creation failed')\n }\n\n updatedHomeAddress = result.employeeAddress\n } else {\n if (!fetchedHomeAddress || !homeAddressUuid) {\n throw new SDKInternalError(\n 'Cannot update home address: no matching address on file',\n )\n }\n\n const result = await updateHomeAddressMutation.mutateAsync({\n request: {\n homeAddressUuid: fetchedHomeAddress.uuid,\n requestBody: {\n version: fetchedHomeAddress.version,\n street1: payload.street1,\n street2: payload.street2 || undefined,\n city: payload.city,\n state: payload.state,\n zip: payload.zip,\n courtesyWithholding: payload.courtesyWithholding,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeAddress) {\n throw new SDKInternalError('Home address update failed')\n }\n\n updatedHomeAddress = result.employeeAddress\n }\n\n submitResult = {\n mode: isCreateMode ? 'create' : 'update',\n data: updatedHomeAddress,\n }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n if (homeAddressUuid && !fetchedHomeAddress) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n homeAddress: fetchedHomeAddress ?? null,\n },\n status: {\n isPending,\n mode: isCreateMode ? ('create' as const) : ('update' as const),\n },\n actions: { onSubmit },\n errorHandling,\n form: {\n Fields: {\n Street1: Street1Field,\n Street2: Street2Field,\n City: CityField,\n State: StateField,\n Zip: ZipField,\n CourtesyWithholding: CourtesyWithholdingField,\n EffectiveDate: withEffectiveDateField ? EffectiveDateField : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n },\n }\n}\n\n/**\n * Discriminated union returned by {@link useHomeAddressForm}.\n *\n * @public\n */\nexport type UseHomeAddressFormResult = HookLoadingResult | UseHomeAddressFormReady\n/**\n * Type of `form.fieldsMetadata` returned by {@link useHomeAddressForm}.\n *\n * @public\n */\nexport type HomeAddressFieldsMetadata = UseHomeAddressFormReady['form']['fieldsMetadata']\n/**\n * Type of `form.Fields` returned by {@link useHomeAddressForm}.\n *\n * @public\n */\nexport type HomeAddressFormFields = UseHomeAddressFormReady['form']['Fields']\n"],"names":["useHomeAddressForm","employeeId","homeAddressUuid","initialAddress","withEffectiveDateField","optionalFieldsToRequire","partnerDefaults","validationMode","shouldFocusError","hasInitialAddressMatch","retrieveHomeAddressQuery","useEmployeeAddressesRetrieveHomeAddress","isCreateMode","fetchedHomeAddress","schemaMode","schema","metadataConfig","useMemo","createHomeAddressSchema","resolvedDefaults","formMethods","useForm","zodResolver","createHomeAddressMutation","useEmployeeAddressesCreateMutation","updateHomeAddressMutation","useEmployeeAddressesUpdateMutation","isPending","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","errorHandling","composeErrorHandler","stateOptions","STATES_ABBR","abbr","baseMetadata","useDeriveFieldsMetadata","fieldsMetadata","withOptions","onSubmit","options","submitResult","resolve","data","payload","resolvedEmployeeId","resolvedEffectiveDate","effectiveDateParam","RFCDate","updatedHomeAddress","result","SDKInternalError","hookFormInternals","useHookFormInternals","Street1Field","Street2Field","CityField","StateField","ZipField","CourtesyWithholdingField","EffectiveDateField","createGetFormSubmissionValues"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useHomeAddressForm.js","sources":["../../../../../../src/components/Employee/Profile/shared/useHomeAddressForm/useHomeAddressForm.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useForm } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport type { EmployeeAddress } from '@gusto/embedded-api-v-2025-11-15/models/components/employeeaddress'\nimport { useEmployeeAddressesRetrieveHomeAddress } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesRetrieveHomeAddress'\nimport { useEmployeeAddressesCreateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesCreate'\nimport { useEmployeeAddressesUpdateMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesUpdate'\nimport { RFCDate } from '@gusto/embedded-api-v-2025-11-15/types/rfcdate'\nimport {\n createHomeAddressSchema,\n type HomeAddressOptionalFieldsToRequire,\n type HomeAddressFormData,\n type HomeAddressFormOutputs,\n} from './homeAddressSchema'\nimport {\n Street1Field,\n Street2Field,\n CityField,\n StateField,\n ZipField,\n CourtesyWithholdingField,\n EffectiveDateField,\n} from './fields'\nimport { useDeriveFieldsMetadata } from '@/partner-hook-utils/form/useDeriveFieldsMetadata'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport { withOptions } from '@/partner-hook-utils/form/withOptions'\nimport { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldsMetadata,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\nimport { STATES_ABBR } from '@/shared/constants'\n\nexport type { HomeAddressOptionalFieldsToRequire } from './homeAddressSchema'\n\n/**\n * Optional overrides passed to {@link UseHomeAddressFormReady.actions.onSubmit | onSubmit}.\n *\n * @public\n */\nexport interface HomeAddressSubmitOptions {\n /** Override the employee identifier supplied to the hook (e.g. after creating a new employee in the same flow). */\n employeeId?: string\n /** Override the effective date submitted with the address. When omitted on update without an effective-date field, the row's `effectiveDate` from the fetched address is used. */\n effectiveDate?: string\n}\n\n/**\n * Configuration options for {@link useHomeAddressForm}.\n *\n * @remarks\n * Presence or absence of `homeAddressUuid` selects the API verb — see the\n * `homeAddressUuid` field description.\n *\n * @public\n */\nexport interface UseHomeAddressFormProps {\n /** UUID of the employee whose home address is being created or edited. */\n employeeId: string\n /**\n * When set, loads that home address via GET `/v1/home_addresses/{uuid}` and updates it (PUT).\n * When omitted, the form is in create mode (POST).\n */\n homeAddressUuid?: string\n /**\n * Pre-loaded address matching `homeAddressUuid`. When supplied, the form uses it directly\n * instead of issuing a GET — useful when the parent already has the row from a list query.\n */\n initialAddress?: EmployeeAddress\n /** When `true`, renders `Fields.EffectiveDate`; otherwise it is `undefined`. Defaults to `true`. */\n withEffectiveDateField?: boolean\n /** Override fields that are optional on a given mode to be required. See `HomeAddressOptionalFieldsToRequire`. */\n optionalFieldsToRequire?: HomeAddressOptionalFieldsToRequire\n /** Pre-fill form values. Server data takes precedence on update. */\n defaultValues?: Partial<HomeAddressFormData>\n /** Passed through to react-hook-form. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Auto-focus the first invalid field on submit. Set to `false` when using `composeSubmitHandler` so submit-time focus is coordinated across multiple forms. Defaults to `true`. */\n shouldFocusError?: boolean\n}\n\n/**\n * Pre-bound field components exposed on `useHomeAddressForm().form.Fields`.\n *\n * @remarks\n * `EffectiveDate` is `undefined` when `withEffectiveDateField` is `false`.\n * Always null-check it before rendering.\n *\n * @public\n */\nexport interface HomeAddressFields {\n /** Street address line 1 text input. Always available. */\n Street1: typeof Street1Field\n /** Street address line 2 text input. Always available. */\n Street2: typeof Street2Field\n /** City text input. Always available. */\n City: typeof CityField\n /** State selector. Always available. */\n State: typeof StateField\n /** ZIP code text input. Always available. */\n Zip: typeof ZipField\n /** Courtesy withholding checkbox. Always available. */\n CourtesyWithholding: typeof CourtesyWithholdingField\n /** Effective-date picker. Only available when `withEffectiveDateField` is `true`. */\n EffectiveDate: typeof EffectiveDateField | undefined\n}\n\n/**\n * Ready-state shape returned by {@link useHomeAddressForm} once data has loaded.\n *\n * @remarks\n * Discriminated by `isLoading: false`. Extends {@link BaseFormHookReady} with\n * the home-address-specific `data`, `status`, `actions`, and `form.Fields` shape.\n *\n * @public\n */\nexport interface UseHomeAddressFormReady extends BaseFormHookReady<\n FieldsMetadata,\n HomeAddressFormData,\n HomeAddressFields\n> {\n /** Static entity data resolved from the API. */\n data: {\n /** The address row loaded for update; `null` in create mode. */\n homeAddress: EmployeeAddress | null\n }\n /** Reactive status flags. */\n status: { isPending: boolean; mode: 'create' | 'update' }\n /** Available actions. */\n actions: {\n onSubmit: (\n options?: HomeAddressSubmitOptions,\n ) => Promise<HookSubmitResult<EmployeeAddress> | undefined>\n }\n}\n\n/**\n * Form hook for creating or editing an employee's home address.\n *\n * @remarks\n * When `homeAddressUuid` is supplied the hook loads that address and issues a PUT on submit;\n * when omitted it operates in create mode and issues a POST. Pass `initialAddress` to\n * skip the fetch when the parent already holds the row.\n *\n * @param props - See {@link UseHomeAddressFormProps}.\n * @returns A {@link HookLoadingResult} while loading, or a {@link UseHomeAddressFormReady} once ready.\n * @public\n *\n * @example\n * ```tsx\n * import {\n * useHomeAddressForm,\n * SDKFormProvider,\n * type UseHomeAddressFormReady,\n * } from '@gusto/embedded-react-sdk'\n *\n * function HomeAddressPage({ employeeId }: { employeeId: string }) {\n * const homeAddress = useHomeAddressForm({ employeeId })\n *\n * if (homeAddress.isLoading) return <div>Loading...</div>\n *\n * return <HomeAddressReady homeAddress={homeAddress} />\n * }\n *\n * function HomeAddressReady({ homeAddress }: { homeAddress: UseHomeAddressFormReady }) {\n * const { Fields } = homeAddress.form\n *\n * return (\n * <SDKFormProvider formHookResult={homeAddress}>\n * <form onSubmit={e => { e.preventDefault(); void homeAddress.actions.onSubmit() }}>\n * <Fields.Street1 label=\"Street address\" />\n * <Fields.Street2 label=\"Apt, suite, etc. (optional)\" />\n * <Fields.City label=\"City\" />\n * <Fields.State label=\"State\" />\n * <Fields.Zip label=\"ZIP code\" />\n * <Fields.CourtesyWithholding label=\"Courtesy withholding\" />\n * {Fields.EffectiveDate && <Fields.EffectiveDate label=\"Effective date\" />}\n * <button type=\"submit\" disabled={homeAddress.status.isPending}>Save</button>\n * </form>\n * </SDKFormProvider>\n * )\n * }\n * ```\n */\nexport function useHomeAddressForm({\n employeeId,\n homeAddressUuid,\n initialAddress,\n withEffectiveDateField = true,\n optionalFieldsToRequire,\n defaultValues: partnerDefaults,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n}: UseHomeAddressFormProps): HookLoadingResult | UseHomeAddressFormReady {\n const hasInitialAddressMatch = !!homeAddressUuid && initialAddress?.uuid === homeAddressUuid\n\n const retrieveHomeAddressQuery = useEmployeeAddressesRetrieveHomeAddress(\n { homeAddressUuid: homeAddressUuid ?? '' },\n { enabled: !!homeAddressUuid && !hasInitialAddressMatch },\n )\n\n const isCreateMode = !homeAddressUuid\n\n const fetchedHomeAddress = homeAddressUuid\n ? hasInitialAddressMatch\n ? initialAddress\n : retrieveHomeAddressQuery.data?.employeeAddress\n : undefined\n\n const schemaMode = isCreateMode ? 'create' : 'update'\n\n const [schema, metadataConfig] = useMemo(\n () =>\n createHomeAddressSchema({\n mode: schemaMode,\n optionalFieldsToRequire,\n withEffectiveDateField,\n }),\n [schemaMode, optionalFieldsToRequire, withEffectiveDateField],\n )\n\n const resolvedDefaults: HomeAddressFormData = useMemo(\n () => ({\n street1: fetchedHomeAddress?.street1 ?? partnerDefaults?.street1 ?? '',\n street2: fetchedHomeAddress?.street2 ?? partnerDefaults?.street2 ?? '',\n city: fetchedHomeAddress?.city ?? partnerDefaults?.city ?? '',\n state: fetchedHomeAddress?.state ?? partnerDefaults?.state ?? '',\n zip: fetchedHomeAddress?.zip ?? partnerDefaults?.zip ?? '',\n courtesyWithholding:\n fetchedHomeAddress?.courtesyWithholding ?? partnerDefaults?.courtesyWithholding ?? false,\n effectiveDate:\n fetchedHomeAddress?.effectiveDate?.toString() ?? partnerDefaults?.effectiveDate ?? '',\n }),\n [fetchedHomeAddress, partnerDefaults],\n )\n\n const formMethods = useForm<HomeAddressFormData, unknown, HomeAddressFormOutputs>({\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n })\n\n const createHomeAddressMutation = useEmployeeAddressesCreateMutation()\n const updateHomeAddressMutation = useEmployeeAddressesUpdateMutation()\n\n const isPending = createHomeAddressMutation.isPending || updateHomeAddressMutation.isPending\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('HomeAddressForm')\n\n const queriesForErrors = homeAddressUuid ? [retrieveHomeAddressQuery] : []\n const errorHandling = composeErrorHandler(queriesForErrors, { submitError, setSubmitError })\n\n const stateOptions = STATES_ABBR.map(abbr => ({\n value: abbr,\n label: abbr,\n }))\n\n const baseMetadata = useDeriveFieldsMetadata(metadataConfig, formMethods.control)\n const fieldsMetadata = {\n street1: baseMetadata.street1,\n street2: baseMetadata.street2,\n city: baseMetadata.city,\n state: withOptions(baseMetadata.state, stateOptions, STATES_ABBR),\n zip: baseMetadata.zip,\n courtesyWithholding: baseMetadata.courtesyWithholding,\n effectiveDate: baseMetadata.effectiveDate,\n }\n\n const onSubmit = async (\n options?: HomeAddressSubmitOptions,\n ): Promise<HookSubmitResult<EmployeeAddress> | undefined> => {\n let submitResult: HookSubmitResult<EmployeeAddress> | undefined\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async (data: HomeAddressFormOutputs) => {\n await baseSubmitHandler(data, async payload => {\n const resolvedEmployeeId = options?.employeeId ?? employeeId\n\n const resolvedEffectiveDate =\n withEffectiveDateField && payload.effectiveDate\n ? payload.effectiveDate\n : (options?.effectiveDate ??\n (!withEffectiveDateField && !isCreateMode\n ? fetchedHomeAddress?.effectiveDate?.toString()\n : undefined))\n\n const effectiveDateParam = resolvedEffectiveDate\n ? new RFCDate(new Date(resolvedEffectiveDate))\n : undefined\n\n let updatedHomeAddress: EmployeeAddress\n\n if (isCreateMode) {\n const result = await createHomeAddressMutation.mutateAsync({\n request: {\n employeeId: resolvedEmployeeId,\n requestBody: {\n street1: payload.street1,\n street2: payload.street2 || undefined,\n city: payload.city,\n state: payload.state,\n zip: payload.zip,\n courtesyWithholding: payload.courtesyWithholding,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeAddress) {\n throw new SDKInternalError('Home address creation failed')\n }\n\n updatedHomeAddress = result.employeeAddress\n } else {\n if (!fetchedHomeAddress || !homeAddressUuid) {\n throw new SDKInternalError(\n 'Cannot update home address: no matching address on file',\n )\n }\n\n const result = await updateHomeAddressMutation.mutateAsync({\n request: {\n homeAddressUuid: fetchedHomeAddress.uuid,\n requestBody: {\n version: fetchedHomeAddress.version,\n street1: payload.street1,\n street2: payload.street2 || undefined,\n city: payload.city,\n state: payload.state,\n zip: payload.zip,\n courtesyWithholding: payload.courtesyWithholding,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeAddress) {\n throw new SDKInternalError('Home address update failed')\n }\n\n updatedHomeAddress = result.employeeAddress\n }\n\n submitResult = {\n mode: isCreateMode ? 'create' : 'update',\n data: updatedHomeAddress,\n }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n if (homeAddressUuid && !fetchedHomeAddress) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n homeAddress: fetchedHomeAddress ?? null,\n },\n status: {\n isPending,\n mode: isCreateMode ? ('create' as const) : ('update' as const),\n },\n actions: { onSubmit },\n errorHandling,\n form: {\n Fields: {\n Street1: Street1Field,\n Street2: Street2Field,\n City: CityField,\n State: StateField,\n Zip: ZipField,\n CourtesyWithholding: CourtesyWithholdingField,\n EffectiveDate: withEffectiveDateField ? EffectiveDateField : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n },\n }\n}\n\n/**\n * Discriminated union returned by {@link useHomeAddressForm}.\n *\n * @public\n */\nexport type UseHomeAddressFormResult = HookLoadingResult | UseHomeAddressFormReady\n/**\n * Type of `form.fieldsMetadata` returned by {@link useHomeAddressForm}.\n *\n * @public\n */\nexport type HomeAddressFieldsMetadata = UseHomeAddressFormReady['form']['fieldsMetadata']\n/**\n * Type of `form.Fields` returned by {@link useHomeAddressForm}.\n *\n * @public\n */\nexport type HomeAddressFormFields = UseHomeAddressFormReady['form']['Fields']\n"],"names":["useHomeAddressForm","employeeId","homeAddressUuid","initialAddress","withEffectiveDateField","optionalFieldsToRequire","partnerDefaults","validationMode","shouldFocusError","hasInitialAddressMatch","retrieveHomeAddressQuery","useEmployeeAddressesRetrieveHomeAddress","isCreateMode","fetchedHomeAddress","schemaMode","schema","metadataConfig","useMemo","createHomeAddressSchema","resolvedDefaults","formMethods","useForm","zodResolver","createHomeAddressMutation","useEmployeeAddressesCreateMutation","updateHomeAddressMutation","useEmployeeAddressesUpdateMutation","isPending","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","errorHandling","composeErrorHandler","stateOptions","STATES_ABBR","abbr","baseMetadata","useDeriveFieldsMetadata","fieldsMetadata","withOptions","onSubmit","options","submitResult","resolve","data","payload","resolvedEmployeeId","resolvedEffectiveDate","effectiveDateParam","RFCDate","updatedHomeAddress","result","SDKInternalError","hookFormInternals","useHookFormInternals","Street1Field","Street2Field","CityField","StateField","ZipField","CourtesyWithholdingField","EffectiveDateField","createGetFormSubmissionValues"],"mappings":"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"}
|
|
@@ -120,6 +120,37 @@ export interface UseWorkAddressFormReady extends BaseFormHookReady<FieldsMetadat
|
|
|
120
120
|
* @param props - See {@link UseWorkAddressFormProps}.
|
|
121
121
|
* @returns A {@link HookLoadingResult} while loading, or a {@link UseWorkAddressFormReady} once ready.
|
|
122
122
|
* @public
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* import {
|
|
127
|
+
* useWorkAddressForm,
|
|
128
|
+
* SDKFormProvider,
|
|
129
|
+
* type UseWorkAddressFormReady,
|
|
130
|
+
* } from '@gusto/embedded-react-sdk'
|
|
131
|
+
*
|
|
132
|
+
* function WorkAddressPage({ companyId, employeeId }: { companyId: string; employeeId: string }) {
|
|
133
|
+
* const workAddress = useWorkAddressForm({ companyId, employeeId })
|
|
134
|
+
*
|
|
135
|
+
* if (workAddress.isLoading) return <div>Loading...</div>
|
|
136
|
+
*
|
|
137
|
+
* return <WorkAddressReady workAddress={workAddress} />
|
|
138
|
+
* }
|
|
139
|
+
*
|
|
140
|
+
* function WorkAddressReady({ workAddress }: { workAddress: UseWorkAddressFormReady }) {
|
|
141
|
+
* const { Fields } = workAddress.form
|
|
142
|
+
*
|
|
143
|
+
* return (
|
|
144
|
+
* <SDKFormProvider formHookResult={workAddress}>
|
|
145
|
+
* <form onSubmit={e => { e.preventDefault(); void workAddress.actions.onSubmit() }}>
|
|
146
|
+
* <Fields.Location label="Work address" />
|
|
147
|
+
* {Fields.EffectiveDate && <Fields.EffectiveDate label="Effective date" />}
|
|
148
|
+
* <button type="submit" disabled={workAddress.status.isPending}>Save</button>
|
|
149
|
+
* </form>
|
|
150
|
+
* </SDKFormProvider>
|
|
151
|
+
* )
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
123
154
|
*/
|
|
124
155
|
export declare function useWorkAddressForm({ companyId, employeeId, workAddressUuid, initialAddress, withEffectiveDateField, optionalFieldsToRequire, defaultValues: partnerDefaults, validationMode, shouldFocusError, }: UseWorkAddressFormProps): HookLoadingResult | UseWorkAddressFormReady;
|
|
125
156
|
/**
|
package/dist/components/Employee/Profile/shared/useWorkAddressForm/useWorkAddressForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWorkAddressForm.js","sources":["../../../../../../src/components/Employee/Profile/shared/useWorkAddressForm/useWorkAddressForm.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useForm } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport type { Location } from '@gusto/embedded-api-v-2025-11-15/models/components/location'\nimport type { EmployeeWorkAddress } from '@gusto/embedded-api-v-2025-11-15/models/components/employeeworkaddress'\nimport { useLocationsGet } from '@gusto/embedded-api-v-2025-11-15/react-query/locationsGet'\nimport { useEmployeeAddressesRetrieveWorkAddress } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesRetrieveWorkAddress'\nimport { useEmployeeAddressesCreateWorkAddressMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesCreateWorkAddress'\nimport { useEmployeeAddressesUpdateWorkAddressMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesUpdateWorkAddress'\nimport { RFCDate } from '@gusto/embedded-api-v-2025-11-15/types/rfcdate'\nimport {\n createWorkAddressSchema,\n type WorkAddressOptionalFieldsToRequire,\n type WorkAddressFormData,\n type WorkAddressFormOutputs,\n} from './workAddressSchema'\nimport { LocationField, EffectiveDateField } from './fields'\nimport { useDeriveFieldsMetadata } from '@/partner-hook-utils/form/useDeriveFieldsMetadata'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport { withOptions } from '@/partner-hook-utils/form/withOptions'\nimport { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldsMetadata,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\nimport { addressInline } from '@/helpers/formattedStrings'\n\nexport type { WorkAddressOptionalFieldsToRequire } from './workAddressSchema'\n\n/**\n * Optional callbacks passed to {@link UseWorkAddressFormReady.actions.onSubmit | onSubmit}.\n *\n * @remarks\n * Only the callback matching the submit mode fires —\n * `onWorkAddressCreated` on create, `onWorkAddressUpdated` on update.\n *\n * @public\n */\nexport interface WorkAddressSubmitCallbacks {\n /** Fired after a new work address is successfully created. */\n onWorkAddressCreated?: (workAddress: EmployeeWorkAddress) => void\n /** Fired after an existing work address is successfully updated. */\n onWorkAddressUpdated?: (workAddress: EmployeeWorkAddress) => void\n}\n\n/**\n * Optional overrides passed to {@link UseWorkAddressFormReady.actions.onSubmit | onSubmit}.\n *\n * @public\n */\nexport interface WorkAddressSubmitOptions {\n /** Override the employee identifier supplied to the hook (e.g. after creating a new employee in the same flow). */\n employeeId?: string\n /** Override the effective date submitted with the address. */\n effectiveDate?: string\n}\n\n/**\n * Configuration options for {@link useWorkAddressForm}.\n *\n * @remarks\n * Presence or absence of `workAddressUuid` selects the API verb — see the\n * `workAddressUuid` field description. `companyId` is required to fetch\n * the location list; pass it when it is known.\n *\n * @public\n */\nexport interface UseWorkAddressFormProps {\n /** Company UUID for locations; omit or leave unset while resolving from the employee record. */\n companyId?: string\n /** UUID of the employee whose work address is being created or edited. */\n employeeId: string\n /**\n * When set, loads that work address via GET `/v1/work_addresses/{work_address_uuid}` and updates it (PUT).\n * When omitted, the form is in create mode (POST).\n */\n workAddressUuid?: string\n /**\n * Pre-loaded address matching `workAddressUuid`. When supplied, the form uses it directly\n * instead of issuing a GET — useful when the parent already has the row from a list query.\n */\n initialAddress?: EmployeeWorkAddress\n /** When `true`, renders `Fields.EffectiveDate`; otherwise it is `undefined`. Defaults to `true`. */\n withEffectiveDateField?: boolean\n /** Override fields that are optional on a given mode to be required. See `WorkAddressOptionalFieldsToRequire`. */\n optionalFieldsToRequire?: WorkAddressOptionalFieldsToRequire\n /** Pre-fill form values. Server data takes precedence on update. */\n defaultValues?: Partial<WorkAddressFormData>\n /** Passed through to react-hook-form. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Auto-focus the first invalid field on submit. Set to `false` when using `composeSubmitHandler` so submit-time focus is coordinated across multiple forms. Defaults to `true`. */\n shouldFocusError?: boolean\n}\n\n/**\n * Pre-bound field components exposed on `useWorkAddressForm().form.Fields`.\n *\n * @remarks\n * `EffectiveDate` is `undefined` when `withEffectiveDateField` is `false`.\n * Always null-check it before rendering.\n *\n * @public\n */\nexport interface WorkAddressFields {\n /** Location selector. Always available. */\n Location: typeof LocationField\n /** Effective-date picker. Only available when `withEffectiveDateField` is `true`. */\n EffectiveDate: typeof EffectiveDateField | undefined\n}\n\n/**\n * Ready-state shape returned by {@link useWorkAddressForm} once data has loaded.\n *\n * @remarks\n * Discriminated by `isLoading: false`. Extends {@link BaseFormHookReady} with\n * the work-address-specific `data`, `status`, `actions`, and `form.Fields` shape.\n *\n * @public\n */\nexport interface UseWorkAddressFormReady extends BaseFormHookReady<\n FieldsMetadata,\n WorkAddressFormData,\n WorkAddressFields\n> {\n /** Static entity data resolved from the API. */\n data: {\n /** The address row loaded for update; `null` in create mode. */\n workAddress: EmployeeWorkAddress | null\n /** Company locations available for selection; `undefined` until the locations query resolves. */\n companyLocations: Location[] | undefined\n }\n /** Reactive status flags. */\n status: { isPending: boolean; mode: 'create' | 'update' }\n /** Available actions. */\n actions: {\n onSubmit: (\n callbacks?: WorkAddressSubmitCallbacks,\n options?: WorkAddressSubmitOptions,\n ) => Promise<HookSubmitResult<EmployeeWorkAddress> | undefined>\n }\n}\n\n/**\n * Form hook for creating or editing an employee's work address.\n *\n * @remarks\n * When `workAddressUuid` is supplied the hook loads that address and issues a PUT on submit;\n * when omitted it operates in create mode and issues a POST. The hook requires `companyId`\n * to fetch the company's location list — it stays in loading state until `companyId` is known.\n *\n * @param props - See {@link UseWorkAddressFormProps}.\n * @returns A {@link HookLoadingResult} while loading, or a {@link UseWorkAddressFormReady} once ready.\n * @public\n */\nexport function useWorkAddressForm({\n companyId,\n employeeId,\n workAddressUuid,\n initialAddress,\n withEffectiveDateField = true,\n optionalFieldsToRequire,\n defaultValues: partnerDefaults,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n}: UseWorkAddressFormProps): HookLoadingResult | UseWorkAddressFormReady {\n const locationsQuery = useLocationsGet({ companyId: companyId ?? '' }, { enabled: !!companyId })\n\n const hasInitialAddressMatch = !!workAddressUuid && initialAddress?.uuid === workAddressUuid\n\n const retrieveWorkAddressQuery = useEmployeeAddressesRetrieveWorkAddress(\n { workAddressUuid: workAddressUuid ?? '' },\n { enabled: !!workAddressUuid && !hasInitialAddressMatch },\n )\n\n const companyLocations = locationsQuery.data?.companyLocationsList\n\n const isCreateMode = !workAddressUuid\n\n const fetchedWorkAddress = workAddressUuid\n ? hasInitialAddressMatch\n ? initialAddress\n : retrieveWorkAddressQuery.data?.employeeWorkAddress\n : undefined\n\n const schemaMode = isCreateMode ? 'create' : 'update'\n\n const [schema, metadataConfig] = useMemo(\n () =>\n createWorkAddressSchema({\n mode: schemaMode,\n optionalFieldsToRequire,\n withEffectiveDateField,\n }),\n [schemaMode, optionalFieldsToRequire, withEffectiveDateField],\n )\n\n const resolvedDefaults: WorkAddressFormData = useMemo(\n () => ({\n locationUuid: fetchedWorkAddress?.locationUuid ?? partnerDefaults?.locationUuid ?? '',\n effectiveDate: fetchedWorkAddress?.effectiveDate ?? partnerDefaults?.effectiveDate ?? '',\n }),\n [fetchedWorkAddress, partnerDefaults],\n )\n\n const formMethods = useForm<WorkAddressFormData, unknown, WorkAddressFormOutputs>({\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n })\n\n const createWorkAddressMutation = useEmployeeAddressesCreateWorkAddressMutation()\n const updateWorkAddressMutation = useEmployeeAddressesUpdateWorkAddressMutation()\n\n const isPending = createWorkAddressMutation.isPending || updateWorkAddressMutation.isPending\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('WorkAddressForm')\n\n const queriesForErrors = [locationsQuery, ...(workAddressUuid ? [retrieveWorkAddressQuery] : [])]\n const errorHandling = composeErrorHandler(queriesForErrors, { submitError, setSubmitError })\n\n const locationOptions = (companyLocations ?? []).map(location => ({\n value: location.uuid,\n label: addressInline(location),\n }))\n\n const baseMetadata = useDeriveFieldsMetadata(metadataConfig, formMethods.control)\n const fieldsMetadata = {\n locationUuid: withOptions<Location>(\n baseMetadata.locationUuid,\n locationOptions,\n companyLocations ?? [],\n ),\n effectiveDate: baseMetadata.effectiveDate,\n }\n\n const onSubmit = async (\n callbacks?: WorkAddressSubmitCallbacks,\n options?: WorkAddressSubmitOptions,\n ): Promise<HookSubmitResult<EmployeeWorkAddress> | undefined> => {\n let submitResult: HookSubmitResult<EmployeeWorkAddress> | undefined\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async (data: WorkAddressFormOutputs) => {\n await baseSubmitHandler(data, async payload => {\n const resolvedEmployeeId = options?.employeeId ?? employeeId\n\n if (!resolvedEmployeeId) {\n throw new SDKInternalError('employeeId is required to submit work address')\n }\n\n const resolvedEffectiveDate =\n withEffectiveDateField && payload.effectiveDate\n ? payload.effectiveDate\n : options?.effectiveDate\n\n const effectiveDateParam = resolvedEffectiveDate\n ? new RFCDate(new Date(resolvedEffectiveDate))\n : undefined\n\n let updatedWorkAddress: EmployeeWorkAddress\n\n if (isCreateMode) {\n const result = await createWorkAddressMutation.mutateAsync({\n request: {\n employeeId: resolvedEmployeeId,\n requestBody: {\n locationUuid: payload.locationUuid,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeWorkAddress) {\n throw new SDKInternalError('Work address creation failed')\n }\n\n updatedWorkAddress = result.employeeWorkAddress\n callbacks?.onWorkAddressCreated?.(updatedWorkAddress)\n } else {\n if (!fetchedWorkAddress || !workAddressUuid) {\n throw new SDKInternalError(\n 'Cannot update work address: no matching address on file',\n )\n }\n\n const result = await updateWorkAddressMutation.mutateAsync({\n request: {\n workAddressUuid: fetchedWorkAddress.uuid,\n requestBody: {\n version: fetchedWorkAddress.version,\n locationUuid: payload.locationUuid,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeWorkAddress) {\n throw new SDKInternalError('Work address update failed')\n }\n\n updatedWorkAddress = result.employeeWorkAddress\n callbacks?.onWorkAddressUpdated?.(updatedWorkAddress)\n }\n\n submitResult = {\n mode: isCreateMode ? 'create' : 'update',\n data: updatedWorkAddress,\n }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n const isDataLoading =\n (!!companyId && locationsQuery.isLoading) ||\n (!!workAddressUuid && retrieveWorkAddressQuery.isLoading)\n\n if (!companyId || isDataLoading || !companyLocations) {\n return { isLoading: true as const, errorHandling }\n }\n\n if (workAddressUuid && !fetchedWorkAddress) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n workAddress: fetchedWorkAddress ?? null,\n companyLocations,\n },\n status: {\n isPending,\n mode: isCreateMode ? ('create' as const) : ('update' as const),\n },\n actions: { onSubmit },\n errorHandling,\n form: {\n Fields: {\n Location: LocationField,\n EffectiveDate: withEffectiveDateField ? EffectiveDateField : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n },\n }\n}\n\n/**\n * Discriminated union returned by {@link useWorkAddressForm}.\n *\n * @public\n */\nexport type UseWorkAddressFormResult = HookLoadingResult | UseWorkAddressFormReady\n/**\n * Type of `form.fieldsMetadata` returned by {@link useWorkAddressForm}.\n *\n * @public\n */\nexport type WorkAddressFieldsMetadata = UseWorkAddressFormReady['form']['fieldsMetadata']\n/**\n * Type of `form.Fields` returned by {@link useWorkAddressForm}.\n *\n * @public\n */\nexport type WorkAddressFormFields = UseWorkAddressFormReady['form']['Fields']\n"],"names":["useWorkAddressForm","companyId","employeeId","workAddressUuid","initialAddress","withEffectiveDateField","optionalFieldsToRequire","partnerDefaults","validationMode","shouldFocusError","locationsQuery","useLocationsGet","hasInitialAddressMatch","retrieveWorkAddressQuery","useEmployeeAddressesRetrieveWorkAddress","companyLocations","isCreateMode","fetchedWorkAddress","schemaMode","schema","metadataConfig","useMemo","createWorkAddressSchema","resolvedDefaults","formMethods","useForm","zodResolver","createWorkAddressMutation","useEmployeeAddressesCreateWorkAddressMutation","updateWorkAddressMutation","useEmployeeAddressesUpdateWorkAddressMutation","isPending","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","queriesForErrors","errorHandling","composeErrorHandler","locationOptions","location","addressInline","baseMetadata","useDeriveFieldsMetadata","fieldsMetadata","withOptions","onSubmit","callbacks","options","submitResult","resolve","data","payload","resolvedEmployeeId","SDKInternalError","resolvedEffectiveDate","effectiveDateParam","RFCDate","updatedWorkAddress","result","hookFormInternals","useHookFormInternals","isDataLoading","LocationField","EffectiveDateField","createGetFormSubmissionValues"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useWorkAddressForm.js","sources":["../../../../../../src/components/Employee/Profile/shared/useWorkAddressForm/useWorkAddressForm.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useForm } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport type { Location } from '@gusto/embedded-api-v-2025-11-15/models/components/location'\nimport type { EmployeeWorkAddress } from '@gusto/embedded-api-v-2025-11-15/models/components/employeeworkaddress'\nimport { useLocationsGet } from '@gusto/embedded-api-v-2025-11-15/react-query/locationsGet'\nimport { useEmployeeAddressesRetrieveWorkAddress } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesRetrieveWorkAddress'\nimport { useEmployeeAddressesCreateWorkAddressMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesCreateWorkAddress'\nimport { useEmployeeAddressesUpdateWorkAddressMutation } from '@gusto/embedded-api-v-2025-11-15/react-query/employeeAddressesUpdateWorkAddress'\nimport { RFCDate } from '@gusto/embedded-api-v-2025-11-15/types/rfcdate'\nimport {\n createWorkAddressSchema,\n type WorkAddressOptionalFieldsToRequire,\n type WorkAddressFormData,\n type WorkAddressFormOutputs,\n} from './workAddressSchema'\nimport { LocationField, EffectiveDateField } from './fields'\nimport { useDeriveFieldsMetadata } from '@/partner-hook-utils/form/useDeriveFieldsMetadata'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport { withOptions } from '@/partner-hook-utils/form/withOptions'\nimport { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldsMetadata,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\nimport { addressInline } from '@/helpers/formattedStrings'\n\nexport type { WorkAddressOptionalFieldsToRequire } from './workAddressSchema'\n\n/**\n * Optional callbacks passed to {@link UseWorkAddressFormReady.actions.onSubmit | onSubmit}.\n *\n * @remarks\n * Only the callback matching the submit mode fires —\n * `onWorkAddressCreated` on create, `onWorkAddressUpdated` on update.\n *\n * @public\n */\nexport interface WorkAddressSubmitCallbacks {\n /** Fired after a new work address is successfully created. */\n onWorkAddressCreated?: (workAddress: EmployeeWorkAddress) => void\n /** Fired after an existing work address is successfully updated. */\n onWorkAddressUpdated?: (workAddress: EmployeeWorkAddress) => void\n}\n\n/**\n * Optional overrides passed to {@link UseWorkAddressFormReady.actions.onSubmit | onSubmit}.\n *\n * @public\n */\nexport interface WorkAddressSubmitOptions {\n /** Override the employee identifier supplied to the hook (e.g. after creating a new employee in the same flow). */\n employeeId?: string\n /** Override the effective date submitted with the address. */\n effectiveDate?: string\n}\n\n/**\n * Configuration options for {@link useWorkAddressForm}.\n *\n * @remarks\n * Presence or absence of `workAddressUuid` selects the API verb — see the\n * `workAddressUuid` field description. `companyId` is required to fetch\n * the location list; pass it when it is known.\n *\n * @public\n */\nexport interface UseWorkAddressFormProps {\n /** Company UUID for locations; omit or leave unset while resolving from the employee record. */\n companyId?: string\n /** UUID of the employee whose work address is being created or edited. */\n employeeId: string\n /**\n * When set, loads that work address via GET `/v1/work_addresses/{work_address_uuid}` and updates it (PUT).\n * When omitted, the form is in create mode (POST).\n */\n workAddressUuid?: string\n /**\n * Pre-loaded address matching `workAddressUuid`. When supplied, the form uses it directly\n * instead of issuing a GET — useful when the parent already has the row from a list query.\n */\n initialAddress?: EmployeeWorkAddress\n /** When `true`, renders `Fields.EffectiveDate`; otherwise it is `undefined`. Defaults to `true`. */\n withEffectiveDateField?: boolean\n /** Override fields that are optional on a given mode to be required. See `WorkAddressOptionalFieldsToRequire`. */\n optionalFieldsToRequire?: WorkAddressOptionalFieldsToRequire\n /** Pre-fill form values. Server data takes precedence on update. */\n defaultValues?: Partial<WorkAddressFormData>\n /** Passed through to react-hook-form. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Auto-focus the first invalid field on submit. Set to `false` when using `composeSubmitHandler` so submit-time focus is coordinated across multiple forms. Defaults to `true`. */\n shouldFocusError?: boolean\n}\n\n/**\n * Pre-bound field components exposed on `useWorkAddressForm().form.Fields`.\n *\n * @remarks\n * `EffectiveDate` is `undefined` when `withEffectiveDateField` is `false`.\n * Always null-check it before rendering.\n *\n * @public\n */\nexport interface WorkAddressFields {\n /** Location selector. Always available. */\n Location: typeof LocationField\n /** Effective-date picker. Only available when `withEffectiveDateField` is `true`. */\n EffectiveDate: typeof EffectiveDateField | undefined\n}\n\n/**\n * Ready-state shape returned by {@link useWorkAddressForm} once data has loaded.\n *\n * @remarks\n * Discriminated by `isLoading: false`. Extends {@link BaseFormHookReady} with\n * the work-address-specific `data`, `status`, `actions`, and `form.Fields` shape.\n *\n * @public\n */\nexport interface UseWorkAddressFormReady extends BaseFormHookReady<\n FieldsMetadata,\n WorkAddressFormData,\n WorkAddressFields\n> {\n /** Static entity data resolved from the API. */\n data: {\n /** The address row loaded for update; `null` in create mode. */\n workAddress: EmployeeWorkAddress | null\n /** Company locations available for selection; `undefined` until the locations query resolves. */\n companyLocations: Location[] | undefined\n }\n /** Reactive status flags. */\n status: { isPending: boolean; mode: 'create' | 'update' }\n /** Available actions. */\n actions: {\n onSubmit: (\n callbacks?: WorkAddressSubmitCallbacks,\n options?: WorkAddressSubmitOptions,\n ) => Promise<HookSubmitResult<EmployeeWorkAddress> | undefined>\n }\n}\n\n/**\n * Form hook for creating or editing an employee's work address.\n *\n * @remarks\n * When `workAddressUuid` is supplied the hook loads that address and issues a PUT on submit;\n * when omitted it operates in create mode and issues a POST. The hook requires `companyId`\n * to fetch the company's location list — it stays in loading state until `companyId` is known.\n *\n * @param props - See {@link UseWorkAddressFormProps}.\n * @returns A {@link HookLoadingResult} while loading, or a {@link UseWorkAddressFormReady} once ready.\n * @public\n *\n * @example\n * ```tsx\n * import {\n * useWorkAddressForm,\n * SDKFormProvider,\n * type UseWorkAddressFormReady,\n * } from '@gusto/embedded-react-sdk'\n *\n * function WorkAddressPage({ companyId, employeeId }: { companyId: string; employeeId: string }) {\n * const workAddress = useWorkAddressForm({ companyId, employeeId })\n *\n * if (workAddress.isLoading) return <div>Loading...</div>\n *\n * return <WorkAddressReady workAddress={workAddress} />\n * }\n *\n * function WorkAddressReady({ workAddress }: { workAddress: UseWorkAddressFormReady }) {\n * const { Fields } = workAddress.form\n *\n * return (\n * <SDKFormProvider formHookResult={workAddress}>\n * <form onSubmit={e => { e.preventDefault(); void workAddress.actions.onSubmit() }}>\n * <Fields.Location label=\"Work address\" />\n * {Fields.EffectiveDate && <Fields.EffectiveDate label=\"Effective date\" />}\n * <button type=\"submit\" disabled={workAddress.status.isPending}>Save</button>\n * </form>\n * </SDKFormProvider>\n * )\n * }\n * ```\n */\nexport function useWorkAddressForm({\n companyId,\n employeeId,\n workAddressUuid,\n initialAddress,\n withEffectiveDateField = true,\n optionalFieldsToRequire,\n defaultValues: partnerDefaults,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n}: UseWorkAddressFormProps): HookLoadingResult | UseWorkAddressFormReady {\n const locationsQuery = useLocationsGet({ companyId: companyId ?? '' }, { enabled: !!companyId })\n\n const hasInitialAddressMatch = !!workAddressUuid && initialAddress?.uuid === workAddressUuid\n\n const retrieveWorkAddressQuery = useEmployeeAddressesRetrieveWorkAddress(\n { workAddressUuid: workAddressUuid ?? '' },\n { enabled: !!workAddressUuid && !hasInitialAddressMatch },\n )\n\n const companyLocations = locationsQuery.data?.companyLocationsList\n\n const isCreateMode = !workAddressUuid\n\n const fetchedWorkAddress = workAddressUuid\n ? hasInitialAddressMatch\n ? initialAddress\n : retrieveWorkAddressQuery.data?.employeeWorkAddress\n : undefined\n\n const schemaMode = isCreateMode ? 'create' : 'update'\n\n const [schema, metadataConfig] = useMemo(\n () =>\n createWorkAddressSchema({\n mode: schemaMode,\n optionalFieldsToRequire,\n withEffectiveDateField,\n }),\n [schemaMode, optionalFieldsToRequire, withEffectiveDateField],\n )\n\n const resolvedDefaults: WorkAddressFormData = useMemo(\n () => ({\n locationUuid: fetchedWorkAddress?.locationUuid ?? partnerDefaults?.locationUuid ?? '',\n effectiveDate: fetchedWorkAddress?.effectiveDate ?? partnerDefaults?.effectiveDate ?? '',\n }),\n [fetchedWorkAddress, partnerDefaults],\n )\n\n const formMethods = useForm<WorkAddressFormData, unknown, WorkAddressFormOutputs>({\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n })\n\n const createWorkAddressMutation = useEmployeeAddressesCreateWorkAddressMutation()\n const updateWorkAddressMutation = useEmployeeAddressesUpdateWorkAddressMutation()\n\n const isPending = createWorkAddressMutation.isPending || updateWorkAddressMutation.isPending\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('WorkAddressForm')\n\n const queriesForErrors = [locationsQuery, ...(workAddressUuid ? [retrieveWorkAddressQuery] : [])]\n const errorHandling = composeErrorHandler(queriesForErrors, { submitError, setSubmitError })\n\n const locationOptions = (companyLocations ?? []).map(location => ({\n value: location.uuid,\n label: addressInline(location),\n }))\n\n const baseMetadata = useDeriveFieldsMetadata(metadataConfig, formMethods.control)\n const fieldsMetadata = {\n locationUuid: withOptions<Location>(\n baseMetadata.locationUuid,\n locationOptions,\n companyLocations ?? [],\n ),\n effectiveDate: baseMetadata.effectiveDate,\n }\n\n const onSubmit = async (\n callbacks?: WorkAddressSubmitCallbacks,\n options?: WorkAddressSubmitOptions,\n ): Promise<HookSubmitResult<EmployeeWorkAddress> | undefined> => {\n let submitResult: HookSubmitResult<EmployeeWorkAddress> | undefined\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async (data: WorkAddressFormOutputs) => {\n await baseSubmitHandler(data, async payload => {\n const resolvedEmployeeId = options?.employeeId ?? employeeId\n\n if (!resolvedEmployeeId) {\n throw new SDKInternalError('employeeId is required to submit work address')\n }\n\n const resolvedEffectiveDate =\n withEffectiveDateField && payload.effectiveDate\n ? payload.effectiveDate\n : options?.effectiveDate\n\n const effectiveDateParam = resolvedEffectiveDate\n ? new RFCDate(new Date(resolvedEffectiveDate))\n : undefined\n\n let updatedWorkAddress: EmployeeWorkAddress\n\n if (isCreateMode) {\n const result = await createWorkAddressMutation.mutateAsync({\n request: {\n employeeId: resolvedEmployeeId,\n requestBody: {\n locationUuid: payload.locationUuid,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeWorkAddress) {\n throw new SDKInternalError('Work address creation failed')\n }\n\n updatedWorkAddress = result.employeeWorkAddress\n callbacks?.onWorkAddressCreated?.(updatedWorkAddress)\n } else {\n if (!fetchedWorkAddress || !workAddressUuid) {\n throw new SDKInternalError(\n 'Cannot update work address: no matching address on file',\n )\n }\n\n const result = await updateWorkAddressMutation.mutateAsync({\n request: {\n workAddressUuid: fetchedWorkAddress.uuid,\n requestBody: {\n version: fetchedWorkAddress.version,\n locationUuid: payload.locationUuid,\n effectiveDate: effectiveDateParam,\n },\n },\n })\n\n if (!result.employeeWorkAddress) {\n throw new SDKInternalError('Work address update failed')\n }\n\n updatedWorkAddress = result.employeeWorkAddress\n callbacks?.onWorkAddressUpdated?.(updatedWorkAddress)\n }\n\n submitResult = {\n mode: isCreateMode ? 'create' : 'update',\n data: updatedWorkAddress,\n }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n const isDataLoading =\n (!!companyId && locationsQuery.isLoading) ||\n (!!workAddressUuid && retrieveWorkAddressQuery.isLoading)\n\n if (!companyId || isDataLoading || !companyLocations) {\n return { isLoading: true as const, errorHandling }\n }\n\n if (workAddressUuid && !fetchedWorkAddress) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n workAddress: fetchedWorkAddress ?? null,\n companyLocations,\n },\n status: {\n isPending,\n mode: isCreateMode ? ('create' as const) : ('update' as const),\n },\n actions: { onSubmit },\n errorHandling,\n form: {\n Fields: {\n Location: LocationField,\n EffectiveDate: withEffectiveDateField ? EffectiveDateField : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n },\n }\n}\n\n/**\n * Discriminated union returned by {@link useWorkAddressForm}.\n *\n * @public\n */\nexport type UseWorkAddressFormResult = HookLoadingResult | UseWorkAddressFormReady\n/**\n * Type of `form.fieldsMetadata` returned by {@link useWorkAddressForm}.\n *\n * @public\n */\nexport type WorkAddressFieldsMetadata = UseWorkAddressFormReady['form']['fieldsMetadata']\n/**\n * Type of `form.Fields` returned by {@link useWorkAddressForm}.\n *\n * @public\n */\nexport type WorkAddressFormFields = UseWorkAddressFormReady['form']['Fields']\n"],"names":["useWorkAddressForm","companyId","employeeId","workAddressUuid","initialAddress","withEffectiveDateField","optionalFieldsToRequire","partnerDefaults","validationMode","shouldFocusError","locationsQuery","useLocationsGet","hasInitialAddressMatch","retrieveWorkAddressQuery","useEmployeeAddressesRetrieveWorkAddress","companyLocations","isCreateMode","fetchedWorkAddress","schemaMode","schema","metadataConfig","useMemo","createWorkAddressSchema","resolvedDefaults","formMethods","useForm","zodResolver","createWorkAddressMutation","useEmployeeAddressesCreateWorkAddressMutation","updateWorkAddressMutation","useEmployeeAddressesUpdateWorkAddressMutation","isPending","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","queriesForErrors","errorHandling","composeErrorHandler","locationOptions","location","addressInline","baseMetadata","useDeriveFieldsMetadata","fieldsMetadata","withOptions","onSubmit","callbacks","options","submitResult","resolve","data","payload","resolvedEmployeeId","SDKInternalError","resolvedEffectiveDate","effectiveDateParam","RFCDate","updatedWorkAddress","result","hookFormInternals","useHookFormInternals","isDataLoading","LocationField","EffectiveDateField","createGetFormSubmissionValues"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workAddressSchema.js","sources":["../../../../../../src/components/Employee/Profile/shared/useWorkAddressForm/workAddressSchema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n buildFormSchema,\n type RequiredFieldConfig,\n type OptionalFieldsToRequire,\n} from '@/partner-hook-utils/form/buildFormSchema'\n\n// ── Error codes ────────────────────────────────────────────────────────\n\n/**\n * Validation error codes emitted by the work address form schema. Map these\n * codes to localized copy in `validationMessages` when composing the hook.\n *\n * @public\n */\nexport const WorkAddressErrorCodes = {\n REQUIRED: 'REQUIRED',\n} as const\n\n/**\n * Union of validation error code strings emitted by the work address form\n * schema.\n *\n * @public\n */\nexport type WorkAddressErrorCode =\n (typeof WorkAddressErrorCodes)[keyof typeof WorkAddressErrorCodes]\n\n// ── Field validators ───────────────────────────────────────────────────\n\nconst fieldValidators = {\n locationUuid: z.string().min(1, { message: WorkAddressErrorCodes.REQUIRED }),\n effectiveDate: z.iso.date({ error: () => WorkAddressErrorCodes.REQUIRED }),\n}\n\n/**\n * Field names accepted by the work address form.\n *\n * @public\n */\nexport type WorkAddressField = keyof typeof fieldValidators\n\n/**\n * Shape of the values managed by the work address form.\n *\n * @public\n */\nexport type WorkAddressFormData = {\n [K in keyof typeof fieldValidators]: z.infer<(typeof fieldValidators)[K]>\n}\n/**\n * Shape of the validated values produced by the work address form on submit.\n *\n * @public\n */\nexport type WorkAddressFormOutputs = WorkAddressFormData\n\n// ── Required fields config ─────────────────────────────────────────────\n\nconst requiredFieldsConfig = {} satisfies RequiredFieldConfig<typeof fieldValidators>\n\n// ── Schema factory ─────────────────────────────────────────────────────\n\n/**\n * Keys of optional work address fields that can be promoted to required via\n * the hook's `optionalFieldsToRequire` option.\n *\n * @public\n */\nexport type WorkAddressOptionalFieldsToRequire = OptionalFieldsToRequire<\n typeof requiredFieldsConfig\n>\n\n/** @internal */\ninterface WorkAddressSchemaOptions {\n mode?: 'create' | 'update'\n optionalFieldsToRequire?: WorkAddressOptionalFieldsToRequire\n withEffectiveDateField?: boolean\n}\n\n/** @internal */\nexport function createWorkAddressSchema(options: WorkAddressSchemaOptions = {}) {\n const { mode = 'create', optionalFieldsToRequire, withEffectiveDateField = true } = options\n\n return buildFormSchema(fieldValidators, {\n requiredFieldsConfig,\n requiredErrorCode: WorkAddressErrorCodes.REQUIRED,\n mode,\n optionalFieldsToRequire,\n excludeFields: withEffectiveDateField ? [] : ['effectiveDate'],\n })\n}\n"],"names":["WorkAddressErrorCodes","fieldValidators","z","requiredFieldsConfig","createWorkAddressSchema","options","mode","optionalFieldsToRequire","withEffectiveDateField","buildFormSchema"],"mappings":";;AAeO,MAAMA,IAAwB;AAAA,EACnC,UAAU;AACZ,GAaMC,IAAkB;AAAA,EACtB,cAAcC,EAAE,OAAA,EAAS,IAAI,GAAG,EAAE,SAASF,EAAsB,UAAU;AAAA,EAC3E,eAAeE,EAAE,IAAI,KAAK,EAAE,OAAO,MAAMF,EAAsB,SAAA,CAAU;AAC3E,
|
|
1
|
+
{"version":3,"file":"workAddressSchema.js","sources":["../../../../../../src/components/Employee/Profile/shared/useWorkAddressForm/workAddressSchema.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n buildFormSchema,\n type RequiredFieldConfig,\n type OptionalFieldsToRequire,\n} from '@/partner-hook-utils/form/buildFormSchema'\n\n// ── Error codes ────────────────────────────────────────────────────────\n\n/**\n * Validation error codes emitted by the work address form schema. Map these\n * codes to localized copy in `validationMessages` when composing the hook.\n *\n * @public\n */\nexport const WorkAddressErrorCodes = {\n REQUIRED: 'REQUIRED',\n} as const\n\n/**\n * Union of validation error code strings emitted by the work address form\n * schema.\n *\n * @public\n */\nexport type WorkAddressErrorCode =\n (typeof WorkAddressErrorCodes)[keyof typeof WorkAddressErrorCodes]\n\n// ── Field validators ───────────────────────────────────────────────────\n\nconst fieldValidators = {\n locationUuid: z.string().min(1, { message: WorkAddressErrorCodes.REQUIRED }),\n effectiveDate: z.iso.date({ error: () => WorkAddressErrorCodes.REQUIRED }),\n}\n\n/**\n * Field names accepted by the work address form.\n *\n * @public\n */\nexport type WorkAddressField = keyof typeof fieldValidators\n\n/**\n * Shape of the values managed by the work address form.\n *\n * @public\n * @interface\n */\nexport type WorkAddressFormData = {\n [K in keyof typeof fieldValidators]: z.infer<(typeof fieldValidators)[K]>\n}\n/**\n * Shape of the validated values produced by the work address form on submit.\n *\n * @public\n */\nexport type WorkAddressFormOutputs = WorkAddressFormData\n\n// ── Required fields config ─────────────────────────────────────────────\n\nconst requiredFieldsConfig = {} satisfies RequiredFieldConfig<typeof fieldValidators>\n\n// ── Schema factory ─────────────────────────────────────────────────────\n\n/**\n * Keys of optional work address fields that can be promoted to required via\n * the hook's `optionalFieldsToRequire` option.\n *\n * @public\n */\nexport type WorkAddressOptionalFieldsToRequire = OptionalFieldsToRequire<\n typeof requiredFieldsConfig\n>\n\n/** @internal */\ninterface WorkAddressSchemaOptions {\n mode?: 'create' | 'update'\n optionalFieldsToRequire?: WorkAddressOptionalFieldsToRequire\n withEffectiveDateField?: boolean\n}\n\n/** @internal */\nexport function createWorkAddressSchema(options: WorkAddressSchemaOptions = {}) {\n const { mode = 'create', optionalFieldsToRequire, withEffectiveDateField = true } = options\n\n return buildFormSchema(fieldValidators, {\n requiredFieldsConfig,\n requiredErrorCode: WorkAddressErrorCodes.REQUIRED,\n mode,\n optionalFieldsToRequire,\n excludeFields: withEffectiveDateField ? [] : ['effectiveDate'],\n })\n}\n"],"names":["WorkAddressErrorCodes","fieldValidators","z","requiredFieldsConfig","createWorkAddressSchema","options","mode","optionalFieldsToRequire","withEffectiveDateField","buildFormSchema"],"mappings":";;AAeO,MAAMA,IAAwB;AAAA,EACnC,UAAU;AACZ,GAaMC,IAAkB;AAAA,EACtB,cAAcC,EAAE,OAAA,EAAS,IAAI,GAAG,EAAE,SAASF,EAAsB,UAAU;AAAA,EAC3E,eAAeE,EAAE,IAAI,KAAK,EAAE,OAAO,MAAMF,EAAsB,SAAA,CAAU;AAC3E,GA2BMG,IAAuB,CAAA;AAsBtB,SAASC,EAAwBC,IAAoC,IAAI;AAC9E,QAAM,EAAE,MAAAC,IAAO,UAAU,yBAAAC,GAAyB,wBAAAC,IAAyB,OAASH;AAEpF,SAAOI,EAAgBR,GAAiB;AAAA,IACtC,sBAAAE;AAAA,IACA,mBAAmBH,EAAsB;AAAA,IACzC,MAAAM;AAAA,IACA,yBAAAC;AAAA,IACA,eAAeC,IAAyB,CAAA,IAAK,CAAC,eAAe;AAAA,EAAA,CAC9D;AACH;"}
|
|
@@ -6,9 +6,9 @@ export type { SelfOnboardingFlowProps } from './SelfOnboardingComponents';
|
|
|
6
6
|
* @remarks
|
|
7
7
|
* Hands the employee responsibility for submitting their own profile, tax, payment, and document-signing information. Drives a multi-step flow keyed to the employee being self-onboarded; when `withEmployeeI9` is enabled, the Document Signer step checks whether the employee has I-9 enabled and, if so, routes them through the employment-eligibility form before presenting the I-9 form alongside other required documents.
|
|
8
8
|
*
|
|
9
|
-
* Each step is also exported as a standalone block (see the
|
|
9
|
+
* Each step is also exported as a standalone block (see the Blocks table) for composing a custom workflow when this orchestration is the wrong fit.
|
|
10
10
|
*
|
|
11
|
-
* The flow forwards every event emitted by its
|
|
11
|
+
* The flow forwards every event emitted by its blocks to `onEvent`; see the events table on each block for the full set of events and payloads observable from this flow.
|
|
12
12
|
*
|
|
13
13
|
* @components
|
|
14
14
|
* - {@link Landing}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelfOnboardingFlow.js","sources":["../../../../src/components/Employee/SelfOnboardingFlow/SelfOnboardingFlow.tsx"],"sourcesContent":["import { createMachine } from 'robot3'\nimport { useMemo } from 'react'\nimport type {\n SelfOnboardingContextInterface,\n SelfOnboardingFlowProps,\n} from './SelfOnboardingComponents'\nimport { Landing } from './SelfOnboardingComponents'\nimport { employeeSelfOnboardingMachine } from './selfOnboardingMachine'\nimport { Flow } from '@/components/Flow/Flow'\n\nexport type { SelfOnboardingFlowProps } from './SelfOnboardingComponents'\n\n/**\n * Guided flow for employees to complete their own onboarding.\n *\n * @remarks\n * Hands the employee responsibility for submitting their own profile, tax, payment, and document-signing information. Drives a multi-step flow keyed to the employee being self-onboarded; when `withEmployeeI9` is enabled, the Document Signer step checks whether the employee has I-9 enabled and, if so, routes them through the employment-eligibility form before presenting the I-9 form alongside other required documents.\n *\n * Each step is also exported as a standalone block (see the
|
|
1
|
+
{"version":3,"file":"SelfOnboardingFlow.js","sources":["../../../../src/components/Employee/SelfOnboardingFlow/SelfOnboardingFlow.tsx"],"sourcesContent":["import { createMachine } from 'robot3'\nimport { useMemo } from 'react'\nimport type {\n SelfOnboardingContextInterface,\n SelfOnboardingFlowProps,\n} from './SelfOnboardingComponents'\nimport { Landing } from './SelfOnboardingComponents'\nimport { employeeSelfOnboardingMachine } from './selfOnboardingMachine'\nimport { Flow } from '@/components/Flow/Flow'\n\nexport type { SelfOnboardingFlowProps } from './SelfOnboardingComponents'\n\n/**\n * Guided flow for employees to complete their own onboarding.\n *\n * @remarks\n * Hands the employee responsibility for submitting their own profile, tax, payment, and document-signing information. Drives a multi-step flow keyed to the employee being self-onboarded; when `withEmployeeI9` is enabled, the Document Signer step checks whether the employee has I-9 enabled and, if so, routes them through the employment-eligibility form before presenting the I-9 form alongside other required documents.\n *\n * Each step is also exported as a standalone block (see the Blocks table) for composing a custom workflow when this orchestration is the wrong fit.\n *\n * The flow forwards every event emitted by its blocks to `onEvent`; see the events table on each block for the full set of events and payloads observable from this flow.\n *\n * @components\n * - {@link Landing}\n * - {@link Profile}\n * - {@link FederalTaxes}\n * - {@link StateTaxes}\n * - {@link PaymentMethod}\n * - {@link DocumentSigner}\n * - {@link OnboardingSummary}\n *\n * @param props - See {@link SelfOnboardingFlowProps}.\n * @returns The multi-step self-onboarding flow.\n * @public\n * @group Flow Components\n *\n * @example\n * ```tsx title=\"App.tsx\"\n * import { EmployeeOnboarding, type EventType } from '@gusto/embedded-react-sdk'\n *\n * function MyApp() {\n * return (\n * <EmployeeOnboarding.SelfOnboardingFlow\n * companyId=\"a007e1ab-3595-43c2-ab4b-af7a5af2e365\"\n * employeeId=\"4b3f930f-82cd-48a8-b797-798686e12e5e\"\n * withEmployeeI9\n * onEvent={(eventType: EventType) => {\n * if (eventType === 'employee/onboarding/done') {\n * // Onboarding complete — navigate to your next screen\n * }\n * }}\n * />\n * )\n * }\n * ```\n */\nexport const SelfOnboardingFlow = ({\n companyId,\n employeeId,\n withEmployeeI9 = false,\n onEvent,\n}: SelfOnboardingFlowProps) => {\n const manageEmployees = useMemo(\n () =>\n createMachine(\n 'index',\n employeeSelfOnboardingMachine,\n (initialContext: SelfOnboardingContextInterface) => ({\n ...initialContext,\n component: Landing,\n companyId,\n employeeId,\n withEmployeeI9,\n }),\n ),\n [companyId, employeeId, withEmployeeI9],\n )\n return <Flow machine={manageEmployees} onEvent={onEvent} />\n}\n"],"names":["SelfOnboardingFlow","companyId","employeeId","withEmployeeI9","onEvent","manageEmployees","useMemo","createMachine","employeeSelfOnboardingMachine","initialContext","Landing","jsx","Flow"],"mappings":";;;;;;AAwDO,MAAMA,IAAqB,CAAC;AAAA,EACjC,WAAAC;AAAA,EACA,YAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,SAAAC;AACF,MAA+B;AAC7B,QAAMC,IAAkBC;AAAA,IACtB,MACEC;AAAA,MACE;AAAA,MACAC;AAAA,MACA,CAACC,OAAoD;AAAA,QACnD,GAAGA;AAAA,QACH,WAAWC;AAAA,QACX,WAAAT;AAAA,QACA,YAAAC;AAAA,QACA,gBAAAC;AAAA,MAAA;AAAA,IACF;AAAA,IAEJ,CAACF,GAAWC,GAAYC,CAAc;AAAA,EAAA;AAExC,SAAO,gBAAAQ,EAACC,GAAA,EAAK,SAASP,GAAiB,SAAAD,EAAA,CAAkB;AAC3D;"}
|