diff --git a/pages/accountLists/[accountListId]/reports/housingAllowance/[requestId].page.tsx b/pages/accountLists/[accountListId]/reports/housingAllowance/[requestId].page.tsx index ff93fe8a63..84df44fb76 100644 --- a/pages/accountLists/[accountListId]/reports/housingAllowance/[requestId].page.tsx +++ b/pages/accountLists/[accountListId]/reports/housingAllowance/[requestId].page.tsx @@ -6,8 +6,12 @@ import { styled } from '@mui/material/styles'; import { useTranslation } from 'react-i18next'; import { blockImpersonatingNonDevelopers } from 'pages/api/utils/pagePropsHelpers'; import { SidePanelsLayout } from 'src/components/Layouts/SidePanelsLayout'; +import { DynamicExpensesClaim } from 'src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/DynamicExpensesClaim'; import { RequestPage } from 'src/components/Reports/MinisterHousingAllowance/RequestPage/RequestPage'; -import { MinisterHousingAllowanceProvider } from 'src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext'; +import { + MinisterHousingAllowanceProvider, + useMinisterHousingAllowance, +} from 'src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext'; import { PageEnum } from 'src/components/Reports/Shared/CalculationReports/Shared/sharedTypes'; import { SimpleScreenOnly } from 'src/components/Reports/styledComponents'; import { @@ -23,11 +27,61 @@ const RequestPageWrapper = styled(Box)(({ theme }) => ({ backgroundColor: theme.palette.common.white, })); +interface HousingAllowanceRequestContentProps { + isNavListOpen: boolean; + onNavListToggle: () => void; +} + +const HousingAllowanceRequestContent: React.FC< + HousingAllowanceRequestContentProps +> = ({ isNavListOpen, onNavListToggle }) => { + const { t } = useTranslation(); + const { isRightPanelOpen } = useMinisterHousingAllowance(); + + return ( + + } + leftOpen={isNavListOpen} + leftWidth="290px" + mainContent={ + <> + + + + + + } + rightPanel={isRightPanelOpen ? : undefined} + rightOpen={isRightPanelOpen} + rightWidth="35%" + /> + ); +}; + const HousingAllowanceRequestPage: React.FC = () => { const { t } = useTranslation(); const router = useRouter(); const { requestId, mode } = router.query; + const [isNavListOpen, setIsNavListOpen] = useState(false); + + const handleNavListToggle = () => { + setIsNavListOpen(!isNavListOpen); + }; + if (!requestId) { return ; } @@ -54,49 +108,21 @@ const HousingAllowanceRequestPage: React.FC = () => { mode: pageType, }); - const [isNavListOpen, setIsNavListOpen] = useState(false); - - const handleNavListToggle = () => { - setIsNavListOpen(!isNavListOpen); - }; - return ( <> {title} - - } - leftOpen={isNavListOpen} - leftWidth="290px" - mainContent={ - <> - - - - - - - - } - /> + + + ); diff --git a/pages/accountLists/[accountListId]/reports/housingAllowance/index.page.tsx b/pages/accountLists/[accountListId]/reports/housingAllowance/index.page.tsx index 38a5834b55..676309a256 100644 --- a/pages/accountLists/[accountListId]/reports/housingAllowance/index.page.tsx +++ b/pages/accountLists/[accountListId]/reports/housingAllowance/index.page.tsx @@ -4,8 +4,12 @@ import { useTranslation } from 'react-i18next'; import { blockImpersonatingNonDevelopers } from 'pages/api/utils/pagePropsHelpers'; import { SidePanelsLayout } from 'src/components/Layouts/SidePanelsLayout'; import Loading from 'src/components/Loading'; +import { DynamicExpensesClaim } from 'src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/DynamicExpensesClaim'; import { MinisterHousingAllowanceReport } from 'src/components/Reports/MinisterHousingAllowance/MinisterHousingAllowance'; -import { MinisterHousingAllowanceProvider } from 'src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext'; +import { + MinisterHousingAllowanceProvider, + useMinisterHousingAllowance, +} from 'src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext'; import { NoStaffAccount } from 'src/components/Reports/Shared/NoStaffAccount/NoStaffAccount'; import { useStaffAccountQuery } from 'src/components/Reports/StaffAccount.generated'; import { @@ -20,6 +24,49 @@ import { import { ReportPageWrapper } from 'src/components/Shared/styledComponents/ReportPageWrapper'; import useGetAppSettings from 'src/hooks/useGetAppSettings'; +interface MinisterHousingAllowanceContentProps { + isNavListOpen: boolean; + onNavListToggle: () => void; +} + +const MinisterHousingAllowanceContent: React.FC< + MinisterHousingAllowanceContentProps +> = ({ isNavListOpen, onNavListToggle }) => { + const { t } = useTranslation(); + const { isRightPanelOpen } = useMinisterHousingAllowance(); + + return ( + + } + leftOpen={isNavListOpen} + leftWidth="290px" + headerHeight={multiPageHeaderHeight} + mainContent={ + <> + + + + } + rightPanel={isRightPanelOpen ? : undefined} + rightOpen={isRightPanelOpen} + rightWidth="35%" + /> + ); +}; + const MinisterHousingAllowancePage: React.FC = () => { const { t } = useTranslation(); const { appName } = useGetAppSettings(); @@ -38,33 +85,12 @@ const MinisterHousingAllowancePage: React.FC = () => { {staffAccountData?.staffAccount?.id ? ( - - } - leftOpen={isNavListOpen} - leftWidth="290px" - headerHeight={multiPageHeaderHeight} - mainContent={ - <> - - - - - - } - /> + + + ) : loading ? ( diff --git a/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/DynamicExpensesClaim.tsx b/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/DynamicExpensesClaim.tsx new file mode 100644 index 0000000000..5743aef4e1 --- /dev/null +++ b/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/DynamicExpensesClaim.tsx @@ -0,0 +1,11 @@ +import dynamic from 'next/dynamic'; +import { DynamicComponentPlaceholder } from 'src/components/DynamicPlaceholders/DynamicComponentPlaceholder'; + +export const preloadExpensesClaim = () => + import(/* webpackChunkName: "ExpensesClaim" */ './ExpensesClaim').then( + ({ ExpensesClaim }) => ExpensesClaim, + ); + +export const DynamicExpensesClaim = dynamic(preloadExpensesClaim, { + loading: DynamicComponentPlaceholder, +}); diff --git a/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/ExpensesClaim.test.tsx b/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/ExpensesClaim.test.tsx new file mode 100644 index 0000000000..4f720108e0 --- /dev/null +++ b/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/ExpensesClaim.test.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { ThemeProvider } from '@mui/material/styles'; +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { GqlMockedProvider } from '__tests__/util/graphqlMocking'; +import theme from 'src/theme'; +import { + ContextType, + MinisterHousingAllowanceContext, +} from '../Shared/Context/MinisterHousingAllowanceContext'; +import { ExpensesClaim } from './ExpensesClaim'; + +const setIsRightPanelOpen = jest.fn(); + +interface TestComponentProps { + contextValue?: Partial; +} + +const TestComponent: React.FC = ({ contextValue }) => ( + + + + + + + +); + +describe('ExpensesClaim', () => { + it('renders component', () => { + const { getByText, getByTestId } = render( + , + ); + + expect( + getByText('What expenses can I claim on my MHA?'), + ).toBeInTheDocument(); + expect(getByTestId('CloseIcon')).toBeInTheDocument(); + expect(getByText('Allowable Expenses for MHA')).toBeInTheDocument(); + }); + + it('closes the panel when close icon is clicked', async () => { + const { getByTestId } = render( + , + ); + + const closeIcon = getByTestId('CloseIcon'); + userEvent.click(closeIcon); + + expect(setIsRightPanelOpen).toHaveBeenCalledWith(false); + }); +}); diff --git a/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/ExpensesClaim.tsx b/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/ExpensesClaim.tsx new file mode 100644 index 0000000000..1848b57eda --- /dev/null +++ b/src/components/Reports/MinisterHousingAllowance/DynamicExpensesClaim/ExpensesClaim.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Close, RequestPageSharp } from '@mui/icons-material'; +import { Box, Container, IconButton, Typography } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import theme from 'src/theme'; +import { useMinisterHousingAllowance } from '../Shared/Context/MinisterHousingAllowanceContext'; + +export const ExpensesClaim: React.FC = () => { + const { t } = useTranslation(); + const { setIsRightPanelOpen } = useMinisterHousingAllowance(); + + return ( + + + + {t('What expenses can I claim on my MHA?')} + + setIsRightPanelOpen(false)}> + + + + + + + + + {t('Allowable Expenses for MHA')} + + + + + ); +}; diff --git a/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.tsx b/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.tsx index 8fd2142579..7850ba7c92 100644 --- a/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.tsx +++ b/src/components/Reports/MinisterHousingAllowance/Shared/Context/MinisterHousingAllowanceContext.tsx @@ -50,6 +50,8 @@ export type ContextType = { spouseHcmData?: HcmData | null; preferredName: string; spousePreferredName: string; + isRightPanelOpen: boolean; + setIsRightPanelOpen: Dispatch>; requestData?: | MinistryHousingAllowanceRequestQuery['ministryHousingAllowanceRequest'] @@ -112,6 +114,7 @@ export const MinisterHousingAllowanceProvider: React.FC = ({ } = useStepList(FormEnum.MHA, type); const [isComplete, setIsComplete] = useState(false); + const [isRightPanelOpen, setIsRightPanelOpen] = useState(false); const steps = useMemo(() => { if (!isComplete) { @@ -205,6 +208,8 @@ export const MinisterHousingAllowanceProvider: React.FC = ({ isPrint, setIsPrint, setIsComplete, + isRightPanelOpen, + setIsRightPanelOpen, requestData: requestData?.ministryHousingAllowanceRequest ?? null, requestError, requestId, @@ -231,6 +236,8 @@ export const MinisterHousingAllowanceProvider: React.FC = ({ isPrint, setIsPrint, setIsComplete, + isRightPanelOpen, + setIsRightPanelOpen, requestData, requestError, requestId, diff --git a/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.test.tsx b/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.test.tsx index d6071b7596..649205dbb0 100644 --- a/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.test.tsx +++ b/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.test.tsx @@ -1,30 +1,41 @@ import React from 'react'; import { ThemeProvider } from '@mui/material/styles'; import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { Formik } from 'formik'; import TestRouter from '__tests__/util/TestRouter'; import { GqlMockedProvider } from '__tests__/util/graphqlMocking'; import { PageEnum } from 'src/components/Reports/Shared/CalculationReports/Shared/sharedTypes'; import theme from 'src/theme'; -import { MinisterHousingAllowanceProvider } from '../../Shared/Context/MinisterHousingAllowanceContext'; +import { + ContextType, + MinisterHousingAllowanceContext, +} from '../../Shared/Context/MinisterHousingAllowanceContext'; import { AboutForm } from './AboutForm'; const submit = jest.fn(); +const setIsRightPanelOpen = jest.fn(); const boardApprovedAt = '2024-09-15'; const availabilityDate = '2024-10-01'; -const TestComponent: React.FC = () => ( +interface TestComponentProps { + contextValue?: Partial; +} + +const TestComponent: React.FC = ({ contextValue }) => ( - + - + @@ -32,7 +43,9 @@ const TestComponent: React.FC = () => ( describe('AboutForm', () => { it('renders form and formatted dates', () => { - const { getByText, getByRole } = render(); + const { getByText, getByRole } = render( + , + ); expect( getByRole('heading', { name: 'About this Form' }), @@ -47,4 +60,20 @@ describe('AboutForm', () => { expect(getByRole('button', { name: 'Continue' })).toBeInTheDocument(); }); + + it('should open right panel when link is clicked', async () => { + const { findByText } = render( + , + ); + + const link = await findByText(/what expenses can i claim on my mha/i); + userEvent.click(link); + + expect(setIsRightPanelOpen).toHaveBeenCalledWith(true); + }); }); diff --git a/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.tsx b/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.tsx index 947b5d711f..0c8be71ad4 100644 --- a/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.tsx +++ b/src/components/Reports/MinisterHousingAllowance/Steps/StepOne/AboutForm.tsx @@ -20,10 +20,11 @@ export const AboutForm: React.FC = ({ const { t } = useTranslation(); const locale = useLocale(); - const { handleNextStep, handlePreviousStep } = useMinisterHousingAllowance(); + const { handleNextStep, handlePreviousStep, setIsRightPanelOpen } = + useMinisterHousingAllowance(); // TODO: "newRequestAboutForm" value needs to be added to translation files to see all values - // TODO: Get correct link for "Salary Calculation Form" and "What expenses can I claim on my MHA?" + // TODO: Get correct link for "Salary Calculation Form" const nextYear = DateTime.now().year + 1; @@ -101,7 +102,11 @@ export const AboutForm: React.FC = ({ fontSize="medium" sx={{ verticalAlign: 'middle', opacity: 0.56 }} />{' '} - + setIsRightPanelOpen(true)} + > What expenses can I claim on my MHA? diff --git a/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.test.tsx b/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.test.tsx index 6a26d376e9..7c3e479caf 100644 --- a/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.test.tsx +++ b/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.test.tsx @@ -22,6 +22,7 @@ const mutationSpy = jest.fn(); const setHasCalcValues = jest.fn(); const setIsPrint = jest.fn(); const updateMutation = jest.fn(); +const setIsRightPanelOpen = jest.fn(); interface TestComponentProps { contextValue: Partial; @@ -351,6 +352,26 @@ describe('Calculation', () => { ); }); + it('should open right panel when link is clicked', async () => { + const { findByText } = render( + , + ); + + const link = await findByText(/what expenses can i claim on my mha/i); + userEvent.click(link); + + expect(setIsRightPanelOpen).toHaveBeenCalledWith(true); + }); + describe('isViewPage behavior', () => { it('renders view only mode', () => { const { getByRole, queryByRole, getByText } = render( diff --git a/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.tsx b/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.tsx index b5128f56d2..8c1f6518b3 100644 --- a/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.tsx +++ b/src/components/Reports/MinisterHousingAllowance/Steps/StepThree/Calculation.tsx @@ -113,6 +113,7 @@ export const Calculation: React.FC = ({ requestData, updateMutation, userHcmData, + setIsRightPanelOpen, } = useMinisterHousingAllowance(); const updateCheckbox = (value: boolean) => @@ -281,7 +282,13 @@ export const Calculation: React.FC = ({ fontSize="medium" sx={{ verticalAlign: 'middle', opacity: 0.56 }} />{' '} - + { + setIsRightPanelOpen(true); + }} + > What expenses can I claim on my MHA?