@gusto/embedded-react-sdk 0.55.8 → 0.56.1

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.
Files changed (211) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/components/Common/UI/Menu/MenuTypes.js.map +1 -1
  3. package/dist/components/Common/UI/MultiSelectComboBox/MultiSelectComboBox.js +43 -42
  4. package/dist/components/Common/UI/MultiSelectComboBox/MultiSelectComboBox.js.map +1 -1
  5. package/dist/components/Company/AssignSignatory/CreateSignatory/useCreateSignatory.js +4 -3
  6. package/dist/components/Company/AssignSignatory/CreateSignatory/useCreateSignatory.js.map +1 -1
  7. package/dist/components/Company/AssignSignatory/InviteSignatory/useInviteSignatory.js +4 -3
  8. package/dist/components/Company/AssignSignatory/InviteSignatory/useInviteSignatory.js.map +1 -1
  9. package/dist/components/Company/AssignSignatory/useAssignSignatory.js +6 -5
  10. package/dist/components/Company/AssignSignatory/useAssignSignatory.js.map +1 -1
  11. package/dist/components/Company/BankAccount/BankAccountForm/context.js +4 -3
  12. package/dist/components/Company/BankAccount/BankAccountForm/context.js.map +1 -1
  13. package/dist/components/Company/DocumentSigner/DocumentList/useDocumentList.js +4 -3
  14. package/dist/components/Company/DocumentSigner/DocumentList/useDocumentList.js.map +1 -1
  15. package/dist/components/Company/FederalTaxes/useFederalTaxes.js +6 -5
  16. package/dist/components/Company/FederalTaxes/useFederalTaxes.js.map +1 -1
  17. package/dist/components/Company/Industry/Context.js +7 -6
  18. package/dist/components/Company/Industry/Context.js.map +1 -1
  19. package/dist/components/Company/Locations/LocationForm/useLocationForm.js +4 -3
  20. package/dist/components/Company/Locations/LocationForm/useLocationForm.js.map +1 -1
  21. package/dist/components/Company/Locations/LocationsList/useLocationsList.js +4 -3
  22. package/dist/components/Company/Locations/LocationsList/useLocationsList.js.map +1 -1
  23. package/dist/components/Company/OnboardingOverview/context.js +4 -3
  24. package/dist/components/Company/OnboardingOverview/context.js.map +1 -1
  25. package/dist/components/Company/StateTaxes/StateTaxesForm/context.js +4 -3
  26. package/dist/components/Company/StateTaxes/StateTaxesForm/context.js.map +1 -1
  27. package/dist/components/Company/StateTaxes/StateTaxesList/context.js +4 -3
  28. package/dist/components/Company/StateTaxes/StateTaxesList/context.js.map +1 -1
  29. package/dist/components/Company/StateTaxes/TaxRateManagement/context.js +4 -3
  30. package/dist/components/Company/StateTaxes/TaxRateManagement/context.js.map +1 -1
  31. package/dist/components/Employee/Documents/onboarding/DocumentSigner/DocumentList/useDocumentList.js +4 -3
  32. package/dist/components/Employee/Documents/onboarding/DocumentSigner/DocumentList/useDocumentList.js.map +1 -1
  33. package/dist/components/Employee/EmployeeList/management/ManagementEmployeeListView.js +70 -69
  34. package/dist/components/Employee/EmployeeList/management/ManagementEmployeeListView.js.map +1 -1
  35. package/dist/components/Employee/EmployeeList/onboarding/EmployeeListView.js +2 -2
  36. package/dist/components/Employee/EmployeeList/onboarding/EmployeeListView.js.map +1 -1
  37. package/dist/components/Employee/EmployeeList/shared/useEmployeeList.js +51 -42
  38. package/dist/components/Employee/EmployeeList/shared/useEmployeeList.js.map +1 -1
  39. package/dist/components/Employee/EmployeeListFlow/employeeListStateMachine.js +29 -26
  40. package/dist/components/Employee/EmployeeListFlow/employeeListStateMachine.js.map +1 -1
  41. package/dist/components/Employee/HomeAddress/management/HomeAddressView.js +2 -2
  42. package/dist/components/Employee/HomeAddress/management/HomeAddressView.js.map +1 -1
  43. package/dist/components/Employee/Terminations/TerminateEmployee/TerminateEmployeePresentation.js +11 -11
  44. package/dist/components/Employee/Terminations/TerminateEmployee/TerminateEmployeePresentation.js.map +1 -1
  45. package/dist/components/Employee/Terminations/TerminationSummary/TerminationSummaryPresentation.js +3 -3
  46. package/dist/components/Employee/Terminations/TerminationSummary/TerminationSummaryPresentation.js.map +1 -1
  47. package/dist/components/Employee/WorkAddress/management/WorkAddressView.js +76 -79
  48. package/dist/components/Employee/WorkAddress/management/WorkAddressView.js.map +1 -1
  49. package/dist/components/InformationRequests/InformationRequestList/InformationRequestList.js +2 -2
  50. package/dist/components/InformationRequests/InformationRequestList/InformationRequestList.js.map +1 -1
  51. package/dist/components/Payroll/ConfirmWireDetails/ConfirmWireDetailsBanner/ConfirmWireDetailsBanner.js +2 -2
  52. package/dist/components/Payroll/ConfirmWireDetails/ConfirmWireDetailsBanner/ConfirmWireDetailsBanner.js.map +1 -1
  53. package/dist/components/Payroll/Dismissal/DismissalPayPeriodSelection/DismissalPayPeriodSelectionPresentation.js +10 -10
  54. package/dist/components/Payroll/Dismissal/DismissalPayPeriodSelection/DismissalPayPeriodSelectionPresentation.js.map +1 -1
  55. package/dist/components/Payroll/GrossUpModal/GrossUpModal.js +49 -45
  56. package/dist/components/Payroll/GrossUpModal/GrossUpModal.js.map +1 -1
  57. package/dist/components/Payroll/OffCycle/OffCycleFlow.js.map +1 -1
  58. package/dist/components/Payroll/OffCycle/OffCycleFlowComponents.js +24 -18
  59. package/dist/components/Payroll/OffCycle/OffCycleFlowComponents.js.map +1 -1
  60. package/dist/components/Payroll/OffCycle/offCycleStateMachine.js +39 -21
  61. package/dist/components/Payroll/OffCycle/offCycleStateMachine.js.map +1 -1
  62. package/dist/components/Payroll/OffCycleCreation/OffCycleCreation.js +98 -88
  63. package/dist/components/Payroll/OffCycleCreation/OffCycleCreation.js.map +1 -1
  64. package/dist/components/Payroll/OffCycleCreation/OffCycleCreationPresentation.js +64 -60
  65. package/dist/components/Payroll/OffCycleCreation/OffCycleCreationPresentation.js.map +1 -1
  66. package/dist/components/Payroll/PayrollBlocker/components/PayrollBlockerAlerts.js +12 -12
  67. package/dist/components/Payroll/PayrollBlocker/components/PayrollBlockerAlerts.js.map +1 -1
  68. package/dist/components/Payroll/PayrollBlocker/components/PayrollBlockerList.js +40 -40
  69. package/dist/components/Payroll/PayrollBlocker/components/PayrollBlockerList.js.map +1 -1
  70. package/dist/components/Payroll/PayrollConfiguration/PayrollConfiguration.js +205 -185
  71. package/dist/components/Payroll/PayrollConfiguration/PayrollConfiguration.js.map +1 -1
  72. package/dist/components/Payroll/PayrollConfiguration/useCalculationPoll.js +48 -34
  73. package/dist/components/Payroll/PayrollConfiguration/useCalculationPoll.js.map +1 -1
  74. package/dist/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.js +13 -16
  75. package/dist/components/Payroll/PayrollEditEmployee/PayrollEditEmployeePresentation.js.map +1 -1
  76. package/dist/components/Payroll/PayrollEditEmployee/TimeOffField.js +0 -1
  77. package/dist/components/Payroll/PayrollEditEmployee/TimeOffField.js.map +1 -1
  78. package/dist/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/payrollEditEmployeeHelpers.js +138 -110
  79. package/dist/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/payrollEditEmployeeHelpers.js.map +1 -1
  80. package/dist/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.js +149 -146
  81. package/dist/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/usePayrollEditEmployeeForm.js.map +1 -1
  82. package/dist/components/Payroll/PayrollExecutionFlow/PayrollExecutionFlow.js.map +1 -1
  83. package/dist/components/Payroll/PayrollExecutionFlow/payrollExecutionMachine.js +4 -0
  84. package/dist/components/Payroll/PayrollExecutionFlow/payrollExecutionMachine.js.map +1 -1
  85. package/dist/components/Payroll/PayrollFlow/PayrollFlow.js.map +1 -1
  86. package/dist/components/Payroll/PayrollFlow/TransitionFlowContextual.js +22 -35
  87. package/dist/components/Payroll/PayrollFlow/TransitionFlowContextual.js.map +1 -1
  88. package/dist/components/Payroll/PayrollOverview/PayrollOverview.js +185 -171
  89. package/dist/components/Payroll/PayrollOverview/PayrollOverview.js.map +1 -1
  90. package/dist/components/Payroll/PayrollOverview/useSubmissionPoll.js +45 -34
  91. package/dist/components/Payroll/PayrollOverview/useSubmissionPoll.js.map +1 -1
  92. package/dist/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.js +44 -44
  93. package/dist/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.js.map +1 -1
  94. package/dist/components/Payroll/PayrollReceipts/PayrollReceiptsPresentation.module.scss.js +14 -14
  95. package/dist/components/Payroll/PrintChecks/PrintChecksFailure/PrintChecksFailure.js +16 -16
  96. package/dist/components/Payroll/PrintChecks/PrintChecksFailure/PrintChecksFailure.js.map +1 -1
  97. package/dist/components/Payroll/PrintChecks/PrintChecksForm/useGenerationPoll.js +52 -37
  98. package/dist/components/Payroll/PrintChecks/PrintChecksForm/useGenerationPoll.js.map +1 -1
  99. package/dist/components/Payroll/Transition/TransitionFlow.js +49 -36
  100. package/dist/components/Payroll/Transition/TransitionFlow.js.map +1 -1
  101. package/dist/components/Payroll/Transition/TransitionFlowComponents.js +24 -47
  102. package/dist/components/Payroll/Transition/TransitionFlowComponents.js.map +1 -1
  103. package/dist/components/Payroll/Transition/transitionStateMachine.js +35 -40
  104. package/dist/components/Payroll/Transition/transitionStateMachine.js.map +1 -1
  105. package/dist/components/Payroll/TransitionPayroll/TransitionPayroll.js +48 -0
  106. package/dist/components/Payroll/TransitionPayroll/TransitionPayroll.js.map +1 -0
  107. package/dist/components/Payroll/TransitionPayroll/TransitionPayrollComponents.js +35 -0
  108. package/dist/components/Payroll/TransitionPayroll/TransitionPayrollComponents.js.map +1 -0
  109. package/dist/components/Payroll/TransitionPayroll/transitionPayrollStateMachine.js +23 -0
  110. package/dist/components/Payroll/TransitionPayroll/transitionPayrollStateMachine.js.map +1 -0
  111. package/dist/components/Payroll/TransitionPayroll/useResolveTransitionPayroll.js +32 -0
  112. package/dist/components/Payroll/TransitionPayroll/useResolveTransitionPayroll.js.map +1 -0
  113. package/dist/components/Payroll/index.js +7 -5
  114. package/dist/components/Payroll/index.js.map +1 -1
  115. package/dist/components/Payroll/usePreparedPayrollData.js +9 -8
  116. package/dist/components/Payroll/usePreparedPayrollData.js.map +1 -1
  117. package/dist/contexts/ApiProvider/ApiProvider.js +29 -28
  118. package/dist/contexts/ApiProvider/ApiProvider.js.map +1 -1
  119. package/dist/contexts/ApiProvider/apiVersionMismatchHook.js +15 -0
  120. package/dist/contexts/ApiProvider/apiVersionMismatchHook.js.map +1 -0
  121. package/dist/contexts/GustoProvider/GustoProviderCustomUIAdapter.js.map +1 -1
  122. package/dist/contexts/ThemeProvider/ThemeProvider.js +32 -26
  123. package/dist/contexts/ThemeProvider/ThemeProvider.js.map +1 -1
  124. package/dist/hooks/usePollingTask/usePollingTask.js +53 -41
  125. package/dist/hooks/usePollingTask/usePollingTask.js.map +1 -1
  126. package/dist/i18n/I18n.js +9 -4
  127. package/dist/i18n/I18n.js.map +1 -1
  128. package/dist/i18n/en/Employee.ManagementEmployeeList.json.js +28 -24
  129. package/dist/i18n/en/Employee.ManagementEmployeeList.json.js.map +1 -1
  130. package/dist/i18n/en/Payroll.GrossUpModal.json.js +12 -10
  131. package/dist/i18n/en/Payroll.GrossUpModal.json.js.map +1 -1
  132. package/dist/i18n/en/Payroll.PayrollBlocker.json.js +10 -8
  133. package/dist/i18n/en/Payroll.PayrollBlocker.json.js.map +1 -1
  134. package/dist/i18n/en/Payroll.PayrollConfiguration.json.js +8 -8
  135. package/dist/i18n/en/Payroll.PayrollOverview.json.js +15 -15
  136. package/dist/i18n/es_US/Company.StateTaxes.json.js +1 -1
  137. package/dist/i18n/es_US/Contractor.ContractorList.json.js +14 -12
  138. package/dist/i18n/es_US/Contractor.ContractorList.json.js.map +1 -1
  139. package/dist/i18n/es_US/Contractor.Management.Compensation.json.js +4 -4
  140. package/dist/i18n/es_US/Contractor.Management.Profile.json.js +4 -4
  141. package/dist/i18n/es_US/Contractor.ManagementContractorList.json.js +40 -38
  142. package/dist/i18n/es_US/Contractor.ManagementContractorList.json.js.map +1 -1
  143. package/dist/i18n/es_US/Contractor.Payments.PaymentsList.json.js +18 -16
  144. package/dist/i18n/es_US/Contractor.Payments.PaymentsList.json.js.map +1 -1
  145. package/dist/i18n/es_US/Contractor.Profile.json.js +5 -5
  146. package/dist/i18n/es_US/Payroll.OffCycleCreation.json.js +11 -9
  147. package/dist/i18n/es_US/Payroll.OffCycleCreation.json.js.map +1 -1
  148. package/dist/i18n/es_US/Payroll.OffCyclePayPeriodDateForm.json.js +2 -2
  149. package/dist/i18n/es_US/Payroll.OffCycleTaxWithholding.json.js +6 -6
  150. package/dist/i18n/es_US/Payroll.PayrollConfiguration.json.js +15 -15
  151. package/dist/i18n/es_US/Payroll.PayrollEditEmployee.json.js +28 -26
  152. package/dist/i18n/es_US/Payroll.PayrollEditEmployee.json.js.map +1 -1
  153. package/dist/i18n/es_US/Payroll.PayrollOverview.json.js +40 -38
  154. package/dist/i18n/es_US/Payroll.PayrollOverview.json.js.map +1 -1
  155. package/dist/i18n/es_US/Payroll.PrintChecksBanner.json.js +14 -0
  156. package/dist/i18n/es_US/Payroll.PrintChecksBanner.json.js.map +1 -0
  157. package/dist/i18n/es_US/Payroll.PrintChecksFailure.json.js +12 -0
  158. package/dist/i18n/es_US/Payroll.PrintChecksFailure.json.js.map +1 -0
  159. package/dist/i18n/es_US/Payroll.PrintChecksForm.json.js +26 -0
  160. package/dist/i18n/es_US/Payroll.PrintChecksForm.json.js.map +1 -0
  161. package/dist/i18n/es_US/Payroll.PrintChecksSummary.json.js +14 -0
  162. package/dist/i18n/es_US/Payroll.PrintChecksSummary.json.js.map +1 -0
  163. package/dist/i18n/es_US/Payroll.UNSTABLE_PayrollEditEmployee.json.js +78 -0
  164. package/dist/i18n/es_US/Payroll.UNSTABLE_PayrollEditEmployee.json.js.map +1 -0
  165. package/dist/i18n/es_US/common.json.js +1 -1
  166. package/dist/package.json.js +1 -1
  167. package/dist/shared/constants.js +21 -20
  168. package/dist/shared/constants.js.map +1 -1
  169. package/dist/src/components/Common/UI/ComboBox/ComboBoxTypes.d.ts +1 -1
  170. package/dist/src/components/Common/UI/DatePicker/DatePickerTypes.d.ts +2 -1
  171. package/dist/src/components/Common/UI/Menu/MenuTypes.d.ts +1 -1
  172. package/dist/src/components/Common/UI/MultiSelectComboBox/MultiSelectComboBox.d.ts +1 -1
  173. package/dist/src/components/Common/UI/MultiSelectComboBox/MultiSelectComboBoxTypes.d.ts +5 -0
  174. package/dist/src/components/Common/UI/Select/SelectTypes.d.ts +2 -1
  175. package/dist/src/components/Employee/EmployeeList/shared/useEmployeeList.d.ts +7 -2
  176. package/dist/src/components/Employee/EmployeeListFlow/employeeListStateMachine.test.d.ts +1 -0
  177. package/dist/src/components/Payroll/OffCycle/OffCycleFlow.d.ts +2 -0
  178. package/dist/src/components/Payroll/OffCycle/OffCycleFlowComponents.d.ts +2 -0
  179. package/dist/src/components/Payroll/OffCycle/offCycleStateMachine.d.ts +1 -0
  180. package/dist/src/components/Payroll/OffCycleCreation/OffCycleCreation.d.ts +1 -0
  181. package/dist/src/components/Payroll/OffCycleCreation/OffCycleCreationPresentation.d.ts +1 -1
  182. package/dist/src/components/Payroll/OffCycleCreation/OffCycleCreationTypes.d.ts +11 -0
  183. package/dist/src/components/Payroll/PayrollConfiguration/PayrollConfiguration.d.ts +1 -1
  184. package/dist/src/components/Payroll/PayrollConfiguration/useCalculationPoll.d.ts +6 -1
  185. package/dist/src/components/Payroll/PayrollEditEmployee/shared/usePayrollEditEmployeeForm/payrollEditEmployeeHelpers.d.ts +18 -0
  186. package/dist/src/components/Payroll/PayrollExecutionFlow/PayrollExecutionFlow.d.ts +1 -1
  187. package/dist/src/components/Payroll/PayrollExecutionFlow/payrollExecutionMachine.d.ts +8 -0
  188. package/dist/src/components/Payroll/PayrollFlow/PayrollFlow.d.ts +1 -1
  189. package/dist/src/components/Payroll/PayrollFlow/TransitionFlowContextual.d.ts +6 -1
  190. package/dist/src/components/Payroll/PayrollOverview/useSubmissionPoll.d.ts +10 -1
  191. package/dist/src/components/Payroll/Transition/TransitionFlow.d.ts +17 -15
  192. package/dist/src/components/Payroll/Transition/TransitionFlowComponents.d.ts +21 -12
  193. package/dist/src/components/Payroll/Transition/transitionStateMachine.d.ts +25 -4
  194. package/dist/src/components/Payroll/TransitionPayroll/TransitionPayroll.d.ts +55 -0
  195. package/dist/src/components/Payroll/TransitionPayroll/TransitionPayrollComponents.d.ts +24 -0
  196. package/dist/src/components/Payroll/TransitionPayroll/TransitionPayrollTypes.d.ts +23 -0
  197. package/dist/src/components/Payroll/TransitionPayroll/index.d.ts +2 -0
  198. package/dist/src/components/Payroll/TransitionPayroll/transitionPayrollStateMachine.d.ts +15 -0
  199. package/dist/src/components/Payroll/TransitionPayroll/useResolveTransitionPayroll.d.ts +28 -0
  200. package/dist/src/components/Payroll/index.d.ts +2 -0
  201. package/dist/src/contexts/ApiProvider/ApiProvider.d.ts +5 -3
  202. package/dist/src/contexts/ApiProvider/apiVersionMismatchHook.d.ts +3 -0
  203. package/dist/src/contexts/ApiProvider/apiVersionMismatchHook.test.d.ts +1 -0
  204. package/dist/src/contexts/GustoProvider/GustoProviderCustomUIAdapter.d.ts +9 -1
  205. package/dist/src/contexts/ThemeProvider/ThemeProvider.d.ts +8 -3
  206. package/dist/src/hooks/usePollingTask/usePollingTask.d.ts +55 -14
  207. package/dist/src/i18n/types.d.ts +20 -0
  208. package/dist/src/shared/constants.d.ts +2 -0
  209. package/dist/style.css +1 -1
  210. package/docs/guides/endpoint-inventory.json +19 -19
  211. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"PayrollConfiguration.js","sources":["../../../../src/components/Payroll/PayrollConfiguration/PayrollConfiguration.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { usePayrollsGetSuspense } from '@gusto/embedded-api/react-query/payrollsGet'\nimport { payrollsCalculate } from '@gusto/embedded-api/funcs/payrollsCalculate'\nimport { useGustoEmbeddedContext } from '@gusto/embedded-api/react-query/_context'\nimport type { GetV1CompaniesCompanyIdPayrollsPayrollIdRequest } from '@gusto/embedded-api/models/operations/getv1companiescompanyidpayrollspayrollid'\nimport type { Employee } from '@gusto/embedded-api/models/components/employee'\nimport { useTranslation } from 'react-i18next'\nimport { usePayrollsUpdateMutation } from '@gusto/embedded-api/react-query/payrollsUpdate'\nimport { usePayrollsCalculateGrossUpMutation } from '@gusto/embedded-api/react-query/payrollsCalculateGrossUp'\nimport type { PayrollEmployeeCompensationsType } from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport type { PayrollUpdateEmployeeCompensations } from '@gusto/embedded-api/models/components/payrollupdate'\nimport { usePayrollsGetBlockersSuspense } from '@gusto/embedded-api/react-query/payrollsGetBlockers'\nimport { payrollSubmitHandler, type ApiPayrollBlocker } from '../PayrollBlocker/payrollHelpers'\nimport { GrossUpModal } from '../GrossUpModal'\nimport { PayrollOverview } from '../PayrollOverview/PayrollOverview'\nimport type { PayrollFlowAlert } from '../PayrollFlow/PayrollFlowComponents'\nimport { PayrollConfigurationPresentation } from './PayrollConfigurationPresentation'\nimport { usePayrollConfigurationData } from './usePayrollConfigurationData'\nimport { getGrossUpTargetCompensationName, isGrossUpEligible } from './grossUpHelpers'\nimport { useCalculationPoll, isCalculatingStatus, type PayrollShow } from './useCalculationPoll'\nimport type { BaseComponentInterface } from '@/components/Base/Base'\nimport { BaseComponent } from '@/components/Base/Base'\nimport { componentEvents, type EventType } from '@/shared/constants'\nimport { useComponentDictionary, useI18n } from '@/i18n'\nimport { useBase } from '@/components/Base'\nimport { useDateFormatter } from '@/hooks/useDateFormatter'\nimport { SDKInternalError } from '@/types/sdkError'\n\n/**\n * Props for {@link PayrollConfiguration}.\n *\n * @public\n */\nexport interface PayrollConfigurationProps extends BaseComponentInterface<'Payroll.PayrollConfiguration'> {\n /** The associated company identifier. */\n companyId: string\n /** The associated payroll identifier. */\n payrollId: string\n /** Optional alert components to render above the configuration content. */\n alerts?: ReactNode\n /** Whether to show the reimbursements column in the compensation table. Defaults to `true`. */\n withReimbursements?: boolean\n}\n\n/**\n * Handles the configuration phase of payroll processing, allowing users to review and modify employee compensation before calculating the payroll.\n *\n * @remarks\n * If the payroll turns out to already be processed (e.g. another actor submitted it while this\n * screen was open), this component emits `runPayroll/alreadyProcessed` and then renders\n * {@link PayrollOverview} in its place — the read-only breakdown with the gated \"Cancel payroll\"\n * action — instead of the configuration table. Events from that delegated view (e.g.\n * `runPayroll/cancelled`) are emitted through this component's own `onEvent`.\n *\n * Emits the following events:\n *\n * @events\n * | Event | Description | Data |\n * | ----- | ----------- | ---- |\n * | `runPayroll/employee/edit` | An employee row is selected for editing | `{ employeeId, firstName, lastName }` |\n * | `runPayroll/employee/skip` | An employee is skipped or unskipped for this payroll | `{ employeeId }` |\n * | `runPayroll/employee/saved` | Employee compensation changes are persisted | `{ payrollPrepared }` |\n * | `runPayroll/calculated` | Payroll calculation completes successfully | `{ payrollId, alert, payPeriod }` |\n * | `runPayroll/alreadyProcessed` | The payroll turns out to already be processed while configuring it | `{ payrollId, alert, payPeriod }` |\n * | `runPayroll/processingFailed` | Payroll calculation fails or times out | — |\n * | `runPayroll/blockers/viewAll` | The \"view all blockers\" affordance is selected | — |\n * | `runPayroll/grossUp/selected` | The set-net-earnings menu item is selected for an employee | `{ employeeUuid }` |\n * | `runPayroll/grossUp/calculated` | A gross-up amount is calculated from a target net pay | `{ grossUp, netPay, employeeUuid }` |\n *\n * @param props - See {@link PayrollConfigurationProps}.\n * @returns The payroll configuration screen.\n * @public\n */\nexport function PayrollConfiguration(props: PayrollConfigurationProps) {\n return (\n <BaseComponent {...props}>\n <Root {...props}>{props.children}</Root>\n </BaseComponent>\n )\n}\n\nconst Root = ({\n onEvent,\n companyId,\n payrollId,\n dictionary,\n alerts,\n withReimbursements = true,\n className,\n}: PayrollConfigurationProps) => {\n useComponentDictionary('Payroll.PayrollConfiguration', dictionary)\n useI18n('Payroll.PayrollConfiguration')\n const { t } = useTranslation('Payroll.PayrollConfiguration')\n const { baseSubmitHandler } = useBase()\n const dateFormatter = useDateFormatter()\n\n const [isCalculatingPayroll, setIsCalculatingPayroll] = useState(false)\n // True once this screen has read a \"calculating\" status for the payroll, whether we started that\n // calc or someone else did. Calling prepare after that would wipe the result, so we use this to\n // keep prepare off.\n const hasSeenCalculatingRef = useRef(false)\n const gustoClient = useGustoEmbeddedContext()\n\n const payrollRequest = useMemo<GetV1CompaniesCompanyIdPayrollsPayrollIdRequest>(\n () => ({\n companyId,\n payrollId,\n include: ['taxes', 'benefits', 'deductions', 'payroll_status_meta'],\n }),\n [companyId, payrollId],\n )\n\n const { data: payrollData, refetch: refetchPayroll } = usePayrollsGetSuspense(payrollRequest)\n\n const excludedEmployeeUuids = useMemo(\n () =>\n payrollData.payrollShow?.employeeCompensations\n ?.filter(comp => comp.excluded)\n .map(comp => comp.employeeUuid!)\n .filter(Boolean) ?? [],\n [payrollData.payrollShow?.employeeCompensations],\n )\n\n // Remember once we've seen it calculating.\n if (isCalculatingStatus(payrollData.payrollShow?.processingRequest)) {\n hasSeenCalculatingRef.current = true\n }\n\n const { data: blockersData } = usePayrollsGetBlockersSuspense({\n companyUuid: companyId,\n })\n\n const payrollBlockerList = blockersData.payrollBlockers ?? []\n\n const blockersFromApi: ApiPayrollBlocker[] = payrollBlockerList.map(blocker => ({\n key: blocker.key,\n message: blocker.message,\n }))\n\n const [payrollBlockers, setPayrollBlockers] = useState(blockersFromApi)\n\n const { start: startCalculationPoll, isPolling } = useCalculationPoll({\n refetch: refetchPayroll,\n onCalculated: (payroll: PayrollShow | undefined) => {\n onEvent(componentEvents.RUN_PAYROLL_CALCULATED, {\n payrollId,\n alert: {\n type: 'success',\n title: t('alerts.progressSaved'),\n alertKey: 'progressSaved',\n },\n payPeriod: payroll?.payPeriod,\n })\n setPayrollBlockers([])\n },\n onProcessingFailed: (payroll: PayrollShow | undefined) => {\n onEvent(componentEvents.RUN_PAYROLL_PROCESSING_FAILED)\n // Let prepare run again on retry — but only when there is no calculation for it to wipe.\n if (payroll?.calculatedAt == null) {\n hasSeenCalculatingRef.current = false\n }\n },\n })\n\n // Show the loading state the whole time we're calculating, so a second tab shows the loader\n // instead of a blank table until it moves to the overview.\n const isCalculatingActive = isCalculatingPayroll || isPolling || hasSeenCalculatingRef.current\n\n const {\n employeeDetails,\n employeeCompensations,\n paySchedule,\n payPeriod,\n payrollCategory,\n pagination,\n isLoading,\n isAlreadyProcessed,\n refetch,\n } = usePayrollConfigurationData({\n companyId,\n payrollId,\n // Don't prepare while calculating, or once we've seen it calculate. If the payroll was already\n // calculated when we opened (e.g. clicking Edit), we do prepare so it can be edited.\n disablePrepare: isPolling || isCalculatingPayroll || hasSeenCalculatingRef.current,\n excludedEmployeeUuids,\n })\n\n const alreadyProcessedAlert: PayrollFlowAlert = useMemo(\n () => ({\n type: 'error',\n title: t('alerts.alreadyProcessed'),\n alertKey: 'alreadyProcessed',\n }),\n [t],\n )\n\n const hasFiredAlreadyProcessedRef = useRef(false)\n\n useEffect(() => {\n if (!isAlreadyProcessed) {\n hasFiredAlreadyProcessedRef.current = false\n return\n }\n if (hasFiredAlreadyProcessedRef.current) return\n hasFiredAlreadyProcessedRef.current = true\n onEvent(componentEvents.RUN_PAYROLL_ALREADY_PROCESSED, {\n payrollId,\n alert: alreadyProcessedAlert,\n payPeriod: payrollData.payrollShow?.payPeriod,\n })\n }, [\n isAlreadyProcessed,\n onEvent,\n payrollId,\n alreadyProcessedAlert,\n payrollData.payrollShow?.payPeriod,\n ])\n\n const { mutateAsync: updatePayroll, isPending: isUpdatingPayroll } = usePayrollsUpdateMutation()\n\n const { mutateAsync: calculateGrossUpMutation } = usePayrollsCalculateGrossUpMutation()\n\n const [grossUpEmployeeUuid, setGrossUpEmployeeUuid] = useState<string | null>(null)\n const [isGrossUpModalOpen, setIsGrossUpModalOpen] = useState(false)\n\n const grossUpEnabled = isGrossUpEligible(payrollCategory)\n const grossUpTargetCompensation = getGrossUpTargetCompensationName(payrollCategory)\n\n const onGrossUpSelect = (employeeUuid: string) => {\n setGrossUpEmployeeUuid(employeeUuid)\n setIsGrossUpModalOpen(true)\n onEvent(componentEvents.RUN_PAYROLL_GROSS_UP_SELECTED, { employeeUuid })\n }\n\n const onCalculateGrossUp = async (netPay: number): Promise<string | null> => {\n if (!grossUpEmployeeUuid) return null\n let grossUp: string | null = null\n\n await baseSubmitHandler(null, async () => {\n const result = await calculateGrossUpMutation({\n request: {\n payrollUuid: payrollId,\n payrollGrossUpRequest: {\n employeeUuid: grossUpEmployeeUuid,\n netPay: netPay.toString(),\n },\n },\n })\n\n grossUp = result.payrollGrossUpResponse?.grossUp ?? null\n\n if (grossUp) {\n onEvent(componentEvents.RUN_PAYROLL_GROSS_UP_CALCULATED, {\n grossUp,\n netPay,\n employeeUuid: grossUpEmployeeUuid,\n })\n }\n })\n\n return grossUp\n }\n\n const onGrossUpApply = async (grossAmount: string) => {\n if (!grossUpEmployeeUuid || !grossUpTargetCompensation) {\n throw new SDKInternalError(\n 'Unable to apply gross-up: missing employee or target compensation.',\n )\n }\n\n const employeeComp = employeeCompensations.find(ec => ec.employeeUuid === grossUpEmployeeUuid)\n if (!employeeComp) {\n throw new SDKInternalError('Unable to apply gross-up: employee compensation not found.')\n }\n\n const existingFixed = employeeComp.fixedCompensations ?? []\n const hasTargetCompensation = existingFixed.some(\n fc => fc.name?.toLowerCase() === grossUpTargetCompensation.toLowerCase(),\n )\n\n const updatedFixedCompensations = existingFixed.map(fc => ({\n name: fc.name,\n jobUuid: fc.jobUuid,\n amount:\n fc.name?.toLowerCase() === grossUpTargetCompensation.toLowerCase() ? grossAmount : '0',\n }))\n\n if (!hasTargetCompensation) {\n const primaryJobUuid =\n employeeComp.hourlyCompensations?.[0]?.jobUuid ?? existingFixed[0]?.jobUuid ?? ''\n updatedFixedCompensations.push({\n name: grossUpTargetCompensation,\n jobUuid: primaryJobUuid,\n amount: grossAmount,\n })\n }\n\n const updatedHourlyCompensations = (employeeComp.hourlyCompensations ?? []).map(hc => ({\n name: hc.name,\n jobUuid: hc.jobUuid,\n hours: '0',\n }))\n\n const updatedPaidTimeOff = (employeeComp.paidTimeOff ?? []).map(pto => ({\n name: pto.name,\n hours: '0',\n }))\n\n const transformedCompensation = transformEmployeeCompensation({\n ...employeeComp,\n fixedCompensations: updatedFixedCompensations,\n hourlyCompensations: updatedHourlyCompensations,\n paidTimeOff: updatedPaidTimeOff,\n })\n\n await baseSubmitHandler({}, async () => {\n const result = await updatePayroll({\n request: {\n companyId,\n payrollId,\n payrollUpdate: {\n employeeCompensations: [{ ...transformedCompensation, excluded: false }],\n },\n },\n })\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_SAVED, {\n payrollPrepared: result.payrollPrepared,\n })\n await refetch()\n })\n\n setGrossUpEmployeeUuid(null)\n setIsGrossUpModalOpen(false)\n }\n\n const handleGrossUpApply = async (grossAmount: string) => {\n try {\n await onGrossUpApply(grossAmount)\n } catch {\n // Modal stays open; error is surfaced by baseSubmitHandler\n }\n }\n\n const onCalculatePayroll = async () => {\n setPayrollBlockers([])\n // Mark it right away so prepare can't run and cancel the calculation we just started.\n hasSeenCalculatingRef.current = true\n\n await baseSubmitHandler({}, async () => {\n const result = await payrollSubmitHandler(async () => {\n setIsCalculatingPayroll(true)\n try {\n const calcResult = await payrollsCalculate(gustoClient, {\n companyId,\n payrollId,\n })\n if (!calcResult.ok) {\n throw calcResult.error\n }\n startCalculationPoll({\n baselineCalculatedAt: payrollData.payrollShow?.calculatedAt?.getTime() ?? null,\n // We just submitted the payroll, so we haven't yet seen it return with the calculating status\n sawCalculatingThisPoll: false,\n })\n } catch (error) {\n // Calculate itself failed before polling ever started (e.g. a 409 conflict), so let\n // prepare run again on retry -- otherwise hasSeenCalculatingRef stays stuck true forever\n // with no RUN_PAYROLL_CALCULATED/RUN_PAYROLL_PROCESSING_FAILED event ever firing.\n hasSeenCalculatingRef.current = false\n throw error\n } finally {\n setIsCalculatingPayroll(false)\n }\n })\n\n if (!result.success && result.blockers.length > 0) {\n setPayrollBlockers(result.blockers)\n }\n })\n }\n\n const onEdit = (employee: Employee) => {\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_EDIT, {\n employeeId: employee.uuid,\n firstName: employee.firstName,\n lastName: employee.lastName,\n })\n }\n\n const transformEmployeeCompensation = (\n compensation: PayrollEmployeeCompensationsType,\n ): PayrollUpdateEmployeeCompensations => {\n const { paymentMethod } = compensation\n return {\n employeeUuid: compensation.employeeUuid,\n version: compensation.version,\n excluded: compensation.excluded,\n fixedCompensations: compensation.fixedCompensations,\n hourlyCompensations: compensation.hourlyCompensations,\n paidTimeOff: compensation.paidTimeOff,\n deductions: compensation.deductions,\n ...(paymentMethod && paymentMethod !== 'Historical' ? { paymentMethod } : {}),\n memo: compensation.memo || undefined,\n }\n }\n\n const onToggleExclude = async (employeeCompensation: PayrollEmployeeCompensationsType) => {\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_SKIP, {\n employeeId: employeeCompensation.employeeUuid,\n })\n await baseSubmitHandler({}, async () => {\n const transformedCompensation = transformEmployeeCompensation(employeeCompensation)\n const result = await updatePayroll({\n request: {\n companyId,\n payrollId,\n payrollUpdate: {\n employeeCompensations: [\n { ...transformedCompensation, excluded: !transformedCompensation.excluded },\n ],\n },\n },\n })\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_SAVED, {\n payrollPrepared: result.payrollPrepared,\n })\n await refetch()\n })\n }\n\n const onViewBlockers = () => {\n onEvent(componentEvents.RUN_PAYROLL_BLOCKERS_VIEW_ALL)\n }\n\n // Pick up a calculation this screen didn't start (another tab, another admin). Starting a poll\n // from rendered data is fine — only the decision to *finish* one must not depend on a render,\n // and that lives in the poll loop.\n useEffect(() => {\n if (isPolling) return\n if (!isCalculatingStatus(payrollData.payrollShow?.processingRequest)) return\n\n startCalculationPoll({\n baselineCalculatedAt: payrollData.payrollShow?.calculatedAt?.getTime() ?? null,\n // We have seen the calculating status, which is why we're starting to poll now until it completes or fails.\n sawCalculatingThisPoll: true,\n })\n }, [\n payrollData.payrollShow?.processingRequest,\n payrollData.payrollShow?.calculatedAt,\n isPolling,\n startCalculationPoll,\n ])\n\n const payrollAlert = (() => {\n const statusMeta = payrollData.payrollShow?.payrollStatusMeta\n\n const isLatePayroll =\n statusMeta?.payrollLate &&\n statusMeta.initialCheckDate &&\n statusMeta.expectedDebitTime &&\n statusMeta.expectedCheckDate\n\n if (isLatePayroll) {\n return {\n label: t('alerts.payrollLate', {\n initialCheckDate: dateFormatter.formatShortWithWeekday(statusMeta.initialCheckDate),\n }),\n content: t('alerts.payrollLateText', {\n ...dateFormatter.formatWithTime(statusMeta.expectedDebitTime),\n newCheckDate: dateFormatter.formatShortWithWeekday(statusMeta.expectedCheckDate),\n }),\n variant: 'warning' as const,\n }\n }\n\n const { payrollShow } = payrollData\n\n if (payrollShow?.checkDate && payrollShow.payrollDeadline) {\n return {\n label: t('alerts.directDepositDeadline', {\n payDate: dateFormatter.formatShortWithWeekday(payrollShow.checkDate),\n ...dateFormatter.formatWithTime(payrollShow.payrollDeadline),\n }),\n content: t('alerts.directDepositDeadlineText'),\n variant: 'info' as const,\n }\n }\n\n return undefined\n })()\n\n if (isAlreadyProcessed) {\n const onAlreadyProcessedOverviewEvent = (type: EventType, data?: unknown) => {\n if (type === componentEvents.RUN_PAYROLL_CANCELLED) {\n // Cancelling un-processes the payroll, making it editable again — re-run prepare so\n // this component drops back into the configuration table for the same payrollId.\n void refetch()\n }\n onEvent(type, data)\n }\n\n return (\n <PayrollOverview\n className={className}\n companyId={companyId}\n payrollId={payrollId}\n onEvent={onAlreadyProcessedOverviewEvent}\n withReimbursements={withReimbursements}\n alerts={[alreadyProcessedAlert]}\n />\n )\n }\n\n return (\n <>\n <PayrollConfigurationPresentation\n className={className}\n onCalculatePayroll={onCalculatePayroll}\n isCalculateDisabled={blockersFromApi.length > 0}\n onEdit={onEdit}\n onToggleExclude={onToggleExclude}\n onViewBlockers={onViewBlockers}\n employeeCompensations={employeeCompensations}\n employeeDetails={employeeDetails}\n payPeriod={payPeriod}\n paySchedule={paySchedule}\n payrollCategory={payrollCategory}\n alerts={alerts}\n payrollAlert={payrollAlert}\n isPending={isCalculatingActive || isLoading || isUpdatingPayroll}\n isCalculating={isCalculatingActive}\n payrollBlockers={payrollBlockers}\n pagination={pagination}\n withReimbursements={withReimbursements}\n grossUpEnabled={grossUpEnabled}\n onGrossUpSelect={onGrossUpSelect}\n />\n {grossUpEnabled && (\n <GrossUpModal\n isOpen={isGrossUpModalOpen}\n onCalculateGrossUp={onCalculateGrossUp}\n onApply={handleGrossUpApply}\n onCancel={() => {\n setIsGrossUpModalOpen(false)\n }}\n />\n )}\n </>\n )\n}\n"],"names":["PayrollConfiguration","props","jsx","BaseComponent","Root","onEvent","companyId","payrollId","dictionary","alerts","withReimbursements","className","useComponentDictionary","useI18n","t","useTranslation","baseSubmitHandler","useBase","dateFormatter","useDateFormatter","isCalculatingPayroll","setIsCalculatingPayroll","useState","hasSeenCalculatingRef","useRef","gustoClient","useGustoEmbeddedContext","payrollRequest","useMemo","payrollData","refetchPayroll","usePayrollsGetSuspense","excludedEmployeeUuids","comp","isCalculatingStatus","blockersData","usePayrollsGetBlockersSuspense","blockersFromApi","blocker","payrollBlockers","setPayrollBlockers","startCalculationPoll","isPolling","useCalculationPoll","payroll","componentEvents","isCalculatingActive","employeeDetails","employeeCompensations","paySchedule","payPeriod","payrollCategory","pagination","isLoading","isAlreadyProcessed","refetch","usePayrollConfigurationData","alreadyProcessedAlert","hasFiredAlreadyProcessedRef","useEffect","updatePayroll","isUpdatingPayroll","usePayrollsUpdateMutation","calculateGrossUpMutation","usePayrollsCalculateGrossUpMutation","grossUpEmployeeUuid","setGrossUpEmployeeUuid","isGrossUpModalOpen","setIsGrossUpModalOpen","grossUpEnabled","isGrossUpEligible","grossUpTargetCompensation","getGrossUpTargetCompensationName","onGrossUpSelect","employeeUuid","onCalculateGrossUp","netPay","grossUp","onGrossUpApply","grossAmount","SDKInternalError","employeeComp","ec","existingFixed","hasTargetCompensation","fc","updatedFixedCompensations","primaryJobUuid","updatedHourlyCompensations","hc","updatedPaidTimeOff","pto","transformedCompensation","transformEmployeeCompensation","result","handleGrossUpApply","onCalculatePayroll","payrollSubmitHandler","calcResult","payrollsCalculate","error","onEdit","employee","compensation","paymentMethod","onToggleExclude","employeeCompensation","onViewBlockers","payrollAlert","statusMeta","payrollShow","PayrollOverview","type","data","jsxs","Fragment","PayrollConfigurationPresentation","GrossUpModal"],"mappings":"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"}
