@gusto/embedded-react-sdk 0.57.2 → 0.57.3
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 +20 -0
- package/dist/components/Common/DateRangeFilter/DateRangeFilter.js +32 -32
- package/dist/components/Common/DateRangeFilter/DateRangeFilter.js.map +1 -1
- package/dist/components/Common/OnboardingStatusBadge/index.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/AutoPilotDialog/AutoPilotDialog.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/AutoPilotDialog/useAutoPilotDialog.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentCompensationStepPresentation.js +34 -14
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentCompensationStepPresentation.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentDepartmentStepPresentation.js +106 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentDepartmentStepPresentation.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentEmployeeStepPresentation.js +136 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentEmployeeStepPresentation.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentScheduleStepPresentation.js +38 -20
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentScheduleStepPresentation.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentTypeStepPresentation.js +78 -44
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentTypeStepPresentation.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/PayScheduleAssignment.js +45 -37
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/PayScheduleAssignment.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/PayScheduleAssignmentComponents.js +244 -95
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/PayScheduleAssignmentComponents.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/departmentAccess.js +22 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/departmentAccess.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/employeeJob.js +13 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/employeeJob.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/payScheduleAssignmentStateMachine.js +48 -43
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/payScheduleAssignmentStateMachine.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/scheduleLabel.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/useAssignableEmployees.js +57 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleAssignment/useAssignableEmployees.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleCompensationOverviewPresentation.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleDepartmentOverviewPresentation.js +83 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleDepartmentOverviewPresentation.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleEmployeeOverviewPresentation.js +84 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleEmployeeOverviewPresentation.js.map +1 -0
- package/dist/components/Company/PaySchedule/management/PayScheduleManagementComponents.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleOverview.js +109 -39
- package/dist/components/Company/PaySchedule/management/PayScheduleOverview.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/PayScheduleOverviewPresentation.js.map +1 -1
- package/dist/components/Company/PaySchedule/management/payScheduleManagementStateMachine.js.map +1 -1
- package/dist/components/Company/PaySchedule/shared/usePayScheduleForm/usePayScheduleForm.js.map +1 -1
- package/dist/components/Contractor/Address/shared/useContractorAddressForm/useContractorAddressForm.js +5 -5
- package/dist/components/Contractor/Address/shared/useContractorAddressForm/useContractorAddressForm.js.map +1 -1
- package/dist/components/Contractor/Address/shared/useContractorAddressSummary/useContractorAddressSummary.js +1 -1
- package/dist/components/Contractor/Address/shared/useContractorAddressSummary/useContractorAddressSummary.js.map +1 -1
- package/dist/components/Contractor/Compensation/shared/useContractorCompensationSummary/useContractorCompensationSummary.js +4 -4
- package/dist/components/Contractor/Compensation/shared/useContractorCompensationSummary/useContractorCompensationSummary.js.map +1 -1
- package/dist/components/Contractor/Compensation/shared/useContractorPayForm/useContractorPayForm.js +3 -3
- package/dist/components/Contractor/Compensation/shared/useContractorPayForm/useContractorPayForm.js.map +1 -1
- package/dist/components/Contractor/ContractorList/shared/useContractorList.js +6 -6
- package/dist/components/Contractor/ContractorList/shared/useContractorList.js.map +1 -1
- package/dist/components/Contractor/Dashboard/Dashboard.js +20 -20
- package/dist/components/Contractor/Dashboard/Dashboard.js.map +1 -1
- package/dist/components/Contractor/Dismissal/useDismissal/useDismissal.js +10 -10
- package/dist/components/Contractor/Dismissal/useDismissal/useDismissal.js.map +1 -1
- package/dist/components/Contractor/Landing/Landing.js +43 -39
- package/dist/components/Contractor/Landing/Landing.js.map +1 -1
- package/dist/components/Contractor/NewHireReport/NewHireReport.js +3 -3
- package/dist/components/Contractor/NewHireReport/NewHireReport.js.map +1 -1
- package/dist/components/Contractor/Payments/CreateHistoricalPayment/CreateHistoricalPayment.js +1 -1
- package/dist/components/Contractor/Payments/CreateHistoricalPayment/CreateHistoricalPayment.js.map +1 -1
- package/dist/components/Contractor/Payments/CreatePayment/CreatePayment.js +10 -10
- package/dist/components/Contractor/Payments/CreatePayment/CreatePayment.js.map +1 -1
- package/dist/components/Contractor/Payments/HistoricalPaymentSummary/HistoricalPaymentSummary.js +4 -4
- package/dist/components/Contractor/Payments/HistoricalPaymentSummary/HistoricalPaymentSummary.js.map +1 -1
- package/dist/components/Contractor/Payments/PaymentHistory/PaymentHistory.js +8 -8
- package/dist/components/Contractor/Payments/PaymentHistory/PaymentHistory.js.map +1 -1
- package/dist/components/Contractor/Payments/PaymentStatement/PaymentStatement.js +5 -5
- package/dist/components/Contractor/Payments/PaymentStatement/PaymentStatement.js.map +1 -1
- package/dist/components/Contractor/Payments/PaymentSummary/PaymentSummary.js +3 -3
- package/dist/components/Contractor/Payments/PaymentSummary/PaymentSummary.js.map +1 -1
- package/dist/components/Contractor/Profile/onboarding/SelfOnboardingContractorProfile.js +1 -1
- package/dist/components/Contractor/Profile/onboarding/SelfOnboardingContractorProfile.js.map +1 -1
- package/dist/components/Contractor/Profile/shared/useContractorDetailsForm/useContractorDetailsForm.js +1 -1
- package/dist/components/Contractor/Profile/shared/useContractorDetailsForm/useContractorDetailsForm.js.map +1 -1
- package/dist/components/Contractor/Profile/shared/useContractorProfileSummary/useContractorProfileSummary.js +1 -1
- package/dist/components/Contractor/Profile/shared/useContractorProfileSummary/useContractorProfileSummary.js.map +1 -1
- package/dist/components/Contractor/SelfOnboardingFlow/SelfOnboardingComponents.js +2 -9
- package/dist/components/Contractor/SelfOnboardingFlow/SelfOnboardingComponents.js.map +1 -1
- package/dist/components/Contractor/Submit/Submit.js +18 -18
- package/dist/components/Contractor/Submit/Submit.js.map +1 -1
- package/dist/components/Contractor/shared/SelectContractors/useSelectContractors.js +6 -6
- package/dist/components/Contractor/shared/SelectContractors/useSelectContractors.js.map +1 -1
- package/dist/components/Employee/Compensation/shared/useCompensationForm/useCompensationForm.js +25 -25
- package/dist/components/Employee/Compensation/shared/useCompensationForm/useCompensationForm.js.map +1 -1
- package/dist/components/Employee/Compensation/shared/useCompensationManagement/useCompensationManagement.js +15 -15
- package/dist/components/Employee/Compensation/shared/useCompensationManagement/useCompensationManagement.js.map +1 -1
- package/dist/components/Employee/Compensation/shared/useJobForm/useJobForm.js +1 -1
- package/dist/components/Employee/Compensation/shared/useJobForm/useJobForm.js.map +1 -1
- package/dist/components/Employee/Dashboard/Dashboard.js +25 -25
- package/dist/components/Employee/Dashboard/Dashboard.js.map +1 -1
- package/dist/components/Employee/Documents/onboarding/DocumentSigner/DocumentSigner.js +7 -7
- package/dist/components/Employee/Documents/onboarding/DocumentSigner/DocumentSigner.js.map +1 -1
- package/dist/components/Employee/Documents/onboarding/EmployeeDocuments/EmployeeDocuments.js +1 -1
- package/dist/components/Employee/Documents/onboarding/EmployeeDocuments/EmployeeDocuments.js.map +1 -1
- package/dist/components/Employee/HomeAddress/management/useHomeAddressManagement.js +6 -6
- package/dist/components/Employee/HomeAddress/management/useHomeAddressManagement.js.map +1 -1
- package/dist/components/Employee/Landing/Landing.js +37 -33
- package/dist/components/Employee/Landing/Landing.js.map +1 -1
- package/dist/components/Employee/OnboardingSummary/OnboardingSummary.js +27 -27
- package/dist/components/Employee/OnboardingSummary/OnboardingSummary.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.js +6 -6
- package/dist/components/Employee/Profile/shared/useEmployeeDetailsForm/useEmployeeDetailsForm.js.map +1 -1
- package/dist/components/Employee/Profile/shared/useEmployeeProfileSummary/useEmployeeProfileSummary.js +1 -1
- package/dist/components/Employee/Profile/shared/useEmployeeProfileSummary/useEmployeeProfileSummary.js.map +1 -1
- package/dist/components/Employee/SelfOnboardingFlow/SelfOnboardingComponents.js +8 -15
- package/dist/components/Employee/SelfOnboardingFlow/SelfOnboardingComponents.js.map +1 -1
- package/dist/components/Employee/Terminations/TerminateEmployee/TerminateEmployee.js +11 -11
- package/dist/components/Employee/Terminations/TerminateEmployee/TerminateEmployee.js.map +1 -1
- package/dist/components/Employee/Terminations/TerminationSummary/TerminationSummary.js +12 -12
- package/dist/components/Employee/Terminations/TerminationSummary/TerminationSummary.js.map +1 -1
- package/dist/components/Employee/WorkAddress/management/useWorkAddressManagement.js +26 -26
- package/dist/components/Employee/WorkAddress/management/useWorkAddressManagement.js.map +1 -1
- package/dist/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.js +66 -64
- package/dist/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.js.map +1 -1
- package/dist/components/Payroll/PayrollConfiguration/usePayrollConfigurationData.js +1 -1
- package/dist/components/Payroll/PayrollConfiguration/usePayrollConfigurationData.js.map +1 -1
- package/dist/components/Payroll/PayrollEditEmployee/PayrollEditEmployee.js +6 -6
- package/dist/components/Payroll/PayrollEditEmployee/PayrollEditEmployee.js.map +1 -1
- package/dist/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.js.map +1 -1
- package/dist/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.js +1 -1
- package/dist/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.js.map +1 -1
- package/dist/components/Payroll/PayrollHistory/PayrollHistory.js.map +1 -1
- package/dist/components/Payroll/PayrollHistory/PayrollHistoryPresentation.js +6 -6
- package/dist/components/Payroll/PayrollHistory/PayrollHistoryPresentation.js.map +1 -1
- package/dist/components/Payroll/PayrollList/PayrollList.js.map +1 -1
- package/dist/components/Payroll/PayrollList/PayrollListPresentation.js +9 -9
- package/dist/components/Payroll/PayrollList/PayrollListPresentation.js.map +1 -1
- package/dist/components/Payroll/PayrollOverview/PayrollOverviewPresentation.js.map +1 -1
- package/dist/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.js.map +1 -1
- package/dist/components/Payroll/helpers.js +1 -1
- package/dist/components/Payroll/helpers.js.map +1 -1
- package/dist/components/Payroll/payrollTypes.js +1 -1
- package/dist/components/Payroll/payrollTypes.js.map +1 -1
- package/dist/components/Payroll/usePreparedPayrollData.js.map +1 -1
- package/dist/contexts/ApiProvider/payrollOffCycleReasonEnumHook.js +1 -1
- package/dist/contexts/ApiProvider/payrollOffCycleReasonEnumHook.js.map +1 -1
- package/dist/i18n/en/Company.Management.PaySchedule.json.js +31 -13
- package/dist/i18n/en/Company.Management.PaySchedule.json.js.map +1 -1
- package/dist/i18n/en/Company.Management.PayScheduleAssignment.json.js +20 -12
- package/dist/i18n/en/Company.Management.PayScheduleAssignment.json.js.map +1 -1
- package/dist/i18n/en/Payroll.PayrollHistory.json.js +1 -1
- package/dist/i18n/en/Payroll.PayrollList.json.js +5 -5
- package/dist/package.json.js +1 -1
- package/dist/shared/constants.js +5 -5
- package/dist/shared/constants.js.map +1 -1
- package/dist/src/components/Common/DateRangeFilter/DateRangeFilter.d.ts +2 -2
- package/dist/src/components/Common/OnboardingStatusBadge/index.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/management/AutoPilotDialog/AutoPilotDialog.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/management/AutoPilotDialog/useAutoPilotDialog.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentCompensationStepPresentation.d.ts +10 -3
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentDepartmentStepPresentation.d.ts +21 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentEmployeeStepPresentation.d.ts +34 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentScheduleStepPresentation.d.ts +9 -3
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/AssignmentTypeStepPresentation.d.ts +5 -1
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/PayScheduleAssignment.d.ts +10 -10
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/PayScheduleAssignmentComponents.d.ts +12 -4
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/departmentAccess.d.ts +19 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/employeeJob.d.ts +17 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/scheduleLabel.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/useAssignableEmployees.d.ts +34 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleAssignment/usePayScheduleAssignment.d.ts +16 -3
- package/dist/src/components/Company/PaySchedule/management/PayScheduleCompensationOverviewPresentation.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/management/PayScheduleDepartmentOverviewPresentation.d.ts +23 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleEmployeeOverviewPresentation.d.ts +25 -0
- package/dist/src/components/Company/PaySchedule/management/PayScheduleManagementComponents.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/management/PayScheduleOverviewPresentation.d.ts +1 -1
- package/dist/src/components/Company/PaySchedule/shared/usePayScheduleForm/usePayScheduleForm.d.ts +1 -1
- package/dist/src/components/Contractor/Landing/Landing.d.ts +5 -2
- package/dist/src/components/Employee/Landing/Landing.d.ts +5 -2
- package/dist/src/components/Payroll/PayrollConfiguration/PayrollConfigurationPresentation.d.ts +1 -1
- package/dist/src/components/Payroll/PayrollConfiguration/usePayrollConfigurationData.d.ts +1 -1
- package/dist/src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.d.ts +1 -1
- package/dist/src/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.d.ts +2 -2
- package/dist/src/components/Payroll/PayrollHistory/PayrollHistoryPresentation.d.ts +1 -1
- package/dist/src/components/Payroll/PayrollList/PayrollListPresentation.d.ts +2 -2
- package/dist/src/components/Payroll/PayrollOverview/PayrollOverviewPresentation.d.ts +1 -1
- package/dist/src/components/Payroll/helpers.d.ts +2 -2
- package/dist/src/components/Payroll/usePreparedPayrollData.d.ts +2 -2
- package/dist/src/i18n/types.d.ts +82 -4
- package/dist/src/models/external.d.ts +63 -48
- package/dist/src/shared/constants.d.ts +1 -1
- package/docs/guides/endpoint-inventory.json +33 -13
- package/package.json +18 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PayrollEditEmployeePresentation.js","sources":["../../../../src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.tsx"],"sourcesContent":["import { FormProvider, useFieldArray, useForm, useWatch } from 'react-hook-form'\nimport { useMemo, useRef, useState } from 'react'\nimport classNames from 'classnames'\nimport type { Employee } from '@gusto/embedded-api/models/components/employee'\nimport type {\n FixedCompensations,\n PayrollEmployeeCompensationsType,\n PayrollEmployeeCompensationsTypePaidTimeOff,\n Reimbursements as Reimbursement,\n} from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport { PayrollEmployeeCompensationsTypePaymentMethod } from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport type { PayrollFixedCompensationTypesType } from '@gusto/embedded-api/models/components/payrollfixedcompensationtypestype'\nimport type { PayScheduleShow as PayScheduleObject } from '@gusto/embedded-api/models/components/payscheduleshow'\nimport { useTranslation } from 'react-i18next'\nimport { z } from 'zod'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport styles from './PayrollEditEmployeePresentation.module.scss'\nimport { TimeOffField, PayoutTimeOffField } from './TimeOffField'\nimport {\n Flex,\n Grid,\n TextInputField,\n RadioGroupField,\n DataView,\n useDataView,\n EmptyData,\n} from '@/components/Common'\nimport { useComponentContext } from '@/contexts/ComponentAdapter/useComponentContext'\nimport { useI18n } from '@/i18n'\nimport { Form } from '@/components/Common/Form'\nimport {\n formatNumberAsCurrency,\n firstLastName,\n stripLeadingZeros,\n} from '@/helpers/formattedStrings'\nimport { getAdditionalEarningsCompensations, calculateGrossPay } from '@/components/Payroll/helpers'\nimport { PayrollCategory, isOffCyclePayroll } from '@/components/Payroll/payrollTypes'\nimport {\n COMPENSATION_NAME_DOUBLE_OVERTIME,\n COMPENSATION_NAME_OVERTIME,\n COMPENSATION_NAME_REGULAR_HOURS,\n HOURS_COMPENSATION_NAMES,\n EXCLUDED_ADDITIONAL_EARNINGS,\n COMPENSATION_NAME_REIMBURSEMENT,\n COMPENSATION_NAME_BONUS,\n COMPENSATION_NAME_PAYCHECK_TIPS,\n COMPENSATION_NAME_CORRECTION_PAYMENT,\n COMPENSATION_NAME_COMMISSION,\n COMPENSATION_NAME_CASH_TIPS,\n} from '@/shared/constants'\nimport useContainerBreakpoints from '@/hooks/useContainerBreakpoints/useContainerBreakpoints'\nimport PlusCircleIcon from '@/assets/icons/plus-circle.svg?react'\nimport TrashCanSvg from '@/assets/icons/trashcan.svg?react'\n\ninterface PayrollEditEmployeeProps {\n /** CSS class name applied to the root element. */\n className?: string\n onSave: (updatedCompensation: PayrollEmployeeCompensationsType) => void\n onCancel: () => void\n employee: Employee\n employeeCompensation?: PayrollEmployeeCompensationsType\n isPending?: boolean\n fixedCompensationTypes: PayrollFixedCompensationTypesType[]\n payPeriodStartDate?: string\n paySchedule?: PayScheduleObject\n payrollCategory?: PayrollCategory\n withReimbursements?: boolean\n hasDirectDepositSetup?: boolean\n}\n\nconst ReimbursementFormSchema = z.object({\n uuid: z.string().nullable().optional(),\n description: z.string(),\n amount: z.string(),\n recurring: z.boolean().optional(),\n})\n\n// Mirrors the server's fixed reimbursement cap (payroll_core_data's\n// Reimbursements::MAX_AMOUNT) so an over-limit value is caught inline instead\n// of round-tripping to a 422.\nconst MAX_REIMBURSEMENT_AMOUNT = 1_000_000\n\nconst DraftReimbursementSchema = z.object({\n description: z.string(),\n amount: z\n .string()\n .refine(\n val => {\n const num = parseFloat(val)\n return !Number.isNaN(num) && num > 0\n },\n { message: 'validations.reimbursementAmount' },\n )\n .refine(val => parseFloat(val) <= MAX_REIMBURSEMENT_AMOUNT, {\n message: 'validations.maxReimbursementAmount',\n }),\n})\n\n// A native `min={0}` only constrains the stepper: it does not stop a typed \"-50\", and the\n// SDK's <form> is noValidate so the browser never enforces it either. Negative amounts\n// therefore reached the platform and came back only as a submit-time error (SDK-1285).\n// Applied via z.record below, this covers every additional earning -- correction payment\n// included -- because they all share the fixedCompensations record.\nconst nonNegativeAmountSchema = z\n .string()\n .optional()\n .refine(val => !val || parseFloat(val) >= 0, { message: 'validations.negativeAmount' })\n\n// Mirrors the server's fixed hours cap (draft_payrolls' MAX_HOURS) so an\n// over-limit value is caught inline instead of round-tripping to a 422.\nconst MAX_HOURS = 99_999\n\nconst hoursAmountSchema = z\n .string()\n .optional()\n .refine(val => !val || parseFloat(val) <= MAX_HOURS, { message: 'validations.maxHours' })\n\nconst PayrollEditEmployeeFormSchema = z.object({\n hourlyCompensations: z.record(z.string(), z.record(z.string(), hoursAmountSchema)),\n timeOffCompensations: z.record(z.string(), z.string().optional()),\n finalPayoutCompensations: z.record(z.string(), z.string().optional()),\n fixedCompensations: z.record(z.string(), nonNegativeAmountSchema),\n reimbursements: z.array(ReimbursementFormSchema),\n paymentMethod: z.enum(PayrollEmployeeCompensationsTypePaymentMethod).optional(),\n})\n\n/** @internal */\nexport type PayrollEditEmployeeFormValues = z.infer<typeof PayrollEditEmployeeFormSchema>\n\nconst buildCompensationFromFormData = (\n formData: PayrollEditEmployeeFormValues,\n employeeCompensation: PayrollEmployeeCompensationsType | undefined,\n timeOff: PayrollEmployeeCompensationsTypePaidTimeOff[],\n primaryJobUuid?: string,\n payrollCategory: PayrollCategory = PayrollCategory.Regular,\n): PayrollEmployeeCompensationsType => {\n const updatedCompensation = {\n ...employeeCompensation,\n paymentMethod: formData.paymentMethod,\n }\n\n updatedCompensation.hourlyCompensations = employeeCompensation?.hourlyCompensations?.map(\n compensation => {\n const hours =\n compensation.jobUuid && compensation.name\n ? formData.hourlyCompensations[compensation.jobUuid]?.[compensation.name]\n : undefined\n return hours\n ? {\n ...compensation,\n hours,\n }\n : compensation\n },\n )\n\n updatedCompensation.paidTimeOff = timeOff.map(timeOffEntry => {\n const isDismissal = payrollCategory === PayrollCategory.Dismissal\n const { finalPayoutUnusedHoursInput: _, ...timeOffWithoutPayout } = timeOffEntry\n\n if (isDismissal) {\n const finalPayout =\n formData.finalPayoutCompensations[timeOffEntry.name!] ??\n timeOffEntry.finalPayoutUnusedHoursInput\n return {\n ...timeOffEntry,\n hours: formData.timeOffCompensations[timeOffEntry.name!] || '0',\n ...(finalPayout != null ? { finalPayoutUnusedHoursInput: finalPayout || '0' } : {}),\n }\n }\n\n return {\n ...timeOffWithoutPayout,\n hours: formData.timeOffCompensations[timeOffEntry.name!] || '0',\n }\n })\n\n // Off-cycle payrolls today use the legacy single Reimbursement field in fixed_compensations\n // because the backend feature flag `emb_off_cycle_disable_named_reimbursements` (default: true,\n // expected removal 2026-09-01) rejects named entries in the itemized `reimbursements[]` array.\n // TODO(post-2026-09-01): once that flag is removed, unify on the itemized path for all categories.\n const usesItemizedReimbursements = !isOffCyclePayroll(payrollCategory)\n\n const updatedFixedCompensations: FixedCompensations[] = []\n\n Object.entries(formData.fixedCompensations).forEach(([fixedCompensationName, formAmount]) => {\n const isReimbursementEntry =\n fixedCompensationName.toLowerCase() === COMPENSATION_NAME_REIMBURSEMENT.toLowerCase()\n\n // Regular payrolls write reimbursements via the itemized array; never let the legacy\n // fixed_compensations entry slip through (the backend rejects it on v2025-11-15+).\n if (isReimbursementEntry && usesItemizedReimbursements) {\n return\n }\n\n const existingFixedCompensation = employeeCompensation?.fixedCompensations?.find(\n fixedCompensation =>\n fixedCompensation.name?.toLowerCase() === fixedCompensationName.toLowerCase(),\n )\n\n // Clearing the field means \"no additional earning\". For an entry that already has a\n // saved amount we have to send an explicit 0: omitting it leaves the previously saved\n // value in place server-side, so the box looked empty while the old amount survived\n // the save (SDK-1284). This makes clearing behave exactly like typing 0. An entry with\n // no saved compensation stays omitted -- there is nothing to zero out.\n const resolvedAmount = formAmount === '' && existingFixedCompensation ? '0' : formAmount\n\n if (resolvedAmount !== undefined && resolvedAmount !== '') {\n if (existingFixedCompensation) {\n updatedFixedCompensations.push({\n name: existingFixedCompensation.name,\n jobUuid: existingFixedCompensation.jobUuid,\n amount: resolvedAmount,\n })\n } else if (parseFloat(resolvedAmount) !== 0) {\n updatedFixedCompensations.push({\n name: fixedCompensationName,\n jobUuid: primaryJobUuid,\n amount: resolvedAmount,\n })\n }\n }\n })\n\n updatedCompensation.fixedCompensations = updatedFixedCompensations\n\n if (usesItemizedReimbursements) {\n updatedCompensation.reimbursements = formData.reimbursements.map(reimbursement => ({\n amount: reimbursement.amount,\n description:\n reimbursement.description.trim() === '' ? null : reimbursement.description.trim(),\n uuid: reimbursement.uuid ?? null,\n recurring: reimbursement.recurring,\n }))\n } else {\n // Off-cycle: ensure no itemized array leaks through. The container also strips this defensively.\n updatedCompensation.reimbursements = []\n }\n\n return updatedCompensation\n}\n\n/** @internal */\nexport const PayrollEditEmployeePresentation = ({\n className,\n onSave,\n onCancel,\n employee,\n employeeCompensation,\n isPending = false,\n fixedCompensationTypes,\n payPeriodStartDate,\n paySchedule,\n payrollCategory = PayrollCategory.Regular,\n withReimbursements = true,\n hasDirectDepositSetup = true,\n}: PayrollEditEmployeeProps) => {\n const { Button, ButtonIcon, Heading, Text } = useComponentContext()\n\n const { t } = useTranslation('Payroll.PayrollEditEmployee')\n useI18n('Payroll.PayrollEditEmployee')\n\n const primaryJob = employee.jobs?.find(job => job.primary)\n const primaryJobHasHourlyCompensations = employeeCompensation?.hourlyCompensations?.some(\n c => c.jobUuid === primaryJob?.uuid,\n )\n const hourlyJobs = primaryJob && primaryJobHasHourlyCompensations ? [primaryJob] : []\n\n const containerRef = useRef<HTMLDivElement>(null)\n const breakpoints = useContainerBreakpoints({\n ref: containerRef,\n })\n const isSmallOrGreater = breakpoints.includes('small')\n\n employeeCompensation?.hourlyCompensations?.forEach(compensation => {\n const job = employee.jobs?.find(job => job.uuid === compensation.jobUuid)\n if (job && !hourlyJobs.find(hourlyJob => hourlyJob.uuid === job.uuid)) {\n hourlyJobs.push(job)\n }\n })\n\n const timeOff = (employeeCompensation?.paidTimeOff || []).filter(entry => entry.name)\n\n const additionalEarnings = getAdditionalEarningsCompensations({\n flsaStatus: primaryJob?.compensations?.[0]?.flsaStatus,\n existingFixedCompensations: employeeCompensation?.fixedCompensations || [],\n primaryJobUuid: primaryJob?.uuid,\n fixedCompensationTypes,\n excludedTypes: EXCLUDED_ADDITIONAL_EARNINGS,\n })\n\n // Off-cycle payrolls use the legacy single Reimbursement field in fixed_compensations because\n // the backend `emb_off_cycle_disable_named_reimbursements` flag (default: true, expected\n // removal 2026-09-01) rejects named entries in the itemized `reimbursements[]` array.\n // TODO(post-2026-09-01): unify on the itemized path once that flag is removed.\n const usesItemizedReimbursements = !isOffCyclePayroll(payrollCategory)\n\n const initialReimbursements: Reimbursement[] = useMemo(\n () =>\n withReimbursements && usesItemizedReimbursements\n ? (employeeCompensation?.reimbursements ?? [])\n : [],\n [withReimbursements, usesItemizedReimbursements, employeeCompensation?.reimbursements],\n )\n\n const existingReimbursementFixedCompensation = useMemo(\n () =>\n employeeCompensation?.fixedCompensations?.find(\n comp => comp.name?.toLowerCase() === COMPENSATION_NAME_REIMBURSEMENT.toLowerCase(),\n ),\n [employeeCompensation?.fixedCompensations],\n )\n\n const showLegacyReimbursementField =\n withReimbursements && !usesItemizedReimbursements && Boolean(primaryJob?.uuid)\n\n const findMatchingCompensation = (jobUuid: string, compensationName: string) => {\n return employeeCompensation?.hourlyCompensations?.find(\n compensation =>\n compensation.jobUuid === jobUuid &&\n compensation.name?.toLowerCase() === compensationName.toLowerCase(),\n )\n }\n\n const getCompensationLabel = (compensationName?: string) => {\n switch (compensationName) {\n case COMPENSATION_NAME_REGULAR_HOURS:\n return t('compensationNames.regularHours')\n case COMPENSATION_NAME_OVERTIME:\n return t('compensationNames.overtime')\n case COMPENSATION_NAME_DOUBLE_OVERTIME:\n return t('compensationNames.doubleOvertime')\n default:\n return compensationName\n }\n }\n\n const getFixedCompensationLabel = (compensationName?: string) => {\n switch (compensationName) {\n case COMPENSATION_NAME_BONUS:\n return t('fixedCompensationNames.bonus')\n case COMPENSATION_NAME_PAYCHECK_TIPS:\n return t('fixedCompensationNames.paycheckTips')\n case COMPENSATION_NAME_CORRECTION_PAYMENT:\n return t('fixedCompensationNames.correctionPayment')\n case COMPENSATION_NAME_COMMISSION:\n return t('fixedCompensationNames.commission')\n case COMPENSATION_NAME_CASH_TIPS:\n return t('fixedCompensationNames.cashTips')\n case COMPENSATION_NAME_REIMBURSEMENT:\n return t('fixedCompensationNames.reimbursement')\n default:\n return compensationName\n }\n }\n\n const resolveDefaultPaymentMethod = () => {\n const preparedPaymentMethod = employeeCompensation?.paymentMethod\n\n if (!preparedPaymentMethod) {\n return hasDirectDepositSetup\n ? PayrollEmployeeCompensationsTypePaymentMethod.DirectDeposit\n : PayrollEmployeeCompensationsTypePaymentMethod.Check\n }\n\n if (\n !hasDirectDepositSetup &&\n preparedPaymentMethod === PayrollEmployeeCompensationsTypePaymentMethod.DirectDeposit\n ) {\n return PayrollEmployeeCompensationsTypePaymentMethod.Check\n }\n\n return preparedPaymentMethod\n }\n\n const defaultValues = {\n hourlyCompensations: (() => {\n const hourlyCompensations: PayrollEditEmployeeFormValues['hourlyCompensations'] = {}\n\n hourlyJobs.forEach(hourlyJob => {\n HOURS_COMPENSATION_NAMES.forEach(compensationName => {\n const matchingCompensation = findMatchingCompensation(hourlyJob.uuid, compensationName)\n if (matchingCompensation) {\n if (!hourlyCompensations[hourlyJob.uuid]) {\n hourlyCompensations[hourlyJob.uuid] = {}\n }\n hourlyCompensations[hourlyJob.uuid]![matchingCompensation.name!] =\n matchingCompensation.hours ? parseFloat(matchingCompensation.hours).toString() : ''\n }\n })\n })\n\n return hourlyCompensations\n })(),\n\n timeOffCompensations: (() => {\n const timeOffCompensations: PayrollEditEmployeeFormValues['timeOffCompensations'] = {}\n\n timeOff.forEach(timeOffCompensation => {\n timeOffCompensations[timeOffCompensation.name!] = timeOffCompensation.hours\n ? parseFloat(timeOffCompensation.hours).toString()\n : ''\n })\n\n return timeOffCompensations\n })(),\n\n finalPayoutCompensations: (() => {\n const finalPayoutCompensations: PayrollEditEmployeeFormValues['finalPayoutCompensations'] = {}\n\n timeOff.forEach(timeOffCompensation => {\n finalPayoutCompensations[timeOffCompensation.name!] =\n timeOffCompensation.finalPayoutUnusedHoursInput ?? '0'\n })\n\n return finalPayoutCompensations\n })(),\n\n fixedCompensations: (() => {\n const fixedCompensations: PayrollEditEmployeeFormValues['fixedCompensations'] = {}\n\n additionalEarnings.forEach(fixedComp => {\n fixedCompensations[fixedComp.name!] = fixedComp.amount ?? ''\n })\n\n if (showLegacyReimbursementField) {\n fixedCompensations[COMPENSATION_NAME_REIMBURSEMENT] =\n existingReimbursementFixedCompensation?.amount ?? '0.00'\n }\n\n return fixedCompensations\n })(),\n\n reimbursements: initialReimbursements.map(reimbursement => ({\n uuid: reimbursement.uuid ?? null,\n description: reimbursement.description ?? '',\n amount: reimbursement.amount,\n recurring: reimbursement.recurring ?? false,\n })),\n\n paymentMethod: resolveDefaultPaymentMethod(),\n }\n\n const formHandlers = useForm<PayrollEditEmployeeFormValues>({\n resolver: zodResolver(PayrollEditEmployeeFormSchema),\n defaultValues,\n })\n\n const {\n fields: reimbursementFields,\n append: appendReimbursement,\n remove: removeReimbursement,\n update: updateReimbursement,\n } = useFieldArray({\n control: formHandlers.control,\n name: 'reimbursements',\n })\n\n const handleRemoveReimbursement = (index: number) => {\n const field = reimbursementFields[index]\n if (!field) return\n\n if (field.uuid) {\n updateReimbursement(index, { ...field, amount: '0' })\n } else {\n removeReimbursement(index)\n }\n }\n\n type VisibleReimbursementRow = (typeof reimbursementFields)[number] & {\n originalIndex: number\n }\n\n const visibleReimbursementRows: VisibleReimbursementRow[] = reimbursementFields\n .map((field, originalIndex) => ({ ...field, originalIndex }))\n .filter(row => parseFloat(row.amount || '0') !== 0)\n\n const [isAddingReimbursement, setIsAddingReimbursement] = useState(false)\n\n type DraftReimbursementValues = z.infer<typeof DraftReimbursementSchema>\n\n const draftForm = useForm<DraftReimbursementValues>({\n resolver: zodResolver(DraftReimbursementSchema),\n defaultValues: { description: '', amount: '' },\n })\n\n const resetReimbursementDraft = () => {\n setIsAddingReimbursement(false)\n draftForm.reset()\n }\n\n const onDraftReimbursementValid = (data: DraftReimbursementValues) => {\n const parsedAmount = parseFloat(data.amount)\n appendReimbursement({\n uuid: null,\n description: data.description.trim(),\n amount: parsedAmount.toFixed(2),\n recurring: false,\n })\n resetReimbursementDraft()\n }\n\n const reimbursementDataViewProps = useDataView<VisibleReimbursementRow>({\n data: visibleReimbursementRows,\n columns: [\n {\n key: 'description',\n title: t('reimbursementDescriptionColumn'),\n render: row => row.description.trim() || t('reimbursementUnnamedFallback'),\n },\n {\n key: 'amount',\n title: t('reimbursementAmountColumn'),\n justify: 'end',\n render: row => formatNumberAsCurrency(parseFloat(row.amount || '0')),\n },\n {\n key: 'recurring',\n title: t('reimbursementTypeColumn'),\n render: row =>\n row.recurring ? t('reimbursementTypeRecurring') : t('reimbursementTypeOneTime'),\n },\n ],\n itemMenu: row => {\n if (row.recurring) return null\n const displayDescription = row.description.trim() || t('reimbursementUnnamedFallback')\n return (\n <ButtonIcon\n variant=\"tertiary\"\n onClick={() => {\n handleRemoveReimbursement(row.originalIndex)\n }}\n aria-label={t('removeReimbursementLabel', { description: displayDescription })}\n >\n <TrashCanSvg aria-hidden />\n </ButtonIcon>\n )\n },\n emptyState: () => (\n <EmptyData title={t('reimbursementEmptyTitle')}>\n <Button\n variant=\"secondary\"\n onClick={() => {\n setIsAddingReimbursement(true)\n }}\n icon={<PlusCircleIcon aria-hidden />}\n >\n {t('addReimbursementCta')}\n </Button>\n </EmptyData>\n ),\n })\n\n const watchedFormData = useWatch({\n control: formHandlers.control,\n })\n\n const currentGrossPay = useMemo(() => {\n try {\n const hourlyCompensations: Record<string, Record<string, string | undefined>> = {}\n if (watchedFormData.hourlyCompensations) {\n Object.entries(watchedFormData.hourlyCompensations).forEach(([jobId, compensations]) => {\n if (compensations) {\n hourlyCompensations[jobId] = compensations\n }\n })\n }\n\n const reimbursementsWithDefaults: PayrollEditEmployeeFormValues['reimbursements'] = (\n watchedFormData.reimbursements ?? []\n ).map(reimbursement => ({\n uuid: reimbursement.uuid ?? null,\n description: reimbursement.description ?? '',\n amount: reimbursement.amount ?? '0',\n recurring: reimbursement.recurring,\n }))\n\n const formDataWithDefaults: PayrollEditEmployeeFormValues = {\n hourlyCompensations,\n timeOffCompensations: watchedFormData.timeOffCompensations || {},\n finalPayoutCompensations: watchedFormData.finalPayoutCompensations || {},\n fixedCompensations: watchedFormData.fixedCompensations || {},\n reimbursements: reimbursementsWithDefaults,\n paymentMethod: watchedFormData.paymentMethod,\n }\n\n const updatedCompensation = buildCompensationFromFormData(\n formDataWithDefaults,\n employeeCompensation,\n (employeeCompensation?.paidTimeOff || []).filter(entry => entry.name),\n primaryJob?.uuid,\n payrollCategory,\n )\n\n return calculateGrossPay(\n updatedCompensation,\n employee,\n payPeriodStartDate,\n paySchedule,\n payrollCategory,\n )\n } catch {\n return employeeCompensation\n ? calculateGrossPay(\n employeeCompensation,\n employee,\n payPeriodStartDate,\n paySchedule,\n payrollCategory,\n )\n : 0\n }\n }, [\n watchedFormData,\n employeeCompensation,\n primaryJob?.uuid,\n employee,\n payPeriodStartDate,\n paySchedule,\n payrollCategory,\n ])\n\n const employeeName = firstLastName({\n first_name: employee.firstName,\n last_name: employee.lastName,\n })\n\n const onSubmit = (data: PayrollEditEmployeeFormValues) => {\n const updatedCompensation = buildCompensationFromFormData(\n data,\n employeeCompensation,\n timeOff,\n primaryJob?.uuid,\n payrollCategory,\n )\n onSave(updatedCompensation)\n }\n\n const formattedCurrentGrossPay = formatNumberAsCurrency(currentGrossPay || 0)\n\n const actions = (\n <Flex\n flexDirection={isSmallOrGreater ? 'row' : 'column'}\n justifyContent={isSmallOrGreater ? 'flex-end' : 'normal'}\n alignItems={isSmallOrGreater ? 'flex-start' : 'stretch'}\n gap={12}\n >\n <Button variant=\"secondary\" onClick={onCancel} title={t('cancelCta')}>\n {t('cancelCta')}\n </Button>\n <Button\n onClick={formHandlers.handleSubmit(onSubmit)}\n title={t('saveCta')}\n isLoading={isPending}\n >\n {t('saveCta')}\n </Button>\n </Flex>\n )\n\n return (\n <div ref={containerRef} className={classNames(styles.container, className)}>\n <div\n className={`${styles.headerSection} ${!isSmallOrGreater ? styles.headerSectionSticky : ''}`}\n >\n <Flex justifyContent=\"space-between\">\n <Flex flexDirection=\"column\" alignItems=\"stretch\" gap={isSmallOrGreater ? 8 : 2}>\n <Heading as=\"h1\" styledAs={isSmallOrGreater ? 'h2' : 'h4'}>\n {t('pageTitle', { employeeName })}\n </Heading>\n {isSmallOrGreater ? (\n <Flex flexDirection=\"column\" gap={6}>\n <Heading as=\"h2\" styledAs=\"h3\">\n {formattedCurrentGrossPay}\n </Heading>\n <Text className={styles.grossPayLabel}>{t('grossPayLabel')}</Text>\n </Flex>\n ) : (\n <Heading as=\"h2\" styledAs=\"h6\" className={styles.grossPayLabel}>\n {t('grossPayLabelMobile', { grossPay: formattedCurrentGrossPay })}\n </Heading>\n )}\n </Flex>\n {isSmallOrGreater && actions}\n </Flex>\n </div>\n <FormProvider {...formHandlers}>\n <Form>\n {hourlyJobs.length > 0 && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\">{t('regularHoursTitle')}</Heading>\n {hourlyJobs.map(hourlyJob => (\n <Flex key={hourlyJob.uuid} flexDirection=\"column\" gap={8}>\n {hourlyJobs.length > 1 && <Heading as=\"h4\">{hourlyJob.title}</Heading>}\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n {HOURS_COMPENSATION_NAMES.map(compensationName => {\n const employeeHourlyCompensation = findMatchingCompensation(\n hourlyJob.uuid,\n compensationName,\n )\n if (employeeHourlyCompensation) {\n return (\n <TextInputField\n key={compensationName}\n type=\"number\"\n min={0}\n max={MAX_HOURS}\n transform={stripLeadingZeros}\n adornmentEnd={t('hoursUnit')}\n label={getCompensationLabel(compensationName)}\n name={`hourlyCompensations.${hourlyJob.uuid}.${employeeHourlyCompensation.name}`}\n errorMessage={t('validations.maxHours')}\n />\n )\n }\n })}\n </Grid>\n </Flex>\n ))}\n </div>\n )}\n {timeOff.length > 0 && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {payrollCategory === PayrollCategory.Dismissal\n ? t('timeOffTitleDismissal')\n : t('timeOffTitle')}\n </Heading>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n {timeOff.map(timeOffEntry => (\n <TimeOffField\n key={timeOffEntry.name}\n timeOff={timeOffEntry}\n employee={employee}\n />\n ))}\n </Grid>\n </div>\n )}\n {payrollCategory === PayrollCategory.Dismissal && timeOff.length > 0 && (\n <div className={styles.fieldGroup}>\n <Flex flexDirection=\"column\" gap={4}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('finalPayoutTitle')}\n </Heading>\n <Text variant=\"supporting\">{t('finalPayoutDescription')}</Text>\n </Flex>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n {timeOff.map(timeOffEntry => (\n <PayoutTimeOffField\n key={`payout-${timeOffEntry.name}`}\n timeOff={timeOffEntry}\n employee={employee}\n />\n ))}\n </Grid>\n </div>\n )}\n {additionalEarnings.length > 0 && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('additionalEarningsTitle')}\n </Heading>\n <Grid\n gridTemplateColumns={{ base: '1fr', small: [320, 320], large: [320, 320, 320] }}\n gap={20}\n >\n {additionalEarnings.map(fixedCompensation => (\n <TextInputField\n key={fixedCompensation.name}\n type=\"number\"\n min={0}\n transform={stripLeadingZeros}\n adornmentStart=\"$\"\n label={getFixedCompensationLabel(fixedCompensation.name)}\n name={`fixedCompensations.${fixedCompensation.name}`}\n // useField only surfaces this once react-hook-form has flagged the\n // field, and the schema's only rule here is the negative-amount check.\n errorMessage={t('validations.negativeAmount')}\n />\n ))}\n </Grid>\n </div>\n )}\n {showLegacyReimbursementField && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('reimbursementTitle')}\n </Heading>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n <TextInputField\n type=\"number\"\n min={0}\n transform={stripLeadingZeros}\n adornmentStart=\"$\"\n label={getFixedCompensationLabel(COMPENSATION_NAME_REIMBURSEMENT)}\n name={`fixedCompensations.${COMPENSATION_NAME_REIMBURSEMENT}`}\n errorMessage={t('validations.negativeAmount')}\n />\n </Grid>\n </div>\n )}\n {withReimbursements && usesItemizedReimbursements && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('reimbursementTitle')}\n </Heading>\n {!(visibleReimbursementRows.length === 0 && isAddingReimbursement) && (\n <DataView label={t('reimbursementsTableLabel')} {...reimbursementDataViewProps} />\n )}\n {isAddingReimbursement ? (\n <FormProvider {...draftForm}>\n <Flex flexDirection=\"column\" gap={12}>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n <TextInputField\n name=\"description\"\n label={t('reimbursementDescriptionLabel')}\n placeholder={t('reimbursementDescriptionPlaceholder')}\n />\n <TextInputField\n name=\"amount\"\n type=\"number\"\n min={0}\n max={MAX_REIMBURSEMENT_AMOUNT}\n transform={stripLeadingZeros}\n adornmentStart=\"$\"\n isRequired\n label={t('reimbursementAmountLabel')}\n errorMessage={\n draftForm.formState.errors.amount?.message ===\n 'validations.maxReimbursementAmount'\n ? t('validations.maxReimbursementAmount')\n : t('validations.reimbursementAmount')\n }\n />\n </Grid>\n <Flex gap={12}>\n <Button onClick={draftForm.handleSubmit(onDraftReimbursementValid)}>\n {t('saveReimbursementCta')}\n </Button>\n <Button variant=\"secondary\" onClick={resetReimbursementDraft}>\n {t('cancelReimbursementCta')}\n </Button>\n </Flex>\n </Flex>\n </FormProvider>\n ) : (\n visibleReimbursementRows.length > 0 && (\n <div>\n <Button\n variant=\"secondary\"\n onClick={() => {\n setIsAddingReimbursement(true)\n }}\n title={t('addReimbursementLink')}\n icon={<PlusCircleIcon aria-hidden />}\n >\n {t('addReimbursementLink')}\n </Button>\n </div>\n )\n )}\n </div>\n )}\n {hasDirectDepositSetup && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('paymentMethodTitle')}\n </Heading>\n <RadioGroupField\n name=\"paymentMethod\"\n isRequired\n label={t('paymentMethodLabel')}\n description={t('paymentMethodDescription')}\n options={[\n {\n value: PayrollEmployeeCompensationsTypePaymentMethod.DirectDeposit,\n label: t('paymentMethodOptions.directDeposit'),\n },\n {\n value: PayrollEmployeeCompensationsTypePaymentMethod.Check,\n label: t('paymentMethodOptions.check'),\n },\n ]}\n />\n </div>\n )}\n </Form>\n {!isSmallOrGreater && actions}\n </FormProvider>\n </div>\n )\n}\n"],"names":["ReimbursementFormSchema","z","MAX_REIMBURSEMENT_AMOUNT","DraftReimbursementSchema","val","num","nonNegativeAmountSchema","MAX_HOURS","hoursAmountSchema","PayrollEditEmployeeFormSchema","PayrollEmployeeCompensationsTypePaymentMethod","buildCompensationFromFormData","formData","employeeCompensation","timeOff","primaryJobUuid","payrollCategory","PayrollCategory","updatedCompensation","compensation","hours","timeOffEntry","isDismissal","_","timeOffWithoutPayout","finalPayout","usesItemizedReimbursements","isOffCyclePayroll","updatedFixedCompensations","fixedCompensationName","formAmount","COMPENSATION_NAME_REIMBURSEMENT","existingFixedCompensation","fixedCompensation","resolvedAmount","reimbursement","PayrollEditEmployeePresentation","className","onSave","onCancel","employee","isPending","fixedCompensationTypes","payPeriodStartDate","paySchedule","withReimbursements","hasDirectDepositSetup","Button","ButtonIcon","Heading","Text","useComponentContext","t","useTranslation","useI18n","primaryJob","job","primaryJobHasHourlyCompensations","c","hourlyJobs","containerRef","useRef","isSmallOrGreater","useContainerBreakpoints","hourlyJob","entry","additionalEarnings","getAdditionalEarningsCompensations","EXCLUDED_ADDITIONAL_EARNINGS","initialReimbursements","useMemo","existingReimbursementFixedCompensation","comp","showLegacyReimbursementField","findMatchingCompensation","jobUuid","compensationName","getCompensationLabel","COMPENSATION_NAME_REGULAR_HOURS","COMPENSATION_NAME_OVERTIME","COMPENSATION_NAME_DOUBLE_OVERTIME","getFixedCompensationLabel","COMPENSATION_NAME_BONUS","COMPENSATION_NAME_PAYCHECK_TIPS","COMPENSATION_NAME_CORRECTION_PAYMENT","COMPENSATION_NAME_COMMISSION","COMPENSATION_NAME_CASH_TIPS","resolveDefaultPaymentMethod","preparedPaymentMethod","defaultValues","hourlyCompensations","HOURS_COMPENSATION_NAMES","matchingCompensation","timeOffCompensations","timeOffCompensation","finalPayoutCompensations","fixedCompensations","fixedComp","formHandlers","useForm","zodResolver","reimbursementFields","appendReimbursement","removeReimbursement","updateReimbursement","useFieldArray","handleRemoveReimbursement","index","field","visibleReimbursementRows","originalIndex","row","isAddingReimbursement","setIsAddingReimbursement","useState","draftForm","resetReimbursementDraft","onDraftReimbursementValid","data","parsedAmount","reimbursementDataViewProps","useDataView","formatNumberAsCurrency","displayDescription","jsx","TrashCanSvg","EmptyData","PlusCircleIcon","watchedFormData","useWatch","currentGrossPay","jobId","compensations","reimbursementsWithDefaults","formDataWithDefaults","calculateGrossPay","employeeName","firstLastName","onSubmit","formattedCurrentGrossPay","actions","jsxs","Flex","classNames","styles","FormProvider","Form","Grid","employeeHourlyCompensation","TextInputField","stripLeadingZeros","TimeOffField","PayoutTimeOffField","DataView","RadioGroupField"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PayrollEditEmployeePresentation.js","sources":["../../../../src/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.tsx"],"sourcesContent":["import { FormProvider, useFieldArray, useForm, useWatch } from 'react-hook-form'\nimport { useMemo, useRef, useState } from 'react'\nimport classNames from 'classnames'\nimport type { Employee } from '@gusto/embedded-api/models/components/employee'\nimport type {\n FixedCompensations,\n PayrollEmployeeCompensationsType,\n PayrollEmployeeCompensationsTypePaidTimeOff,\n Reimbursements as Reimbursement,\n} from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport { PayrollEmployeeCompensationsTypePaymentMethod } from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport type { PayrollFixedCompensationTypesType } from '@gusto/embedded-api/models/components/payrollfixedcompensationtypestype'\nimport type { PayScheduleShow as PayScheduleObject } from '@gusto/embedded-api/models/components/payschedulelistitem'\nimport { useTranslation } from 'react-i18next'\nimport { z } from 'zod'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport styles from './PayrollEditEmployeePresentation.module.scss'\nimport { TimeOffField, PayoutTimeOffField } from './TimeOffField'\nimport {\n Flex,\n Grid,\n TextInputField,\n RadioGroupField,\n DataView,\n useDataView,\n EmptyData,\n} from '@/components/Common'\nimport { useComponentContext } from '@/contexts/ComponentAdapter/useComponentContext'\nimport { useI18n } from '@/i18n'\nimport { Form } from '@/components/Common/Form'\nimport {\n formatNumberAsCurrency,\n firstLastName,\n stripLeadingZeros,\n} from '@/helpers/formattedStrings'\nimport { getAdditionalEarningsCompensations, calculateGrossPay } from '@/components/Payroll/helpers'\nimport { PayrollCategory, isOffCyclePayroll } from '@/components/Payroll/payrollTypes'\nimport {\n COMPENSATION_NAME_DOUBLE_OVERTIME,\n COMPENSATION_NAME_OVERTIME,\n COMPENSATION_NAME_REGULAR_HOURS,\n HOURS_COMPENSATION_NAMES,\n EXCLUDED_ADDITIONAL_EARNINGS,\n COMPENSATION_NAME_REIMBURSEMENT,\n COMPENSATION_NAME_BONUS,\n COMPENSATION_NAME_PAYCHECK_TIPS,\n COMPENSATION_NAME_CORRECTION_PAYMENT,\n COMPENSATION_NAME_COMMISSION,\n COMPENSATION_NAME_CASH_TIPS,\n} from '@/shared/constants'\nimport useContainerBreakpoints from '@/hooks/useContainerBreakpoints/useContainerBreakpoints'\nimport PlusCircleIcon from '@/assets/icons/plus-circle.svg?react'\nimport TrashCanSvg from '@/assets/icons/trashcan.svg?react'\n\ninterface PayrollEditEmployeeProps {\n /** CSS class name applied to the root element. */\n className?: string\n onSave: (updatedCompensation: PayrollEmployeeCompensationsType) => void\n onCancel: () => void\n employee: Employee\n employeeCompensation?: PayrollEmployeeCompensationsType\n isPending?: boolean\n fixedCompensationTypes: PayrollFixedCompensationTypesType[]\n payPeriodStartDate?: string\n paySchedule?: PayScheduleObject\n payrollCategory?: PayrollCategory\n withReimbursements?: boolean\n hasDirectDepositSetup?: boolean\n}\n\nconst ReimbursementFormSchema = z.object({\n uuid: z.string().nullable().optional(),\n description: z.string(),\n amount: z.string(),\n recurring: z.boolean().optional(),\n})\n\n// Mirrors the server's fixed reimbursement cap (payroll_core_data's\n// Reimbursements::MAX_AMOUNT) so an over-limit value is caught inline instead\n// of round-tripping to a 422.\nconst MAX_REIMBURSEMENT_AMOUNT = 1_000_000\n\nconst DraftReimbursementSchema = z.object({\n description: z.string(),\n amount: z\n .string()\n .refine(\n val => {\n const num = parseFloat(val)\n return !Number.isNaN(num) && num > 0\n },\n { message: 'validations.reimbursementAmount' },\n )\n .refine(val => parseFloat(val) <= MAX_REIMBURSEMENT_AMOUNT, {\n message: 'validations.maxReimbursementAmount',\n }),\n})\n\n// A native `min={0}` only constrains the stepper: it does not stop a typed \"-50\", and the\n// SDK's <form> is noValidate so the browser never enforces it either. Negative amounts\n// therefore reached the platform and came back only as a submit-time error (SDK-1285).\n// Applied via z.record below, this covers every additional earning -- correction payment\n// included -- because they all share the fixedCompensations record.\nconst nonNegativeAmountSchema = z\n .string()\n .optional()\n .refine(val => !val || parseFloat(val) >= 0, { message: 'validations.negativeAmount' })\n\n// Mirrors the server's fixed hours cap (draft_payrolls' MAX_HOURS) so an\n// over-limit value is caught inline instead of round-tripping to a 422.\nconst MAX_HOURS = 99_999\n\nconst hoursAmountSchema = z\n .string()\n .optional()\n .refine(val => !val || parseFloat(val) <= MAX_HOURS, { message: 'validations.maxHours' })\n\nconst PayrollEditEmployeeFormSchema = z.object({\n hourlyCompensations: z.record(z.string(), z.record(z.string(), hoursAmountSchema)),\n timeOffCompensations: z.record(z.string(), z.string().optional()),\n finalPayoutCompensations: z.record(z.string(), z.string().optional()),\n fixedCompensations: z.record(z.string(), nonNegativeAmountSchema),\n reimbursements: z.array(ReimbursementFormSchema),\n paymentMethod: z.enum(PayrollEmployeeCompensationsTypePaymentMethod).optional(),\n})\n\n/** @internal */\nexport type PayrollEditEmployeeFormValues = z.infer<typeof PayrollEditEmployeeFormSchema>\n\nconst buildCompensationFromFormData = (\n formData: PayrollEditEmployeeFormValues,\n employeeCompensation: PayrollEmployeeCompensationsType | undefined,\n timeOff: PayrollEmployeeCompensationsTypePaidTimeOff[],\n primaryJobUuid?: string,\n payrollCategory: PayrollCategory = PayrollCategory.Regular,\n): PayrollEmployeeCompensationsType => {\n const updatedCompensation = {\n ...employeeCompensation,\n paymentMethod: formData.paymentMethod,\n }\n\n updatedCompensation.hourlyCompensations = employeeCompensation?.hourlyCompensations?.map(\n compensation => {\n const hours =\n compensation.jobUuid && compensation.name\n ? formData.hourlyCompensations[compensation.jobUuid]?.[compensation.name]\n : undefined\n return hours\n ? {\n ...compensation,\n hours,\n }\n : compensation\n },\n )\n\n updatedCompensation.paidTimeOff = timeOff.map(timeOffEntry => {\n const isDismissal = payrollCategory === PayrollCategory.Dismissal\n const { finalPayoutUnusedHoursInput: _, ...timeOffWithoutPayout } = timeOffEntry\n\n if (isDismissal) {\n const finalPayout =\n formData.finalPayoutCompensations[timeOffEntry.name!] ??\n timeOffEntry.finalPayoutUnusedHoursInput\n return {\n ...timeOffEntry,\n hours: formData.timeOffCompensations[timeOffEntry.name!] || '0',\n ...(finalPayout != null ? { finalPayoutUnusedHoursInput: finalPayout || '0' } : {}),\n }\n }\n\n return {\n ...timeOffWithoutPayout,\n hours: formData.timeOffCompensations[timeOffEntry.name!] || '0',\n }\n })\n\n // Off-cycle payrolls today use the legacy single Reimbursement field in fixed_compensations\n // because the backend feature flag `emb_off_cycle_disable_named_reimbursements` (default: true,\n // expected removal 2026-09-01) rejects named entries in the itemized `reimbursements[]` array.\n // TODO(post-2026-09-01): once that flag is removed, unify on the itemized path for all categories.\n const usesItemizedReimbursements = !isOffCyclePayroll(payrollCategory)\n\n const updatedFixedCompensations: FixedCompensations[] = []\n\n Object.entries(formData.fixedCompensations).forEach(([fixedCompensationName, formAmount]) => {\n const isReimbursementEntry =\n fixedCompensationName.toLowerCase() === COMPENSATION_NAME_REIMBURSEMENT.toLowerCase()\n\n // Regular payrolls write reimbursements via the itemized array; never let the legacy\n // fixed_compensations entry slip through (the backend rejects it on v2025-11-15+).\n if (isReimbursementEntry && usesItemizedReimbursements) {\n return\n }\n\n const existingFixedCompensation = employeeCompensation?.fixedCompensations?.find(\n fixedCompensation =>\n fixedCompensation.name?.toLowerCase() === fixedCompensationName.toLowerCase(),\n )\n\n // Clearing the field means \"no additional earning\". For an entry that already has a\n // saved amount we have to send an explicit 0: omitting it leaves the previously saved\n // value in place server-side, so the box looked empty while the old amount survived\n // the save (SDK-1284). This makes clearing behave exactly like typing 0. An entry with\n // no saved compensation stays omitted -- there is nothing to zero out.\n const resolvedAmount = formAmount === '' && existingFixedCompensation ? '0' : formAmount\n\n if (resolvedAmount !== undefined && resolvedAmount !== '') {\n if (existingFixedCompensation) {\n updatedFixedCompensations.push({\n name: existingFixedCompensation.name,\n jobUuid: existingFixedCompensation.jobUuid,\n amount: resolvedAmount,\n })\n } else if (parseFloat(resolvedAmount) !== 0) {\n updatedFixedCompensations.push({\n name: fixedCompensationName,\n jobUuid: primaryJobUuid,\n amount: resolvedAmount,\n })\n }\n }\n })\n\n updatedCompensation.fixedCompensations = updatedFixedCompensations\n\n if (usesItemizedReimbursements) {\n updatedCompensation.reimbursements = formData.reimbursements.map(reimbursement => ({\n amount: reimbursement.amount,\n description:\n reimbursement.description.trim() === '' ? null : reimbursement.description.trim(),\n uuid: reimbursement.uuid ?? null,\n recurring: reimbursement.recurring,\n }))\n } else {\n // Off-cycle: ensure no itemized array leaks through. The container also strips this defensively.\n updatedCompensation.reimbursements = []\n }\n\n return updatedCompensation\n}\n\n/** @internal */\nexport const PayrollEditEmployeePresentation = ({\n className,\n onSave,\n onCancel,\n employee,\n employeeCompensation,\n isPending = false,\n fixedCompensationTypes,\n payPeriodStartDate,\n paySchedule,\n payrollCategory = PayrollCategory.Regular,\n withReimbursements = true,\n hasDirectDepositSetup = true,\n}: PayrollEditEmployeeProps) => {\n const { Button, ButtonIcon, Heading, Text } = useComponentContext()\n\n const { t } = useTranslation('Payroll.PayrollEditEmployee')\n useI18n('Payroll.PayrollEditEmployee')\n\n const primaryJob = employee.jobs?.find(job => job.primary)\n const primaryJobHasHourlyCompensations = employeeCompensation?.hourlyCompensations?.some(\n c => c.jobUuid === primaryJob?.uuid,\n )\n const hourlyJobs = primaryJob && primaryJobHasHourlyCompensations ? [primaryJob] : []\n\n const containerRef = useRef<HTMLDivElement>(null)\n const breakpoints = useContainerBreakpoints({\n ref: containerRef,\n })\n const isSmallOrGreater = breakpoints.includes('small')\n\n employeeCompensation?.hourlyCompensations?.forEach(compensation => {\n const job = employee.jobs?.find(job => job.uuid === compensation.jobUuid)\n if (job && !hourlyJobs.find(hourlyJob => hourlyJob.uuid === job.uuid)) {\n hourlyJobs.push(job)\n }\n })\n\n const timeOff = (employeeCompensation?.paidTimeOff || []).filter(entry => entry.name)\n\n const additionalEarnings = getAdditionalEarningsCompensations({\n flsaStatus: primaryJob?.compensations?.[0]?.flsaStatus,\n existingFixedCompensations: employeeCompensation?.fixedCompensations || [],\n primaryJobUuid: primaryJob?.uuid,\n fixedCompensationTypes,\n excludedTypes: EXCLUDED_ADDITIONAL_EARNINGS,\n })\n\n // Off-cycle payrolls use the legacy single Reimbursement field in fixed_compensations because\n // the backend `emb_off_cycle_disable_named_reimbursements` flag (default: true, expected\n // removal 2026-09-01) rejects named entries in the itemized `reimbursements[]` array.\n // TODO(post-2026-09-01): unify on the itemized path once that flag is removed.\n const usesItemizedReimbursements = !isOffCyclePayroll(payrollCategory)\n\n const initialReimbursements: Reimbursement[] = useMemo(\n () =>\n withReimbursements && usesItemizedReimbursements\n ? (employeeCompensation?.reimbursements ?? [])\n : [],\n [withReimbursements, usesItemizedReimbursements, employeeCompensation?.reimbursements],\n )\n\n const existingReimbursementFixedCompensation = useMemo(\n () =>\n employeeCompensation?.fixedCompensations?.find(\n comp => comp.name?.toLowerCase() === COMPENSATION_NAME_REIMBURSEMENT.toLowerCase(),\n ),\n [employeeCompensation?.fixedCompensations],\n )\n\n const showLegacyReimbursementField =\n withReimbursements && !usesItemizedReimbursements && Boolean(primaryJob?.uuid)\n\n const findMatchingCompensation = (jobUuid: string, compensationName: string) => {\n return employeeCompensation?.hourlyCompensations?.find(\n compensation =>\n compensation.jobUuid === jobUuid &&\n compensation.name?.toLowerCase() === compensationName.toLowerCase(),\n )\n }\n\n const getCompensationLabel = (compensationName?: string) => {\n switch (compensationName) {\n case COMPENSATION_NAME_REGULAR_HOURS:\n return t('compensationNames.regularHours')\n case COMPENSATION_NAME_OVERTIME:\n return t('compensationNames.overtime')\n case COMPENSATION_NAME_DOUBLE_OVERTIME:\n return t('compensationNames.doubleOvertime')\n default:\n return compensationName\n }\n }\n\n const getFixedCompensationLabel = (compensationName?: string) => {\n switch (compensationName) {\n case COMPENSATION_NAME_BONUS:\n return t('fixedCompensationNames.bonus')\n case COMPENSATION_NAME_PAYCHECK_TIPS:\n return t('fixedCompensationNames.paycheckTips')\n case COMPENSATION_NAME_CORRECTION_PAYMENT:\n return t('fixedCompensationNames.correctionPayment')\n case COMPENSATION_NAME_COMMISSION:\n return t('fixedCompensationNames.commission')\n case COMPENSATION_NAME_CASH_TIPS:\n return t('fixedCompensationNames.cashTips')\n case COMPENSATION_NAME_REIMBURSEMENT:\n return t('fixedCompensationNames.reimbursement')\n default:\n return compensationName\n }\n }\n\n const resolveDefaultPaymentMethod = () => {\n const preparedPaymentMethod = employeeCompensation?.paymentMethod\n\n if (!preparedPaymentMethod) {\n return hasDirectDepositSetup\n ? PayrollEmployeeCompensationsTypePaymentMethod.DirectDeposit\n : PayrollEmployeeCompensationsTypePaymentMethod.Check\n }\n\n if (\n !hasDirectDepositSetup &&\n preparedPaymentMethod === PayrollEmployeeCompensationsTypePaymentMethod.DirectDeposit\n ) {\n return PayrollEmployeeCompensationsTypePaymentMethod.Check\n }\n\n return preparedPaymentMethod\n }\n\n const defaultValues = {\n hourlyCompensations: (() => {\n const hourlyCompensations: PayrollEditEmployeeFormValues['hourlyCompensations'] = {}\n\n hourlyJobs.forEach(hourlyJob => {\n HOURS_COMPENSATION_NAMES.forEach(compensationName => {\n const matchingCompensation = findMatchingCompensation(hourlyJob.uuid, compensationName)\n if (matchingCompensation) {\n if (!hourlyCompensations[hourlyJob.uuid]) {\n hourlyCompensations[hourlyJob.uuid] = {}\n }\n hourlyCompensations[hourlyJob.uuid]![matchingCompensation.name!] =\n matchingCompensation.hours ? parseFloat(matchingCompensation.hours).toString() : ''\n }\n })\n })\n\n return hourlyCompensations\n })(),\n\n timeOffCompensations: (() => {\n const timeOffCompensations: PayrollEditEmployeeFormValues['timeOffCompensations'] = {}\n\n timeOff.forEach(timeOffCompensation => {\n timeOffCompensations[timeOffCompensation.name!] = timeOffCompensation.hours\n ? parseFloat(timeOffCompensation.hours).toString()\n : ''\n })\n\n return timeOffCompensations\n })(),\n\n finalPayoutCompensations: (() => {\n const finalPayoutCompensations: PayrollEditEmployeeFormValues['finalPayoutCompensations'] = {}\n\n timeOff.forEach(timeOffCompensation => {\n finalPayoutCompensations[timeOffCompensation.name!] =\n timeOffCompensation.finalPayoutUnusedHoursInput ?? '0'\n })\n\n return finalPayoutCompensations\n })(),\n\n fixedCompensations: (() => {\n const fixedCompensations: PayrollEditEmployeeFormValues['fixedCompensations'] = {}\n\n additionalEarnings.forEach(fixedComp => {\n fixedCompensations[fixedComp.name!] = fixedComp.amount ?? ''\n })\n\n if (showLegacyReimbursementField) {\n fixedCompensations[COMPENSATION_NAME_REIMBURSEMENT] =\n existingReimbursementFixedCompensation?.amount ?? '0.00'\n }\n\n return fixedCompensations\n })(),\n\n reimbursements: initialReimbursements.map(reimbursement => ({\n uuid: reimbursement.uuid ?? null,\n description: reimbursement.description ?? '',\n amount: reimbursement.amount,\n recurring: reimbursement.recurring ?? false,\n })),\n\n paymentMethod: resolveDefaultPaymentMethod(),\n }\n\n const formHandlers = useForm<PayrollEditEmployeeFormValues>({\n resolver: zodResolver(PayrollEditEmployeeFormSchema),\n defaultValues,\n })\n\n const {\n fields: reimbursementFields,\n append: appendReimbursement,\n remove: removeReimbursement,\n update: updateReimbursement,\n } = useFieldArray({\n control: formHandlers.control,\n name: 'reimbursements',\n })\n\n const handleRemoveReimbursement = (index: number) => {\n const field = reimbursementFields[index]\n if (!field) return\n\n if (field.uuid) {\n updateReimbursement(index, { ...field, amount: '0' })\n } else {\n removeReimbursement(index)\n }\n }\n\n type VisibleReimbursementRow = (typeof reimbursementFields)[number] & {\n originalIndex: number\n }\n\n const visibleReimbursementRows: VisibleReimbursementRow[] = reimbursementFields\n .map((field, originalIndex) => ({ ...field, originalIndex }))\n .filter(row => parseFloat(row.amount || '0') !== 0)\n\n const [isAddingReimbursement, setIsAddingReimbursement] = useState(false)\n\n type DraftReimbursementValues = z.infer<typeof DraftReimbursementSchema>\n\n const draftForm = useForm<DraftReimbursementValues>({\n resolver: zodResolver(DraftReimbursementSchema),\n defaultValues: { description: '', amount: '' },\n })\n\n const resetReimbursementDraft = () => {\n setIsAddingReimbursement(false)\n draftForm.reset()\n }\n\n const onDraftReimbursementValid = (data: DraftReimbursementValues) => {\n const parsedAmount = parseFloat(data.amount)\n appendReimbursement({\n uuid: null,\n description: data.description.trim(),\n amount: parsedAmount.toFixed(2),\n recurring: false,\n })\n resetReimbursementDraft()\n }\n\n const reimbursementDataViewProps = useDataView<VisibleReimbursementRow>({\n data: visibleReimbursementRows,\n columns: [\n {\n key: 'description',\n title: t('reimbursementDescriptionColumn'),\n render: row => row.description.trim() || t('reimbursementUnnamedFallback'),\n },\n {\n key: 'amount',\n title: t('reimbursementAmountColumn'),\n justify: 'end',\n render: row => formatNumberAsCurrency(parseFloat(row.amount || '0')),\n },\n {\n key: 'recurring',\n title: t('reimbursementTypeColumn'),\n render: row =>\n row.recurring ? t('reimbursementTypeRecurring') : t('reimbursementTypeOneTime'),\n },\n ],\n itemMenu: row => {\n if (row.recurring) return null\n const displayDescription = row.description.trim() || t('reimbursementUnnamedFallback')\n return (\n <ButtonIcon\n variant=\"tertiary\"\n onClick={() => {\n handleRemoveReimbursement(row.originalIndex)\n }}\n aria-label={t('removeReimbursementLabel', { description: displayDescription })}\n >\n <TrashCanSvg aria-hidden />\n </ButtonIcon>\n )\n },\n emptyState: () => (\n <EmptyData title={t('reimbursementEmptyTitle')}>\n <Button\n variant=\"secondary\"\n onClick={() => {\n setIsAddingReimbursement(true)\n }}\n icon={<PlusCircleIcon aria-hidden />}\n >\n {t('addReimbursementCta')}\n </Button>\n </EmptyData>\n ),\n })\n\n const watchedFormData = useWatch({\n control: formHandlers.control,\n })\n\n const currentGrossPay = useMemo(() => {\n try {\n const hourlyCompensations: Record<string, Record<string, string | undefined>> = {}\n if (watchedFormData.hourlyCompensations) {\n Object.entries(watchedFormData.hourlyCompensations).forEach(([jobId, compensations]) => {\n if (compensations) {\n hourlyCompensations[jobId] = compensations\n }\n })\n }\n\n const reimbursementsWithDefaults: PayrollEditEmployeeFormValues['reimbursements'] = (\n watchedFormData.reimbursements ?? []\n ).map(reimbursement => ({\n uuid: reimbursement.uuid ?? null,\n description: reimbursement.description ?? '',\n amount: reimbursement.amount ?? '0',\n recurring: reimbursement.recurring,\n }))\n\n const formDataWithDefaults: PayrollEditEmployeeFormValues = {\n hourlyCompensations,\n timeOffCompensations: watchedFormData.timeOffCompensations || {},\n finalPayoutCompensations: watchedFormData.finalPayoutCompensations || {},\n fixedCompensations: watchedFormData.fixedCompensations || {},\n reimbursements: reimbursementsWithDefaults,\n paymentMethod: watchedFormData.paymentMethod,\n }\n\n const updatedCompensation = buildCompensationFromFormData(\n formDataWithDefaults,\n employeeCompensation,\n (employeeCompensation?.paidTimeOff || []).filter(entry => entry.name),\n primaryJob?.uuid,\n payrollCategory,\n )\n\n return calculateGrossPay(\n updatedCompensation,\n employee,\n payPeriodStartDate,\n paySchedule,\n payrollCategory,\n )\n } catch {\n return employeeCompensation\n ? calculateGrossPay(\n employeeCompensation,\n employee,\n payPeriodStartDate,\n paySchedule,\n payrollCategory,\n )\n : 0\n }\n }, [\n watchedFormData,\n employeeCompensation,\n primaryJob?.uuid,\n employee,\n payPeriodStartDate,\n paySchedule,\n payrollCategory,\n ])\n\n const employeeName = firstLastName({\n first_name: employee.firstName,\n last_name: employee.lastName,\n })\n\n const onSubmit = (data: PayrollEditEmployeeFormValues) => {\n const updatedCompensation = buildCompensationFromFormData(\n data,\n employeeCompensation,\n timeOff,\n primaryJob?.uuid,\n payrollCategory,\n )\n onSave(updatedCompensation)\n }\n\n const formattedCurrentGrossPay = formatNumberAsCurrency(currentGrossPay || 0)\n\n const actions = (\n <Flex\n flexDirection={isSmallOrGreater ? 'row' : 'column'}\n justifyContent={isSmallOrGreater ? 'flex-end' : 'normal'}\n alignItems={isSmallOrGreater ? 'flex-start' : 'stretch'}\n gap={12}\n >\n <Button variant=\"secondary\" onClick={onCancel} title={t('cancelCta')}>\n {t('cancelCta')}\n </Button>\n <Button\n onClick={formHandlers.handleSubmit(onSubmit)}\n title={t('saveCta')}\n isLoading={isPending}\n >\n {t('saveCta')}\n </Button>\n </Flex>\n )\n\n return (\n <div ref={containerRef} className={classNames(styles.container, className)}>\n <div\n className={`${styles.headerSection} ${!isSmallOrGreater ? styles.headerSectionSticky : ''}`}\n >\n <Flex justifyContent=\"space-between\">\n <Flex flexDirection=\"column\" alignItems=\"stretch\" gap={isSmallOrGreater ? 8 : 2}>\n <Heading as=\"h1\" styledAs={isSmallOrGreater ? 'h2' : 'h4'}>\n {t('pageTitle', { employeeName })}\n </Heading>\n {isSmallOrGreater ? (\n <Flex flexDirection=\"column\" gap={6}>\n <Heading as=\"h2\" styledAs=\"h3\">\n {formattedCurrentGrossPay}\n </Heading>\n <Text className={styles.grossPayLabel}>{t('grossPayLabel')}</Text>\n </Flex>\n ) : (\n <Heading as=\"h2\" styledAs=\"h6\" className={styles.grossPayLabel}>\n {t('grossPayLabelMobile', { grossPay: formattedCurrentGrossPay })}\n </Heading>\n )}\n </Flex>\n {isSmallOrGreater && actions}\n </Flex>\n </div>\n <FormProvider {...formHandlers}>\n <Form>\n {hourlyJobs.length > 0 && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\">{t('regularHoursTitle')}</Heading>\n {hourlyJobs.map(hourlyJob => (\n <Flex key={hourlyJob.uuid} flexDirection=\"column\" gap={8}>\n {hourlyJobs.length > 1 && <Heading as=\"h4\">{hourlyJob.title}</Heading>}\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n {HOURS_COMPENSATION_NAMES.map(compensationName => {\n const employeeHourlyCompensation = findMatchingCompensation(\n hourlyJob.uuid,\n compensationName,\n )\n if (employeeHourlyCompensation) {\n return (\n <TextInputField\n key={compensationName}\n type=\"number\"\n min={0}\n max={MAX_HOURS}\n transform={stripLeadingZeros}\n adornmentEnd={t('hoursUnit')}\n label={getCompensationLabel(compensationName)}\n name={`hourlyCompensations.${hourlyJob.uuid}.${employeeHourlyCompensation.name}`}\n errorMessage={t('validations.maxHours')}\n />\n )\n }\n })}\n </Grid>\n </Flex>\n ))}\n </div>\n )}\n {timeOff.length > 0 && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {payrollCategory === PayrollCategory.Dismissal\n ? t('timeOffTitleDismissal')\n : t('timeOffTitle')}\n </Heading>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n {timeOff.map(timeOffEntry => (\n <TimeOffField\n key={timeOffEntry.name}\n timeOff={timeOffEntry}\n employee={employee}\n />\n ))}\n </Grid>\n </div>\n )}\n {payrollCategory === PayrollCategory.Dismissal && timeOff.length > 0 && (\n <div className={styles.fieldGroup}>\n <Flex flexDirection=\"column\" gap={4}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('finalPayoutTitle')}\n </Heading>\n <Text variant=\"supporting\">{t('finalPayoutDescription')}</Text>\n </Flex>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n {timeOff.map(timeOffEntry => (\n <PayoutTimeOffField\n key={`payout-${timeOffEntry.name}`}\n timeOff={timeOffEntry}\n employee={employee}\n />\n ))}\n </Grid>\n </div>\n )}\n {additionalEarnings.length > 0 && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('additionalEarningsTitle')}\n </Heading>\n <Grid\n gridTemplateColumns={{ base: '1fr', small: [320, 320], large: [320, 320, 320] }}\n gap={20}\n >\n {additionalEarnings.map(fixedCompensation => (\n <TextInputField\n key={fixedCompensation.name}\n type=\"number\"\n min={0}\n transform={stripLeadingZeros}\n adornmentStart=\"$\"\n label={getFixedCompensationLabel(fixedCompensation.name)}\n name={`fixedCompensations.${fixedCompensation.name}`}\n // useField only surfaces this once react-hook-form has flagged the\n // field, and the schema's only rule here is the negative-amount check.\n errorMessage={t('validations.negativeAmount')}\n />\n ))}\n </Grid>\n </div>\n )}\n {showLegacyReimbursementField && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('reimbursementTitle')}\n </Heading>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n <TextInputField\n type=\"number\"\n min={0}\n transform={stripLeadingZeros}\n adornmentStart=\"$\"\n label={getFixedCompensationLabel(COMPENSATION_NAME_REIMBURSEMENT)}\n name={`fixedCompensations.${COMPENSATION_NAME_REIMBURSEMENT}`}\n errorMessage={t('validations.negativeAmount')}\n />\n </Grid>\n </div>\n )}\n {withReimbursements && usesItemizedReimbursements && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('reimbursementTitle')}\n </Heading>\n {!(visibleReimbursementRows.length === 0 && isAddingReimbursement) && (\n <DataView label={t('reimbursementsTableLabel')} {...reimbursementDataViewProps} />\n )}\n {isAddingReimbursement ? (\n <FormProvider {...draftForm}>\n <Flex flexDirection=\"column\" gap={12}>\n <Grid gridTemplateColumns={{ base: '1fr', small: [320, 320] }} gap={20}>\n <TextInputField\n name=\"description\"\n label={t('reimbursementDescriptionLabel')}\n placeholder={t('reimbursementDescriptionPlaceholder')}\n />\n <TextInputField\n name=\"amount\"\n type=\"number\"\n min={0}\n max={MAX_REIMBURSEMENT_AMOUNT}\n transform={stripLeadingZeros}\n adornmentStart=\"$\"\n isRequired\n label={t('reimbursementAmountLabel')}\n errorMessage={\n draftForm.formState.errors.amount?.message ===\n 'validations.maxReimbursementAmount'\n ? t('validations.maxReimbursementAmount')\n : t('validations.reimbursementAmount')\n }\n />\n </Grid>\n <Flex gap={12}>\n <Button onClick={draftForm.handleSubmit(onDraftReimbursementValid)}>\n {t('saveReimbursementCta')}\n </Button>\n <Button variant=\"secondary\" onClick={resetReimbursementDraft}>\n {t('cancelReimbursementCta')}\n </Button>\n </Flex>\n </Flex>\n </FormProvider>\n ) : (\n visibleReimbursementRows.length > 0 && (\n <div>\n <Button\n variant=\"secondary\"\n onClick={() => {\n setIsAddingReimbursement(true)\n }}\n title={t('addReimbursementLink')}\n icon={<PlusCircleIcon aria-hidden />}\n >\n {t('addReimbursementLink')}\n </Button>\n </div>\n )\n )}\n </div>\n )}\n {hasDirectDepositSetup && (\n <div className={styles.fieldGroup}>\n <Heading as=\"h3\" styledAs=\"h4\">\n {t('paymentMethodTitle')}\n </Heading>\n <RadioGroupField\n name=\"paymentMethod\"\n isRequired\n label={t('paymentMethodLabel')}\n description={t('paymentMethodDescription')}\n options={[\n {\n value: PayrollEmployeeCompensationsTypePaymentMethod.DirectDeposit,\n label: t('paymentMethodOptions.directDeposit'),\n },\n {\n value: PayrollEmployeeCompensationsTypePaymentMethod.Check,\n label: t('paymentMethodOptions.check'),\n },\n ]}\n />\n </div>\n )}\n </Form>\n {!isSmallOrGreater && actions}\n </FormProvider>\n </div>\n )\n}\n"],"names":["ReimbursementFormSchema","z","MAX_REIMBURSEMENT_AMOUNT","DraftReimbursementSchema","val","num","nonNegativeAmountSchema","MAX_HOURS","hoursAmountSchema","PayrollEditEmployeeFormSchema","PayrollEmployeeCompensationsTypePaymentMethod","buildCompensationFromFormData","formData","employeeCompensation","timeOff","primaryJobUuid","payrollCategory","PayrollCategory","updatedCompensation","compensation","hours","timeOffEntry","isDismissal","_","timeOffWithoutPayout","finalPayout","usesItemizedReimbursements","isOffCyclePayroll","updatedFixedCompensations","fixedCompensationName","formAmount","COMPENSATION_NAME_REIMBURSEMENT","existingFixedCompensation","fixedCompensation","resolvedAmount","reimbursement","PayrollEditEmployeePresentation","className","onSave","onCancel","employee","isPending","fixedCompensationTypes","payPeriodStartDate","paySchedule","withReimbursements","hasDirectDepositSetup","Button","ButtonIcon","Heading","Text","useComponentContext","t","useTranslation","useI18n","primaryJob","job","primaryJobHasHourlyCompensations","c","hourlyJobs","containerRef","useRef","isSmallOrGreater","useContainerBreakpoints","hourlyJob","entry","additionalEarnings","getAdditionalEarningsCompensations","EXCLUDED_ADDITIONAL_EARNINGS","initialReimbursements","useMemo","existingReimbursementFixedCompensation","comp","showLegacyReimbursementField","findMatchingCompensation","jobUuid","compensationName","getCompensationLabel","COMPENSATION_NAME_REGULAR_HOURS","COMPENSATION_NAME_OVERTIME","COMPENSATION_NAME_DOUBLE_OVERTIME","getFixedCompensationLabel","COMPENSATION_NAME_BONUS","COMPENSATION_NAME_PAYCHECK_TIPS","COMPENSATION_NAME_CORRECTION_PAYMENT","COMPENSATION_NAME_COMMISSION","COMPENSATION_NAME_CASH_TIPS","resolveDefaultPaymentMethod","preparedPaymentMethod","defaultValues","hourlyCompensations","HOURS_COMPENSATION_NAMES","matchingCompensation","timeOffCompensations","timeOffCompensation","finalPayoutCompensations","fixedCompensations","fixedComp","formHandlers","useForm","zodResolver","reimbursementFields","appendReimbursement","removeReimbursement","updateReimbursement","useFieldArray","handleRemoveReimbursement","index","field","visibleReimbursementRows","originalIndex","row","isAddingReimbursement","setIsAddingReimbursement","useState","draftForm","resetReimbursementDraft","onDraftReimbursementValid","data","parsedAmount","reimbursementDataViewProps","useDataView","formatNumberAsCurrency","displayDescription","jsx","TrashCanSvg","EmptyData","PlusCircleIcon","watchedFormData","useWatch","currentGrossPay","jobId","compensations","reimbursementsWithDefaults","formDataWithDefaults","calculateGrossPay","employeeName","firstLastName","onSubmit","formattedCurrentGrossPay","actions","jsxs","Flex","classNames","styles","FormProvider","Form","Grid","employeeHourlyCompensation","TextInputField","stripLeadingZeros","TimeOffField","PayoutTimeOffField","DataView","RadioGroupField"],"mappings":"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"}
|
|
@@ -63,7 +63,7 @@ function Yt({
|
|
|
63
63
|
const j = Ne(
|
|
64
64
|
{ companyId: l, payScheduleId: n?.payPeriod?.payScheduleUuid ?? "" },
|
|
65
65
|
{ enabled: !!n?.payPeriod?.payScheduleUuid }
|
|
66
|
-
), a = te.
|
|
66
|
+
), a = te.employeeShow, s = n?.employeeCompensations?.find(
|
|
67
67
|
(e) => e.employeeUuid === u
|
|
68
68
|
), S = X(n ?? {}), d = (re.employeeBankAccounts?.length ?? 0) > 0, i = o(
|
|
69
69
|
() => n ? Je(n.workweeks, n.payPeriod) : [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePayrollEditEmployeeForm.js","sources":["../../../../../../src/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useFieldArray, useForm, useWatch } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { useEmployeesGetSuspense } from '@gusto/embedded-api/react-query/employeesGet'\nimport { useEmployeePaymentMethodsGetBankAccountsSuspense } from '@gusto/embedded-api/react-query/employeePaymentMethodsGetBankAccounts'\nimport { useEarningTypesListSuspense } from '@gusto/embedded-api/react-query/earningTypesList'\nimport { usePayrollsGetSuspense } from '@gusto/embedded-api/react-query/payrollsGet'\nimport { usePayrollsPrepareMutation } from '@gusto/embedded-api/react-query/payrollsPrepare'\nimport { usePaySchedulesGet } from '@gusto/embedded-api/react-query/paySchedulesGet'\nimport { usePayrollsUpdateMutation } from '@gusto/embedded-api/react-query/payrollsUpdate'\nimport type { Employee } from '@gusto/embedded-api/models/components/employee'\nimport type { PayrollEmployeeCompensationsType } from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport type { PayrollPrepared } from '@gusto/embedded-api/models/components/payrollshow'\nimport type { PayScheduleShow } from '@gusto/embedded-api/models/components/payscheduleshow'\nimport { UnprocessableEntityError } from '@gusto/embedded-api/models/errors/unprocessableentityerror'\nimport {\n createPayrollEditEmployeeSchema,\n PAYMENT_METHOD_OPTIONS,\n PAYMENT_METHOD_VALUES,\n PayrollEditEmployeeErrorCodes,\n reimbursementDraftSchema,\n type PayrollEditEmployeeFormData,\n type PayrollEditEmployeeFormOutputs,\n} from './payrollEditEmployeeSchema'\nimport {\n buildPayrollUpdateEmployeeCompensation,\n collectOvertimeEarningNames,\n derivePayrollEditEmployeeDefaults,\n hasBreakdownsMatchingWorkweeks,\n hasExistingOvertimeHours,\n normalizeWorkweeks,\n resolveEditableFixedCompensations,\n zeroFillClearedWorkweekCells,\n type NormalizedWorkweek,\n} from './payrollEditEmployeeHelpers'\nimport {\n computeTimeOffRemaining,\n createPayrollEditEmployeeFields,\n createReimbursementDraftFields,\n type PayrollEditEmployeeErrorMessages,\n type PayrollEditEmployeeFields,\n type ReimbursementDraftFields,\n type ReimbursementRow,\n} from './fields'\nimport { withOptions } from '@/partner-hook-utils/form/withOptions'\nimport {\n derivePayrollCategory,\n isOffCyclePayroll,\n PayrollCategory,\n} from '@/components/Payroll/payrollTypes'\nimport { PREPARE_QUERY_KEY } from '@/components/Payroll/PayrollConfiguration/usePayrollConfigurationData'\nimport { isOvertimeEligibleFlsaStatus } from '@/components/Payroll/helpers'\nimport { retryAsync } from '@/helpers/retryAsync'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport {\n composeErrorHandler,\n type QueryWithRefetch,\n} from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldMetadata,\n FieldMetadataWithOptions,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\n\nconst PREPARE_MAX_ATTEMPTS = 4\nconst PREPARE_RETRY_DELAY_MS = 1500\n\nconst isPayrollBeingProcessedError = (error: unknown): boolean =>\n error instanceof UnprocessableEntityError &&\n error.errors.some(issue => issue.category === 'invalid_operation')\n\n/**\n * Options accepted by {@link usePayrollEditEmployeeForm}.\n *\n * @public\n */\nexport interface UsePayrollEditEmployeeFormProps {\n /** The associated employee identifier. */\n employeeId: string\n /** The associated company identifier. */\n companyId: string\n /** The associated payroll identifier. */\n payrollId: string\n /**\n * Whether to expose reimbursement controls (`form.Fields.reimbursements`,\n * `actions.addReimbursement`/`removeReimbursement`, `form.reimbursements`).\n * Defaults to `true`. Controls are omitted for off-cycle payrolls regardless,\n * since those write reimbursements via the legacy fixed-compensation path.\n */\n withReimbursements?: boolean\n /** When validation runs. Passed through to react-hook-form. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Auto-focus the first invalid field on submit. Defaults to `true`. Set to `false` when composing with other forms. */\n shouldFocusError?: boolean\n /**\n * Display copy for each validation error code, baked into every bound field so\n * it resolves and renders its own message. Supply it once, keyed by\n * {@link PayrollEditEmployeeErrorCodes}; a missing code falls back to the raw\n * code. Omit it to render raw codes.\n */\n errorMessages?: PayrollEditEmployeeErrorMessages\n}\n\n/**\n * Field metadata for {@link usePayrollEditEmployeeForm}, keyed by full form path.\n *\n * @remarks\n * Keys are minted from the prepared payroll's compensations at runtime\n * (`hours.${jobUuid}.${name}.${workweekStart}` and similar), so neither the key\n * set nor which entries carry options is known ahead of time.\n *\n * @public\n */\nexport type PayrollEditEmployeeFieldsMetadata = Record<\n string,\n FieldMetadata | FieldMetadataWithOptions\n>\n\n/**\n * Ready-state return value of {@link usePayrollEditEmployeeForm} — the\n * `isLoading: false` branch of {@link UsePayrollEditEmployeeFormResult}.\n *\n * @public\n */\nexport interface UsePayrollEditEmployeeFormReady extends BaseFormHookReady<\n PayrollEditEmployeeFieldsMetadata,\n PayrollEditEmployeeFormData,\n PayrollEditEmployeeFields\n> {\n /** Loaded entities backing the editor. */\n data: {\n /** The employee being edited. */\n employee: Employee\n /** The employee's prepared compensation for this payroll, if present. */\n employeeCompensation?: PayrollEmployeeCompensationsType\n /** The prepared payroll (server-calculated totals and workweeks). */\n preparedPayroll: PayrollPrepared\n /** The pay schedule for the payroll, if loaded. */\n paySchedule?: PayScheduleShow\n /** Whether the pay period spans more than one workweek. Raw workweeks are on `preparedPayroll.workweeks`. */\n isMultipleWorkweeks: boolean\n /**\n * The pay period's normalized workweeks (`{ startDate, endDate }` strings),\n * in order — one entry, spanning the pay period, when it's a single\n * workweek. The per-workweek split fields are keyed by start date only, so\n * this is the source for each column's date range.\n */\n workweeks: NormalizedWorkweek[]\n /** Whether the employee is overtime-eligible (nonexempt family). Drives whether hours split by workweek. */\n isOvertimeEligible: boolean\n /**\n * The single, form-wide overtime-mode flag. `false` renders one flat\n * column per line with Overtime/Double-overtime rows hidden; `true`\n * splits hours and overtime-affecting earnings into per-workweek columns\n * (for overtime-eligible employees on a multi-workweek payroll) and\n * un-hides those rows. Starts `true` when the employee already has real\n * overtime hours or matching per-workweek breakdowns (see\n * `hasExistingOvertimeHours`, `hasBreakdownsMatchingWorkweeks`), or after\n * `actions.addOvertime` is called; otherwise starts `false`.\n */\n withOvertime: boolean\n /** Whether the employee has a direct-deposit bank account set up. */\n hasDirectDepositSetup: boolean\n /**\n * Committed reimbursement rows to render in a table, present only when\n * reimbursement controls are exposed. Seeded from the employee's existing\n * reimbursements and appended to as drafts are saved. Remove a row via\n * `actions.removeReimbursement(row.index)`.\n */\n reimbursements?: ReimbursementRow[]\n }\n /** Submission status. `mode` is always `'update'` since the payroll already exists. */\n status: { isPending: boolean; mode: 'update' }\n /** Form actions. */\n actions: {\n /** Validates and submits the form, resolving to the updated prepared payroll on success or `undefined` when validation blocked the submit. */\n onSubmit: () => Promise<HookSubmitResult<PayrollPrepared> | undefined>\n /**\n * Sets `data.withOvertime` to `true`, switching the whole form to the\n * workweek split: un-hides Overtime/Double-overtime rows and splits hours\n * and overtime-affecting earnings into per-workweek columns. Populates\n * only the first workweek cell of each line with that line's current\n * total, leaving every other cell blank — no auto distribution — so the\n * per-row validation then requires the user to fill in the rest. One\n * affordance for the whole employee, not one per job. One-directional —\n * there's no corresponding \"remove overtime\" action.\n */\n addOvertime: () => void\n /** Reveals the draft reimbursement row. Present only when reimbursement controls are exposed. */\n beginAddReimbursement?: () => void\n /** Validates the draft and commits it to the reimbursement list, or flags the draft amount if invalid. Present only when reimbursement controls are exposed. */\n saveReimbursement?: () => void\n /** Discards the draft reimbursement row. Present only when reimbursement controls are exposed. */\n cancelReimbursement?: () => void\n /** Removes the committed reimbursement row at `index` (zeroing existing rows so the update clears them). Present only when reimbursement controls are exposed. */\n removeReimbursement?: (index: number) => void\n }\n /** Form internals plus the reimbursement draft state. */\n form: BaseFormHookReady<\n PayrollEditEmployeeFieldsMetadata,\n PayrollEditEmployeeFormData,\n PayrollEditEmployeeFields\n >['form'] & {\n /** Draft reimbursement state, present only when reimbursement controls are exposed. */\n reimbursementDraft?: { isAdding: boolean }\n }\n}\n\n/**\n * Discriminated union returned by {@link usePayrollEditEmployeeForm}. Loading\n * branch carries only `errorHandling`; ready branch carries form data, fields,\n * status, and actions.\n *\n * @public\n */\nexport type UsePayrollEditEmployeeFormResult = HookLoadingResult | UsePayrollEditEmployeeFormReady\n\n/**\n * Headless form hook for editing a single employee's compensation within a\n * payroll run, built for regular-rate-of-pay (RRoP) support.\n *\n * @remarks\n * Prepares the payroll for the target employee, then exposes a workweek-keyed\n * form whose submit builds a `PayrollUpdate`. Single-workweek pay periods send\n * totals without `breakdowns`; multi-workweek pay periods send `breakdowns` per\n * line once that line's every workweek cell is filled. Overtime-eligible\n * (nonexempt) employees split hours and overtime-affecting earnings per\n * workweek while the single `data.withOvertime` flag is on (see\n * `actions.addOvertime`); everyone else, and every line while `withOvertime` is\n * off, edits flat totals.\n *\n * @param props - Hook options.\n * @returns A loading result while data is fetching, or a ready result with data,\n * fields, status, actions, and error handling.\n * @public\n */\nexport function usePayrollEditEmployeeForm({\n employeeId,\n companyId,\n payrollId,\n withReimbursements = true,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n errorMessages,\n}: UsePayrollEditEmployeeFormProps): UsePayrollEditEmployeeFormResult {\n const { data: employeeData } = useEmployeesGetSuspense({ employeeId })\n const { data: bankAccountsList } = useEmployeePaymentMethodsGetBankAccountsSuspense({\n employeeId,\n })\n const { data: earningTypesData } = useEarningTypesListSuspense({ companyId })\n const { data: payrollData } = usePayrollsGetSuspense({ companyId, payrollId })\n const isTransitionPayroll =\n derivePayrollCategory(payrollData.payrollShow ?? {}) === PayrollCategory.Transition\n\n const queryClient = useQueryClient()\n const { mutateAsync: preparePayroll } = usePayrollsPrepareMutation()\n const { mutateAsync: updatePayroll, isPending } = usePayrollsUpdateMutation()\n\n const [preparedPayroll, setPreparedPayroll] = useState<PayrollPrepared | undefined>()\n const [prepareError, setPrepareError] = useState<Error | null>(null)\n const hasFiredRef = useRef(false)\n\n const executePrepare = useCallback(async () => {\n setPrepareError(null)\n try {\n const result = await retryAsync(\n () =>\n preparePayroll({\n request: {\n companyId,\n payrollId,\n requestBody: { employeeUuids: isTransitionPayroll ? undefined : [employeeId] },\n },\n }),\n {\n maxAttempts: PREPARE_MAX_ATTEMPTS,\n delayMs: PREPARE_RETRY_DELAY_MS,\n shouldRetry: isPayrollBeingProcessedError,\n },\n )\n setPreparedPayroll(result.payrollPrepared)\n } catch (error) {\n setPrepareError(error as Error)\n }\n }, [companyId, payrollId, employeeId, preparePayroll, isTransitionPayroll])\n\n useEffect(() => {\n if (hasFiredRef.current) return\n hasFiredRef.current = true\n void executePrepare()\n }, [executePrepare])\n\n const payScheduleQuery = usePaySchedulesGet(\n { companyId, payScheduleId: preparedPayroll?.payPeriod?.payScheduleUuid ?? '' },\n { enabled: !!preparedPayroll?.payPeriod?.payScheduleUuid },\n )\n\n const employee = employeeData.employee\n const employeeCompensation = preparedPayroll?.employeeCompensations?.find(\n comp => comp.employeeUuid === employeeId,\n )\n const payrollCategory = derivePayrollCategory(preparedPayroll ?? {})\n const hasDirectDepositSetup = (bankAccountsList.employeeBankAccounts?.length ?? 0) > 0\n\n // Only normalize once the payroll is prepared: normalizeWorkweeks throws on a\n // payroll with neither workweeks nor a pay period, and before prepare resolves\n // both are legitimately absent (still loading, not malformed).\n const workweeks = useMemo(\n () =>\n preparedPayroll\n ? normalizeWorkweeks(preparedPayroll.workweeks, preparedPayroll.payPeriod)\n : [],\n [preparedPayroll],\n )\n\n const overtimeEarningNames = useMemo(\n () => collectOvertimeEarningNames(earningTypesData.earningTypeList),\n [earningTypesData.earningTypeList],\n )\n\n // Source of truth for the employee's FLSA status: prefer the prepared\n // compensation's hourly lines (the same data the fields are built from, so the\n // gate and the rendered lines always agree), falling back to the employee's\n // primary-job compensation. Unknown status is treated as not overtime-eligible.\n const flsaStatus = useMemo(() => {\n const fromCompensation = employeeCompensation?.hourlyCompensations?.find(\n compensation => compensation.flsaStatus,\n )?.flsaStatus\n if (fromCompensation) return fromCompensation\n const primaryJob = employee?.jobs?.find(job => job.primary)\n return primaryJob?.compensations?.[0]?.flsaStatus\n }, [employeeCompensation, employee])\n const isOvertimeEligible = isOvertimeEligibleFlsaStatus(flsaStatus)\n\n // Starts on when the employee already has real overtime hours, or already has\n // per-workweek breakdowns matching the current pay period's workweeks (nothing\n // to hide either way), otherwise starts off until the user opts in via\n // `actions.addOvertime`. One-directional: there's no \"remove overtime\" action.\n const [withOvertimeSetByUser, setWithOvertimeSetByUser] = useState(false)\n const withOvertime =\n withOvertimeSetByUser ||\n hasExistingOvertimeHours(employeeCompensation?.hourlyCompensations) ||\n hasBreakdownsMatchingWorkweeks(employeeCompensation?.hourlyCompensations, workweeks)\n\n const primaryJobUuid = useMemo(() => employee?.jobs?.find(job => job.primary)?.uuid, [employee])\n\n // Seed a blank input for every payroll fixed-compensation type (like the stable\n // editor), then let the field/defaults builders split them into additional\n // earnings vs `overtimeExcludedEarnings` by overtime inclusion. Without this, an employee whose\n // prepared payroll carries no fixed compensations shows no earnings inputs.\n const resolvedFixedCompensations = useMemo(\n () =>\n resolveEditableFixedCompensations(\n employeeCompensation?.fixedCompensations,\n preparedPayroll?.fixedCompensationTypes,\n primaryJobUuid,\n flsaStatus,\n ),\n [employeeCompensation, preparedPayroll?.fixedCompensationTypes, primaryJobUuid, flsaStatus],\n )\n\n const jobTitlesByUuid = useMemo(() => {\n const titles = new Map<string, string>()\n for (const job of employee?.jobs ?? []) {\n if (job.uuid && job.title) titles.set(job.uuid, job.title)\n }\n return titles\n }, [employee])\n\n // Accrual balance per time-off policy, owned by the hook (rather than looked\n // up in the consumer) so the time-off field can render its own live remaining\n // balance.\n const timeOffAccrualByName = useMemo(() => {\n const balances = new Map<string, string>()\n for (const policy of employee?.eligiblePaidTimeOff ?? []) {\n if (policy.name && policy.accrualBalance != null) {\n balances.set(policy.name, policy.accrualBalance)\n }\n }\n return balances\n }, [employee])\n\n const schema = useMemo(() => createPayrollEditEmployeeSchema(), [])\n\n const resolvedDefaults = useMemo(\n () =>\n derivePayrollEditEmployeeDefaults(\n employeeCompensation,\n workweeks,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n resolvedFixedCompensations,\n ),\n [\n employeeCompensation,\n workweeks,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n resolvedFixedCompensations,\n ],\n )\n\n const formMethods = useForm<PayrollEditEmployeeFormData, unknown, PayrollEditEmployeeFormOutputs>(\n {\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n },\n )\n\n // Watched so each `Fields.timeOff[i].remaining` stays live as the user edits\n // hours. The whole form re-renders on keystroke regardless of who owns this\n // watch, so there's no cost to owning it here rather than in a per-row\n // subcomponent.\n const watchedTimeOff = useWatch({ control: formMethods.control, name: 'timeOff' })\n\n // Off-cycle payrolls write reimbursements via the legacy fixed-compensation path\n // (the itemized array is rejected server-side), so itemized reimbursement controls\n // are exposed only for regular payrolls and only when the partner opts in.\n const usesItemizedReimbursements = !isOffCyclePayroll(payrollCategory)\n const showReimbursements = withReimbursements && usesItemizedReimbursements\n\n const {\n fields: reimbursementArrayFields,\n append: appendReimbursement,\n remove: removeReimbursementRow,\n update: updateReimbursementRow,\n } = useFieldArray({\n control: formMethods.control,\n name: 'reimbursements',\n })\n\n const [isAddingReimbursement, setIsAddingReimbursement] = useState(false)\n\n const reimbursementDraftFields = useMemo<ReimbursementDraftFields>(\n () => createReimbursementDraftFields(errorMessages),\n [errorMessages],\n )\n\n // Committed rows for the consumer's table. A removed existing row (one with a\n // uuid) is zeroed rather than dropped so the update still clears it server-side;\n // those zero-amount rows are filtered out of the visible list but remain in the\n // form array for submit.\n const reimbursementRows = useMemo<ReimbursementRow[]>(\n () =>\n reimbursementArrayFields\n .map((field, index) => ({\n key: field.id,\n index,\n uuid: field.uuid ?? undefined,\n description: field.description,\n amount: field.amount,\n recurring: field.recurring ?? false,\n }))\n .filter(row => parseFloat(row.amount || '0') !== 0),\n [reimbursementArrayFields],\n )\n\n const beginAddReimbursement = useCallback(() => {\n setIsAddingReimbursement(true)\n }, [])\n\n const cancelReimbursement = useCallback(() => {\n formMethods.setValue('reimbursementDraft', { description: '', amount: '' })\n formMethods.clearErrors('reimbursementDraft')\n setIsAddingReimbursement(false)\n }, [formMethods])\n\n const saveReimbursement = useCallback(() => {\n const draft = formMethods.getValues('reimbursementDraft')\n const result = reimbursementDraftSchema.safeParse(draft)\n if (!result.success) {\n // The error code is a fallback; the field renders the consumer-supplied\n // `errorMessage` prop when present (see useField), so the copy is theirs to set.\n formMethods.setError('reimbursementDraft.amount', {\n message: PayrollEditEmployeeErrorCodes.REIMBURSEMENT_AMOUNT,\n })\n return\n }\n appendReimbursement({\n uuid: null,\n description: result.data.description.trim(),\n amount: parseFloat(result.data.amount).toFixed(2),\n recurring: false,\n })\n formMethods.setValue('reimbursementDraft', { description: '', amount: '' })\n formMethods.clearErrors('reimbursementDraft')\n setIsAddingReimbursement(false)\n }, [appendReimbursement, formMethods])\n\n const removeReimbursement = useCallback(\n (index: number) => {\n const field = reimbursementArrayFields[index]\n if (!field) return\n if (field.uuid) {\n updateReimbursementRow(index, { ...field, amount: '0' })\n } else {\n removeReimbursementRow(index)\n }\n },\n [reimbursementArrayFields, removeReimbursementRow, updateReimbursementRow],\n )\n\n const fields = useMemo(\n () =>\n createPayrollEditEmployeeFields({\n employeeCompensation,\n fixedCompensations: resolvedFixedCompensations,\n workweeks,\n payrollCategory,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n jobTitlesByUuid,\n timeOffAccrualByName,\n errorMessages,\n }),\n [\n employeeCompensation,\n resolvedFixedCompensations,\n workweeks,\n payrollCategory,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n jobTitlesByUuid,\n timeOffAccrualByName,\n errorMessages,\n ],\n )\n\n // Overlay the live remaining balance onto each time-off entry every render, so\n // it tracks the watched entered values without rebuilding (and remounting) the\n // bound field components the `fields` memo owns.\n const timeOffFields = useMemo(\n () =>\n fields.timeOff.map(entry => ({\n ...entry,\n remaining: computeTimeOffRemaining(\n timeOffAccrualByName.get(entry.name),\n watchedTimeOff[entry.name],\n ),\n })),\n [fields.timeOff, timeOffAccrualByName, watchedTimeOff],\n )\n\n // Re-derives with `withOvertime` forced `true` and pushes the result straight\n // into the form: every line's first workweek cell gets that line's current\n // total, every other cell is left blank (never auto-distributed — see\n // `derivePayrollEditEmployeeDefaults`/`buildWeekMap`). The per-row validation\n // then requires the user to fill in the rest before they can submit.\n // `setValue` (not `resetField`) is used so this overwrites even a value the\n // user already typed into the collapsed input. Plain function (not memoized):\n // it only runs on a user click, and its inputs are recomputed each render, so\n // a `useCallback` here would never actually hold a stable reference.\n const addOvertime = () => {\n setWithOvertimeSetByUser(true)\n const revealedDefaults = derivePayrollEditEmployeeDefaults(\n employeeCompensation,\n workweeks,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n true,\n resolvedFixedCompensations,\n )\n // Keep the user's edited collapsed value on the first workweek cell rather\n // than the seeded API total.\n const firstWeekStart = workweeks[0]?.startDate ?? ''\n const currentValues = formMethods.getValues()\n const overlayLiveFirstWeek = (\n revealed: PayrollEditEmployeeFormData['hours'],\n live: PayrollEditEmployeeFormData['hours'] | undefined,\n ) => {\n for (const [jobUuid, names] of Object.entries(revealed)) {\n for (const [name, weekMap] of Object.entries(names)) {\n const liveValue = live?.[jobUuid]?.[name]?.[firstWeekStart]\n if (liveValue !== undefined) weekMap[firstWeekStart] = liveValue\n }\n }\n return revealed\n }\n // `shouldDirty` so the form's `values`-prop reset (triggered by flipping\n // `withOvertimeSetByUser`) keeps these via `keepDirtyValues`.\n formMethods.setValue(\n 'hours',\n overlayLiveFirstWeek(revealedDefaults.hours, currentValues.hours),\n { shouldDirty: true },\n )\n formMethods.setValue(\n 'overtimeIncludedEarnings',\n overlayLiveFirstWeek(\n revealedDefaults.overtimeIncludedEarnings,\n currentValues.overtimeIncludedEarnings,\n ),\n { shouldDirty: true },\n )\n }\n const fieldsMetadata = useMemo<PayrollEditEmployeeFieldsMetadata>(\n () => ({\n paymentMethod: withOptions(\n { name: 'paymentMethod' },\n PAYMENT_METHOD_OPTIONS,\n PAYMENT_METHOD_VALUES,\n ),\n }),\n [],\n )\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('PayrollEditEmployeeForm')\n\n const prepareQuerySource: QueryWithRefetch = {\n error: prepareError,\n refetch: (() => executePrepare()) as unknown as QueryWithRefetch['refetch'],\n }\n\n const errorHandling = composeErrorHandler([prepareQuerySource, payScheduleQuery], {\n submitError,\n setSubmitError,\n })\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n const onSubmit = async (): Promise<HookSubmitResult<PayrollPrepared> | undefined> => {\n let submitResult: HookSubmitResult<PayrollPrepared> | undefined\n\n // A workweek input that loaded with a value and was cleared by the user\n // submits an explicit `0` for that cell. Writing the `0` into form state\n // before validation lets the existing per-row check and submit builder run\n // unchanged: the cell is now filled rather than blank. Cells that were blank\n // at load stay blank (and keep validating as required in a touched row).\n const cleared = zeroFillClearedWorkweekCells(formMethods.getValues(), resolvedDefaults)\n if (cleared.hours) {\n formMethods.setValue('hours', cleared.hours, { shouldDirty: true })\n }\n if (cleared.overtimeIncludedEarnings) {\n formMethods.setValue('overtimeIncludedEarnings', cleared.overtimeIncludedEarnings, {\n shouldDirty: true,\n })\n }\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async data => {\n await baseSubmitHandler(data, async payload => {\n const compensation = buildPayrollUpdateEmployeeCompensation(\n payload,\n employeeCompensation,\n workweeks,\n payrollCategory,\n isOvertimeEligible,\n withOvertime,\n )\n\n const response = await updatePayroll({\n request: {\n companyId,\n payrollId,\n payrollUpdate: { employeeCompensations: [compensation] },\n },\n })\n\n const updated = response.payrollPrepared\n if (!updated) {\n throw new SDKInternalError('Payroll update did not return a prepared payroll')\n }\n\n setPreparedPayroll(updated)\n\n // The payroll configuration surface caches its prepared payroll under a hand-written\n // key, which the global SDK auto-invalidation (namespaced to @gusto/embedded-api\n // queries only) does not touch. Invalidate it explicitly so configuration reflects\n // this edit without a manual refresh.\n await queryClient.invalidateQueries({\n queryKey: [PREPARE_QUERY_KEY, payrollId],\n })\n\n submitResult = { mode: 'update', data: updated }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n if (!preparedPayroll || !employee) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n employee,\n employeeCompensation,\n preparedPayroll,\n paySchedule: payScheduleQuery.data?.payScheduleShow,\n isMultipleWorkweeks: workweeks.length > 1,\n workweeks,\n isOvertimeEligible,\n withOvertime,\n hasDirectDepositSetup,\n ...(showReimbursements ? { reimbursements: reimbursementRows } : {}),\n },\n status: { isPending, mode: 'update' as const },\n actions: {\n onSubmit,\n addOvertime,\n ...(showReimbursements\n ? {\n beginAddReimbursement,\n saveReimbursement,\n cancelReimbursement,\n removeReimbursement,\n }\n : {}),\n },\n errorHandling,\n form: {\n Fields: {\n ...fields,\n timeOff: timeOffFields,\n reimbursementDraft: showReimbursements ? reimbursementDraftFields : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n ...(showReimbursements ? { reimbursementDraft: { isAdding: isAddingReimbursement } } : {}),\n },\n }\n}\n"],"names":["PREPARE_MAX_ATTEMPTS","PREPARE_RETRY_DELAY_MS","isPayrollBeingProcessedError","error","UnprocessableEntityError","issue","usePayrollEditEmployeeForm","employeeId","companyId","payrollId","withReimbursements","validationMode","shouldFocusError","errorMessages","employeeData","useEmployeesGetSuspense","bankAccountsList","useEmployeePaymentMethodsGetBankAccountsSuspense","earningTypesData","useEarningTypesListSuspense","payrollData","usePayrollsGetSuspense","isTransitionPayroll","derivePayrollCategory","PayrollCategory","queryClient","useQueryClient","preparePayroll","usePayrollsPrepareMutation","updatePayroll","isPending","usePayrollsUpdateMutation","preparedPayroll","setPreparedPayroll","useState","prepareError","setPrepareError","hasFiredRef","useRef","executePrepare","useCallback","result","retryAsync","useEffect","payScheduleQuery","usePaySchedulesGet","employee","employeeCompensation","comp","payrollCategory","hasDirectDepositSetup","workweeks","useMemo","normalizeWorkweeks","overtimeEarningNames","collectOvertimeEarningNames","flsaStatus","fromCompensation","compensation","job","isOvertimeEligible","isOvertimeEligibleFlsaStatus","withOvertimeSetByUser","setWithOvertimeSetByUser","withOvertime","hasExistingOvertimeHours","hasBreakdownsMatchingWorkweeks","primaryJobUuid","resolvedFixedCompensations","resolveEditableFixedCompensations","jobTitlesByUuid","titles","timeOffAccrualByName","balances","policy","schema","createPayrollEditEmployeeSchema","resolvedDefaults","derivePayrollEditEmployeeDefaults","formMethods","useForm","zodResolver","watchedTimeOff","useWatch","usesItemizedReimbursements","isOffCyclePayroll","showReimbursements","reimbursementArrayFields","appendReimbursement","removeReimbursementRow","updateReimbursementRow","useFieldArray","isAddingReimbursement","setIsAddingReimbursement","reimbursementDraftFields","createReimbursementDraftFields","reimbursementRows","field","index","row","beginAddReimbursement","cancelReimbursement","saveReimbursement","draft","reimbursementDraftSchema","PayrollEditEmployeeErrorCodes","removeReimbursement","fields","createPayrollEditEmployeeFields","timeOffFields","entry","computeTimeOffRemaining","addOvertime","revealedDefaults","firstWeekStart","currentValues","overlayLiveFirstWeek","revealed","live","jobUuid","names","name","weekMap","liveValue","fieldsMetadata","withOptions","PAYMENT_METHOD_OPTIONS","PAYMENT_METHOD_VALUES","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","errorHandling","composeErrorHandler","hookFormInternals","useHookFormInternals","onSubmit","submitResult","cleared","zeroFillClearedWorkweekCells","resolve","data","payload","buildPayrollUpdateEmployeeCompensation","updated","SDKInternalError","PREPARE_QUERY_KEY","createGetFormSubmissionValues"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usePayrollEditEmployeeForm.js","sources":["../../../../../../src/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useFieldArray, useForm, useWatch } from 'react-hook-form'\nimport type { UseFormProps } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { useEmployeesGetSuspense } from '@gusto/embedded-api/react-query/employeesGet'\nimport { useEmployeePaymentMethodsGetBankAccountsSuspense } from '@gusto/embedded-api/react-query/employeePaymentMethodsGetBankAccounts'\nimport { useEarningTypesListSuspense } from '@gusto/embedded-api/react-query/earningTypesList'\nimport { usePayrollsGetSuspense } from '@gusto/embedded-api/react-query/payrollsGet'\nimport { usePayrollsPrepareMutation } from '@gusto/embedded-api/react-query/payrollsPrepare'\nimport { usePaySchedulesGet } from '@gusto/embedded-api/react-query/paySchedulesGet'\nimport { usePayrollsUpdateMutation } from '@gusto/embedded-api/react-query/payrollsUpdate'\nimport type { Employee } from '@gusto/embedded-api/models/components/employee'\nimport type { PayrollEmployeeCompensationsType } from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport type { PayrollPrepared } from '@gusto/embedded-api/models/components/unprocessedpayroll'\nimport type { PayScheduleShow } from '@gusto/embedded-api/models/components/payschedulelistitem'\nimport { UnprocessableEntityError } from '@gusto/embedded-api/models/errors/unprocessableentityerror'\nimport {\n createPayrollEditEmployeeSchema,\n PAYMENT_METHOD_OPTIONS,\n PAYMENT_METHOD_VALUES,\n PayrollEditEmployeeErrorCodes,\n reimbursementDraftSchema,\n type PayrollEditEmployeeFormData,\n type PayrollEditEmployeeFormOutputs,\n} from './payrollEditEmployeeSchema'\nimport {\n buildPayrollUpdateEmployeeCompensation,\n collectOvertimeEarningNames,\n derivePayrollEditEmployeeDefaults,\n hasBreakdownsMatchingWorkweeks,\n hasExistingOvertimeHours,\n normalizeWorkweeks,\n resolveEditableFixedCompensations,\n zeroFillClearedWorkweekCells,\n type NormalizedWorkweek,\n} from './payrollEditEmployeeHelpers'\nimport {\n computeTimeOffRemaining,\n createPayrollEditEmployeeFields,\n createReimbursementDraftFields,\n type PayrollEditEmployeeErrorMessages,\n type PayrollEditEmployeeFields,\n type ReimbursementDraftFields,\n type ReimbursementRow,\n} from './fields'\nimport { withOptions } from '@/partner-hook-utils/form/withOptions'\nimport {\n derivePayrollCategory,\n isOffCyclePayroll,\n PayrollCategory,\n} from '@/components/Payroll/payrollTypes'\nimport { PREPARE_QUERY_KEY } from '@/components/Payroll/PayrollConfiguration/usePayrollConfigurationData'\nimport { isOvertimeEligibleFlsaStatus } from '@/components/Payroll/helpers'\nimport { retryAsync } from '@/helpers/retryAsync'\nimport { useHookFormInternals } from '@/partner-hook-utils/form/useHookFormInternals'\nimport { createGetFormSubmissionValues } from '@/partner-hook-utils/form/getFormSubmissionValues'\nimport {\n composeErrorHandler,\n type QueryWithRefetch,\n} from '@/partner-hook-utils/composeErrorHandler'\nimport type {\n BaseFormHookReady,\n FieldMetadata,\n FieldMetadataWithOptions,\n HookLoadingResult,\n HookSubmitResult,\n} from '@/partner-hook-utils/types'\nimport { useBaseSubmit } from '@/components/Base/useBaseSubmit'\nimport { SDKInternalError } from '@/types/sdkError'\n\nconst PREPARE_MAX_ATTEMPTS = 4\nconst PREPARE_RETRY_DELAY_MS = 1500\n\nconst isPayrollBeingProcessedError = (error: unknown): boolean =>\n error instanceof UnprocessableEntityError &&\n error.errors.some(issue => issue.category === 'invalid_operation')\n\n/**\n * Options accepted by {@link usePayrollEditEmployeeForm}.\n *\n * @public\n */\nexport interface UsePayrollEditEmployeeFormProps {\n /** The associated employee identifier. */\n employeeId: string\n /** The associated company identifier. */\n companyId: string\n /** The associated payroll identifier. */\n payrollId: string\n /**\n * Whether to expose reimbursement controls (`form.Fields.reimbursements`,\n * `actions.addReimbursement`/`removeReimbursement`, `form.reimbursements`).\n * Defaults to `true`. Controls are omitted for off-cycle payrolls regardless,\n * since those write reimbursements via the legacy fixed-compensation path.\n */\n withReimbursements?: boolean\n /** When validation runs. Passed through to react-hook-form. Defaults to `'onSubmit'`. */\n validationMode?: UseFormProps['mode']\n /** Auto-focus the first invalid field on submit. Defaults to `true`. Set to `false` when composing with other forms. */\n shouldFocusError?: boolean\n /**\n * Display copy for each validation error code, baked into every bound field so\n * it resolves and renders its own message. Supply it once, keyed by\n * {@link PayrollEditEmployeeErrorCodes}; a missing code falls back to the raw\n * code. Omit it to render raw codes.\n */\n errorMessages?: PayrollEditEmployeeErrorMessages\n}\n\n/**\n * Field metadata for {@link usePayrollEditEmployeeForm}, keyed by full form path.\n *\n * @remarks\n * Keys are minted from the prepared payroll's compensations at runtime\n * (`hours.${jobUuid}.${name}.${workweekStart}` and similar), so neither the key\n * set nor which entries carry options is known ahead of time.\n *\n * @public\n */\nexport type PayrollEditEmployeeFieldsMetadata = Record<\n string,\n FieldMetadata | FieldMetadataWithOptions\n>\n\n/**\n * Ready-state return value of {@link usePayrollEditEmployeeForm} — the\n * `isLoading: false` branch of {@link UsePayrollEditEmployeeFormResult}.\n *\n * @public\n */\nexport interface UsePayrollEditEmployeeFormReady extends BaseFormHookReady<\n PayrollEditEmployeeFieldsMetadata,\n PayrollEditEmployeeFormData,\n PayrollEditEmployeeFields\n> {\n /** Loaded entities backing the editor. */\n data: {\n /** The employee being edited. */\n employee: Employee\n /** The employee's prepared compensation for this payroll, if present. */\n employeeCompensation?: PayrollEmployeeCompensationsType\n /** The prepared payroll (server-calculated totals and workweeks). */\n preparedPayroll: PayrollPrepared\n /** The pay schedule for the payroll, if loaded. */\n paySchedule?: PayScheduleShow\n /** Whether the pay period spans more than one workweek. Raw workweeks are on `preparedPayroll.workweeks`. */\n isMultipleWorkweeks: boolean\n /**\n * The pay period's normalized workweeks (`{ startDate, endDate }` strings),\n * in order — one entry, spanning the pay period, when it's a single\n * workweek. The per-workweek split fields are keyed by start date only, so\n * this is the source for each column's date range.\n */\n workweeks: NormalizedWorkweek[]\n /** Whether the employee is overtime-eligible (nonexempt family). Drives whether hours split by workweek. */\n isOvertimeEligible: boolean\n /**\n * The single, form-wide overtime-mode flag. `false` renders one flat\n * column per line with Overtime/Double-overtime rows hidden; `true`\n * splits hours and overtime-affecting earnings into per-workweek columns\n * (for overtime-eligible employees on a multi-workweek payroll) and\n * un-hides those rows. Starts `true` when the employee already has real\n * overtime hours or matching per-workweek breakdowns (see\n * `hasExistingOvertimeHours`, `hasBreakdownsMatchingWorkweeks`), or after\n * `actions.addOvertime` is called; otherwise starts `false`.\n */\n withOvertime: boolean\n /** Whether the employee has a direct-deposit bank account set up. */\n hasDirectDepositSetup: boolean\n /**\n * Committed reimbursement rows to render in a table, present only when\n * reimbursement controls are exposed. Seeded from the employee's existing\n * reimbursements and appended to as drafts are saved. Remove a row via\n * `actions.removeReimbursement(row.index)`.\n */\n reimbursements?: ReimbursementRow[]\n }\n /** Submission status. `mode` is always `'update'` since the payroll already exists. */\n status: { isPending: boolean; mode: 'update' }\n /** Form actions. */\n actions: {\n /** Validates and submits the form, resolving to the updated prepared payroll on success or `undefined` when validation blocked the submit. */\n onSubmit: () => Promise<HookSubmitResult<PayrollPrepared> | undefined>\n /**\n * Sets `data.withOvertime` to `true`, switching the whole form to the\n * workweek split: un-hides Overtime/Double-overtime rows and splits hours\n * and overtime-affecting earnings into per-workweek columns. Populates\n * only the first workweek cell of each line with that line's current\n * total, leaving every other cell blank — no auto distribution — so the\n * per-row validation then requires the user to fill in the rest. One\n * affordance for the whole employee, not one per job. One-directional —\n * there's no corresponding \"remove overtime\" action.\n */\n addOvertime: () => void\n /** Reveals the draft reimbursement row. Present only when reimbursement controls are exposed. */\n beginAddReimbursement?: () => void\n /** Validates the draft and commits it to the reimbursement list, or flags the draft amount if invalid. Present only when reimbursement controls are exposed. */\n saveReimbursement?: () => void\n /** Discards the draft reimbursement row. Present only when reimbursement controls are exposed. */\n cancelReimbursement?: () => void\n /** Removes the committed reimbursement row at `index` (zeroing existing rows so the update clears them). Present only when reimbursement controls are exposed. */\n removeReimbursement?: (index: number) => void\n }\n /** Form internals plus the reimbursement draft state. */\n form: BaseFormHookReady<\n PayrollEditEmployeeFieldsMetadata,\n PayrollEditEmployeeFormData,\n PayrollEditEmployeeFields\n >['form'] & {\n /** Draft reimbursement state, present only when reimbursement controls are exposed. */\n reimbursementDraft?: { isAdding: boolean }\n }\n}\n\n/**\n * Discriminated union returned by {@link usePayrollEditEmployeeForm}. Loading\n * branch carries only `errorHandling`; ready branch carries form data, fields,\n * status, and actions.\n *\n * @public\n */\nexport type UsePayrollEditEmployeeFormResult = HookLoadingResult | UsePayrollEditEmployeeFormReady\n\n/**\n * Headless form hook for editing a single employee's compensation within a\n * payroll run, built for regular-rate-of-pay (RRoP) support.\n *\n * @remarks\n * Prepares the payroll for the target employee, then exposes a workweek-keyed\n * form whose submit builds a `PayrollUpdate`. Single-workweek pay periods send\n * totals without `breakdowns`; multi-workweek pay periods send `breakdowns` per\n * line once that line's every workweek cell is filled. Overtime-eligible\n * (nonexempt) employees split hours and overtime-affecting earnings per\n * workweek while the single `data.withOvertime` flag is on (see\n * `actions.addOvertime`); everyone else, and every line while `withOvertime` is\n * off, edits flat totals.\n *\n * @param props - Hook options.\n * @returns A loading result while data is fetching, or a ready result with data,\n * fields, status, actions, and error handling.\n * @public\n */\nexport function usePayrollEditEmployeeForm({\n employeeId,\n companyId,\n payrollId,\n withReimbursements = true,\n validationMode = 'onSubmit',\n shouldFocusError = true,\n errorMessages,\n}: UsePayrollEditEmployeeFormProps): UsePayrollEditEmployeeFormResult {\n const { data: employeeData } = useEmployeesGetSuspense({ employeeId })\n const { data: bankAccountsList } = useEmployeePaymentMethodsGetBankAccountsSuspense({\n employeeId,\n })\n const { data: earningTypesData } = useEarningTypesListSuspense({ companyId })\n const { data: payrollData } = usePayrollsGetSuspense({ companyId, payrollId })\n const isTransitionPayroll =\n derivePayrollCategory(payrollData.payrollShow ?? {}) === PayrollCategory.Transition\n\n const queryClient = useQueryClient()\n const { mutateAsync: preparePayroll } = usePayrollsPrepareMutation()\n const { mutateAsync: updatePayroll, isPending } = usePayrollsUpdateMutation()\n\n const [preparedPayroll, setPreparedPayroll] = useState<PayrollPrepared | undefined>()\n const [prepareError, setPrepareError] = useState<Error | null>(null)\n const hasFiredRef = useRef(false)\n\n const executePrepare = useCallback(async () => {\n setPrepareError(null)\n try {\n const result = await retryAsync(\n () =>\n preparePayroll({\n request: {\n companyId,\n payrollId,\n requestBody: { employeeUuids: isTransitionPayroll ? undefined : [employeeId] },\n },\n }),\n {\n maxAttempts: PREPARE_MAX_ATTEMPTS,\n delayMs: PREPARE_RETRY_DELAY_MS,\n shouldRetry: isPayrollBeingProcessedError,\n },\n )\n setPreparedPayroll(result.payrollPrepared)\n } catch (error) {\n setPrepareError(error as Error)\n }\n }, [companyId, payrollId, employeeId, preparePayroll, isTransitionPayroll])\n\n useEffect(() => {\n if (hasFiredRef.current) return\n hasFiredRef.current = true\n void executePrepare()\n }, [executePrepare])\n\n const payScheduleQuery = usePaySchedulesGet(\n { companyId, payScheduleId: preparedPayroll?.payPeriod?.payScheduleUuid ?? '' },\n { enabled: !!preparedPayroll?.payPeriod?.payScheduleUuid },\n )\n\n const employee = employeeData.employeeShow\n const employeeCompensation = preparedPayroll?.employeeCompensations?.find(\n comp => comp.employeeUuid === employeeId,\n )\n const payrollCategory = derivePayrollCategory(preparedPayroll ?? {})\n const hasDirectDepositSetup = (bankAccountsList.employeeBankAccounts?.length ?? 0) > 0\n\n // Only normalize once the payroll is prepared: normalizeWorkweeks throws on a\n // payroll with neither workweeks nor a pay period, and before prepare resolves\n // both are legitimately absent (still loading, not malformed).\n const workweeks = useMemo(\n () =>\n preparedPayroll\n ? normalizeWorkweeks(preparedPayroll.workweeks, preparedPayroll.payPeriod)\n : [],\n [preparedPayroll],\n )\n\n const overtimeEarningNames = useMemo(\n () => collectOvertimeEarningNames(earningTypesData.earningTypeList),\n [earningTypesData.earningTypeList],\n )\n\n // Source of truth for the employee's FLSA status: prefer the prepared\n // compensation's hourly lines (the same data the fields are built from, so the\n // gate and the rendered lines always agree), falling back to the employee's\n // primary-job compensation. Unknown status is treated as not overtime-eligible.\n const flsaStatus = useMemo(() => {\n const fromCompensation = employeeCompensation?.hourlyCompensations?.find(\n compensation => compensation.flsaStatus,\n )?.flsaStatus\n if (fromCompensation) return fromCompensation\n const primaryJob = employee?.jobs?.find(job => job.primary)\n return primaryJob?.compensations?.[0]?.flsaStatus\n }, [employeeCompensation, employee])\n const isOvertimeEligible = isOvertimeEligibleFlsaStatus(flsaStatus)\n\n // Starts on when the employee already has real overtime hours, or already has\n // per-workweek breakdowns matching the current pay period's workweeks (nothing\n // to hide either way), otherwise starts off until the user opts in via\n // `actions.addOvertime`. One-directional: there's no \"remove overtime\" action.\n const [withOvertimeSetByUser, setWithOvertimeSetByUser] = useState(false)\n const withOvertime =\n withOvertimeSetByUser ||\n hasExistingOvertimeHours(employeeCompensation?.hourlyCompensations) ||\n hasBreakdownsMatchingWorkweeks(employeeCompensation?.hourlyCompensations, workweeks)\n\n const primaryJobUuid = useMemo(() => employee?.jobs?.find(job => job.primary)?.uuid, [employee])\n\n // Seed a blank input for every payroll fixed-compensation type (like the stable\n // editor), then let the field/defaults builders split them into additional\n // earnings vs `overtimeExcludedEarnings` by overtime inclusion. Without this, an employee whose\n // prepared payroll carries no fixed compensations shows no earnings inputs.\n const resolvedFixedCompensations = useMemo(\n () =>\n resolveEditableFixedCompensations(\n employeeCompensation?.fixedCompensations,\n preparedPayroll?.fixedCompensationTypes,\n primaryJobUuid,\n flsaStatus,\n ),\n [employeeCompensation, preparedPayroll?.fixedCompensationTypes, primaryJobUuid, flsaStatus],\n )\n\n const jobTitlesByUuid = useMemo(() => {\n const titles = new Map<string, string>()\n for (const job of employee?.jobs ?? []) {\n if (job.uuid && job.title) titles.set(job.uuid, job.title)\n }\n return titles\n }, [employee])\n\n // Accrual balance per time-off policy, owned by the hook (rather than looked\n // up in the consumer) so the time-off field can render its own live remaining\n // balance.\n const timeOffAccrualByName = useMemo(() => {\n const balances = new Map<string, string>()\n for (const policy of employee?.eligiblePaidTimeOff ?? []) {\n if (policy.name && policy.accrualBalance != null) {\n balances.set(policy.name, policy.accrualBalance)\n }\n }\n return balances\n }, [employee])\n\n const schema = useMemo(() => createPayrollEditEmployeeSchema(), [])\n\n const resolvedDefaults = useMemo(\n () =>\n derivePayrollEditEmployeeDefaults(\n employeeCompensation,\n workweeks,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n resolvedFixedCompensations,\n ),\n [\n employeeCompensation,\n workweeks,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n resolvedFixedCompensations,\n ],\n )\n\n const formMethods = useForm<PayrollEditEmployeeFormData, unknown, PayrollEditEmployeeFormOutputs>(\n {\n resolver: zodResolver(schema),\n mode: validationMode,\n shouldFocusError,\n defaultValues: resolvedDefaults,\n values: resolvedDefaults,\n resetOptions: { keepDirtyValues: true },\n },\n )\n\n // Watched so each `Fields.timeOff[i].remaining` stays live as the user edits\n // hours. The whole form re-renders on keystroke regardless of who owns this\n // watch, so there's no cost to owning it here rather than in a per-row\n // subcomponent.\n const watchedTimeOff = useWatch({ control: formMethods.control, name: 'timeOff' })\n\n // Off-cycle payrolls write reimbursements via the legacy fixed-compensation path\n // (the itemized array is rejected server-side), so itemized reimbursement controls\n // are exposed only for regular payrolls and only when the partner opts in.\n const usesItemizedReimbursements = !isOffCyclePayroll(payrollCategory)\n const showReimbursements = withReimbursements && usesItemizedReimbursements\n\n const {\n fields: reimbursementArrayFields,\n append: appendReimbursement,\n remove: removeReimbursementRow,\n update: updateReimbursementRow,\n } = useFieldArray({\n control: formMethods.control,\n name: 'reimbursements',\n })\n\n const [isAddingReimbursement, setIsAddingReimbursement] = useState(false)\n\n const reimbursementDraftFields = useMemo<ReimbursementDraftFields>(\n () => createReimbursementDraftFields(errorMessages),\n [errorMessages],\n )\n\n // Committed rows for the consumer's table. A removed existing row (one with a\n // uuid) is zeroed rather than dropped so the update still clears it server-side;\n // those zero-amount rows are filtered out of the visible list but remain in the\n // form array for submit.\n const reimbursementRows = useMemo<ReimbursementRow[]>(\n () =>\n reimbursementArrayFields\n .map((field, index) => ({\n key: field.id,\n index,\n uuid: field.uuid ?? undefined,\n description: field.description,\n amount: field.amount,\n recurring: field.recurring ?? false,\n }))\n .filter(row => parseFloat(row.amount || '0') !== 0),\n [reimbursementArrayFields],\n )\n\n const beginAddReimbursement = useCallback(() => {\n setIsAddingReimbursement(true)\n }, [])\n\n const cancelReimbursement = useCallback(() => {\n formMethods.setValue('reimbursementDraft', { description: '', amount: '' })\n formMethods.clearErrors('reimbursementDraft')\n setIsAddingReimbursement(false)\n }, [formMethods])\n\n const saveReimbursement = useCallback(() => {\n const draft = formMethods.getValues('reimbursementDraft')\n const result = reimbursementDraftSchema.safeParse(draft)\n if (!result.success) {\n // The error code is a fallback; the field renders the consumer-supplied\n // `errorMessage` prop when present (see useField), so the copy is theirs to set.\n formMethods.setError('reimbursementDraft.amount', {\n message: PayrollEditEmployeeErrorCodes.REIMBURSEMENT_AMOUNT,\n })\n return\n }\n appendReimbursement({\n uuid: null,\n description: result.data.description.trim(),\n amount: parseFloat(result.data.amount).toFixed(2),\n recurring: false,\n })\n formMethods.setValue('reimbursementDraft', { description: '', amount: '' })\n formMethods.clearErrors('reimbursementDraft')\n setIsAddingReimbursement(false)\n }, [appendReimbursement, formMethods])\n\n const removeReimbursement = useCallback(\n (index: number) => {\n const field = reimbursementArrayFields[index]\n if (!field) return\n if (field.uuid) {\n updateReimbursementRow(index, { ...field, amount: '0' })\n } else {\n removeReimbursementRow(index)\n }\n },\n [reimbursementArrayFields, removeReimbursementRow, updateReimbursementRow],\n )\n\n const fields = useMemo(\n () =>\n createPayrollEditEmployeeFields({\n employeeCompensation,\n fixedCompensations: resolvedFixedCompensations,\n workweeks,\n payrollCategory,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n jobTitlesByUuid,\n timeOffAccrualByName,\n errorMessages,\n }),\n [\n employeeCompensation,\n resolvedFixedCompensations,\n workweeks,\n payrollCategory,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n withOvertime,\n jobTitlesByUuid,\n timeOffAccrualByName,\n errorMessages,\n ],\n )\n\n // Overlay the live remaining balance onto each time-off entry every render, so\n // it tracks the watched entered values without rebuilding (and remounting) the\n // bound field components the `fields` memo owns.\n const timeOffFields = useMemo(\n () =>\n fields.timeOff.map(entry => ({\n ...entry,\n remaining: computeTimeOffRemaining(\n timeOffAccrualByName.get(entry.name),\n watchedTimeOff[entry.name],\n ),\n })),\n [fields.timeOff, timeOffAccrualByName, watchedTimeOff],\n )\n\n // Re-derives with `withOvertime` forced `true` and pushes the result straight\n // into the form: every line's first workweek cell gets that line's current\n // total, every other cell is left blank (never auto-distributed — see\n // `derivePayrollEditEmployeeDefaults`/`buildWeekMap`). The per-row validation\n // then requires the user to fill in the rest before they can submit.\n // `setValue` (not `resetField`) is used so this overwrites even a value the\n // user already typed into the collapsed input. Plain function (not memoized):\n // it only runs on a user click, and its inputs are recomputed each render, so\n // a `useCallback` here would never actually hold a stable reference.\n const addOvertime = () => {\n setWithOvertimeSetByUser(true)\n const revealedDefaults = derivePayrollEditEmployeeDefaults(\n employeeCompensation,\n workweeks,\n hasDirectDepositSetup,\n overtimeEarningNames,\n isOvertimeEligible,\n true,\n resolvedFixedCompensations,\n )\n // Keep the user's edited collapsed value on the first workweek cell rather\n // than the seeded API total.\n const firstWeekStart = workweeks[0]?.startDate ?? ''\n const currentValues = formMethods.getValues()\n const overlayLiveFirstWeek = (\n revealed: PayrollEditEmployeeFormData['hours'],\n live: PayrollEditEmployeeFormData['hours'] | undefined,\n ) => {\n for (const [jobUuid, names] of Object.entries(revealed)) {\n for (const [name, weekMap] of Object.entries(names)) {\n const liveValue = live?.[jobUuid]?.[name]?.[firstWeekStart]\n if (liveValue !== undefined) weekMap[firstWeekStart] = liveValue\n }\n }\n return revealed\n }\n // `shouldDirty` so the form's `values`-prop reset (triggered by flipping\n // `withOvertimeSetByUser`) keeps these via `keepDirtyValues`.\n formMethods.setValue(\n 'hours',\n overlayLiveFirstWeek(revealedDefaults.hours, currentValues.hours),\n { shouldDirty: true },\n )\n formMethods.setValue(\n 'overtimeIncludedEarnings',\n overlayLiveFirstWeek(\n revealedDefaults.overtimeIncludedEarnings,\n currentValues.overtimeIncludedEarnings,\n ),\n { shouldDirty: true },\n )\n }\n const fieldsMetadata = useMemo<PayrollEditEmployeeFieldsMetadata>(\n () => ({\n paymentMethod: withOptions(\n { name: 'paymentMethod' },\n PAYMENT_METHOD_OPTIONS,\n PAYMENT_METHOD_VALUES,\n ),\n }),\n [],\n )\n\n const {\n baseSubmitHandler,\n error: submitError,\n setError: setSubmitError,\n } = useBaseSubmit('PayrollEditEmployeeForm')\n\n const prepareQuerySource: QueryWithRefetch = {\n error: prepareError,\n refetch: (() => executePrepare()) as unknown as QueryWithRefetch['refetch'],\n }\n\n const errorHandling = composeErrorHandler([prepareQuerySource, payScheduleQuery], {\n submitError,\n setSubmitError,\n })\n\n const hookFormInternals = useHookFormInternals(formMethods)\n\n const onSubmit = async (): Promise<HookSubmitResult<PayrollPrepared> | undefined> => {\n let submitResult: HookSubmitResult<PayrollPrepared> | undefined\n\n // A workweek input that loaded with a value and was cleared by the user\n // submits an explicit `0` for that cell. Writing the `0` into form state\n // before validation lets the existing per-row check and submit builder run\n // unchanged: the cell is now filled rather than blank. Cells that were blank\n // at load stay blank (and keep validating as required in a touched row).\n const cleared = zeroFillClearedWorkweekCells(formMethods.getValues(), resolvedDefaults)\n if (cleared.hours) {\n formMethods.setValue('hours', cleared.hours, { shouldDirty: true })\n }\n if (cleared.overtimeIncludedEarnings) {\n formMethods.setValue('overtimeIncludedEarnings', cleared.overtimeIncludedEarnings, {\n shouldDirty: true,\n })\n }\n\n await new Promise<void>(resolve => {\n void formMethods.handleSubmit(\n async data => {\n await baseSubmitHandler(data, async payload => {\n const compensation = buildPayrollUpdateEmployeeCompensation(\n payload,\n employeeCompensation,\n workweeks,\n payrollCategory,\n isOvertimeEligible,\n withOvertime,\n )\n\n const response = await updatePayroll({\n request: {\n companyId,\n payrollId,\n payrollUpdate: { employeeCompensations: [compensation] },\n },\n })\n\n const updated = response.payrollPrepared\n if (!updated) {\n throw new SDKInternalError('Payroll update did not return a prepared payroll')\n }\n\n setPreparedPayroll(updated)\n\n // The payroll configuration surface caches its prepared payroll under a hand-written\n // key, which the global SDK auto-invalidation (namespaced to @gusto/embedded-api\n // queries only) does not touch. Invalidate it explicitly so configuration reflects\n // this edit without a manual refresh.\n await queryClient.invalidateQueries({\n queryKey: [PREPARE_QUERY_KEY, payrollId],\n })\n\n submitResult = { mode: 'update', data: updated }\n })\n resolve()\n },\n () => {\n resolve()\n },\n )()\n })\n\n return submitResult\n }\n\n if (!preparedPayroll || !employee) {\n return { isLoading: true as const, errorHandling }\n }\n\n return {\n isLoading: false as const,\n data: {\n employee,\n employeeCompensation,\n preparedPayroll,\n paySchedule: payScheduleQuery.data?.payScheduleShow,\n isMultipleWorkweeks: workweeks.length > 1,\n workweeks,\n isOvertimeEligible,\n withOvertime,\n hasDirectDepositSetup,\n ...(showReimbursements ? { reimbursements: reimbursementRows } : {}),\n },\n status: { isPending, mode: 'update' as const },\n actions: {\n onSubmit,\n addOvertime,\n ...(showReimbursements\n ? {\n beginAddReimbursement,\n saveReimbursement,\n cancelReimbursement,\n removeReimbursement,\n }\n : {}),\n },\n errorHandling,\n form: {\n Fields: {\n ...fields,\n timeOff: timeOffFields,\n reimbursementDraft: showReimbursements ? reimbursementDraftFields : undefined,\n },\n fieldsMetadata,\n hookFormInternals,\n getFormSubmissionValues: createGetFormSubmissionValues(formMethods, schema),\n ...(showReimbursements ? { reimbursementDraft: { isAdding: isAddingReimbursement } } : {}),\n },\n }\n}\n"],"names":["PREPARE_MAX_ATTEMPTS","PREPARE_RETRY_DELAY_MS","isPayrollBeingProcessedError","error","UnprocessableEntityError","issue","usePayrollEditEmployeeForm","employeeId","companyId","payrollId","withReimbursements","validationMode","shouldFocusError","errorMessages","employeeData","useEmployeesGetSuspense","bankAccountsList","useEmployeePaymentMethodsGetBankAccountsSuspense","earningTypesData","useEarningTypesListSuspense","payrollData","usePayrollsGetSuspense","isTransitionPayroll","derivePayrollCategory","PayrollCategory","queryClient","useQueryClient","preparePayroll","usePayrollsPrepareMutation","updatePayroll","isPending","usePayrollsUpdateMutation","preparedPayroll","setPreparedPayroll","useState","prepareError","setPrepareError","hasFiredRef","useRef","executePrepare","useCallback","result","retryAsync","useEffect","payScheduleQuery","usePaySchedulesGet","employee","employeeCompensation","comp","payrollCategory","hasDirectDepositSetup","workweeks","useMemo","normalizeWorkweeks","overtimeEarningNames","collectOvertimeEarningNames","flsaStatus","fromCompensation","compensation","job","isOvertimeEligible","isOvertimeEligibleFlsaStatus","withOvertimeSetByUser","setWithOvertimeSetByUser","withOvertime","hasExistingOvertimeHours","hasBreakdownsMatchingWorkweeks","primaryJobUuid","resolvedFixedCompensations","resolveEditableFixedCompensations","jobTitlesByUuid","titles","timeOffAccrualByName","balances","policy","schema","createPayrollEditEmployeeSchema","resolvedDefaults","derivePayrollEditEmployeeDefaults","formMethods","useForm","zodResolver","watchedTimeOff","useWatch","usesItemizedReimbursements","isOffCyclePayroll","showReimbursements","reimbursementArrayFields","appendReimbursement","removeReimbursementRow","updateReimbursementRow","useFieldArray","isAddingReimbursement","setIsAddingReimbursement","reimbursementDraftFields","createReimbursementDraftFields","reimbursementRows","field","index","row","beginAddReimbursement","cancelReimbursement","saveReimbursement","draft","reimbursementDraftSchema","PayrollEditEmployeeErrorCodes","removeReimbursement","fields","createPayrollEditEmployeeFields","timeOffFields","entry","computeTimeOffRemaining","addOvertime","revealedDefaults","firstWeekStart","currentValues","overlayLiveFirstWeek","revealed","live","jobUuid","names","name","weekMap","liveValue","fieldsMetadata","withOptions","PAYMENT_METHOD_OPTIONS","PAYMENT_METHOD_VALUES","baseSubmitHandler","submitError","setSubmitError","useBaseSubmit","errorHandling","composeErrorHandler","hookFormInternals","useHookFormInternals","onSubmit","submitResult","cleared","zeroFillClearedWorkweekCells","resolve","data","payload","buildPayrollUpdateEmployeeCompensation","updated","SDKInternalError","PREPARE_QUERY_KEY","createGetFormSubmissionValues"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PayrollHistory.js","sources":["../../../../src/components/Payroll/PayrollHistory/PayrollHistory.tsx"],"sourcesContent":["import { useState, useCallback } from 'react'\nimport { keepPreviousData } from '@tanstack/react-query'\nimport { usePayrollsList } from '@gusto/embedded-api/react-query/payrollsList'\nimport { usePayrollsCancelMutation } from '@gusto/embedded-api/react-query/payrollsCancel'\nimport { useWireInRequestsListSuspense } from '@gusto/embedded-api/react-query/wireInRequestsList'\nimport {\n ProcessingStatuses,\n QueryParamPayrollTypes,\n QueryParamSortOrder as SortOrder,\n} from '@gusto/embedded-api/models/operations/getv1companiescompanyidpayrolls'\nimport type { Payroll } from '@gusto/embedded-api/models/components/
|
|
1
|
+
{"version":3,"file":"PayrollHistory.js","sources":["../../../../src/components/Payroll/PayrollHistory/PayrollHistory.tsx"],"sourcesContent":["import { useState, useCallback } from 'react'\nimport { keepPreviousData } from '@tanstack/react-query'\nimport { usePayrollsList } from '@gusto/embedded-api/react-query/payrollsList'\nimport { usePayrollsCancelMutation } from '@gusto/embedded-api/react-query/payrollsCancel'\nimport { useWireInRequestsListSuspense } from '@gusto/embedded-api/react-query/wireInRequestsList'\nimport {\n ProcessingStatuses,\n QueryParamPayrollTypes,\n QueryParamSortOrder as SortOrder,\n} from '@gusto/embedded-api/models/operations/getv1companiescompanyidpayrolls'\nimport type { Payroll } from '@gusto/embedded-api/models/components/unprocessedpayroll'\nimport { PayrollHistoryPresentation } from './PayrollHistoryPresentation'\nimport type { BaseComponentInterface } from '@/components/Base/Base'\nimport { BaseComponent, BaseLayout } from '@/components/Base/Base'\nimport { useBase } from '@/components/Base/useBase'\nimport { componentEvents } from '@/shared/constants'\nimport { useComponentDictionary, useI18n } from '@/i18n'\nimport { usePagination } from '@/hooks/usePagination/usePagination'\nimport { useDateRangeFilter } from '@/hooks/useDateRangeFilter/useDateRangeFilter'\n\n/**\n * Props for the {@link PayrollHistory} component.\n *\n * @public\n */\nexport interface PayrollHistoryProps extends BaseComponentInterface<'Payroll.PayrollHistory'> {\n /** Identifier of the company whose processed payrolls should be listed. */\n companyId: string\n}\n\n/**\n * Displays historical payroll records with filtering and management capabilities.\n *\n * @remarks\n * Lists processed regular, off-cycle, and external payrolls for a company and supports filtering by\n * pay period, viewing payroll summaries and receipts, and cancelling processed payrolls when they\n * remain within the cancellation window. Each row shows the pay period, payroll type, pay date,\n * status, and total pay amount.\n *\n * @events\n * | Event | Description | Data |\n * | ----- | ----------- | ---- |\n * | `runPayroll/summary/viewed` | User views a payroll summary | `{ payrollId: string; startDate?: string; endDate?: string }` |\n * | `runPayroll/receipt/viewed` | User views a payroll receipt | `{ payrollId: string; startDate?: string; endDate?: string }` |\n * | `runPayroll/cancelled` | A payroll is cancelled | `{ payrollId: string; result: PayrollsCancelResponse }` |\n *\n * @param props - See {@link PayrollHistoryProps}.\n * @returns The rendered payroll history view.\n * @public\n */\nexport function PayrollHistory(props: PayrollHistoryProps) {\n return (\n <BaseComponent {...props}>\n <Root {...props}>{props.children}</Root>\n </BaseComponent>\n )\n}\n\nconst DEFAULT_LOOKBACK_MONTHS = 6\nconst DEFAULT_LOOKAHEAD_MONTHS = 3\n\nconst getDefaultStartDate = (): Date => {\n const date = new Date()\n date.setMonth(date.getMonth() - DEFAULT_LOOKBACK_MONTHS)\n return date\n}\n\nconst getDefaultEndDate = (): Date => {\n const date = new Date()\n date.setMonth(date.getMonth() + DEFAULT_LOOKAHEAD_MONTHS)\n return date\n}\n\nconst Root = ({\n onEvent,\n companyId,\n dictionary,\n LoaderComponent,\n className,\n}: PayrollHistoryProps) => {\n useComponentDictionary('Payroll.PayrollHistory', dictionary)\n useI18n('Payroll.PayrollHistory')\n\n const [cancelDialogItem, setCancelDialogItem] = useState<Payroll | null>(null)\n const { baseSubmitHandler } = useBase()\n const { currentPage, itemsPerPage, getPaginationProps, resetPage } = usePagination()\n\n const dateRangeFilter = useDateRangeFilter({\n initialStartDate: getDefaultStartDate(),\n initialEndDate: getDefaultEndDate(),\n onFilterChange: useCallback(() => {\n resetPage()\n }, [resetPage]),\n })\n const dateFilterParams = dateRangeFilter.getApiDateParams()\n\n const { data: payrollsData, isFetching } = usePayrollsList(\n {\n companyId,\n processingStatuses: [ProcessingStatuses.Processed],\n payrollTypes: [QueryParamPayrollTypes.Regular, QueryParamPayrollTypes.OffCycle],\n includeOffCycle: true,\n include: ['totals', 'payroll_status_meta'],\n sortOrder: SortOrder.Desc,\n startDate: dateFilterParams.startDate,\n endDate: dateFilterParams.endDate,\n page: currentPage,\n per: itemsPerPage,\n },\n { placeholderData: keepPreviousData, throwOnError: true },\n )\n\n const payrollHistory = payrollsData?.payrollList || []\n\n const { data: wireInRequestsData } = useWireInRequestsListSuspense({\n companyUuid: companyId,\n })\n\n const wireInRequests = wireInRequestsData.wireInRequestList ?? []\n\n const { mutateAsync: cancelPayroll, isPending: isCancelling } = usePayrollsCancelMutation()\n\n const handleViewSummary = (payrollId: string, startDate?: string, endDate?: string) => {\n onEvent(componentEvents.RUN_PAYROLL_SUMMARY_VIEWED, { payrollId, startDate, endDate })\n }\n\n const handleViewReceipt = (payrollId: string, startDate?: string, endDate?: string) => {\n onEvent(componentEvents.RUN_PAYROLL_RECEIPT_VIEWED, { payrollId, startDate, endDate })\n }\n\n const handleCancelPayroll = async (item: Payroll) => {\n const payrollId = item.payrollUuid || item.uuid!\n try {\n await baseSubmitHandler(payrollId, async id => {\n const result = await cancelPayroll({\n request: {\n companyId,\n payrollId: id,\n },\n })\n\n onEvent(componentEvents.RUN_PAYROLL_CANCELLED, { payrollId: id, result })\n })\n } finally {\n setCancelDialogItem(null)\n }\n }\n\n if (!payrollsData) {\n return <BaseLayout isLoading LoaderComponent={LoaderComponent} />\n }\n\n const paginationProps = getPaginationProps(payrollsData.httpMeta.response.headers, isFetching)\n\n return (\n <PayrollHistoryPresentation\n className={className}\n payrollHistory={payrollHistory}\n wireInRequests={wireInRequests}\n pagination={paginationProps}\n onViewSummary={handleViewSummary}\n onViewReceipt={handleViewReceipt}\n onCancelPayroll={handleCancelPayroll}\n cancelDialogItem={cancelDialogItem}\n onCancelDialogOpen={setCancelDialogItem}\n onCancelDialogClose={() => {\n setCancelDialogItem(null)\n }}\n isLoading={isCancelling}\n dateRangeFilter={dateRangeFilter}\n />\n )\n}\n"],"names":["PayrollHistory","props","jsx","BaseComponent","Root","DEFAULT_LOOKBACK_MONTHS","DEFAULT_LOOKAHEAD_MONTHS","getDefaultStartDate","date","getDefaultEndDate","onEvent","companyId","dictionary","LoaderComponent","className","useComponentDictionary","useI18n","cancelDialogItem","setCancelDialogItem","useState","baseSubmitHandler","useBase","currentPage","itemsPerPage","getPaginationProps","resetPage","usePagination","dateRangeFilter","useDateRangeFilter","useCallback","dateFilterParams","payrollsData","isFetching","usePayrollsList","ProcessingStatuses","QueryParamPayrollTypes","SortOrder","keepPreviousData","payrollHistory","wireInRequestsData","useWireInRequestsListSuspense","wireInRequests","cancelPayroll","isCancelling","usePayrollsCancelMutation","handleViewSummary","payrollId","startDate","endDate","componentEvents","handleViewReceipt","handleCancelPayroll","item","id","result","BaseLayout","paginationProps","PayrollHistoryPresentation"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsxs as d, jsx as a } from "react/jsx-runtime";
|
|
2
2
|
import { useTranslation as A } from "react-i18next";
|
|
3
|
-
import { getPayPeriodOrCheckDateLabel as p, getPayrollTypeLabel as w, calculateTotalPayroll as M, getCancelDeadlineValues as
|
|
3
|
+
import { getPayPeriodOrCheckDateLabel as p, getPayrollTypeLabel as w, calculateTotalPayroll as M, getCancelDeadlineValues as T, canCancelPayroll as E } from "../helpers.js";
|
|
4
4
|
import { Flex as c } from "../../Common/Flex/Flex.js";
|
|
5
5
|
import { EmptyData as u } from "../../Common/EmptyData/EmptyData.js";
|
|
6
|
-
import { HamburgerMenu as
|
|
6
|
+
import { HamburgerMenu as H } from "../../Common/HamburgerMenu/HamburgerMenu.js";
|
|
7
7
|
import { DateRangeFilter as j } from "../../Common/DateRangeFilter/DateRangeFilter.js";
|
|
8
8
|
import { useComponentContext as O } from "../../../contexts/ComponentAdapter/useComponentContext.js";
|
|
9
9
|
import { formatNumberAsCurrency as U } from "../../../helpers/formattedStrings.js";
|
|
@@ -59,7 +59,7 @@ const oe = ({
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
];
|
|
62
|
-
return
|
|
62
|
+
return E(t) && n.push({
|
|
63
63
|
label: e("menu.cancelPayroll"),
|
|
64
64
|
icon: /* @__PURE__ */ a(B, { "aria-hidden": !0 }),
|
|
65
65
|
onClick: () => {
|
|
@@ -85,7 +85,7 @@ const oe = ({
|
|
|
85
85
|
cancelLabel: e("dateFilter.cancel"),
|
|
86
86
|
resetLabel: e("dateFilter.reset"),
|
|
87
87
|
selectDatesLabel: e("dateFilter.selectDates"),
|
|
88
|
-
|
|
88
|
+
getTriggerLabel: (t) => e("dateFilter.triggerLabel", { selection: t }),
|
|
89
89
|
maxEndDate: i.getMaxEndDate(),
|
|
90
90
|
minStartDate: i.getMinStartDate()
|
|
91
91
|
}
|
|
@@ -139,7 +139,7 @@ const oe = ({
|
|
|
139
139
|
}
|
|
140
140
|
],
|
|
141
141
|
data: D,
|
|
142
|
-
itemMenu: (t) => /* @__PURE__ */ a(
|
|
142
|
+
itemMenu: (t) => /* @__PURE__ */ a(H, { items: k(t) })
|
|
143
143
|
}
|
|
144
144
|
),
|
|
145
145
|
/* @__PURE__ */ a(
|
|
@@ -159,7 +159,7 @@ const oe = ({
|
|
|
159
159
|
/* @__PURE__ */ a(m, { children: e("cancelDialog.body") }),
|
|
160
160
|
r.payrollDeadline && /* @__PURE__ */ a(m, { children: e(
|
|
161
161
|
"cancelDialog.deadline",
|
|
162
|
-
|
|
162
|
+
T(r, l)
|
|
163
163
|
) })
|
|
164
164
|
] })
|
|
165
165
|
}
|