From 1045d03b369ac88b4eda330380f89d33e1eacc90 Mon Sep 17 00:00:00 2001 From: TrevorAntony <61781670+TrevorAntony@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:50:11 +0300 Subject: [PATCH] Reporting Demo Changes (#1912) --- .../components/reports/home.component.scss | 143 ++++++++++++++++ .../src/components/reports/reportfilters.tsx | 75 +++++++++ .../reports/reports-home.component.tsx | 153 +++++++++++++++++- .../reports/reports-root.component.tsx | 4 +- packages/esm-commons-lib/src/config-schema.ts | 16 ++ 5 files changed, 382 insertions(+), 9 deletions(-) create mode 100644 packages/esm-commons-lib/src/components/reports/home.component.scss create mode 100644 packages/esm-commons-lib/src/components/reports/reportfilters.tsx diff --git a/packages/esm-commons-lib/src/components/reports/home.component.scss b/packages/esm-commons-lib/src/components/reports/home.component.scss new file mode 100644 index 000000000..5f252fe23 --- /dev/null +++ b/packages/esm-commons-lib/src/components/reports/home.component.scss @@ -0,0 +1,143 @@ +.centeredTextContainer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 50px; + text-align: center; + } + + .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: 8px; + justify-content: space-between; + flex-wrap: wrap; + } + + .datePickerContainer > * { + flex: 1; + min-width: 150px; + } + + .fetchButtonContainer { + margin-left: 16px; + display: flex; + align-items: center; + } + + .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; + } + + .dataTableContainer { + margin-top: 2rem; + padding: 1rem; + border: solid 1px #e0e0e0; + max-height: calc(100vh - 200px); + overflow: auto; + height: 100vh; + } + + .dataTableFullContainer { + margin-top: 2rem; + padding: 1rem; + max-height: calc(100vh - 200px); + overflow: auto; + } + + + .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-commons-lib/src/components/reports/reportfilters.tsx b/packages/esm-commons-lib/src/components/reports/reportfilters.tsx new file mode 100644 index 000000000..8af4a8eb3 --- /dev/null +++ b/packages/esm-commons-lib/src/components/reports/reportfilters.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { ComboBox, Button, DatePicker, DatePickerInput } from '@carbon/react'; +import styles from './home.component.scss'; + +const ReportFilters = ({ + config, + uuid, + reportId, + setReportId, + ptrackerId, + setPtrackerId, + personUuid, + setPersonUuid, + startDate, + setStartDate, + endDate, + setEndDate, + handleSubmit, + setReportRequested, +}) => { + const handleDateChange = (setter) => (event) => { + const date = event[0] ? event[0].toISOString().split('T')[0] : ''; + setter(date); + }; + + return ( + <> +
+

Report Filters

+
+
+
+ (item ? item.name : '')} + onChange={({ selectedItem }) => { + if (selectedItem) { + setReportId(selectedItem.uuid || ''); + } else { + setReportId(''); + setPtrackerId(''); + setPersonUuid(''); + setStartDate(''); + setEndDate(''); + setReportRequested(false); + } + }} + /> + + + + + + + +
+
+ + ); +}; + +export default ReportFilters; diff --git a/packages/esm-commons-lib/src/components/reports/reports-home.component.tsx b/packages/esm-commons-lib/src/components/reports/reports-home.component.tsx index bad9ba041..9ddc878b1 100644 --- a/packages/esm-commons-lib/src/components/reports/reports-home.component.tsx +++ b/packages/esm-commons-lib/src/components/reports/reports-home.component.tsx @@ -1,14 +1,153 @@ -import React from 'react'; +import React, { useState, useMemo, useEffect } 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 { Reports } from './reports'; +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(''); + const [uuid, setUuid] = useState(''); + const [ptrackerId, setPtrackerId] = useState(''); + const [personUuid, setPersonUuid] = useState(''); + const [startDate, setStartDate] = useState(''); + const [endDate, setEndDate] = useState(''); + const [reportRequested, setReportRequested] = useState(false); + + const url = useMemo(() => { + if (!startDate || !endDate || !reportId) return null; + return `${restBaseUrl}/reportingrest/reportdata/${reportId}?startDate=${startDate}&endDate=${endDate}`; + }, [reportId, startDate, endDate]); + + const { data, error, mutate } = useSWR(url, fetcher, { revalidateOnFocus: false }); + + useEffect(() => { + if (error) { + console.error('Error fetching report data:', error); + } + }, [error]); + + const headers = useMemo(() => { + if (!data || !data.dataSets || !data.dataSets.length || !data.dataSets[0].metadata) return []; + return data.dataSets[0].metadata.columns.map((column) => ({ + key: column.name, + header: column.label, + })); + }, [data]); + + const rows = useMemo(() => { + if (!data || !data.dataSets || !data.dataSets.length || !data.dataSets[0].rows) return []; + return data.dataSets[0].rows.map((result, idx) => ({ + id: idx.toString(), + ...result, + })); + }, [data]); + + const loading = !data && !error && reportRequested; + + const handleSubmit = (e) => { + e.preventDefault(); + setReportRequested(true); + mutate(); + }; -const ReportsHomecomponent = () => { return ( -
- - +
+ + + {loading ? ( + + ) : error ? ( +
+ + +

{t('errorLoadingData', '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 ReportsHomecomponent; +export default ReportComponent; diff --git a/packages/esm-commons-lib/src/components/reports/reports-root.component.tsx b/packages/esm-commons-lib/src/components/reports/reports-root.component.tsx index 19d31230b..01e8545fb 100644 --- a/packages/esm-commons-lib/src/components/reports/reports-root.component.tsx +++ b/packages/esm-commons-lib/src/components/reports/reports-root.component.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { SWRConfig } from 'swr'; import { BrowserRouter, Route, Routes } from 'react-router-dom'; -import ReportsHome from './reports-home.component'; +import ReportComponent from './reports-home.component'; const swrConfiguration = { errorRetryCount: 3, @@ -15,7 +15,7 @@ const RootComponent: React.FC = () => { - } /> + } /> diff --git a/packages/esm-commons-lib/src/config-schema.ts b/packages/esm-commons-lib/src/config-schema.ts index 44609ea53..9efd64323 100644 --- a/packages/esm-commons-lib/src/config-schema.ts +++ b/packages/esm-commons-lib/src/config-schema.ts @@ -6,6 +6,22 @@ export const configSchema = { _description: 'Show mamba reports', _default: false, }, + 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: '12f236b1-b0b5-4ecc-9037-681c23fb45bd' }, + { name: 'Mamba HTS Line List', uuid: '6a6ae4ce-8427-45a6-9835-bbd6ade7a670' }, + { + name: 'Mother HIV Status Report', + uuid: 'mother_hiv_status', + ptrackerId: '12345A232567', + personUuid: 'bd49d697-b1de-49b9-95c2-6031fb1375fd', + }, + ], + }, }; export interface ConfigObject {