@ampath/esm-reports-app 1.0.0-next.79 → 1.0.0-next.80
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/0.css +1 -0
- package/dist/0.css.map +1 -0
- package/dist/0.js +1 -0
- package/dist/0.js.map +1 -0
- package/dist/410.js +1 -1
- package/dist/410.js.map +1 -1
- package/dist/600.js +1 -1
- package/dist/600.js.map +1 -1
- package/dist/757.js +1 -0
- package/dist/757.js.map +1 -0
- package/dist/ampath-esm-reports-app.js +1 -1
- package/dist/ampath-esm-reports-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/common/report-filters/report-filters.scss +15 -6
- package/src/common/report-page/download-sheet-pdf.ts +193 -27
- package/src/common/report-register/report-parents.ts +2 -0
- package/src/dashboard/report-catalog.ts +18 -0
- package/src/registers/moh-267/moh-267-register.component.tsx +407 -0
- package/src/registers/moh-267/moh-267-register.scss +298 -0
- package/src/registers/moh-267/moh-267-summary.ts +102 -0
- package/src/registers/moh-267/moh-267.component.tsx +94 -0
- package/src/registers/moh-267/moh-267.types.ts +47 -0
- package/src/registers/moh-362/moh-362-lab-register.component.tsx +469 -310
- package/src/registers/moh-362/moh-362-lab-register.scss +412 -0
- package/src/registers/moh-362/moh-362-linkage-register.component.tsx +188 -93
- package/src/registers/moh-362/moh-362-linkage-register.scss +91 -0
- package/src/registers/moh-362/moh-362.component.tsx +33 -15
- package/src/registers/moh-362/moh-362.types.ts +15 -25
- package/src/registers/presumptive-tb/presumptive-tb-register.component.tsx +391 -0
- package/src/registers/presumptive-tb/presumptive-tb-register.scss +262 -0
- package/src/registers/presumptive-tb/presumptive-tb.component.tsx +92 -0
- package/src/registers/presumptive-tb/presumptive-tb.types.ts +88 -0
- package/src/registers/register-catalog.ts +37 -3
- package/src/registers/register-file-name.ts +18 -0
- package/src/registers/tb4/tb4-parts.tsx +164 -0
- package/src/registers/tb4/tb4-patient-sheet.component.tsx +418 -0
- package/src/registers/tb4/tb4-register.scss +282 -0
- package/src/registers/tb4/tb4-treatment-sheet.component.tsx +349 -0
- package/src/registers/tb4/tb4.component.tsx +120 -0
- package/src/registers/tb4/tb4.types.ts +129 -0
- package/src/reports/acf-summary/acf-summary-form.component.tsx +176 -0
- package/src/reports/acf-summary/acf-summary-linelist.component.tsx +86 -0
- package/src/reports/acf-summary/acf-summary.component.tsx +97 -0
- package/src/reports/acf-summary/acf-summary.counts.ts +37 -0
- package/src/reports/acf-summary/acf-summary.scss +162 -0
- package/src/reports/moh-729b/moh-729b-form.component.tsx +385 -0
- package/src/reports/moh-729b/moh-729b-linelist.component.tsx +205 -0
- package/src/reports/moh-729b/moh-729b-summary.component.tsx +258 -0
- package/src/reports/moh-729b/moh-729b-summary.config.ts +229 -0
- package/src/reports/moh-729b/moh-729b.component.tsx +157 -0
- package/src/reports/moh-729b/moh-729b.config.ts +235 -0
- package/src/reports/moh-729b/moh-729b.scss +276 -0
- package/src/reports/moh-729b/moh-729b.types.ts +111 -0
- package/src/reports/moh-731/moh-731.component.tsx +10 -7
- package/src/reports/moh-731/moh-731.scss +3 -6
- package/src/reports/moh-731/summary/moh-731-summary.config.ts +2 -4
- package/src/reports/moh-731/summary/moh-731-summary.scss +5 -0
- package/src/resources/moh-267.resource.ts +27 -0
- package/src/resources/moh-729b.resource.ts +25 -0
- package/src/resources/presumptive-tb.resource.ts +27 -0
- package/src/root.component.tsx +14 -0
- package/dist/177.css +0 -1
- package/dist/177.css.map +0 -1
- package/dist/177.js +0 -1
- package/dist/177.js.map +0 -1
- package/dist/580.js +0 -1
- package/dist/580.js.map +0 -1
- package/src/registers/moh-362/moh-362-register.scss +0 -222
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
GenderFemale,
|
|
7
7
|
Growth,
|
|
8
8
|
HealthCross,
|
|
9
|
+
Medication,
|
|
9
10
|
Microscope,
|
|
11
|
+
Stethoscope,
|
|
10
12
|
UserMultiple,
|
|
11
13
|
Warning,
|
|
12
14
|
type CarbonIconType,
|
|
@@ -50,6 +52,14 @@ export const reportCategories: ReportCategory[] = [
|
|
|
50
52
|
icon: HealthCross,
|
|
51
53
|
keywords: ['hiv', 'nascop', 'art', 'prep', 'emtct', 'pmtct', 'tb'],
|
|
52
54
|
},
|
|
55
|
+
{
|
|
56
|
+
code: 'MOH 729B',
|
|
57
|
+
name: 'Facility ARV patient summary (F-MAPS)',
|
|
58
|
+
description: 'Monthly count of current active patients on each ARV and OI regimen.',
|
|
59
|
+
path: '/moh-729b',
|
|
60
|
+
icon: Medication,
|
|
61
|
+
keywords: ['fmaps', 'f-maps', 'arv', 'regimen', 'art', 'pmtct', 'pep', 'prep', 'tpt', 'pharmacy'],
|
|
62
|
+
},
|
|
53
63
|
{
|
|
54
64
|
code: 'MOH 740',
|
|
55
65
|
name: 'Diabetes & hypertension',
|
|
@@ -146,6 +156,14 @@ export const reportCategories: ReportCategory[] = [
|
|
|
146
156
|
icon: Warning,
|
|
147
157
|
keywords: ['idsr', 'surveillance', 'epidemic', 'notifiable', 'outbreak'],
|
|
148
158
|
},
|
|
159
|
+
{
|
|
160
|
+
code: 'MOH/F/DNTLDP/02',
|
|
161
|
+
name: 'TB active case finding summary',
|
|
162
|
+
description: 'Monthly facility summary of TB screening, investigation, diagnosis and treatment by department.',
|
|
163
|
+
path: '/acf-summary',
|
|
164
|
+
icon: Stethoscope,
|
|
165
|
+
keywords: ['tb', 'tuberculosis', 'acf', 'active case finding', 'screening', 'presumptive', 'dntldp'],
|
|
166
|
+
},
|
|
149
167
|
],
|
|
150
168
|
},
|
|
151
169
|
];
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { usePageScale } from '../../common/report-page';
|
|
4
|
+
import { AGE_BANDS, METHODS, moh267Summary, type AgeSexCounts, type Population } from './moh-267-summary';
|
|
5
|
+
import { formDate, text, type Moh267Row } from './moh-267.types';
|
|
6
|
+
import styles from './moh-267-register.scss';
|
|
7
|
+
|
|
8
|
+
interface Moh267RegisterProps {
|
|
9
|
+
rows: Moh267Row[];
|
|
10
|
+
/** the period's last day, for the clients on PrEP at least 3 months */
|
|
11
|
+
endDate: string;
|
|
12
|
+
/** the visits in the calendar month of the period's end, for TOTAL this Month */
|
|
13
|
+
monthVisits: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Rows ruled on the last page, which also holds the summary tables, as on the form */
|
|
17
|
+
const ROWS_ON_LAST_PAGE = 15;
|
|
18
|
+
|
|
19
|
+
/** Rows on every page before it: the summary's space ruled as further rows */
|
|
20
|
+
const ROWS_PER_FULL_PAGE = 22;
|
|
21
|
+
|
|
22
|
+
/** A4 landscape less its 8mm margins: the page as drawn on screen, inside the report card */
|
|
23
|
+
const PAGE_WIDTH_MM = 297 - 2 * 8;
|
|
24
|
+
|
|
25
|
+
const COLUMN_IDS = 'abcdefghijk'.split('');
|
|
26
|
+
|
|
27
|
+
/** Column widths, measured off page 3 of the form, as fractions of the sheet */
|
|
28
|
+
const COLUMN_WIDTHS = [147, 166, 199, 104, 115, 203, 150, 219, 165, 137, 244];
|
|
29
|
+
const COLUMN_TOTAL = COLUMN_WIDTHS.reduce((sum, width) => sum + width, 0);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The summary tables' rows, as each table words them, and the register's
|
|
33
|
+
* population each counts. MSM/MSW are male and FSW female, so the other sex's
|
|
34
|
+
* cells are shaded as on the form.
|
|
35
|
+
*/
|
|
36
|
+
type SummaryRow = { label: string; population: Population | 'TOTAL'; only?: 'M' | 'F' };
|
|
37
|
+
const summaryRows = (pwid: string, vulnerable: string): SummaryRow[] => [
|
|
38
|
+
{ label: 'General popn', population: 'General Population' },
|
|
39
|
+
{ label: 'MSM/MSW', population: 'MSM/MSW', only: 'M' },
|
|
40
|
+
{ label: 'FSW', population: 'FSW', only: 'F' },
|
|
41
|
+
{ label: pwid, population: 'PWID/PWUD' },
|
|
42
|
+
{ label: 'Discordant Couple', population: 'Discordant Couple' },
|
|
43
|
+
{ label: vulnerable, population: 'VP' },
|
|
44
|
+
{ label: 'TOTAL', population: 'TOTAL' },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Full pages of rows, then a last page of at most 15 rows that carries the
|
|
49
|
+
* summary. A full page never takes every remaining row, so the last page always
|
|
50
|
+
* has at least one visit on it.
|
|
51
|
+
*/
|
|
52
|
+
const paginate = (rows: Moh267Row[]) => {
|
|
53
|
+
const pages: Moh267Row[][] = [];
|
|
54
|
+
let start = 0;
|
|
55
|
+
while (rows.length - start > ROWS_ON_LAST_PAGE) {
|
|
56
|
+
const size = Math.min(ROWS_PER_FULL_PAGE, rows.length - start - 1);
|
|
57
|
+
pages.push(rows.slice(start, start + size));
|
|
58
|
+
start += size;
|
|
59
|
+
}
|
|
60
|
+
pages.push(rows.slice(start));
|
|
61
|
+
return pages;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** One visit: two ruled lines, column (c) split into national ID over NUPI */
|
|
65
|
+
const VisitRows: React.FC<{ row?: Moh267Row }> = ({ row }) => (
|
|
66
|
+
<>
|
|
67
|
+
<tr className={styles.upperLine}>
|
|
68
|
+
<td rowSpan={2}>{text(row?.prep_number)}</td>
|
|
69
|
+
<td rowSpan={2}>{formDate(row?.date_of_visit)}</td>
|
|
70
|
+
<td className={styles.upperCell}>{text(row?.id_number)}</td>
|
|
71
|
+
<td rowSpan={2}>{text(row?.age)}</td>
|
|
72
|
+
<td rowSpan={2}>{text(row?.sex)}</td>
|
|
73
|
+
<td rowSpan={2}>{text(row?.population_type)}</td>
|
|
74
|
+
<td rowSpan={2}>{text(row?.prep_status)}</td>
|
|
75
|
+
<td rowSpan={2}>{text(row?.prep_method)}</td>
|
|
76
|
+
<td rowSpan={2}>{text(row?.hiv_result)}</td>
|
|
77
|
+
<td rowSpan={2}>{text(row?.sti_diagnosed)}</td>
|
|
78
|
+
<td rowSpan={2} className={styles.left}>
|
|
79
|
+
<span className={styles.clamp}>{text(row?.remarks)}</span>
|
|
80
|
+
</td>
|
|
81
|
+
</tr>
|
|
82
|
+
<tr className={styles.lowerLine}>
|
|
83
|
+
<td className={styles.lowerCell}>{text(row?.nupi)}</td>
|
|
84
|
+
</tr>
|
|
85
|
+
</>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* A total row's figure: the number of visits -- the page's, or the calendar
|
|
90
|
+
* month's -- in the first column after the label, the rest of the row left
|
|
91
|
+
* ruled and blank
|
|
92
|
+
*/
|
|
93
|
+
const VisitTotals: React.FC<{ visits: number }> = ({ visits }) => (
|
|
94
|
+
<>
|
|
95
|
+
<td>{visits}</td>
|
|
96
|
+
{COLUMN_IDS.slice(4).map((id) => (
|
|
97
|
+
<td key={id} />
|
|
98
|
+
))}
|
|
99
|
+
</>
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
/** An age-band-by-sex summary table: initiated on PrEP, current on PrEP, diagnosed with STI */
|
|
103
|
+
const AgeSexTable: React.FC<{
|
|
104
|
+
title: string;
|
|
105
|
+
corner?: React.ReactNode;
|
|
106
|
+
rows: SummaryRow[];
|
|
107
|
+
counts: AgeSexCounts;
|
|
108
|
+
}> = ({ title, corner, rows, counts }) => (
|
|
109
|
+
<table className={`${styles.summaryTable} ${styles.ageTable}`}>
|
|
110
|
+
<thead>
|
|
111
|
+
<tr>
|
|
112
|
+
<th rowSpan={3} className={styles.rowLabel}>
|
|
113
|
+
{corner}
|
|
114
|
+
</th>
|
|
115
|
+
<th colSpan={9}>{title}</th>
|
|
116
|
+
<th />
|
|
117
|
+
</tr>
|
|
118
|
+
<tr>
|
|
119
|
+
{AGE_BANDS.map((band) => (
|
|
120
|
+
<th key={band.label} colSpan={2}>
|
|
121
|
+
{band.label}
|
|
122
|
+
</th>
|
|
123
|
+
))}
|
|
124
|
+
</tr>
|
|
125
|
+
<tr>
|
|
126
|
+
{AGE_BANDS.map((band) => (
|
|
127
|
+
<React.Fragment key={band.label}>
|
|
128
|
+
<th>M</th>
|
|
129
|
+
<th>F</th>
|
|
130
|
+
</React.Fragment>
|
|
131
|
+
))}
|
|
132
|
+
</tr>
|
|
133
|
+
</thead>
|
|
134
|
+
<tbody>
|
|
135
|
+
{rows.map((population) => (
|
|
136
|
+
<tr key={population.label}>
|
|
137
|
+
<th className={styles.rowLabel}>{population.label}</th>
|
|
138
|
+
{AGE_BANDS.map((band, bandIndex) =>
|
|
139
|
+
(['M', 'F'] as const).map((sex) =>
|
|
140
|
+
population.only && population.only !== sex ? (
|
|
141
|
+
<td key={`${band.label}-${sex}`} className={styles.notApplicable} />
|
|
142
|
+
) : (
|
|
143
|
+
<td key={`${band.label}-${sex}`}>{counts(population.population, bandIndex, sex)}</td>
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
)}
|
|
147
|
+
</tr>
|
|
148
|
+
))}
|
|
149
|
+
</tbody>
|
|
150
|
+
</table>
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
/** The summary tables at the foot of the last page, counting every visit in the register */
|
|
154
|
+
const Summary: React.FC<{ rows: Moh267Row[]; endDate: string }> = ({ rows, endDate }) => {
|
|
155
|
+
const summary = moh267Summary(rows, endDate);
|
|
156
|
+
return (
|
|
157
|
+
<div className={styles.summary}>
|
|
158
|
+
<AgeSexTable
|
|
159
|
+
title="Number initiated (New) on PrEP (g)"
|
|
160
|
+
rows={summaryRows('PWID/PWUD', 'Vulnerable Pop.')}
|
|
161
|
+
counts={summary.initiated}
|
|
162
|
+
/>
|
|
163
|
+
<AgeSexTable
|
|
164
|
+
title="Number Current on PrEP"
|
|
165
|
+
corner={
|
|
166
|
+
<>
|
|
167
|
+
New +<br />
|
|
168
|
+
Refill +<br />
|
|
169
|
+
Restart
|
|
170
|
+
</>
|
|
171
|
+
}
|
|
172
|
+
rows={summaryRows('PWID', 'VP')}
|
|
173
|
+
counts={summary.current}
|
|
174
|
+
/>
|
|
175
|
+
<AgeSexTable
|
|
176
|
+
title="Number diagnosed with STI (j)"
|
|
177
|
+
rows={summaryRows('PWID', 'Vulnerable Pop.')}
|
|
178
|
+
counts={summary.sti}
|
|
179
|
+
/>
|
|
180
|
+
|
|
181
|
+
<div className={styles.methodColumn}>
|
|
182
|
+
<table className={`${styles.summaryTable} ${styles.methodTable}`}>
|
|
183
|
+
<thead>
|
|
184
|
+
<tr>
|
|
185
|
+
<th rowSpan={2} className={styles.rowLabel}>
|
|
186
|
+
Indicator/
|
|
187
|
+
<br />
|
|
188
|
+
PrEP method
|
|
189
|
+
</th>
|
|
190
|
+
<th colSpan={5}>Number of Clients on each PrEP method (h)</th>
|
|
191
|
+
</tr>
|
|
192
|
+
<tr>
|
|
193
|
+
<th>
|
|
194
|
+
Event
|
|
195
|
+
<br />
|
|
196
|
+
Driven
|
|
197
|
+
</th>
|
|
198
|
+
<th>
|
|
199
|
+
Daily
|
|
200
|
+
<br />
|
|
201
|
+
Oral
|
|
202
|
+
</th>
|
|
203
|
+
<th>
|
|
204
|
+
Dapivirine
|
|
205
|
+
<br />
|
|
206
|
+
Vaginal
|
|
207
|
+
</th>
|
|
208
|
+
<th>
|
|
209
|
+
Cabotegravir
|
|
210
|
+
<br />
|
|
211
|
+
injectable
|
|
212
|
+
</th>
|
|
213
|
+
<th>Total</th>
|
|
214
|
+
</tr>
|
|
215
|
+
</thead>
|
|
216
|
+
<tbody>
|
|
217
|
+
{summary.methods.map((indicator) => (
|
|
218
|
+
<tr key={indicator.label}>
|
|
219
|
+
<th className={styles.rowLabel}>{indicator.label}</th>
|
|
220
|
+
{METHODS.map((method) => (
|
|
221
|
+
<td key={method}>{indicator.count(method)}</td>
|
|
222
|
+
))}
|
|
223
|
+
{/* every method, Lenacapavir included, which has no column of its own */}
|
|
224
|
+
<td>{indicator.count('Total')}</td>
|
|
225
|
+
</tr>
|
|
226
|
+
))}
|
|
227
|
+
</tbody>
|
|
228
|
+
</table>
|
|
229
|
+
|
|
230
|
+
<table className={`${styles.summaryTable} ${styles.seroconverting}`}>
|
|
231
|
+
<tbody>
|
|
232
|
+
<tr>
|
|
233
|
+
<th>Number Seroconverting while on PrEP (i)</th>
|
|
234
|
+
<td>{summary.seroconverted}</td>
|
|
235
|
+
</tr>
|
|
236
|
+
</tbody>
|
|
237
|
+
</table>
|
|
238
|
+
</div>
|
|
239
|
+
</div>
|
|
240
|
+
);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* One A4 landscape page of the register. Pages before the last are ruled with
|
|
245
|
+
* visits and their page total; the last has 15 rows, the page and month
|
|
246
|
+
* totals, and the summary tables beneath, in one frame.
|
|
247
|
+
*/
|
|
248
|
+
const RegisterPage: React.FC<{
|
|
249
|
+
rows: Moh267Row[];
|
|
250
|
+
page: number;
|
|
251
|
+
pages: number;
|
|
252
|
+
scale: number;
|
|
253
|
+
/** every visit in the register and the period's end, given only to the last page */
|
|
254
|
+
summary?: { rows: Moh267Row[]; endDate: string; monthVisits: number };
|
|
255
|
+
}> = ({ rows, page, pages, scale, summary }) => {
|
|
256
|
+
const isLast = summary !== undefined;
|
|
257
|
+
return (
|
|
258
|
+
<section className={styles.page} data-register-page style={{ '--page-zoom': scale } as React.CSSProperties}>
|
|
259
|
+
<div className={styles.runningHead}>
|
|
260
|
+
<span>Ministry Of Health</span>
|
|
261
|
+
<span>MOH 267 PrEP Daily Activity Register</span>
|
|
262
|
+
<span>Ver. July 2023</span>
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<div className={isLast ? `${styles.frame} ${styles.lastFrame}` : styles.frame}>
|
|
266
|
+
<table className={styles.register}>
|
|
267
|
+
<colgroup>
|
|
268
|
+
{COLUMN_WIDTHS.map((width, index) => (
|
|
269
|
+
<col key={index} style={{ width: `${(width / COLUMN_TOTAL) * 100}%` }} />
|
|
270
|
+
))}
|
|
271
|
+
</colgroup>
|
|
272
|
+
<thead>
|
|
273
|
+
<tr className={styles.headings}>
|
|
274
|
+
<th>PrEP No</th>
|
|
275
|
+
<th>Date of Visit</th>
|
|
276
|
+
<th className={styles.splitHeader}>
|
|
277
|
+
<div className={styles.splitStack}>
|
|
278
|
+
<span>National Identification Number</span>
|
|
279
|
+
<span>National Unique Patient Identifier (NUPI)</span>
|
|
280
|
+
</div>
|
|
281
|
+
</th>
|
|
282
|
+
<th>Age</th>
|
|
283
|
+
<th>
|
|
284
|
+
Sex
|
|
285
|
+
<br />
|
|
286
|
+
(M/F)
|
|
287
|
+
</th>
|
|
288
|
+
<th className={styles.codeHeading}>
|
|
289
|
+
<strong>Population type</strong>
|
|
290
|
+
<br />
|
|
291
|
+
(Use the codes):
|
|
292
|
+
<br />
|
|
293
|
+
1. General Population
|
|
294
|
+
<br />
|
|
295
|
+
2. Discordant Couple
|
|
296
|
+
<br />
|
|
297
|
+
3. MSM/MSW
|
|
298
|
+
<br />
|
|
299
|
+
4. FSW
|
|
300
|
+
<br />
|
|
301
|
+
5. PWID/PWUD
|
|
302
|
+
<br />
|
|
303
|
+
6. VP
|
|
304
|
+
</th>
|
|
305
|
+
<th className={styles.codeHeading}>
|
|
306
|
+
<strong>Client PrEP Status:</strong>
|
|
307
|
+
<br />
|
|
308
|
+
<strong>N</strong>- New
|
|
309
|
+
<br />
|
|
310
|
+
<strong>C</strong>- Continuing
|
|
311
|
+
<br />
|
|
312
|
+
<strong>D</strong>-Discontinued
|
|
313
|
+
<br />
|
|
314
|
+
<strong>R</strong>-Restart
|
|
315
|
+
</th>
|
|
316
|
+
<th className={styles.codeHeading}>
|
|
317
|
+
<strong>PrEP Method:</strong>
|
|
318
|
+
<br />
|
|
319
|
+
<strong>1.</strong> Daily oral PrEP
|
|
320
|
+
<br />
|
|
321
|
+
<strong>2.</strong> Event driven oral PrEP
|
|
322
|
+
<br />
|
|
323
|
+
<strong>3.</strong> Dapivirine Vaginal ring
|
|
324
|
+
<br />
|
|
325
|
+
<strong>4.</strong> Cabotegravir Injectable
|
|
326
|
+
</th>
|
|
327
|
+
<th>
|
|
328
|
+
HIV Results
|
|
329
|
+
<br />
|
|
330
|
+
<span className={styles.codes}>(N/P/Ic/NA)</span>
|
|
331
|
+
</th>
|
|
332
|
+
<th>
|
|
333
|
+
Diagnosed with
|
|
334
|
+
<br />
|
|
335
|
+
STI
|
|
336
|
+
<br />
|
|
337
|
+
<br />
|
|
338
|
+
<span className={styles.codes}>(N/Y)</span>
|
|
339
|
+
</th>
|
|
340
|
+
<th>Remarks</th>
|
|
341
|
+
</tr>
|
|
342
|
+
<tr className={styles.columnIds}>
|
|
343
|
+
{COLUMN_IDS.map((id) => (
|
|
344
|
+
<th key={id}>({id})</th>
|
|
345
|
+
))}
|
|
346
|
+
</tr>
|
|
347
|
+
</thead>
|
|
348
|
+
<tbody>
|
|
349
|
+
{Array.from({ length: isLast ? ROWS_ON_LAST_PAGE : ROWS_PER_FULL_PAGE }, (_, index) => (
|
|
350
|
+
<VisitRows key={index} row={rows[index]} />
|
|
351
|
+
))}
|
|
352
|
+
<tr className={styles.totalRow}>
|
|
353
|
+
<th colSpan={3} className={styles.left}>
|
|
354
|
+
TOTAL this Page
|
|
355
|
+
</th>
|
|
356
|
+
<VisitTotals visits={rows.length} />
|
|
357
|
+
</tr>
|
|
358
|
+
{isLast && (
|
|
359
|
+
<tr className={styles.totalRow}>
|
|
360
|
+
<th colSpan={3} className={styles.left}>
|
|
361
|
+
TOTAL this Month
|
|
362
|
+
</th>
|
|
363
|
+
<VisitTotals visits={summary.monthVisits} />
|
|
364
|
+
</tr>
|
|
365
|
+
)}
|
|
366
|
+
</tbody>
|
|
367
|
+
</table>
|
|
368
|
+
|
|
369
|
+
{summary && <Summary rows={summary.rows} endDate={summary.endDate} />}
|
|
370
|
+
</div>
|
|
371
|
+
|
|
372
|
+
<div className={styles.pageFoot}>
|
|
373
|
+
<span>
|
|
374
|
+
Page {page} of {pages}
|
|
375
|
+
</span>
|
|
376
|
+
<span>Ver. July 2023</span>
|
|
377
|
+
</div>
|
|
378
|
+
</section>
|
|
379
|
+
);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* MOH 267 PrEP DAILY ACTIVITY REGISTER (Ver. July 2023), page 3 of the form,
|
|
384
|
+
* as A4 landscape pages of visits, columns (a) to (k). The summary tables sum
|
|
385
|
+
* the whole register, so they appear once, at the foot of the last page.
|
|
386
|
+
*/
|
|
387
|
+
const Moh267Register: React.FC<Moh267RegisterProps> = ({ rows, endDate, monthVisits }) => {
|
|
388
|
+
const { ref, scale } = usePageScale<HTMLDivElement>(PAGE_WIDTH_MM);
|
|
389
|
+
const pages = paginate(rows);
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<div className={styles.viewport} ref={ref}>
|
|
393
|
+
{pages.map((pageRows, index) => (
|
|
394
|
+
<RegisterPage
|
|
395
|
+
key={index}
|
|
396
|
+
rows={pageRows}
|
|
397
|
+
page={index + 1}
|
|
398
|
+
pages={pages.length}
|
|
399
|
+
scale={scale}
|
|
400
|
+
summary={index === pages.length - 1 ? { rows, endDate, monthVisits } : undefined}
|
|
401
|
+
/>
|
|
402
|
+
))}
|
|
403
|
+
</div>
|
|
404
|
+
);
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
export default Moh267Register;
|