diff --git a/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.test.tsx b/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.test.tsx index 6e3500f3c8..85173f6754 100644 --- a/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.test.tsx +++ b/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.test.tsx @@ -435,6 +435,26 @@ describe('useAdditionalSalaryRequestForm', () => { expect(errors.childrenCollegeEducation).toContain('$21,000.00'); }); + it('should accept empty string for currency fields', async () => { + const { result } = renderHook( + () => + useAdditionalSalaryRequestForm({ + ...defaultFormValues, + adoption: '', + phoneNumber: '555-123-4567', + emailAddress: 'test@example.com', + }), + { wrapper: TestWrapper }, + ); + + let errors: Record = {}; + await act(async () => { + errors = await result.current.validateForm(); + }); + + expect(errors.adoption).toBeUndefined(); + }); + it('should validate additional info when exceedsCap is true', async () => { const { result } = renderHook( () => diff --git a/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.ts b/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.ts index 97e28ae0ff..f49c0acc4b 100644 --- a/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.ts +++ b/src/components/Reports/AdditionalSalaryRequest/Shared/useAdditionalSalaryRequestForm.ts @@ -95,7 +95,7 @@ export const useAdditionalSalaryRequestForm = ( const createCurrencyValidation = useCallback( (fieldName: string, max?: number) => { - let schema = amount(fieldName, t); + let schema = amount(fieldName, t).nullable(); if (max !== null && max !== undefined) { schema = schema.max( max, @@ -121,33 +121,36 @@ export const useAdditionalSalaryRequestForm = ( emailAddress: user?.staffInfo?.emailAddress || '', } as CompleteFormValues; - const initialValues: CompleteFormValues = useMemo(() => { - if (providedInitialValues) { - return providedInitialValues; - } + const initialValuesRef = useRef(null); - const request = requestData?.latestAdditionalSalaryRequest; - if (!request) { - return defaultInitialValues; + if (!initialValuesRef.current) { + if (providedInitialValues) { + initialValuesRef.current = providedInitialValues; + } else { + const request = requestData?.latestAdditionalSalaryRequest; + if (request) { + initialValuesRef.current = { + ...Object.fromEntries( + fieldConfig.map(({ key }) => [ + key, + String((request[key as keyof typeof request] as number) ?? ''), + ]), + ), + deductTaxDeferredPercent: request.deductTaxDeferredPercent || false, + deductRothPercent: request.deductRothPercent || false, + phoneNumber: + request.phoneNumber || user?.staffInfo?.primaryPhoneNumber || '', + emailAddress: + request.emailAddress || user?.staffInfo?.emailAddress || '', + totalAdditionalSalaryRequested: + request.totalAdditionalSalaryRequested || '', + additionalInfo: request.additionalInfo || '', + } as CompleteFormValues; + } } + } - return { - ...Object.fromEntries( - fieldConfig.map(({ key }) => [ - key, - String((request[key as keyof typeof request] as number) ?? ''), - ]), - ), - deductTaxDeferredPercent: request.deductTaxDeferredPercent || false, - deductRothPercent: request.deductRothPercent || false, - phoneNumber: - request.phoneNumber || user?.staffInfo?.primaryPhoneNumber || '', - emailAddress: request.emailAddress || user?.staffInfo?.emailAddress || '', - totalAdditionalSalaryRequested: - request.totalAdditionalSalaryRequested || '', - additionalInfo: request.additionalInfo || '', - } as CompleteFormValues; - }, [providedInitialValues, requestData?.latestAdditionalSalaryRequest, user]); + const initialValues = initialValuesRef.current ?? defaultInitialValues; const getMaxForField = useCallback( (field: (typeof fieldConfig)[number]): number | undefined => { @@ -188,12 +191,11 @@ export const useAdditionalSalaryRequestForm = ( function () { const total = getTotal(this.parent as CompleteFormValues); - if (total > 0) { + if (total >= 0) { lastValidTotalRef.current = total; } - const stableTotal = total > 0 ? total : lastValidTotalRef.current; - return stableTotal <= primaryAccountBalance; + return lastValidTotalRef.current <= primaryAccountBalance; }, ), additionalInfo: yup diff --git a/src/components/Reports/AdditionalSalaryRequest/SharedComponents/ValidationAlert.tsx b/src/components/Reports/AdditionalSalaryRequest/SharedComponents/ValidationAlert.tsx index 028c55f1e8..0f6fae809c 100644 --- a/src/components/Reports/AdditionalSalaryRequest/SharedComponents/ValidationAlert.tsx +++ b/src/components/Reports/AdditionalSalaryRequest/SharedComponents/ValidationAlert.tsx @@ -8,7 +8,7 @@ import { fieldConfig } from '../Shared/useAdditionalSalaryRequestForm'; export const ValidationAlert: React.FC = () => { const { t } = useTranslation(); - const { submitCount, isValid, values, errors } = + const { submitCount, values, errors } = useFormikContext(); const { salaryInfo, isInternational } = useAdditionalSalaryRequest(); @@ -35,25 +35,31 @@ export const ValidationAlert: React.FC = () => { .map(({ label }) => t(label)); }, [submitCount, salaryInfo, isInternational, values, t]); - if (!submitCount || isValid) { + const hasRequiredErrors = Object.keys(errors).some((key) => + ['phoneNumber', 'emailAddress', 'additionalInfo'].includes(key), + ); + + const hasErrors = + hasRequiredErrors || + exceedingLimitFields.length > 0 || + !!errors.totalAdditionalSalaryRequested; + + if (!submitCount || !hasErrors) { return null; } - const hasFieldErrors = Object.keys(errors).some( - (key) => key !== 'totalAdditionalSalaryRequested', - ); - return ( {t('Your form is missing information.')}
    - {hasFieldErrors && ( + {hasRequiredErrors && (
  • {t('Please enter a value for all required fields.')}
  • )} {exceedingLimitFields.length > 0 && (
  • {t('The following fields exceed their limits: {{fields}}', { fields: exceedingLimitFields.join(', '), + interpolation: { escapeValue: false }, })}
  • )}