@ampath/esm-reports-app 1.0.0-next.55 → 1.0.0-next.57

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 (67) hide show
  1. package/dist/295.js +1 -1
  2. package/dist/410.js +1 -1
  3. package/dist/580.js +1 -0
  4. package/dist/580.js.map +1 -0
  5. package/dist/907.js +2 -1
  6. package/dist/907.js.map +1 -1
  7. package/dist/998.css +1 -0
  8. package/dist/998.css.map +1 -0
  9. package/dist/998.js +1 -0
  10. package/dist/998.js.map +1 -0
  11. package/dist/ampath-esm-reports-app.js +1 -1
  12. package/dist/routes.json +1 -1
  13. package/package.json +1 -1
  14. package/src/common/daily-summary-table.tsx +55 -0
  15. package/src/common/linelist-table/index.ts +3 -0
  16. package/src/common/linelist-table/linelist-columns.ts +48 -0
  17. package/src/common/linelist-table/linelist-table.component.tsx +442 -0
  18. package/src/common/linelist-table/linelist-table.scss +306 -0
  19. package/src/common/linelist-table/linelist-table.test.tsx +120 -0
  20. package/src/common/linelist-table/use-all-rows.ts +93 -0
  21. package/src/common/linelist-table/use-column-layout.ts +123 -0
  22. package/src/common/report-filters/report-filters.component.tsx +11 -5
  23. package/src/common/report-filters/report-filters.scss +63 -7
  24. package/src/common/report-page/use-page-scale.ts +27 -17
  25. package/src/common/report-placeholder/index.ts +1 -0
  26. package/src/common/report-placeholder/report-placeholder.component.tsx +57 -32
  27. package/src/common/report-placeholder/report-placeholder.scss +2 -0
  28. package/src/common/report-placeholder/use-generated-location.ts +62 -0
  29. package/src/common/report-register/index.ts +1 -0
  30. package/src/common/report-register/register-layout.component.tsx +26 -4
  31. package/src/common/report-register/register-layout.scss +10 -0
  32. package/src/common/report-register/use-location-name.ts +54 -0
  33. package/src/reports/moh-505/moh-505.component.tsx +9 -3
  34. package/src/reports/moh-705B/moh-204b-register.component.tsx +11 -2
  35. package/src/reports/moh-705B/moh-705b.component.tsx +533 -418
  36. package/src/reports/moh-705B/moh-705b.scss +44 -2
  37. package/src/reports/moh-705a/moh-705a.component.tsx +533 -421
  38. package/src/reports/moh-705a/moh-705a.scss +44 -2
  39. package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +12 -3
  40. package/src/reports/moh-706/moh-706.component.tsx +9 -3
  41. package/src/reports/moh-710/moh-710.component.tsx +9 -3
  42. package/src/reports/moh-711/moh-711.component.tsx +9 -3
  43. package/src/reports/moh-717/moh-717.component.tsx +12 -3
  44. package/src/reports/moh-731/linelist/moh-731-indicators.ts +1040 -0
  45. package/src/reports/moh-731/linelist/moh-731-linelist-sections.ts +423 -0
  46. package/src/reports/moh-731/linelist/moh-731-linelist.component.tsx +102 -0
  47. package/src/reports/moh-731/linelist/use-open-moh-731-linelist.ts +50 -0
  48. package/src/reports/moh-731/moh-731.component.tsx +138 -85
  49. package/src/reports/moh-731/moh-731.scss +51 -4
  50. package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +74 -77
  51. package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +84 -70
  52. package/src/reports/moh-731/sections/pmtct.component.tsx +43 -43
  53. package/src/reports/moh-731/summary/moh-731-summary.component.tsx +313 -0
  54. package/src/reports/moh-731/summary/moh-731-summary.config.ts +520 -0
  55. package/src/reports/moh-731/summary/moh-731-summary.scss +242 -0
  56. package/src/reports/moh-740/moh-740.component.scss +3 -1
  57. package/src/reports/moh-740/moh-740.component.tsx +14 -4
  58. package/src/reports/moh-745/moh-745.component.tsx +7 -3
  59. package/src/root.component.tsx +2 -0
  60. package/webpack.config.js +22 -1
  61. package/dist/427.js +0 -2
  62. package/dist/427.js.map +0 -1
  63. package/dist/441.js +0 -1
  64. package/dist/441.js.map +0 -1
  65. package/dist/907.css +0 -1
  66. package/dist/907.css.map +0 -1
  67. /package/dist/{427.js.LICENSE.txt → 907.js.LICENSE.txt} +0 -0
