Skip to content

Commit d4cdb8a

Browse files
authored
fix: clarify policy deletion error when pending requests exist (#1906)
* fix: clarify policy deletion error when pending requests exist The raw API error about pending/approved time off requests was confusing. Now catches the 422 and provides a clear, actionable message explaining what needs to be done before the policy can be deleted. * chore: regenerate i18n types for new policy deletion error keys
1 parent 07dcf33 commit d4cdb8a

3 files changed

Lines changed: 32 additions & 3 deletions

File tree

src/components/TimeOff/PolicyList/PolicyList.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ import {
1313
} from '@gusto/embedded-api/react-query/holidayPayPoliciesGet'
1414
import { useHolidayPayPoliciesDeleteMutation } from '@gusto/embedded-api/react-query/holidayPayPoliciesDelete'
1515
import type { TimeOffPolicy } from '@gusto/embedded-api/models/components/timeoffpolicy'
16+
import { UnprocessableEntityError } from '@gusto/embedded-api/models/errors/unprocessableentityerror'
1617
import { PolicyListPresentation } from './PolicyListPresentation'
1718
import type { PolicyListItem } from './PolicyListTypes'
1819
import { isListedTimeOffPolicyType } from '@/components/TimeOff/TimeOffFlow/timeOffPolicyTypes'
1920
import { BaseBoundaries, BaseLayout, type BaseComponentInterface } from '@/components/Base'
2021
import { useBaseSubmit } from '@/components/Base/useBaseSubmit'
22+
import { SDKInternalError } from '@/types/sdkError'
2123
import { composeErrorHandler } from '@/partner-hook-utils/composeErrorHandler'
2224
import { componentEvents } from '@/shared/constants'
2325
import { useI18n } from '@/i18n'
@@ -140,9 +142,28 @@ function Root({ companyId, onEvent }: PolicyListProps) {
140142
await invalidateAllHolidayPayPoliciesGet(queryClient)
141143
setDeleteSuccessAlert(t('flash.holidayDeleted'))
142144
} else {
143-
await deactivatePolicyMutation.mutateAsync({
144-
request: { timeOffPolicyUuid: policy.uuid },
145-
})
145+
try {
146+
await deactivatePolicyMutation.mutateAsync({
147+
request: { timeOffPolicyUuid: policy.uuid },
148+
})
149+
} catch (err) {
150+
if (err instanceof UnprocessableEntityError) {
151+
const hasPendingRequests = err.errors.some(
152+
e =>
153+
e.message?.toLowerCase().includes('pending') ||
154+
e.message?.toLowerCase().includes('approved'),
155+
)
156+
if (hasPendingRequests) {
157+
throw new SDKInternalError(
158+
t('errors.pendingRequestsBlockDeletion', { name: policy.name }),
159+
'api_error',
160+
)
161+
}
162+
const messages = err.errors.map(e => e.message).filter(Boolean)
163+
throw new SDKInternalError(messages.join('. ') || t('errors.deleteFailed'), 'api_error')
164+
}
165+
throw err
166+
}
146167
await invalidateAllTimeOffPoliciesGetAll(queryClient)
147168
setDeleteSuccessAlert(t('flash.policyDeleted', { name: policy.name }))
148169
}

src/i18n/en/Company.TimeOff.TimeOffPolicies.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,9 @@
3737
"policyDeleted": "Policy \"{{name}}\" deleted successfully",
3838
"holidayDeleted": "Holiday pay policy deleted successfully",
3939
"invalidPolicyType": "Please select a valid policy type."
40+
},
41+
"errors": {
42+
"pendingRequestsBlockDeletion": "\"{{name}}\" has pending or approved time off requests. Please decline or cancel those requests before deleting this policy.",
43+
"deleteFailed": "Unable to delete this policy. Please try again."
4044
}
4145
}

src/types/i18next.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,10 @@ export interface CompanyTimeOffTimeOffPolicies{
651651
"holidayDeleted":string;
652652
"invalidPolicyType":string;
653653
};
654+
"errors":{
655+
"pendingRequestsBlockDeletion":string;
656+
"deleteFailed":string;
657+
};
654658
};
655659
export interface CompanyTimeOffTimeOffPolicyDetails{
656660
"breadcrumb":string;

0 commit comments

Comments
 (0)