@ampath/esm-reports-app 1.0.0-next.8 → 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/197.js +1 -1
- package/dist/282.js +1 -1
- package/dist/282.js.map +1 -1
- package/dist/295.css +1 -0
- package/dist/295.css.map +1 -0
- package/dist/295.js +1 -0
- package/dist/295.js.map +1 -0
- package/dist/299.js +2 -0
- package/dist/299.js.LICENSE.txt +3 -0
- package/dist/299.js.map +1 -0
- package/dist/300.js +1 -1
- package/dist/311.js +1 -1
- package/dist/311.js.map +1 -1
- package/dist/335.js +1 -1
- package/dist/353.js +1 -1
- package/dist/353.js.map +1 -1
- package/dist/354.js +2 -0
- package/dist/354.js.LICENSE.txt +20 -0
- package/dist/354.js.map +1 -0
- package/dist/410.js +1 -0
- package/dist/410.js.map +1 -0
- package/dist/457.js +2 -0
- package/dist/457.js.LICENSE.txt +261 -0
- package/dist/457.js.map +1 -0
- package/dist/478.js +1 -1
- package/dist/478.js.map +1 -1
- package/dist/480.js +1 -0
- package/dist/540.js +1 -1
- package/dist/540.js.map +1 -1
- package/dist/55.js +1 -1
- package/dist/600.js +2 -0
- package/dist/600.js.LICENSE.txt +35 -0
- package/dist/600.js.map +1 -0
- package/dist/652.js +1 -1
- package/dist/757.js +1 -0
- package/dist/757.js.map +1 -0
- package/dist/781.js +1 -0
- package/dist/781.js.map +1 -0
- package/dist/961.js +1 -1
- package/dist/961.js.map +1 -1
- package/dist/99.js +1 -1
- package/dist/99.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 +4 -2
- 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-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 +317 -99
- package/src/common/report-filters/report-filters.scss +264 -32
- package/src/common/report-filters/types.ts +79 -0
- package/src/common/report-filters/use-restore-period.ts +43 -0
- package/src/common/report-header/index.ts +1 -0
- package/src/common/report-header/use-location-details.ts +58 -0
- package/src/common/report-page/download-sheet-pdf.ts +225 -0
- package/src/common/report-page/index.ts +3 -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 +60 -0
- package/src/common/report-placeholder/has-report-data.ts +15 -0
- package/src/common/report-placeholder/index.ts +3 -0
- package/src/common/report-placeholder/report-placeholder.component.tsx +81 -0
- package/src/common/report-placeholder/report-placeholder.scss +48 -0
- package/src/common/report-placeholder/use-generated-location.ts +62 -0
- package/src/common/report-register/index.ts +6 -0
- package/src/common/report-register/register-columns.ts +46 -0
- package/src/common/report-register/register-layout.component.tsx +265 -0
- package/src/common/report-register/register-layout.scss +150 -0
- package/src/common/report-register/register-table.scss +71 -0
- package/src/common/report-register/report-parents.ts +29 -0
- package/src/common/report-register/rows-to-csv.ts +89 -0
- package/src/common/report-register/use-location-name.ts +54 -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 +191 -0
- package/src/dashboard/reports-dasboard.tsx +189 -18
- package/src/dashboard/reports-dashboard.module.scss +357 -14
- package/src/index.ts +13 -1
- package/src/registers/moh-240/moh-240-register.scss +41 -0
- package/src/registers/moh-240/moh-240.component.test.tsx +166 -0
- package/src/registers/moh-240/moh-240.component.tsx +164 -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 +551 -0
- package/src/registers/moh-362/moh-362-lab-register.scss +412 -0
- package/src/registers/moh-362/moh-362-linkage-register.component.tsx +215 -0
- package/src/registers/moh-362/moh-362-linkage-register.scss +91 -0
- package/src/registers/moh-362/moh-362.component.tsx +117 -0
- package/src/registers/moh-362/moh-362.scss +11 -0
- package/src/registers/moh-362/moh-362.types.ts +87 -0
- 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 +202 -0
- package/src/registers/register-file-name.ts +18 -0
- package/src/registers/tb-lab-register/tb-lab-register-table.component.tsx +116 -0
- package/src/registers/tb-lab-register/tb-lab-register-table.scss +123 -0
- package/src/registers/tb-lab-register/tb-lab-register.columns.ts +164 -0
- package/src/registers/tb-lab-register/tb-lab-register.component.test.tsx +232 -0
- package/src/registers/tb-lab-register/tb-lab-register.component.tsx +153 -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/datatable-wrapper/datatable-wrapper.component.tsx +63 -48
- package/src/reports/moh-240/moh-240-header.component.tsx +62 -0
- package/src/reports/moh-240/moh-240.columns.ts +113 -0
- package/src/reports/moh-240/moh-240.component.tsx +72 -9
- package/src/reports/moh-240/moh-240.scss +40 -0
- package/src/reports/moh-240/sub-reports/moh-240-register.component.tsx +31 -37
- package/src/reports/moh-240/sub-reports/page-summary.component.tsx +143 -106
- package/src/reports/moh-505/moh-505-header.component.tsx +67 -0
- package/src/reports/moh-505/moh-505.component.tsx +441 -0
- package/src/reports/moh-505/moh-505.scss +117 -0
- package/src/reports/moh-705B/moh-204b-register.component.tsx +246 -0
- package/src/reports/moh-705B/moh-204b.columns.ts +39 -0
- package/src/reports/moh-705B/moh-705b.component.tsx +659 -0
- package/src/reports/moh-705B/moh-705b.scss +172 -0
- package/src/reports/moh-705a/moh-705a.component.tsx +661 -0
- package/src/reports/moh-705a/moh-705a.scss +172 -0
- package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +331 -0
- package/src/reports/moh-705a/registers/moh-204a.columns.ts +57 -0
- package/src/reports/moh-705a/type.ts +6 -0
- package/src/reports/moh-706/moh-706-header.component.tsx +66 -0
- package/src/reports/moh-706/moh-706.component.tsx +150 -24
- package/src/reports/moh-706/moh-706.scss +119 -11
- package/src/reports/moh-706/sub-reports/bacteriology/bacteriology.component.tsx +35 -28
- package/src/reports/moh-706/sub-reports/blood-chemistry/blood-chemistry.component.tsx +229 -305
- package/src/reports/moh-706/sub-reports/haematology/haematology.component.tsx +26 -19
- package/src/reports/moh-706/sub-reports/histology-and-cytology/histology-and-cytology.component.tsx +23 -23
- package/src/reports/moh-706/sub-reports/parasitology/parasitology.component.tsx +25 -18
- package/src/reports/moh-706/sub-reports/serology/serology.component.tsx +21 -14
- package/src/reports/moh-706/sub-reports/specimen-referral-to-higher-levels/specimen-referral-to-higher-levels.component.tsx +2 -2
- package/src/reports/moh-706/sub-reports/urine-analysis/urine-analysis.component.tsx +27 -20
- package/src/reports/moh-710/moh-710.component.tsx +815 -632
- package/src/reports/moh-710/moh-710.scss +142 -21
- package/src/reports/moh-710/registers/moh-413/moh-413-columns.ts +22 -0
- package/src/reports/moh-710/registers/moh-413/moh-413.component.tsx +140 -0
- package/src/reports/moh-710/registers/moh-413/moh-413.scss +64 -0
- package/src/reports/moh-710/registers/moh-510/moh-510.columns.ts +40 -0
- package/src/reports/moh-710/registers/moh-510/moh-510.component.tsx +191 -0
- package/src/reports/moh-710/registers/moh-510/moh-510.scss +130 -0
- package/src/reports/moh-710/registers/moh-511-710-register.component.tsx +268 -0
- package/src/reports/moh-710/registers/moh-511-710.columns.ts +52 -0
- package/src/reports/moh-710/registers/type.ts +31 -0
- package/src/reports/moh-711/moh-711.component.tsx +153 -1269
- package/src/reports/moh-711/moh711.scss +135 -20
- package/src/reports/moh-711/registers/moh-333-register.component.tsx +680 -0
- package/src/reports/moh-711/registers/moh-333.columns.ts +119 -0
- package/src/reports/moh-711/registers/moh-405-register.component.tsx +566 -0
- package/src/reports/moh-711/registers/moh-405.columns.ts +120 -0
- package/src/reports/moh-711/registers/moh-406-register.component.tsx +581 -0
- package/src/reports/moh-711/registers/moh-406.columns.ts +133 -0
- package/src/reports/moh-711/registers/moh-407-register.component.tsx +157 -0
- package/src/reports/moh-711/registers/moh-407.columns.ts +24 -0
- package/src/reports/moh-711/registers/moh-407.scss +64 -0
- package/src/reports/moh-711/registers/moh-510-register.component.tsx +55 -0
- package/src/reports/moh-711/registers/moh-511-register.component.tsx +270 -0
- package/src/reports/moh-711/registers/moh-511.columns.ts +59 -0
- package/src/reports/moh-711/registers/moh-512-columns.ts +94 -0
- package/src/reports/moh-711/registers/moh-512.component.tsx +191 -0
- package/src/reports/moh-711/registers/moh-512.scss +64 -0
- package/src/reports/moh-711/registers/tb-register-columns.ts +17 -0
- package/src/reports/moh-711/registers/tb-register.component.tsx +96 -0
- package/src/reports/moh-711/registers/tb-register.scss +64 -0
- package/src/reports/moh-711/registers/type.ts +192 -0
- package/src/reports/moh-711/sections/anc.component.tsx +159 -0
- package/src/reports/moh-711/sections/cervical-cancer.component.tsx +148 -0
- package/src/reports/moh-711/sections/chanis.component.tsx +389 -0
- package/src/reports/moh-711/sections/family-planning.component.tsx +299 -0
- package/src/reports/moh-711/sections/gbv.component.tsx +115 -0
- package/src/reports/moh-711/sections/maternity.component.tsx +321 -0
- package/src/reports/moh-711/sections/medical-social-work.component.tsx +73 -0
- package/src/reports/moh-711/sections/other.component.tsx +47 -0
- package/src/reports/moh-711/sections/physiotherapy.component.tsx +61 -0
- package/src/reports/moh-711/sections/pnc.component.tsx +127 -0
- package/src/reports/moh-711/sections/post-abortion.component.tsx +42 -0
- package/src/reports/moh-711/sections/rehabilitation.component.tsx +57 -0
- package/src/reports/moh-711/sections/report-compiled-by.component.tsx +50 -0
- package/src/reports/moh-711/sections/tb-screening.component.tsx +94 -0
- package/src/reports/moh-717/moh-717.component.tsx +149 -985
- package/src/reports/moh-717/moh717.scss +217 -21
- package/src/reports/moh-717/registers/nutrition-register.component.tsx +48 -0
- package/src/reports/moh-717/sections/finance.component.tsx +42 -0
- package/src/reports/moh-717/sections/inpatient.component.tsx +374 -0
- package/src/reports/moh-717/sections/maternity.component.tsx +126 -0
- package/src/reports/moh-717/sections/medical-records.component.tsx +35 -0
- package/src/reports/moh-717/sections/mortuary.component.tsx +43 -0
- package/src/reports/moh-717/sections/operations.component.tsx +53 -0
- package/src/reports/moh-717/sections/orthopaedic-trauma.component.tsx +98 -0
- package/src/reports/moh-717/sections/outpatient.component.tsx +597 -0
- package/src/reports/moh-717/sections/pharmacy.component.tsx +43 -0
- package/src/reports/moh-717/sections/preparedby.component.tsx +52 -0
- package/src/reports/moh-717/sections/special-services.component.tsx +114 -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/linelist/moh-731-indicators.ts +1122 -0
- package/src/reports/moh-731/linelist/moh-731-linelist-sections.ts +472 -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 +269 -0
- package/src/reports/moh-731/moh-731.scss +496 -0
- package/src/reports/moh-731/registers/moh-366.columns.ts +38 -0
- package/src/reports/moh-731/registers/moh-366.component.tsx +471 -0
- package/src/reports/moh-731/registers/prep-register.component.tsx +284 -0
- package/src/reports/moh-731/registers/prep.columns.ts +34 -0
- package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +1206 -0
- package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +727 -0
- package/src/reports/moh-731/sections/pmtct.component.tsx +572 -0
- package/src/reports/moh-731/summary/moh-731-summary.component.tsx +313 -0
- package/src/reports/moh-731/summary/moh-731-summary.config.ts +527 -0
- package/src/reports/moh-731/summary/moh-731-summary.scss +247 -0
- package/src/reports/moh-740/moh-740.component.scss +202 -0
- package/src/reports/moh-740/moh-740.component.tsx +1332 -0
- package/src/reports/moh-740/moh-740.resource.ts +54 -0
- package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.tsx +149 -0
- package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.tsx +123 -0
- package/src/reports/moh-740/registers/moh-740-patient-list.scss +0 -0
- package/src/reports/moh-740/registers/moh-740-patient-list.tsx +60 -0
- package/src/reports/moh-740/registers/moh-740.columns.ts +54 -0
- package/src/reports/moh-740/shared/data-cell/data-cell.scss +6 -0
- package/src/reports/moh-740/shared/data-cell/data-cell.tsx +23 -0
- package/src/reports/moh-740/shared/utils/indicator-register-map.ts +159 -0
- package/src/reports/moh-740/types/index.ts +223 -0
- package/src/reports/moh-745/moh-745.component.tsx +2058 -0
- package/src/reports/moh-745/moh-745.scss +142 -0
- package/src/reports/moh-745/registers/moh-412-register.component.tsx +249 -0
- package/src/reports/moh-745/registers/moh-412.columns.ts +52 -0
- package/src/reports/moh-745/registers/type.ts +223 -0
- package/src/reports/table-wrapper/table-row-mapper.component.tsx +20 -5
- 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-267.resource.ts +27 -0
- package/src/resources/moh-362.resource.ts +27 -0
- package/src/resources/moh-505.resource.ts +69 -0
- package/src/resources/moh-705.resource.ts +118 -0
- package/src/resources/moh-706.resource.ts +80 -0
- package/src/resources/moh-710.resource.ts +60 -9
- package/src/resources/moh-711.resource.ts +206 -9
- package/src/resources/moh-717.resource.ts +26 -9
- package/src/resources/moh-729b.resource.ts +25 -0
- package/src/resources/moh-731.resource.ts +90 -0
- package/src/resources/moh-745.resource.ts +76 -0
- package/src/resources/patient-list-page.ts +66 -0
- package/src/resources/presumptive-tb.resource.ts +27 -0
- package/src/root.component.tsx +79 -8
- package/src/root.scss +36 -0
- package/src/routes.json +3 -1
- package/src/utils/format-indicator.ts +39 -0
- package/src/utils/get-base-url.ts +39 -7
- package/src/utils/utils.ts +30 -1
- package/tsconfig.json +1 -1
- package/webpack.config.js +22 -1
- package/dist/138.js +0 -2
- package/dist/138.js.LICENSE.txt +0 -20
- package/dist/138.js.map +0 -1
- package/dist/184.js +0 -2
- package/dist/184.js.LICENSE.txt +0 -14
- package/dist/184.js.map +0 -1
- package/dist/205.js +0 -1
- package/dist/205.js.map +0 -1
- package/dist/812.js +0 -1
- package/dist/812.js.map +0 -1
- package/dist/879.js +0 -1
- package/dist/879.js.map +0 -1
- package/dist/ampath-esm-reports-app.js.buildmanifest.json +0 -539
- package/dist/main.js +0 -1
- package/dist/main.js.map +0 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
|
|
4
|
+
import { usePageScale } from '../../common/report-page';
|
|
5
|
+
import { COUNTED_DEPARTMENT } from './acf-summary.counts';
|
|
6
|
+
import styles from './acf-summary.scss';
|
|
7
|
+
|
|
8
|
+
/** A4 landscape less its 8mm margins: the page as drawn on screen, inside the report card */
|
|
9
|
+
const PAGE_WIDTH_MM = 297 - 2 * 8;
|
|
10
|
+
|
|
11
|
+
/** The form's measuring unit (row heights below) in millimetres */
|
|
12
|
+
const MM_PER_UNIT = 0.227;
|
|
13
|
+
const height = (units: number): React.CSSProperties => ({ height: `${units * MM_PER_UNIT}mm` });
|
|
14
|
+
|
|
15
|
+
/** The departments across the top, then Total; widths measured off the form */
|
|
16
|
+
const DEPARTMENTS: Array<[string, number]> = [
|
|
17
|
+
['OPD', 44],
|
|
18
|
+
['TB / Chest Clinic', 48],
|
|
19
|
+
['Maternity', 68],
|
|
20
|
+
['Medical ward', 73],
|
|
21
|
+
['Surgical ward', 77],
|
|
22
|
+
['Pediatric Ward', 82],
|
|
23
|
+
['CCC', 45],
|
|
24
|
+
['Radiology', 71],
|
|
25
|
+
['HTS', 42],
|
|
26
|
+
['Nutrition', 65],
|
|
27
|
+
['Diabtes', 67],
|
|
28
|
+
['Eye Clinic', 49],
|
|
29
|
+
['ENT clinic', 54],
|
|
30
|
+
['Dental clinic', 65],
|
|
31
|
+
['Laboratory', 82],
|
|
32
|
+
['Other departments', 89],
|
|
33
|
+
['Total', 49],
|
|
34
|
+
];
|
|
35
|
+
const LABEL_WIDTH = 138;
|
|
36
|
+
const TOTAL_WIDTH = DEPARTMENTS.reduce((sum, [, width]) => sum + width, LABEL_WIDTH);
|
|
37
|
+
const percent = (width: number) => `${(width / TOTAL_WIDTH) * 100}%`;
|
|
38
|
+
|
|
39
|
+
/** The indicators down the side, each with its row height as printed */
|
|
40
|
+
const INDICATORS: Array<[string, number]> = [
|
|
41
|
+
['1. Workload', 25],
|
|
42
|
+
['2. Number of people screened for TB', 48],
|
|
43
|
+
['3. Number of people with respiratory conditions', 58],
|
|
44
|
+
['4. Number of presumptive TB cases investigated for TB disease', 69],
|
|
45
|
+
['5. Number of presumptive TB cases diagnosed with TB', 73],
|
|
46
|
+
['6. Number of presumptive cases Bact.confirmed with TB', 84],
|
|
47
|
+
['7. Number of presumptive cases diagnosed with TB clinically', 85],
|
|
48
|
+
['8. Number of diagnosed TB cases initiated on treatment', 73],
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
/** A count on the form, opening the linelist of its cases when clicked; blank where there is none */
|
|
52
|
+
const Count: React.FC<{ value?: number; onOpen?: () => void }> = ({ value, onOpen }) =>
|
|
53
|
+
value === undefined || !onOpen ? (
|
|
54
|
+
<td className={styles.count} />
|
|
55
|
+
) : (
|
|
56
|
+
<td
|
|
57
|
+
className={`${styles.count} ${styles.clickable}`}
|
|
58
|
+
title="Click to open linelist"
|
|
59
|
+
role="button"
|
|
60
|
+
tabIndex={0}
|
|
61
|
+
onClick={onOpen}
|
|
62
|
+
onKeyDown={(event) => (event.key === 'Enter' || event.key === ' ') && onOpen()}
|
|
63
|
+
>
|
|
64
|
+
{value}
|
|
65
|
+
</td>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
/** A label and the ruled line it is written on */
|
|
69
|
+
const Field: React.FC<{ label: string; value?: string; wide?: boolean }> = ({ label, value, wide }) => (
|
|
70
|
+
<span className={styles.field}>
|
|
71
|
+
{label}:<span className={wide ? styles.wideLine : styles.line}>{value}</span>
|
|
72
|
+
</span>
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
interface AcfSummaryFormProps {
|
|
76
|
+
facility: string;
|
|
77
|
+
/** Any date in the reporting month */
|
|
78
|
+
month: string;
|
|
79
|
+
/** The counts by indicator number, for the TB / Chest Clinic and the Total;
|
|
80
|
+
an indicator without one is left blank */
|
|
81
|
+
counts?: Record<number, number>;
|
|
82
|
+
/** Opens the linelist of an indicator's cases */
|
|
83
|
+
onOpen?: (indicator: number) => void;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Summary Tool for Facility-Based Active Case Finding (MOH/F/DNTLDP/02,
|
|
88
|
+
* February 2023): page 2 of the tool as one A4 landscape sheet -- the eight ACF
|
|
89
|
+
* indicators by department, with a Total column.
|
|
90
|
+
*
|
|
91
|
+
* Indicators 4 to 8 are counted from the Presumptive TB Register's cases (its
|
|
92
|
+
* TB assessment encounters), under the TB / Chest Clinic and so the Total;
|
|
93
|
+
* workload (1, from MOH 717), screened (2) and respiratory conditions (3) and
|
|
94
|
+
* the other departments are blank until their queries are added.
|
|
95
|
+
*/
|
|
96
|
+
const AcfSummaryForm: React.FC<AcfSummaryFormProps> = ({ facility, month, counts = {}, onOpen }) => {
|
|
97
|
+
const { ref, scale } = usePageScale<HTMLDivElement>(PAGE_WIDTH_MM);
|
|
98
|
+
const date = month ? dayjs(month) : undefined;
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className={styles.viewport} ref={ref}>
|
|
102
|
+
<section className={styles.page} data-register-page style={{ '--page-zoom': scale } as React.CSSProperties}>
|
|
103
|
+
<h2 className={styles.title}>Summary Tool for Facility-Based Active Case Finding</h2>
|
|
104
|
+
|
|
105
|
+
<div className={styles.fields}>
|
|
106
|
+
<Field label="County" />
|
|
107
|
+
<Field label="Sub County" />
|
|
108
|
+
<Field label="Health Facility" value={facility} wide />
|
|
109
|
+
</div>
|
|
110
|
+
<div className={styles.fields}>
|
|
111
|
+
<Field label="Month" value={date?.format('MMMM')} />
|
|
112
|
+
<Field label="Year" value={date?.format('YYYY')} />
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<table className={styles.grid}>
|
|
116
|
+
<colgroup>
|
|
117
|
+
<col style={{ width: percent(LABEL_WIDTH) }} />
|
|
118
|
+
{DEPARTMENTS.map(([name, width]) => (
|
|
119
|
+
<col key={name} style={{ width: percent(width) }} />
|
|
120
|
+
))}
|
|
121
|
+
</colgroup>
|
|
122
|
+
<thead>
|
|
123
|
+
<tr style={height(50)}>
|
|
124
|
+
<th />
|
|
125
|
+
{DEPARTMENTS.map(([name]) => (
|
|
126
|
+
<th key={name}>{name}</th>
|
|
127
|
+
))}
|
|
128
|
+
</tr>
|
|
129
|
+
</thead>
|
|
130
|
+
<tbody>
|
|
131
|
+
{INDICATORS.map(([indicator, rowHeight], index) => (
|
|
132
|
+
<tr key={indicator} style={height(rowHeight)}>
|
|
133
|
+
<th scope="row">{indicator}</th>
|
|
134
|
+
{DEPARTMENTS.map(([name]) => (
|
|
135
|
+
<Count
|
|
136
|
+
key={name}
|
|
137
|
+
value={name === COUNTED_DEPARTMENT || name === 'Total' ? counts[index + 1] : undefined}
|
|
138
|
+
onOpen={onOpen && (() => onOpen(index + 1))}
|
|
139
|
+
/>
|
|
140
|
+
))}
|
|
141
|
+
</tr>
|
|
142
|
+
))}
|
|
143
|
+
</tbody>
|
|
144
|
+
</table>
|
|
145
|
+
|
|
146
|
+
<div className={styles.signOff}>
|
|
147
|
+
<span>
|
|
148
|
+
Prepared by
|
|
149
|
+
<span className={styles.dots} />
|
|
150
|
+
</span>
|
|
151
|
+
<span>
|
|
152
|
+
Signature
|
|
153
|
+
<span className={styles.dots} />
|
|
154
|
+
</span>
|
|
155
|
+
<span>
|
|
156
|
+
Date
|
|
157
|
+
<span className={styles.dots} />
|
|
158
|
+
</span>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div className={styles.instructions}>
|
|
162
|
+
<strong>Instructions</strong>:
|
|
163
|
+
<ol>
|
|
164
|
+
<li>
|
|
165
|
+
Workload- Information to be obtained from MOH 717
|
|
166
|
+
<br />
|
|
167
|
+
Summarize indicators 2-6 from departmental ACF summary tools
|
|
168
|
+
</li>
|
|
169
|
+
</ol>
|
|
170
|
+
</div>
|
|
171
|
+
</section>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export default AcfSummaryForm;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useSearchParams } from 'react-router-dom';
|
|
3
|
+
|
|
4
|
+
import { type LinelistColumn, LinelistTable, useAllRows } from '../../common/linelist-table';
|
|
5
|
+
import { RegisterLayout, useLocationName } from '../../common/report-register';
|
|
6
|
+
import { getPresumptiveTb } from '../../resources/presumptive-tb.resource';
|
|
7
|
+
import { ACF_INDICATORS, type AcfCase } from './acf-summary.counts';
|
|
8
|
+
|
|
9
|
+
const formatDate = (value: unknown) => (value ? new Date(String(value)).toLocaleDateString('en-GB') : '');
|
|
10
|
+
|
|
11
|
+
const COLUMNS: LinelistColumn[] = [
|
|
12
|
+
{ header: 'Name', field: 'full_name' },
|
|
13
|
+
{ header: 'CCC Number', field: 'department_number', text: true },
|
|
14
|
+
{ header: 'Date', value: (row) => formatDate(row.date), sortValue: (row) => row.date },
|
|
15
|
+
{ header: 'Sex', field: 'sex' },
|
|
16
|
+
{ header: 'Age', field: 'age' },
|
|
17
|
+
{ header: 'National ID', field: 'national_id', text: true },
|
|
18
|
+
{ header: 'CR Number', field: 'cr_number', text: true },
|
|
19
|
+
{ header: 'Referred By', field: 'referred_by' },
|
|
20
|
+
{ header: 'HIV Result', field: 'hiv_result' },
|
|
21
|
+
{ header: 'Chest X-ray', field: 'xray_result' },
|
|
22
|
+
{ header: 'Microscopy', field: 'microscopy_result' },
|
|
23
|
+
{ header: 'Culture', field: 'molecular_result', wrap: true },
|
|
24
|
+
{ header: 'Outcome', field: 'outcome' },
|
|
25
|
+
{ header: 'Started Anti-TB', field: 'started_tb_treatment' },
|
|
26
|
+
{ header: 'TB Treatment Start', field: 'tb_registration' },
|
|
27
|
+
/* Available from the Columns menu */
|
|
28
|
+
{ header: 'Phone Number', field: 'phone_number', text: true, hidden: true },
|
|
29
|
+
{ header: 'Physical Address', field: 'physical_address', wrap: true, hidden: true },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The cases behind a count on the ACF Facility Summary Tool: the Presumptive TB
|
|
34
|
+
* Register's cases for the period (the same rows the form is counted from),
|
|
35
|
+
* narrowed to the indicator's rule.
|
|
36
|
+
*/
|
|
37
|
+
const AcfSummaryLinelist: React.FC = () => {
|
|
38
|
+
const [searchParams] = useSearchParams();
|
|
39
|
+
const startDate = searchParams.get('startDate') ?? '';
|
|
40
|
+
const endDate = searchParams.get('endDate') ?? '';
|
|
41
|
+
const locationUuids = searchParams.get('locationUuids') ?? '';
|
|
42
|
+
const number = Number(searchParams.get('indicator'));
|
|
43
|
+
const indicator = ACF_INDICATORS[number];
|
|
44
|
+
const heading = indicator ? `${number}. ${indicator.label} linelist` : 'ACF linelist';
|
|
45
|
+
|
|
46
|
+
const locationName = useLocationName(locationUuids);
|
|
47
|
+
/* the period's cases come back in one response; they are fetched once and
|
|
48
|
+
handed to the table in the batches it reads */
|
|
49
|
+
let cases: Promise<AcfCase[]> | undefined;
|
|
50
|
+
const { rows, isLoading } = useAllRows(
|
|
51
|
+
({ startIndex, limit }) => {
|
|
52
|
+
cases ??= getPresumptiveTb({ locationUuids, startDate, endDate }).then((all) =>
|
|
53
|
+
(all as AcfCase[]).filter((row) => indicator?.counts(row)),
|
|
54
|
+
);
|
|
55
|
+
return cases.then((matching) => ({
|
|
56
|
+
results: matching.slice(startIndex, startIndex + limit),
|
|
57
|
+
total: matching.length,
|
|
58
|
+
isTotalExact: true,
|
|
59
|
+
}));
|
|
60
|
+
},
|
|
61
|
+
[searchParams.toString()],
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<RegisterLayout
|
|
66
|
+
parentLabel="ACF Facility Summary Tool"
|
|
67
|
+
parentPath="/acf-summary"
|
|
68
|
+
title="ACF Facility Summary · TB / Chest Clinic"
|
|
69
|
+
heading={heading}
|
|
70
|
+
location={locationName}
|
|
71
|
+
isLoading={isLoading}
|
|
72
|
+
isEmpty={rows.length === 0}
|
|
73
|
+
>
|
|
74
|
+
{/* the layout key changed when the IDs became visible, so a layout saved
|
|
75
|
+
while they were hidden does not hide them again */}
|
|
76
|
+
<LinelistTable
|
|
77
|
+
rows={rows}
|
|
78
|
+
columns={COLUMNS}
|
|
79
|
+
layoutKey="acf-summary:ids"
|
|
80
|
+
exportName={`ACF ${heading} ${endDate}`}
|
|
81
|
+
/>
|
|
82
|
+
</RegisterLayout>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default AcfSummaryLinelist;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router-dom';
|
|
3
|
+
import { useSession } from '@openmrs/esm-framework';
|
|
4
|
+
|
|
5
|
+
import { ReportFiltersComponent, type ReportPeriod, useRestorePeriod } from '../../common/report-filters';
|
|
6
|
+
import { downloadSheetsPdf } from '../../common/report-page';
|
|
7
|
+
import { ReportPlaceholder, useGeneratedLocation } from '../../common/report-placeholder';
|
|
8
|
+
import { showReportError } from '../../common/report-error';
|
|
9
|
+
import { ReportSkeleton } from '../../common/report-skeleton';
|
|
10
|
+
import { registerFileName } from '../../registers/register-file-name';
|
|
11
|
+
import { getPresumptiveTb } from '../../resources/presumptive-tb.resource';
|
|
12
|
+
import { acfCounts, type AcfCase } from './acf-summary.counts';
|
|
13
|
+
import AcfSummaryForm from './acf-summary-form.component';
|
|
14
|
+
import styles from './acf-summary.scss';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Summary Tool for Facility-Based Active Case Finding (MOH/F/DNTLDP/02),
|
|
18
|
+
* opened from the landing page's Reports tab, with the reports' filter bar.
|
|
19
|
+
*
|
|
20
|
+
* Indicators 4 to 8 are counted from the Presumptive TB Register's cases for
|
|
21
|
+
* the month (/presumptive-tb-register), so the two always agree.
|
|
22
|
+
*/
|
|
23
|
+
const AcfSummaryReport: React.FC = () => {
|
|
24
|
+
const [isGenerated, setIsGenerated] = useState(false);
|
|
25
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
26
|
+
const [counts, setCounts] = useState<Record<number, number>>({});
|
|
27
|
+
const [period, setPeriod] = useState<{ startDate: string; endDate: string }>({ startDate: '', endDate: '' });
|
|
28
|
+
|
|
29
|
+
const navigate = useNavigate();
|
|
30
|
+
const session = useSession();
|
|
31
|
+
const locationUuids = session?.sessionLocation?.uuid ?? '';
|
|
32
|
+
const facility = session?.sessionLocation?.display ?? '';
|
|
33
|
+
/* Only a report for the current location counts */
|
|
34
|
+
const { isForCurrentLocation, hasLocationChanged, markGenerated } = useGeneratedLocation('acfSummaryLocation');
|
|
35
|
+
const isReportGenerated = isGenerated && isForCurrentLocation;
|
|
36
|
+
|
|
37
|
+
const generate = async ({ startDate, endDate }: ReportPeriod) => {
|
|
38
|
+
setIsLoading(true);
|
|
39
|
+
setPeriod({ startDate, endDate });
|
|
40
|
+
try {
|
|
41
|
+
setCounts(acfCounts((await getPresumptiveTb({ locationUuids, startDate, endDate })) as AcfCase[]));
|
|
42
|
+
setIsGenerated(true);
|
|
43
|
+
markGenerated(locationUuids);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
showReportError('the ACF Facility Summary Tool', error);
|
|
46
|
+
} finally {
|
|
47
|
+
setIsLoading(false);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
useRestorePeriod(generate);
|
|
52
|
+
|
|
53
|
+
/* Each count opens the register cases it counts */
|
|
54
|
+
const openLinelist = (indicator: number) => {
|
|
55
|
+
const params = new URLSearchParams({ ...period, locationUuids, indicator: String(indicator), from: 'acf-summary' });
|
|
56
|
+
navigate(`/acf-summary-linelist?${params}`);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/* Download PDF saves the form as one A4 landscape page, made from a copy, so
|
|
60
|
+
the page on screen is left as it is */
|
|
61
|
+
const sheetRef = useRef<HTMLDivElement>(null);
|
|
62
|
+
const downloadPdf = async () => {
|
|
63
|
+
const pages = Array.from(sheetRef.current?.querySelectorAll<HTMLElement>('[data-register-page]') ?? []);
|
|
64
|
+
await downloadSheetsPdf(pages, registerFileName('ACF-Facility-Summary', facility, period), {
|
|
65
|
+
orientation: 'landscape',
|
|
66
|
+
stylesheetsOnly: true,
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<>
|
|
72
|
+
<ReportFiltersComponent
|
|
73
|
+
reportName="ACF Facility Summary Tool"
|
|
74
|
+
mode="monthly"
|
|
75
|
+
onGenerate={generate}
|
|
76
|
+
isLoading={isLoading}
|
|
77
|
+
isReportGenerated={isReportGenerated}
|
|
78
|
+
generatedPeriod={period}
|
|
79
|
+
onDownloadPdf={downloadPdf}
|
|
80
|
+
/>
|
|
81
|
+
{isLoading && <ReportSkeleton />}
|
|
82
|
+
{!isLoading && !isReportGenerated && (
|
|
83
|
+
<ReportPlaceholder
|
|
84
|
+
reportName="ACF Facility Summary Tool"
|
|
85
|
+
isLocationChanged={isGenerated && hasLocationChanged}
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
88
|
+
{!isLoading && isReportGenerated && (
|
|
89
|
+
<div className={styles.reportFrame} ref={sheetRef}>
|
|
90
|
+
<AcfSummaryForm facility={facility} month={period.startDate} counts={counts} onOpen={openLinelist} />
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
93
|
+
</>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default AcfSummaryReport;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isDiagnosed,
|
|
3
|
+
isInitiated,
|
|
4
|
+
isInvestigated,
|
|
5
|
+
type PresumptiveTbRow,
|
|
6
|
+
} from '../../registers/presumptive-tb/presumptive-tb.types';
|
|
7
|
+
|
|
8
|
+
/** A register row with the ETL's bacteriological confirmation flag */
|
|
9
|
+
export type AcfCase = PresumptiveTbRow & { bact_confirmed?: number | string | null };
|
|
10
|
+
|
|
11
|
+
/** The department the register's cases are counted under: its TB assessment encounters (331) */
|
|
12
|
+
export const COUNTED_DEPARTMENT = 'TB / Chest Clinic';
|
|
13
|
+
|
|
14
|
+
const isBactConfirmed = (row: AcfCase) => isDiagnosed(row) && Number(row.bact_confirmed) === 1;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The ACF indicators counted from the Presumptive TB Register's rows, by the
|
|
18
|
+
* indicator's number on the form, each with the cases it counts. The ones the
|
|
19
|
+
* register cannot give (workload, screened, respiratory conditions) are absent
|
|
20
|
+
* and stay blank.
|
|
21
|
+
*/
|
|
22
|
+
export const ACF_INDICATORS: Record<number, { label: string; counts: (row: AcfCase) => boolean }> = {
|
|
23
|
+
4: { label: 'Presumptive TB cases investigated for TB disease', counts: isInvestigated },
|
|
24
|
+
5: { label: 'Presumptive TB cases diagnosed with TB', counts: isDiagnosed },
|
|
25
|
+
6: { label: 'Presumptive cases Bact. confirmed with TB', counts: isBactConfirmed },
|
|
26
|
+
7: {
|
|
27
|
+
label: 'Presumptive cases diagnosed with TB clinically',
|
|
28
|
+
counts: (row) => isDiagnosed(row) && !isBactConfirmed(row),
|
|
29
|
+
},
|
|
30
|
+
8: { label: 'Diagnosed TB cases initiated on treatment', counts: isInitiated },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function acfCounts(rows: AcfCase[]): Record<number, number> {
|
|
34
|
+
return Object.fromEntries(
|
|
35
|
+
Object.entries(ACF_INDICATORS).map(([number, indicator]) => [number, rows.filter(indicator.counts).length]),
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
3
|
+
|
|
4
|
+
/* The Summary Tool for Facility-Based Active Case Finding (MOH/F/DNTLDP/02) as
|
|
5
|
+
one A4 landscape sheet, drawn in the units the paper is measured in (mm, pt)
|
|
6
|
+
so it prints as one page: the title and header fields, the indicators by
|
|
7
|
+
department, and the sign-off with the instructions. Row heights come from
|
|
8
|
+
the form (acf-summary-form.component.tsx). */
|
|
9
|
+
|
|
10
|
+
/* On screen a page is the printable area only, A4 landscape less its 8mm
|
|
11
|
+
margins: the card around it gives the margin, and `usePageScale` is told
|
|
12
|
+
this width. */
|
|
13
|
+
$page-w: 297mm - 2 * 8mm;
|
|
14
|
+
$page-h: 210mm - 2 * 8mm;
|
|
15
|
+
|
|
16
|
+
$ink: #1a1a1a;
|
|
17
|
+
$rule: 0.6pt solid #404040;
|
|
18
|
+
|
|
19
|
+
/* The card the page sits in, drawn like the filter card above it */
|
|
20
|
+
.reportFrame {
|
|
21
|
+
margin: layout.$spacing-05 0 layout.$spacing-07;
|
|
22
|
+
padding: layout.$spacing-05;
|
|
23
|
+
background-color: $ui-02;
|
|
24
|
+
border: 1px solid $ui-03;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Holds the fixed-width page without making the app scroll sideways */
|
|
28
|
+
.viewport {
|
|
29
|
+
overflow-x: auto;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.page {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
width: $page-w;
|
|
37
|
+
height: $page-h;
|
|
38
|
+
margin: 0 auto;
|
|
39
|
+
padding: 4mm 3mm 0;
|
|
40
|
+
color: $ink;
|
|
41
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
42
|
+
font-size: 7pt;
|
|
43
|
+
line-height: 1.2;
|
|
44
|
+
background-color: #fff;
|
|
45
|
+
/* set by `usePageScale` from the measured container width, floored at 1 */
|
|
46
|
+
zoom: var(--page-zoom, 1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.title {
|
|
50
|
+
margin: 0 0 5mm;
|
|
51
|
+
font-size: 13pt;
|
|
52
|
+
font-weight: 700;
|
|
53
|
+
text-align: center;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* County, sub county and facility; then month and year */
|
|
57
|
+
.fields {
|
|
58
|
+
display: flex;
|
|
59
|
+
gap: 10mm;
|
|
60
|
+
margin: 0 0 6mm 15mm;
|
|
61
|
+
font-size: 9pt;
|
|
62
|
+
font-weight: 700;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.field {
|
|
66
|
+
display: inline-flex;
|
|
67
|
+
align-items: flex-end;
|
|
68
|
+
white-space: nowrap;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.line,
|
|
72
|
+
.wideLine {
|
|
73
|
+
display: inline-block;
|
|
74
|
+
min-height: 4mm;
|
|
75
|
+
margin-left: 1mm;
|
|
76
|
+
padding: 0 1mm;
|
|
77
|
+
font-weight: 400;
|
|
78
|
+
border-bottom: 1px dashed $ink;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.line {
|
|
82
|
+
width: 55mm;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.wideLine {
|
|
86
|
+
width: 65mm;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.grid {
|
|
90
|
+
width: 100%;
|
|
91
|
+
table-layout: fixed;
|
|
92
|
+
border-collapse: collapse;
|
|
93
|
+
|
|
94
|
+
th,
|
|
95
|
+
td {
|
|
96
|
+
padding: 0.6mm 0.8mm;
|
|
97
|
+
overflow: hidden;
|
|
98
|
+
border: $rule;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
thead th {
|
|
102
|
+
font-size: 6pt;
|
|
103
|
+
font-weight: 700;
|
|
104
|
+
text-align: left;
|
|
105
|
+
vertical-align: top;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
tbody th {
|
|
109
|
+
font-size: 6pt;
|
|
110
|
+
font-weight: 700;
|
|
111
|
+
text-align: left;
|
|
112
|
+
vertical-align: top;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.count {
|
|
117
|
+
font-size: 8pt;
|
|
118
|
+
text-align: center;
|
|
119
|
+
vertical-align: middle;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.clickable {
|
|
123
|
+
cursor: pointer;
|
|
124
|
+
|
|
125
|
+
&:hover,
|
|
126
|
+
&:focus-visible {
|
|
127
|
+
background-color: $brand-primary-10;
|
|
128
|
+
outline: 1px solid var(--brand-01);
|
|
129
|
+
outline-offset: -1px;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.signOff {
|
|
134
|
+
display: flex;
|
|
135
|
+
justify-content: space-between;
|
|
136
|
+
margin-top: 4mm;
|
|
137
|
+
font-size: 9pt;
|
|
138
|
+
font-weight: 700;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* The dotted line a sign-off is written on */
|
|
142
|
+
.dots {
|
|
143
|
+
display: inline-block;
|
|
144
|
+
width: 50mm;
|
|
145
|
+
margin-left: 0.5mm;
|
|
146
|
+
border-bottom: 1px dotted $ink;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.instructions {
|
|
150
|
+
margin-top: 1.5mm;
|
|
151
|
+
font-size: 7pt;
|
|
152
|
+
|
|
153
|
+
ol {
|
|
154
|
+
margin: 0.5mm 0 0 5mm;
|
|
155
|
+
padding: 0;
|
|
156
|
+
list-style: decimal;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
li {
|
|
160
|
+
padding-left: 1mm;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -1,54 +1,69 @@
|
|
|
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
|
+
/** Header keys whose cells wrap instead of stretching the row (`wrap: true` columns) */
|
|
19
|
+
wrapKeys?: readonly string[];
|
|
20
|
+
/** Applied to the table, so a register can use its own stylesheet */
|
|
21
|
+
className?: string;
|
|
8
22
|
}
|
|
9
23
|
|
|
10
|
-
const DatatableWrapper: React.FC<DatatableWrapperProps> = ({
|
|
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
|
-
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
const DatatableWrapper: React.FC<DatatableWrapperProps> = ({
|
|
25
|
+
rows,
|
|
26
|
+
headers,
|
|
27
|
+
subHeaders = [],
|
|
28
|
+
wrapKeys = [],
|
|
29
|
+
className,
|
|
30
|
+
}) => {
|
|
31
|
+
return (
|
|
32
|
+
<DataTable rows={rows} headers={headers}>
|
|
33
|
+
{({ rows, headers, getTableProps, getHeaderProps, getRowProps, getCellProps }) => (
|
|
34
|
+
<Table {...getTableProps()} className={className}>
|
|
35
|
+
<TableHead>
|
|
36
|
+
<TableRow>
|
|
37
|
+
{headers.map((header) => (
|
|
38
|
+
<TableHeader {...getHeaderProps({ header })}>{header.header}</TableHeader>
|
|
39
|
+
))}
|
|
40
|
+
</TableRow>
|
|
41
|
+
{subHeaders && subHeaders.length && (
|
|
42
|
+
<TableRow>
|
|
43
|
+
{subHeaders.map((head, i) => (
|
|
44
|
+
<TableHeader key={i}>{head}</TableHeader>
|
|
45
|
+
))}
|
|
46
|
+
</TableRow>
|
|
47
|
+
)}
|
|
48
|
+
</TableHead>
|
|
49
|
+
<TableBody>
|
|
50
|
+
{rows.map((row) => (
|
|
51
|
+
<TableRow {...getRowProps({ row })}>
|
|
52
|
+
{row.cells.map((cell, i) => (
|
|
53
|
+
<TableCell
|
|
54
|
+
{...getCellProps({ cell })}
|
|
55
|
+
className={wrapKeys.includes(headers[i]?.key) ? 'wrapCell' : undefined}
|
|
56
|
+
>
|
|
57
|
+
{cell.value}
|
|
58
|
+
</TableCell>
|
|
59
|
+
))}
|
|
60
|
+
</TableRow>
|
|
61
|
+
))}
|
|
62
|
+
</TableBody>
|
|
63
|
+
</Table>
|
|
64
|
+
)}
|
|
51
65
|
</DataTable>
|
|
52
|
-
|
|
66
|
+
);
|
|
67
|
+
};
|
|
53
68
|
|
|
54
|
-
export default DatatableWrapper;
|
|
69
|
+
export default DatatableWrapper;
|