1
+ {"version":3,"file":"PayrollConfiguration.js","sources":["../../../../src/components/Payroll/PayrollConfiguration/PayrollConfiguration.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { usePayrollsGetSuspense } from '@gusto/embedded-api/react-query/payrollsGet'\nimport { payrollsCalculate } from '@gusto/embedded-api/funcs/payrollsCalculate'\nimport { useGustoEmbeddedContext } from '@gusto/embedded-api/react-query/_context'\nimport type { GetV1CompaniesCompanyIdPayrollsPayrollIdRequest } from '@gusto/embedded-api/models/operations/getv1companiescompanyidpayrollspayrollid'\nimport type { Employee } from '@gusto/embedded-api/models/components/employee'\nimport { useTranslation } from 'react-i18next'\nimport { usePayrollsUpdateMutation } from '@gusto/embedded-api/react-query/payrollsUpdate'\nimport { usePayrollsCalculateGrossUpMutation } from '@gusto/embedded-api/react-query/payrollsCalculateGrossUp'\nimport type { PayrollEmployeeCompensationsType } from '@gusto/embedded-api/models/components/payrollemployeecompensationstype'\nimport type { PayrollUpdateEmployeeCompensations } from '@gusto/embedded-api/models/components/payrollupdate'\nimport { usePayrollsGetBlockersSuspense } from '@gusto/embedded-api/react-query/payrollsGetBlockers'\nimport { payrollSubmitHandler, type ApiPayrollBlocker } from '../PayrollBlocker/payrollHelpers'\nimport { GrossUpModal } from '../GrossUpModal'\nimport { PayrollOverview } from '../PayrollOverview/PayrollOverview'\nimport type { PayrollFlowAlert } from '../PayrollFlow/PayrollFlowComponents'\nimport { PayrollConfigurationPresentation } from './PayrollConfigurationPresentation'\nimport { usePayrollConfigurationData } from './usePayrollConfigurationData'\nimport { getGrossUpTargetCompensationName, isGrossUpEligible } from './grossUpHelpers'\nimport { useCalculationPoll, isCalculatingStatus, type PayrollShow } from './useCalculationPoll'\nimport type { BaseComponentInterface } from '@/components/Base/Base'\nimport { BaseComponent } from '@/components/Base/Base'\nimport { componentEvents, type EventType } from '@/shared/constants'\nimport { useComponentDictionary, useI18n } from '@/i18n'\nimport { useBase } from '@/components/Base'\nimport { useDateFormatter } from '@/hooks/useDateFormatter'\nimport { SDKInternalError } from '@/types/sdkError'\n\n/**\n * Props for {@link PayrollConfiguration}.\n *\n * @public\n */\nexport interface PayrollConfigurationProps extends BaseComponentInterface<'Payroll.PayrollConfiguration'> {\n /** The associated company identifier. */\n companyId: string\n /** The associated payroll identifier. */\n payrollId: string\n /** Optional alert components to render above the configuration content. */\n alerts?: ReactNode\n /** Whether to show the reimbursements column in the compensation table. Defaults to `true`. */\n withReimbursements?: boolean\n}\n\n/**\n * Handles the configuration phase of payroll processing, allowing users to review and modify employee compensation before calculating the payroll.\n *\n * @remarks\n * If the payroll turns out to already be processed (e.g. another actor submitted it while this\n * screen was open), this component emits `runPayroll/alreadyProcessed` and then renders\n * {@link PayrollOverview} in its place — the read-only breakdown with the gated \"Cancel payroll\"\n * action — instead of the configuration table. Events from that delegated view (e.g.\n * `runPayroll/cancelled`) are emitted through this component's own `onEvent`.\n *\n * Emits the following events:\n *\n * @events\n * | Event | Description | Data |\n * | ----- | ----------- | ---- |\n * | `runPayroll/employee/edit` | An employee row is selected for editing | `{ payrollId, employeeId, firstName, lastName }` |\n * | `runPayroll/employee/skip` | An employee is skipped or unskipped for this payroll | `{ employeeId }` |\n * | `runPayroll/employee/saved` | Employee compensation changes are persisted | `{ payrollPrepared }` |\n * | `runPayroll/calculated` | Payroll calculation completes successfully | `{ payrollId, alert, payPeriod }` |\n * | `runPayroll/alreadyProcessed` | The payroll turns out to already be processed while configuring it | `{ payrollId, alert, payPeriod }` |\n * | `runPayroll/processingFailed` | Payroll calculation fails or times out | — |\n * | `runPayroll/blockers/viewAll` | The \"view all blockers\" affordance is selected | — |\n * | `runPayroll/grossUp/selected` | The set-net-earnings menu item is selected for an employee | `{ employeeUuid }` |\n * | `runPayroll/grossUp/calculated` | A gross-up amount is calculated from a target net pay | `{ grossUp, netPay, employeeUuid }` |\n *\n * @param props - See {@link PayrollConfigurationProps}.\n * @returns The payroll configuration screen.\n * @public\n */\nexport function PayrollConfiguration(props: PayrollConfigurationProps) {\n return (\n <BaseComponent {...props}>\n <Root {...props}>{props.children}</Root>\n </BaseComponent>\n )\n}\n\nconst Root = ({\n onEvent,\n companyId,\n payrollId,\n dictionary,\n alerts,\n withReimbursements = true,\n className,\n}: PayrollConfigurationProps) => {\n useComponentDictionary('Payroll.PayrollConfiguration', dictionary)\n useI18n('Payroll.PayrollConfiguration')\n const { t } = useTranslation('Payroll.PayrollConfiguration')\n const { baseSubmitHandler, setError } = useBase()\n const dateFormatter = useDateFormatter()\n\n const [isCalculatingPayroll, setIsCalculatingPayroll] = useState(false)\n // True once this screen has read a \"calculating\" status for the payroll, whether we started that\n // calc or someone else did. Calling prepare after that would wipe the result, so we use this to\n // keep prepare off.\n const hasSeenCalculatingRef = useRef(false)\n // Set when a poll ends in a non-retryable read error without confirming a calculated/failed\n // outcome. Guards the auto-pickup effect below from re-arming a poll against the same stale\n // \"Calculating\" read over and over -- it only clears once the status genuinely leaves Calculating.\n const hasTerminalPollErrorRef = useRef(false)\n const gustoClient = useGustoEmbeddedContext()\n\n const payrollRequest = useMemo<GetV1CompaniesCompanyIdPayrollsPayrollIdRequest>(\n () => ({\n companyId,\n payrollId,\n include: ['taxes', 'benefits', 'deductions', 'payroll_status_meta'],\n }),\n [companyId, payrollId],\n )\n\n const { data: payrollData, refetch: refetchPayroll } = usePayrollsGetSuspense(payrollRequest)\n\n const excludedEmployeeUuids = useMemo(\n () =>\n payrollData.payrollShow?.employeeCompensations\n ?.filter(comp => comp.excluded)\n .map(comp => comp.employeeUuid!)\n .filter(Boolean) ?? [],\n [payrollData.payrollShow?.employeeCompensations],\n )\n\n // Remember once we've seen it calculating.\n if (isCalculatingStatus(payrollData.payrollShow?.processingRequest)) {\n hasSeenCalculatingRef.current = true\n }\n\n const { data: blockersData } = usePayrollsGetBlockersSuspense({\n companyUuid: companyId,\n })\n\n const payrollBlockerList = blockersData.payrollBlockers ?? []\n\n const blockersFromApi: ApiPayrollBlocker[] = payrollBlockerList.map(blocker => ({\n key: blocker.key,\n message: blocker.message,\n }))\n\n const [payrollBlockers, setPayrollBlockers] = useState(blockersFromApi)\n // Drives the loader gate below. Deliberately separate from `error` -- `baseSubmitHandler`\n // clears `error` at the start of *any* submit (e.g. skipping an employee, applying a gross-up),\n // which would otherwise reopen this gate and get the loader stuck on with no poll running to\n // ever clear it (SDK-1276). Only the same sites that used to own the old boolean flag touch it.\n const [hasProcessingFailedAlert, setHasProcessingFailedAlert] = useState(false)\n\n const emitProcessingFailed = () => {\n onEvent(componentEvents.RUN_PAYROLL_PROCESSING_FAILED)\n setHasProcessingFailedAlert(true)\n setError({\n category: 'internal_error',\n message: `${t('alerts.processingFailed.label')}. ${t('alerts.processingFailed.message')}`,\n fieldErrors: [],\n })\n }\n\n const onProcessingFailed = (payroll: PayrollShow | undefined) => {\n emitProcessingFailed()\n // Let prepare run again on retry — but only when there is no calculation for it to wipe.\n if (payroll?.calculatedAt == null) {\n hasSeenCalculatingRef.current = false\n }\n }\n\n const { start: startCalculationPoll, isPolling } = useCalculationPoll({\n refetch: refetchPayroll,\n onCalculated: (payroll: PayrollShow | undefined) => {\n onEvent(componentEvents.RUN_PAYROLL_CALCULATED, {\n payrollId,\n alert: {\n type: 'success',\n title: t('alerts.progressSaved'),\n alertKey: 'progressSaved',\n },\n payPeriod: payroll?.payPeriod,\n })\n setPayrollBlockers([])\n },\n onProcessingFailed,\n // Unlike a real processing failure, we never confirmed whether the calculation actually\n // succeeded server-side, so this must not reset hasSeenCalculatingRef — doing so would\n // re-arm prepare and risk wiping a calculation that may have genuinely completed.\n onError: () => {\n hasTerminalPollErrorRef.current = true\n emitProcessingFailed()\n },\n })\n\n // Show the loading state the whole time we're calculating, so a second tab shows the loader\n // instead of a blank table until it moves to the overview. Once the failed/error alert is\n // showing, the poll has already reached a terminal state, so the loading UI must clear even\n // though hasSeenCalculatingRef stays true (it still guards prepare separately, below).\n const isCalculatingActive =\n !hasProcessingFailedAlert &&\n (isCalculatingPayroll || isPolling || hasSeenCalculatingRef.current)\n\n const {\n employeeDetails,\n employeeCompensations,\n paySchedule,\n payPeriod,\n payrollCategory,\n pagination,\n isLoading,\n isAlreadyProcessed,\n refetch,\n } = usePayrollConfigurationData({\n companyId,\n payrollId,\n // Don't prepare while calculating, or once we've seen it calculate. If the payroll was already\n // calculated when we opened (e.g. clicking Edit), we do prepare so it can be edited.\n disablePrepare: isPolling || isCalculatingPayroll || hasSeenCalculatingRef.current,\n excludedEmployeeUuids,\n })\n\n const alreadyProcessedAlert: PayrollFlowAlert = useMemo(\n () => ({\n type: 'error',\n title: t('alerts.alreadyProcessed'),\n alertKey: 'alreadyProcessed',\n }),\n [t],\n )\n\n const hasFiredAlreadyProcessedRef = useRef(false)\n\n useEffect(() => {\n if (!isAlreadyProcessed) {\n hasFiredAlreadyProcessedRef.current = false\n return\n }\n if (hasFiredAlreadyProcessedRef.current) return\n hasFiredAlreadyProcessedRef.current = true\n onEvent(componentEvents.RUN_PAYROLL_ALREADY_PROCESSED, {\n payrollId,\n alert: alreadyProcessedAlert,\n payPeriod: payrollData.payrollShow?.payPeriod,\n })\n }, [\n isAlreadyProcessed,\n onEvent,\n payrollId,\n alreadyProcessedAlert,\n payrollData.payrollShow?.payPeriod,\n ])\n\n const { mutateAsync: updatePayroll, isPending: isUpdatingPayroll } = usePayrollsUpdateMutation()\n\n const { mutateAsync: calculateGrossUpMutation } = usePayrollsCalculateGrossUpMutation()\n\n const [grossUpEmployeeUuid, setGrossUpEmployeeUuid] = useState<string | null>(null)\n const [isGrossUpModalOpen, setIsGrossUpModalOpen] = useState(false)\n\n const grossUpEnabled = isGrossUpEligible(payrollCategory)\n const grossUpTargetCompensation = getGrossUpTargetCompensationName(payrollCategory)\n\n const onGrossUpSelect = (employeeUuid: string) => {\n setGrossUpEmployeeUuid(employeeUuid)\n setIsGrossUpModalOpen(true)\n onEvent(componentEvents.RUN_PAYROLL_GROSS_UP_SELECTED, { employeeUuid })\n }\n\n const onCalculateGrossUp = async (netPay: number): Promise<string | null> => {\n if (!grossUpEmployeeUuid) return null\n let grossUp: string | null = null\n\n await baseSubmitHandler(null, async () => {\n const result = await calculateGrossUpMutation({\n request: {\n payrollUuid: payrollId,\n payrollGrossUpRequest: {\n employeeUuid: grossUpEmployeeUuid,\n netPay: netPay.toString(),\n },\n },\n })\n\n grossUp = result.payrollGrossUpResponse?.grossUp ?? null\n\n if (grossUp) {\n onEvent(componentEvents.RUN_PAYROLL_GROSS_UP_CALCULATED, {\n grossUp,\n netPay,\n employeeUuid: grossUpEmployeeUuid,\n })\n }\n })\n\n return grossUp\n }\n\n const onGrossUpApply = async (grossAmount: string) => {\n if (!grossUpEmployeeUuid || !grossUpTargetCompensation) {\n throw new SDKInternalError(\n 'Unable to apply gross-up: missing employee or target compensation.',\n )\n }\n\n const employeeComp = employeeCompensations.find(ec => ec.employeeUuid === grossUpEmployeeUuid)\n if (!employeeComp) {\n throw new SDKInternalError('Unable to apply gross-up: employee compensation not found.')\n }\n\n const existingFixed = employeeComp.fixedCompensations ?? []\n const hasTargetCompensation = existingFixed.some(\n fc => fc.name?.toLowerCase() === grossUpTargetCompensation.toLowerCase(),\n )\n\n const updatedFixedCompensations = existingFixed.map(fc => ({\n name: fc.name,\n jobUuid: fc.jobUuid,\n amount:\n fc.name?.toLowerCase() === grossUpTargetCompensation.toLowerCase() ? grossAmount : '0',\n }))\n\n if (!hasTargetCompensation) {\n const primaryJobUuid =\n employeeComp.hourlyCompensations?.[0]?.jobUuid ?? existingFixed[0]?.jobUuid ?? ''\n updatedFixedCompensations.push({\n name: grossUpTargetCompensation,\n jobUuid: primaryJobUuid,\n amount: grossAmount,\n })\n }\n\n const updatedHourlyCompensations = (employeeComp.hourlyCompensations ?? []).map(hc => ({\n name: hc.name,\n jobUuid: hc.jobUuid,\n hours: '0',\n }))\n\n const updatedPaidTimeOff = (employeeComp.paidTimeOff ?? []).map(pto => ({\n name: pto.name,\n hours: '0',\n }))\n\n const transformedCompensation = transformEmployeeCompensation({\n ...employeeComp,\n fixedCompensations: updatedFixedCompensations,\n hourlyCompensations: updatedHourlyCompensations,\n paidTimeOff: updatedPaidTimeOff,\n })\n\n await baseSubmitHandler({}, async () => {\n const result = await updatePayroll({\n request: {\n companyId,\n payrollId,\n payrollUpdate: {\n employeeCompensations: [{ ...transformedCompensation, excluded: false }],\n },\n },\n })\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_SAVED, {\n payrollPrepared: result.payrollPrepared,\n })\n await refetch()\n })\n\n setGrossUpEmployeeUuid(null)\n setIsGrossUpModalOpen(false)\n }\n\n const handleGrossUpApply = async (grossAmount: string) => {\n try {\n await onGrossUpApply(grossAmount)\n } catch {\n // Modal stays open; error is surfaced by baseSubmitHandler\n }\n }\n\n const onCalculatePayroll = async () => {\n setPayrollBlockers([])\n setHasProcessingFailedAlert(false)\n setError(null)\n // Mark it right away so prepare can't run and cancel the calculation we just started.\n hasSeenCalculatingRef.current = true\n\n await baseSubmitHandler({}, async () => {\n const result = await payrollSubmitHandler(async () => {\n setIsCalculatingPayroll(true)\n try {\n const calcResult = await payrollsCalculate(gustoClient, {\n companyId,\n payrollId,\n })\n if (!calcResult.ok) {\n throw calcResult.error\n }\n startCalculationPoll({\n baselineCalculatedAt: payrollData.payrollShow?.calculatedAt?.getTime() ?? null,\n // We just submitted the payroll, so we haven't yet seen it return with the calculating status\n sawCalculatingThisPoll: false,\n })\n } catch (error) {\n // Calculate itself failed before polling ever started (e.g. a 409 conflict), so let\n // prepare run again on retry -- otherwise hasSeenCalculatingRef stays stuck true forever\n // with no RUN_PAYROLL_CALCULATED/RUN_PAYROLL_PROCESSING_FAILED event ever firing.\n hasSeenCalculatingRef.current = false\n throw error\n } finally {\n setIsCalculatingPayroll(false)\n }\n })\n\n if (!result.success && result.blockers.length > 0) {\n setPayrollBlockers(result.blockers)\n }\n })\n }\n\n const onEdit = (employee: Employee) => {\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_EDIT, {\n payrollId,\n employeeId: employee.uuid,\n firstName: employee.firstName,\n lastName: employee.lastName,\n })\n }\n\n const transformEmployeeCompensation = (\n compensation: PayrollEmployeeCompensationsType,\n ): PayrollUpdateEmployeeCompensations => {\n const { paymentMethod } = compensation\n return {\n employeeUuid: compensation.employeeUuid,\n version: compensation.version,\n excluded: compensation.excluded,\n fixedCompensations: compensation.fixedCompensations,\n hourlyCompensations: compensation.hourlyCompensations,\n paidTimeOff: compensation.paidTimeOff,\n deductions: compensation.deductions,\n ...(paymentMethod && paymentMethod !== 'Historical' ? { paymentMethod } : {}),\n memo: compensation.memo || undefined,\n }\n }\n\n const onToggleExclude = async (employeeCompensation: PayrollEmployeeCompensationsType) => {\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_SKIP, {\n employeeId: employeeCompensation.employeeUuid,\n })\n await baseSubmitHandler({}, async () => {\n const transformedCompensation = transformEmployeeCompensation(employeeCompensation)\n const result = await updatePayroll({\n request: {\n companyId,\n payrollId,\n payrollUpdate: {\n employeeCompensations: [\n { ...transformedCompensation, excluded: !transformedCompensation.excluded },\n ],\n },\n },\n })\n onEvent(componentEvents.RUN_PAYROLL_EMPLOYEE_SAVED, {\n payrollPrepared: result.payrollPrepared,\n })\n await refetch()\n })\n }\n\n const onViewBlockers = () => {\n onEvent(componentEvents.RUN_PAYROLL_BLOCKERS_VIEW_ALL)\n }\n\n // Pick up a calculation this screen didn't start (another tab, another admin). Starting a poll\n // from rendered data is fine — only the decision to *finish* one must not depend on a render,\n // and that lives in the poll loop.\n useEffect(() => {\n if (isPolling) return\n if (!isCalculatingStatus(payrollData.payrollShow?.processingRequest)) {\n // The status only leaves Calculating on a genuinely fresh read, so this is where a prior\n // terminal failure stops blocking future pickups.\n hasTerminalPollErrorRef.current = false\n return\n }\n // A read error we already reported for this same stale \"Calculating\" snapshot -- retrying it\n // immediately would just spin (fail, isPolling flips false, this effect fires again, repeat)\n // instead of waiting for a genuinely new read.\n if (hasTerminalPollErrorRef.current) return\n\n // A fresh calculating status means a real calculation is in flight again -- even right after\n // this screen's own deadline reported one as failed -- so any stale failure alert must not\n // linger over it and block the loading UI.\n setHasProcessingFailedAlert(false)\n setError(null)\n startCalculationPoll({\n baselineCalculatedAt: payrollData.payrollShow?.calculatedAt?.getTime() ?? null,\n // We have seen the calculating status, which is why we're starting to poll now until it completes or fails.\n sawCalculatingThisPoll: true,\n })\n }, [\n payrollData.payrollShow?.processingRequest,\n payrollData.payrollShow?.calculatedAt,\n isPolling,\n startCalculationPoll,\n setError,\n ])\n\n const payrollAlert = (() => {\n const statusMeta = payrollData.payrollShow?.payrollStatusMeta\n\n const isLatePayroll =\n statusMeta?.payrollLate &&\n statusMeta.initialCheckDate &&\n statusMeta.expectedDebitTime &&\n statusMeta.expectedCheckDate\n\n if (isLatePayroll) {\n return {\n label: t('alerts.payrollLate', {\n initialCheckDate: dateFormatter.formatShortWithWeekday(statusMeta.initialCheckDate),\n }),\n content: t('alerts.payrollLateText', {\n ...dateFormatter.formatWithTime(statusMeta.expectedDebitTime),\n newCheckDate: dateFormatter.formatShortWithWeekday(statusMeta.expectedCheckDate),\n }),\n variant: 'warning' as const,\n }\n }\n\n const { payrollShow } = payrollData\n\n if (payrollShow?.checkDate && payrollShow.payrollDeadline) {\n return {\n label: t('alerts.directDepositDeadline', {\n payDate: dateFormatter.formatShortWithWeekday(payrollShow.checkDate),\n ...dateFormatter.formatWithTime(payrollShow.payrollDeadline),\n }),\n content: t('alerts.directDepositDeadlineText'),\n variant: 'info' as const,\n }\n }\n\n return undefined\n })()\n\n if (isAlreadyProcessed) {\n const onAlreadyProcessedOverviewEvent = (type: EventType, data?: unknown) => {\n if (type === componentEvents.RUN_PAYROLL_CANCELLED) {\n // Cancelling un-processes the payroll, making it editable again — re-run prepare so\n // this component drops back into the configuration table for the same payrollId.\n void refetch()\n }\n onEvent(type, data)\n }\n\n return (\n <PayrollOverview\n className={className}\n companyId={companyId}\n payrollId={payrollId}\n onEvent={onAlreadyProcessedOverviewEvent}\n withReimbursements={withReimbursements}\n alerts={[alreadyProcessedAlert]}\n />\n )\n }\n\n return (\n <>\n <PayrollConfigurationPresentation\n className={className}\n onCalculatePayroll={onCalculatePayroll}\n isCalculateDisabled={blockersFromApi.length > 0}\n onEdit={onEdit}\n onToggleExclude={onToggleExclude}\n onViewBlockers={onViewBlockers}\n employeeCompensations={employeeCompensations}\n employeeDetails={employeeDetails}\n payPeriod={payPeriod}\n paySchedule={paySchedule}\n payrollCategory={payrollCategory}\n alerts={alerts}\n payrollAlert={payrollAlert}\n isPending={isCalculatingActive || isLoading || isUpdatingPayroll}\n isCalculating={isCalculatingActive}\n payrollBlockers={payrollBlockers}\n pagination={pagination}\n withReimbursements={withReimbursements}\n grossUpEnabled={grossUpEnabled}\n onGrossUpSelect={onGrossUpSelect}\n />\n {grossUpEnabled && (\n <GrossUpModal\n isOpen={isGrossUpModalOpen}\n onCalculateGrossUp={onCalculateGrossUp}\n onApply={handleGrossUpApply}\n onCancel={() => {\n setIsGrossUpModalOpen(false)\n }}\n />\n )}\n </>\n )\n}\n"],"names":["PayrollConfiguration","props","jsx","BaseComponent","Root","onEvent","companyId","payrollId","dictionary","alerts","withReimbursements","className","useComponentDictionary","useI18n","t","useTranslation","baseSubmitHandler","setError","useBase","dateFormatter","useDateFormatter","isCalculatingPayroll","setIsCalculatingPayroll","useState","hasSeenCalculatingRef","useRef","hasTerminalPollErrorRef","gustoClient","useGustoEmbeddedContext","payrollRequest","useMemo","payrollData","refetchPayroll","usePayrollsGetSuspense","excludedEmployeeUuids","comp","isCalculatingStatus","blockersData","usePayrollsGetBlockersSuspense","blockersFromApi","blocker","payrollBlockers","setPayrollBlockers","hasProcessingFailedAlert","setHasProcessingFailedAlert","emitProcessingFailed","componentEvents","onProcessingFailed","payroll","startCalculationPoll","isPolling","useCalculationPoll","isCalculatingActive","employeeDetails","employeeCompensations","paySchedule","payPeriod","payrollCategory","pagination","isLoading","isAlreadyProcessed","refetch","usePayrollConfigurationData","alreadyProcessedAlert","hasFiredAlreadyProcessedRef","useEffect","updatePayroll","isUpdatingPayroll","usePayrollsUpdateMutation","calculateGrossUpMutation","usePayrollsCalculateGrossUpMutation","grossUpEmployeeUuid","setGrossUpEmployeeUuid","isGrossUpModalOpen","setIsGrossUpModalOpen","grossUpEnabled","isGrossUpEligible","grossUpTargetCompensation","getGrossUpTargetCompensationName","onGrossUpSelect","employeeUuid","onCalculateGrossUp","netPay","grossUp","onGrossUpApply","grossAmount","SDKInternalError","employeeComp","ec","existingFixed","hasTargetCompensation","fc","updatedFixedCompensations","primaryJobUuid","updatedHourlyCompensations","hc","updatedPaidTimeOff","pto","transformedCompensation","transformEmployeeCompensation","result","handleGrossUpApply","onCalculatePayroll","payrollSubmitHandler","calcResult","payrollsCalculate","error","onEdit","employee","compensation","paymentMethod","onToggleExclude","employeeCompensation","onViewBlockers","payrollAlert","statusMeta","payrollShow","PayrollOverview","type","data","jsxs","Fragment","PayrollConfigurationPresentation","GrossUpModal"],"mappings":"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"}
@@ -1,22 +1,33 @@
1
- import { useRef as p, useCallback as y } from "react";
2
- import { PayrollProcessingRequestStatus as o } from "@gusto/embedded-api/models/components/payrollprocessingrequest";
3
- import { usePollingTask as g } from "../../../hooks/usePollingTask/usePollingTask.js";
4
- const C = (a) => a?.status === o.Calculating, c = (a, l) => l != null && (a?.status === o.CalculateSuccess || a == null), h = (a, l) => {
5
- const e = a.payrollShow;
6
- if (C(e?.processingRequest))
7
- return l && (l.sawCalculatingThisPoll = !0), { done: !1 };
8
- if (e?.processingRequest?.status === o.ProcessingFailed)
9
- return { done: !0, value: { type: "failed", payroll: e } };
10
- const s = e?.calculatedAt;
11
- return (l?.sawCalculatingThisPoll === !0 || s?.getTime() !== l?.baselineCalculatedAt) && c(e?.processingRequest, s) ? { done: !0, value: { type: "calculated", payroll: e } } : { done: !1 };
1
+ import { useRef as C, useCallback as P } from "react";
2
+ import { PayrollProcessingRequestStatus as n } from "@gusto/embedded-api/models/components/payrollprocessingrequest";
3
+ import { usePollingTask as m, isNonRetryablePollError as h } from "../../../hooks/usePollingTask/usePollingTask.js";
4
+ import { useObservability as w } from "../../../contexts/ObservabilityProvider/useObservability.js";
5
+ import { normalizeToSDKError as v } from "../../../types/sdkError.js";
6
+ const E = "Payroll.PayrollConfiguration", R = (l) => l?.status === n.Calculating, c = (l, a) => a != null && (l?.status === n.CalculateSuccess || l == null), f = (l) => {
7
+ const a = l?.payrollShow;
8
+ return c(a?.processingRequest, a?.calculatedAt) ? { type: "calculated", payroll: a } : { type: "failed", payroll: a };
9
+ }, b = (l, a) => {
10
+ if (!l.success) {
11
+ if (!h(l.error)) return { status: "polling" };
12
+ const s = f(l.lastData);
13
+ return s.type === "calculated" ? { status: "done", value: s } : { status: "error", error: l.error };
14
+ }
15
+ const e = l.data.payrollShow;
16
+ if (R(e?.processingRequest))
17
+ return a && (a.sawCalculatingThisPoll = !0), { status: "polling" };
18
+ if (e?.processingRequest?.status === n.ProcessingFailed)
19
+ return { status: "done", value: { type: "failed", payroll: e } };
20
+ const r = e?.calculatedAt;
21
+ return (a?.sawCalculatingThisPoll === !0 || r?.getTime() !== a?.baselineCalculatedAt) && c(e?.processingRequest, r) ? { status: "done", value: { type: "calculated", payroll: e } } : { status: "polling" };
12
22
  };
13
- function S({
14
- refetch: a,
15
- onCalculated: l,
16
- onProcessingFailed: e
23
+ function q({
24
+ refetch: l,
25
+ onCalculated: a,
26
+ onProcessingFailed: e,
27
+ onError: r
17
28
  }) {
18
- const s = p(null), r = async () => {
19
- const t = await a();
29
+ const o = C(null), { observability: s } = w(), p = async () => {
30
+ const t = await l();
20
31
  if (t.status !== "success") throw t.error ?? new Error("Payroll refetch failed");
21
32
  return t.data;
22
33
  }, i = (t) => {
@@ -24,29 +35,32 @@ function S({
24
35
  e(t.payroll);
25
36
  return;
26
37
  }
27
- l(t.payroll);
28
- }, f = (t) => {
29
- const n = t?.payrollShow;
30
- if (c(n?.processingRequest, n?.calculatedAt)) {
31
- l(n);
32
- return;
33
- }
34
- e(n);
35
- }, { start: u, isPolling: d } = g({
36
- fetch: r,
37
- evaluate: (t) => h(t, s.current),
38
+ a(t.payroll);
39
+ }, d = (t) => {
40
+ i(f(t));
41
+ }, { start: u, isPolling: y } = m({
42
+ fetch: p,
43
+ evaluate: (t) => b(t, o.current),
38
44
  onDone: i,
39
- onDeadline: f
45
+ onError: (t) => {
46
+ const g = v(t);
47
+ s?.onError?.({
48
+ ...g,
49
+ timestamp: Date.now(),
50
+ componentName: E
51
+ }), r();
52
+ },
53
+ onDeadline: d
40
54
  });
41
- return { start: y(
55
+ return { start: P(
42
56
  (t) => {
43
- s.current = t, u();
57
+ o.current = t, u();
44
58
  },
45
59
  [u]
46
- ), isPolling: d };
60
+ ), isPolling: y };
47
61
  }
48
62
  export {
49
- C as isCalculatingStatus,
50
- S as useCalculationPoll
63
+ R as isCalculatingStatus,
64
+ q as useCalculationPoll
51
65
  };
52
66
  //# sourceMappingURL=useCalculationPoll.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCalculationPoll.js","sources":["../../../../src/components/Payroll/PayrollConfiguration/useCalculationPoll.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\nimport type {\n PayrollsGetQueryData,\n PayrollsGetQueryError,\n} from '@gusto/embedded-api/react-query/payrollsGet'\nimport type { QueryObserverResult } from '@tanstack/react-query'\nimport type { PayrollProcessingRequest } from '@gusto/embedded-api/models/components/payrollprocessingrequest'\nimport { PayrollProcessingRequestStatus } from '@gusto/embedded-api/models/components/payrollprocessingrequest'\nimport { usePollingTask, type PollTickResult } from '@/hooks/usePollingTask/usePollingTask'\n\n/** @internal */\nexport type PayrollShow = NonNullable<PayrollsGetQueryData['payrollShow']>\n\ntype CalculationOutcome =\n | { type: 'calculated'; payroll: PayrollShow | undefined }\n | { type: 'failed'; payroll: PayrollShow | undefined }\n\n/**\n * Per-run state for the calculation poll. Written when a run starts and read only from inside\n * the poll loop — never during render, which is what made the previous `previousCalculatedAtRef`\n * completion gate depend on a render arriving.\n */\ninterface CalculationPollRun {\n /**\n * Fast calculations may transition directly to `CalculateSuccess` between ticks, without ever\n * seeing the `Calculating` status.\n * If we know the previous `calculatedAt` timestamp and it changes, we know our polling can resolve.\n */\n baselineCalculatedAt: number | null\n /**\n * The API contract guarantees no relationship between `processingRequest.status` and `calculatedAt` —\n * a deduped/coalesced calculate can legitimately return `CalculateSuccess` with the exact same\n * `calculatedAt` as the baseline captured when this run started.\n * If we have seen `Calculating` status during this run, and it changes to `CalculateSuccess`,\n * we know our polling can resolve even if the timestamp hasn't changed.\n */\n sawCalculatingThisPoll: boolean\n}\n\n/** @internal */\nexport const isCalculatingStatus = (processingRequest?: PayrollProcessingRequest | null) =>\n processingRequest?.status === PayrollProcessingRequestStatus.Calculating\n\nconst isCalculatedStatus = (\n processingRequest?: PayrollProcessingRequest | null,\n calculatedAt?: Date | null,\n) =>\n calculatedAt != null &&\n (processingRequest?.status === PayrollProcessingRequestStatus.CalculateSuccess ||\n processingRequest == null)\n\nconst evaluateCalculationOutcome = (\n data: PayrollsGetQueryData,\n run: CalculationPollRun | null,\n): PollTickResult<CalculationOutcome> => {\n const payroll = data.payrollShow\n\n if (isCalculatingStatus(payroll?.processingRequest)) {\n if (run) run.sawCalculatingThisPoll = true\n return { done: false }\n }\n\n if (payroll?.processingRequest?.status === PayrollProcessingRequestStatus.ProcessingFailed) {\n return { done: true, value: { type: 'failed', payroll } }\n }\n\n const calculatedAt = payroll?.calculatedAt\n const isNewCalculation =\n run?.sawCalculatingThisPoll === true || calculatedAt?.getTime() !== run?.baselineCalculatedAt\n\n if (isNewCalculation && isCalculatedStatus(payroll?.processingRequest, calculatedAt)) {\n return { done: true, value: { type: 'calculated', payroll } }\n }\n\n return { done: false }\n}\n\n/** @internal */\nexport interface UseCalculationPollOptions {\n /**\n * The render-driving payroll query's own `refetch`, reused so the poll's reads land on the\n * same query the component observes rather than racing a second, independently-built one.\n */\n refetch: () => Promise<QueryObserverResult<PayrollsGetQueryData, PayrollsGetQueryError>>\n onCalculated: (payroll: PayrollShow | undefined) => void\n onProcessingFailed: (payroll: PayrollShow | undefined) => void\n}\n\n/** @internal */\nexport interface CalculationPoll {\n start: (props: CalculationPollRun) => void\n isPolling: boolean\n}\n\n/**\n * Polls a payroll until its calculation reaches a terminal state, via {@link usePollingTask}.\n *\n * @internal\n */\nexport function useCalculationPoll({\n refetch,\n onCalculated,\n onProcessingFailed,\n}: UseCalculationPollOptions): CalculationPoll {\n const pollRunRef = useRef<CalculationPollRun | null>(null)\n\n const fetchPayroll = async (): Promise<PayrollsGetQueryData> => {\n const result = await refetch()\n if (result.status !== 'success') throw result.error ?? new Error('Payroll refetch failed')\n return result.data\n }\n\n const handleDone = (outcome: CalculationOutcome) => {\n if (outcome.type === 'failed') {\n onProcessingFailed(outcome.payroll)\n return\n }\n onCalculated(outcome.payroll)\n }\n\n // The server is the source of truth. A calculation that succeeded while we were waiting must\n // never be reported as a failure — that reported false failures for payrolls that had\n // calculated fine, and re-armed the prepare that would then wipe the result (SDK-1291).\n // Advancing on a stale success is the safer of the two wrong answers: the next screen re-reads\n // the payroll, whereas a false failure destroys real data.\n const handleDeadline = (lastData: PayrollsGetQueryData | null) => {\n const payroll = lastData?.payrollShow\n if (isCalculatedStatus(payroll?.processingRequest, payroll?.calculatedAt)) {\n onCalculated(payroll)\n return\n }\n onProcessingFailed(payroll)\n }\n\n const { start: startPoll, isPolling } = usePollingTask<PayrollsGetQueryData, CalculationOutcome>({\n fetch: fetchPayroll,\n evaluate: data => evaluateCalculationOutcome(data, pollRunRef.current),\n onDone: handleDone,\n onDeadline: handleDeadline,\n })\n\n const start = useCallback(\n (run: CalculationPollRun) => {\n pollRunRef.current = run\n startPoll()\n },\n [startPoll],\n )\n\n return { start, isPolling }\n}\n"],"names":["isCalculatingStatus","processingRequest","PayrollProcessingRequestStatus","isCalculatedStatus","calculatedAt","evaluateCalculationOutcome","data","run","payroll","useCalculationPoll","refetch","onCalculated","onProcessingFailed","pollRunRef","useRef","fetchPayroll","result","handleDone","outcome","handleDeadline","lastData","startPoll","isPolling","usePollingTask","useCallback"],"mappings":";;;AAwCO,MAAMA,IAAsB,CAACC,MAClCA,GAAmB,WAAWC,EAA+B,aAEzDC,IAAqB,CACzBF,GACAG,MAEAA,KAAgB,SACfH,GAAmB,WAAWC,EAA+B,oBAC5DD,KAAqB,OAEnBI,IAA6B,CACjCC,GACAC,MACuC;AACvC,QAAMC,IAAUF,EAAK;AAErB,MAAIN,EAAoBQ,GAAS,iBAAiB;AAChD,WAAID,QAAS,yBAAyB,KAC/B,EAAE,MAAM,GAAA;AAGjB,MAAIC,GAAS,mBAAmB,WAAWN,EAA+B;AACxE,WAAO,EAAE,MAAM,IAAM,OAAO,EAAE,MAAM,UAAU,SAAAM,IAAQ;AAGxD,QAAMJ,IAAeI,GAAS;AAI9B,UAFED,GAAK,2BAA2B,MAAQH,GAAc,QAAA,MAAcG,GAAK,yBAEnDJ,EAAmBK,GAAS,mBAAmBJ,CAAY,IAC1E,EAAE,MAAM,IAAM,OAAO,EAAE,MAAM,cAAc,SAAAI,IAAQ,IAGrD,EAAE,MAAM,GAAA;AACjB;AAwBO,SAASC,EAAmB;AAAA,EACjC,SAAAC;AAAA,EACA,cAAAC;AAAA,EACA,oBAAAC;AACF,GAA+C;AAC7C,QAAMC,IAAaC,EAAkC,IAAI,GAEnDC,IAAe,YAA2C;AAC9D,UAAMC,IAAS,MAAMN,EAAA;AACrB,QAAIM,EAAO,WAAW,UAAW,OAAMA,EAAO,SAAS,IAAI,MAAM,wBAAwB;AACzF,WAAOA,EAAO;AAAA,EAChB,GAEMC,IAAa,CAACC,MAAgC;AAClD,QAAIA,EAAQ,SAAS,UAAU;AAC7B,MAAAN,EAAmBM,EAAQ,OAAO;AAClC;AAAA,IACF;AACA,IAAAP,EAAaO,EAAQ,OAAO;AAAA,EAC9B,GAOMC,IAAiB,CAACC,MAA0C;AAChE,UAAMZ,IAAUY,GAAU;AAC1B,QAAIjB,EAAmBK,GAAS,mBAAmBA,GAAS,YAAY,GAAG;AACzE,MAAAG,EAAaH,CAAO;AACpB;AAAA,IACF;AACA,IAAAI,EAAmBJ,CAAO;AAAA,EAC5B,GAEM,EAAE,OAAOa,GAAW,WAAAC,EAAA,IAAcC,EAAyD;AAAA,IAC/F,OAAOR;AAAA,IACP,UAAU,CAAAT,MAAQD,EAA2BC,GAAMO,EAAW,OAAO;AAAA,IACrE,QAAQI;AAAA,IACR,YAAYE;AAAA,EAAA,CACb;AAUD,SAAO,EAAE,OARKK;AAAA,IACZ,CAACjB,MAA4B;AAC3B,MAAAM,EAAW,UAAUN,GACrBc,EAAA;AAAA,IACF;AAAA,IACA,CAACA,CAAS;AAAA,EAAA,GAGI,WAAAC,EAAA;AAClB;"}
1
+ {"version":3,"file":"useCalculationPoll.js","sources":["../../../../src/components/Payroll/PayrollConfiguration/useCalculationPoll.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\nimport type {\n PayrollsGetQueryData,\n PayrollsGetQueryError,\n} from '@gusto/embedded-api/react-query/payrollsGet'\nimport type { QueryObserverResult } from '@tanstack/react-query'\nimport type { PayrollProcessingRequest } from '@gusto/embedded-api/models/components/payrollprocessingrequest'\nimport { PayrollProcessingRequestStatus } from '@gusto/embedded-api/models/components/payrollprocessingrequest'\nimport {\n usePollingTask,\n isNonRetryablePollError,\n type PollReadOutcome,\n type PollTickResult,\n} from '@/hooks/usePollingTask/usePollingTask'\nimport { useObservability } from '@/contexts/ObservabilityProvider/useObservability'\nimport { normalizeToSDKError } from '@/types/sdkError'\n\nconst COMPONENT_NAME = 'Payroll.PayrollConfiguration'\n\n/** @internal */\nexport type PayrollShow = NonNullable<PayrollsGetQueryData['payrollShow']>\n\ntype CalculationOutcome =\n | { type: 'calculated'; payroll: PayrollShow | undefined }\n | { type: 'failed'; payroll: PayrollShow | undefined }\n\n/**\n * Per-run state for the calculation poll. Written when a run starts and read only from inside\n * the poll loop — never during render, which is what made the previous `previousCalculatedAtRef`\n * completion gate depend on a render arriving.\n */\ninterface CalculationPollRun {\n /**\n * Fast calculations may transition directly to `CalculateSuccess` between ticks, without ever\n * seeing the `Calculating` status.\n * If we know the previous `calculatedAt` timestamp and it changes, we know our polling can resolve.\n */\n baselineCalculatedAt: number | null\n /**\n * The API contract guarantees no relationship between `processingRequest.status` and `calculatedAt` —\n * a deduped/coalesced calculate can legitimately return `CalculateSuccess` with the exact same\n * `calculatedAt` as the baseline captured when this run started.\n * If we have seen `Calculating` status during this run, and it changes to `CalculateSuccess`,\n * we know our polling can resolve even if the timestamp hasn't changed.\n */\n sawCalculatingThisPoll: boolean\n}\n\n/** @internal */\nexport const isCalculatingStatus = (processingRequest?: PayrollProcessingRequest | null) =>\n processingRequest?.status === PayrollProcessingRequestStatus.Calculating\n\nconst isCalculatedStatus = (\n processingRequest?: PayrollProcessingRequest | null,\n calculatedAt?: Date | null,\n) =>\n calculatedAt != null &&\n (processingRequest?.status === PayrollProcessingRequestStatus.CalculateSuccess ||\n processingRequest == null)\n\n// A calculation that succeeded must never be reported as a failure just because we stopped\n// reading it (deadline, or a non-retryable error) — a false failure re-arms prepare, which would\n// then wipe the result. Advancing on a stale success is the safer of the two wrong answers: the\n// next screen re-reads the payroll, whereas a false failure destroys real data.\nconst verifiedCalculationOutcome = (lastData: PayrollsGetQueryData | null): CalculationOutcome => {\n const payroll = lastData?.payrollShow\n if (isCalculatedStatus(payroll?.processingRequest, payroll?.calculatedAt)) {\n return { type: 'calculated', payroll }\n }\n return { type: 'failed', payroll }\n}\n\nconst evaluateCalculationOutcome = (\n outcome: PollReadOutcome<PayrollsGetQueryData>,\n run: CalculationPollRun | null,\n): PollTickResult<CalculationOutcome> => {\n if (!outcome.success) {\n if (!isNonRetryablePollError(outcome.error)) return { status: 'polling' }\n // Rescue a success the freshness check above missed (e.g. a same-tick calculatedAt match\n // with baseline); never rescue a failure this way -- an unconfirmed read must stay 'error',\n // not 'done', so it doesn't reset hasSeenCalculatingRef.\n const verified = verifiedCalculationOutcome(outcome.lastData)\n if (verified.type === 'calculated') return { status: 'done', value: verified }\n return { status: 'error', error: outcome.error }\n }\n\n const payroll = outcome.data.payrollShow\n\n if (isCalculatingStatus(payroll?.processingRequest)) {\n if (run) run.sawCalculatingThisPoll = true\n return { status: 'polling' }\n }\n\n if (payroll?.processingRequest?.status === PayrollProcessingRequestStatus.ProcessingFailed) {\n return { status: 'done', value: { type: 'failed', payroll } }\n }\n\n const calculatedAt = payroll?.calculatedAt\n const isNewCalculation =\n run?.sawCalculatingThisPoll === true || calculatedAt?.getTime() !== run?.baselineCalculatedAt\n\n if (isNewCalculation && isCalculatedStatus(payroll?.processingRequest, calculatedAt)) {\n return { status: 'done', value: { type: 'calculated', payroll } }\n }\n\n return { status: 'polling' }\n}\n\n/** @internal */\nexport interface UseCalculationPollOptions {\n /**\n * The render-driving payroll query's own `refetch`, reused so the poll's reads land on the\n * same query the component observes rather than racing a second, independently-built one.\n */\n refetch: () => Promise<QueryObserverResult<PayrollsGetQueryData, PayrollsGetQueryError>>\n onCalculated: (payroll: PayrollShow | undefined) => void\n onProcessingFailed: (payroll: PayrollShow | undefined) => void\n /**\n * Called when the poll gives up on a non-retryable read error, without ever confirming a\n * calculated/failed outcome. The raw error is reported to observability by this hook already.\n */\n onError: () => void\n}\n\n/** @internal */\nexport interface CalculationPoll {\n start: (props: CalculationPollRun) => void\n isPolling: boolean\n}\n\n/**\n * Polls a payroll until its calculation reaches a terminal state, via {@link usePollingTask}.\n *\n * @internal\n */\nexport function useCalculationPoll({\n refetch,\n onCalculated,\n onProcessingFailed,\n onError,\n}: UseCalculationPollOptions): CalculationPoll {\n const pollRunRef = useRef<CalculationPollRun | null>(null)\n const { observability } = useObservability()\n\n const fetchPayroll = async (): Promise<PayrollsGetQueryData> => {\n const result = await refetch()\n if (result.status !== 'success') throw result.error ?? new Error('Payroll refetch failed')\n return result.data\n }\n\n const handleDone = (outcome: CalculationOutcome) => {\n if (outcome.type === 'failed') {\n onProcessingFailed(outcome.payroll)\n return\n }\n onCalculated(outcome.payroll)\n }\n\n const handleDeadline = (lastData: PayrollsGetQueryData | null) => {\n handleDone(verifiedCalculationOutcome(lastData))\n }\n\n const { start: startPoll, isPolling } = usePollingTask<PayrollsGetQueryData, CalculationOutcome>({\n fetch: fetchPayroll,\n evaluate: outcome => evaluateCalculationOutcome(outcome, pollRunRef.current),\n onDone: handleDone,\n onError: error => {\n const sdkError = normalizeToSDKError(error)\n observability?.onError?.({\n ...sdkError,\n timestamp: Date.now(),\n componentName: COMPONENT_NAME,\n })\n onError()\n },\n onDeadline: handleDeadline,\n })\n\n const start = useCallback(\n (run: CalculationPollRun) => {\n pollRunRef.current = run\n startPoll()\n },\n [startPoll],\n )\n\n return { start, isPolling }\n}\n"],"names":["COMPONENT_NAME","isCalculatingStatus","processingRequest","PayrollProcessingRequestStatus","isCalculatedStatus","calculatedAt","verifiedCalculationOutcome","lastData","payroll","evaluateCalculationOutcome","outcome","run","isNonRetryablePollError","verified","useCalculationPoll","refetch","onCalculated","onProcessingFailed","onError","pollRunRef","useRef","observability","useObservability","fetchPayroll","result","handleDone","handleDeadline","startPoll","isPolling","usePollingTask","error","sdkError","normalizeToSDKError","useCallback"],"mappings":";;;;;AAiBA,MAAMA,IAAiB,gCAgCVC,IAAsB,CAACC,MAClCA,GAAmB,WAAWC,EAA+B,aAEzDC,IAAqB,CACzBF,GACAG,MAEAA,KAAgB,SACfH,GAAmB,WAAWC,EAA+B,oBAC5DD,KAAqB,OAMnBI,IAA6B,CAACC,MAA8D;AAChG,QAAMC,IAAUD,GAAU;AAC1B,SAAIH,EAAmBI,GAAS,mBAAmBA,GAAS,YAAY,IAC/D,EAAE,MAAM,cAAc,SAAAA,EAAA,IAExB,EAAE,MAAM,UAAU,SAAAA,EAAA;AAC3B,GAEMC,IAA6B,CACjCC,GACAC,MACuC;AACvC,MAAI,CAACD,EAAQ,SAAS;AACpB,QAAI,CAACE,EAAwBF,EAAQ,KAAK,EAAG,QAAO,EAAE,QAAQ,UAAA;AAI9D,UAAMG,IAAWP,EAA2BI,EAAQ,QAAQ;AAC5D,WAAIG,EAAS,SAAS,eAAqB,EAAE,QAAQ,QAAQ,OAAOA,EAAA,IAC7D,EAAE,QAAQ,SAAS,OAAOH,EAAQ,MAAA;AAAA,EAC3C;AAEA,QAAMF,IAAUE,EAAQ,KAAK;AAE7B,MAAIT,EAAoBO,GAAS,iBAAiB;AAChD,WAAIG,QAAS,yBAAyB,KAC/B,EAAE,QAAQ,UAAA;AAGnB,MAAIH,GAAS,mBAAmB,WAAWL,EAA+B;AACxE,WAAO,EAAE,QAAQ,QAAQ,OAAO,EAAE,MAAM,UAAU,SAAAK,IAAQ;AAG5D,QAAMH,IAAeG,GAAS;AAI9B,UAFEG,GAAK,2BAA2B,MAAQN,GAAc,QAAA,MAAcM,GAAK,yBAEnDP,EAAmBI,GAAS,mBAAmBH,CAAY,IAC1E,EAAE,QAAQ,QAAQ,OAAO,EAAE,MAAM,cAAc,SAAAG,IAAQ,IAGzD,EAAE,QAAQ,UAAA;AACnB;AA6BO,SAASM,EAAmB;AAAA,EACjC,SAAAC;AAAA,EACA,cAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,SAAAC;AACF,GAA+C;AAC7C,QAAMC,IAAaC,EAAkC,IAAI,GACnD,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GAEpBC,IAAe,YAA2C;AAC9D,UAAMC,IAAS,MAAMT,EAAA;AACrB,QAAIS,EAAO,WAAW,UAAW,OAAMA,EAAO,SAAS,IAAI,MAAM,wBAAwB;AACzF,WAAOA,EAAO;AAAA,EAChB,GAEMC,IAAa,CAACf,MAAgC;AAClD,QAAIA,EAAQ,SAAS,UAAU;AAC7B,MAAAO,EAAmBP,EAAQ,OAAO;AAClC;AAAA,IACF;AACA,IAAAM,EAAaN,EAAQ,OAAO;AAAA,EAC9B,GAEMgB,IAAiB,CAACnB,MAA0C;AAChE,IAAAkB,EAAWnB,EAA2BC,CAAQ,CAAC;AAAA,EACjD,GAEM,EAAE,OAAOoB,GAAW,WAAAC,EAAA,IAAcC,EAAyD;AAAA,IAC/F,OAAON;AAAA,IACP,UAAU,CAAAb,MAAWD,EAA2BC,GAASS,EAAW,OAAO;AAAA,IAC3E,QAAQM;AAAA,IACR,SAAS,CAAAK,MAAS;AAChB,YAAMC,IAAWC,EAAoBF,CAAK;AAC1C,MAAAT,GAAe,UAAU;AAAA,QACvB,GAAGU;AAAA,QACH,WAAW,KAAK,IAAA;AAAA,QAChB,eAAe/B;AAAA,MAAA,CAChB,GACDkB,EAAA;AAAA,IACF;AAAA,IACA,YAAYQ;AAAA,EAAA,CACb;AAUD,SAAO,EAAE,OARKO;AAAA,IACZ,CAACtB,MAA4B;AAC3B,MAAAQ,EAAW,UAAUR,GACrBgB,EAAA;AAAA,IACF;AAAA,IACA,CAACA,CAAS;AAAA,EAAA,GAGI,WAAAC,EAAA;AAClB;"}
@@ -17,8 +17,8 @@ import { Form as Le } from "../../Common/Form/Form.js";
17
17
  import { formatNumberAsCurrency as ie, firstLastName as ke } from "../../../helpers/formattedStrings.js";
18
18
  import { getAdditionalEarningsCompensations as Ue, calculateGrossPay as re } from "../helpers.js";
19
19
  import { PayrollCategory as F, isOffCyclePayroll as me } from "../payrollTypes.js";
20
- import { COMPENSATION_NAME_REIMBURSEMENT as S, HOURS_COMPENSATION_NAMES as se, EXCLUDED_ADDITIONAL_EARNINGS as je, COMPENSATION_NAME_DOUBLE_OVERTIME as Ge, COMPENSATION_NAME_OVERTIME as He, COMPENSATION_NAME_REGULAR_HOURS as we, COMPENSATION_NAME_CASH_TIPS as $e, COMPENSATION_NAME_COMMISSION as Ve, COMPENSATION_NAME_CORRECTION_PAYMENT as Be, COMPENSATION_NAME_PAYCHECK_TIPS as qe, COMPENSATION_NAME_BONUS as ze } from "../../../shared/constants.js";
21
- import We from "../../../hooks/useContainerBreakpoints/useContainerBreakpoints.js";
20
+ import { COMPENSATION_NAME_REIMBURSEMENT as S, HOURS_COMPENSATION_NAMES as se, EXCLUDED_ADDITIONAL_EARNINGS as je, COMPENSATION_NAME_DOUBLE_OVERTIME as Ge, COMPENSATION_NAME_OVERTIME as He, COMPENSATION_NAME_REGULAR_HOURS as we, COMPENSATION_NAME_CASH_TIPS as $e, COMPENSATION_NAME_COMMISSION as Ve, COMPENSATION_NAME_CORRECTION_PAYMENT as Be, COMPENSATION_NAME_PAYCHECK_TIPS as ze, COMPENSATION_NAME_BONUS as We } from "../../../shared/constants.js";
21
+ import qe from "../../../hooks/useContainerBreakpoints/useContainerBreakpoints.js";
22
22
  import oe from "../../../assets/icons/plus-circle.svg.js";
23
23
  import Ye from "../../../assets/icons/trashcan.svg.js";
24
24
  import { TextInputField as I } from "../../Common/Fields/TextInputField/TextInputField.js";
@@ -114,7 +114,7 @@ const Ze = s.object({
114
114
  _e("Payroll.PayrollEditEmployee");
115
115
  const b = p.jobs?.find((e) => e.primary), ue = o?.hourlyCompensations?.some(
116
116
  (e) => e.jobUuid === b?.uuid
117
- ), v = b && ue ? [b] : [], B = Oe(null), g = We({
117
+ ), v = b && ue ? [b] : [], B = Oe(null), g = qe({
118
118
  ref: B
119
119
  }).includes("small");
120
120
  o?.hourlyCompensations?.forEach((e) => {
@@ -135,7 +135,7 @@ const Ze = s.object({
135
135
  (e) => e.name?.toLowerCase() === S.toLowerCase()
136
136
  ),
137
137
  [o?.fixedCompensations]
138
- ), q = O && !_ && !!b?.uuid, z = (e, i) => o?.hourlyCompensations?.find(
138
+ ), z = O && !_ && !!b?.uuid, W = (e, i) => o?.hourlyCompensations?.find(
139
139
  (d) => d.jobUuid === e && d.name?.toLowerCase() === i.toLowerCase()
140
140
  ), ce = (e) => {
141
141
  switch (e) {
@@ -148,11 +148,11 @@ const Ze = s.object({
148
148
  default:
149
149
  return e;
150
150
  }
151
- }, W = (e) => {
151
+ }, q = (e) => {
152
152
  switch (e) {
153
- case ze:
153
+ case We:
154
154
  return n("fixedCompensationNames.bonus");
155
- case qe:
155
+ case ze:
156
156
  return n("fixedCompensationNames.paycheckTips");
157
157
  case Be:
158
158
  return n("fixedCompensationNames.correctionPayment");
@@ -173,7 +173,7 @@ const Ze = s.object({
173
173
  const e = {};
174
174
  return v.forEach((i) => {
175
175
  se.forEach((d) => {
176
- const R = z(i.uuid, d);
176
+ const R = W(i.uuid, d);
177
177
  R && (e[i.uuid] || (e[i.uuid] = {}), e[i.uuid][R.name] = R.hours ? parseFloat(R.hours).toString() : "");
178
178
  });
179
179
  }), e;
@@ -194,7 +194,7 @@ const Ze = s.object({
194
194
  const e = {};
195
195
  return j.forEach((i) => {
196
196
  e[i.name] = i.amount ?? "";
197
- }), q && (e[S] = de?.amount ?? "0.00"), e;
197
+ }), z && (e[S] = de?.amount ?? "0.00"), e;
198
198
  })(),
199
199
  reimbursements: le.map((e) => ({
200
200
  uuid: e.uuid ?? null,
@@ -384,7 +384,7 @@ const Ze = s.object({
384
384
  v.map((e) => /* @__PURE__ */ a(P, { flexDirection: "column", gap: 8, children: [
385
385
  v.length > 1 && /* @__PURE__ */ t(f, { as: "h4", children: e.title }),
386
386
  /* @__PURE__ */ t(x, { gridTemplateColumns: { base: "1fr", small: [320, 320] }, gap: 20, children: se.map((i) => {
387
- const d = z(
387
+ const d = W(
388
388
  e.uuid,
389
389
  i
390
390
  );
@@ -395,7 +395,6 @@ const Ze = s.object({
395
395
  type: "number",
396
396
  min: 0,
397
397
  adornmentEnd: n("hoursUnit"),
398
- isRequired: !0,
399
398
  label: ce(i),
400
399
  name: `hourlyCompensations.${e.uuid}.${d.name}`
401
400
  },
@@ -442,8 +441,7 @@ const Ze = s.object({
442
441
  type: "number",
443
442
  min: 0,
444
443
  adornmentStart: "$",
445
- isRequired: !0,
446
- label: W(e.name),
444
+ label: q(e.name),
447
445
  name: `fixedCompensations.${e.name}`,
448
446
  errorMessage: n("validations.negativeAmount")
449
447
  },
@@ -452,7 +450,7 @@ const Ze = s.object({
452
450
  }
453
451
  )
454
452
  ] }),
455
- q && /* @__PURE__ */ a("div", { className: c.fieldGroup, children: [
453
+ z && /* @__PURE__ */ a("div", { className: c.fieldGroup, children: [
456
454
  /* @__PURE__ */ t(f, { as: "h3", styledAs: "h4", children: n("reimbursementTitle") }),
457
455
  /* @__PURE__ */ t(x, { gridTemplateColumns: { base: "1fr", small: [320, 320] }, gap: 20, children: /* @__PURE__ */ t(
458
456
  I,
@@ -460,8 +458,7 @@ const Ze = s.object({
460
458
  type: "number",
461
459
  min: 0,
462
460
  adornmentStart: "$",
463
- isRequired: !0,
464
- label: W(S),
461
+ label: q(S),
465
462
  name: `fixedCompensations.${S}`,
466
463
  errorMessage: n("validations.negativeAmount")
467
464
  }