diff --git a/packages/esm-covid-app/src/ReportFilters.tsx b/packages/esm-covid-app/src/ReportFilters.tsx
new file mode 100644
index 000000000..e275e66c4
--- /dev/null
+++ b/packages/esm-covid-app/src/ReportFilters.tsx
@@ -0,0 +1,77 @@
+import React from 'react';
+import { Dropdown, Button, Accordion, AccordionItem, DatePicker, DatePickerInput } from '@carbon/react';
+import styles from './home.component.scss';
+import { ComboBox } from '@carbon/react';
+
+const ReportFilters = ({
+ config,
+ reportId,
+ setReportId,
+ ptrackerId,
+ setPtrackerId,
+ personUuid,
+ setPersonUuid,
+ startDate,
+ setStartDate,
+ endDate,
+ setEndDate,
+ handleSubmit,
+ showFilters,
+ handleFiltersToggle,
+}) => {
+ const handleDateChange = (setter) => (event) => {
+ const date = event[0] ? event[0].toISOString().split('T')[0] : '';
+ setter(date);
+ };
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default ReportFilters;
diff --git a/packages/esm-covid-app/src/config-schema.ts b/packages/esm-covid-app/src/config-schema.ts
index 17535f111..9cba61635 100644
--- a/packages/esm-covid-app/src/config-schema.ts
+++ b/packages/esm-covid-app/src/config-schema.ts
@@ -89,9 +89,8 @@ export const configSchema = {
CovidAssessmentFormName: 'COVID Assessment Form',
CovidOutcomeFormName: 'COVID Outcome Form',
CovidVaccinationFormName: 'COVID Vaccination Form',
- CovidLabTestFormName: 'COVID Lab Test',
- CovidLabResultFormName: 'COVID Lab Result Form',
- CovidLabCancellationFormName: 'Lab Order Cancellation',
+ CovidLabTestFormName: 'COVID Lab Test Form',
+ CCovidLabCancellationFormName: 'Lab Order Cancellation',
CovidSampleCollectionFormName: 'Sample Collection',
CovidLabOrderFormName: 'COVID Lab Order Form',
},
@@ -110,12 +109,19 @@ export const configSchema = {
covidSampleCollectionFormUuid: '371d19b6-485f-11ec-99cc-1fdd2d4e9d88',
},
},
+ reports: {
+ _type: Type.Array,
+ _description: 'Reports and their associated UUIDs.',
+ _default: [
+ { name: 'Covid-19 Report', uuid: 'ecabd559-14f6-4c65-87af-1254dfdf1304' },
+ { name: 'HTS Report', uuid: '3ffa5a53-fc65-4a1e-a434-46dbcf1c2de2' },
+ { name: 'ADX-HIV Report', uuid: '2f236b1-b0b5-4ecc-9037-681c23fb45bd' },
+ {
+ name: 'Mother HIV Status Report',
+ ptrackerId: '12345A232567',
+ personUuid: 'bd49d697-b1de-49b9-95c2-6031fb1375fd',
+ reportId: 'mother_hiv_status',
+ },
+ ],
+ },
};
-
-export interface ConfigObject {
- encounterTypes: Object;
- obsConcepts: Object;
- formNames: object;
- cohorts: object;
- formUuids: Object;
-}
diff --git a/packages/esm-covid-app/src/dashboard.meta.ts b/packages/esm-covid-app/src/dashboard.meta.ts
index d88764052..0c2ccf043 100644
--- a/packages/esm-covid-app/src/dashboard.meta.ts
+++ b/packages/esm-covid-app/src/dashboard.meta.ts
@@ -1,4 +1,4 @@
-import { Coronavirus } from '@carbon/react/icons';
+import { Coronavirus, VisualRecognition } from '@carbon/react/icons';
// Patient Chart Dashboards
export const covidPatientChartMeta = {
@@ -39,6 +39,17 @@ export const covidClinicalViewDashboardMeta = {
title: 'COVID',
};
+export const covidCasesDashboardMeta = {
+ name: 'covid-dashboard',
+ icon: VisualRecognition,
+ slot: 'covid-dashboard-slot',
+ title: 'Covid Test',
+ isFolder: true,
+ folderTitle: 'Covid Test',
+ folderIcon: VisualRecognition,
+ isHidde: true,
+};
+
export const covid19CasesDashboardMeta = {
name: 'covid-cases',
slot: 'covid-cases-dashboard-slot',
@@ -47,3 +58,13 @@ export const covid19CasesDashboardMeta = {
folderTitle: 'COVID',
folderIcon: Coronavirus,
};
+
+export const reportingDemoDashboardMeta = {
+ name: 'covid-report',
+ icon: VisualRecognition,
+ slot: 'covid-reporting-dashboard-slot',
+ title: 'Reporting Demo',
+ isFolder: true,
+ folderTitle: 'Reporting Demo',
+ folderIcon: VisualRecognition,
+};
diff --git a/packages/esm-covid-app/src/home.component.scss b/packages/esm-covid-app/src/home.component.scss
new file mode 100644
index 000000000..d7f92af12
--- /dev/null
+++ b/packages/esm-covid-app/src/home.component.scss
@@ -0,0 +1,133 @@
+.container {
+ padding: 2rem;
+}
+.homeContainer {
+ padding: 1rem;
+}
+.dropdownItem {
+ display: flex;
+ align-items: center;
+}
+.layer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 300px;
+}
+
+.tile {
+ padding: 2rem;
+ text-align: center;
+}
+
+.content {
+ font-size: 1.25rem;
+ color: #5a5a5a;
+}
+
+.explainer {
+ color: #777;
+}
+
+.form {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+.formContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.datePickerContainer {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+}
+
+.fetchButtonContainer {
+ margin-left: 16px;
+ display: flex;
+ align-items: center;
+}
+
+.datePickerContainer > * {
+ flex: 1;
+}
+
+.datePickerInput {
+ min-width: 120px;
+}
+
+.button {
+ max-height: 40px;
+ line-height: 40px;
+ font-size: 14px;
+ padding: 0 16px;
+ margin-top: 1rem;
+ max-width: 120px;
+ align-items: center;
+}
+
+
+.datePickerContainer {
+ display: flex;
+ gap: 1rem;
+}
+
+.fetchButtonContainer {
+ display: flex;
+ justify-content: flex-end;
+}
+
+.dataTableContainer {
+ margin-top: 2rem;
+ padding: 1rem;
+ border: solid 1px #e0e0e0;
+ height: 100vh;
+}
+
+.dataTableFullContainer {
+ margin-top: 2rem;
+ padding: 1rem;
+ height: 100vh;
+}
+
+.tableContainer {
+ margin-top: 1rem;
+}
+
+.toolbarWrapper {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.toolbarContent {
+ display: flex;
+ gap: 1rem;
+}
+
+.searchbox {
+ flex-grow: 1;
+}
+
+.tileContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 200px;
+}
+
+.tileContent {
+ text-align: center;
+}
+
+.content {
+ font-size: 1.25rem;
+ color: #5a5a5a;
+}
+
+.pagination {
+ margin-top: 1rem;
+}
\ No newline at end of file
diff --git a/packages/esm-covid-app/src/home.component.tsx b/packages/esm-covid-app/src/home.component.tsx
index c3748ced2..c92d0e469 100644
--- a/packages/esm-covid-app/src/home.component.tsx
+++ b/packages/esm-covid-app/src/home.component.tsx
@@ -3,7 +3,7 @@ import { OHRIWelcomeSection } from '@ohri/openmrs-esm-ohri-commons-lib';
import CovidHomePatientTabs from './covid/dashboard/patient-list-tabs/covid-patient-list-tabs.component';
import CovidSummaryTiles from './covid/dashboard/summary-tiles/covid-summary-tiles.component';
-const Homecomponent = () => {
+const Home = () => {
return (
@@ -13,4 +13,4 @@ const Homecomponent = () => {
);
};
-export default Homecomponent;
+export default Home;
diff --git a/packages/esm-covid-app/src/index.ts b/packages/esm-covid-app/src/index.ts
index 93f65014f..79f2d1a80 100644
--- a/packages/esm-covid-app/src/index.ts
+++ b/packages/esm-covid-app/src/index.ts
@@ -9,11 +9,13 @@ import {
covidClinicalViewDashboardMeta,
covid19CasesDashboardMeta,
covidPatientChartMeta,
+ reportingDemoDashboardMeta,
} from './dashboard.meta';
import { createOHRIDashboardLink, createOHRIGroupedLink } from '@ohri/openmrs-esm-ohri-commons-lib';
import { createDashboardGroup, createDashboardLink } from '@openmrs/esm-patient-common-lib';
import { configSchema } from './config-schema';
-import rootComponent from './root.component';
+import Root from './root.component';
+import ReportRoot from './report-root';
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
@@ -69,4 +71,7 @@ export const covidClinicalViewDashboardLink = getSyncLifecycle(
options,
);
export const covidCasesDashboardLink = getSyncLifecycle(createOHRIGroupedLink(covid19CasesDashboardMeta), options);
-export const covidCasesDashboard = getSyncLifecycle(rootComponent, options);
+export const covidCasesDashboard = getSyncLifecycle(Root, options);
+
+export const reportingDemoDashboardLink = getSyncLifecycle(createOHRIGroupedLink(reportingDemoDashboardMeta), options);
+export const reportingDemoDashboard = getSyncLifecycle(ReportRoot, options);
diff --git a/packages/esm-covid-app/src/report-home.tsx b/packages/esm-covid-app/src/report-home.tsx
new file mode 100644
index 000000000..c1ebd13ce
--- /dev/null
+++ b/packages/esm-covid-app/src/report-home.tsx
@@ -0,0 +1,155 @@
+import React, { useState, useMemo } from 'react';
+import useSWR from 'swr';
+import {
+ DataTable,
+ Table,
+ TableHead,
+ TableRow,
+ TableHeader,
+ TableBody,
+ TableCell,
+ Layer,
+ Tile,
+ DataTableSkeleton,
+} from '@carbon/react';
+import { OHRIWelcomeSection } from '@ohri/openmrs-esm-ohri-commons-lib';
+import { openmrsFetch, useConfig, restBaseUrl } from '@openmrs/esm-framework';
+import styles from './home.component.scss';
+import capitalize from 'lodash/capitalize';
+import { EmptyDataIllustration } from '@openmrs/esm-patient-common-lib';
+import ReportFilters from './ReportFilters';
+import { useTranslation } from 'react-i18next';
+
+const snakeCaseToCapitalizedWords = (snakeCaseString) =>
+ snakeCaseString
+ .split('_')
+ .map((word) => capitalize(word))
+ .join(' ');
+
+const fetcher = (url) => openmrsFetch(url).then((res) => res.json());
+
+const ReportComponent = () => {
+ const config = useConfig();
+ const { t } = useTranslation();
+ const [reportId, setReportId] = useState('mother_hiv_status');
+ const [ptrackerId, setPtrackerId] = useState('');
+ const [personUuid, setPersonUuid] = useState('');
+ const [startDate, setStartDate] = useState('');
+ const [endDate, setEndDate] = useState('');
+ const [showFilters, setShowFilters] = useState(false);
+ const [reportRequested, setReportRequested] = useState(false);
+
+ const url = useMemo(() => {
+ if (!startDate || !endDate) return null;
+ return `${restBaseUrl}/mamba/report?report_id=${reportId}&ptracker_id=${ptrackerId}&person_uuid=${personUuid}&start_date=${startDate}&end_date=${endDate}`;
+ }, [reportId, ptrackerId, personUuid, startDate, endDate]);
+
+ const { data, error, mutate } = useSWR(url, fetcher, { revalidateOnFocus: false });
+
+ const headers = useMemo(() => {
+ if (!data || !data.results.length) return [];
+ return data.results[0].record.map((column) => ({
+ key: column.column,
+ header: snakeCaseToCapitalizedWords(column.column),
+ }));
+ }, [data]);
+
+ const rows = useMemo(() => {
+ if (!data || !data.results.length) return [];
+ return data.results.map((result) => ({
+ id: result.serialId.toString(),
+ ...result.record.reduce(
+ (acc, column) => ({
+ ...acc,
+ [column.column]: column.value === null ? '-' : column.value,
+ }),
+ {},
+ ),
+ }));
+ }, [data]);
+
+ const loading = !data && !error && reportRequested;
+
+ const handleFiltersToggle = () => setShowFilters(!showFilters);
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ setReportRequested(true);
+ mutate();
+ };
+
+ return (
+
+
+
+ {loading ? (
+
+ ) : error ? (
+
+
+
+ {t('errorLadigData', 'Error loading data')}
+ {t('pleaseTryAgain', 'Please try again later')}
+
+
+
+ ) : rows.length === 0 || !reportRequested ? (
+
+
+
+
+ {t('noDataToDisplay', 'No data to display')}
+
+ {t('useReportsAboveToBuild', 'Use the report filters above to build your reports')}
+
+
+
+
+ ) : (
+
+
+ {({ rows, headers, getTableProps, getHeaderProps, getRowProps }) => (
+
+
+
+ {headers.map((header) => (
+
+ {header.header}
+
+ ))}
+
+
+
+ {rows.map((row) => (
+
+ {headers.map((header) => (
+ {row[header.key] || '-'}
+ ))}
+
+ ))}
+
+
+ )}
+
+
+ )}
+
+ );
+};
+
+export default ReportComponent;
diff --git a/packages/esm-covid-app/src/report-root.tsx b/packages/esm-covid-app/src/report-root.tsx
new file mode 100644
index 000000000..f9ef72a7f
--- /dev/null
+++ b/packages/esm-covid-app/src/report-root.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import { SWRConfig } from 'swr';
+import { BrowserRouter, Route, Routes } from 'react-router-dom';
+import ReportComponent from './report-home';
+
+const swrConfiguration = {
+ // Maximum number of retries when the backend returns an error
+ errorRetryCount: 3,
+};
+
+const ReportRoot: React.FC = () => {
+ const reportingBasename = window.getOpenmrsSpaBase() + 'home/covid-report';
+
+ return (
+
+
+
+
+ } />
+
+
+
+
+ );
+};
+
+export default ReportRoot;
diff --git a/packages/esm-covid-app/src/routes.json b/packages/esm-covid-app/src/routes.json
index f7a8a6f3f..b0cb6ed6b 100644
--- a/packages/esm-covid-app/src/routes.json
+++ b/packages/esm-covid-app/src/routes.json
@@ -21,6 +21,26 @@
"slot": "patient-chart-dashboard-slot",
"component": "covidPatientChartDashboard"
},
+
+
+ {
+ "name": "covid-dashboard",
+ "slot": "covid-dashboard",
+ "component": "covidCasesDashboardLink",
+ "meta": {
+
+ "name": "covid-dashboard",
+ "slot": "covid-dashboard-slot",
+ "cofig": {
+ "title": "Covid Dashboard",
+ "columns": 1,
+ "layoutMode": "anchored"
+ },
+ "title": "Covid Dashboard"
+ }
+ },
+
+
{
"name": "covid-assessments-dashboard",
"slot": "ohri-covid-patient-chart-slot",
@@ -76,7 +96,7 @@
"meta": {
"name": "covid-cases",
"slot": "covid-cases-dashboard-slot",
- "title": "TB Treatment"
+ "title": "Covid Cases"
},
"order": 5
},
@@ -84,6 +104,23 @@
"name": "covid-cases-dashboard",
"slot": "covid-cases-dashboard-slot",
"component": "covidCasesDashboard"
+ },
+ {
+ "name": "covid-report-dashboard-ext",
+ "slot": "homepage-dashboard-slot",
+ "component": "reportingDemoDashboardLink",
+ "meta": {
+ "name": "covid-report",
+ "slot": "covid-reporting-dashboard-slot",
+ "title": "Covid Report"
+ },
+ "order": 5
+ },
+ {
+ "name": "covid-reporting-demo-dashboard",
+ "slot": "covid-reporting-dashboard-slot",
+ "component": "reportingDemoDashboard"
}
+
]
}