diff --git a/src/components/UNSTABLE_TimeOff/PolicySettings/PolicySettings.tsx b/src/components/UNSTABLE_TimeOff/PolicySettings/PolicySettings.tsx index 6e1a64029..6adad8df4 100644 --- a/src/components/UNSTABLE_TimeOff/PolicySettings/PolicySettings.tsx +++ b/src/components/UNSTABLE_TimeOff/PolicySettings/PolicySettings.tsx @@ -2,6 +2,7 @@ import { useTimeOffPoliciesGetSuspense } from '@gusto/embedded-api/react-query/t import { useTimeOffPoliciesUpdateMutation } from '@gusto/embedded-api/react-query/timeOffPoliciesUpdate' import type { PutV1TimeOffPoliciesTimeOffPolicyUuidRequestBody } from '@gusto/embedded-api/models/operations/putv1timeoffpoliciestimeoffpolicyuuid' import type { TimeOffPolicy } from '@gusto/embedded-api/models/components/timeoffpolicy' +import { useQueryClient } from '@tanstack/react-query' import { PolicySettingsPresentation } from './PolicySettingsPresentation' import type { PolicySettingsFormData, PolicySettingsAccrualMethod } from './PolicySettingsTypes' import { BaseComponent, type BaseComponentInterface } from '@/components/Base' @@ -89,6 +90,7 @@ function buildUpdateRequestBody( function Root({ policyId }: PolicySettingsProps) { const { onEvent, baseSubmitHandler } = useBase() + const queryClient = useQueryClient() const { data: policyResponse } = useTimeOffPoliciesGetSuspense({ timeOffPolicyUuid: policyId, @@ -111,6 +113,9 @@ function Root({ policyId }: PolicySettingsProps) { }, }) + void queryClient.invalidateQueries({ + queryKey: ['@gusto/embedded-api', 'timeOffPolicies', 'get'], + }) onEvent(componentEvents.TIME_OFF_POLICY_SETTINGS_DONE, timeOffPolicy) }) } diff --git a/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.test.ts b/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.test.ts index 4a0959404..ecd782daa 100644 --- a/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.test.ts +++ b/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.test.ts @@ -9,6 +9,7 @@ type TimeOffState = | 'policyTypeSelector' | 'policyDetailsForm' | 'policySettings' + | 'editPolicySettings' | 'addEmployeesToPolicy' | 'viewTimeOffPolicyDetail' | 'holidaySelectionForm' @@ -311,13 +312,17 @@ describe('timeOffStateMachine', () => { }) describe('viewTimeOffPolicyDetail state', () => { - it('transitions to addEmployeesToPolicy on TIME_OFF_ADD_EMPLOYEES_TO_POLICY with policyId', () => { - const service = createService() + function toViewPolicyDetail(service: ReturnType) { send(service, componentEvents.TIME_OFF_VIEW_POLICY, { policyId: 'policy-existing', policyType: 'vacation', }) expect(service.machine.current).toBe('viewTimeOffPolicyDetail') + } + + it('transitions to addEmployeesToPolicy on TIME_OFF_ADD_EMPLOYEES_TO_POLICY with policyId', () => { + const service = createService() + toViewPolicyDetail(service) send(service, componentEvents.TIME_OFF_ADD_EMPLOYEES_TO_POLICY, { policyId: 'policy-existing', @@ -330,10 +335,7 @@ describe('timeOffStateMachine', () => { it('returns to viewTimeOffPolicyDetail with the same policyId after adding employees', () => { const service = createService() - send(service, componentEvents.TIME_OFF_VIEW_POLICY, { - policyId: 'policy-existing', - policyType: 'vacation', - }) + toViewPolicyDetail(service) send(service, componentEvents.TIME_OFF_ADD_EMPLOYEES_TO_POLICY, { policyId: 'policy-existing', }) @@ -344,13 +346,9 @@ describe('timeOffStateMachine', () => { expect(service.context.policyId).toBe('policy-existing') }) - it('transitions to policyDetailsForm on TIME_OFF_EDIT_POLICY', () => { + it('transitions to policyDetailsForm on TIME_OFF_EDIT_POLICY with policyId', () => { const service = createService() - send(service, componentEvents.TIME_OFF_VIEW_POLICY, { - policyId: 'policy-existing', - policyType: 'vacation', - }) - expect(service.machine.current).toBe('viewTimeOffPolicyDetail') + toViewPolicyDetail(service) send(service, componentEvents.TIME_OFF_EDIT_POLICY, { policyId: 'policy-existing' }) @@ -359,19 +357,57 @@ describe('timeOffStateMachine', () => { expect(service.context.alerts).toBeUndefined() }) - it('transitions to policySettings on TIME_OFF_CHANGE_SETTINGS', () => { + it('transitions to editPolicySettings on TIME_OFF_CHANGE_SETTINGS with policyId', () => { const service = createService() - send(service, componentEvents.TIME_OFF_VIEW_POLICY, { - policyId: 'policy-existing', - policyType: 'vacation', - }) + toViewPolicyDetail(service) + + send(service, componentEvents.TIME_OFF_CHANGE_SETTINGS, { policyId: 'policy-existing' }) + + expect(service.machine.current).toBe('editPolicySettings') + expect(service.context.policyId).toBe('policy-existing') + }) + + it('returns to viewTimeOffPolicyDetail on TIME_OFF_POLICY_SETTINGS_DONE in the edit flow', () => { + const service = createService() + toViewPolicyDetail(service) + send(service, componentEvents.TIME_OFF_CHANGE_SETTINGS, { policyId: 'policy-existing' }) + + send(service, componentEvents.TIME_OFF_POLICY_SETTINGS_DONE) + expect(service.machine.current).toBe('viewTimeOffPolicyDetail') + // policyId is preserved so the detail view re-renders for the same policy + expect(service.context.policyId).toBe('policy-existing') + }) + it('returns to viewTimeOffPolicyDetail on TIME_OFF_POLICY_SETTINGS_BACK in the edit flow', () => { + const service = createService() + toViewPolicyDetail(service) send(service, componentEvents.TIME_OFF_CHANGE_SETTINGS, { policyId: 'policy-existing' }) - expect(service.machine.current).toBe('policySettings') + send(service, componentEvents.TIME_OFF_POLICY_SETTINGS_BACK) + + expect(service.machine.current).toBe('viewTimeOffPolicyDetail') expect(service.context.policyId).toBe('policy-existing') - expect(service.context.alerts).toBeUndefined() + }) + + it('cancels from editPolicySettings to policyList', () => { + const service = createService() + toViewPolicyDetail(service) + send(service, componentEvents.TIME_OFF_CHANGE_SETTINGS, { policyId: 'policy-existing' }) + + send(service, componentEvents.CANCEL) + + expect(service.machine.current).toBe('policyList') + }) + + it('does not route TIME_OFF_POLICY_SETTINGS_DONE in the create flow back to the detail view', () => { + // Guards against regression of the create flow when adding the edit-only state. + const service = createService() + toPolicySettings(service) + + send(service, componentEvents.TIME_OFF_POLICY_SETTINGS_DONE) + + expect(service.machine.current).toBe('addEmployeesToPolicy') }) }) diff --git a/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.ts b/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.ts index 249914d9e..57480983e 100644 --- a/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.ts +++ b/src/components/UNSTABLE_TimeOff/TimeOffFlow/timeOffStateMachine.ts @@ -308,7 +308,7 @@ export const timeOffMachine = { ), transition( componentEvents.TIME_OFF_CHANGE_SETTINGS, - 'policySettings', + 'editPolicySettings', reduce( ( ctx: TimeOffFlowContextInterface, @@ -324,6 +324,35 @@ export const timeOffMachine = { backToListTransition, ), + // Distinct from `policySettings` (the create-flow step) so that DONE/BACK + // return to the policy detail view instead of routing into the create + // flow's add-employees / details-form steps. + editPolicySettings: state( + transition( + componentEvents.TIME_OFF_POLICY_SETTINGS_DONE, + 'viewTimeOffPolicyDetail', + reduce( + (ctx: TimeOffFlowContextInterface): TimeOffFlowContextInterface => ({ + ...ctx, + component: TimeOffPolicyDetailContextual, + alerts: undefined, + }), + ), + ), + transition( + componentEvents.TIME_OFF_POLICY_SETTINGS_BACK, + 'viewTimeOffPolicyDetail', + reduce( + (ctx: TimeOffFlowContextInterface): TimeOffFlowContextInterface => ({ + ...ctx, + component: TimeOffPolicyDetailContextual, + alerts: undefined, + }), + ), + ), + cancelToPolicyList, + ), + holidaySelectionForm: state( transition( componentEvents.TIME_OFF_HOLIDAY_SELECTION_DONE,