@ampath/esm-reports-app 1.0.0-next.7 → 1.0.0-next.70

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 (258) hide show
  1. package/dist/197.js +1 -1
  2. package/dist/282.js +1 -1
  3. package/dist/282.js.map +1 -1
  4. package/dist/295.css +1 -0
  5. package/dist/295.css.map +1 -0
  6. package/dist/295.js +1 -0
  7. package/dist/295.js.map +1 -0
  8. package/dist/299.js +2 -0
  9. package/dist/299.js.LICENSE.txt +3 -0
  10. package/dist/299.js.map +1 -0
  11. package/dist/300.js +1 -1
  12. package/dist/311.js +1 -1
  13. package/dist/311.js.map +1 -1
  14. package/dist/335.js +1 -1
  15. package/dist/353.js +1 -1
  16. package/dist/353.js.map +1 -1
  17. package/dist/354.js +2 -0
  18. package/dist/354.js.LICENSE.txt +20 -0
  19. package/dist/354.js.map +1 -0
  20. package/dist/410.js +1 -0
  21. package/dist/410.js.map +1 -0
  22. package/dist/457.js +2 -0
  23. package/dist/457.js.LICENSE.txt +261 -0
  24. package/dist/457.js.map +1 -0
  25. package/dist/478.js +1 -1
  26. package/dist/478.js.map +1 -1
  27. package/dist/480.js +1 -0
  28. package/dist/540.js +1 -1
  29. package/dist/540.js.map +1 -1
  30. package/dist/55.js +1 -1
  31. package/dist/580.js +1 -0
  32. package/dist/580.js.map +1 -0
  33. package/dist/600.js +2 -0
  34. package/dist/600.js.LICENSE.txt +35 -0
  35. package/dist/600.js.map +1 -0
  36. package/dist/652.js +1 -1
  37. package/dist/781.js +1 -0
  38. package/dist/781.js.map +1 -0
  39. package/dist/919.css +1 -0
  40. package/dist/919.css.map +1 -0
  41. package/dist/919.js +1 -0
  42. package/dist/919.js.map +1 -0
  43. package/dist/961.js +1 -1
  44. package/dist/961.js.map +1 -1
  45. package/dist/99.js +1 -1
  46. package/dist/99.js.map +1 -0
  47. package/dist/ampath-esm-reports-app.js +1 -1
  48. package/dist/ampath-esm-reports-app.js.map +1 -1
  49. package/dist/routes.json +1 -1
  50. package/package.json +4 -2
  51. package/src/common/daily-summary-table.tsx +55 -0
  52. package/src/common/linelist-table/index.ts +3 -0
  53. package/src/common/linelist-table/linelist-columns.ts +48 -0
  54. package/src/common/linelist-table/linelist-table.component.tsx +442 -0
  55. package/src/common/linelist-table/linelist-table.scss +306 -0
  56. package/src/common/linelist-table/linelist-table.test.tsx +120 -0
  57. package/src/common/linelist-table/use-all-rows.ts +93 -0
  58. package/src/common/linelist-table/use-column-layout.ts +123 -0
  59. package/src/common/report-error/index.ts +1 -0
  60. package/src/common/report-error/show-report-error.ts +25 -0
  61. package/src/common/report-filters/date-range.ts +137 -0
  62. package/src/common/report-filters/index.ts +4 -0
  63. package/src/common/report-filters/report-filters.component.tsx +317 -99
  64. package/src/common/report-filters/report-filters.scss +255 -32
  65. package/src/common/report-filters/types.ts +79 -0
  66. package/src/common/report-filters/use-restore-period.ts +43 -0
  67. package/src/common/report-header/index.ts +1 -0
  68. package/src/common/report-header/use-location-details.ts +58 -0
  69. package/src/common/report-page/download-sheet-pdf.ts +59 -0
  70. package/src/common/report-page/index.ts +3 -0
  71. package/src/common/report-page/report-page.component.tsx +32 -0
  72. package/src/common/report-page/report-page.scss +45 -0
  73. package/src/common/report-page/use-page-scale.ts +60 -0
  74. package/src/common/report-placeholder/has-report-data.ts +15 -0
  75. package/src/common/report-placeholder/index.ts +3 -0
  76. package/src/common/report-placeholder/report-placeholder.component.tsx +81 -0
  77. package/src/common/report-placeholder/report-placeholder.scss +48 -0
  78. package/src/common/report-placeholder/use-generated-location.ts +62 -0
  79. package/src/common/report-register/index.ts +6 -0
  80. package/src/common/report-register/register-columns.ts +46 -0
  81. package/src/common/report-register/register-layout.component.tsx +265 -0
  82. package/src/common/report-register/register-layout.scss +150 -0
  83. package/src/common/report-register/register-table.scss +71 -0
  84. package/src/common/report-register/report-parents.ts +27 -0
  85. package/src/common/report-register/rows-to-csv.ts +89 -0
  86. package/src/common/report-register/use-location-name.ts +54 -0
  87. package/src/common/report-register/use-patient-list.ts +92 -0
  88. package/src/common/report-skeleton/index.ts +1 -0
  89. package/src/common/report-skeleton/report-skeleton.component.tsx +46 -0
  90. package/src/common/report-skeleton/report-skeleton.scss +29 -0
  91. package/src/config-schema.ts +9 -1
  92. package/src/dashboard/report-catalog.ts +173 -0
  93. package/src/dashboard/reports-dasboard.tsx +189 -18
  94. package/src/dashboard/reports-dashboard.module.scss +357 -14
  95. package/src/index.ts +13 -1
  96. package/src/registers/moh-240/moh-240-register.scss +41 -0
  97. package/src/registers/moh-240/moh-240.component.test.tsx +166 -0
  98. package/src/registers/moh-240/moh-240.component.tsx +164 -0
  99. package/src/registers/moh-362/moh-362-lab-register.component.tsx +392 -0
  100. package/src/registers/moh-362/moh-362-linkage-register.component.tsx +120 -0
  101. package/src/registers/moh-362/moh-362-register.scss +222 -0
  102. package/src/registers/moh-362/moh-362.component.tsx +99 -0
  103. package/src/registers/moh-362/moh-362.scss +11 -0
  104. package/src/registers/moh-362/moh-362.types.ts +97 -0
  105. package/src/registers/register-catalog.ts +80 -0
  106. package/src/registers/tb-lab-register/tb-lab-register-table.component.tsx +116 -0
  107. package/src/registers/tb-lab-register/tb-lab-register-table.scss +123 -0
  108. package/src/registers/tb-lab-register/tb-lab-register.columns.ts +164 -0
  109. package/src/registers/tb-lab-register/tb-lab-register.component.test.tsx +232 -0
  110. package/src/registers/tb-lab-register/tb-lab-register.component.tsx +153 -0
  111. package/src/reports/datatable-wrapper/datatable-wrapper.component.tsx +63 -48
  112. package/src/reports/moh-240/moh-240-header.component.tsx +62 -0
  113. package/src/reports/moh-240/moh-240.columns.ts +113 -0
  114. package/src/reports/moh-240/moh-240.component.tsx +72 -9
  115. package/src/reports/moh-240/moh-240.scss +40 -0
  116. package/src/reports/moh-240/sub-reports/moh-240-register.component.tsx +31 -37
  117. package/src/reports/moh-240/sub-reports/page-summary.component.tsx +143 -106
  118. package/src/reports/moh-505/moh-505-header.component.tsx +67 -0
  119. package/src/reports/moh-505/moh-505.component.tsx +441 -0
  120. package/src/reports/moh-505/moh-505.scss +117 -0
  121. package/src/reports/moh-705B/moh-204b-register.component.tsx +244 -0
  122. package/src/reports/moh-705B/moh-204b.columns.ts +39 -0
  123. package/src/reports/moh-705B/moh-705b.component.tsx +659 -0
  124. package/src/reports/moh-705B/moh-705b.scss +172 -0
  125. package/src/reports/moh-705a/moh-705a.component.tsx +661 -0
  126. package/src/reports/moh-705a/moh-705a.scss +172 -0
  127. package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +329 -0
  128. package/src/reports/moh-705a/registers/moh-204a.columns.ts +57 -0
  129. package/src/reports/moh-705a/type.ts +6 -0
  130. package/src/reports/moh-706/moh-706-header.component.tsx +66 -0
  131. package/src/reports/moh-706/moh-706.component.tsx +150 -24
  132. package/src/reports/moh-706/moh-706.scss +119 -11
  133. package/src/reports/moh-706/sub-reports/bacteriology/bacteriology.component.tsx +54 -62
  134. package/src/reports/moh-706/sub-reports/blood-chemistry/blood-chemistry.component.tsx +228 -317
  135. package/src/reports/moh-706/sub-reports/drug-susceptibility-testing/drug-susceptibility-testing.component.tsx +31 -46
  136. package/src/reports/moh-706/sub-reports/haematology/haematology.component.tsx +47 -55
  137. package/src/reports/moh-706/sub-reports/histology-and-cytology/histology-and-cytology.component.tsx +43 -58
  138. package/src/reports/moh-706/sub-reports/parasitology/parasitology.component.tsx +31 -39
  139. package/src/reports/moh-706/sub-reports/serology/serology.component.tsx +26 -34
  140. package/src/reports/moh-706/sub-reports/specimen-referral-to-higher-levels/specimen-referral-to-higher-levels.component.tsx +9 -24
  141. package/src/reports/moh-706/sub-reports/urine-analysis/urine-analysis.component.tsx +43 -51
  142. package/src/reports/moh-710/moh-710.component.tsx +799 -632
  143. package/src/reports/moh-710/moh-710.scss +142 -21
  144. package/src/reports/moh-710/registers/moh-510/moh-510.columns.ts +40 -0
  145. package/src/reports/moh-710/registers/moh-510/moh-510.component.tsx +144 -0
  146. package/src/reports/moh-710/registers/moh-510/moh-510.scss +130 -0
  147. package/src/reports/moh-710/registers/moh-511-710-register.component.tsx +268 -0
  148. package/src/reports/moh-710/registers/moh-511-710.columns.ts +52 -0
  149. package/src/reports/moh-710/registers/type.ts +31 -0
  150. package/src/reports/moh-711/moh-711.component.tsx +138 -1269
  151. package/src/reports/moh-711/moh711.scss +135 -20
  152. package/src/reports/moh-711/registers/moh-333-register.component.tsx +637 -0
  153. package/src/reports/moh-711/registers/moh-333.columns.ts +119 -0
  154. package/src/reports/moh-711/registers/moh-405-register.component.tsx +520 -0
  155. package/src/reports/moh-711/registers/moh-405.columns.ts +120 -0
  156. package/src/reports/moh-711/registers/moh-406-register.component.tsx +530 -0
  157. package/src/reports/moh-711/registers/moh-406.columns.ts +133 -0
  158. package/src/reports/moh-711/registers/moh-510-register.component.tsx +55 -0
  159. package/src/reports/moh-711/registers/moh-511-register.component.tsx +270 -0
  160. package/src/reports/moh-711/registers/moh-511.columns.ts +59 -0
  161. package/src/reports/moh-711/registers/type.ts +192 -0
  162. package/src/reports/moh-711/sections/anc.component.tsx +159 -0
  163. package/src/reports/moh-711/sections/cervical-cancer.component.tsx +148 -0
  164. package/src/reports/moh-711/sections/chanis.component.tsx +366 -0
  165. package/src/reports/moh-711/sections/family-planning.component.tsx +221 -0
  166. package/src/reports/moh-711/sections/gbv.component.tsx +115 -0
  167. package/src/reports/moh-711/sections/maternity.component.tsx +321 -0
  168. package/src/reports/moh-711/sections/medical-social-work.component.tsx +73 -0
  169. package/src/reports/moh-711/sections/other.component.tsx +47 -0
  170. package/src/reports/moh-711/sections/physiotherapy.component.tsx +61 -0
  171. package/src/reports/moh-711/sections/pnc.component.tsx +127 -0
  172. package/src/reports/moh-711/sections/post-abortion.component.tsx +42 -0
  173. package/src/reports/moh-711/sections/rehabilitation.component.tsx +57 -0
  174. package/src/reports/moh-711/sections/report-compiled-by.component.tsx +50 -0
  175. package/src/reports/moh-711/sections/tb-screening.component.tsx +57 -0
  176. package/src/reports/moh-717/moh-717.component.tsx +149 -985
  177. package/src/reports/moh-717/moh717.scss +217 -21
  178. package/src/reports/moh-717/registers/nutrition-register.component.tsx +48 -0
  179. package/src/reports/moh-717/sections/finance.component.tsx +42 -0
  180. package/src/reports/moh-717/sections/inpatient.component.tsx +374 -0
  181. package/src/reports/moh-717/sections/maternity.component.tsx +126 -0
  182. package/src/reports/moh-717/sections/medical-records.component.tsx +35 -0
  183. package/src/reports/moh-717/sections/mortuary.component.tsx +43 -0
  184. package/src/reports/moh-717/sections/operations.component.tsx +53 -0
  185. package/src/reports/moh-717/sections/orthopaedic-trauma.component.tsx +98 -0
  186. package/src/reports/moh-717/sections/outpatient.component.tsx +597 -0
  187. package/src/reports/moh-717/sections/pharmacy.component.tsx +43 -0
  188. package/src/reports/moh-717/sections/preparedby.component.tsx +52 -0
  189. package/src/reports/moh-717/sections/special-services.component.tsx +114 -0
  190. package/src/reports/moh-731/linelist/moh-731-indicators.ts +1122 -0
  191. package/src/reports/moh-731/linelist/moh-731-linelist-sections.ts +472 -0
  192. package/src/reports/moh-731/linelist/moh-731-linelist.component.tsx +102 -0
  193. package/src/reports/moh-731/linelist/use-open-moh-731-linelist.ts +50 -0
  194. package/src/reports/moh-731/moh-731.component.tsx +266 -0
  195. package/src/reports/moh-731/moh-731.scss +499 -0
  196. package/src/reports/moh-731/registers/moh-366.columns.ts +38 -0
  197. package/src/reports/moh-731/registers/moh-366.component.tsx +471 -0
  198. package/src/reports/moh-731/registers/prep-register.component.tsx +284 -0
  199. package/src/reports/moh-731/registers/prep.columns.ts +34 -0
  200. package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +1206 -0
  201. package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +727 -0
  202. package/src/reports/moh-731/sections/pmtct.component.tsx +572 -0
  203. package/src/reports/moh-731/summary/moh-731-summary.component.tsx +313 -0
  204. package/src/reports/moh-731/summary/moh-731-summary.config.ts +529 -0
  205. package/src/reports/moh-731/summary/moh-731-summary.scss +242 -0
  206. package/src/reports/moh-740/moh-740.component.scss +202 -0
  207. package/src/reports/moh-740/moh-740.component.tsx +1332 -0
  208. package/src/reports/moh-740/moh-740.resource.ts +54 -0
  209. package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.tsx +149 -0
  210. package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.tsx +123 -0
  211. package/src/reports/moh-740/registers/moh-740-patient-list.scss +0 -0
  212. package/src/reports/moh-740/registers/moh-740-patient-list.tsx +60 -0
  213. package/src/reports/moh-740/registers/moh-740.columns.ts +54 -0
  214. package/src/reports/moh-740/shared/data-cell/data-cell.scss +6 -0
  215. package/src/reports/moh-740/shared/data-cell/data-cell.tsx +23 -0
  216. package/src/reports/moh-740/shared/utils/indicator-register-map.ts +159 -0
  217. package/src/reports/moh-740/types/index.ts +223 -0
  218. package/src/reports/moh-745/moh-745.component.tsx +1021 -0
  219. package/src/reports/moh-745/moh-745.scss +132 -0
  220. package/src/reports/moh-745/registers/moh-412-register.component.tsx +199 -0
  221. package/src/reports/moh-745/registers/moh-412.columns.ts +52 -0
  222. package/src/reports/moh-745/registers/type.ts +181 -0
  223. package/src/reports/table-wrapper/table-row-mapper.component.tsx +57 -0
  224. package/src/reports/table-wrapper/table-wrapper.component.tsx +23 -14
  225. package/src/reports/table-wrapper/table-wrapper.scss +1 -16
  226. package/src/resources/moh-362.resource.ts +27 -0
  227. package/src/resources/moh-505.resource.ts +69 -0
  228. package/src/resources/moh-705.resource.ts +106 -0
  229. package/src/resources/moh-706.resource.ts +80 -0
  230. package/src/resources/moh-710.resource.ts +32 -9
  231. package/src/resources/moh-711.resource.ts +137 -9
  232. package/src/resources/moh-717.resource.ts +26 -9
  233. package/src/resources/moh-731.resource.ts +90 -0
  234. package/src/resources/moh-745.resource.ts +76 -0
  235. package/src/resources/patient-list-page.ts +65 -0
  236. package/src/root.component.tsx +59 -8
  237. package/src/root.scss +36 -0
  238. package/src/routes.json +3 -1
  239. package/src/utils/format-indicator.ts +39 -0
  240. package/src/utils/get-base-url.ts +39 -7
  241. package/src/utils/utils.ts +36 -0
  242. package/tsconfig.json +1 -1
  243. package/webpack.config.js +22 -1
  244. package/dist/138.js +0 -2
  245. package/dist/138.js.LICENSE.txt +0 -20
  246. package/dist/138.js.map +0 -1
  247. package/dist/184.js +0 -2
  248. package/dist/184.js.LICENSE.txt +0 -14
  249. package/dist/184.js.map +0 -1
  250. package/dist/205.js +0 -1
  251. package/dist/205.js.map +0 -1
  252. package/dist/711.js +0 -1
  253. package/dist/711.js.map +0 -1
  254. package/dist/812.js +0 -1
  255. package/dist/812.js.map +0 -1
  256. package/dist/ampath-esm-reports-app.js.buildmanifest.json +0 -539
  257. package/dist/main.js +0 -1
  258. package/dist/main.js.map +0 -1
