@ampath/esm-reports-app 1.0.0-next.41 → 1.0.0-next.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/110.js +2 -1
- package/dist/110.js.LICENSE.txt +35 -0
- package/dist/110.js.map +1 -1
- package/dist/205.js +1 -1
- package/dist/441.js +1 -0
- package/dist/441.js.map +1 -0
- package/dist/738.js +1 -0
- package/dist/738.js.map +1 -0
- package/dist/812.js +1 -1
- package/dist/812.js.map +1 -1
- package/dist/ampath-esm-reports-app.js +1 -1
- package/dist/ampath-esm-reports-app.js.buildmanifest.json +66 -39
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/common/report-error/index.ts +1 -0
- package/src/common/report-error/show-report-error.ts +25 -0
- package/src/common/report-filters/date-range.ts +137 -0
- package/src/common/report-filters/index.ts +4 -0
- package/src/common/report-filters/report-filters.component.tsx +281 -151
- package/src/common/report-filters/report-filters.scss +180 -55
- package/src/common/report-filters/types.ts +66 -0
- package/src/common/report-filters/use-restore-period.ts +43 -0
- package/src/common/report-page/index.ts +2 -0
- package/src/common/report-page/report-page.component.tsx +32 -0
- package/src/common/report-page/report-page.scss +45 -0
- package/src/common/report-page/use-page-scale.ts +50 -0
- package/src/common/report-placeholder/has-report-data.ts +15 -0
- package/src/common/report-placeholder/index.ts +2 -0
- package/src/common/report-placeholder/report-placeholder.component.tsx +56 -0
- package/src/common/report-placeholder/report-placeholder.scss +46 -0
- package/src/common/report-register/index.ts +5 -0
- package/src/common/report-register/register-columns.ts +34 -0
- package/src/common/report-register/register-layout.component.tsx +237 -0
- package/src/common/report-register/register-layout.scss +140 -0
- package/src/common/report-register/register-table.scss +62 -0
- package/src/common/report-register/report-parents.ts +27 -0
- package/src/common/report-register/rows-to-csv.ts +59 -0
- package/src/common/report-register/use-patient-list.ts +92 -0
- package/src/common/report-skeleton/index.ts +1 -0
- package/src/common/report-skeleton/report-skeleton.component.tsx +46 -0
- package/src/common/report-skeleton/report-skeleton.scss +29 -0
- package/src/config-schema.ts +9 -1
- package/src/dashboard/report-catalog.ts +173 -0
- package/src/dashboard/reports-dasboard.tsx +101 -35
- package/src/dashboard/reports-dashboard.module.scss +269 -11
- package/src/index.ts +13 -1
- package/src/reports/datatable-wrapper/datatable-wrapper.component.tsx +50 -48
- package/src/reports/moh-240/moh-240-header.component.tsx +54 -56
- package/src/reports/moh-240/moh-240.columns.ts +64 -0
- package/src/reports/moh-240/moh-240.component.tsx +65 -84
- package/src/reports/moh-240/moh-240.scss +36 -7
- package/src/reports/moh-240/sub-reports/moh-240-register.component.tsx +27 -65
- package/src/reports/moh-240/sub-reports/page-summary.component.tsx +2 -2
- package/src/reports/moh-505/moh-505-header.component.tsx +59 -57
- package/src/reports/moh-505/moh-505.component.tsx +51 -56
- package/src/reports/moh-505/moh-505.scss +116 -2
- package/src/reports/moh-705B/moh-204b-register.component.tsx +41 -42
- package/src/reports/moh-705B/moh-204b.columns.ts +39 -0
- package/src/reports/moh-705B/moh-705b.component.tsx +492 -473
- package/src/reports/moh-705B/moh-705b.scss +110 -24
- package/src/reports/moh-705a/moh-705a.component.tsx +496 -476
- package/src/reports/moh-705a/moh-705a.scss +109 -24
- package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +41 -42
- package/src/reports/moh-705a/registers/moh-204a.columns.ts +57 -0
- package/src/reports/moh-706/moh-706-header.component.tsx +58 -56
- package/src/reports/moh-706/moh-706.component.tsx +84 -55
- package/src/reports/moh-706/moh-706.scss +115 -19
- package/src/reports/moh-710/moh-710.component.tsx +743 -727
- package/src/reports/moh-710/moh-710.scss +140 -23
- package/src/reports/moh-710/registers/moh-511-710-register.component.tsx +48 -43
- package/src/reports/moh-710/registers/moh-511-710.columns.ts +52 -0
- package/src/reports/moh-711/moh-711.component.tsx +94 -106
- package/src/reports/moh-711/moh711.scss +95 -64
- package/src/reports/moh-711/registers/moh-333-register.component.tsx +92 -94
- package/src/reports/moh-711/registers/moh-333.columns.ts +119 -0
- package/src/reports/moh-711/registers/moh-405-register.component.tsx +88 -89
- package/src/reports/moh-711/registers/moh-405.columns.ts +120 -0
- package/src/reports/moh-711/registers/moh-406-register.component.tsx +85 -88
- package/src/reports/moh-711/registers/moh-406.columns.ts +133 -0
- package/src/reports/moh-711/registers/moh-510-register.component.tsx +38 -44
- package/src/reports/moh-711/registers/moh-511-register.component.tsx +42 -43
- package/src/reports/moh-711/registers/moh-511.columns.ts +59 -0
- package/src/reports/moh-711/sections/anc.component.tsx +3 -3
- package/src/reports/moh-711/sections/cervical-cancer.component.tsx +3 -3
- package/src/reports/moh-711/sections/chanis.component.tsx +2 -3
- package/src/reports/moh-711/sections/family-planning.component.tsx +2 -2
- package/src/reports/moh-711/sections/gbv.component.tsx +2 -2
- package/src/reports/moh-711/sections/maternity.component.tsx +3 -8
- package/src/reports/moh-711/sections/medical-social-work.component.tsx +2 -12
- package/src/reports/moh-711/sections/other.component.tsx +2 -2
- package/src/reports/moh-711/sections/physiotherapy.component.tsx +2 -2
- package/src/reports/moh-711/sections/pnc.component.tsx +7 -5
- package/src/reports/moh-711/sections/post-abortion.component.tsx +2 -2
- package/src/reports/moh-711/sections/rehabilitation.component.tsx +2 -2
- package/src/reports/moh-711/sections/report-compiled-by.component.tsx +12 -4
- package/src/reports/moh-711/sections/tb-screening.component.tsx +2 -2
- package/src/reports/moh-717/moh-717.component.tsx +100 -121
- package/src/reports/moh-717/moh717.scss +163 -102
- package/src/reports/moh-717/sections/maternity.component.tsx +1 -1
- package/src/reports/moh-717/sections/orthopaedic-trauma.component.tsx +1 -1
- package/src/reports/moh-717/sections/outpatient.component.tsx +23 -23
- package/src/reports/moh-717/sections/preparedby.component.tsx +7 -2
- package/src/reports/moh-717/sections/special-services.component.tsx +1 -1
- package/src/reports/moh-731/moh-731.component.tsx +127 -110
- package/src/reports/moh-731/moh-731.scss +396 -68
- package/src/reports/moh-731/registers/moh-366.columns.ts +38 -0
- package/src/reports/moh-731/registers/moh-366.component.tsx +76 -83
- package/src/reports/moh-731/registers/prep-register.component.tsx +70 -78
- package/src/reports/moh-731/registers/prep.columns.ts +34 -0
- package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +1031 -751
- package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +230 -86
- package/src/reports/moh-731/sections/pmtct.component.tsx +185 -64
- package/src/reports/moh-740/moh-740.component.scss +159 -79
- package/src/reports/moh-740/moh-740.component.tsx +258 -227
- package/src/reports/moh-740/moh-740.resource.ts +17 -10
- package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.tsx +77 -96
- package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.tsx +50 -70
- package/src/reports/moh-740/registers/moh-740-patient-list.tsx +61 -32
- package/src/reports/moh-740/registers/moh-740.columns.ts +52 -0
- package/src/reports/moh-745/moh-745.component.tsx +897 -877
- package/src/reports/moh-745/moh-745.scss +104 -46
- package/src/reports/moh-745/registers/moh-412-register.component.tsx +42 -43
- package/src/reports/moh-745/registers/moh-412.columns.ts +52 -0
- package/src/reports/table-wrapper/table-wrapper.component.tsx +23 -14
- package/src/reports/table-wrapper/table-wrapper.scss +1 -16
- package/src/resources/moh-505.resource.ts +18 -35
- package/src/resources/moh-705.resource.ts +28 -39
- package/src/resources/moh-706.resource.ts +17 -30
- package/src/resources/moh-710.resource.ts +7 -17
- package/src/resources/moh-711.resource.ts +46 -64
- package/src/resources/moh-717.resource.ts +7 -17
- package/src/resources/moh-731.resource.ts +26 -32
- package/src/resources/moh-745.resource.ts +18 -20
- package/src/resources/patient-list-page.ts +66 -0
- package/src/root.component.tsx +28 -26
- package/src/root.scss +39 -0
- package/src/utils/get-base-url.ts +39 -7
- package/dist/822.js +0 -2
- package/dist/822.js.LICENSE.txt +0 -20
- package/dist/822.js.map +0 -1
- package/src/reports/moh-731/registers/moh-366.scss +0 -45
- package/src/reports/moh-731/registers/prep-registers.scss +0 -45
- package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.scss +0 -18
- package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.scss +0 -18
- /package/src/{reports/moh-740/shared/utils → utils}/format-indicator.ts +0 -0
|
@@ -1,54 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
DataTable,
|
|
3
|
+
type DataTableHeader,
|
|
4
|
+
type DataTableRow,
|
|
5
|
+
Table,
|
|
6
|
+
TableBody,
|
|
7
|
+
TableCell,
|
|
8
|
+
TableHead,
|
|
9
|
+
TableHeader,
|
|
10
|
+
TableRow,
|
|
11
|
+
} from '@carbon/react';
|
|
12
|
+
import React from 'react';
|
|
3
13
|
|
|
4
14
|
interface DatatableWrapperProps {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
15
|
+
rows: Omit<DataTableRow<any[]>, 'cells'>[];
|
|
16
|
+
headers: DataTableHeader[];
|
|
17
|
+
subHeaders?: string[];
|
|
18
|
+
/** Applied to the table, so a register can use its own stylesheet */
|
|
19
|
+
className?: string;
|
|
8
20
|
}
|
|
9
21
|
|
|
10
|
-
const DatatableWrapper: React.FC<DatatableWrapperProps> = ({ rows, headers, subHeaders = [] }) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<TableBody>
|
|
41
|
-
{rows.map((row) => (
|
|
42
|
-
<TableRow {...getRowProps({ row })}>
|
|
43
|
-
{row.cells.map((cell) => (
|
|
44
|
-
<TableCell {...getCellProps({ cell })}>{cell.value}</TableCell>
|
|
45
|
-
))}
|
|
46
|
-
</TableRow>
|
|
47
|
-
))}
|
|
48
|
-
</TableBody>
|
|
49
|
-
</Table>
|
|
50
|
-
)}
|
|
22
|
+
const DatatableWrapper: React.FC<DatatableWrapperProps> = ({ rows, headers, subHeaders = [], className }) => {
|
|
23
|
+
return (
|
|
24
|
+
<DataTable rows={rows} headers={headers}>
|
|
25
|
+
{({ rows, headers, getTableProps, getHeaderProps, getRowProps, getCellProps }) => (
|
|
26
|
+
<Table {...getTableProps()} className={className}>
|
|
27
|
+
<TableHead>
|
|
28
|
+
<TableRow>
|
|
29
|
+
{headers.map((header) => (
|
|
30
|
+
<TableHeader {...getHeaderProps({ header })}>{header.header}</TableHeader>
|
|
31
|
+
))}
|
|
32
|
+
</TableRow>
|
|
33
|
+
{subHeaders && subHeaders.length && (
|
|
34
|
+
<TableRow>
|
|
35
|
+
{subHeaders.map((head, i) => (
|
|
36
|
+
<TableHeader key={i}>{head}</TableHeader>
|
|
37
|
+
))}
|
|
38
|
+
</TableRow>
|
|
39
|
+
)}
|
|
40
|
+
</TableHead>
|
|
41
|
+
<TableBody>
|
|
42
|
+
{rows.map((row) => (
|
|
43
|
+
<TableRow {...getRowProps({ row })}>
|
|
44
|
+
{row.cells.map((cell) => (
|
|
45
|
+
<TableCell {...getCellProps({ cell })}>{cell.value}</TableCell>
|
|
46
|
+
))}
|
|
47
|
+
</TableRow>
|
|
48
|
+
))}
|
|
49
|
+
</TableBody>
|
|
50
|
+
</Table>
|
|
51
|
+
)}
|
|
51
52
|
</DataTable>
|
|
52
|
-
|
|
53
|
+
);
|
|
54
|
+
};
|
|
53
55
|
|
|
54
|
-
export default DatatableWrapper;
|
|
56
|
+
export default DatatableWrapper;
|
|
@@ -1,61 +1,59 @@
|
|
|
1
|
-
import React, { useMemo } from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import TableWrapper from '../table-wrapper/table-wrapper.component';
|
|
4
|
+
import TableRowMapper from '../table-wrapper/table-row-mapper.component';
|
|
5
|
+
import { getCell } from '../../utils/utils';
|
|
5
6
|
import styles from './moh-240.scss';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
],
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
tableCells: [
|
|
18
|
-
getCell("", "Sub-County:", 1, 1, true),
|
|
19
|
-
getCell("", "", 3),
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
tableCells: [
|
|
24
|
-
getCell("", "Health Facility:", 1, 1, true),
|
|
25
|
-
getCell("", "", 3),
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
tableCells: [
|
|
30
|
-
getCell("", "KMHFL Code:", 1, 1, true),
|
|
31
|
-
getCell("", "", 3),
|
|
32
|
-
],
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
tableCells: [
|
|
36
|
-
getCell("", "Type:", 1, 1, true),
|
|
37
|
-
getCell("", ""),
|
|
38
|
-
getCell("", "Man. Agency:", 1, 1, true),
|
|
39
|
-
getCell("", ""),
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
tableCells: [
|
|
44
|
-
getCell("", "Start date:", 1, 1, true),
|
|
45
|
-
getCell("", ""),
|
|
46
|
-
getCell("", "End date:", 1, 1, true),
|
|
47
|
-
getCell("", ""),
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
];
|
|
51
|
-
}, []);
|
|
8
|
+
interface MOH240HeaderProps {
|
|
9
|
+
facility?: string;
|
|
10
|
+
startDate?: string;
|
|
11
|
+
endDate?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const asDate = (value?: string) => (value ? dayjs(value).format('DD/MM/YYYY') : '');
|
|
52
15
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
16
|
+
const MOH240Header: React.FC<MOH240HeaderProps> = ({ facility = '', startDate, endDate }) => {
|
|
17
|
+
const tableRows = useMemo(() => {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
tableCells: [getCell('', 'County:', 1, 1, true), getCell('', '', 3)],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
tableCells: [getCell('', 'Sub-County:', 1, 1, true), getCell('', '', 3)],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tableCells: [getCell('', 'Health Facility:', 1, 1, true), getCell('', facility, 3)],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
tableCells: [getCell('', 'KMHFL Code:', 1, 1, true), getCell('', '', 3)],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
tableCells: [
|
|
33
|
+
getCell('', 'Type:', 1, 1, true),
|
|
34
|
+
getCell('', ''),
|
|
35
|
+
getCell('', 'Man. Agency:', 1, 1, true),
|
|
36
|
+
getCell('', ''),
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
tableCells: [
|
|
41
|
+
getCell('', 'Start date:', 1, 1, true),
|
|
42
|
+
getCell('', asDate(startDate)),
|
|
43
|
+
getCell('', 'End date:', 1, 1, true),
|
|
44
|
+
getCell('', asDate(endDate)),
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
}, [facility, startDate, endDate]);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div className={styles.headerSection}>
|
|
52
|
+
<TableWrapper className={styles.formTable}>
|
|
53
|
+
<TableRowMapper tableRows={tableRows} />
|
|
54
|
+
</TableWrapper>
|
|
58
55
|
</div>
|
|
59
|
-
|
|
56
|
+
);
|
|
57
|
+
};
|
|
60
58
|
|
|
61
|
-
export default MOH240Header;
|
|
59
|
+
export default MOH240Header;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type RegisterColumn } from '../../common/report-register';
|
|
2
|
+
|
|
3
|
+
/** The register's columns, in the order the printed MOH 240 prints them */
|
|
4
|
+
export const MOH_240_HEADERS = [
|
|
5
|
+
{ key: 'date', header: 'Date (DD/MM/YYYY)' },
|
|
6
|
+
{ key: 'opd_ip_ref_no', header: 'OPD / IPD Ref. No.' },
|
|
7
|
+
{ key: 'lab_no', header: 'Lab. No. (new client)' },
|
|
8
|
+
{ key: 'revisit_no', header: 'Revisit No.' },
|
|
9
|
+
{ key: 'full_name', header: 'Full Names (Three names)' },
|
|
10
|
+
{ key: 'age', header: 'Age' },
|
|
11
|
+
{ key: 'sex', header: 'Sex' },
|
|
12
|
+
{ key: 'county_sub_county', header: 'County / Sub County' },
|
|
13
|
+
{ key: 'village_estate_landmark', header: 'Village / Estate / Landmark' },
|
|
14
|
+
{ key: 'telephone_number', header: 'Telephone Number' },
|
|
15
|
+
{ key: 'clinical_diagnosis', header: 'Clinical Diagnosis' },
|
|
16
|
+
{ key: 'prior_treatment', header: 'Prior Treatment' },
|
|
17
|
+
{ key: 'type_of_specimen', header: 'Type of Specimen' },
|
|
18
|
+
{ key: 'condition_of_specimen', header: 'Condition of Specimen' },
|
|
19
|
+
{ key: 'investigation_required', header: 'Investigation Required' },
|
|
20
|
+
{ key: 'test_datetime', header: 'Date Sample Collected' },
|
|
21
|
+
{ key: 'date_sample_received', header: 'Date Sample Received' },
|
|
22
|
+
{ key: 'clinician_name', header: 'Clinician Name' },
|
|
23
|
+
{ key: 'date_sample_analysed', header: 'Date Sample Analysed' },
|
|
24
|
+
{ key: 'results', header: 'Results' },
|
|
25
|
+
{ key: 'date_results_dispatched', header: 'Date Results Dispatched' },
|
|
26
|
+
{ key: 'amount_charged', header: 'Amount Charged' },
|
|
27
|
+
{ key: 'receipt_number', header: 'Receipt Number' },
|
|
28
|
+
{ key: 'referrals', header: 'Referrals (From Other HF / To Other HF / 3rd Tier Reference Laboratories)' },
|
|
29
|
+
{ key: 'comments', header: 'Comments' },
|
|
30
|
+
{ key: 'testing_officer', header: 'Name of Analysing/Testing Officer' },
|
|
31
|
+
{ key: 'signature', header: 'Signature' },
|
|
32
|
+
] as const;
|
|
33
|
+
|
|
34
|
+
/** The column letters the printed register runs across the top */
|
|
35
|
+
export const MOH_240_SUB_HEADERS = MOH_240_HEADERS.map((_, i) =>
|
|
36
|
+
i < 26 ? String.fromCharCode(65 + i) : `A${String.fromCharCode(65 + i - 26)}`,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The results column carries whichever indicator the drill-down was opened for,
|
|
41
|
+
* so it is read from a field named by that indicator rather than from `results`.
|
|
42
|
+
*/
|
|
43
|
+
export function resultFieldFor(indicator: string): string {
|
|
44
|
+
if (indicator.startsWith('min_') || indicator.startsWith('max_')) {
|
|
45
|
+
return indicator.substring(4);
|
|
46
|
+
}
|
|
47
|
+
if (indicator.startsWith('total_')) {
|
|
48
|
+
return indicator.substring(6);
|
|
49
|
+
}
|
|
50
|
+
if (indicator.startsWith('positive_')) {
|
|
51
|
+
return indicator.substring(9);
|
|
52
|
+
}
|
|
53
|
+
return indicator;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Exported with the register's own headings, so the CSV matches the form */
|
|
57
|
+
export function moh240Columns(indicator: string): RegisterColumn[] {
|
|
58
|
+
const resultField = resultFieldFor(indicator);
|
|
59
|
+
|
|
60
|
+
return MOH_240_HEADERS.map(({ key, header }) => ({
|
|
61
|
+
header,
|
|
62
|
+
value: (row: Record<string, any>) => (key === 'results' ? (row[resultField] ?? '') : (row[key] ?? '')),
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
@@ -1,93 +1,74 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { useSearchParams } from
|
|
3
|
-
import {
|
|
4
|
-
import Moh240Register from "./sub-reports/moh-240-register.component";
|
|
5
|
-
import Moh240PageSummary from "./sub-reports/page-summary.component";
|
|
6
|
-
import { getMoh706PatientList } from "../../resources/moh-706.resource";
|
|
7
|
-
import { getMoh505PatientList } from "../../resources/moh-505.resource";
|
|
8
|
-
import MOH240Header from "./moh-240-header.component";
|
|
9
|
-
import styles from "./moh-240.scss";
|
|
10
|
-
import { navigate } from "@openmrs/esm-framework";
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useSearchParams } from 'react-router-dom';
|
|
3
|
+
import { useSession } from '@openmrs/esm-framework';
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
import Moh240Register from './sub-reports/moh-240-register.component';
|
|
6
|
+
import Moh240PageSummary from './sub-reports/page-summary.component';
|
|
7
|
+
import MOH240Header from './moh-240-header.component';
|
|
8
|
+
import { moh240Columns } from './moh-240.columns';
|
|
9
|
+
import { getMoh706PatientList } from '../../resources/moh-706.resource';
|
|
10
|
+
import { getMoh505PatientList } from '../../resources/moh-505.resource';
|
|
11
|
+
import { RegisterLayout, usePatientList } from '../../common/report-register';
|
|
12
|
+
import styles from './moh-240.scss';
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const report = searchParams.get('report');
|
|
14
|
+
/** The reports that drill down into this register */
|
|
15
|
+
const PARENTS: Record<string, { label: string; path: string }> = {
|
|
16
|
+
'moh-505': { label: 'MOH-505 Report', path: '/moh-505' },
|
|
17
|
+
'moh-706': { label: 'MOH-706 Report', path: '/moh-706' },
|
|
18
|
+
};
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
}, [searchParams]);
|
|
20
|
+
const Moh240Report: React.FC = () => {
|
|
21
|
+
const [searchParams] = useSearchParams();
|
|
22
|
+
const session = useSession();
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (params.report === 'moh-505') {
|
|
38
|
-
result = await getMoh505PatientList(params);
|
|
39
|
-
} else {
|
|
40
|
-
result = await getMoh706PatientList(params);
|
|
41
|
-
}
|
|
42
|
-
setPatientList(result);
|
|
43
|
-
} catch (error: any) {
|
|
44
|
-
setErrorMessage(error instanceof Error ? error.message : String(error));
|
|
45
|
-
} finally {
|
|
46
|
-
setIsLoading(false);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
24
|
+
const locationUuids = searchParams.get('locationUuids') ?? '';
|
|
25
|
+
const startDate = searchParams.get('startDate') ?? '';
|
|
26
|
+
const endDate = searchParams.get('endDate') ?? '';
|
|
27
|
+
const indicators = searchParams.get('indicators') ?? '';
|
|
28
|
+
const report = searchParams.get('report') || 'moh-706';
|
|
49
29
|
|
|
50
|
-
|
|
51
|
-
const report = searchParams.get('report');
|
|
52
|
-
const locationUuids = searchParams.get('locationUuids');
|
|
53
|
-
const startDate = searchParams.get('startDate');
|
|
54
|
-
const endDate = searchParams.get('endDate');
|
|
30
|
+
const parent = PARENTS[report] ?? PARENTS['moh-706'];
|
|
55
31
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
32
|
+
const {
|
|
33
|
+
rows: patientList,
|
|
34
|
+
total,
|
|
35
|
+
isTotalExact,
|
|
36
|
+
isLoading,
|
|
37
|
+
page,
|
|
38
|
+
pageSize,
|
|
39
|
+
onPageChange,
|
|
40
|
+
fetchAll,
|
|
41
|
+
} = usePatientList(
|
|
42
|
+
({ startIndex, limit }) => {
|
|
43
|
+
const params = { locationUuids, startDate, endDate, indicators, startIndex, limit };
|
|
62
44
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
</div>
|
|
68
|
-
{isLoading && <Loading description="Fetching patient list...." />}
|
|
69
|
-
{!isLoading && errorMessage && (
|
|
70
|
-
<div>
|
|
71
|
-
<a href="#" className="close" data-dismiss="alert">
|
|
72
|
-
×
|
|
73
|
-
</a>
|
|
74
|
-
<h4>
|
|
75
|
-
<strong>
|
|
76
|
-
<span className="glyphicon glyphicon-warning-sign"></span>{' '}
|
|
77
|
-
</strong>{' '}
|
|
78
|
-
An error occurred while trying to load the patient list. Please try again.
|
|
79
|
-
</h4>
|
|
80
|
-
<p>
|
|
81
|
-
<small>{errorMessage}</small>
|
|
82
|
-
</p>
|
|
83
|
-
</div>
|
|
84
|
-
)}
|
|
45
|
+
return report === 'moh-505' ? getMoh505PatientList(params) : getMoh706PatientList(params);
|
|
46
|
+
},
|
|
47
|
+
[locationUuids, startDate, endDate, indicators, report],
|
|
48
|
+
);
|
|
85
49
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
50
|
+
return (
|
|
51
|
+
<RegisterLayout
|
|
52
|
+
parentLabel={parent.label}
|
|
53
|
+
parentPath={parent.path}
|
|
54
|
+
title="Laboratory (LAB) Register MOH 240"
|
|
55
|
+
isLoading={isLoading}
|
|
56
|
+
isEmpty={patientList.length === 0}
|
|
57
|
+
page={page}
|
|
58
|
+
pageSize={pageSize}
|
|
59
|
+
total={total}
|
|
60
|
+
isTotalExact={isTotalExact}
|
|
61
|
+
onPageChange={onPageChange}
|
|
62
|
+
fetchAll={fetchAll}
|
|
63
|
+
columns={moh240Columns(indicators)}
|
|
64
|
+
>
|
|
65
|
+
<div className={styles.sheet}>
|
|
66
|
+
<MOH240Header facility={session?.sessionLocation?.display ?? ''} startDate={startDate} endDate={endDate} />
|
|
67
|
+
<Moh240Register patientList={patientList} indicator={indicators} />
|
|
68
|
+
<Moh240PageSummary />
|
|
69
|
+
</div>
|
|
70
|
+
</RegisterLayout>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
92
73
|
|
|
93
|
-
export default Moh240Report;
|
|
74
|
+
export default Moh240Report;
|
|
@@ -1,11 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* MOH-240 is a drill-down line list, so its table comes from the shared
|
|
2
|
+
register stylesheet. What is styled here is the printed register's own
|
|
3
|
+
furniture: the facility block above the list and the page summary below it.
|
|
4
|
+
|
|
5
|
+
Both render through TableWrapper, whose cell rules are single-class, so
|
|
6
|
+
scoping these under `.sheet` (a class plus an element) wins deterministically
|
|
7
|
+
rather than by module load order. The wrapper is asked for a plain table so
|
|
8
|
+
Carbon's data-table rules, which are far more specific, never apply. */
|
|
9
|
+
|
|
10
|
+
$ink: #000;
|
|
11
|
+
$rule: 1px solid $ink;
|
|
12
|
+
|
|
13
|
+
$text: 0.75rem;
|
|
14
|
+
|
|
15
|
+
.sheet {
|
|
16
|
+
.formTable table {
|
|
17
|
+
width: 100%;
|
|
18
|
+
border-collapse: collapse;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.formTable td,
|
|
22
|
+
.formTable th {
|
|
23
|
+
height: auto;
|
|
24
|
+
min-width: 0;
|
|
25
|
+
padding: 0.25rem 0.375rem;
|
|
26
|
+
overflow-wrap: anywhere;
|
|
27
|
+
font-size: $text;
|
|
28
|
+
line-height: 1.3;
|
|
29
|
+
text-align: left;
|
|
30
|
+
border: $rule;
|
|
31
|
+
}
|
|
3
32
|
}
|
|
4
33
|
|
|
5
|
-
.
|
|
6
|
-
margin:
|
|
34
|
+
.headerSection {
|
|
35
|
+
margin-bottom: 0.75rem;
|
|
7
36
|
}
|
|
8
37
|
|
|
9
|
-
.
|
|
10
|
-
margin:
|
|
11
|
-
}
|
|
38
|
+
.summarySection {
|
|
39
|
+
margin-top: 0.75rem;
|
|
40
|
+
}
|
|
@@ -1,75 +1,37 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import DatatableWrapper from
|
|
3
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import DatatableWrapper from '../../datatable-wrapper/datatable-wrapper.component';
|
|
3
|
+
import { MOH_240_HEADERS, MOH_240_SUB_HEADERS, resultFieldFor } from '../moh-240.columns';
|
|
4
|
+
import tableStyles from '../../../common/report-register/register-table.scss';
|
|
5
|
+
import classNames from 'classnames';
|
|
6
|
+
|
|
4
7
|
interface Moh240RegisterProps {
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
patientList?: any[];
|
|
9
|
+
indicator?: string;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
const Moh240Register: React.FC<Moh240RegisterProps> = ({ patientList = [], indicator = '' }) => {
|
|
10
|
-
|
|
11
|
-
{ key: 'date', header: 'Date (DD/MM/YYYY)' },
|
|
12
|
-
{ key: 'opd_ip_ref_no', header: 'OPD / IPD Ref. No.' },
|
|
13
|
-
{ key: 'lab_no', header: 'Lab. No. (new client)' },
|
|
14
|
-
{ key: 'revisit_no', header: 'Revisit No.' },
|
|
15
|
-
{ key: 'full_name', header: 'Full Names (Three names)' },
|
|
16
|
-
{ key: 'age', header: 'Age' },
|
|
17
|
-
{ key: 'sex', header: 'Sex' },
|
|
18
|
-
{ key: 'county_sub_county', header: 'County / Sub County' },
|
|
19
|
-
{ key: 'village_estate_landmark', header: 'Village / Estate / Landmark' },
|
|
20
|
-
{ key: 'telephone_number', header: 'Telephone Number' },
|
|
21
|
-
{ key: 'clinical_diagnosis', header: 'Clinical Diagnosis' },
|
|
22
|
-
{ key: 'prior_treatment', header: 'Prior Treatment' },
|
|
23
|
-
{ key: 'type_of_specimen', header: 'Type of Specimen' },
|
|
24
|
-
{ key: 'condition_of_specimen', header: 'Condition of Specimen' },
|
|
25
|
-
{ key: 'investigation_required', header: 'Investigation Required' },
|
|
26
|
-
{ key: 'test_datetime', header: 'Date Sample Collected' },
|
|
27
|
-
{ key: 'date_sample_received', header: 'Date Sample Received' },
|
|
28
|
-
{ key: 'clinician_name', header: 'Clinician Name' },
|
|
29
|
-
{ key: 'date_sample_analysed', header: 'Date Sample Analysed' },
|
|
30
|
-
{ key: 'results', header: 'Results' },
|
|
31
|
-
{ key: 'date_results_dispatched', header: 'Date Results Dispatched' },
|
|
32
|
-
{ key: 'amount_charged', header: 'Amount Charged' },
|
|
33
|
-
{ key: 'receipt_number', header: 'Receipt Number' },
|
|
34
|
-
{ key: 'referrals', header: 'Referrals (From Other HF / To Other HF / 3rd Tier Reference Laboratories)' },
|
|
35
|
-
{ key: 'comments', header: 'Comments' },
|
|
36
|
-
{ key: 'testing_officer', header: 'Name of Analysing/Testing Officer' },
|
|
37
|
-
{ key: 'signature', header: 'Signature' }
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
const getResultField = (ind: string) => {
|
|
41
|
-
if (ind.startsWith('min_') || ind.startsWith('max_')) {
|
|
42
|
-
return ind.substring(4);
|
|
43
|
-
}
|
|
44
|
-
if (ind.startsWith('total_')) {
|
|
45
|
-
return ind.substring(6);
|
|
46
|
-
}
|
|
47
|
-
if (ind.startsWith('positive_')) {
|
|
48
|
-
return ind.substring(9);
|
|
49
|
-
}
|
|
50
|
-
return ind;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const resultField = getResultField(indicator);
|
|
13
|
+
const resultField = resultFieldFor(indicator);
|
|
54
14
|
|
|
55
|
-
|
|
15
|
+
const rows = patientList.map((patient, index) => {
|
|
16
|
+
const row: { id: string } & Record<string, any> = { id: String(index) };
|
|
56
17
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
headers.forEach(header => {
|
|
60
|
-
if (header.key === 'results') {
|
|
61
|
-
row[header.key] = patient[resultField] || '';
|
|
62
|
-
} else {
|
|
63
|
-
row[header.key] = patient[header.key] || '';
|
|
64
|
-
}
|
|
65
|
-
row["id"] = header.key + index;
|
|
66
|
-
});
|
|
67
|
-
return row;
|
|
18
|
+
MOH_240_HEADERS.forEach(({ key }) => {
|
|
19
|
+
row[key] = (key === 'results' ? patient[resultField] : patient[key]) || '';
|
|
68
20
|
});
|
|
69
21
|
|
|
70
|
-
return
|
|
71
|
-
|
|
22
|
+
return row;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className={tableStyles.tableContainer}>
|
|
27
|
+
<DatatableWrapper
|
|
28
|
+
headers={[...MOH_240_HEADERS]}
|
|
29
|
+
rows={rows}
|
|
30
|
+
subHeaders={MOH_240_SUB_HEADERS}
|
|
31
|
+
className={classNames(tableStyles.table, tableStyles.tableBordered, tableStyles.tableStriped)}
|
|
32
|
+
/>
|
|
72
33
|
</div>
|
|
73
|
-
|
|
34
|
+
);
|
|
35
|
+
};
|
|
74
36
|
|
|
75
|
-
export default Moh240Register;
|
|
37
|
+
export default Moh240Register;
|
|
@@ -88,8 +88,8 @@ const Moh240PageSummary: React.FC = () => {
|
|
|
88
88
|
}, []);
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
return <div className={styles.
|
|
92
|
-
<TableWrapper>
|
|
91
|
+
return <div className={styles.summarySection}>
|
|
92
|
+
<TableWrapper className={styles.formTable}>
|
|
93
93
|
<TableRowMapper tableRows={tableRows} />
|
|
94
94
|
</TableWrapper>
|
|
95
95
|
</div>
|