-
Notifications
You must be signed in to change notification settings - Fork 1
MPDX-9129 - MHA Eligibility check for new requests #1546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1b0df9f
993e021
cf60178
d3e2df2
5945ba5
bb8eacb
e66290a
8d0681c
8f7a664
9ca3d9c
64a45d0
20dd8d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,86 +1,93 @@ | ||
| 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 TestRouter from '__tests__/util/TestRouter'; | ||
| import { GqlMockedProvider } from '__tests__/util/graphqlMocking'; | ||
| import theme from 'src/theme'; | ||
| import { HcmDataQuery } from '../../Shared/HcmData/HCMData.generated'; | ||
| import { | ||
| ContextType, | ||
| HcmData, | ||
| MinisterHousingAllowanceContext, | ||
| } from '../Shared/Context/MinisterHousingAllowanceContext'; | ||
| marriedBothIneligible, | ||
| marriedSpouseIneligible, | ||
| marriedUserIneligible, | ||
| singleIneligible, | ||
| } from '../../Shared/HcmData/mockData'; | ||
| import { MinistryHousingAllowanceRequestsQuery } from '../MinisterHousingAllowance.generated'; | ||
| import { MinisterHousingAllowanceProvider } from '../Shared/Context/MinisterHousingAllowanceContext'; | ||
| import { IneligibleDisplay } from './IneligibleDisplay'; | ||
|
|
||
| interface TestComponentProps { | ||
| contextValue: Partial<ContextType>; | ||
| hcmMock: HcmDataQuery['hcm']; | ||
| } | ||
|
|
||
| const TestComponent: React.FC<TestComponentProps> = ({ contextValue }) => { | ||
| const TestComponent: React.FC<TestComponentProps> = ({ hcmMock }) => { | ||
| return ( | ||
| <ThemeProvider theme={theme}> | ||
| <LocalizationProvider dateAdapter={AdapterLuxon}> | ||
| <MinisterHousingAllowanceContext.Provider | ||
| value={contextValue as ContextType} | ||
| <TestRouter> | ||
| <GqlMockedProvider<{ | ||
| HcmData: HcmDataQuery; | ||
| MinistryHousingAllowanceRequests: MinistryHousingAllowanceRequestsQuery; | ||
| }> | ||
| mocks={{ | ||
| HcmData: { | ||
| hcm: hcmMock, | ||
| }, | ||
| MinistryHousingAllowanceRequests: { | ||
| ministryHousingAllowanceRequests: { | ||
| nodes: [], | ||
| }, | ||
| }, | ||
| }} | ||
| > | ||
| <IneligibleDisplay /> | ||
| </MinisterHousingAllowanceContext.Provider> | ||
| </LocalizationProvider> | ||
| <MinisterHousingAllowanceProvider> | ||
| <IneligibleDisplay /> | ||
| </MinisterHousingAllowanceProvider> | ||
| </GqlMockedProvider> | ||
| </TestRouter> | ||
| </ThemeProvider> | ||
| ); | ||
| }; | ||
|
|
||
| describe('IneligibleDisplay', () => { | ||
| it('should render page with single staff', () => { | ||
| const { getByText, queryByText } = render( | ||
| <TestComponent | ||
| contextValue={{ | ||
| isMarried: false, | ||
| preferredName: 'John', | ||
| spousePreferredName: '', | ||
| userHcmData: { | ||
| staffInfo: { | ||
| personNumber: '000123456', | ||
| }, | ||
| } as unknown as HcmData, | ||
| spouseHcmData: null, | ||
| }} | ||
| />, | ||
| it('should render page with single ineligible staff', async () => { | ||
| const { findByRole, findByText, findByTestId } = render( | ||
| <TestComponent hcmMock={singleIneligible} />, | ||
| ); | ||
|
|
||
| expect(getByText('Your MHA')).toBeInTheDocument(); | ||
| expect( | ||
| getByText( | ||
| await findByRole('heading', { name: 'Your MHA' }), | ||
| ).toBeInTheDocument(); | ||
| expect( | ||
| await findByText( | ||
| /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(await findByTestId('user-ineligible-message')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('should render page with married staff', () => { | ||
| const { getByText } = render( | ||
| <TestComponent | ||
| contextValue={{ | ||
| isMarried: true, | ||
| preferredName: 'John', | ||
| spousePreferredName: 'Jane', | ||
| userHcmData: { | ||
| staffInfo: { | ||
| personNumber: '000123456', | ||
| }, | ||
| } as unknown as HcmData, | ||
| spouseHcmData: { | ||
| staffInfo: { | ||
| personNumber: '100123456', | ||
| }, | ||
| } as unknown as HcmData, | ||
| }} | ||
| />, | ||
| it('should render page with married staff and ineligible spouse', async () => { | ||
| const { findByTestId } = render( | ||
| <TestComponent hcmMock={marriedSpouseIneligible} />, | ||
| ); | ||
|
|
||
| expect( | ||
| getByText(/Jane has not completed the required ibs courses/i), | ||
| ).toBeInTheDocument(); | ||
| expect(await findByTestId('spouse-ineligible-message')).toBeInTheDocument(); | ||
| expect(await findByTestId('user-ineligible-message')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('should render page with married staff and ineligible user', async () => { | ||
| const { findByTestId, queryByTestId } = render( | ||
| <TestComponent hcmMock={marriedUserIneligible} />, | ||
| ); | ||
|
|
||
| expect(await findByTestId('user-ineligible-message')).toBeInTheDocument(); | ||
| expect(queryByTestId('spouse-ineligible-message')).not.toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('should render page with both married staff ineligible', async () => { | ||
| const { findByTestId, queryByTestId } = render( | ||
| <TestComponent hcmMock={marriedBothIneligible} />, | ||
| ); | ||
|
|
||
| expect(await findByTestId('user-ineligible-message')).toBeInTheDocument(); | ||
| expect(queryByTestId('spouse-ineligible-message')).not.toBeInTheDocument(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,44 +4,63 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const IneligibleDisplay: React.FC = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { t } = useTranslation(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { isMarried, preferredName, spousePreferredName } = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useMinisterHousingAllowance(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO - Add spouse to API and check eligibility | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // We will get this from HCM data in the future | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const spouseEligibleForMHA = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isMarried, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| preferredName, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spousePreferredName, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userEligibleForMHA, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spouseEligibleForMHA, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hcmLoading, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = useMinisterHousingAllowance(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Box mb={2}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Typography variant="h5">{t('Your MHA')}</Typography> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Trans | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| i18nKey={isMarried ? 'newMhaRequestMarried' : 'newMhaRequestSingle'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p style={{ lineHeight: 1.5 }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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-2252 or{' '} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <a href="mailto:MHA@cru.org">MHA@cru.org</a>. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Trans> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {isMarried && spouseEligibleForMHA === false && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Box mt={2}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Trans i18nKey="spouseNotEligibleMha"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p style={{ lineHeight: 1.5 }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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 <a href="mailto:MHA@cru.org">MHA@cru.org</a>. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Trans> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {!hcmLoading && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isMarried && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userEligibleForMHA && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !spouseEligibleForMHA && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Box mt={2} data-testid="spouse-ineligible-message"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Trans | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| i18nKey="spouseNotEligibleMha" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| values={{ preferredName, spousePreferredName }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p style={{ lineHeight: 1.5 }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Completing a Minister's Housing Allowance calculation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| form will submit the request for {preferredName}.{' '} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {spousePreferredName} has not completed the required IBS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| courses to meet eligibility criteria. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Trans> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {!hcmLoading && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ((isMarried && !spouseEligibleForMHA) || !userEligibleForMHA) && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+50
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These checks feel like a lot in one place. Would we be able to extract these checks into a single variable instead? Even then, |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Box mt={2} data-testid="user-ineligible-message"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Trans i18nKey="userNotEligibleMha" values={{ preferredName }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p style={{ lineHeight: 1.5 }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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-2236 or{' '} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contact Personnel Records at 407-826-2236 or{' '} | |
| contact Personnel Records at 407-826-2252 or{' '} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already reached out to Ryan to find out what the correct number is. Awaiting a response.
Check warning on line 63 in src/components/Reports/MinisterHousingAllowance/MainPages/IneligibleDisplay.tsx
CodeScene Delta Analysis / CodeScene Code Health Review (main)
❌ New issue: Complex Method
IneligibleDisplay:React.FC has a cyclomatic complexity of 10, threshold = 10. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition for displaying the user-ineligible-message has a logic issue. The current condition ((isMarried && !spouseEligibleForMHA) || !userEligibleForMHA) will show the user-ineligible message even when the user IS eligible if they're married and the spouse is ineligible. This doesn't match the intended behavior based on the test cases and the message content.
The condition should be checking if the user is NOT eligible, or if both are married and both are ineligible. Consider simplifying to just !userEligibleForMHA since this message is specifically about the user's eligibility status and when they can see approved amounts.
| {!hcmLoading && | |
| ((isMarried && !spouseEligibleForMHA) || !userEligibleForMHA) && ( | |
| <Box mt={2} data-testid="user-ineligible-message"> | |
| <Trans i18nKey="userNotEligibleMha" values={{ preferredName }}> | |
| <p style={{ lineHeight: 1.5 }}> | |
| 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-2236 or{' '} | |
| <a href="mailto:MHA@cru.org">MHA@cru.org</a>. | |
| </p> | |
| </Trans> | |
| </Box> | |
| )} | |
| {!hcmLoading && !userEligibleForMHA && ( | |
| <Box mt={2} data-testid="user-ineligible-message"> | |
| <Trans i18nKey="userNotEligibleMha" values={{ preferredName }}> | |
| <p style={{ lineHeight: 1.5 }}> | |
| 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-2236 or{' '} | |
| <a href="mailto:MHA@cru.org">MHA@cru.org</a>. | |
| </p> | |
| </Trans> | |
| </Box> | |
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping this as is to match the criteria of the Figma doc. Can change if needed.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,8 +39,12 @@ | |
| spousePreferredName, | ||
| userHcmData, | ||
| spouseHcmData, | ||
| userEligibleForMHA, | ||
| spouseEligibleForMHA, | ||
| } = useMinisterHousingAllowance(); | ||
|
|
||
| const canAccessMHA = userEligibleForMHA || spouseEligibleForMHA; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought they would have to switch screens to be a ble to see if their spouse is eligible? What. if the primary user is not Eligible but the spouse is?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dr-bizz I asked Katelyn about this and neither of us are sure what the intended behavior there is. I assumed that the form should only apply to the user if eligible, or both if both eligible. If it's true the form can still be filled out for the spouse when the user is ineligible, I'll change that. I'll reach out to Ryan as well to get better understanding.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refer to comment in |
||
|
|
||
|
Check warning on line 47 in src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance.tsx
|
||
| const personNumber = userHcmData?.staffInfo?.personNumber ?? ''; | ||
| const spousePersonNumber = spouseHcmData?.staffInfo?.personNumber ?? ''; | ||
| const lastName = userHcmData?.staffInfo?.lastName ?? ''; | ||
|
|
@@ -56,6 +60,13 @@ | |
| const [createMHA] = useCreateHousingAllowanceRequestMutation(); | ||
|
|
||
| const onCreateMHARequest = async () => { | ||
| if (!userEligibleForMHA) { | ||
| enqueueSnackbar(t('You are not eligible to create a new MHA request.'), { | ||
| variant: 'error', | ||
|
Comment on lines
+63
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One thing I noticed in MHA is that a lot of the backend logic already had errors set up, so I was getting a double snackbar sometimes. I'm not sure if you did that in the backend, but if not, this is great!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would probably want some form of frontend validation to avoid making uneccessary requests. Maybe it's best to disable fields if they are ineligible instead, but I'm wondering what the best way to notify the user of their ineligibility might be (assuming they manage to get this far)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think with eligibility, it would be best to disable "New Request" button and maybe have an information alert box on the main page. This is what Ryan and I did with edit access and the new component I created was a safety net incase a user saved the edit page but their access changed.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I plan to do that, but a user can technically bypass that right? I don't know enough about MHA. I assume disabling the fields will be sufficient in this case. |
||
| }); | ||
| return; | ||
| } | ||
|
|
||
| await createMHA({ | ||
| variables: { | ||
| requestAttributes: {}, | ||
|
|
@@ -122,7 +133,7 @@ | |
| ) : ( | ||
| <> | ||
| <Stack direction="column" width={mainContentWidth}> | ||
| {hasNoRequests ? ( | ||
| {hasNoRequests || !canAccessMHA ? ( | ||
| <IneligibleDisplay /> | ||
|
Comment on lines
+136
to
137
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code reads as if they have no requests they get the same message as users who are not eligilble for MHA |
||
| ) : ( | ||
| <EligibleDisplay isPending={isCurrentRequestPending} /> | ||
|
|
@@ -149,7 +160,7 @@ | |
| </> | ||
| )} | ||
|
|
||
| {previousApprovedRequest && ( | ||
| {canAccessMHA && previousApprovedRequest && ( | ||
| <Stack direction="column" width={mainContentWidth} mt={4}> | ||
| <CurrentBoardApproved request={previousApprovedRequest} /> | ||
| </Stack> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the user is not eligible, but the spouse is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked with Ryan and he said to display the same text that you would for a person who is eligible and has a spouse who is ineligible. The only difference would be flipping the names around! He is thinking that the request would be created for the person who is eligible.