diff --git a/README.md b/README.md
index c7dcebddae..afe5e506f7 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@ Note: there is a test account you can use. Get this from another developer if yo
- `HS_HOME_SUGGESTIONS` - Comma-separated IDs of the HelpScout articles to suggest on the dashboard page
- `HS_REPORTS_SUGGESTIONS` - Comma-separated IDs of the HelpScout articles to suggest on the reports pages
- `HS_TASKS_SUGGESTIONS` - Comma-separated IDs of the HelpScout articles to suggest on the tasks page
+- `SHOW_BANNER` - Display a hard-coded banner on the Dashboard. Set to `true` or `false`
#### Auth provider
diff --git a/next.config.js b/next.config.js
index 21556856c3..e1c12d7156 100644
--- a/next.config.js
+++ b/next.config.js
@@ -95,6 +95,7 @@ module.exports = withPlugins([
HS_REPORTS_SUGGESTIONS: process.env.HS_REPORTS_SUGGESTIONS,
HS_TASKS_SUGGESTIONS: process.env.HS_TASKS_SUGGESTIONS,
ALERT_MESSAGE: process.env.ALERT_MESSAGE,
+ SHOW_BANNER: process.env.SHOW_BANNER,
},
experimental: {
modularizeImports: {
diff --git a/pages/accountLists/[accountListId].page.tsx b/pages/accountLists/[accountListId].page.tsx
index 0ac9535dd8..7d5a2c53c9 100644
--- a/pages/accountLists/[accountListId].page.tsx
+++ b/pages/accountLists/[accountListId].page.tsx
@@ -29,6 +29,7 @@ const AccountListIdPage = ({
const { openTaskModal } = useTaskModal();
const [selectedMenuItem, setSelectedMenuItem] = useState(-1);
const [dialogOpen, setDialogOpen] = useState(false);
+ const shouldShowBanner = process.env.SHOW_BANNER === 'true';
useEffect(() => {
suggestArticles('HS_HOME_SUGGESTIONS');
@@ -65,7 +66,11 @@ const AccountListIdPage = ({
{appName} | {data.accountList.name}
-
+
{modal && renderDialog(selectedMenuItem, dialogOpen, setDialogOpen)}
>
diff --git a/src/components/Dashboard/Dashboard.test.tsx b/src/components/Dashboard/Dashboard.test.tsx
index ad2e7f804d..85a0651ecb 100644
--- a/src/components/Dashboard/Dashboard.test.tsx
+++ b/src/components/Dashboard/Dashboard.test.tsx
@@ -216,3 +216,49 @@ describe('Dashboard', () => {
).toEqual('Committed $700');
});
});
+
+describe('Static Banner', () => {
+ beforeEach(() => {
+ beforeTestResizeObserver();
+ });
+
+ afterAll(() => {
+ afterTestResizeObserver();
+ });
+
+ it('should show the banner if the shouldShowBanner prop is true', () => {
+ const shouldShowBanner = true;
+
+ const { getByTestId } = render(
+
+
+
+
+ ,
+ );
+
+ expect(getByTestId('staticBanner')).toBeInTheDocument();
+ });
+
+ it('should NOT show the banner if the shouldShowBanner prop is false', () => {
+ const shouldShowBanner = false;
+
+ const { queryByTestId } = render(
+
+
+
+
+ ,
+ );
+
+ expect(queryByTestId('staticBanner')).not.toBeInTheDocument();
+ });
+});
diff --git a/src/components/Dashboard/Dashboard.tsx b/src/components/Dashboard/Dashboard.tsx
index b33fa9d43e..47fe509944 100644
--- a/src/components/Dashboard/Dashboard.tsx
+++ b/src/components/Dashboard/Dashboard.tsx
@@ -7,10 +7,12 @@ import MonthlyGoal from './MonthlyGoal/MonthlyGoal';
import Balance from './Balance';
import DonationHistories from './DonationHistories';
import ThisWeek from './ThisWeek';
+import { StaticBanner } from '../Shared/staticBanner/StaticBanner';
interface Props {
data: GetDashboardQuery;
accountListId: string;
+ shouldShowBanner?: boolean;
}
const variants = {
@@ -27,7 +29,11 @@ const variants = {
},
};
-const Dashboard = ({ data, accountListId }: Props): ReactElement => {
+const Dashboard = ({
+ data,
+ accountListId,
+ shouldShowBanner = false,
+}: Props): ReactElement => {
return (
<>
@@ -39,6 +45,7 @@ const Dashboard = ({ data, accountListId }: Props): ReactElement => {
exit="exit"
variants={variants}
>
+ {shouldShowBanner && }
{
+ const { queryByTestId } = render(
+
+ mocks={{
+ mockResponseNonCru,
+ }}
+ >
+
+ ,
+ );
+
+ await waitFor(() =>
+ expect(queryByTestId('nonCruOrgReminder')).toBeInTheDocument(),
+ );
+});
+
+test('static banner does not display for user in a Cru org', async () => {
+ const { queryByTestId } = render(
+
+ mocks={{
+ mockResponseCru,
+ }}
+ >
+
+ ,
+ );
+
+ await waitFor(() =>
+ expect(queryByTestId('nonCruOrgReminder')).not.toBeInTheDocument(),
+ );
+});
diff --git a/src/components/Shared/staticBanner/StaticBanner.tsx b/src/components/Shared/staticBanner/StaticBanner.tsx
new file mode 100644
index 0000000000..c5e21a4400
--- /dev/null
+++ b/src/components/Shared/staticBanner/StaticBanner.tsx
@@ -0,0 +1,53 @@
+import React, { useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import Alert from '@mui/material/Alert';
+import { Link } from '@mui/material';
+import { useGetUsersOrganizationsQuery } from './getOrganizationType.generated';
+
+interface StaticBannerProps {
+ severity?: 'error' | 'info' | 'success' | 'warning';
+}
+
+export const StaticBanner: React.FC = ({
+ severity = 'warning',
+}) => {
+ const { t } = useTranslation();
+
+ const { data, loading } = useGetUsersOrganizationsQuery();
+ const nonCruUser = useMemo(() => {
+ const foundCruOrg = data?.userOrganizationAccounts.some(
+ (org) =>
+ org.organization.organizationType === 'Cru-International' ||
+ org.organization.organizationType === 'Cru',
+ );
+ return !foundCruOrg;
+ }, [data]);
+
+ return (
+
+ {!loading && nonCruUser ? (
+
+ {t(
+ `Due to data privacy regulations and costs, Cru will no longer be able to host MPDX data for non-Cru/non-CCCI ministries. `,
+ )}
+
+ {t(
+ `Your data in MPDX will be deleted if you don’t export from MPDX by January 31, 2024,`,
+ )}
+
+ {t(
+ ` or let us know why you might need an extension. For more information and to take action, read `,
+ )}
+
+ {t('this communication.')}
+
+
+ ) : null}
+