@ampath/esm-reports-app 1.0.0-next.55 → 1.0.0-next.57
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/295.js +1 -1
- package/dist/410.js +1 -1
- package/dist/580.js +1 -0
- package/dist/580.js.map +1 -0
- package/dist/907.js +2 -1
- package/dist/907.js.map +1 -1
- package/dist/998.css +1 -0
- package/dist/998.css.map +1 -0
- package/dist/998.js +1 -0
- package/dist/998.js.map +1 -0
- package/dist/ampath-esm-reports-app.js +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/common/daily-summary-table.tsx +55 -0
- package/src/common/linelist-table/index.ts +3 -0
- package/src/common/linelist-table/linelist-columns.ts +48 -0
- package/src/common/linelist-table/linelist-table.component.tsx +442 -0
- package/src/common/linelist-table/linelist-table.scss +306 -0
- package/src/common/linelist-table/linelist-table.test.tsx +120 -0
- package/src/common/linelist-table/use-all-rows.ts +93 -0
- package/src/common/linelist-table/use-column-layout.ts +123 -0
- package/src/common/report-filters/report-filters.component.tsx +11 -5
- package/src/common/report-filters/report-filters.scss +63 -7
- package/src/common/report-page/use-page-scale.ts +27 -17
- package/src/common/report-placeholder/index.ts +1 -0
- package/src/common/report-placeholder/report-placeholder.component.tsx +57 -32
- package/src/common/report-placeholder/report-placeholder.scss +2 -0
- package/src/common/report-placeholder/use-generated-location.ts +62 -0
- package/src/common/report-register/index.ts +1 -0
- package/src/common/report-register/register-layout.component.tsx +26 -4
- package/src/common/report-register/register-layout.scss +10 -0
- package/src/common/report-register/use-location-name.ts +54 -0
- package/src/reports/moh-505/moh-505.component.tsx +9 -3
- package/src/reports/moh-705B/moh-204b-register.component.tsx +11 -2
- package/src/reports/moh-705B/moh-705b.component.tsx +533 -418
- package/src/reports/moh-705B/moh-705b.scss +44 -2
- package/src/reports/moh-705a/moh-705a.component.tsx +533 -421
- package/src/reports/moh-705a/moh-705a.scss +44 -2
- package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +12 -3
- package/src/reports/moh-706/moh-706.component.tsx +9 -3
- package/src/reports/moh-710/moh-710.component.tsx +9 -3
- package/src/reports/moh-711/moh-711.component.tsx +9 -3
- package/src/reports/moh-717/moh-717.component.tsx +12 -3
- package/src/reports/moh-731/linelist/moh-731-indicators.ts +1040 -0
- package/src/reports/moh-731/linelist/moh-731-linelist-sections.ts +423 -0
- package/src/reports/moh-731/linelist/moh-731-linelist.component.tsx +102 -0
- package/src/reports/moh-731/linelist/use-open-moh-731-linelist.ts +50 -0
- package/src/reports/moh-731/moh-731.component.tsx +138 -85
- package/src/reports/moh-731/moh-731.scss +51 -4
- package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +74 -77
- package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +84 -70
- package/src/reports/moh-731/sections/pmtct.component.tsx +43 -43
- package/src/reports/moh-731/summary/moh-731-summary.component.tsx +313 -0
- package/src/reports/moh-731/summary/moh-731-summary.config.ts +520 -0
- package/src/reports/moh-731/summary/moh-731-summary.scss +242 -0
- package/src/reports/moh-740/moh-740.component.scss +3 -1
- package/src/reports/moh-740/moh-740.component.tsx +14 -4
- package/src/reports/moh-745/moh-745.component.tsx +7 -3
- package/src/root.component.tsx +2 -0
- package/webpack.config.js +22 -1
- package/dist/427.js +0 -2
- package/dist/427.js.map +0 -1
- package/dist/441.js +0 -1
- package/dist/441.js.map +0 -1
- package/dist/907.css +0 -1
- package/dist/907.css.map +0 -1
- /package/dist/{427.js.LICENSE.txt → 907.js.LICENSE.txt} +0 -0
|
@@ -3,19 +3,25 @@ import React, { useEffect, useState } from 'react';
|
|
|
3
3
|
import styles from './moh-731.scss';
|
|
4
4
|
import { ReportFiltersComponent, type ReportPeriod } from '../../common/report-filters';
|
|
5
5
|
import { showReportError } from '../../common/report-error';
|
|
6
|
-
import { hasReportData, ReportPlaceholder } from '../../common/report-placeholder';
|
|
6
|
+
import { hasReportData, ReportPlaceholder, useGeneratedLocation } from '../../common/report-placeholder';
|
|
7
7
|
import { formatDate, useSession } from '@openmrs/esm-framework';
|
|
8
8
|
import dayjs from 'dayjs';
|
|
9
|
-
import { useNavigate } from 'react-router-dom';
|
|
9
|
+
import { useNavigate, useSearchParams } from 'react-router-dom';
|
|
10
|
+
import { Tab, TabList, TabPanel, TabPanels, Tabs } from '@carbon/react';
|
|
10
11
|
import { getMoh731 } from '../../resources/moh-731.resource';
|
|
11
12
|
import HivTestingandPreExposusreProphylaxis from './sections/hiv-testing-and-pre-exposure.component';
|
|
12
13
|
import PmtctComponent from './sections/pmtct.component';
|
|
13
14
|
import HivAndTBTreatmentComponent from './sections/hiv-and-tb-treatment.component';
|
|
14
15
|
import { ReportSkeleton } from '../../common/report-skeleton';
|
|
15
16
|
import { usePageScale } from '../../common/report-page';
|
|
17
|
+
import Moh731Summary from './summary/moh-731-summary.component';
|
|
18
|
+
import { useOpenMoh731Linelist } from './linelist/use-open-moh-731-linelist';
|
|
16
19
|
|
|
17
20
|
interface Moh731Props {}
|
|
18
21
|
|
|
22
|
+
/** The sheet's on-screen width: A4 less its 8mm margins (`.form` in moh-731.scss) */
|
|
23
|
+
const SHEET_WIDTH_MM = 210 - 2 * 8;
|
|
24
|
+
|
|
19
25
|
const Moh731Report: React.FC<Moh731Props> = () => {
|
|
20
26
|
const [moh731Data, setMoh731Data] = useState<any>(() => {
|
|
21
27
|
const saved = sessionStorage.getItem('moh731Data');
|
|
@@ -45,7 +51,32 @@ const Moh731Report: React.FC<Moh731Props> = () => {
|
|
|
45
51
|
const locationUuids = session?.sessionLocation?.uuid;
|
|
46
52
|
const navigate = useNavigate();
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
/* The form tab is the default; the selected tab is kept in the URL so a
|
|
55
|
+
linelist opened from the Summary tab comes back to it. */
|
|
56
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
57
|
+
const selectedTab = searchParams.get('view') === 'summary' ? 1 : 0;
|
|
58
|
+
const selectTab = ({ selectedIndex }: { selectedIndex: number }) => {
|
|
59
|
+
const next = new URLSearchParams(searchParams);
|
|
60
|
+
if (selectedIndex === 1) {
|
|
61
|
+
next.set('view', 'summary');
|
|
62
|
+
} else {
|
|
63
|
+
next.delete('view');
|
|
64
|
+
}
|
|
65
|
+
setSearchParams(next, { replace: true });
|
|
66
|
+
};
|
|
67
|
+
/* the Summary's section tab, kept in the URL the same way */
|
|
68
|
+
const summarySection = searchParams.get('section') ?? '';
|
|
69
|
+
const selectSummarySection = (section: string) => {
|
|
70
|
+
const next = new URLSearchParams(searchParams);
|
|
71
|
+
next.set('section', section);
|
|
72
|
+
setSearchParams(next, { replace: true });
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/* Only a report for the current location counts: after switching location the
|
|
76
|
+
old figures would otherwise be shown, and labelled, as the new location's. */
|
|
77
|
+
const { isForCurrentLocation, hasLocationChanged, markGenerated } = useGeneratedLocation('moh731Location');
|
|
78
|
+
const isReportGenerated = hasReportData(moh731Data) && isForCurrentLocation;
|
|
79
|
+
const openSummaryLinelist = useOpenMoh731Linelist(startDate, endDate, locationUuids ?? '', 'summary', summarySection);
|
|
49
80
|
|
|
50
81
|
/* The sign-off records who produced the return and when. Designation and
|
|
51
82
|
signature stay blank -- those are filled in by hand on the printed sheet. */
|
|
@@ -65,7 +96,7 @@ const Moh731Report: React.FC<Moh731Props> = () => {
|
|
|
65
96
|
const generatedOn = formatDate(new Date(), { mode: 'standard', time: false, noToday: true });
|
|
66
97
|
|
|
67
98
|
/** Fills the available width, never rendering below A4 */
|
|
68
|
-
const { ref: viewportRef, scale } = usePageScale<HTMLDivElement>();
|
|
99
|
+
const { ref: viewportRef, scale } = usePageScale<HTMLDivElement>(SHEET_WIDTH_MM);
|
|
69
100
|
|
|
70
101
|
const fetchMoh731ReportData = async ({ startDate, endDate }: ReportPeriod) => {
|
|
71
102
|
setIsLoading(true);
|
|
@@ -81,6 +112,7 @@ const Moh731Report: React.FC<Moh731Props> = () => {
|
|
|
81
112
|
const data = await getMoh731(params);
|
|
82
113
|
const flatData = Object.assign({}, ...data.result);
|
|
83
114
|
setMoh731Data(flatData);
|
|
115
|
+
markGenerated(params.locationUuids);
|
|
84
116
|
setIsLoading(false);
|
|
85
117
|
} catch (error: any) {
|
|
86
118
|
setIsLoading(false);
|
|
@@ -99,97 +131,118 @@ const Moh731Report: React.FC<Moh731Props> = () => {
|
|
|
99
131
|
generatedPeriod={{ startDate, endDate }}
|
|
100
132
|
/>
|
|
101
133
|
{isLoading && <ReportSkeleton blocks={3} />}
|
|
102
|
-
{!isLoading && !isReportGenerated &&
|
|
134
|
+
{!isLoading && !isReportGenerated && (
|
|
135
|
+
<ReportPlaceholder reportName="MOH-731" isLocationChanged={hasReportData(moh731Data) && hasLocationChanged} />
|
|
136
|
+
)}
|
|
103
137
|
{!isLoading && isReportGenerated && (
|
|
104
|
-
|
|
105
|
-
|
|
138
|
+
<Tabs selectedIndex={selectedTab} onChange={selectTab}>
|
|
139
|
+
<TabList aria-label="MOH 731 views" className={styles.tabList}>
|
|
140
|
+
<Tab>MOH 731 Form</Tab>
|
|
141
|
+
<Tab>Summary</Tab>
|
|
142
|
+
</TabList>
|
|
143
|
+
<TabPanels>
|
|
144
|
+
<TabPanel className={styles.formPanel}>
|
|
145
|
+
{/* The sheet is a fixed A4 page, so it scrolls inside this viewport
|
|
106
146
|
rather than forcing the whole app to scroll sideways. */}
|
|
107
|
-
|
|
108
|
-
|
|
147
|
+
<div className={styles.reportFrame}>
|
|
148
|
+
<div className={styles.viewport} ref={viewportRef}>
|
|
149
|
+
{/* The scale is a custom property rather than an inline `zoom`, so
|
|
109
150
|
the print stylesheet can still reset it to 1 */}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
151
|
+
<div className={styles.form} style={{ '--page-zoom': scale } as React.CSSProperties}>
|
|
152
|
+
{/* Ministry line sits above the ruled sheet, as on the printed form */}
|
|
153
|
+
<div className={styles.ministryLine}>
|
|
154
|
+
<span>Ministry of Health</span>
|
|
155
|
+
<span>Ver. July 2023</span>
|
|
156
|
+
</div>
|
|
116
157
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
158
|
+
<div className={styles.sheet}>
|
|
159
|
+
<div className={styles.formHeader}>
|
|
160
|
+
<div className={styles.formTitle}>
|
|
161
|
+
<strong>National AIDS & STI Control Program- NASCOP</strong>
|
|
162
|
+
<strong>Comprehensive HIV/ AIDS reporting form</strong>
|
|
163
|
+
</div>
|
|
164
|
+
<span className={styles.formVersion}>(MOH 731-Ver. July 2023)</span>
|
|
165
|
+
</div>
|
|
125
166
|
|
|
126
|
-
|
|
167
|
+
{/* Each label and its rule is one flex item, so the six pairs stay
|
|
127
168
|
on a single centred line and cannot run together. */}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
<p className={styles.locationContainer}>
|
|
170
|
+
<span>
|
|
171
|
+
County<span className={styles.line}>{county}</span>
|
|
172
|
+
</span>
|
|
173
|
+
<span>
|
|
174
|
+
Sub County<span className={styles.line}>{subCounty}</span>
|
|
175
|
+
</span>
|
|
176
|
+
<span>
|
|
177
|
+
Facility<span className={styles.line}>{facility}</span>
|
|
178
|
+
</span>
|
|
179
|
+
<span>
|
|
180
|
+
MFL<span className={styles.shortLine}>{mflCode}</span>
|
|
181
|
+
</span>
|
|
182
|
+
<span>
|
|
183
|
+
Month<span className={styles.shortLine}>{reportMonth}</span>
|
|
184
|
+
</span>
|
|
185
|
+
<span>
|
|
186
|
+
year<span className={styles.shortLine}>{reportYear}</span>
|
|
187
|
+
</span>
|
|
188
|
+
</p>
|
|
189
|
+
|
|
190
|
+
<h5 className={styles.sectionHeader}>1. HIV Testing Services & Pre exposure Prophylaxis</h5>
|
|
191
|
+
<HivTestingandPreExposusreProphylaxis
|
|
192
|
+
MOH731Data={moh731Data}
|
|
193
|
+
startDate={startDate}
|
|
194
|
+
endDate={endDate}
|
|
195
|
+
locationUuids={locationUuids!}
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
<h5 className={styles.sectionHeader}>2. Elimination of Mother-to-Child Transmission (EMTCT)</h5>
|
|
199
|
+
<PmtctComponent
|
|
200
|
+
MOH731Data={moh731Data}
|
|
201
|
+
startDate={startDate}
|
|
202
|
+
endDate={endDate}
|
|
203
|
+
locationUuids={locationUuids!}
|
|
204
|
+
/>
|
|
205
|
+
|
|
206
|
+
{/* The sign-off is the bottom band of columns 1 and 2 on the printed
|
|
166
207
|
sheet, with section 5 continuing beside it, so it is handed to
|
|
167
208
|
section 3 rather than rendered after it. */}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
209
|
+
<HivAndTBTreatmentComponent
|
|
210
|
+
MOH731Data={moh731Data}
|
|
211
|
+
startDate={startDate}
|
|
212
|
+
endDate={endDate}
|
|
213
|
+
locationUuids={locationUuids!}
|
|
214
|
+
footer={
|
|
215
|
+
<div className={styles.reviewSection}>
|
|
216
|
+
<span className={styles.reviewLabel}>Reviewed by:</span>
|
|
217
|
+
<span>Name</span>
|
|
218
|
+
<span>Designation</span>
|
|
219
|
+
<span>Signature</span>
|
|
220
|
+
<span>Date</span>
|
|
221
|
+
|
|
222
|
+
<span />
|
|
223
|
+
<span className={styles.reviewRule}>{generatedBy}</span>
|
|
224
|
+
<span className={styles.reviewRule} />
|
|
225
|
+
<span className={styles.reviewRule} />
|
|
226
|
+
<span className={styles.reviewRule}>{generatedOn}</span>
|
|
227
|
+
</div>
|
|
228
|
+
}
|
|
229
|
+
/>
|
|
186
230
|
</div>
|
|
187
|
-
|
|
188
|
-
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
189
233
|
</div>
|
|
190
|
-
</
|
|
191
|
-
|
|
192
|
-
|
|
234
|
+
</TabPanel>
|
|
235
|
+
<TabPanel className={styles.summaryPanel}>
|
|
236
|
+
<Moh731Summary
|
|
237
|
+
data={moh731Data}
|
|
238
|
+
openLinelist={openSummaryLinelist}
|
|
239
|
+
sectionId={summarySection}
|
|
240
|
+
onSectionChange={selectSummarySection}
|
|
241
|
+
period={`${startDate}-${endDate}`}
|
|
242
|
+
/>
|
|
243
|
+
</TabPanel>
|
|
244
|
+
</TabPanels>
|
|
245
|
+
</Tabs>
|
|
193
246
|
)}
|
|
194
247
|
</>
|
|
195
248
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
1
2
|
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
2
3
|
|
|
3
4
|
/* A replica of the printed MOH 731 (Ver. July 2023) facility summary sheet,
|
|
@@ -41,6 +42,32 @@ $label-gap: 4mm; // between a row label and its first code
|
|
|
41
42
|
$label-w: 36mm;
|
|
42
43
|
$section-gap: 0.8mm; // around a divider
|
|
43
44
|
|
|
45
|
+
/* Form / Summary tabs, between the filters and the panels */
|
|
46
|
+
.tabList {
|
|
47
|
+
margin-top: layout.$spacing-05;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Each tab's panel brings its own spacing (the report card, the summary grid) */
|
|
51
|
+
.formPanel,
|
|
52
|
+
.summaryPanel {
|
|
53
|
+
padding: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.summaryPanel {
|
|
57
|
+
margin-top: layout.$spacing-05;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* The card the sheet sits in, drawn like the filter card above it (same rule
|
|
61
|
+
and fill) so the report reads as the second panel of one page.
|
|
62
|
+
It wraps `.viewport` rather than styling it: the page is scaled to the
|
|
63
|
+
viewport's width, so padding there would push the sheet into a scrollbar. */
|
|
64
|
+
.reportFrame {
|
|
65
|
+
margin-top: layout.$spacing-05;
|
|
66
|
+
padding: layout.$spacing-05;
|
|
67
|
+
background-color: $ui-02;
|
|
68
|
+
border: 1px solid $ui-03;
|
|
69
|
+
}
|
|
70
|
+
|
|
44
71
|
/* Holds the fixed-width page without making the app scroll sideways.
|
|
45
72
|
|
|
46
73
|
No padding of its own: vertical padding here is dead space, and horizontal
|
|
@@ -52,17 +79,19 @@ $section-gap: 0.8mm; // around a divider
|
|
|
52
79
|
overflow-x: auto;
|
|
53
80
|
}
|
|
54
81
|
|
|
82
|
+
/* On screen the sheet sits inside `.reportFrame`, whose padding is the margin:
|
|
83
|
+
drawn as a separate shadowed page with its own 8mm margins, it sat further
|
|
84
|
+
in from the card's edge than any other panel's content does. So the screen
|
|
85
|
+
sheet is the printable area only -- A4 less its margins, which `@page` puts
|
|
86
|
+
back for print -- and `usePageScale` is told that width. */
|
|
55
87
|
.form {
|
|
56
88
|
box-sizing: border-box;
|
|
57
|
-
width: $page-w;
|
|
58
|
-
min-height: $page-h;
|
|
59
|
-
padding: $page-margin;
|
|
89
|
+
width: $page-w - 2 * $page-margin;
|
|
60
90
|
margin: 0 auto;
|
|
61
91
|
color: $ink;
|
|
62
92
|
font-size: $text;
|
|
63
93
|
line-height: 1.15;
|
|
64
94
|
background-color: #fff;
|
|
65
|
-
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
|
|
66
95
|
/* Set by `usePageScale` from the measured container width, floored at 1 so
|
|
67
96
|
the sheet is never drawn smaller than the paper. Reset to 1 for print. */
|
|
68
97
|
zoom: var(--page-zoom, 1);
|
|
@@ -428,6 +457,24 @@ $section-gap: 0.8mm; // around a divider
|
|
|
428
457
|
overflow: visible;
|
|
429
458
|
}
|
|
430
459
|
|
|
460
|
+
/* Download PDF prints the form whichever tab is open */
|
|
461
|
+
.tabList,
|
|
462
|
+
.summaryPanel {
|
|
463
|
+
display: none !important;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.formPanel[hidden] {
|
|
467
|
+
display: block !important;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* the card is screen chrome; the printout is the bare sheet */
|
|
471
|
+
.reportFrame {
|
|
472
|
+
margin: 0;
|
|
473
|
+
padding: 0;
|
|
474
|
+
background: none;
|
|
475
|
+
border: none;
|
|
476
|
+
}
|
|
477
|
+
|
|
431
478
|
.form {
|
|
432
479
|
width: auto;
|
|
433
480
|
min-height: 0;
|