@ampath/esm-reports-app 1.0.0-next.77 → 1.0.0-next.79

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.
Files changed (30) hide show
  1. package/dist/{255.css → 177.css} +1 -1
  2. package/dist/177.css.map +1 -0
  3. package/dist/177.js +1 -0
  4. package/dist/177.js.map +1 -0
  5. package/dist/410.js +1 -1
  6. package/dist/ampath-esm-reports-app.js +1 -1
  7. package/dist/routes.json +1 -1
  8. package/package.json +1 -1
  9. package/src/registers/register-catalog.ts +74 -2
  10. package/src/reports/moh-710/registers/moh-413/moh-413.component.tsx +105 -53
  11. package/src/reports/moh-710/registers/moh-510/moh-510.component.tsx +158 -109
  12. package/src/reports/moh-711/moh-711.component.tsx +6 -1
  13. package/src/reports/moh-711/registers/moh-333-register.component.tsx +621 -580
  14. package/src/reports/moh-711/registers/moh-405-register.component.tsx +519 -475
  15. package/src/reports/moh-711/registers/moh-406-register.component.tsx +529 -480
  16. package/src/reports/moh-711/registers/moh-407-register.component.tsx +157 -0
  17. package/src/reports/moh-711/registers/moh-407.columns.ts +24 -0
  18. package/src/reports/moh-711/registers/moh-407.scss +64 -0
  19. package/src/reports/moh-711/registers/moh-512.component.tsx +102 -52
  20. package/src/reports/moh-711/registers/tb-register.component.tsx +5 -2
  21. package/src/reports/moh-711/sections/chanis.component.tsx +24 -1
  22. package/src/reports/moh-745/moh-745.component.tsx +1368 -331
  23. package/src/reports/moh-745/moh-745.scss +10 -0
  24. package/src/reports/moh-745/registers/moh-412-register.component.tsx +1 -1
  25. package/src/reports/moh-745/registers/type.ts +42 -0
  26. package/src/resources/moh-711.resource.ts +31 -31
  27. package/src/root.component.tsx +2 -0
  28. package/dist/255.css.map +0 -1
  29. package/dist/255.js +0 -1
  30. package/dist/255.js.map +0 -1
