Skip to content

Commit 10d96e3

Browse files
authored
Merge pull request #1800 from CruGlobal/MPDX-9626-mha-uat
MPDX-9626, MPDX-9627 MHA UAT fixes
2 parents f9395e4 + 2085de3 commit 10d96e3

7 files changed

Lines changed: 61 additions & 142 deletions

File tree

pages/accountLists/[accountListId]/hrTools/mhaCalculator/[requestId].page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const HousingAllowanceRequestPageContent: React.FC = () => {
5151
const { requestData, loading, isMutating, pageType } =
5252
useMinisterHousingAllowance();
5353

54-
const title = t("{{mode}} Minister's Housing Allowance Request", {
54+
const title = t("{{mode}} Minister's Housing Allowance Calculation Tool", {
5555
mode: pageType,
5656
});
5757

@@ -76,7 +76,7 @@ export const HousingAllowanceRequestPageContent: React.FC = () => {
7676
isOpen={isNavListOpen}
7777
selectedId={'mhaCalculator' + pageType}
7878
onClose={handleNavListToggle}
79-
navType={NavTypeEnum.Reports}
79+
navType={NavTypeEnum.HrTools}
8080
/>
8181
}
8282
leftOpen={isNavListOpen}
@@ -87,7 +87,7 @@ export const HousingAllowanceRequestPageContent: React.FC = () => {
8787
<MultiPageHeader
8888
isNavListOpen={isNavListOpen}
8989
onNavListToggle={handleNavListToggle}
90-
title={t("Minister's Housing Allowance Request")}
90+
title={t("Minister's Housing Allowance Calculation Tool")}
9191
rightExtra={
9292
<SavingStatus
9393
loading={loading}
@@ -96,7 +96,7 @@ export const HousingAllowanceRequestPageContent: React.FC = () => {
9696
lastSavedAt={requestData?.updatedAt ?? null}
9797
/>
9898
}
99-
headerType={HeaderTypeEnum.Report}
99+
headerType={HeaderTypeEnum.HrTools}
100100
/>
101101
</SimpleScreenOnly>
102102
<RequestPage />

pages/accountLists/[accountListId]/hrTools/mhaCalculator/index.page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const MinisterHousingAllowancePage: React.FC = () => {
5858
<MultiPageHeader
5959
isNavListOpen={isNavListOpen}
6060
onNavListToggle={handleNavListToggle}
61-
title={t("Minister's Housing Allowance Request")}
61+
title={t("Minister's Housing Allowance Calculation Tool")}
6262
headerType={HeaderTypeEnum.HrTools}
6363
/>
6464
<MinisterHousingAllowanceProvider>

src/components/HrTools/MinisterHousingAllowance/MinisterHousingAllowance.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ mutation SubmitMinistryHousingAllowanceRequest(
9595
) {
9696
submitMinistryHousingAllowanceRequest(input: $input) {
9797
ministryHousingAllowanceRequest {
98+
id
9899
requestAttributes {
99100
...RequestAttributes
100101
}

src/components/HrTools/MinisterHousingAllowance/Steps/StepThree/CalcComponents/CostOfHome.tsx

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const CostOfHome: React.FC<CostOfHomeProps> = ({
2424
const locale = useLocale();
2525
const currency = 'USD';
2626

27-
const { values, touched, errors } = useFormikContext<CalculationFormValues>();
27+
const { values } = useFormikContext<CalculationFormValues>();
2828

2929
const { totalCostOfHome, annualCostOfHome } = useAnnualTotal(
3030
values,
@@ -49,10 +49,6 @@ export const CostOfHome: React.FC<CostOfHomeProps> = ({
4949
sx={{
5050
width: '30%',
5151
color: 'text.secondary',
52-
border:
53-
touched.mortgageOrRentPayment && errors.mortgageOrRentPayment
54-
? '2px solid red'
55-
: '',
5652
}}
5753
>
5854
<AutosaveCustomTextField
@@ -80,10 +76,6 @@ export const CostOfHome: React.FC<CostOfHomeProps> = ({
8076
sx={{
8177
width: '30%',
8278
color: 'text.secondary',
83-
border:
84-
touched.furnitureCostsTwo && errors.furnitureCostsTwo
85-
? '2px solid red'
86-
: '',
8779
}}
8880
>
8981
<AutosaveCustomTextField
@@ -111,8 +103,6 @@ export const CostOfHome: React.FC<CostOfHomeProps> = ({
111103
sx={{
112104
width: '30%',
113105
color: 'text.secondary',
114-
border:
115-
touched.repairCosts && errors.repairCosts ? '2px solid red' : '',
116106
}}
117107
>
118108
<AutosaveCustomTextField
@@ -143,10 +133,6 @@ export const CostOfHome: React.FC<CostOfHomeProps> = ({
143133
sx={{
144134
width: '30%',
145135
color: 'text.secondary',
146-
border:
147-
touched.avgUtilityTwo && errors.avgUtilityTwo
148-
? '2px solid red'
149-
: '',
150136
}}
151137
>
152138
<AutosaveCustomTextField
@@ -173,10 +159,6 @@ export const CostOfHome: React.FC<CostOfHomeProps> = ({
173159
sx={{
174160
width: '30%',
175161
color: 'text.secondary',
176-
border:
177-
touched.unexpectedExpenses && errors.unexpectedExpenses
178-
? '2px solid red'
179-
: '',
180162
}}
181163
>
182164
<AutosaveCustomTextField

src/components/HrTools/MinisterHousingAllowance/Steps/StepThree/CalcComponents/FairRentalValue.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const FairRentalValue: React.FC<FairRentalValueProps> = ({ schema }) => {
2020
const locale = useLocale();
2121
const currency = 'USD';
2222

23-
const { values, touched, errors } = useFormikContext<CalculationFormValues>();
23+
const { values } = useFormikContext<CalculationFormValues>();
2424

2525
const { totalFairRental, annualFairRental } = useAnnualTotal(
2626
values,
@@ -50,8 +50,6 @@ export const FairRentalValue: React.FC<FairRentalValueProps> = ({ schema }) => {
5050
sx={{
5151
width: '30%',
5252
color: 'text.secondary',
53-
border:
54-
touched.rentalValue && errors.rentalValue ? '2px solid red' : '',
5553
}}
5654
>
5755
<AutosaveCustomTextField
@@ -85,10 +83,6 @@ export const FairRentalValue: React.FC<FairRentalValueProps> = ({ schema }) => {
8583
sx={{
8684
width: '30%',
8785
color: 'text.secondary',
88-
border:
89-
touched.furnitureCostsOne && errors.furnitureCostsOne
90-
? '2px solid red'
91-
: '',
9286
}}
9387
>
9488
<AutosaveCustomTextField
@@ -114,10 +108,6 @@ export const FairRentalValue: React.FC<FairRentalValueProps> = ({ schema }) => {
114108
sx={{
115109
width: '30%',
116110
color: 'text.secondary',
117-
border:
118-
touched.avgUtilityOne && errors.avgUtilityOne
119-
? '2px solid red'
120-
: '',
121111
}}
122112
>
123113
<AutosaveCustomTextField

src/components/HrTools/MinisterHousingAllowance/Steps/StepThree/Calculation.test.tsx

Lines changed: 17 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -130,44 +130,6 @@ describe('Calculation', () => {
130130
expect(getByRole('button', { name: /submit/i })).toBeInTheDocument();
131131
});
132132

133-
it('should show validation error when inputs are invalid', async () => {
134-
const { findByText, getByRole, findByRole, getByText } = render(
135-
<TestComponent
136-
contextValue={{
137-
...defaultContext,
138-
requestData: {
139-
...mockMHARequest,
140-
id: 'request-id',
141-
},
142-
}}
143-
/>,
144-
);
145-
146-
const row = await findByRole('row', {
147-
name: /average monthly amount for unexpected/i,
148-
});
149-
const input = within(row).getByPlaceholderText(/\$0/i);
150-
151-
userEvent.type(input, '100');
152-
expect(input).toHaveValue('100');
153-
userEvent.clear(input);
154-
expect(input).toHaveValue('');
155-
156-
input.focus();
157-
userEvent.tab();
158-
159-
expect(await findByText('Required field.')).toBeInTheDocument();
160-
161-
const submitButton = getByRole('button', { name: /submit/i });
162-
163-
userEvent.click(submitButton);
164-
165-
expect(await findByRole('alert')).toBeInTheDocument();
166-
expect(
167-
getByText('Please enter a value for all required fields.'),
168-
).toBeInTheDocument();
169-
});
170-
171133
it('should show validation error when checkbox is not checked', async () => {
172134
const { findByText, findByRole, getByText } = render(
173135
<TestComponent contextValue={defaultContext} />,
@@ -230,34 +192,6 @@ describe('Calculation', () => {
230192
expect(await findByText('Invalid email address.')).toBeInTheDocument();
231193
});
232194

233-
it('shows validation error when input is 0', async () => {
234-
const { findByRole, findByText } = render(
235-
<TestComponent
236-
contextValue={{
237-
...defaultContext,
238-
requestData: {
239-
...mockMHARequest,
240-
id: 'request-id',
241-
},
242-
}}
243-
/>,
244-
);
245-
246-
const row = await findByRole('row', {
247-
name: /average monthly amount for unexpected/i,
248-
});
249-
const input = within(row).getByPlaceholderText(/\$0/i);
250-
251-
userEvent.type(input, '0');
252-
253-
input.focus();
254-
userEvent.tab();
255-
256-
expect(input).toHaveValue('$0.00');
257-
258-
expect(await findByText('Must be greater than $0.')).toBeInTheDocument();
259-
});
260-
261195
it('shows confirmation modal when submit is clicked', async () => {
262196
const { getByRole, getByText, findByRole } = render(
263197
<TestComponent
@@ -268,6 +202,7 @@ describe('Calculation', () => {
268202
id: 'request-id',
269203
requestAttributes: {
270204
...mockMHARequest.requestAttributes,
205+
rentOrOwn: MhaRentOrOwnEnum.Rent,
271206
iUnderstandMhaPolicy: false,
272207
phoneNumber: '1234567890',
273208
emailAddress: 'john.doe@cru.org',
@@ -296,16 +231,10 @@ describe('Calculation', () => {
296231
});
297232
const input4 = within(row4).getByPlaceholderText(/\$0/i);
298233

299-
const row5 = getByRole('row', {
300-
name: /average monthly amount for unexpected/i,
301-
});
302-
const input5 = within(row5).getByPlaceholderText(/\$0/i);
303-
304234
userEvent.type(input1, '1000');
305235
userEvent.type(input2, '200');
306236
userEvent.type(input3, '300');
307237
userEvent.type(input4, '400');
308-
userEvent.type(input5, '500');
309238
const checkbox = getByRole('checkbox', {
310239
name: /i understand that my approved/i,
311240
});
@@ -337,7 +266,22 @@ describe('Calculation', () => {
337266
userEvent.click(confirmButton);
338267

339268
await waitFor(() => {
340-
expect(mutationSpy).toHaveBeenCalledTimes(6);
269+
expect(mutationSpy).toHaveBeenCalledTimes(5); // 4 field updates + 1 submit
270+
});
271+
272+
expect(updateMutation).toHaveBeenCalledWith({
273+
variables: {
274+
input: {
275+
requestId: 'request-id',
276+
requestAttributes: {
277+
mortgageOrRentPayment: 1000,
278+
furnitureCostsTwo: 200,
279+
repairCosts: 300,
280+
avgUtilityTwo: 400,
281+
unexpectedExpenses: 0,
282+
},
283+
},
284+
},
341285
});
342286

343287
expect(mutationSpy).toHaveGraphqlOperation(

src/components/HrTools/MinisterHousingAllowance/Steps/StepThree/Calculation.tsx

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -63,26 +63,11 @@ export interface CalculationFormValues {
6363

6464
const getValidationSchema = (rentOrOwn?: MhaRentOrOwnEnum) => {
6565
const baseSchema = {
66-
mortgageOrRentPayment: yup
67-
.number()
68-
.moreThan(0, i18n.t('Must be greater than $0.'))
69-
.required(i18n.t('Required field.')),
70-
furnitureCostsTwo: yup
71-
.number()
72-
.moreThan(0, i18n.t('Must be greater than $0.'))
73-
.required(i18n.t('Required field.')),
74-
repairCosts: yup
75-
.number()
76-
.moreThan(0, i18n.t('Must be greater than $0.'))
77-
.required(i18n.t('Required field.')),
78-
avgUtilityTwo: yup
79-
.number()
80-
.moreThan(0, i18n.t('Must be greater than $0.'))
81-
.required(i18n.t('Required field.')),
82-
unexpectedExpenses: yup
83-
.number()
84-
.moreThan(0, i18n.t('Must be greater than $0.'))
85-
.required(i18n.t('Required field.')),
66+
mortgageOrRentPayment: yup.number().nullable(),
67+
furnitureCostsTwo: yup.number().nullable(),
68+
repairCosts: yup.number().nullable(),
69+
avgUtilityTwo: yup.number().nullable(),
70+
unexpectedExpenses: yup.number().nullable(),
8671
phoneNumber: phoneNumber(i18n.t).required(
8772
i18n.t('Phone Number is required.'),
8873
),
@@ -99,18 +84,9 @@ const getValidationSchema = (rentOrOwn?: MhaRentOrOwnEnum) => {
9984
if (rentOrOwn === MhaRentOrOwnEnum.Own) {
10085
return yup.object({
10186
...baseSchema,
102-
rentalValue: yup
103-
.number()
104-
.moreThan(0, i18n.t('Must be greater than $0.'))
105-
.required(i18n.t('Required field.')),
106-
furnitureCostsOne: yup
107-
.number()
108-
.moreThan(0, i18n.t('Must be greater than $0.'))
109-
.required(i18n.t('Required field.')),
110-
avgUtilityOne: yup
111-
.number()
112-
.moreThan(0, i18n.t('Must be greater than $0.'))
113-
.required(i18n.t('Required field.')),
87+
rentalValue: yup.number().nullable(),
88+
furnitureCostsOne: yup.number().nullable(),
89+
avgUtilityOne: yup.number().nullable(),
11490
});
11591
}
11692

@@ -154,6 +130,30 @@ export const Calculation: React.FC<CalculationProps> = ({
154130
},
155131
});
156132

133+
const transformNullValues = (values: CalculationFormValues) => {
134+
const isOwn = rentOrOwn === MhaRentOrOwnEnum.Own;
135+
136+
return updateMutation({
137+
variables: {
138+
input: {
139+
requestId: requestData?.id ?? '',
140+
requestAttributes: {
141+
mortgageOrRentPayment: values.mortgageOrRentPayment ?? 0,
142+
furnitureCostsTwo: values.furnitureCostsTwo ?? 0,
143+
repairCosts: values.repairCosts ?? 0,
144+
avgUtilityTwo: values.avgUtilityTwo ?? 0,
145+
unexpectedExpenses: values.unexpectedExpenses ?? 0,
146+
...(isOwn && {
147+
rentalValue: values.rentalValue ?? 0,
148+
furnitureCostsOne: values.furnitureCostsOne ?? 0,
149+
avgUtilityOne: values.avgUtilityOne ?? 0,
150+
}),
151+
},
152+
},
153+
},
154+
});
155+
};
156+
157157
const request = requestData ? requestData.requestAttributes : null;
158158

159159
const actionRequired =
@@ -207,9 +207,11 @@ export const Calculation: React.FC<CalculationProps> = ({
207207
validationSchema={schema}
208208
validateOnChange
209209
validateOnBlur
210-
onSubmit={() => {
210+
onSubmit={async (values) => {
211211
try {
212-
submitMutation({
212+
await transformNullValues(values);
213+
214+
await submitMutation({
213215
variables: { input: { requestId: requestData?.id ?? '' } },
214216
});
215217
enqueueSnackbar(t('MHA request submitted successfully.'), {

0 commit comments

Comments
 (0)