@@ -2,7 +2,7 @@ import React from 'react';
2
2
 
3
3
  import styles from '../moh-731.scss';
4
4
  import classNames from 'classnames';
5
- import { useNavigate } from 'react-router-dom';
5
+ import { useOpenMoh731Linelist } from '../linelist/use-open-moh-731-linelist';
6
6
 
7
7
  interface PmtctComponentProps {
8
8
  MOH731Data: any;
@@ -12,13 +12,7 @@ interface PmtctComponentProps {
12
12
  }
13
13
 
14
14
  const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate, endDate, locationUuids }) => {
15
- const navigate = useNavigate();
16
-
17
- const navigateToRegister = (indicator: string, gender: string, label: string) => {
18
- navigate(
19
- `/moh-366-register?startDate=${startDate}&endDate=${endDate}&locationUuids=${locationUuids}&indicator=${indicator}&gender=${gender}&label=${encodeURIComponent(label)}&from=moh-731`,
20
- );
21
- };
15
+ const openLinelist = useOpenMoh731Linelist(startDate, endDate, locationUuids);
22
16
  return (
23
17
  <>
24
18
  <div className={styles.flexRow}>
@@ -35,7 +29,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
35
29
  <td className={styles.textBox}>
36
30
  <span>HV02-01</span>
37
31
  <div
38
- onClick={() => navigateToRegister('known_positive_1st_anc', 'F', 'Known Positive at 1st ANC')}
32
+ onClick={() => openLinelist('HV02-01')}
39
33
  className={styles.rectangle}
40
34
  title="Click to open linelist"
41
35
  >
@@ -54,7 +48,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
54
48
  <td className={styles.textBox}>
55
49
  <span>HV02-02</span>
56
50
  <div
57
- onClick={() => navigateToRegister('initial_test_anc', 'F', 'Tested at ANC')}
51
+ onClick={() => openLinelist('HV02-02')}
58
52
  className={styles.rectangle}
59
53
  title="Click to open linelist"
60
54
  >
@@ -65,7 +59,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
65
59
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
66
60
  <span>HV02-03</span>
67
61
  <div
68
- onClick={() => navigateToRegister('retest_anc', 'F', 'Tested at ANC')}
62
+ onClick={() => openLinelist('HV02-03')}
69
63
  className={styles.rectangle}
70
64
  title="Click to open linelist"
71
65
  >
@@ -79,7 +73,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
79
73
  <td className={styles.textBox}>
80
74
  <span>HV02-04</span>
81
75
  <div
82
- onClick={() => navigateToRegister('initial_test_LD', 'F', 'Tested at L&D')}
76
+ onClick={() => openLinelist('HV02-04')}
83
77
  className={styles.rectangle}
84
78
  title="Click to open linelist"
85
79
  >
@@ -90,7 +84,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
90
84
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
91
85
  <span>HV02-05</span>
92
86
  <div
93
- onClick={() => navigateToRegister('retest_LD', 'F', 'Tested at L&D')}
87
+ onClick={() => openLinelist('HV02-05')}
94
88
  className={styles.rectangle}
95
89
  title="Click to open linelist"
96
90
  >
@@ -104,7 +98,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
104
98
  <td className={styles.textBox}>
105
99
  <span>HV02-06</span>
106
100
  <div
107
- onClick={() => navigateToRegister('initial_test_pnc_less_6_weeks', 'F', 'Tested at PNC_≤6weeks')}
101
+ onClick={() => openLinelist('HV02-06')}
108
102
  className={styles.rectangle}
109
103
  title="Click to open linelist"
110
104
  >
@@ -115,7 +109,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
115
109
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
116
110
  <span>HV02-07</span>
117
111
  <div
118
- onClick={() => navigateToRegister('retest_pnc_less_6_weeks', 'F', 'Tested at PNC_≤6weeks')}
112
+ onClick={() => openLinelist('HV02-07')}
119
113
  className={styles.rectangle}
120
114
  title="Click to open linelist"
121
115
  >
@@ -129,7 +123,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
129
123
  <td className={styles.textBox}>
130
124
  <span>HV02-08</span>
131
125
  <div
132
- onClick={() => navigateToRegister('initial_test_pnc_greater_6_weeks', 'F', 'Tested at PNC_>6weeks')}
126
+ onClick={() => openLinelist('HV02-08')}
133
127
  className={styles.rectangle}
134
128
  title="Click to open linelist"
135
129
  >
@@ -140,7 +134,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
140
134
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
141
135
  <span>HV02-09</span>
142
136
  <div
143
- onClick={() => navigateToRegister('retest_pnc_greater_6_weeks', 'F', 'Tested at PNC_>6weeks')}
137
+ onClick={() => openLinelist('HV02-09')}
144
138
  className={styles.rectangle}
145
139
  title="Click to open linelist"
146
140
  >
@@ -164,7 +158,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
164
158
  <td className={styles.textBox}>
165
159
  <span>HV02-10</span>
166
160
  <div
167
- onClick={() => navigateToRegister('positive_anc', 'F', 'Tested at ANC')}
161
+ onClick={() => openLinelist('HV02-10')}
168
162
  className={styles.rectangle}
169
163
  title="Click to open linelist"
170
164
  >
@@ -178,7 +172,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
178
172
  <td className={styles.textBox}>
179
173
  <span>HV02-11</span>
180
174
  <div
181
- onClick={() => navigateToRegister('positive_LD', 'F', 'Tested at L&D')}
175
+ onClick={() => openLinelist('HV02-11')}
182
176
  className={styles.rectangle}
183
177
  title="Click to open linelist"
184
178
  >
@@ -192,7 +186,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
192
186
  <td className={styles.textBox}>
193
187
  <span>HV02-12</span>
194
188
  <div
195
- onClick={() => navigateToRegister('positive_pnc_less_6_weeks', 'F', 'Tested at PNC_≤6weeks')}
189
+ onClick={() => openLinelist('HV02-12')}
196
190
  className={styles.rectangle}
197
191
  title="Click to open linelist"
198
192
  >
@@ -206,7 +200,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
206
200
  <td className={styles.textBox}>
207
201
  <span>HV02-13</span>
208
202
  <div
209
- onClick={() => navigateToRegister('positive_pnc_greater_6_weeks', 'F', 'Tested at PNC_>6weeks')}
203
+ onClick={() => openLinelist('HV02-13')}
210
204
  className={styles.rectangle}
211
205
  title="Click to open linelist"
212
206
  >
@@ -230,7 +224,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
230
224
  <td className={styles.textBox}>
231
225
  <span>HV02-14</span>
232
226
  <div
233
- onClick={() => navigateToRegister('maternal_haart_1st_anc', 'F', 'On HAART at 1st ANC')}
227
+ onClick={() => openLinelist('HV02-14')}
234
228
  className={styles.rectangle}
235
229
  title="Click to open linelist"
236
230
  >
@@ -244,7 +238,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
244
238
  <td className={styles.textBox}>
245
239
  <span>HV02-15</span>
246
240
  <div
247
- onClick={() => navigateToRegister('start_maternal_haart_1st_anc', 'F', 'Start HAART_ANC')}
241
+ onClick={() => openLinelist('HV02-15')}
248
242
  className={styles.rectangle}
249
243
  title="Click to open linelist"
250
244
  >
@@ -258,7 +252,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
258
252
  <td className={styles.textBox}>
259
253
  <span>HV02-16</span>
260
254
  <div
261
- onClick={() => navigateToRegister('start_maternal_haart_LD', 'F', 'Start HAART_L&D')}
255
+ onClick={() => openLinelist('HV02-16')}
262
256
  className={styles.rectangle}
263
257
  title="Click to open linelist"
264
258
  >
@@ -272,7 +266,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
272
266
  <td className={styles.textBox}>
273
267
  <span>HV02-17</span>
274
268
  <div
275
- onClick={() => navigateToRegister('maternal_haart_less_6_weeks', 'F', 'Start HAART_PNC_≤6weeks')}
269
+ onClick={() => openLinelist('HV02-17')}
276
270
  className={styles.rectangle}
277
271
  title="Click to open linelist"
278
272
  >
@@ -286,7 +280,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
286
280
  <td className={styles.textBox}>
287
281
  <span>HV02-18</span>
288
282
  <div
289
- onClick={() => navigateToRegister('maternal_haart_more_6_weeks', 'F', 'Start HAART_PNC_>6weeks')}
283
+ onClick={() => openLinelist('HV02-18')}
290
284
  className={styles.rectangle}
291
285
  title="Click to open linelist"
292
286
  >
@@ -311,7 +305,13 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
311
305
  <td>Screened_HBV_ANC</td>
312
306
  <td className={styles.textBox}>
313
307
  <span>HV02-19</span>
314
- <div className={styles.rectangle}></div>
308
+ <div
309
+ onClick={() => openLinelist('HV02-19')}
310
+ className={styles.rectangle}
311
+ title="Click to open linelist"
312
+ >
313
+ {MOH731Data.hbv_screened_anc}
314
+ </div>
315
315
  </td>
316
316
  <td></td>
317
317
  </tr>
@@ -320,7 +320,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
320
320
  <td className={styles.textBox}>
321
321
  <span>HV02-20</span>
322
322
  <div
323
- onClick={() => navigateToRegister('hbv_screened_positive_anc', 'F', 'HBV Screened_Positive')}
323
+ onClick={() => openLinelist('HV02-20')}
324
324
  className={styles.rectangle}
325
325
  title="Click to open linelist"
326
326
  >
@@ -351,7 +351,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
351
351
  <td className={styles.textBox}>
352
352
  <span>HV02-21</span>
353
353
  <div
354
- onClick={() => navigateToRegister('known_positive_anc_10_19', 'F', '1st ANC KP')}
354
+ onClick={() => openLinelist('HV02-21')}
355
355
  className={styles.rectangle}
356
356
  title="Click to open linelist"
357
357
  >
@@ -362,7 +362,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
362
362
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
363
363
  <span>HV02-22</span>
364
364
  <div
365
- onClick={() => navigateToRegister('known_positive_anc_20_24', 'F', '1st ANC KP')}
365
+ onClick={() => openLinelist('HV02-22')}
366
366
  className={styles.rectangle}
367
367
  title="Click to open linelist"
368
368
  >
@@ -376,7 +376,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
376
376
  <td className={styles.textBox}>
377
377
  <span>HV02-23</span>
378
378
  <div
379
- onClick={() => navigateToRegister('positive_anc_ld_pnc_10_19', 'F', 'New HIV Positive')}
379
+ onClick={() => openLinelist('HV02-23')}
380
380
  className={styles.rectangle}
381
381
  title="Click to open linelist"
382
382
  >
@@ -387,7 +387,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
387
387
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
388
388
  <span>HV02-24</span>
389
389
  <div
390
- onClick={() => navigateToRegister('positive_anc_ld_pnc_20_24', 'F', 'New HIV Positive')}
390
+ onClick={() => openLinelist('HV02-24')}
391
391
  className={styles.rectangle}
392
392
  title="Click to open linelist"
393
393
  >
@@ -401,7 +401,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
401
401
  <td className={styles.textBox}>
402
402
  <span>HV02-25</span>
403
403
  <div
404
- onClick={() => navigateToRegister('on_art_anc_10_19', 'F', 'On HAART 1st ANC KP')}
404
+ onClick={() => openLinelist('HV02-25')}
405
405
  className={styles.rectangle}
406
406
  title="Click to open linelist"
407
407
  >
@@ -412,7 +412,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
412
412
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
413
413
  <span>HV02-26</span>
414
414
  <div
415
- onClick={() => navigateToRegister('on_art_anc_20_24', 'F', 'On HAART 1st ANC KP')}
415
+ onClick={() => openLinelist('HV02-26')}
416
416
  className={styles.rectangle}
417
417
  title="Click to open linelist"
418
418
  >
@@ -426,7 +426,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
426
426
  <td className={styles.textBox}>
427
427
  <span>HV02-27</span>
428
428
  <div
429
- onClick={() => navigateToRegister('start_art_10_19', 'F', 'Started HAART New')}
429
+ onClick={() => openLinelist('HV02-27')}
430
430
  className={styles.rectangle}
431
431
  title="Click to open linelist"
432
432
  >
@@ -437,7 +437,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
437
437
  <div className={classNames(`${styles.textBox}`, `${styles.textBox2}`)}>
438
438
  <span>HV02-28</span>
439
439
  <div
440
- onClick={() => navigateToRegister('start_art_20_24', 'F', 'Started HAART New')}
440
+ onClick={() => openLinelist('HV02-28')}
441
441
  className={styles.rectangle}
442
442
  title="Click to open linelist"
443
443
  >
@@ -461,7 +461,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
461
461
  <td className={styles.textBox}>
462
462
  <span>HV02-29</span>
463
463
  <div
464
- onClick={() => navigateToRegister('infant_arv_anc', 'F', 'Infant ARV Prophylaxis_ANC')}
464
+ onClick={() => openLinelist('HV02-29')}
465
465
  className={styles.rectangle}
466
466
  title="Click to open linelist"
467
467
  >
@@ -475,7 +475,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
475
475
  <td className={styles.textBox}>
476
476
  <span>HV02-30</span>
477
477
  <div
478
- onClick={() => navigateToRegister('infant_arv_ld', 'F', 'Infant ARV Prophylaxis_L&D')}
478
+ onClick={() => openLinelist('HV02-30')}
479
479
  className={styles.rectangle}
480
480
  title="Click to open linelist"
481
481
  >
@@ -485,11 +485,11 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
485
485
  <td></td>
486
486
  </tr>
487
487
  <tr>
488
- <td>Infant ARV Prophylaxis_L&PNC</td>
488
+ <td>Infant ARV Prophylaxis_PNC</td>
489
489
  <td className={styles.textBox}>
490
490
  <span>HV02-31</span>
491
491
  <div
492
- onClick={() => navigateToRegister('infant_arv_pnc', 'F', 'Infant ARV Prophylaxis_L&PNC')}
492
+ onClick={() => openLinelist('HV02-31')}
493
493
  className={styles.rectangle}
494
494
  title="Click to open linelist"
495
495
  >
@@ -518,7 +518,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
518
518
  <td className={styles.textBox}>
519
519
  <span>HV02-32</span>
520
520
  <div
521
- onClick={() => navigateToRegister('exclusive_bf', 'F', 'Exclusive Breastfeeding (EBF)')}
521
+ onClick={() => openLinelist('HV02-32')}
522
522
  className={styles.rectangle}
523
523
  title="Click to open linelist"
524
524
  >
@@ -537,7 +537,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
537
537
  <td className={styles.textBox}>
538
538
  <span>HV02-33</span>
539
539
  <div
540
- onClick={() => navigateToRegister('bf', 'F', 'Breastfeeding (BF)')}
540
+ onClick={() => openLinelist('HV02-33')}
541
541
  className={styles.rectangle}
542
542
  title="Click to open linelist"
543
543
  >
@@ -551,7 +551,7 @@ const PmtctComponent: React.FC<PmtctComponentProps> = ({ MOH731Data, startDate,
551
551
  <td className={styles.textBox}>
552
552
  <span>HV02-34</span>
553
553
  <div
554
- onClick={() => navigateToRegister('weaning', 'F', 'Not Breastfeeding (NBF)')}
554
+ onClick={() => openLinelist('HV02-34')}
555
555
  className={styles.rectangle}
556
556
  title="Click to open linelist"
557
557
  >
@@ -0,0 +1,313 @@
1
+ import React, { useState } from 'react';
2
+ import classNames from 'classnames';
3
+ import { Button, Tab, TabList, TabPanel, TabPanels, Tabs, Toggle } from '@carbon/react';
4
+ import { Download } from '@carbon/react/icons';
5
+
6
+ import { columnsToCsv, downloadCsv } from '../../../common/report-register';
7
+ import { MOH_731_INDICATORS } from '../linelist/moh-731-indicators';
8
+ import { type Moh731LinelistTotal } from '../linelist/use-open-moh-731-linelist';
9
+ import {
10
+ MOH_731_SUMMARY,
11
+ rowTotalCodes,
12
+ type SummaryRow,
13
+ type SummarySection,
14
+ type SummaryTable,
15
+ } from './moh-731-summary.config';
16
+ import styles from './moh-731-summary.scss';
17
+
18
+ interface Moh731SummaryProps {
19
+ /** The report as generated: indicator key -> value */
20
+ data: Record<string, unknown>;
21
+ openLinelist: (figure: string | Moh731LinelistTotal) => void;
22
+ /** The section tab shown, by id */
23
+ sectionId: string;
24
+ onSectionChange: (sectionId: string) => void;
25
+ /** Used to name the export */
26
+ period: string;
27
+ }
28
+
29
+ const SHOW_CODES_KEY = 'ampath-moh731-summary-show-codes';
30
+
31
+ /** A figure's value, 0 where the report has none */
32
+ const valueOf = (data: Record<string, unknown>, code: string) => {
33
+ const indicator = MOH_731_INDICATORS[code]?.indicator;
34
+ return Number((indicator && data[indicator]) || 0);
35
+ };
36
+
37
+ const sum = (data: Record<string, unknown>, codes: string[]) =>
38
+ codes.reduce((total, code) => total + valueOf(data, code), 0);
39
+
40
+ /** The codes a table's Total row adds up: every row that counts towards the total */
41
+ const tableCodes = (table: SummaryTable) =>
42
+ table.rows.filter((row) => !row.ofWhich && !row.excluded).flatMap(rowTotalCodes);
43
+
44
+ const rowLabel = (row: SummaryRow) => (row.ofWhich ? `of which ${row.label}` : row.label);
45
+
46
+ const readShowCodes = () => {
47
+ try {
48
+ return localStorage.getItem(SHOW_CODES_KEY) === 'true';
49
+ } catch {
50
+ return false;
51
+ }
52
+ };
53
+
54
+ /**
55
+ * The MOH 731 report regrouped for reading: a tab per section, each sub-section
56
+ * as a compact table with a Total column and a Total row. Every number opens its
57
+ * linelist, and a total opens the linelists of the figures it adds up.
58
+ */
59
+ const Moh731Summary: React.FC<Moh731SummaryProps> = ({ data, openLinelist, sectionId, onSectionChange, period }) => {
60
+ const [showCodes, setShowCodes] = useState(readShowCodes);
61
+ const selectedIndex = Math.max(
62
+ 0,
63
+ MOH_731_SUMMARY.findIndex((section) => section.id === sectionId),
64
+ );
65
+
66
+ const toggleCodes = (checked: boolean) => {
67
+ setShowCodes(checked);
68
+ try {
69
+ localStorage.setItem(SHOW_CODES_KEY, String(checked));
70
+ } catch {
71
+ /* not remembered, still applied */
72
+ }
73
+ };
74
+
75
+ /* One figure opens its own linelist; several open as a total */
76
+ const open = (codes: string[], label: string, block: string) => {
77
+ if (codes.length === 1) {
78
+ openLinelist(codes[0]);
79
+ } else if (codes.length > 1) {
80
+ openLinelist({ codes, label, block });
81
+ }
82
+ };
83
+
84
+ /** A figure or total: its value, opening its linelist; the MOH code on hover (or shown) */
85
+ const value = (codes: string[], label: string, block: string, options: { strong?: boolean; code?: boolean } = {}) => {
86
+ if (codes.length === 0) {
87
+ return <span className={styles.none}>–</span>;
88
+ }
89
+ const amount = sum(data, codes);
90
+ const code = codes.length === 1 ? codes[0] : undefined;
91
+ return (
92
+ <button
93
+ type="button"
94
+ className={classNames(styles.value, { [styles.zero]: amount === 0, [styles.strong]: options.strong })}
95
+ onClick={() => open(codes, label, block)}
96
+ title={code ? `${code} · open the linelist` : `Open the ${label} linelist`}
97
+ >
98
+ {amount.toLocaleString()}
99
+ {showCodes && code && options.code !== false && <span className={styles.code}>{code}</span>}
100
+ </button>
101
+ );
102
+ };
103
+
104
+ const exportCsv = () => {
105
+ const lines: Array<Record<string, unknown>> = [];
106
+ MOH_731_SUMMARY.forEach((section) =>
107
+ section.subsections.forEach((sub) =>
108
+ sub.tables.forEach((table) => {
109
+ table.rows.forEach((row) => {
110
+ (row.cells ?? []).forEach((cell, index) => {
111
+ if (cell) {
112
+ lines.push({
113
+ section: section.title,
114
+ block: sub.block,
115
+ row: rowLabel(row),
116
+ column: table.columns[index],
117
+ code: cell,
118
+ value: valueOf(data, cell),
119
+ });
120
+ }
121
+ });
122
+ lines.push({
123
+ section: section.title,
124
+ block: sub.block,
125
+ row: rowLabel(row),
126
+ column: 'Total',
127
+ code: row.only ?? '',
128
+ value: sum(data, rowTotalCodes(row)),
129
+ });
130
+ });
131
+ if (table.totalLabel) {
132
+ lines.push({
133
+ section: section.title,
134
+ block: sub.block,
135
+ row: table.totalLabel,
136
+ column: 'Total',
137
+ code: '',
138
+ value: sum(data, tableCodes(table)),
139
+ });
140
+ }
141
+ }),
142
+ ),
143
+ );
144
+ downloadCsv(
145
+ columnsToCsv(lines, [
146
+ { header: 'Section', value: (line) => line.section },
147
+ { header: 'Sub-section', value: (line) => line.block },
148
+ { header: 'Row', value: (line) => line.row },
149
+ { header: 'Column', value: (line) => line.column },
150
+ { header: 'MOH 731 Code', value: (line) => line.code, text: true },
151
+ { header: 'Value', value: (line) => line.value },
152
+ ]),
153
+ `moh-731-summary-${period}.csv`.replace(/[^a-z0-9.-]+/gi, '-').toLowerCase(),
154
+ );
155
+ };
156
+
157
+ const renderTable = (table: SummaryTable, block: string, key: number) => {
158
+ const included = table.rows.filter((row) => !row.ofWhich && !row.excluded);
159
+ const hasTotalColumn = table.rowTotals !== false;
160
+ return (
161
+ <div key={key} className={styles.tableScroll}>
162
+ {table.title && <p className={styles.tableTitle}>{table.title}</p>}
163
+ <table className={classNames(styles.table, { [styles.single]: table.columns.length === 0 })}>
164
+ <thead>
165
+ <tr>
166
+ <th scope="col" className={styles.labelCol} />
167
+ {table.columns.map((column) => (
168
+ <th scope="col" key={column}>
169
+ {column}
170
+ </th>
171
+ ))}
172
+ {/* a table without a breakdown has one column of figures, not totals */}
173
+ {hasTotalColumn && (
174
+ <th scope="col" className={styles.totalCol}>
175
+ {table.columns.length ? 'Total' : 'Number'}
176
+ </th>
177
+ )}
178
+ </tr>
179
+ </thead>
180
+ <tbody>
181
+ {table.rows.map((row) => (
182
+ <tr
183
+ key={row.label}
184
+ className={classNames({ [styles.ofWhich]: row.ofWhich, [styles.excluded]: row.excluded })}
185
+ >
186
+ <th scope="row" className={styles.labelCol}>
187
+ {row.group && <span className={styles.group}>{row.group} · </span>}
188
+ {rowLabel(row)}
189
+ </th>
190
+ {table.columns.map((column, index) => (
191
+ <td key={column}>
192
+ {row.only
193
+ ? null
194
+ : value(row.cells?.[index] ? [row.cells[index] as string] : [], `${row.label} ${column}`, block)}
195
+ </td>
196
+ ))}
197
+ {/* the code is beside the row's own figures already; only a figure
198
+ shown in the Total column alone carries it here */}
199
+ {hasTotalColumn && (
200
+ <td className={styles.totalCol}>
201
+ {value(rowTotalCodes(row), `${row.label} total`, block, { code: Boolean(row.only) })}
202
+ </td>
203
+ )}
204
+ </tr>
205
+ ))}
206
+ </tbody>
207
+ {table.totalLabel && (
208
+ <tfoot>
209
+ <tr>
210
+ <th scope="row" className={styles.labelCol}>
211
+ {table.totalLabel}
212
+ </th>
213
+ {table.columns.map((column, index) => (
214
+ <td key={column}>
215
+ {value(
216
+ included.map((row) => row.cells?.[index]).filter((cell): cell is string => Boolean(cell)),
217
+ `${table.totalLabel} – ${column}`,
218
+ block,
219
+ { strong: true, code: false },
220
+ )}
221
+ </td>
222
+ ))}
223
+ {hasTotalColumn && (
224
+ <td className={styles.totalCol}>
225
+ {value(tableCodes(table), table.totalLabel, block, { strong: true, code: false })}
226
+ </td>
227
+ )}
228
+ </tr>
229
+ </tfoot>
230
+ )}
231
+ </table>
232
+ </div>
233
+ );
234
+ };
235
+
236
+ const renderSection = (section: SummarySection) => (
237
+ <>
238
+ {section.headlines.length > 0 && (
239
+ <div className={styles.strip}>
240
+ {section.headlines.map((headline) => {
241
+ const table = section.subsections
242
+ .find((sub) => sub.block === headline.block)
243
+ ?.tables.find((t) => t.totalLabel);
244
+ const codes = table ? tableCodes(table) : [];
245
+ return (
246
+ <button
247
+ type="button"
248
+ key={headline.block}
249
+ className={styles.headline}
250
+ onClick={() => open(codes, table?.totalLabel ?? headline.label, headline.block)}
251
+ >
252
+ <span className={styles.headlineLabel}>{headline.label}</span>
253
+ <span className={styles.headlineValue}>{sum(data, codes).toLocaleString()}</span>
254
+ </button>
255
+ );
256
+ })}
257
+ </div>
258
+ )}
259
+ <div className={styles.grid}>
260
+ {section.subsections.map((sub) => (
261
+ <div key={sub.block} className={styles.card}>
262
+ <h5 className={styles.cardTitle}>{sub.block}</h5>
263
+ {sub.note && <p className={styles.note}>{sub.note}</p>}
264
+ {sub.tables.map((table, index) => renderTable(table, sub.block, index))}
265
+ </div>
266
+ ))}
267
+ </div>
268
+ </>
269
+ );
270
+
271
+ return (
272
+ <div className={styles.summary}>
273
+ <Tabs
274
+ selectedIndex={selectedIndex}
275
+ onChange={({ selectedIndex: index }) => onSectionChange(MOH_731_SUMMARY[index].id)}
276
+ >
277
+ <div className={styles.bar}>
278
+ <TabList aria-label="MOH 731 sections" className={styles.sectionTabs}>
279
+ {MOH_731_SUMMARY.map((section) => (
280
+ <Tab key={section.id} title={section.title}>
281
+ {section.tab}
282
+ </Tab>
283
+ ))}
284
+ </TabList>
285
+ <div className={styles.tools}>
286
+ <Toggle
287
+ id="moh731-summary-codes"
288
+ size="sm"
289
+ labelText="Show MOH codes"
290
+ hideLabel
291
+ labelA="MOH codes"
292
+ labelB="MOH codes"
293
+ toggled={showCodes}
294
+ onToggle={toggleCodes}
295
+ />
296
+ <Button kind="ghost" size="sm" renderIcon={Download} onClick={exportCsv}>
297
+ Export CSV
298
+ </Button>
299
+ </div>
300
+ </div>
301
+ <TabPanels>
302
+ {MOH_731_SUMMARY.map((section) => (
303
+ <TabPanel key={section.id} className={styles.panel}>
304
+ {renderSection(section)}
305
+ </TabPanel>
306
+ ))}
307
+ </TabPanels>
308
+ </Tabs>
309
+ </div>
310
+ );
311
+ };
312
+
313
+ export default Moh731Summary;