@@ -0,0 +1,157 @@
1
+ import React, { useState } from 'react';
2
+ import { RegisterLayout, usePatientList } from '../../../common/report-register';
3
+ import { useLocation, useSearchParams } from 'react-router-dom';
4
+ import classNames from 'classnames';
5
+ import { useSession } from '@openmrs/esm-framework';
6
+
7
+ import styles from './moh-407.scss';
8
+ import { Moh407xportColumns } from './moh-407.columns';
9
+ import { getMoh407PatientList } from '../../../resources/moh-711.resource';
10
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@carbon/react';
11
+ import { ReportFiltersComponent, type ReportPeriod } from '../../../common/report-filters';
12
+
13
+ interface Moh407RegisterComponentProps {}
14
+
15
+ const Moh407RegisterComponent: React.FC<Moh407RegisterComponentProps> = () => {
16
+ const [searchParams, setSearchParams] = useSearchParams();
17
+ const location = useLocation();
18
+ const session = useSession();
19
+
20
+ const from = searchParams.get('from');
21
+ const isDrilldown = Boolean(from);
22
+ const [generatedPeriod, setGeneratedPeriod] = useState<{ startDate: string; endDate: string } | null>(() => {
23
+ const startDate = searchParams.get('startDate');
24
+ const endDate = searchParams.get('endDate');
25
+ return !isDrilldown && startDate && endDate ? { startDate, endDate } : null;
26
+ });
27
+ const isGenerated = isDrilldown || Boolean(generatedPeriod);
28
+
29
+ const startDate = generatedPeriod?.startDate ?? searchParams.get('startDate');
30
+ const endDate = generatedPeriod?.endDate ?? searchParams.get('endDate');
31
+ const locationUuids = searchParams.get('locationUuids') ?? session?.sessionLocation?.uuid ?? '';
32
+ const indicator = searchParams.get('indicator');
33
+ const reportName = location.state?.reportName || 'moh711Report';
34
+
35
+ const {
36
+ rows: patientlist,
37
+ total,
38
+ isTotalExact,
39
+ isLoading,
40
+ page,
41
+ pageSize,
42
+ onPageChange,
43
+ fetchAll,
44
+ } = usePatientList(
45
+ ({ startIndex, limit }) => {
46
+ if (!isDrilldown && !generatedPeriod) {
47
+ return Promise.resolve({ results: [], total: 0, isTotalExact: true });
48
+ }
49
+
50
+ return getMoh407PatientList({
51
+ startDate,
52
+ endDate,
53
+ locationUuids,
54
+ indicator,
55
+ reportName,
56
+ startIndex,
57
+ limit,
58
+ from,
59
+ });
60
+ },
61
+ [startDate, endDate, locationUuids, indicator, reportName, from, isDrilldown, generatedPeriod],
62
+ );
63
+
64
+ const generate = ({ startDate, endDate }: ReportPeriod) => {
65
+ setGeneratedPeriod({ startDate, endDate });
66
+ setSearchParams((currentParams) => {
67
+ const nextParams = new URLSearchParams(currentParams);
68
+ nextParams.set('startDate', startDate);
69
+ nextParams.set('endDate', endDate);
70
+ if (!nextParams.has('locationUuids') && locationUuids) {
71
+ nextParams.set('locationUuids', locationUuids);
72
+ }
73
+ return nextParams;
74
+ });
75
+ };
76
+
77
+ return (
78
+ <>
79
+ {!isDrilldown && (
80
+ <ReportFiltersComponent
81
+ reportName="MOH 407 Register"
82
+ mode="range"
83
+ onGenerate={generate}
84
+ isLoading={isLoading}
85
+ isReportGenerated={Boolean(generatedPeriod)}
86
+ generatedPeriod={generatedPeriod ?? undefined}
87
+ backLink={{ label: 'All registers', to: '/?tab=registers' }}
88
+ />
89
+ )}
90
+ <RegisterLayout
91
+ parentLabel={isDrilldown ? 'MOH-711 Report' : 'All registers'}
92
+ parentPath={isDrilldown ? '/moh-711' : '/?tab=registers'}
93
+ title="MOH 407 Register"
94
+ isLoading={isLoading}
95
+ isEmpty={isGenerated && patientlist.length === 0}
96
+ page={page}
97
+ pageSize={pageSize}
98
+ total={total}
99
+ isTotalExact={isTotalExact}
100
+ onPageChange={onPageChange}
101
+ fetchAll={isGenerated ? fetchAll : undefined}
102
+ columns={Moh407xportColumns}
103
+ >
104
+ {isGenerated && (
105
+ <div className={styles.tableContainer}>
106
+ <Table className={classNames(`${styles.table}`, `${styles.tableBordered}`, `${styles.tableStriped}`)}>
107
+ <TableHead>
108
+ <TableRow>
109
+ <TableHeader aria-rowspan={2}>Serial Number</TableHeader>
110
+ <TableHeader aria-rowspan={2}>Date</TableHeader>
111
+ <TableHeader aria-rowspan={2}>National Identification Number</TableHeader>
112
+ <TableHeader aria-rowspan={2}>Patient Names</TableHeader>
113
+ <TableHeader aria-rowspan={2}>Patient Visit</TableHeader>
114
+ <TableHeader aria-rowspan={2}>Residence</TableHeader>
115
+ <TableHeader aria-rowspan={2}>Sex</TableHeader>
116
+ <TableHeader colSpan={2}>Age</TableHeader>
117
+ <TableHeader aria-rowspan={2}>Pregnant or Breastfeeding</TableHeader>
118
+ <TableHeader>Nutritional Assessment</TableHeader>
119
+ <TableHeader aria-rowspan={2}>Nutrition Status</TableHeader>
120
+ <TableHeader aria-rowspan={2}>Serostatus</TableHeader>
121
+ <TableHeader aria-rowspan={2}>Medical Condition</TableHeader>
122
+ <TableHeader aria-rowspan={2}>Food Secure</TableHeader>
123
+ <TableHeader aria-rowspan={2}>Nutrition Intervention</TableHeader>
124
+ <TableHeader aria-rowspan={2}>Remarks</TableHeader>
125
+ </TableRow>
126
+ <TableRow>
127
+ <TableHeader>Years</TableHeader>
128
+ <TableHeader>Months</TableHeader>
129
+ <TableHeader>Figure for z score</TableHeader>
130
+ </TableRow>
131
+ </TableHead>
132
+ <TableBody>
133
+ {patientlist.length > 0 ? (
134
+ patientlist.map((patient, index) => (
135
+ <TableRow key={patient.person_id || patient.id || index}>
136
+ {Moh407xportColumns.map((column, columnIndex) => (
137
+ <TableCell key={`${column.header}-${columnIndex}`}>
138
+ {String(column.value(patient, (page - 1) * pageSize + index) ?? '')}
139
+ </TableCell>
140
+ ))}
141
+ </TableRow>
142
+ ))
143
+ ) : (
144
+ <TableRow>
145
+ <TableCell colSpan={Moh407xportColumns.length}>No data available</TableCell>
146
+ </TableRow>
147
+ )}
148
+ </TableBody>
149
+ </Table>
150
+ </div>
151
+ )}
152
+ </RegisterLayout>
153
+ </>
154
+ );
155
+ };
156
+
157
+ export default Moh407RegisterComponent;
@@ -0,0 +1,24 @@
1
+ import { type RegisterColumn } from '../../../common/report-register/register-columns';
2
+
3
+ /**
4
+ * MOH 407 columns, flattened from the register's two-row table header.
5
+ */
6
+ export const Moh407xportColumns: RegisterColumn[] = [
7
+ { header: 'Serial Number', value: (_row, index) => index + 1 },
8
+ { header: 'Date', value: (row) => row.date ?? '' },
9
+ { header: 'National Identification Number', value: (row) => row.national_identification_number ?? '' },
10
+ { header: 'Patient Names', value: (row) => row.patient_names ?? '' },
11
+ { header: 'Patient Visit', value: (row) => row.patient_visit ?? '' },
12
+ { header: 'Residence', value: (row) => row.residence ?? '' },
13
+ { header: 'Sex', value: (row) => row.sex ?? '' },
14
+ { header: 'Age - Years', value: (row) => row.age_years ?? '' },
15
+ { header: 'Age - Months', value: (row) => row.age_months ?? '' },
16
+ { header: 'Pregnant or Breastfeeding', value: (row) => row.pregnant_or_breastfeeding ?? '' },
17
+ { header: 'Nutritional Assessment - Figure for z score', value: (row) => row.z_score ?? '' },
18
+ { header: 'Nutrition Status', value: (row) => row.nutrition_status ?? '' },
19
+ { header: 'Serostatus', value: (row) => row.serostatus ?? '' },
20
+ { header: 'Medical Condition', value: (row) => row.medical_condition ?? '' },
21
+ { header: 'Food Secure', value: (row) => row.food_secure ?? '' },
22
+ { header: 'Nutrition Intervention', value: (row) => row.nutrition_intervention ?? '' },
23
+ { header: 'Remarks', value: (row) => row.remarks ?? '' },
24
+ ];
@@ -0,0 +1,64 @@
1
+ @use '@openmrs/esm-styleguide/src/vars' as *;
2
+
3
+
4
+ .tableContainer {
5
+ width: 100%;
6
+ }
7
+
8
+ /* Sized to content rather than to the frame, so a long value -- a full name,
9
+ say -- widens its own column instead of wrapping. `.tableScroll` in the
10
+ layout scrolls when the table outgrows the page. */
11
+
12
+ .table {
13
+ width: auto;
14
+ min-width: 100%;
15
+ margin: 0;
16
+ font-size: 0.75rem;
17
+ border-collapse: collapse;
18
+ }
19
+
20
+ .tableBordered td,
21
+ .tableBordered th {
22
+ padding: 0.125rem 0.5rem;
23
+ font-size: 0.75rem;
24
+ line-height: 1.3;
25
+ border: 1px solid $ui-04;
26
+ }
27
+
28
+ .tableBordered th {
29
+ font-weight: 600;
30
+ color: $color-gray-100;
31
+ background-color: $ui-01;
32
+ /* headings carry deliberate line breaks, so they wrap where the markup says */
33
+ white-space: normal;
34
+ }
35
+
36
+ .tableBordered td {
37
+ white-space: nowrap;
38
+ }
39
+
40
+ /* Long prose columns (diagnoses, referrals, comments) wrap inside a bounded
41
+ width instead of stretching the row past the fold. */
42
+ .tableBordered td.wrapCell {
43
+ white-space: normal;
44
+ min-width: 8rem;
45
+ max-width: 16rem;
46
+ overflow-wrap: anywhere;
47
+ }
48
+
49
+ .tableStriped tbody tr:nth-of-type(odd) {
50
+ background-color: $ui-01;
51
+ }
52
+
53
+ .tableStriped tbody tr:hover {
54
+ background-color: $brand-primary-10;
55
+ }
56
+
57
+ .textCentre {
58
+ text-align: center;
59
+ }
60
+
61
+ .verticalText {
62
+ writing-mode: vertical-rl;
63
+ transform: rotate(180deg);
64
+ }
@@ -1,22 +1,35 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { useLocation, useSearchParams } from 'react-router-dom';
3
3
  import { RegisterLayout, usePatientList } from '../../../common/report-register';
