@ampath/esm-reports-app 1.0.0-next.40 → 1.0.0-next.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/110.js +2 -1
- package/dist/110.js.LICENSE.txt +35 -0
- package/dist/110.js.map +1 -1
- package/dist/205.js +1 -1
- package/dist/441.js +1 -0
- package/dist/441.js.map +1 -0
- package/dist/738.js +1 -0
- package/dist/738.js.map +1 -0
- package/dist/812.js +1 -1
- package/dist/812.js.map +1 -1
- package/dist/ampath-esm-reports-app.js +1 -1
- package/dist/ampath-esm-reports-app.js.buildmanifest.json +66 -39
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/common/report-error/index.ts +1 -0
- package/src/common/report-error/show-report-error.ts +25 -0
- package/src/common/report-filters/date-range.ts +137 -0
- package/src/common/report-filters/index.ts +4 -0
- package/src/common/report-filters/report-filters.component.tsx +291 -104
- package/src/common/report-filters/report-filters.scss +199 -32
- package/src/common/report-filters/types.ts +66 -0
- package/src/common/report-filters/use-restore-period.ts +43 -0
- package/src/common/report-page/index.ts +2 -0
- package/src/common/report-page/report-page.component.tsx +32 -0
- package/src/common/report-page/report-page.scss +45 -0
- package/src/common/report-page/use-page-scale.ts +50 -0
- package/src/common/report-placeholder/has-report-data.ts +15 -0
- package/src/common/report-placeholder/index.ts +2 -0
- package/src/common/report-placeholder/report-placeholder.component.tsx +56 -0
- package/src/common/report-placeholder/report-placeholder.scss +46 -0
- package/src/common/report-register/index.ts +5 -0
- package/src/common/report-register/register-columns.ts +34 -0
- package/src/common/report-register/register-layout.component.tsx +237 -0
- package/src/common/report-register/register-layout.scss +140 -0
- package/src/common/report-register/register-table.scss +62 -0
- package/src/common/report-register/report-parents.ts +27 -0
- package/src/common/report-register/rows-to-csv.ts +59 -0
- package/src/common/report-register/use-patient-list.ts +92 -0
- package/src/common/report-skeleton/index.ts +1 -0
- package/src/common/report-skeleton/report-skeleton.component.tsx +46 -0
- package/src/common/report-skeleton/report-skeleton.scss +29 -0
- package/src/config-schema.ts +9 -1
- package/src/dashboard/report-catalog.ts +173 -0
- package/src/dashboard/reports-dasboard.tsx +101 -35
- package/src/dashboard/reports-dashboard.module.scss +269 -11
- package/src/index.ts +13 -1
- package/src/reports/datatable-wrapper/datatable-wrapper.component.tsx +50 -48
- package/src/reports/moh-240/moh-240-header.component.tsx +54 -56
- package/src/reports/moh-240/moh-240.columns.ts +64 -0
- package/src/reports/moh-240/moh-240.component.tsx +65 -84
- package/src/reports/moh-240/moh-240.scss +36 -7
- package/src/reports/moh-240/sub-reports/moh-240-register.component.tsx +27 -65
- package/src/reports/moh-240/sub-reports/page-summary.component.tsx +2 -2
- package/src/reports/moh-505/moh-505-header.component.tsx +59 -57
- package/src/reports/moh-505/moh-505.component.tsx +51 -56
- package/src/reports/moh-505/moh-505.scss +116 -2
- package/src/reports/moh-705B/moh-204b-register.component.tsx +41 -42
- package/src/reports/moh-705B/moh-204b.columns.ts +39 -0
- package/src/reports/moh-705B/moh-705b.component.tsx +492 -473
- package/src/reports/moh-705B/moh-705b.scss +110 -24
- package/src/reports/moh-705a/moh-705a.component.tsx +496 -476
- package/src/reports/moh-705a/moh-705a.scss +109 -24
- package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +41 -42
- package/src/reports/moh-705a/registers/moh-204a.columns.ts +57 -0
- package/src/reports/moh-706/moh-706-header.component.tsx +58 -56
- package/src/reports/moh-706/moh-706.component.tsx +84 -55
- package/src/reports/moh-706/moh-706.scss +115 -19
- package/src/reports/moh-710/moh-710.component.tsx +743 -727
- package/src/reports/moh-710/moh-710.scss +140 -23
- package/src/reports/moh-710/registers/moh-511-710-register.component.tsx +48 -43
- package/src/reports/moh-710/registers/moh-511-710.columns.ts +52 -0
- package/src/reports/moh-711/moh-711.component.tsx +94 -106
- package/src/reports/moh-711/moh711.scss +95 -64
- package/src/reports/moh-711/registers/moh-333-register.component.tsx +92 -94
- package/src/reports/moh-711/registers/moh-333.columns.ts +119 -0
- package/src/reports/moh-711/registers/moh-405-register.component.tsx +88 -89
- package/src/reports/moh-711/registers/moh-405.columns.ts +120 -0
- package/src/reports/moh-711/registers/moh-406-register.component.tsx +85 -88
- package/src/reports/moh-711/registers/moh-406.columns.ts +133 -0
- package/src/reports/moh-711/registers/moh-510-register.component.tsx +38 -44
- package/src/reports/moh-711/registers/moh-511-register.component.tsx +42 -43
- package/src/reports/moh-711/registers/moh-511.columns.ts +59 -0
- package/src/reports/moh-711/sections/anc.component.tsx +3 -3
- package/src/reports/moh-711/sections/cervical-cancer.component.tsx +3 -3
- package/src/reports/moh-711/sections/chanis.component.tsx +2 -3
- package/src/reports/moh-711/sections/family-planning.component.tsx +2 -2
- package/src/reports/moh-711/sections/gbv.component.tsx +2 -2
- package/src/reports/moh-711/sections/maternity.component.tsx +3 -8
- package/src/reports/moh-711/sections/medical-social-work.component.tsx +2 -12
- package/src/reports/moh-711/sections/other.component.tsx +2 -2
- package/src/reports/moh-711/sections/physiotherapy.component.tsx +2 -2
- package/src/reports/moh-711/sections/pnc.component.tsx +7 -5
- package/src/reports/moh-711/sections/post-abortion.component.tsx +2 -2
- package/src/reports/moh-711/sections/rehabilitation.component.tsx +2 -2
- package/src/reports/moh-711/sections/report-compiled-by.component.tsx +12 -4
- package/src/reports/moh-711/sections/tb-screening.component.tsx +2 -2
- package/src/reports/moh-717/moh-717.component.tsx +100 -121
- package/src/reports/moh-717/moh717.scss +163 -102
- package/src/reports/moh-717/sections/maternity.component.tsx +1 -1
- package/src/reports/moh-717/sections/orthopaedic-trauma.component.tsx +1 -1
- package/src/reports/moh-717/sections/outpatient.component.tsx +23 -23
- package/src/reports/moh-717/sections/preparedby.component.tsx +7 -2
- package/src/reports/moh-717/sections/special-services.component.tsx +1 -1
- package/src/reports/moh-731/moh-731.component.tsx +127 -110
- package/src/reports/moh-731/moh-731.scss +396 -68
- package/src/reports/moh-731/registers/moh-366.columns.ts +38 -0
- package/src/reports/moh-731/registers/moh-366.component.tsx +76 -83
- package/src/reports/moh-731/registers/prep-register.component.tsx +70 -78
- package/src/reports/moh-731/registers/prep.columns.ts +34 -0
- package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +1031 -751
- package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +230 -86
- package/src/reports/moh-731/sections/pmtct.component.tsx +185 -64
- package/src/reports/moh-740/moh-740.component.scss +159 -79
- package/src/reports/moh-740/moh-740.component.tsx +258 -227
- package/src/reports/moh-740/moh-740.resource.ts +17 -10
- package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.tsx +77 -96
- package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.tsx +50 -70
- package/src/reports/moh-740/registers/moh-740-patient-list.tsx +61 -32
- package/src/reports/moh-740/registers/moh-740.columns.ts +52 -0
- package/src/reports/moh-745/moh-745.component.tsx +897 -877
- package/src/reports/moh-745/moh-745.scss +104 -46
- package/src/reports/moh-745/registers/moh-412-register.component.tsx +42 -43
- package/src/reports/moh-745/registers/moh-412.columns.ts +52 -0
- package/src/reports/table-wrapper/table-wrapper.component.tsx +23 -14
- package/src/reports/table-wrapper/table-wrapper.scss +1 -16
- package/src/resources/moh-505.resource.ts +18 -35
- package/src/resources/moh-705.resource.ts +28 -39
- package/src/resources/moh-706.resource.ts +17 -30
- package/src/resources/moh-710.resource.ts +7 -17
- package/src/resources/moh-711.resource.ts +46 -64
- package/src/resources/moh-717.resource.ts +7 -17
- package/src/resources/moh-731.resource.ts +26 -32
- package/src/resources/moh-745.resource.ts +18 -20
- package/src/resources/patient-list-page.ts +66 -0
- package/src/root.component.tsx +28 -26
- package/src/root.scss +39 -0
- package/src/utils/get-base-url.ts +39 -7
- package/dist/822.js +0 -2
- package/dist/822.js.LICENSE.txt +0 -20
- package/dist/822.js.map +0 -1
- package/src/reports/moh-731/registers/moh-366.scss +0 -45
- package/src/reports/moh-731/registers/prep-registers.scss +0 -45
- package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.scss +0 -18
- package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.scss +0 -18
- /package/src/{reports/moh-740/shared/utils → utils}/format-indicator.ts +0 -0
|
@@ -1,46 +1,112 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
2
|
import { useNavigate } from 'react-router-dom';
|
|
3
|
-
import { ClickableTile } from '@carbon/react';
|
|
3
|
+
import { Button, ClickableTile, Layer, Search, Tag } from '@carbon/react';
|
|
4
|
+
import { ArrowRight, Calendar, Location, Report } from '@carbon/react/icons';
|
|
5
|
+
import { formatDate, useSession } from '@openmrs/esm-framework';
|
|
4
6
|
|
|
7
|
+
import { filterCategories, reportCategories, totalReportCount, type ReportDefinition } from './report-catalog';
|
|
5
8
|
import styles from './reports-dashboard.module.scss';
|
|
9
|
+
|
|
6
10
|
interface ReportsDashboardProps {}
|
|
11
|
+
|
|
7
12
|
const ReportsDashboard: React.FC<ReportsDashboardProps> = () => {
|
|
8
13
|
const navigate = useNavigate();
|
|
14
|
+
const session = useSession();
|
|
15
|
+
const [searchTerm, setSearchTerm] = useState<string>('');
|
|
16
|
+
|
|
17
|
+
const facilityName = session?.sessionLocation?.display;
|
|
18
|
+
const today = formatDate(new Date(), { mode: 'standard', time: false, noToday: true });
|
|
19
|
+
|
|
20
|
+
const visibleCategories = useMemo(() => filterCategories(reportCategories, searchTerm), [searchTerm]);
|
|
21
|
+
const matchCount = visibleCategories.reduce((count, category) => count + category.reports.length, 0);
|
|
22
|
+
const isSearching = searchTerm.trim().length > 0;
|
|
23
|
+
|
|
24
|
+
const renderReportTile = (report: ReportDefinition, tone: string) => {
|
|
25
|
+
const Icon = report.icon;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<ClickableTile
|
|
29
|
+
key={report.path}
|
|
30
|
+
className={styles.tile}
|
|
31
|
+
data-tone={tone}
|
|
32
|
+
onClick={() => navigate(report.path)}
|
|
33
|
+
aria-label={`${report.code} ${report.name}`}
|
|
34
|
+
>
|
|
35
|
+
<div className={styles.tileIcon}>
|
|
36
|
+
<Icon size={20} />
|
|
37
|
+
</div>
|
|
38
|
+
<div className={styles.tileCopy}>
|
|
39
|
+
<p className={styles.tileCode}>{report.code}</p>
|
|
40
|
+
<h4 className={styles.tileName}>{report.name}</h4>
|
|
41
|
+
</div>
|
|
42
|
+
<ArrowRight size={16} className={styles.tileArrow} />
|
|
43
|
+
</ClickableTile>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
9
47
|
return (
|
|
10
|
-
|
|
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
|
-
</
|
|
48
|
+
<div className={styles.dashboard}>
|
|
49
|
+
<header className={styles.header}>
|
|
50
|
+
<div className={styles.headerIcon}>
|
|
51
|
+
<Report size={20} />
|
|
52
|
+
</div>
|
|
53
|
+
<h3 className={styles.headerTitle}>Reports</h3>
|
|
54
|
+
<div className={styles.headerMeta}>
|
|
55
|
+
{facilityName && (
|
|
56
|
+
<span className={styles.metaItem}>
|
|
57
|
+
<Location size={16} />
|
|
58
|
+
{facilityName}
|
|
59
|
+
</span>
|
|
60
|
+
)}
|
|
61
|
+
<span className={styles.metaItem}>
|
|
62
|
+
<Calendar size={16} />
|
|
63
|
+
{today}
|
|
64
|
+
</span>
|
|
65
|
+
</div>
|
|
66
|
+
</header>
|
|
67
|
+
|
|
68
|
+
<div className={styles.toolbar}>
|
|
69
|
+
<Layer className={styles.searchLayer}>
|
|
70
|
+
<Search
|
|
71
|
+
id="reports-search"
|
|
72
|
+
labelText="Search reports"
|
|
73
|
+
placeholder="Search reports"
|
|
74
|
+
size="sm"
|
|
75
|
+
value={searchTerm}
|
|
76
|
+
onChange={(event) => setSearchTerm(event.target.value)}
|
|
77
|
+
onClear={() => setSearchTerm('')}
|
|
78
|
+
/>
|
|
79
|
+
</Layer>
|
|
80
|
+
<p className={styles.resultCount}>
|
|
81
|
+
{isSearching ? `${matchCount} of ${totalReportCount} reports` : `${totalReportCount} reports available`}
|
|
82
|
+
</p>
|
|
42
83
|
</div>
|
|
43
|
-
|
|
84
|
+
|
|
85
|
+
{visibleCategories.length > 0 ? (
|
|
86
|
+
visibleCategories.map((category) => (
|
|
87
|
+
<section key={category.id} className={styles.category}>
|
|
88
|
+
<div className={styles.categoryHeader} data-tone={category.tone}>
|
|
89
|
+
<h5 className={styles.categoryTitle}>{category.title}</h5>
|
|
90
|
+
<Tag size="sm" type="outline">
|
|
91
|
+
{category.reports.length}
|
|
92
|
+
</Tag>
|
|
93
|
+
</div>
|
|
94
|
+
<div className={styles.grid}>
|
|
95
|
+
{category.reports.map((report) => renderReportTile(report, category.tone))}
|
|
96
|
+
</div>
|
|
97
|
+
</section>
|
|
98
|
+
))
|
|
99
|
+
) : (
|
|
100
|
+
<Layer className={styles.emptyState}>
|
|
101
|
+
<Report size={32} className={styles.emptyStateIcon} />
|
|
102
|
+
<h5>No reports match “{searchTerm}”</h5>
|
|
103
|
+
<p>Try a form number such as 731, or a service such as immunization.</p>
|
|
104
|
+
<Button kind="ghost" size="sm" onClick={() => setSearchTerm('')}>
|
|
105
|
+
Clear search
|
|
106
|
+
</Button>
|
|
107
|
+
</Layer>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
44
110
|
);
|
|
45
111
|
};
|
|
46
112
|
|
|
@@ -1,14 +1,272 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
@use 'sass:list';
|
|
2
|
+
@use '@carbon/colors';
|
|
3
|
+
@use '@carbon/layout';
|
|
4
|
+
@use '@carbon/motion';
|
|
5
|
+
@use '@carbon/type';
|
|
6
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
|
7
|
+
|
|
8
|
+
$tones: (
|
|
9
|
+
'violet': (
|
|
10
|
+
colors.$purple-60,
|
|
11
|
+
colors.$purple-10,
|
|
12
|
+
),
|
|
13
|
+
'magenta': (
|
|
14
|
+
colors.$magenta-60,
|
|
15
|
+
colors.$magenta-10,
|
|
16
|
+
),
|
|
17
|
+
'teal': (
|
|
18
|
+
colors.$teal-60,
|
|
19
|
+
colors.$teal-10,
|
|
20
|
+
),
|
|
21
|
+
'blue': (
|
|
22
|
+
colors.$blue-60,
|
|
23
|
+
colors.$blue-10,
|
|
24
|
+
),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
.dashboard {
|
|
28
|
+
/* Horizontal gutter comes from `.page` in root.scss */
|
|
29
|
+
padding: layout.$spacing-05 0 layout.$spacing-07;
|
|
30
|
+
background-color: $openmrs-background-grey;
|
|
31
|
+
min-height: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Header */
|
|
35
|
+
|
|
36
|
+
.header {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
gap: layout.$spacing-03 layout.$spacing-04;
|
|
41
|
+
padding: layout.$spacing-03 layout.$spacing-05;
|
|
42
|
+
margin-bottom: layout.$spacing-04;
|
|
43
|
+
background-color: $ui-02;
|
|
44
|
+
border: 1px solid $ui-03;
|
|
45
|
+
border-left: layout.$spacing-02 solid var(--brand-01);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.headerIcon {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
flex-shrink: 0;
|
|
53
|
+
width: layout.$spacing-06;
|
|
54
|
+
height: layout.$spacing-06;
|
|
55
|
+
color: var(--brand-01);
|
|
56
|
+
background-color: $brand-primary-10;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.headerTitle {
|
|
60
|
+
@include type.type-style('productive-heading-03');
|
|
61
|
+
color: $color-gray-100;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.headerMeta {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: layout.$spacing-05;
|
|
68
|
+
margin-left: auto;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.metaItem {
|
|
72
|
+
@include type.type-style('label-01');
|
|
73
|
+
display: inline-flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
gap: layout.$spacing-02;
|
|
76
|
+
color: $text-02;
|
|
77
|
+
white-space: nowrap;
|
|
78
|
+
|
|
79
|
+
svg {
|
|
80
|
+
fill: var(--brand-01);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Toolbar */
|
|
85
|
+
|
|
86
|
+
.toolbar {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
gap: layout.$spacing-05;
|
|
90
|
+
margin-bottom: layout.$spacing-05;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.searchLayer {
|
|
94
|
+
flex: 1 1 auto;
|
|
95
|
+
max-width: 24rem;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.resultCount {
|
|
99
|
+
@include type.type-style('label-01');
|
|
100
|
+
color: $text-02;
|
|
101
|
+
white-space: nowrap;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Categories */
|
|
105
|
+
|
|
106
|
+
.category {
|
|
107
|
+
margin-bottom: layout.$spacing-06;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.categoryHeader {
|
|
111
|
+
display: flex;
|
|
112
|
+
align-items: center;
|
|
113
|
+
gap: layout.$spacing-03;
|
|
114
|
+
padding-left: layout.$spacing-03;
|
|
115
|
+
margin-bottom: layout.$spacing-04;
|
|
116
|
+
border-left: layout.$spacing-02 solid $ui-04;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.categoryTitle {
|
|
120
|
+
@include type.type-style('productive-heading-01');
|
|
121
|
+
color: $color-gray-100;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.grid {
|
|
125
|
+
display: grid;
|
|
126
|
+
grid-template-columns: repeat(3, 1fr);
|
|
127
|
+
gap: layout.$spacing-04;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Report tiles. Selectors are nested under `.grid` so they win over the
|
|
131
|
+
Carbon tile styles the app shell loads globally. */
|
|
132
|
+
|
|
133
|
+
.grid .tile {
|
|
134
|
+
position: relative;
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
gap: layout.$spacing-04;
|
|
138
|
+
min-height: 0;
|
|
139
|
+
padding: layout.$spacing-04;
|
|
140
|
+
background-color: $ui-02;
|
|
141
|
+
border: 1px solid $ui-03;
|
|
142
|
+
border-left: layout.$spacing-02 solid $ui-04;
|
|
143
|
+
text-decoration: none;
|
|
144
|
+
transition: all motion.$duration-fast-02 motion.motion(standard, productive);
|
|
145
|
+
|
|
146
|
+
&:hover {
|
|
147
|
+
background-color: $ui-02;
|
|
148
|
+
border-color: $ui-04;
|
|
149
|
+
box-shadow: 0 layout.$spacing-02 layout.$spacing-05 rgba(0, 0, 0, 0.1);
|
|
150
|
+
|
|
151
|
+
.tileArrow {
|
|
152
|
+
transform: translateX(layout.$spacing-02);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.tileIcon {
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
justify-content: center;
|
|
161
|
+
flex-shrink: 0;
|
|
162
|
+
width: layout.$spacing-07;
|
|
163
|
+
height: layout.$spacing-07;
|
|
164
|
+
background-color: $ui-01;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.tileCopy {
|
|
168
|
+
min-width: 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.tileCode {
|
|
172
|
+
@include type.type-style('label-01');
|
|
173
|
+
color: $text-02;
|
|
174
|
+
letter-spacing: 0.04em;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.tileName {
|
|
178
|
+
@include type.type-style('productive-heading-01');
|
|
179
|
+
color: $color-gray-100;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.tileArrow {
|
|
183
|
+
flex-shrink: 0;
|
|
184
|
+
margin-left: auto;
|
|
185
|
+
fill: $text-02;
|
|
186
|
+
transition: transform motion.$duration-fast-02 motion.motion(standard, productive);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Tone accents, applied per category */
|
|
190
|
+
|
|
191
|
+
@each $name, $tone in $tones {
|
|
192
|
+
$accent: list.nth($tone, 1);
|
|
193
|
+
$tint: list.nth($tone, 2);
|
|
194
|
+
|
|
195
|
+
.categoryHeader[data-tone='#{$name}'] {
|
|
196
|
+
border-left-color: $accent;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.grid .tile[data-tone='#{$name}'] {
|
|
200
|
+
border-left-color: $accent;
|
|
201
|
+
|
|
202
|
+
.tileIcon {
|
|
203
|
+
color: $accent;
|
|
204
|
+
background-color: $tint;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
&:hover {
|
|
208
|
+
border-color: $accent;
|
|
209
|
+
|
|
210
|
+
.tileArrow {
|
|
211
|
+
fill: $accent;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* Empty state */
|
|
218
|
+
|
|
219
|
+
.emptyState {
|
|
220
|
+
display: flex;
|
|
221
|
+
flex-direction: column;
|
|
222
|
+
align-items: center;
|
|
223
|
+
gap: layout.$spacing-03;
|
|
224
|
+
padding: layout.$spacing-07 layout.$spacing-05;
|
|
225
|
+
text-align: center;
|
|
226
|
+
background-color: $ui-02;
|
|
227
|
+
border: 1px solid $ui-03;
|
|
228
|
+
|
|
229
|
+
h5 {
|
|
230
|
+
@include type.type-style('productive-heading-02');
|
|
231
|
+
color: $color-gray-100;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
p {
|
|
235
|
+
@include type.type-style('body-long-01');
|
|
236
|
+
color: $text-02;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.emptyStateIcon {
|
|
241
|
+
fill: $ui-04;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@media (max-width: $breakpoint-tablet-max) {
|
|
245
|
+
.dashboard {
|
|
246
|
+
padding: layout.$spacing-05 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.headerMeta {
|
|
250
|
+
align-items: flex-start;
|
|
251
|
+
flex-wrap: wrap;
|
|
252
|
+
margin-left: 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.toolbar {
|
|
3
256
|
flex-wrap: wrap;
|
|
4
|
-
|
|
5
|
-
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.searchLayer {
|
|
260
|
+
max-width: none;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.grid {
|
|
264
|
+
grid-template-columns: repeat(2, 1fr);
|
|
265
|
+
}
|
|
6
266
|
}
|
|
7
267
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
text-align: center;
|
|
14
|
-
}
|
|
268
|
+
@media (max-width: $breakpoint-phone-max) {
|
|
269
|
+
.grid {
|
|
270
|
+
grid-template-columns: 1fr;
|
|
271
|
+
}
|
|
272
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,18 @@ import { reportsDashboardMeta } from './dashboard-meta/reports-dashboard.meta';
|
|
|
5
5
|
|
|
6
6
|
export const moduleName = '@ampath/esm-reports-app';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* The section this app's configuration is declared under.
|
|
10
|
+
*
|
|
11
|
+
* Not the package name: the AMPATH deployment's `o3-config.json` declares
|
|
12
|
+
* `@ampath/esm-reporting`, and there is no `@ampath/esm-reports-app` section in
|
|
13
|
+
* it. Registering the schema under the package name left `etlBaseUrl` on its
|
|
14
|
+
* empty default no matter what the deployment set, so every report failed with
|
|
15
|
+
* "the ETL base URL is not configured". Keep this in step with the config, not
|
|
16
|
+
* with `package.json`.
|
|
17
|
+
*/
|
|
18
|
+
export const configSectionName = '@ampath/esm-reporting';
|
|
19
|
+
|
|
8
20
|
const options = {
|
|
9
21
|
featureName: 'ampath-esm-reports',
|
|
10
22
|
moduleName,
|
|
@@ -13,7 +25,7 @@ const options = {
|
|
|
13
25
|
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
14
26
|
|
|
15
27
|
export function startupApp() {
|
|
16
|
-
defineConfigSchema(
|
|
28
|
+
defineConfigSchema(configSectionName, configSchema);
|
|
17
29
|
}
|
|
18
30
|
export const root = getAsyncLifecycle(() => import('./root.component'), options);
|
|
19
31
|
|
|
@@ -1,54 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
DataTable,
|
|
3
|
+
type DataTableHeader,
|
|
4
|
+
type DataTableRow,
|
|
5
|
+
Table,
|
|
6
|
+
TableBody,
|
|
7
|
+
TableCell,
|
|
8
|
+
TableHead,
|
|
9
|
+
TableHeader,
|
|
10
|
+
TableRow,
|
|
11
|
+
} from '@carbon/react';
|
|
12
|
+
import React from 'react';
|
|
3
13
|
|
|
4
14
|
interface DatatableWrapperProps {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
15
|
+
rows: Omit<DataTableRow<any[]>, 'cells'>[];
|
|
16
|
+
headers: DataTableHeader[];
|
|
17
|
+
subHeaders?: string[];
|
|
18
|
+
/** Applied to the table, so a register can use its own stylesheet */
|
|
19
|
+
className?: string;
|
|
8
20
|
}
|
|
9
21
|
|
|
10
|
-
const DatatableWrapper: React.FC<DatatableWrapperProps> = ({ rows, headers, subHeaders = [] }) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<TableBody>
|
|
41
|
-
{rows.map((row) => (
|
|
42
|
-
<TableRow {...getRowProps({ row })}>
|
|
43
|
-
{row.cells.map((cell) => (
|
|
44
|
-
<TableCell {...getCellProps({ cell })}>{cell.value}</TableCell>
|
|
45
|
-
))}
|
|
46
|
-
</TableRow>
|
|
47
|
-
))}
|
|
48
|
-
</TableBody>
|
|
49
|
-
</Table>
|
|
50
|
-
)}
|
|
22
|
+
const DatatableWrapper: React.FC<DatatableWrapperProps> = ({ rows, headers, subHeaders = [], className }) => {
|
|
23
|
+
return (
|
|
24
|
+
<DataTable rows={rows} headers={headers}>
|
|
25
|
+
{({ rows, headers, getTableProps, getHeaderProps, getRowProps, getCellProps }) => (
|
|
26
|
+
<Table {...getTableProps()} className={className}>
|
|
27
|
+
<TableHead>
|
|
28
|
+
<TableRow>
|
|
29
|
+
{headers.map((header) => (
|
|
30
|
+
<TableHeader {...getHeaderProps({ header })}>{header.header}</TableHeader>
|
|
31
|
+
))}
|
|
32
|
+
</TableRow>
|
|
33
|
+
{subHeaders && subHeaders.length && (
|
|
34
|
+
<TableRow>
|
|
35
|
+
{subHeaders.map((head, i) => (
|
|
36
|
+
<TableHeader key={i}>{head}</TableHeader>
|
|
37
|
+
))}
|
|
38
|
+
</TableRow>
|
|
39
|
+
)}
|
|
40
|
+
</TableHead>
|
|
41
|
+
<TableBody>
|
|
42
|
+
{rows.map((row) => (
|
|
43
|
+
<TableRow {...getRowProps({ row })}>
|
|
44
|
+
{row.cells.map((cell) => (
|
|
45
|
+
<TableCell {...getCellProps({ cell })}>{cell.value}</TableCell>
|
|
46
|
+
))}
|
|
47
|
+
</TableRow>
|
|
48
|
+
))}
|
|
49
|
+
</TableBody>
|
|
50
|
+
</Table>
|
|
51
|
+
)}
|
|
51
52
|
</DataTable>
|
|
52
|
-
|
|
53
|
+
);
|
|
54
|
+
};
|
|
53
55
|
|
|
54
|
-
export default DatatableWrapper;
|
|
56
|
+
export default DatatableWrapper;
|
|
@@ -1,61 +1,59 @@
|
|
|
1
|
-
import React, { useMemo } from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import TableWrapper from '../table-wrapper/table-wrapper.component';
|
|
4
|
+
import TableRowMapper from '../table-wrapper/table-row-mapper.component';
|
|
5
|
+
import { getCell } from '../../utils/utils';
|
|
5
6
|
import styles from './moh-240.scss';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
],
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
tableCells: [
|
|
18
|
-
getCell("", "Sub-County:", 1, 1, true),
|
|
19
|
-
getCell("", "", 3),
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
tableCells: [
|
|
24
|
-
getCell("", "Health Facility:", 1, 1, true),
|
|
25
|
-
getCell("", "", 3),
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
tableCells: [
|
|
30
|
-
getCell("", "KMHFL Code:", 1, 1, true),
|
|
31
|
-
getCell("", "", 3),
|
|
32
|
-
],
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
tableCells: [
|
|
36
|
-
getCell("", "Type:", 1, 1, true),
|
|
37
|
-
getCell("", ""),
|
|
38
|
-
getCell("", "Man. Agency:", 1, 1, true),
|
|
39
|
-
getCell("", ""),
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
tableCells: [
|
|
44
|
-
getCell("", "Start date:", 1, 1, true),
|
|
45
|
-
getCell("", ""),
|
|
46
|
-
getCell("", "End date:", 1, 1, true),
|
|
47
|
-
getCell("", ""),
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
];
|
|
51
|
-
}, []);
|
|
8
|
+
interface MOH240HeaderProps {
|
|
9
|
+
facility?: string;
|
|
10
|
+
startDate?: string;
|
|
11
|
+
endDate?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const asDate = (value?: string) => (value ? dayjs(value).format('DD/MM/YYYY') : '');
|
|
52
15
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
16
|
+
const MOH240Header: React.FC<MOH240HeaderProps> = ({ facility = '', startDate, endDate }) => {
|
|
17
|
+
const tableRows = useMemo(() => {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
tableCells: [getCell('', 'County:', 1, 1, true), getCell('', '', 3)],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
tableCells: [getCell('', 'Sub-County:', 1, 1, true), getCell('', '', 3)],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tableCells: [getCell('', 'Health Facility:', 1, 1, true), getCell('', facility, 3)],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
tableCells: [getCell('', 'KMHFL Code:', 1, 1, true), getCell('', '', 3)],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
tableCells: [
|
|
33
|
+
getCell('', 'Type:', 1, 1, true),
|
|
34
|
+
getCell('', ''),
|
|
35
|
+
getCell('', 'Man. Agency:', 1, 1, true),
|
|
36
|
+
getCell('', ''),
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
tableCells: [
|
|
41
|
+
getCell('', 'Start date:', 1, 1, true),
|
|
42
|
+
getCell('', asDate(startDate)),
|
|
43
|
+
getCell('', 'End date:', 1, 1, true),
|
|
44
|
+
getCell('', asDate(endDate)),
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
}, [facility, startDate, endDate]);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div className={styles.headerSection}>
|
|
52
|
+
<TableWrapper className={styles.formTable}>
|
|
53
|
+
<TableRowMapper tableRows={tableRows} />
|
|
54
|
+
</TableWrapper>
|
|
58
55
|
</div>
|
|
59
|
-
|
|
56
|
+
);
|
|
57
|
+
};
|
|
60
58
|
|
|
61
|
-
export default MOH240Header;
|
|
59
|
+
export default MOH240Header;
|