@@ -0,0 +1,392 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ AGE_BANDS,
5
+ clientName,
6
+ finalResult,
7
+ formDate,
8
+ inBand,
9
+ testResult,
10
+ text,
11
+ type Moh362Row,
12
+ } from './moh-362.types';
13
+ import styles from './moh-362-register.scss';
14
+
15
+ interface Moh362LabRegisterProps {
16
+ rows: Moh362Row[];
17
+ }
18
+
19
+ const COLUMN_IDS = 'abcdefghijklmnopqr'.split('');
20
+
21
+ const count = (rows: Moh362Row[], test: (row: Moh362Row) => boolean) => rows.filter(test).length;
22
+
23
+ /** One HIV test's header cell: the test, then kit, lot and expiry lines, then its result codes */
24
+ const TestHeader: React.FC<{ test: string; codes: string }> = ({ test, codes }) => (
25
+ <th className={styles.testHeader}>
26
+ <span>{test}</span>
27
+ <span>Kit Name:</span>
28
+ <span>Lot No.</span>
29
+ <span>Expiry Date</span>
30
+ <span className={styles.dateRule}>____/____/____</span>
31
+ <span>{codes}</span>
32
+ </th>
33
+ );
34
+
35
+ /** One client's HIV test: the result, with the kit, lot and expiry used beneath it */
36
+ const TestCell: React.FC<{ result: unknown; kit: unknown; lot: unknown; expiry: unknown }> = ({
37
+ result,
38
+ kit,
39
+ lot,
40
+ expiry,
41
+ }) => {
42
+ const detail = [text(kit), text(lot), formDate(expiry)].filter(Boolean).join(' · ');
43
+ return (
44
+ <td rowSpan={2} className={styles.testCell}>
45
+ <strong>{testResult(result)}</strong>
46
+ {detail && <span className={styles.testDetail}>{detail}</span>}
47
+ </td>
48
+ );
49
+ };
50
+
51
+ /** A Tests (n) / Positive (n) block: age bands by sex, with totals */
52
+ const AgeSexSummary: React.FC<{ title: string; rows: Moh362Row[] }> = ({ title, rows }) => {
53
+ const sexes: Array<{ label: string; code: string }> = [
54
+ { label: 'Male', code: 'M' },
55
+ { label: 'Female', code: 'F' },
56
+ ];
57
+ return (
58
+ <table className={styles.summaryTable}>
59
+ <thead>
60
+ <tr>
61
+ <th className={styles.summaryLabel}>{title}</th>
62
+ {AGE_BANDS.map((band) => (
63
+ <th key={band.label}>{band.label}</th>
64
+ ))}
65
+ <th>Total</th>
66
+ </tr>
67
+ </thead>
68
+ <tbody>
69
+ {sexes.map((sex) => {
70
+ const ofSex = rows.filter((row) => row.sex === sex.code);
71
+ return (
72
+ <tr key={sex.code}>
73
+ <th className={styles.summaryLabel}>{sex.label}</th>
74
+ {AGE_BANDS.map((band) => (
75
+ <td key={band.label}>{count(ofSex, (row) => inBand(row, band))}</td>
76
+ ))}
77
+ <td>{ofSex.length}</td>
78
+ </tr>
79
+ );
80
+ })}
81
+ <tr>
82
+ <th className={styles.summaryLabel}>Total</th>
83
+ {AGE_BANDS.map((band) => (
84
+ <td key={band.label}>{count(rows, (row) => inBand(row, band))}</td>
85
+ ))}
86
+ <td>{rows.length}</td>
87
+ </tr>
88
+ </tbody>
89
+ </table>
90
+ );
91
+ };
92
+
93
+ /**
94
+ * MOH 362: HTS LAB REGISTER (Ver. July 2023), page 5 of the MOH 362 form: one
95
+ * row per client tested, columns (a) to (r), and the summary blocks beneath.
96
+ */
97
+ const Moh362LabRegister: React.FC<Moh362LabRegisterProps> = ({ rows }) => {
98
+ const positives = rows.filter((row) => row.final_result === 'P');
99
+ const isKvp = (row: Moh362Row) => String(row.population_type ?? '') === '2';
100
+ const testTotals = (field: 'hiv_test1' | 'hiv_test2' | 'hiv_test3') => {
101
+ const by = (code: string) => count(rows, (row) => testResult(row[field]) === code);
102
+ const n = by('N');
103
+ const p = by('P');
104
+ const i = by('I');
105
+ return { n, p, i, total: n + p + i };
106
+ };
107
+ const tests = [
108
+ { label: 'HIV Test 1 (k)', ...testTotals('hiv_test1') },
109
+ { label: 'HIV Test 2 (l)', ...testTotals('hiv_test2') },
110
+ { label: 'HIV Test 3 (m)', ...testTotals('hiv_test3') },
111
+ ];
112
+
113
+ return (
114
+ <div className={styles.sheet}>
115
+ <div className={styles.runningHead}>
116
+ <span>Ministry Of Health</span>
117
+ <span>MOH 362 HTS LAB, REFERRAL AND LINKAGE REGISTER</span>
118
+ <span>Ver. July 2023</span>
119
+ </div>
120
+ <h4 className={styles.sheetTitle}>MOH 362: HTS LAB REGISTER</h4>
121
+
122
+ <div className={styles.tableScroll}>
123
+ <table className={styles.register}>
124
+ <thead>
125
+ <tr>
126
+ <th>
127
+ Serial
128
+ <br />
129
+ Number
130
+ </th>
131
+ <th className={styles.splitHeader}>
132
+ <span>National Identification Number</span>
133
+ <span>National Unique Patient Identifier (NUPI) Number</span>
134
+ </th>
135
+ <th>
136
+ Date of visit
137
+ <br />
138
+ (DD/MM/YYYY)
139
+ </th>
140
+ <th className={styles.wide}>
141
+ Client Name
142
+ <br />
143
+ (First, Middle, Last)
144
+ </th>
145
+ <th>Age</th>
146
+ <th>
147
+ Sex
148
+ <br />
149
+ (M/F)
150
+ </th>
151
+ <th>Telephone Number</th>
152
+ <th className={styles.codes}>
153
+ Marital Status
154
+ <br />
155
+ 1=Married
156
+ <br />
157
+ 2=Widowed
158
+ <br />
159
+ 3=Single
160
+ <br />
161
+ 4=Divorced
162
+ <br />
163
+ 5=Separated
164
+ </th>
165
+ <th className={styles.codes}>
166
+ Population Type
167
+ <br />
168
+ 1. Gen Pop
169
+ <br />
170
+ 2. Key and Vulnerable Pop.
171
+ <br />
172
+ Codes for KVP
173
+ <br />- DC
174
+ <br />- MSM/MSW
175
+ <br />- FSW
176
+ <br />- PWID/PWUD
177
+ <br />- VP
178
+ </th>
179
+ <th className={styles.codes}>
180
+ Setting
181
+ <br />
182
+ (1=Facility
183
+ <br />
184
+ 2=Community)
185
+ </th>
186
+ <TestHeader test="HIV Test 1" codes="(N,P,I)" />
187
+ <TestHeader test="HIV Test 2" codes="(N,P,I,NA)" />
188
+ <TestHeader test="HIV Test 3" codes="(N,P,I,NA)" />
189
+ <th>
190
+ Final HIV
191
+ <br />
192
+ Result
193
+ <br />
194
+ <br />
195
+ (N,P,Ic,NA)
196
+ </th>
197
+ <th>
198
+ Discordant
199
+ <br />
200
+ Couple
201
+ <br />
202
+ <br />
203
+ (Y/N/NA)
204
+ </th>
205
+ <th className={styles.codes}>
206
+ Referred for Prevention Services
207
+ <br />
208
+ 1. PrEP
209
+ <br />
210
+ 2. PEP
211
+ <br />
212
+ 3. VMMC
213
+ <br />
214
+ 4. PMTCT
215
+ <br />
216
+ 5.NA
217
+ </th>
218
+ <th className={styles.wide}>
219
+ HTS Provider
220
+ <br />
221
+ (Name)
222
+ </th>
223
+ <th className={styles.wide}>Remarks</th>
224
+ </tr>
225
+ <tr className={styles.columnIds}>
226
+ {COLUMN_IDS.map((id) => (
227
+ <th key={id}>({id})</th>
228
+ ))}
229
+ </tr>
230
+ </thead>
231
+ <tbody>
232
+ {rows.map((row, index) => (
233
+ <React.Fragment key={`${row.patient_id}-${row.serial_number}-${index}`}>
234
+ <tr>
235
+ <td rowSpan={2}>{text(row.serial_number) || index + 1}</td>
236
+ <td className={styles.upperCell}>{text(row.id_number)}</td>
237
+ <td rowSpan={2}>{formDate(row.date_of_visit)}</td>
238
+ <td rowSpan={2} className={styles.left}>
239
+ {clientName(row)}
240
+ </td>
241
+ <td rowSpan={2}>{text(row.age)}</td>
242
+ <td rowSpan={2}>{text(row.sex)}</td>
243
+ <td rowSpan={2}>{text(row.telephone)}</td>
244
+ <td rowSpan={2}>{text(row.marital_status)}</td>
245
+ <td className={styles.upperCell}>{text(row.population_type)}</td>
246
+ <td rowSpan={2}>{text(row.setting)}</td>
247
+ <TestCell result={row.hiv_test1} kit={row.kit1_name} lot={row.lot1} expiry={row.expiry1} />
248
+ <TestCell result={row.hiv_test2} kit={row.kit2_name} lot={row.lot2} expiry={row.expiry2} />
249
+ <TestCell result={row.hiv_test3} kit={row.kit3_name} lot={row.lot3} expiry={row.expiry3} />
250
+ <td rowSpan={2}>{finalResult(row.final_result)}</td>
251
+ <td rowSpan={2}>{text(row.discordant_couple)}</td>
252
+ <td rowSpan={2}>{text(row.referral_services)}</td>
253
+ <td rowSpan={2} className={styles.left}>
254
+ {text(row.hts_provider)}
255
+ </td>
256
+ <td rowSpan={2} className={styles.left}>
257
+ {text(row.initial_remarks)}
258
+ </td>
259
+ </tr>
260
+ <tr>
261
+ <td className={styles.lowerCell}>{text(row.nupi)}</td>
262
+ <td className={styles.lowerCell}>{text(row.sub_population)}</td>
263
+ </tr>
264
+ </React.Fragment>
265
+ ))}
266
+ </tbody>
267
+ </table>
268
+ </div>
269
+
270
+ {/* The summary blocks at the foot of the sheet, laid out as on the form */}
271
+ <div className={styles.summary}>
272
+ <div className={styles.summaryColumn}>
273
+ <AgeSexSummary title="Tests (n )" rows={rows} />
274
+ <AgeSexSummary title="Positive (n)" rows={positives} />
275
+ </div>
276
+
277
+ <div className={styles.summaryColumn}>
278
+ <table className={styles.summaryTable}>
279
+ <thead>
280
+ <tr>
281
+ <th>Total Negative (n)</th>
282
+ </tr>
283
+ </thead>
284
+ <tbody>
285
+ <tr>
286
+ <td className={styles.bigFigure}>{count(rows, (row) => row.final_result === 'N')}</td>
287
+ </tr>
288
+ </tbody>
289
+ </table>
290
+ <table className={styles.summaryTable}>
291
+ <thead>
292
+ <tr>
293
+ <th>Inconclusive test (n)</th>
294
+ </tr>
295
+ </thead>
296
+ <tbody>
297
+ <tr>
298
+ <td className={styles.bigFigure}>{count(rows, (row) => finalResult(row.final_result) === 'Ic')}</td>
299
+ </tr>
300
+ </tbody>
301
+ </table>
302
+ </div>
303
+
304
+ <div className={styles.summaryColumn}>
305
+ <table className={styles.summaryTable}>
306
+ <tbody>
307
+ <tr>
308
+ <th className={styles.summaryLabel}>Tests Facility (j)</th>
309
+ <td>{count(rows, (row) => String(row.setting ?? '') === '1')}</td>
310
+ </tr>
311
+ <tr>
312
+ <th className={styles.summaryLabel}>Tests Community (j)</th>
313
+ <td>{count(rows, (row) => String(row.setting ?? '') === '2')}</td>
314
+ </tr>
315
+ </tbody>
316
+ </table>
317
+ <table className={styles.summaryTable}>
318
+ <tbody>
319
+ <tr>
320
+ <th className={styles.summaryLabel}>Discordant (o)</th>
321
+ <td>{count(rows, (row) => row.discordant_couple === 'Y')}</td>
322
+ </tr>
323
+ </tbody>
324
+ </table>
325
+ <table className={styles.summaryTable}>
326
+ <tbody>
327
+ <tr>
328
+ <th className={styles.summaryLabel}>Tests Key pops (i)</th>
329
+ <td>{count(rows, isKvp)}</td>
330
+ </tr>
331
+ <tr>
332
+ <th className={styles.summaryLabel}>
333
+ Positive Key pops
334
+ <br />
335
+ (i) &amp; (n)
336
+ </th>
337
+ <td>{count(positives, isKvp)}</td>
338
+ </tr>
339
+ </tbody>
340
+ </table>
341
+ </div>
342
+
343
+ <div className={styles.summaryColumn}>
344
+ <table className={styles.summaryTable}>
345
+ <thead>
346
+ <tr>
347
+ {tests.map((test) => (
348
+ <React.Fragment key={test.label}>
349
+ <th className={styles.summaryLabel}>{test.label}</th>
350
+ <th>Number</th>
351
+ </React.Fragment>
352
+ ))}
353
+ </tr>
354
+ </thead>
355
+ <tbody>
356
+ {(
357
+ [
358
+ ['N: Negative', 'n'],
359
+ ['P: Positive', 'p'],
360
+ ['I: Invalid', 'i'],
361
+ ['Wastage:', null],
362
+ ['Total:', 'total'],
363
+ ] as Array<[string, 'n' | 'p' | 'i' | 'total' | null]>
364
+ ).map(([label, key]) => (
365
+ <tr key={label}>
366
+ {tests.map((test) => (
367
+ <React.Fragment key={test.label}>
368
+ <th className={styles.summaryLabel}>{label}</th>
369
+ {/* wastage is counted on the kits, not recorded per client */}
370
+ <td>{key ? test[key] : ''}</td>
371
+ </React.Fragment>
372
+ ))}
373
+ </tr>
374
+ ))}
375
+ </tbody>
376
+ </table>
377
+ </div>
378
+ </div>
379
+
380
+ <div className={styles.signOff}>
381
+ <span>
382
+ Supervisor&apos;s Name: <span className={styles.rule} />
383
+ </span>
384
+ <span>
385
+ Signature: <span className={styles.rule} />
386
+ </span>
387
+ </div>
388
+ </div>
389
+ );
390
+ };
391
+
392
+ export default Moh362LabRegister;
@@ -0,0 +1,120 @@
1
+ import React from 'react';
2
+
3
+ import { clientName, formDate, text, type Moh362Row } from './moh-362.types';
4
+ import styles from './moh-362-register.scss';
5
+
6
+ interface Moh362LinkageRegisterProps {
7
+ rows: Moh362Row[];
8
+ }
9
+
10
+ const COLUMN_IDS = 'abcdefghij'.split('');
11
+
12
+ /**
13
+ * REFERRAL AND LINKAGE REGISTER (Ver. July 2023), page 6 of the MOH 362 form:
14
+ * the clients who tested HIV positive and were linked to care (started on ART),
15
+ * columns (a) to (j), with the total linked at the foot.
16
+ */
17
+ const Moh362LinkageRegister: React.FC<Moh362LinkageRegisterProps> = ({ rows }) => {
18
+ const linked = rows.length;
19
+
20
+ return (
21
+ <div className={styles.sheet}>
22
+ <div className={styles.runningHead}>
23
+ <span>Ministry Of Health</span>
24
+ <span>MOH 362 HTS LAB, REFERRAL AND LINKAGE REGISTER</span>
25
+ <span>Ver. July 2023</span>
26
+ </div>
27
+ <h4 className={`${styles.sheetTitle} ${styles.serifTitle}`}>REFERRAL AND LINKAGE REGISTER</h4>
28
+
29
+ <div className={styles.tableScroll}>
30
+ <table className={styles.register}>
31
+ <thead>
32
+ <tr>
33
+ <th>
34
+ Serial
35
+ <br />
36
+ Number
37
+ </th>
38
+ <th className={styles.splitHeader}>
39
+ <span>National Identification Number</span>
40
+ <span>National Unique Patient Identifier (NUPI) Number</span>
41
+ </th>
42
+ <th className={styles.wide}>Client Names</th>
43
+ <th className={styles.splitHeader}>
44
+ <span>Telephone Number</span>
45
+ <span>Residence</span>
46
+ </th>
47
+ <th>
48
+ Identification
49
+ <br />
50
+ Strategy
51
+ <br />
52
+ (VCT/IT/HIVST
53
+ <br />
54
+ /SNS)
55
+ </th>
56
+ <th className={styles.wide}>Patient referred to</th>
57
+ <th className={styles.wide}>
58
+ Handed over to:
59
+ <br />
60
+ (Indicate Name (upper cell)
61
+ <br />
62
+ and Cadre (lower cell)
63
+ </th>
64
+ <th>
65
+ Date started on
66
+ <br />
67
+ ART
68
+ </th>
69
+ <th>CCC Number</th>
70
+ <th className={styles.wide}>Remarks</th>
71
+ </tr>
72
+ <tr className={styles.columnIds}>
73
+ {COLUMN_IDS.map((id) => (
74
+ <th key={id}>({id})</th>
75
+ ))}
76
+ </tr>
77
+ </thead>
78
+ <tbody>
79
+ {rows.map((row, index) => (
80
+ <React.Fragment key={`${row.patient_id}-${row.serial_number}-${index}`}>
81
+ <tr>
82
+ <td rowSpan={2}>{index + 1}</td>
83
+ <td className={styles.upperCell}>{text(row.id_number)}</td>
84
+ <td rowSpan={2} className={styles.left}>
85
+ {clientName(row)}
86
+ </td>
87
+ <td className={styles.upperCell}>{text(row.telephone)}</td>
88
+ <td rowSpan={2}>{text(row.client_tested_as)}</td>
89
+ <td rowSpan={2} className={styles.left}>
90
+ {text(row.referral_to)}
91
+ </td>
92
+ <td className={`${styles.upperCell} ${styles.left}`}>{text(row.handed_to)}</td>
93
+ <td rowSpan={2}>{formDate(row.art_start_date)}</td>
94
+ <td rowSpan={2}>{text(row.ccc_number)}</td>
95
+ <td rowSpan={2} className={styles.left}>
96
+ {text(row.screening_remarks)}
97
+ </td>
98
+ </tr>
99
+ <tr>
100
+ <td className={styles.lowerCell}>{text(row.nupi)}</td>
101
+ <td className={styles.lowerCell}>{text(row.residence)}</td>
102
+ {/* the receiving health worker's cadre is not recorded */}
103
+ <td className={styles.lowerCell} />
104
+ </tr>
105
+ </React.Fragment>
106
+ ))}
107
+ <tr className={styles.totalRow}>
108
+ <th colSpan={9} className={styles.left}>
109
+ Totals Clients Linked
110
+ </th>
111
+ <td>{linked}</td>
112
+ </tr>
113
+ </tbody>
114
+ </table>
115
+ </div>
116
+ </div>
117
+ );
118
+ };
119
+
120
+ export default Moh362LinkageRegister;