4
4
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@carbon/react';
5
5
  import classNames from 'classnames';
6
+ import dayjs from 'dayjs';
7
+ import { useSession } from '@openmrs/esm-framework';
6
8
 
7
9
  import styles from './moh-512.scss';
8
10
  import { moh512ExportColumns } from './moh-512-columns';
9
11
  import { getMoh512PatientList } from '../../../resources/moh-711.resource';
12
+ import { ReportFiltersComponent, type ReportPeriod } from '../../../common/report-filters';
10
13
 
11
14
  interface Moh512RegisterComponentProps {}
12
15
 
13
16
  const Moh512RegisterComponent: React.FC<Moh512RegisterComponentProps> = () => {
14
- const [searchParams] = useSearchParams();
17
+ const [searchParams, setSearchParams] = useSearchParams();
15
18
  const location = useLocation();
19
+ const session = useSession();
16
20
 
17
- const startDate = searchParams.get('startDate');
18
- const endDate = searchParams.get('endDate');
19
- const locationUuids = searchParams.get('locationUuids');
21
+ const from = searchParams.get('from');
22
+ const isDrilldown = Boolean(from);
23
+ const [generatedPeriod, setGeneratedPeriod] = useState<{ startDate: string; endDate: string } | null>(() => {
24
+ const startDate = searchParams.get('startDate');
25
+ const endDate = searchParams.get('endDate');
26
+ return !isDrilldown && startDate && endDate ? { startDate, endDate } : null;
27
+ });
28
+ const isGenerated = isDrilldown || Boolean(generatedPeriod);
29
+
30
+ const startDate = generatedPeriod?.startDate ?? searchParams.get('startDate');
31
+ const endDate = generatedPeriod?.endDate ?? searchParams.get('endDate');
32
+ const locationUuids = searchParams.get('locationUuids') ?? session?.sessionLocation?.uuid ?? '';
20
33
  const indicator = searchParams.get('indicator');
21
34
  const reportName = location.state?.reportName || '';
22
35
 
@@ -30,8 +43,12 @@ const Moh512RegisterComponent: React.FC<Moh512RegisterComponentProps> = () => {
30
43
  onPageChange,
31
44
  fetchAll,
32
45
  } = usePatientList(
33
- ({ startIndex, limit }) =>
34
- getMoh512PatientList({
46
+ ({ startIndex, limit }) => {
47
+ if (!isDrilldown && !generatedPeriod) {
48
+ return Promise.resolve({ results: [], total: 0, isTotalExact: true });
49
+ }
50
+
51
+ return getMoh512PatientList({
35
52
  startDate,
36
53
  endDate,
37
54
  locationUuids,
@@ -39,10 +56,24 @@ const Moh512RegisterComponent: React.FC<Moh512RegisterComponentProps> = () => {
39
56
  reportName,
40
57
  startIndex,
41
58
  limit,
42
- }),
43
- [startDate, endDate, locationUuids, indicator, reportName],
59
+ });
60
+ },
61
+ [startDate, endDate, locationUuids, indicator, reportName, isDrilldown, generatedPeriod],
44
62
  );
45
63
 
64
+ const generate = ({ startDate, endDate }: ReportPeriod) => {
65
+ setGeneratedPeriod({ startDate, endDate });
66
+ setSearchParams((currentParams) => {
67
+ const nextParams = new URLSearchParams(currentParams);
68
+ nextParams.set('startDate', startDate);
69
+ nextParams.set('endDate', endDate);
70
+ if (!nextParams.has('locationUuids') && locationUuids) {
71
+ nextParams.set('locationUuids', locationUuids);
72
+ }
73
+ return nextParams;
74
+ });
75
+ };
76
+
46
77
  const columns = [
47
78
  { key: 'date', label: 'Date' },
48
79
  { key: 'cr_id', label: 'Client Number' },
@@ -89,52 +120,71 @@ const Moh512RegisterComponent: React.FC<Moh512RegisterComponentProps> = () => {
89
120
  ];
90
121
 
91
122
  return (
92
- <RegisterLayout
93
- parentLabel="MOH-711 Report"
94
- parentPath="/moh-711"
95
- title="MOH 512 Register"
96
- isLoading={isLoading}
97
- isEmpty={patientlist.length === 0}
98
- page={page}
99
- pageSize={pageSize}
100
- total={total}
101
- isTotalExact={isTotalExact}
102
- onPageChange={onPageChange}
103
- fetchAll={fetchAll}
104
- columns={moh512ExportColumns}
105
- >
106
- <div className={styles.tableContainer}>
107
- <Table className={classNames(styles.table, styles.tableBordered, styles.tableStriped)}>
108
- <TableHead>
109
- <TableRow>
110
- {columns.map((column) => (
111
- <TableHeader key={column.key}>{column.label}</TableHeader>
112
- ))}
113
- </TableRow>
114
- </TableHead>
115
-
116
- <TableBody>
117
- {isLoading ? (
118
- <TableRow>
119
- <TableCell colSpan={columns.length}>Loading register...</TableCell>
120
- </TableRow>
121
- ) : patientlist.length === 0 ? (
122
- <TableRow>
123
- <TableCell colSpan={columns.length}>No records found.</TableCell>
124
- </TableRow>
125
- ) : (
126
- patientlist.map((patient, index) => (
127
- <TableRow key={patient.person_id || patient.id || index}>
123
+ <>
124
+ {!isDrilldown && (
125
+ <ReportFiltersComponent
126
+ reportName="MOH 512 Register"
127
+ mode="range"
128
+ onGenerate={generate}
129
+ isLoading={isLoading}
130
+ isReportGenerated={Boolean(generatedPeriod)}
131
+ generatedPeriod={generatedPeriod ?? undefined}
132
+ backLink={{ label: 'All registers', to: '/?tab=registers' }}
133
+ />
134
+ )}
135
+ <RegisterLayout
136
+ parentLabel={isDrilldown ? 'MOH-711 Report' : 'All registers'}
137
+ parentPath={isDrilldown ? '/moh-711' : '/?tab=registers'}
138
+ title="MOH 512 Register"
139
+ isLoading={isLoading}
140
+ isEmpty={isGenerated && patientlist.length === 0}
141
+ page={page}
142
+ pageSize={pageSize}
143
+ total={total}
144
+ isTotalExact={isTotalExact}
145
+ onPageChange={onPageChange}
146
+ fetchAll={isGenerated ? fetchAll : undefined}
147
+ columns={moh512ExportColumns}
148
+ >
149
+ {isGenerated && (
150
+ <div className={styles.tableContainer}>
151
+ <Table className={classNames(styles.table, styles.tableBordered, styles.tableStriped)}>
152
+ <TableHead>
153
+ <TableRow>
128
154
  {columns.map((column) => (
129
- <TableCell key={column.key}>{patient[column.key] ?? ''}</TableCell>
155
+ <TableHeader key={column.key}>{column.label}</TableHeader>
130
156
  ))}
131
157
  </TableRow>
132
- ))
133
- )}
134
- </TableBody>
135
- </Table>
136
- </div>
137
- </RegisterLayout>
158
+ </TableHead>
159
+
160
+ <TableBody>
161
+ {isLoading ? (
162
+ <TableRow>
163
+ <TableCell colSpan={columns.length}>Loading register...</TableCell>
164
+ </TableRow>
165
+ ) : patientlist.length === 0 ? (
166
+ <TableRow>
167
+ <TableCell colSpan={columns.length}>No records found.</TableCell>
168
+ </TableRow>
169
+ ) : (
170
+ patientlist.map((patient, index) => (
171
+ <TableRow key={patient.person_id || patient.id || index}>
172
+ {columns.map((column) => (
173
+ <TableCell key={column.key}>
174
+ {column.key === 'date' && patient[column.key]
175
+ ? dayjs(patient[column.key]).format('YYYY-MM-DD')
176
+ : (patient[column.key] ?? '')}
177
+ </TableCell>
178
+ ))}
179
+ </TableRow>
180
+ ))
181
+ )}
182
+ </TableBody>
183
+ </Table>
184
+ </div>
185
+ )}
186
+ </RegisterLayout>
187
+ </>
138
188
  );
139
189
  };
140
190
 
@@ -3,6 +3,7 @@ import { useSearchParams } from 'react-router-dom';
3
3
  import { RegisterLayout, usePatientList } from '../../../common/report-register';
4
4
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@carbon/react';
5
5
  import classNames from 'classnames';
6
+ import dayjs from 'dayjs';
6
7
 
7
8
  import styles from './tb-register.scss';
8
9
  import { TBExportColumns } from './tb-register-columns';
@@ -70,9 +71,11 @@ const TbRegisterComponent: React.FC<TbRegisterComponentProps> = () => {
70
71
  {patientlist?.length > 0 ? (
71
72
  patientlist?.map((patient, i) => (
72
73
  <TableRow key={patient.person_id || patient.id}>
73
- <TableCell>{patient.date}</TableCell>
74
+ <TableCell>{patient.date ? dayjs(patient.date).format('YYYY-MM-DD') : ''}</TableCell>
74
75
  <TableCell>{patient.cr_id}</TableCell>
75
- <TableCell>{patient.date_of_birth}</TableCell>
76
+ <TableCell>
77
+ {patient.date_of_birth ? dayjs(patient.date_of_birth).format('YYYY-MM-DD') : ''}
78
+ </TableCell>
76
79
  <TableCell>{patient.gender}</TableCell>
77
80
  <TableCell>{patient.tb_screening}</TableCell>
78
81
  <TableCell>{patient.rtc}</TableCell>
@@ -1,15 +1,38 @@
1
1
  import React from 'react';
2
+ import { Button } from '@carbon/react';
3
+ import { useNavigate } from 'react-router-dom';
2
4
 
3
5
  import styles from '../moh711.scss';
4
6
  import classNames from 'classnames';
5
7
 
6
8
  interface ChanisComponentProps {
7
9
  moh711Data: any;
10
+ startDate: string;
11
+ endDate: string;
12
+ locationUuids: string;
8
13
  }
9
14
 
10
- const ChanisComponent: React.FC<ChanisComponentProps> = ({ moh711Data }) => {
15
+ const ChanisComponent: React.FC<ChanisComponentProps> = ({ moh711Data, startDate, endDate, locationUuids }) => {
16
+ const navigate = useNavigate();
17
+
18
+ const openRegister = () => {
19
+ const params = new URLSearchParams({
20
+ startDate,
21
+ endDate,
22
+ locationUuids,
23
+ from: 'moh-711',
24
+ });
25
+
26
+ navigate(`/moh-407-register?${params}`, {
27
+ state: { from: '/moh-711', reportName: 'moh711Report' },
28
+ });
29
+ };
30
+
11
31
  return (
12
32
  <div className={styles.section}>
33
+ <Button kind="ghost" size="sm" onClick={openRegister}>
34
+ Open MOH 407 Register
35
+ </Button>
13
36
  <table className={classNames(`${styles.table}`, `${styles.tableBordered}`, `${styles.tableStriped}`)}>
14
37
  <thead>
15
38
  <tr>