Skip to content

Commit 2d20393

Browse files
authored
Merge pull request #1808 from CruGlobal/fix-payrate
MPDX-9365 - PDS Goal Calculator: Make Pay Rate required and fix validation
2 parents a524e15 + 6abc403 commit 2d20393

3 files changed

Lines changed: 71 additions & 29 deletions

File tree

src/components/HrTools/PdsGoalCalculator/PdsGoalCalculator.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ describe('PdsGoalCalculator', () => {
5050
expect(await findByRole('button', { name: /continue/i })).toBeDisabled();
5151
});
5252

53+
it('disables the Continue button when Pay Type is not selected', async () => {
54+
const { findByRole } = render(
55+
<PdsGoalCalculatorTestWrapper calculationMock={{ salaryOrHourly: null }}>
56+
<PdsGoalCalculator />
57+
</PdsGoalCalculatorTestWrapper>,
58+
);
59+
60+
expect(await findByRole('button', { name: /continue/i })).toBeDisabled();
61+
});
62+
5363
it('re-enables the Continue button after the user fills in the missing field', async () => {
5464
const { findByRole } = render(
5565
<PdsGoalCalculatorTestWrapper calculationMock={{ name: '' }}>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, { useMemo } from 'react';
2+
import { MenuItem, TextField } from '@mui/material';
3+
import { useTranslation } from 'react-i18next';
4+
import * as yup from 'yup';
5+
import { DesignationSupportSalaryType } from 'src/graphql/types.generated';
6+
import { usePdsGoalAutoSave } from '../Shared/Autosave/usePdsGoalAutoSave';
7+
import { useSaveField } from '../Shared/Autosave/useSaveField';
8+
9+
// Uses usePdsGoalAutoSave directly (not AutosaveTextField) so the onChange can
10+
// atomically clear payRate alongside salaryOrHourly in a single mutation.
11+
export const PayTypeField: React.FC = () => {
12+
const { t } = useTranslation();
13+
const saveField = useSaveField();
14+
const schema = useMemo(
15+
() =>
16+
yup.object({
17+
salaryOrHourly: yup
18+
.string()
19+
.required(t('Pay Type is a required field')),
20+
}),
21+
[t],
22+
);
23+
const {
24+
value,
25+
onChange: updateValidation,
26+
disabled,
27+
error,
28+
helperText: errorMessage,
29+
} = usePdsGoalAutoSave({ fieldName: 'salaryOrHourly', schema });
30+
31+
return (
32+
<TextField
33+
fullWidth
34+
size="small"
35+
variant="outlined"
36+
select
37+
label={t('Pay Type')}
38+
error={error}
39+
helperText={error ? errorMessage : t('Changing this clears Pay Rate.')}
40+
value={value}
41+
disabled={disabled}
42+
onChange={(event) => {
43+
updateValidation(event as React.ChangeEvent<HTMLInputElement>);
44+
const newValue = event.target.value as DesignationSupportSalaryType;
45+
if (newValue !== value) {
46+
saveField({ salaryOrHourly: newValue, payRate: null });
47+
}
48+
}}
49+
>
50+
<MenuItem value={DesignationSupportSalaryType.Salaried}>
51+
{t('Salaried')}
52+
</MenuItem>
53+
<MenuItem value={DesignationSupportSalaryType.Hourly}>
54+
{t('Hourly')}
55+
</MenuItem>
56+
</TextField>
57+
);
58+
};

src/components/HrTools/PdsGoalCalculator/Setup/SetupStep.tsx

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ import { AutosaveTextField } from '../Shared/Autosave/AutosaveTextField';
3434
import { useSaveField } from '../Shared/Autosave/useSaveField';
3535
import { usePdsGoalCalculator } from '../Shared/PdsGoalCalculatorContext';
3636
import { HoursPerWeekGrid } from './HoursPerWeekGrid/HoursPerWeekGrid';
37+
import { PayTypeField } from './PayTypeField';
3738

3839
export const SetupStep: React.FC = () => {
3940
const { t } = useTranslation();
4041
const theme = useTheme();
41-
const { calculation, hcmUser, isMutating, setRightPanelContent } =
42-
usePdsGoalCalculator();
42+
const { calculation, hcmUser, setRightPanelContent } = usePdsGoalCalculator();
4343
const { data: userData } = useGetUserQuery();
4444
const schema = useMemo(
4545
() =>
@@ -203,33 +203,7 @@ export const SetupStep: React.FC = () => {
203203
</Grid>
204204

205205
<Grid item xs={12}>
206-
{/* Manual TextField (not AutosaveTextField) because changing Pay
207-
Type must atomically clear payRate as well; AutosaveTextField
208-
only writes the single bound fieldName. */}
209-
<TextField
210-
fullWidth
211-
size="small"
212-
variant="outlined"
213-
select
214-
label={t('Pay Type')}
215-
helperText={t('Changing this clears Pay Rate.')}
216-
value={calculation?.salaryOrHourly ?? ''}
217-
disabled={!calculation || isMutating}
218-
onChange={(event) => {
219-
const newValue = event.target
220-
.value as DesignationSupportSalaryType;
221-
if (newValue !== calculation?.salaryOrHourly) {
222-
saveField({ salaryOrHourly: newValue, payRate: null });
223-
}
224-
}}
225-
>
226-
<MenuItem value={DesignationSupportSalaryType.Salaried}>
227-
{t('Salaried')}
228-
</MenuItem>
229-
<MenuItem value={DesignationSupportSalaryType.Hourly}>
230-
{t('Hourly')}
231-
</MenuItem>
232-
</TextField>
206+
<PayTypeField />
233207
</Grid>
234208

235209
{payType && (

0 commit comments

Comments
 (0)