diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.test.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.test.tsx index 379910247a..449dcdcd31 100644 --- a/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.test.tsx +++ b/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.test.tsx @@ -19,17 +19,15 @@ const TestComponent: React.FC = ({ isPending }) => ( ); describe('EligibleDisplay', () => { - it('should render title and message when pending is true', () => { + it('should render message when pending is true', () => { const { getByText } = render(); - expect(getByText('Your MHA')).toBeInTheDocument(); expect(getByText(/waiting to be processed/i)).toBeInTheDocument(); }); - it('should render title and message when pending is false', () => { + it('should render message when pending is false', () => { const { getByText } = render(); - expect(getByText('Your MHA')).toBeInTheDocument(); expect( getByText(/our records indicate that you have an approved mha amount/i), ).toBeInTheDocument(); diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx index 121ec8c478..8039e03cac 100644 --- a/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx +++ b/src/components/Reports/MinisterHousingAllowance/MainPages/EligibleDisplay.tsx @@ -1,5 +1,5 @@ -import { Box, Typography } from '@mui/material'; -import { Trans, useTranslation } from 'react-i18next'; +import { Box } from '@mui/material'; +import { Trans } from 'react-i18next'; interface EligibleDisplayProps { isPending: boolean; @@ -8,34 +8,28 @@ interface EligibleDisplayProps { export const EligibleDisplay: React.FC = ({ isPending, }) => { - const { t } = useTranslation(); return ( - <> - - {t('Your MHA')} - - - {isPending ? ( - -

- Our records indicate that you have an MHA request{' '} - waiting to be processed. To view your MHA - request, click on the "View Current MHA" button below. - If you would like to make changes to your request, click on the - "Edit Request" button below. -

-
- ) : ( - -

- 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 - "Update Current MHA". -

-
- )} -
- + + {isPending ? ( + +

+ Our records indicate that you have an MHA request{' '} + waiting to be processed. To view your MHA request, + click on the "View Current MHA" button below. If you would + like to make changes to your request, click on the "Edit + Request" button below. +

+
+ ) : ( + +

+ 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 "Update + Current MHA". +

+
+ )} +
); }; diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.test.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.test.tsx index b0b8b9cb5b..5cbd9e2da3 100644 --- a/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.test.tsx +++ b/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.test.tsx @@ -6,7 +6,6 @@ import { render } from '@testing-library/react'; import theme from 'src/theme'; import { ContextType, - HcmData, MinisterHousingAllowanceContext, } from '../Shared/Context/MinisterHousingAllowanceContext'; import { IneligibleDisplay } from './IneligibleDisplay'; @@ -30,57 +29,67 @@ const TestComponent: React.FC = ({ contextValue }) => { }; describe('IneligibleDisplay', () => { - it('should render page with single staff', () => { - const { getByText, queryByText } = render( + it('should render single user ineligible message', () => { + const { getByTestId } = render( , + ); + + expect(getByTestId('single-ineligible')).toBeInTheDocument(); + }); + + it('should render both ineligible message when neither user is eligible', () => { + const { getByTestId } = render( + , + ); + + expect(getByTestId('both-ineligible')).toBeInTheDocument(); + }); + + it('should render user ineligible message when user ineligible', () => { + const { getByTestId } = render( + , ); - expect(getByText('Your MHA')).toBeInTheDocument(); - expect( - getByText( - /our records indicate that you have not applied for minister's housing allowance/i, - ), - ).toBeInTheDocument(); - expect( - queryByText(/Jane has not completed the required ibs courses/i), - ).not.toBeInTheDocument(); + expect(getByTestId('one-ineligible')).toBeInTheDocument(); }); - it('should render page with married staff', () => { - const { getByText } = render( + it('should render spouse ineligible message when spouse ineligible', () => { + const { getByTestId } = render( , ); - expect( - getByText(/Jane has not completed the required ibs courses/i), - ).toBeInTheDocument(); + expect(getByTestId('one-ineligible')).toBeInTheDocument(); }); }); diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx index 6de04f8293..cd2acc2ef8 100644 --- a/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx +++ b/src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx @@ -1,53 +1,96 @@ -import { Box, Typography } from '@mui/material'; +import { Box } from '@mui/material'; import { Trans, useTranslation } from 'react-i18next'; import { useMinisterHousingAllowance } from '../Shared/Context/MinisterHousingAllowanceContext'; export const IneligibleDisplay: React.FC = () => { - const { t } = useTranslation(); - const { isMarried, preferredName, spousePreferredName } = - useMinisterHousingAllowance(); + const { + isMarried, + preferredName, + spousePreferredName, + userEligibleForMHA, + spouseEligibleForMHA, + } = useMinisterHousingAllowance(); - // TODO - Add spouse to API and check eligibility - // We will get this from HCM data in the future - const spouseEligibleForMHA = false; + const { t } = useTranslation(); - return ( - <> - - {t('Your MHA')} + if (!isMarried) { + return ( + + +

+ You have not completed the required IBS courses to meet eligibility + criteria. +

+

+ Once approved, when you calculate your salary, you will see the + approved amount that can be applied to your salary. If you believe + this is incorrect, please contact Personnel Records at{' '} + 407-826-2230 or{' '} + MHA@cru.org. +

+
- + ); + } + + const bothIneligible = !userEligibleForMHA && !spouseEligibleForMHA; + + if (bothIneligible) { + return ( +

- Our records indicate that you have not applied for Minister's - Housing Allowance. If you would like information about applying for - one, contact Personnel Records at{' '} - (407) 826-2230 or{' '} + {'{{preferredName}}'} and {'{{spousePreferredName}}'} have not + completed the required IBS courses to meet eligibility criteria. +

+

+ Once approved, when you calculate your salary, you will see the + approved amount that can be applied to {'{{preferredName}}'} and{' '} + {'{{spousePreferredName}}'}'s salary. If you believe this is + incorrect, please contact Personnel Records at{' '} + 407-826-2230 or{' '} MHA@cru.org.

- {isMarried && spouseEligibleForMHA === false && ( - - -

- Completing a Minister's Housing Allowance will submit the - request for {preferredName}. {spousePreferredName} has not - completed the required IBS courses to meet eligibility criteria. -

-

- 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-2230 or{' '} - MHA@cru.org. -

-
-
- )}
- + ); + } + + const eligibleUserName = userEligibleForMHA + ? preferredName + : spousePreferredName; + const ineligibleUserName = userEligibleForMHA + ? spousePreferredName + : preferredName; + + return ( + + +

+ Completing a Minister's Housing Allowance will submit the request + for {'{{eligibleUserName}}'}. {'{{ineligibleUserName}}'} has not + completed the required IBS courses to meet eligibility criteria. +

+

+ Once approved, when you calculate your salary, you will see the + approved amount that can be applied to {'{{ineligibleUserName}}'} + 's salary. If you believe this is incorrect, please contact + Personnel Records at 407-826-2230 or{' '} + MHA@cru.org. +

+
+
); }; diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/NoRequestsDisplay.test.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/NoRequestsDisplay.test.tsx new file mode 100644 index 0000000000..76cf851f5e --- /dev/null +++ b/src/components/Reports/MinisterHousingAllowance/MainPages/NoRequestsDisplay.test.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { ThemeProvider } from '@mui/material/styles'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon'; +import { render } from '@testing-library/react'; +import theme from 'src/theme'; +import { NoRequestsDisplay } from './NoRequestsDisplay'; + +const TestComponent: React.FC = () => ( + + + + + +); + +describe('NoRequestsDisplay', () => { + it('should render no requests message', () => { + const { getByTestId } = render(); + + expect(getByTestId('no-requests-display')).toBeInTheDocument(); + }); + + it('should render contact email link', () => { + const { getByRole } = render(); + + expect(getByRole('link', { name: 'MHA@cru.org' })).toHaveAttribute( + 'href', + 'mailto:MHA@cru.org', + ); + }); +}); diff --git a/src/components/Reports/MinisterHousingAllowance/MainPages/NoRequestsDisplay.tsx b/src/components/Reports/MinisterHousingAllowance/MainPages/NoRequestsDisplay.tsx new file mode 100644 index 0000000000..239511379f --- /dev/null +++ b/src/components/Reports/MinisterHousingAllowance/MainPages/NoRequestsDisplay.tsx @@ -0,0 +1,20 @@ +import { Box } from '@mui/material'; +import { Trans, useTranslation } from 'react-i18next'; + +export const NoRequestsDisplay: React.FC = () => { + const { t } = useTranslation(); + + return ( + + +

+ Our records indicate that you have not applied for Minister's + Housing Allowance. If you would like information about applying for + one, contact Personnel Records at{' '} + 407-826-2230 or{' '} + MHA@cru.org. +

+
+
+ ); +}; diff --git a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.test.tsx b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.test.tsx index 6f7f06cbfa..dcb60e02a9 100644 --- a/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.test.tsx +++ b/src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.test.tsx @@ -8,8 +8,10 @@ import { MhaStatusEnum } from 'src/graphql/types.generated'; import theme from 'src/theme'; import { HcmDataQuery } from '../Shared/HcmData/HCMData.generated'; import { + marriedBothIneligible, marriedMhaAndNoException, marriedNoMhaNoException, + singleIneligible, singleMhaNoException, singleNoMhaNoException, } from '../Shared/HcmData/mockData'; @@ -74,9 +76,6 @@ describe('MinisterHousingAllowanceReport', () => { expect( await findByText(/our records indicate that you have not applied for/i), ).toBeInTheDocument(); - expect( - await findByText(/will submit the request for john. jane has not/i), - ).toBeInTheDocument(); expect(await findByText('John Doe and Jane Doe')).toBeInTheDocument(); }); @@ -127,6 +126,56 @@ describe('MinisterHousingAllowanceReport', () => { expect(getByText('Current Board Approved MHA')).toBeInTheDocument(); }); + it('renders fully ineligible single user with requests and hides request details', async () => { + const { findByText, queryByText } = render( + , + ); + + expect( + await findByText(/you have not completed the required ibs courses/i), + ).toBeInTheDocument(); + + expect( + queryByText(/our records indicate that you have an mha request/i), + ).not.toBeInTheDocument(); + }); + + it('renders fully ineligible married couple and hides request details', async () => { + const { findByText, queryByText } = render( + , + ); + + expect( + await findByText(/have not completed the required ibs courses/i), + ).toBeInTheDocument(); + + expect(queryByText('Current Board Approved MHA')).not.toBeInTheDocument(); + expect( + queryByText(/our records indicate that you have an approved/i), + ).not.toBeInTheDocument(); + }); + it('renders married, pending, no approved correctly', async () => { const { findByText } = render( { isMarried, preferredName, spousePreferredName, + userEligibleForMHA, + spouseEligibleForMHA, userHcmData, spouseHcmData, } = useMinisterHousingAllowance(); @@ -94,8 +97,6 @@ export const MinisterHousingAllowanceReport = () => { }); }; - const hasNoRequests = !requests.length; - const currentRequest = requests[0] || {}; // It default to true when no availableDate as the request is likely still being processed const isCurrentRequestPending = @@ -113,6 +114,18 @@ export const MinisterHousingAllowanceReport = () => { isCurrentRequestPending, ); + const hasNoRequests = !requests.length; + + const bothEligible = userEligibleForMHA && spouseEligibleForMHA; + const eitherPersonEligible = userEligibleForMHA || spouseEligibleForMHA; + + const showIneligibleDisplay = + !userEligibleForMHA || (isMarried && !bothEligible); + const showNewRequestButton = + eitherPersonEligible && (!isCurrentRequestPending || hasNoRequests); + const showCurrentRequest = eitherPersonEligible && currentRequest; + const showPreviousRequests = eitherPersonEligible && previousApprovedRequest; + return ( { ) : ( <> + + {t('Your MHA')} + + {hasNoRequests ? ( - + <> + + {showIneligibleDisplay && } + ) : ( - + <> + {showIneligibleDisplay && } + {eitherPersonEligible && ( + + )} + )} + - {currentRequest && + {showCurrentRequest && (isCurrentRequestPending ? ( ) : ( ))} - {(!isCurrentRequestPending || hasNoRequests) && ( + {showNewRequestButton && ( )} - {previousApprovedRequest && ( + {showPreviousRequests && ( diff --git a/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx b/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx index 513dc425b6..d52b09f3b4 100644 --- a/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx +++ b/src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage.tsx @@ -52,6 +52,7 @@ export const RequestPage: React.FC = () => { requestData, loading, userEligibleForMHA, + spouseEligibleForMHA, } = useMinisterHousingAllowance(); const canEdit = @@ -116,7 +117,7 @@ export const RequestPage: React.FC = () => { } /> - ) : !userEligibleForMHA ? ( + ) : !userEligibleForMHA && !spouseEligibleForMHA ? ( Promise; requestData?: @@ -198,6 +199,11 @@ export const MinisterHousingAllowanceProvider: React.FC = ({ [userHcmData], ); + const spouseEligibleForMHA = useMemo( + () => spouseHcmData?.mhaEit?.mhaEligibility ?? false, + [spouseHcmData], + ); + const [isDrawerOpen, setIsDrawerOpen] = useState(true); const toggleDrawer = useCallback(() => { setIsDrawerOpen((prev) => !prev); @@ -227,6 +233,7 @@ export const MinisterHousingAllowanceProvider: React.FC = ({ preferredName, spousePreferredName, userEligibleForMHA, + spouseEligibleForMHA, handleDiscard, setIsComplete, requestData: requestData?.ministryHousingAllowanceRequest ?? null, @@ -256,6 +263,7 @@ export const MinisterHousingAllowanceProvider: React.FC = ({ preferredName, spousePreferredName, userEligibleForMHA, + spouseEligibleForMHA, handleDiscard, requestData, requestError, diff --git a/src/components/Reports/Shared/HcmData/mockData.ts b/src/components/Reports/Shared/HcmData/mockData.ts index 3fb8bb3b09..a73d95e0c6 100644 --- a/src/components/Reports/Shared/HcmData/mockData.ts +++ b/src/components/Reports/Shared/HcmData/mockData.ts @@ -58,6 +58,13 @@ const noMhaAndNoException: HcmDataQuery['hcm'][number] = { }, }; +const ineligibleAndNoException: HcmDataQuery['hcm'][number] = { + ...noMhaAndNoException, + mhaEit: { + mhaEligibility: false, + }, +}; + const mhaAndNoException: HcmDataQuery['hcm'][number] = { ...noMhaAndNoException, mhaRequest: { @@ -84,3 +91,11 @@ export const marriedNoMhaNoException: HcmDataQuery['hcm'] = [ staffInfo: janeDoe, }, ]; +export const singleIneligible: HcmDataQuery['hcm'] = [ineligibleAndNoException]; +export const marriedBothIneligible: HcmDataQuery['hcm'] = [ + ineligibleAndNoException, + { + ...ineligibleAndNoException, + staffInfo: janeDoe, + }, +];