-
{getHeader(t, currentStep)}
+
{getHeader(t, currentIndex)}
Drawer: {isDrawerOpen ? 'open' : 'closed'}
diff --git a/src/components/Reports/AdditionalSalaryRequest/Shared/AdditionalSalaryRequestContext.tsx b/src/components/Reports/AdditionalSalaryRequest/Shared/AdditionalSalaryRequestContext.tsx
index 0a1cbebaef..0ddaa23ee4 100644
--- a/src/components/Reports/AdditionalSalaryRequest/Shared/AdditionalSalaryRequestContext.tsx
+++ b/src/components/Reports/AdditionalSalaryRequest/Shared/AdditionalSalaryRequestContext.tsx
@@ -9,14 +9,12 @@ import { amount } from 'src/lib/yupHelpers';
import { FormEnum } from '../../Shared/CalculationReports/Shared/sharedTypes';
import { Steps } from '../../Shared/CalculationReports/StepsList/StepsList';
import { CompleteFormValues } from '../AdditionalSalaryRequest';
-import { AdditionalSalaryRequestSectionEnum } from '../AdditionalSalaryRequestHelper';
import { calculateCompletionPercentage } from './calculateCompletionPercentage';
export type AdditionalSalaryRequestType = {
steps: Steps[];
currentIndex: number;
percentComplete: number;
- currentStep: AdditionalSalaryRequestSectionEnum;
handleNextStep: () => void;
handlePreviousStep: () => void;
isDrawerOpen: boolean;
@@ -43,16 +41,13 @@ interface Props {
initialValues?: CompleteFormValues;
}
-const objects = Object.values(AdditionalSalaryRequestSectionEnum);
-
export const AdditionalSalaryRequestProvider: React.FC
= ({
children,
initialValues: providedInitialValues,
}) => {
const { t } = useTranslation();
- const { steps, nextStep, previousStep, currentIndex } = useStepList(
- FormEnum.AdditionalSalary,
- );
+ const { steps, handleNextStep, handlePreviousStep, currentIndex } =
+ useStepList(FormEnum.AdditionalSalary);
const locale = useLocale();
const createCurrencyValidation = useCallback(
@@ -132,25 +127,6 @@ export const AdditionalSalaryRequestProvider: React.FC = ({
[createCurrencyValidation, t],
);
- // Step Handlers
- const [currentStep, setCurrentStep] = useState(
- AdditionalSalaryRequestSectionEnum.AboutForm,
- );
-
- const handleNextStep = useCallback(() => {
- const next = objects[currentIndex + 1];
- nextStep();
-
- setCurrentStep(next);
- }, [currentIndex, objects, nextStep]);
-
- const handlePreviousStep = useCallback(() => {
- const next = objects[currentIndex - 1];
- previousStep();
-
- setCurrentStep(next);
- }, [currentIndex, objects, previousStep]);
-
const [isDrawerOpen, setIsDrawerOpen] = useState(true);
const toggleDrawer = useCallback(() => {
setIsDrawerOpen((prev) => !prev);
@@ -185,7 +161,6 @@ export const AdditionalSalaryRequestProvider: React.FC = ({
steps,
currentIndex,
percentComplete,
- currentStep,
handleNextStep,
handlePreviousStep,
isDrawerOpen,
@@ -197,11 +172,12 @@ export const AdditionalSalaryRequestProvider: React.FC = ({
steps,
currentIndex,
percentComplete,
- currentStep,
handleNextStep,
handlePreviousStep,
isDrawerOpen,
toggleDrawer,
+ setIsDrawerOpen,
+ handleCancel,
],
);
diff --git a/src/components/Reports/AdditionalSalaryRequest/Shared/Helper/getHeader.ts b/src/components/Reports/AdditionalSalaryRequest/Shared/Helper/getHeader.ts
index 73dd4e090b..caabb3d773 100644
--- a/src/components/Reports/AdditionalSalaryRequest/Shared/Helper/getHeader.ts
+++ b/src/components/Reports/AdditionalSalaryRequest/Shared/Helper/getHeader.ts
@@ -1,16 +1,14 @@
import { TFunction } from 'i18next';
-import { AdditionalSalaryRequestSectionEnum } from '../../AdditionalSalaryRequestHelper';
-export const getHeader = (
- t: TFunction,
- step: AdditionalSalaryRequestSectionEnum,
-): string => {
+export const getHeader = (t: TFunction, step: number): string => {
switch (step) {
- case AdditionalSalaryRequestSectionEnum.AboutForm:
+ case 0:
return 'About this Form';
- case AdditionalSalaryRequestSectionEnum.CompleteForm:
+ case 1:
return 'Complete the Form';
- case AdditionalSalaryRequestSectionEnum.Receipt:
+ case 2:
return 'Receipt';
+ default:
+ return '';
}
};
diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx
index b1ea0ab5a9..121ec8c478 100644
--- a/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx
@@ -30,9 +30,8 @@ export const EligibleDisplay: React.FC = ({
Our records indicate that you have an approved MHA amount. To view
your MHA amount, click on the "View Current MHA" button
- below. If you would like to apply for a new MHA, click on the
- "Duplicate Last Year's MHA" button below or
- "Request New MHA" below.
+ below. If you would like to apply for a new MHA, click
+ "Update Current MHA".
)}
diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx
index f33e8031f8..55515dc0cd 100644
--- a/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx
@@ -34,10 +34,13 @@ export const IneligibleDisplay: React.FC = () => {
Completing a Minister's Housing Allowance will submit the
request for {preferredName}. {spousePreferredName} has not
completed the required IBS courses to meet eligibility criteria.
- When you calculate your salary, you will see the approved amount
- that can be applied to {preferredName}'s salary. If you
- believe this is incorrect, please contact Personnel Records at
- 407-826-2252 or MHA@cru.org .
+
+
+ Once approved, when you calculate your salary, you will see the
+ approved amount that can be applied to {preferredName}'s
+ salary. If you believe this is incorrect, please contact
+ Personnel Records at 407-826-2252 or{' '}
+ MHA@cru.org .
diff --git a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.graphql b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.graphql
index 2934360f02..6bc9659b6d 100644
--- a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.graphql
+++ b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.graphql
@@ -1,31 +1,36 @@
+fragment RequestAttributes on MhaRequestAttributes {
+ rentOrOwn
+ rentalValue
+ furnitureCostsOne
+ avgUtilityOne
+ mortgageOrRentPayment
+ furnitureCostsTwo
+ repairCosts
+ avgUtilityTwo
+ unexpectedExpenses
+ overallAmount
+ phoneNumber
+ emailAddress
+ iUnderstandMhaPolicy
+ hrApprovedAt
+ approvedOverallAmount
+ availableDate
+ boardApprovedAt
+ deadlineDate
+ spouseSpecific
+ staffSpecific
+ submittedAt
+ changesRequestedAt
+}
+
query MinistryHousingAllowanceRequests {
ministryHousingAllowanceRequests {
nodes {
id
personNumber
+ updatedAt
requestAttributes {
- rentOrOwn
- rentalValue
- furnitureCostsOne
- avgUtilityOne
- mortgageOrRentPayment
- furnitureCostsTwo
- repairCosts
- avgUtilityTwo
- unexpectedExpenses
- overallAmount
- phoneNumber
- emailAddress
- iUnderstandMhaPolicy
- hrApprovedAt
- approvedOverallAmount
- availableDate
- boardApprovedAt
- deadlineDate
- spouseSpecific
- staffSpecific
- submittedAt
- changesRequestedAt
+ ...RequestAttributes
}
status
user {
@@ -42,29 +47,9 @@ query MinistryHousingAllowanceRequest($ministryHousingAllowanceRequestId: ID!) {
ministryHousingAllowanceRequest(id: $ministryHousingAllowanceRequestId) {
id
personNumber
+ updatedAt
requestAttributes {
- rentOrOwn
- rentalValue
- furnitureCostsOne
- avgUtilityOne
- mortgageOrRentPayment
- furnitureCostsTwo
- repairCosts
- avgUtilityTwo
- unexpectedExpenses
- overallAmount
- phoneNumber
- emailAddress
- iUnderstandMhaPolicy
- hrApprovedAt
- approvedOverallAmount
- availableDate
- boardApprovedAt
- deadlineDate
- spouseSpecific
- staffSpecific
- submittedAt
- changesRequestedAt
+ ...RequestAttributes
}
status
user {
@@ -87,10 +72,7 @@ mutation CreateHousingAllowanceRequest(
status
personNumber
requestAttributes {
- rentOrOwn
- rentalValue
- furnitureCostsOne
- avgUtilityOne
+ ...RequestAttributes
}
user {
id
@@ -108,19 +90,40 @@ mutation UpdateMinistryHousingAllowanceRequest(
ministryHousingAllowanceRequest {
id
requestAttributes {
- rentOrOwn
- rentalValue
- furnitureCostsOne
- avgUtilityOne
- mortgageOrRentPayment
- furnitureCostsTwo
- repairCosts
- avgUtilityTwo
- unexpectedExpenses
- overallAmount
- phoneNumber
- emailAddress
- iUnderstandMhaPolicy
+ ...RequestAttributes
+ }
+ }
+ }
+}
+
+mutation DeleteMinistryHousingAllowanceRequest(
+ $input: MinistryHousingAllowanceRequestDeleteMutationInput!
+) {
+ deleteMinistryHousingAllowanceRequest(input: $input) {
+ id
+ }
+}
+
+mutation SubmitMinistryHousingAllowanceRequest(
+ $input: MinistryHousingAllowanceRequestSubmitMutationInput!
+) {
+ submitMinistryHousingAllowanceRequest(input: $input) {
+ ministryHousingAllowanceRequest {
+ requestAttributes {
+ ...RequestAttributes
+ }
+ }
+ }
+}
+
+mutation DuplicateMinistryHousingAllowanceRequest(
+ $input: DuplicateMinistryHousingAllowanceRequestMutationInput!
+) {
+ duplicateMinistryHousingAllowanceRequest(input: $input) {
+ ministryHousingAllowanceRequest {
+ id
+ requestAttributes {
+ ...RequestAttributes
}
}
}
diff --git a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.tsx b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.tsx
index 9e2507e5eb..87e4fa14e6 100644
--- a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.tsx
@@ -29,8 +29,11 @@ export const MinisterHousingAllowanceReport = () => {
const { enqueueSnackbar } = useSnackbar();
const accountListId = useAccountListId();
- const { data, error: requestsError } =
- useMinistryHousingAllowanceRequestsQuery();
+ const {
+ data,
+ error: requestsError,
+ loading,
+ } = useMinistryHousingAllowanceRequestsQuery();
const requests = data?.ministryHousingAllowanceRequests.nodes ?? [];
const {
@@ -58,9 +61,11 @@ export const MinisterHousingAllowanceReport = () => {
const onCreateMHARequest = async () => {
await createMHA({
variables: {
- requestAttributes: {},
+ requestAttributes: {
+ phoneNumber: userHcmData?.staffInfo.primaryPhoneNumber,
+ emailAddress: userHcmData?.staffInfo.emailAddress,
+ },
},
- refetchQueries: ['MinistryHousingAllowanceRequests'],
onCompleted: ({ createMinistryHousingAllowanceRequest: newRequest }) => {
enqueueSnackbar(
t("Successfully created MHA Request. You'll be redirected shortly."),
@@ -107,6 +112,7 @@ export const MinisterHousingAllowanceReport = () => {
request.status === MhaStatusEnum.BoardApproved &&
isCurrentRequestPending,
);
+
return (
{
{requestsError ? (
- ) : !requests ? (
+ ) : loading ? (
) : (
<>
@@ -146,14 +152,13 @@ export const MinisterHousingAllowanceReport = () => {
{t('Request New MHA')}
)}
+ {previousApprovedRequest && (
+
+
+
+ )}
>
)}
-
- {previousApprovedRequest && (
-
-
-
- )}
}
/>
diff --git a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowanceSkeleton.tsx b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowanceSkeleton.tsx
index 2fa037b925..40271ba4de 100644
--- a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowanceSkeleton.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowanceSkeleton.tsx
@@ -6,7 +6,7 @@ export const MinisterHousingAllowanceReportSkeleton: React.FC = () => {
return (
<>
{
}}
/>
{
}}
/>
{
}}
/>
;
+ mocks?: {
+ HcmData?: HcmDataQuery;
+ MinistryHousingAllowanceRequest?: MinistryHousingAllowanceRequestQuery;
+ UpdateMinistryHousingAllowanceRequest?: UpdateMinistryHousingAllowanceRequestMutation;
+ };
}
const TestComponent: React.FC = ({
type,
contextValue,
+ mocks,
}) => {
const content = contextValue ? (
= ({
return (
-
- onCall={mutationSpy}
- >
- {content}
-
+
+
+ mocks={mocks}
+ onCall={mutationSpy}
+ >
+ {content}
+
+
);
};
describe('RequestPage', () => {
- it('renders steps list', () => {
- const { getByText } = render( );
-
- expect(getByText(/1. about this form/i)).toBeInTheDocument();
+ it('renders steps list', async () => {
+ const { getByText, findByText } = render(
+ ,
+ );
+
+ expect(await findByText(/1. about this form/i)).toBeInTheDocument();
expect(getByText(/2. rent or own?/i)).toBeInTheDocument();
expect(getByText(/3. edit your mha/i)).toBeInTheDocument();
expect(getByText(/4. receipt/i)).toBeInTheDocument();
});
describe('Edit Page', () => {
- it('starts on step 2 and updates steps when Continue clicked', () => {
- const { getByRole, getAllByRole, getByText, queryByTestId } = render(
- ,
- );
+ it('starts on step 2 and updates steps when Continue clicked', async () => {
+ const { getByRole, getAllByRole, getByText, queryByTestId, findByRole } =
+ render(
+ ,
+ );
- expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '50');
+ expect(await findByRole('progressbar')).toHaveAttribute(
+ 'aria-valuenow',
+ '50',
+ );
expect(queryByTestId('ArrowBackIcon')).toBeInTheDocument();
const continueButton = getByRole('button', { name: 'Continue' });
userEvent.click(continueButton);
- const steps = getAllByRole('listitem');
+ const stepItems = getAllByRole('listitem');
- const [firstStep, secondStep, thirdStep] = steps;
+ const [firstStep, secondStep, thirdStep] = stepItems;
expect(firstStep).toHaveTextContent('1. About this Form');
expect(
@@ -141,17 +182,19 @@ describe('RequestPage', () => {
});
it('should show an option is preselected', async () => {
- const { findAllByRole, getByRole, findByRole } = render(
+ const { findAllByRole, findByRole } = render(
{
/>,
);
- const continueButton = getByRole('button', { name: 'Continue' });
+ const continueButton = await findByRole('button', { name: 'Continue' });
userEvent.click(continueButton);
expect(await findByRole('radio', { name: 'Rent' })).toBeChecked();
@@ -169,20 +212,22 @@ describe('RequestPage', () => {
});
it('opens confirmation modal when changing selection', async () => {
- const { getByRole, getByText, queryByText } = render(
+ const { getByRole, getByText, queryByText, findByRole } = render(
{
/>,
);
- const ownRadio = getByRole('radio', { name: 'Own' });
+ const ownRadio = await findByRole('radio', { name: 'Own' });
userEvent.click(ownRadio);
expect(ownRadio).not.toBeChecked();
@@ -215,11 +260,22 @@ describe('RequestPage', () => {
describe('New Page', () => {
it('updates steps when Continue clicked', async () => {
- const { getByRole, getAllByRole, getByText, queryByTestId } = render(
- ,
- );
+ const { getByRole, getAllByRole, getByText, queryByTestId, findByRole } =
+ render(
+ ,
+ );
- expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '25');
+ expect(await findByRole('progressbar')).toHaveAttribute(
+ 'aria-valuenow',
+ '25',
+ );
expect(queryByTestId('ArrowBackIcon')).toBeInTheDocument();
const continueButton = getByRole('button', { name: 'Continue' });
@@ -272,11 +328,18 @@ describe('RequestPage', () => {
it('should show validation error if continue is clicked without selecting an option', async () => {
const { getByRole, findByRole } = render(
,
);
@@ -299,15 +362,17 @@ describe('RequestPage', () => {
{
pageType: PageEnum.New,
steps,
- currentStep: StepsEnum.RentOrOwn,
+ currentIndex: 1,
handleNextStep,
handlePreviousStep,
hasCalcValues: true,
setHasCalcValues,
updateMutation,
setIsPrint,
+ userEligibleForMHA: true,
requestData: {
id: 'request-id',
+ status: MhaStatusEnum.InProgress,
requestAttributes: {
rentOrOwn: null,
rentalValue: 1000,
@@ -349,7 +414,7 @@ describe('RequestPage', () => {
describe('View Page', () => {
it('renders empty panel layout,', () => {
- const { getByText, queryByRole, queryByTestId } = render(
+ const { getByText, queryByRole, getByTestId } = render(
{
expect(getByText('Your MHA')).toBeInTheDocument();
expect(queryByRole('progressbar')).not.toBeInTheDocument();
- expect(queryByTestId('ArrowBackIcon')).not.toBeInTheDocument();
+ expect(getByTestId('ArrowBackIcon')).toBeInTheDocument();
});
it('should have disabled text fields', () => {
@@ -383,4 +448,31 @@ describe('RequestPage', () => {
expect(input).toBeDisabled();
});
});
+
+ describe('Permission Denied', () => {
+ it('renders permission denied layout', () => {
+ const { getByText, queryByRole, getByTestId } = render(
+ ,
+ );
+
+ expect(getByText('Your MHA')).toBeInTheDocument();
+ expect(queryByRole('progressbar')).not.toBeInTheDocument();
+ expect(getByTestId('ArrowBackIcon')).toBeInTheDocument();
+ expect(
+ getByText('You do not have permission to edit this request.'),
+ ).toBeInTheDocument();
+ });
+ });
});
diff --git a/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx b/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx
index fbad31c8a9..59ffc4418c 100644
--- a/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx
@@ -2,9 +2,11 @@ import { Container, Stack } from '@mui/material';
import { Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import * as yup from 'yup';
-import { MhaRentOrOwnEnum } from 'src/graphql/types.generated';
+import Loading from 'src/components/Loading/Loading';
+import { MhaRentOrOwnEnum, MhaStatusEnum } from 'src/graphql/types.generated';
import { useAccountListId } from 'src/hooks/useAccountListId';
import i18n from 'src/lib/i18n';
+import theme from 'src/theme';
import { PanelLayout } from '../../Shared/CalculationReports/PanelLayout/PanelLayout';
import { useIconPanelItems } from '../../Shared/CalculationReports/PanelLayout/useIconPanelItems';
import { Receipt } from '../../Shared/CalculationReports/ReceiptStep/Receipt';
@@ -17,11 +19,14 @@ import { mainContentWidth } from '../MinisterHousingAllowance';
import { useMinisterHousingAllowance } from '../Shared/Context/MinisterHousingAllowanceContext';
import { getRequestUrl } from '../Shared/Helper/getRequestUrl';
import { mocks } from '../Shared/mockData';
-import { StepsEnum } from '../Shared/sharedTypes';
+import { NoEditAccess } from '../Steps/NoEditAccess/NoEditAccess';
+import { NoRequestAccess } from '../Steps/NoRequestAccess/NoRequestAccess';
import { AboutForm } from '../Steps/StepOne/AboutForm';
import { Calculation } from '../Steps/StepThree/Calculation';
import { RentOwn } from '../Steps/StepTwo/RentOwn';
+const permissionDeniedWidth = theme.spacing(100);
+
export interface FormValues {
rentOrOwn: MhaRentOrOwnEnum | undefined;
}
@@ -39,7 +44,6 @@ export const RequestPage: React.FC = () => {
requestId,
steps,
handleNextStep,
- currentStep,
pageType,
isDrawerOpen,
toggleDrawer,
@@ -47,8 +51,15 @@ export const RequestPage: React.FC = () => {
currentIndex,
setIsComplete,
requestData,
+ loading,
+ userEligibleForMHA,
} = useMinisterHousingAllowance();
+ const canEdit =
+ !requestData ||
+ requestData.status === MhaStatusEnum.InProgress ||
+ requestData.status === MhaStatusEnum.ActionRequired;
+
const request = requestData?.requestAttributes;
const value = request?.rentOrOwn ?? undefined;
@@ -65,12 +76,21 @@ export const RequestPage: React.FC = () => {
const availableDate = mocks[4].mhaDetails.staffMHA?.availableDate ?? '';
const deadlineDate = mocks[4].mhaDetails.staffMHA?.deadlineDate ?? '';
+ const iconPanelItems = useIconPanelItems(isDrawerOpen, toggleDrawer);
+
+ const editLink = getRequestUrl(accountListId, requestId, 'edit');
+ const viewLink = getRequestUrl(accountListId, requestId, 'view');
+
+ if (loading) {
+ return ;
+ }
+
return isView ? (
@@ -86,10 +106,38 @@ export const RequestPage: React.FC = () => {
}
/>
+ ) : !canEdit ? (
+
+
+
+
+
+ }
+ />
+ ) : !userEligibleForMHA ? (
+
+
+
+
+
+ }
+ />
) : (
{
{({ values }) => (
- {currentStep === StepsEnum.AboutForm ? (
+ {currentIndex === 0 && (
- ) : currentStep === StepsEnum.RentOrOwn ? (
-
- ) : currentStep === StepsEnum.CalcForm ? (
+ )}
+ {currentIndex === 1 && }
+ {currentIndex === 2 && (
- ) : currentStep === StepsEnum.Receipt ? (
+ )}
+ {currentIndex === 3 && (
- ) : null}
+ )}
)}
diff --git a/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/AutosaveCustomTextField.test.tsx b/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/AutosaveCustomTextField.test.tsx
index 9b42543a55..a9cc3be41e 100644
--- a/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/AutosaveCustomTextField.test.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/AutosaveCustomTextField.test.tsx
@@ -3,6 +3,7 @@ import { ThemeProvider } from '@mui/material/styles';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Formik } from 'formik';
+import { SnackbarProvider } from 'notistack';
import * as yup from 'yup';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { PageEnum } from 'src/components/Reports/Shared/CalculationReports/Shared/sharedTypes';
@@ -23,30 +24,32 @@ const defaultSchema = yup.object({
const TestComponent: React.FC = () => (
-
- onCall={mutationSpy}
- >
-
+
+ onCall={mutationSpy}
>
-
-
-
-
-
+
+
+
+
+
+
+
);
diff --git a/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.test.tsx b/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.test.tsx
index be6389c04e..1b3c1c6097 100644
--- a/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.test.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.test.tsx
@@ -1,5 +1,6 @@
import { ThemeProvider } from '@mui/material/styles';
import { renderHook, waitFor } from '@testing-library/react';
+import { SnackbarProvider } from 'notistack';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { PageEnum } from 'src/components/Reports/Shared/CalculationReports/Shared/sharedTypes';
import theme from 'src/theme';
@@ -11,6 +12,18 @@ import {
import { useSaveField } from './useSaveField';
const mutationSpy = jest.fn();
+const mockEnqueue = jest.fn();
+
+jest.mock('notistack', () => ({
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ ...jest.requireActual('notistack'),
+ useSnackbar: () => {
+ return {
+ enqueueSnackbar: mockEnqueue,
+ };
+ },
+}));
interface TestComponentProps {
children: React.ReactNode;
@@ -19,25 +32,27 @@ interface TestComponentProps {
const TestComponent: React.FC = ({ children }) => {
return (
-
- onCall={mutationSpy}
- >
-
+
+ onCall={mutationSpy}
>
- {children}
-
-
+
+ {children}
+
+
+
);
};
@@ -69,5 +84,42 @@ describe('useSaveField', () => {
},
),
);
+
+ await waitFor(() =>
+ expect(mockEnqueue).toHaveBeenCalledWith(
+ expect.stringContaining('Saved successfully'),
+ { variant: 'success' },
+ ),
+ );
+ });
+
+ it('should not show snackbar if all values are null', async () => {
+ const { result } = renderHook(
+ () =>
+ useSaveField({
+ formValues: { rentalValue: 50 },
+ }),
+ {
+ wrapper: TestComponent,
+ },
+ );
+
+ result.current({ rentalValue: null });
+
+ await waitFor(() =>
+ expect(mutationSpy).toHaveGraphqlOperation(
+ 'UpdateMinistryHousingAllowanceRequest',
+ {
+ input: {
+ requestId: 'request-id',
+ requestAttributes: {
+ rentalValue: null,
+ },
+ },
+ },
+ ),
+ );
+
+ expect(mockEnqueue).not.toHaveBeenCalled();
});
});
diff --git a/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.ts b/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.ts
index 09c5377632..4364c1d72a 100644
--- a/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.ts
+++ b/src/components/Reports/MinisterHousingAllowance/Shared/AutoSave/useSaveField.ts
@@ -1,4 +1,6 @@
import { useCallback } from 'react';
+import { useSnackbar } from 'notistack';
+import { useTranslation } from 'react-i18next';
import { MinistryHousingAllowanceRequestAttributesInput } from 'pages/api/graphql-rest.page.generated';
import { calculateAnnualTotals } from 'src/hooks/useAnnualTotal';
import { useUpdateMinistryHousingAllowanceRequestMutation } from '../../MinisterHousingAllowance.generated';
@@ -10,11 +12,12 @@ interface UseSaveFieldOptions {
}
export const useSaveField = ({ formValues }: UseSaveFieldOptions) => {
+ const { t } = useTranslation();
+ const { enqueueSnackbar } = useSnackbar();
+
const { requestData } = useMinisterHousingAllowance();
const [updateMinistryHousingAllowanceRequest] =
- useUpdateMinistryHousingAllowanceRequestMutation({
- refetchQueries: ['MinistryHousingAllowanceRequest'],
- });
+ useUpdateMinistryHousingAllowanceRequestMutation({});
const values = requestData?.requestAttributes;
const saveField = useCallback(
@@ -32,35 +35,41 @@ export const useSaveField = ({ formValues }: UseSaveFieldOptions) => {
const { annualTotal: overallAmount } =
calculateAnnualTotals(updatedValues);
- try {
- await updateMinistryHousingAllowanceRequest({
- variables: {
- input: {
- requestId: requestData.id,
+ await updateMinistryHousingAllowanceRequest({
+ variables: {
+ input: {
+ requestId: requestData.id,
+ requestAttributes: {
+ ...attributes,
+ overallAmount,
+ },
+ },
+ },
+ optimisticResponse: {
+ updateMinistryHousingAllowanceRequest: {
+ __typename: 'MinistryHousingAllowanceRequestUpdateMutationPayload',
+ ministryHousingAllowanceRequest: {
+ ...requestData,
requestAttributes: {
+ __typename: 'MhaRequestAttributes',
+ ...values,
...attributes,
overallAmount,
},
},
},
- optimisticResponse: {
- updateMinistryHousingAllowanceRequest: {
- __typename:
- 'MinistryHousingAllowanceRequestUpdateMutationPayload',
- ministryHousingAllowanceRequest: {
- ...requestData,
- requestAttributes: {
- ...values,
- ...attributes,
- overallAmount,
- },
- },
- },
- },
- });
- } catch (error) {}
+ },
+ onCompleted: () => {
+ const hasValue = Object.values(attributes).some(
+ (value) => value !== null,
+ );
+ if (hasValue) {
+ enqueueSnackbar(t('Saved successfully'), { variant: 'success' });
+ }
+ },
+ });
},
- [formValues, updateMinistryHousingAllowanceRequest, requestData],
+ [formValues, updateMinistryHousingAllowanceRequest, requestData, t],
);
return saveField;
diff --git a/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.test.tsx b/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.test.tsx
index 130984ca37..fbaa4b8f9f 100644
--- a/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.test.tsx
+++ b/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.test.tsx
@@ -7,7 +7,6 @@ import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { render } from '__tests__/util/testingLibraryReactMock';
import { PageEnum } from 'src/components/Reports/Shared/CalculationReports/Shared/sharedTypes';
import theme from 'src/theme';
-import { StepsEnum } from '../sharedTypes';
import {
MinisterHousingAllowanceProvider,
useMinisterHousingAllowance,
@@ -38,7 +37,7 @@ function FailedConsumer() {
function TestConsumer() {
const {
steps,
- currentStep,
+ currentIndex,
handleNextStep,
handlePreviousStep,
percentComplete,
@@ -49,7 +48,7 @@ function TestConsumer() {
{steps.length}
{percentComplete}
- {currentStep}
+ {currentIndex}
Next
Previous
@@ -66,63 +65,65 @@ describe('MinisterHousingAllowanceContext', () => {
});
it('provides initial state for new page', async () => {
- const { getByTestId, getByRole } = render(