@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,92 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { PAGE_SIZE, type PatientListPage } from '../../resources/patient-list-page';
|
|
4
|
+
import { showReportError } from '../report-error';
|
|
5
|
+
|
|
6
|
+
type Fetcher = (paging: { startIndex: number; limit: number }) => Promise<PatientListPage>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Page state and fetching for a register's line list.
|
|
10
|
+
*
|
|
11
|
+
* Registers used to ask for a hardcoded 300 rows and render every one of them.
|
|
12
|
+
* At 41 columns that is 12,300 cells, and anything past 300 was silently
|
|
13
|
+
* dropped. This fetches a page at a time, so the DOM stays flat however large
|
|
14
|
+
* the list is, and reports the total so truncation is never invisible.
|
|
15
|
+
*/
|
|
16
|
+
export function usePatientList(fetcher: Fetcher, deps: React.DependencyList) {
|
|
17
|
+
const [rows, setRows] = useState<Array<Record<string, any>>>([]);
|
|
18
|
+
const [total, setTotal] = useState(0);
|
|
19
|
+
const [isTotalExact, setIsTotalExact] = useState(true);
|
|
20
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
21
|
+
const [page, setPage] = useState(1);
|
|
22
|
+
const [pageSize, setPageSize] = useState(PAGE_SIZE);
|
|
23
|
+
|
|
24
|
+
/* Guards against an earlier page landing after a later one and overwriting
|
|
25
|
+
it, which is easy to trigger by clicking through pages quickly. */
|
|
26
|
+
const request = useRef(0);
|
|
27
|
+
|
|
28
|
+
const load = useCallback(
|
|
29
|
+
async (nextPage: number, size: number) => {
|
|
30
|
+
const id = ++request.current;
|
|
31
|
+
|
|
32
|
+
setIsLoading(true);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const result = await fetcher({ startIndex: (nextPage - 1) * size, limit: size });
|
|
36
|
+
|
|
37
|
+
if (id !== request.current) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setRows(result.results);
|
|
42
|
+
setTotal(result.total);
|
|
43
|
+
setIsTotalExact(result.isTotalExact);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (id === request.current) {
|
|
46
|
+
setRows([]);
|
|
47
|
+
showReportError('the register', error);
|
|
48
|
+
}
|
|
49
|
+
} finally {
|
|
50
|
+
if (id === request.current) {
|
|
51
|
+
setIsLoading(false);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
56
|
+
deps,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
/** Back to page one whenever the query behind the list changes */
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
setPage(1);
|
|
62
|
+
load(1, pageSize);
|
|
63
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
64
|
+
}, deps);
|
|
65
|
+
|
|
66
|
+
const onPageChange = useCallback(
|
|
67
|
+
({ page: nextPage, pageSize: nextSize }: { page: number; pageSize: number }) => {
|
|
68
|
+
setPage(nextPage);
|
|
69
|
+
setPageSize(nextSize);
|
|
70
|
+
load(nextPage, nextSize);
|
|
71
|
+
},
|
|
72
|
+
[load],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
/** Every row across every page, for the CSV export */
|
|
76
|
+
const fetchAll = useCallback(async () => {
|
|
77
|
+
const all: Array<Record<string, any>> = [];
|
|
78
|
+
const size = 500;
|
|
79
|
+
|
|
80
|
+
for (let index = 0; ; index += size) {
|
|
81
|
+
const result = await fetcher({ startIndex: index, limit: size });
|
|
82
|
+
all.push(...result.results);
|
|
83
|
+
|
|
84
|
+
if (result.results.length < size) {
|
|
85
|
+
return all;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
|
+
}, deps);
|
|
90
|
+
|
|
91
|
+
return { rows, total, isTotalExact, isLoading, page, pageSize, onPageChange, fetchAll };
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './report-skeleton.component';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DataTableSkeleton, SkeletonText } from '@carbon/react';
|
|
3
|
+
|
|
4
|
+
import styles from './report-skeleton.scss';
|
|
5
|
+
|
|
6
|
+
interface ReportSkeletonProps {
|
|
7
|
+
/** How many indicator blocks to outline. Roughly the sections a form has. */
|
|
8
|
+
blocks?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Placeholder in the shape of a generated report.
|
|
13
|
+
*
|
|
14
|
+
* Reports replaced their whole body while fetching, so a centred spinner left
|
|
15
|
+
* the page blank and shifted everything when the data landed. Outlining the
|
|
16
|
+
* masthead and the indicator tables keeps the layout stable and shows how much
|
|
17
|
+
* is coming.
|
|
18
|
+
*/
|
|
19
|
+
export const ReportSkeleton: React.FC<ReportSkeletonProps> = ({ blocks = 2 }) => (
|
|
20
|
+
<div className={styles.skeleton} aria-busy="true" aria-label="Loading report">
|
|
21
|
+
<div className={styles.header}>
|
|
22
|
+
<SkeletonText heading width="45%" />
|
|
23
|
+
<SkeletonText width="70%" />
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
{Array.from({ length: blocks }, (_, index) => (
|
|
27
|
+
<div key={index} className={styles.block}>
|
|
28
|
+
<SkeletonText heading width="30%" />
|
|
29
|
+
<DataTableSkeleton showHeader={false} showToolbar={false} columnCount={4} rowCount={5} size="sm" />
|
|
30
|
+
</div>
|
|
31
|
+
))}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Placeholder for the register and patient-list pages, which are a single
|
|
37
|
+
* table rather than a form.
|
|
38
|
+
*/
|
|
39
|
+
export const RegisterSkeleton: React.FC<{ columnCount?: number; rowCount?: number }> = ({
|
|
40
|
+
columnCount = 6,
|
|
41
|
+
rowCount = 8,
|
|
42
|
+
}) => (
|
|
43
|
+
<div className={styles.skeleton} aria-busy="true" aria-label="Loading register">
|
|
44
|
+
<DataTableSkeleton showHeader={false} showToolbar={false} columnCount={columnCount} rowCount={rowCount} size="sm" />
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@use '@carbon/layout';
|
|
2
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
3
|
+
|
|
4
|
+
.skeleton {
|
|
5
|
+
padding: layout.$spacing-05;
|
|
6
|
+
margin-bottom: layout.$spacing-05;
|
|
7
|
+
background-color: $ui-02;
|
|
8
|
+
border: 1px solid $ui-03;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* When it stands in for a register table it sits under the caption bar */
|
|
12
|
+
.skeleton:not(:first-child) {
|
|
13
|
+
margin-bottom: 0;
|
|
14
|
+
border-top: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.header {
|
|
18
|
+
padding-bottom: layout.$spacing-05;
|
|
19
|
+
margin-bottom: layout.$spacing-05;
|
|
20
|
+
border-bottom: 1px solid $ui-03;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.block {
|
|
24
|
+
margin-bottom: layout.$spacing-06;
|
|
25
|
+
|
|
26
|
+
&:last-child {
|
|
27
|
+
margin-bottom: 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/config-schema.ts
CHANGED
|
@@ -3,10 +3,18 @@ export const configSchema = {
|
|
|
3
3
|
etlBaseUrl: {
|
|
4
4
|
_type: Type.String,
|
|
5
5
|
_default: '',
|
|
6
|
-
_description: 'ETL
|
|
6
|
+
_description: 'Base URL of the ETL service every report reads from, e.g. "/etl"',
|
|
7
|
+
},
|
|
8
|
+
/* Declared because the deployment sets it in this section. Nothing reads it
|
|
9
|
+
yet; without it the config validator reports it as an unknown key. */
|
|
10
|
+
subDomainUrl: {
|
|
11
|
+
_type: Type.String,
|
|
12
|
+
_default: '',
|
|
13
|
+
_description: 'Origin this instance is served from',
|
|
7
14
|
},
|
|
8
15
|
};
|
|
9
16
|
|
|
10
17
|
export type Config = {
|
|
11
18
|
etlBaseUrl: string;
|
|
19
|
+
subDomainUrl: string;
|
|
12
20
|
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Activity,
|
|
3
|
+
ChartColumn,
|
|
4
|
+
Document,
|
|
5
|
+
DocumentTasks,
|
|
6
|
+
GenderFemale,
|
|
7
|
+
Growth,
|
|
8
|
+
HealthCross,
|
|
9
|
+
Medication,
|
|
10
|
+
Microscope,
|
|
11
|
+
Stethoscope,
|
|
12
|
+
UserMultiple,
|
|
13
|
+
Warning,
|
|
14
|
+
type CarbonIconType,
|
|
15
|
+
} from '@carbon/react/icons';
|
|
16
|
+
|
|
17
|
+
export type ReportTone = 'violet' | 'magenta' | 'teal' | 'blue';
|
|
18
|
+
|
|
19
|
+
export interface ReportDefinition {
|
|
20
|
+
/** The MOH form number, e.g. `MOH 731` */
|
|
21
|
+
code: string;
|
|
22
|
+
/** Human readable name of the form */
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
/** Route registered in root.component.tsx */
|
|
26
|
+
path: string;
|
|
27
|
+
icon: CarbonIconType;
|
|
28
|
+
/** Extra terms matched by the search field */
|
|
29
|
+
keywords: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ReportCategory {
|
|
33
|
+
id: string;
|
|
34
|
+
title: string;
|
|
35
|
+
description: string;
|
|
36
|
+
tone: ReportTone;
|
|
37
|
+
reports: ReportDefinition[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const reportCategories: ReportCategory[] = [
|
|
41
|
+
{
|
|
42
|
+
id: 'hiv-and-chronic-care',
|
|
43
|
+
title: 'HIV & chronic care',
|
|
44
|
+
description: 'Comprehensive care programme summaries',
|
|
45
|
+
tone: 'violet',
|
|
46
|
+
reports: [
|
|
47
|
+
{
|
|
48
|
+
code: 'MOH 731',
|
|
49
|
+
name: 'Comprehensive HIV/AIDS',
|
|
50
|
+
description: 'NASCOP monthly summary for HIV testing, EMTCT, care and treatment.',
|
|
51
|
+
path: '/moh-731',
|
|
52
|
+
icon: HealthCross,
|
|
53
|
+
keywords: ['hiv', 'nascop', 'art', 'prep', 'emtct', 'pmtct', 'tb'],
|
|
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
|
+
},
|
|
63
|
+
{
|
|
64
|
+
code: 'MOH 740',
|
|
65
|
+
name: 'Diabetes & hypertension',
|
|
66
|
+
description: 'Monthly summary for the NCD comprehensive care clinic.',
|
|
67
|
+
path: '/moh-740',
|
|
68
|
+
icon: Activity,
|
|
69
|
+
keywords: ['ncd', 'diabetes', 'hypertension', 'chronic'],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'reproductive-and-child-health',
|
|
75
|
+
title: 'Reproductive & child health',
|
|
76
|
+
description: 'RMNCAH service delivery summaries',
|
|
77
|
+
tone: 'magenta',
|
|
78
|
+
reports: [
|
|
79
|
+
{
|
|
80
|
+
code: 'MOH 710',
|
|
81
|
+
name: 'Immunization',
|
|
82
|
+
description: 'Child immunization and vitamin A supplementation summary.',
|
|
83
|
+
path: '/moh-710',
|
|
84
|
+
icon: Growth,
|
|
85
|
+
keywords: ['immunization', 'vaccine', 'child', 'khis', 'bcg', 'polio'],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
code: 'MOH 711',
|
|
89
|
+
name: 'Integrated programme summary',
|
|
90
|
+
description: 'Reproductive and child health, medical and rehabilitation services.',
|
|
91
|
+
path: '/moh-711',
|
|
92
|
+
icon: UserMultiple,
|
|
93
|
+
keywords: ['rmncah', 'anc', 'pnc', 'maternity', 'family planning', 'gbv', 'physiotherapy'],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
code: 'MOH 745',
|
|
97
|
+
name: 'Cancer screening',
|
|
98
|
+
description: 'Monthly cervical and breast cancer screening summary.',
|
|
99
|
+
path: '/moh-745',
|
|
100
|
+
icon: GenderFemale,
|
|
101
|
+
keywords: ['cancer', 'cervical', 'screening', 'via', 'hpv'],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 'outpatient-and-workload',
|
|
107
|
+
title: 'Outpatient & workload',
|
|
108
|
+
description: 'Morbidity and facility workload returns',
|
|
109
|
+
tone: 'teal',
|
|
110
|
+
reports: [
|
|
111
|
+
{
|
|
112
|
+
code: 'MOH 705A',
|
|
113
|
+
name: 'Outpatient morbidity, under 5',
|
|
114
|
+
description: 'Summary of diagnoses for children under five years.',
|
|
115
|
+
path: '/moh-705a',
|
|
116
|
+
icon: DocumentTasks,
|
|
117
|
+
keywords: ['morbidity', 'outpatient', 'under five', 'children', 'khis'],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
code: 'MOH 705B',
|
|
121
|
+
name: 'Outpatient morbidity, over 5',
|
|
122
|
+
description: 'Summary of diagnoses for clients aged five years and above.',
|
|
123
|
+
path: '/moh-705b',
|
|
124
|
+
icon: Document,
|
|
125
|
+
keywords: ['morbidity', 'outpatient', 'above five', 'adults', 'khis'],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
code: 'MOH 717',
|
|
129
|
+
name: 'Service workload',
|
|
130
|
+
description: 'Monthly service workload across facility departments.',
|
|
131
|
+
path: '/moh-717',
|
|
132
|
+
icon: ChartColumn,
|
|
133
|
+
keywords: ['workload', 'inpatient', 'pharmacy', 'mortuary', 'theatre', 'maternity'],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: 'diagnostics-and-surveillance',
|
|
139
|
+
title: 'Diagnostics & surveillance',
|
|
140
|
+
description: 'Laboratory and disease surveillance returns',
|
|
141
|
+
tone: 'blue',
|
|
142
|
+
reports: [
|
|
143
|
+
{
|
|
144
|
+
code: 'MOH 706',
|
|
145
|
+
name: 'Laboratory services',
|
|
146
|
+
description: 'Monthly summary of laboratory investigations and results.',
|
|
147
|
+
path: '/moh-706',
|
|
148
|
+
icon: Microscope,
|
|
149
|
+
keywords: ['laboratory', 'lab', 'urine', 'parasitology', 'blood chemistry'],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
code: 'MOH 505',
|
|
153
|
+
name: 'IDSR epidemic monitoring',
|
|
154
|
+
description: 'Weekly monitoring form for priority notifiable diseases.',
|
|
155
|
+
path: '/moh-505',
|
|
156
|
+
icon: Warning,
|
|
157
|
+
keywords: ['idsr', 'surveillance', 'epidemic', 'notifiable', 'outbreak'],
|
|
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
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
export const totalReportCount = reportCategories.reduce((count, category) => count + category.reports.length, 0);
|
|
172
|
+
|
|
173
|
+
export function filterCategories(categories: ReportCategory[], searchTerm: string): ReportCategory[] {
|
|
174
|
+
const term = searchTerm.trim().toLowerCase();
|
|
175
|
+
|
|
176
|
+
if (!term) {
|
|
177
|
+
return categories;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return categories
|
|
181
|
+
.map((category) => ({
|
|
182
|
+
...category,
|
|
183
|
+
reports: category.reports.filter((report) =>
|
|
184
|
+
[report.code, report.name, report.description, category.title, ...report.keywords]
|
|
185
|
+
.join(' ')
|
|
186
|
+
.toLowerCase()
|
|
187
|
+
.includes(term),
|
|
188
|
+
),
|
|
189
|
+
}))
|
|
190
|
+
.filter((category) => category.reports.length > 0);
|
|
191
|
+
}
|
|
@@ -1,28 +1,199 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useNavigate } from 'react-router-dom';
|
|
3
|
-
import { ClickableTile } from '@carbon/react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useNavigate, useSearchParams } from 'react-router-dom';
|
|
3
|
+
import { Button, ClickableTile, Layer, Search, Tab, TabList, TabPanel, TabPanels, Tabs, Tag } from '@carbon/react';
|
|
4
|
+
import { ArrowRight, DocumentMultiple_01, Report, type CarbonIconType } from '@carbon/react/icons';
|
|
5
|
+
import { formatDate, useSession } from '@openmrs/esm-framework';
|
|
4
6
|
|
|
7
|
+
import { registerCategories, totalRegisterCount } from '../registers/register-catalog';
|
|
8
|
+
import {
|
|
9
|
+
filterCategories,
|
|
10
|
+
reportCategories,
|
|
11
|
+
totalReportCount,
|
|
12
|
+
type ReportCategory,
|
|
13
|
+
type ReportDefinition,
|
|
14
|
+
} from './report-catalog';
|
|
5
15
|
import styles from './reports-dashboard.module.scss';
|
|
16
|
+
|
|
6
17
|
interface ReportsDashboardProps {}
|
|
18
|
+
|
|
7
19
|
const ReportsDashboard: React.FC<ReportsDashboardProps> = () => {
|
|
8
20
|
const navigate = useNavigate();
|
|
21
|
+
const session = useSession();
|
|
22
|
+
/* each tab keeps its own search */
|
|
23
|
+
const [reportSearch, setReportSearch] = useState<string>('');
|
|
24
|
+
const [registerSearch, setRegisterSearch] = useState<string>('');
|
|
25
|
+
|
|
26
|
+
/* Reports first, Registers second; the open tab is kept in the URL */
|
|
27
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
28
|
+
const selectedTab = searchParams.get('tab') === 'registers' ? 1 : 0;
|
|
29
|
+
const selectTab = ({ selectedIndex }: { selectedIndex: number }) => {
|
|
30
|
+
const next = new URLSearchParams(searchParams);
|
|
31
|
+
if (selectedIndex === 1) {
|
|
32
|
+
next.set('tab', 'registers');
|
|
33
|
+
} else {
|
|
34
|
+
next.delete('tab');
|
|
35
|
+
}
|
|
36
|
+
setSearchParams(next, { replace: true });
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const facilityName = session?.sessionLocation?.display;
|
|
40
|
+
const today = formatDate(new Date(), { mode: 'standard', time: false, noToday: true });
|
|
41
|
+
|
|
42
|
+
const renderReportTile = (report: ReportDefinition, tone: string) => {
|
|
43
|
+
const Icon = report.icon;
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ClickableTile
|
|
47
|
+
key={report.path}
|
|
48
|
+
className={styles.tile}
|
|
49
|
+
data-tone={tone}
|
|
50
|
+
onClick={() => navigate(report.path)}
|
|
51
|
+
aria-label={`${report.code} ${report.name}`}
|
|
52
|
+
>
|
|
53
|
+
<div className={styles.tileIcon}>
|
|
54
|
+
<Icon size={20} />
|
|
55
|
+
</div>
|
|
56
|
+
<div className={styles.tileCopy}>
|
|
57
|
+
<p className={styles.tileCode}>{report.code}</p>
|
|
58
|
+
<h4 className={styles.tileName}>{report.name}</h4>
|
|
59
|
+
</div>
|
|
60
|
+
<ArrowRight size={16} className={styles.tileArrow} />
|
|
61
|
+
</ClickableTile>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const renderCategory = (category: ReportCategory) => (
|
|
66
|
+
<section key={category.id} className={styles.category}>
|
|
67
|
+
<div className={styles.categoryHeader} data-tone={category.tone}>
|
|
68
|
+
<h5 className={styles.categoryTitle}>{category.title}</h5>
|
|
69
|
+
<Tag size="sm" type="outline">
|
|
70
|
+
{category.reports.length}
|
|
71
|
+
</Tag>
|
|
72
|
+
</div>
|
|
73
|
+
<div className={styles.grid}>{category.reports.map((report) => renderReportTile(report, category.tone))}</div>
|
|
74
|
+
</section>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
/** A tab's list: search row, then its categories, or a message when nothing matches */
|
|
78
|
+
const renderCatalog = ({
|
|
79
|
+
id,
|
|
80
|
+
noun,
|
|
81
|
+
categories,
|
|
82
|
+
total,
|
|
83
|
+
term,
|
|
84
|
+
setTerm,
|
|
85
|
+
icon: Icon,
|
|
86
|
+
hint,
|
|
87
|
+
}: {
|
|
88
|
+
id: string;
|
|
89
|
+
noun: string;
|
|
90
|
+
categories: ReportCategory[];
|
|
91
|
+
total: number;
|
|
92
|
+
term: string;
|
|
93
|
+
setTerm: (term: string) => void;
|
|
94
|
+
icon: CarbonIconType;
|
|
95
|
+
hint: string;
|
|
96
|
+
}) => {
|
|
97
|
+
const visible = filterCategories(categories, term);
|
|
98
|
+
const matches = visible.reduce((count, category) => count + category.reports.length, 0);
|
|
99
|
+
const isSearching = term.trim().length > 0;
|
|
100
|
+
const label = `Search ${noun}`;
|
|
101
|
+
/* "1 register", "10 reports" */
|
|
102
|
+
const counted = (n: number) => (n === 1 ? noun.replace(/s$/, '') : noun);
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<>
|
|
106
|
+
<div className={styles.toolbar}>
|
|
107
|
+
<Layer className={styles.searchLayer}>
|
|
108
|
+
<Search
|
|
109
|
+
id={id}
|
|
110
|
+
labelText={label}
|
|
111
|
+
placeholder={label}
|
|
112
|
+
size="md"
|
|
113
|
+
value={term}
|
|
114
|
+
onChange={(event) => setTerm(event.target.value)}
|
|
115
|
+
onClear={() => setTerm('')}
|
|
116
|
+
/>
|
|
117
|
+
</Layer>
|
|
118
|
+
<p className={styles.resultCount}>
|
|
119
|
+
{isSearching ? `${matches} of ${total} ${counted(total)}` : `${total} ${counted(total)} available`}
|
|
120
|
+
</p>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
{visible.length > 0 ? (
|
|
124
|
+
visible.map(renderCategory)
|
|
125
|
+
) : (
|
|
126
|
+
<Layer className={styles.emptyState}>
|
|
127
|
+
<Icon size={32} className={styles.emptyStateIcon} />
|
|
128
|
+
<h5>
|
|
129
|
+
No {noun} match “{term}”
|
|
130
|
+
</h5>
|
|
131
|
+
<p>{hint}</p>
|
|
132
|
+
<Button kind="ghost" size="sm" onClick={() => setTerm('')}>
|
|
133
|
+
Clear search
|
|
134
|
+
</Button>
|
|
135
|
+
</Layer>
|
|
136
|
+
)}
|
|
137
|
+
</>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
9
141
|
return (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
142
|
+
<div className={styles.dashboard}>
|
|
143
|
+
{/* The facility and date sit at the right end of the tab row */}
|
|
144
|
+
<div className={styles.tabsArea}>
|
|
145
|
+
<p className={styles.headerMeta}>{[facilityName, today].filter(Boolean).join(' · ')}</p>
|
|
146
|
+
<Tabs selectedIndex={selectedTab} onChange={selectTab}>
|
|
147
|
+
<TabList aria-label="Reports and registers" className={styles.tabList}>
|
|
148
|
+
<Tab>
|
|
149
|
+
<span className={styles.tabLabel}>
|
|
150
|
+
<Report size={16} />
|
|
151
|
+
Reports
|
|
152
|
+
<Tag size="sm" type="gray" className={styles.tabCount}>
|
|
153
|
+
{totalReportCount}
|
|
154
|
+
</Tag>
|
|
155
|
+
</span>
|
|
156
|
+
</Tab>
|
|
157
|
+
<Tab>
|
|
158
|
+
<span className={styles.tabLabel}>
|
|
159
|
+
<DocumentMultiple_01 size={16} />
|
|
160
|
+
Registers
|
|
161
|
+
<Tag size="sm" type="gray" className={styles.tabCount}>
|
|
162
|
+
{totalRegisterCount}
|
|
163
|
+
</Tag>
|
|
164
|
+
</span>
|
|
165
|
+
</Tab>
|
|
166
|
+
</TabList>
|
|
167
|
+
<TabPanels>
|
|
168
|
+
<TabPanel className={styles.tabPanel}>
|
|
169
|
+
{renderCatalog({
|
|
170
|
+
id: 'reports-search',
|
|
171
|
+
noun: 'reports',
|
|
172
|
+
categories: reportCategories,
|
|
173
|
+
total: totalReportCount,
|
|
174
|
+
term: reportSearch,
|
|
175
|
+
setTerm: setReportSearch,
|
|
176
|
+
icon: Report,
|
|
177
|
+
hint: 'Try a form number such as 731, or a service such as immunization.',
|
|
178
|
+
})}
|
|
179
|
+
</TabPanel>
|
|
180
|
+
<TabPanel className={styles.tabPanel}>
|
|
181
|
+
{/* Registers, from src/registers, listed and searched as the reports are */}
|
|
182
|
+
{renderCatalog({
|
|
183
|
+
id: 'registers-search',
|
|
184
|
+
noun: 'registers',
|
|
185
|
+
categories: registerCategories,
|
|
186
|
+
total: totalRegisterCount,
|
|
187
|
+
term: registerSearch,
|
|
188
|
+
setTerm: setRegisterSearch,
|
|
189
|
+
icon: DocumentMultiple_01,
|
|
190
|
+
hint: 'Try a register number such as 362, or a service such as HTS.',
|
|
191
|
+
})}
|
|
192
|
+
</TabPanel>
|
|
193
|
+
</TabPanels>
|
|
194
|
+
</Tabs>
|
|
24
195
|
</div>
|
|
25
|
-
|
|
196
|
+
</div>
|
|
26
197
|
);
|
|
27
198
|
};
|
|
28
199
|
|