@ampath/esm-reports-app 1.0.0-next.8 → 1.0.0-next.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/dist/0.css +1 -0
  2. package/dist/0.css.map +1 -0
  3. package/dist/0.js +1 -0
  4. package/dist/0.js.map +1 -0
  5. package/dist/197.js +1 -1
  6. package/dist/282.js +1 -1
  7. package/dist/282.js.map +1 -1
  8. package/dist/295.css +1 -0
  9. package/dist/295.css.map +1 -0
  10. package/dist/295.js +1 -0
  11. package/dist/295.js.map +1 -0
  12. package/dist/299.js +2 -0
  13. package/dist/299.js.LICENSE.txt +3 -0
  14. package/dist/299.js.map +1 -0
  15. package/dist/300.js +1 -1
  16. package/dist/311.js +1 -1
  17. package/dist/311.js.map +1 -1
  18. package/dist/335.js +1 -1
  19. package/dist/353.js +1 -1
  20. package/dist/353.js.map +1 -1
  21. package/dist/354.js +2 -0
  22. package/dist/354.js.LICENSE.txt +20 -0
  23. package/dist/354.js.map +1 -0
  24. package/dist/410.js +1 -0
  25. package/dist/410.js.map +1 -0
  26. package/dist/457.js +2 -0
  27. package/dist/457.js.LICENSE.txt +261 -0
  28. package/dist/457.js.map +1 -0
  29. package/dist/478.js +1 -1
  30. package/dist/478.js.map +1 -1
  31. package/dist/480.js +1 -0
  32. package/dist/540.js +1 -1
  33. package/dist/540.js.map +1 -1
  34. package/dist/55.js +1 -1
  35. package/dist/600.js +2 -0
  36. package/dist/600.js.LICENSE.txt +35 -0
  37. package/dist/600.js.map +1 -0
  38. package/dist/652.js +1 -1
  39. package/dist/757.js +1 -0
  40. package/dist/757.js.map +1 -0
  41. package/dist/781.js +1 -0
  42. package/dist/781.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 +264 -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 +225 -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 +29 -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 +191 -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-267/moh-267-register.component.tsx +407 -0
  100. package/src/registers/moh-267/moh-267-register.scss +298 -0
  101. package/src/registers/moh-267/moh-267-summary.ts +102 -0
  102. package/src/registers/moh-267/moh-267.component.tsx +94 -0
  103. package/src/registers/moh-267/moh-267.types.ts +47 -0
  104. package/src/registers/moh-362/moh-362-lab-register.component.tsx +551 -0
  105. package/src/registers/moh-362/moh-362-lab-register.scss +412 -0
  106. package/src/registers/moh-362/moh-362-linkage-register.component.tsx +215 -0
  107. package/src/registers/moh-362/moh-362-linkage-register.scss +91 -0
  108. package/src/registers/moh-362/moh-362.component.tsx +117 -0
  109. package/src/registers/moh-362/moh-362.scss +11 -0
  110. package/src/registers/moh-362/moh-362.types.ts +87 -0
  111. package/src/registers/presumptive-tb/presumptive-tb-register.component.tsx +391 -0
  112. package/src/registers/presumptive-tb/presumptive-tb-register.scss +262 -0
  113. package/src/registers/presumptive-tb/presumptive-tb.component.tsx +92 -0
  114. package/src/registers/presumptive-tb/presumptive-tb.types.ts +88 -0
  115. package/src/registers/register-catalog.ts +202 -0
  116. package/src/registers/register-file-name.ts +18 -0
  117. package/src/registers/tb-lab-register/tb-lab-register-table.component.tsx +116 -0
  118. package/src/registers/tb-lab-register/tb-lab-register-table.scss +123 -0
  119. package/src/registers/tb-lab-register/tb-lab-register.columns.ts +164 -0
  120. package/src/registers/tb-lab-register/tb-lab-register.component.test.tsx +232 -0
  121. package/src/registers/tb-lab-register/tb-lab-register.component.tsx +153 -0
  122. package/src/registers/tb4/tb4-parts.tsx +164 -0
  123. package/src/registers/tb4/tb4-patient-sheet.component.tsx +418 -0
  124. package/src/registers/tb4/tb4-register.scss +282 -0
  125. package/src/registers/tb4/tb4-treatment-sheet.component.tsx +349 -0
  126. package/src/registers/tb4/tb4.component.tsx +120 -0
  127. package/src/registers/tb4/tb4.types.ts +129 -0
  128. package/src/reports/acf-summary/acf-summary-form.component.tsx +176 -0
  129. package/src/reports/acf-summary/acf-summary-linelist.component.tsx +86 -0
  130. package/src/reports/acf-summary/acf-summary.component.tsx +97 -0
  131. package/src/reports/acf-summary/acf-summary.counts.ts +37 -0
  132. package/src/reports/acf-summary/acf-summary.scss +162 -0
  133. package/src/reports/datatable-wrapper/datatable-wrapper.component.tsx +63 -48
  134. package/src/reports/moh-240/moh-240-header.component.tsx +62 -0
  135. package/src/reports/moh-240/moh-240.columns.ts +113 -0
  136. package/src/reports/moh-240/moh-240.component.tsx +72 -9
  137. package/src/reports/moh-240/moh-240.scss +40 -0
  138. package/src/reports/moh-240/sub-reports/moh-240-register.component.tsx +31 -37
  139. package/src/reports/moh-240/sub-reports/page-summary.component.tsx +143 -106
  140. package/src/reports/moh-505/moh-505-header.component.tsx +67 -0
  141. package/src/reports/moh-505/moh-505.component.tsx +441 -0
  142. package/src/reports/moh-505/moh-505.scss +117 -0
  143. package/src/reports/moh-705B/moh-204b-register.component.tsx +246 -0
  144. package/src/reports/moh-705B/moh-204b.columns.ts +39 -0
  145. package/src/reports/moh-705B/moh-705b.component.tsx +659 -0
  146. package/src/reports/moh-705B/moh-705b.scss +172 -0
  147. package/src/reports/moh-705a/moh-705a.component.tsx +661 -0
  148. package/src/reports/moh-705a/moh-705a.scss +172 -0
  149. package/src/reports/moh-705a/registers/moh-204a-register.component.tsx +331 -0
  150. package/src/reports/moh-705a/registers/moh-204a.columns.ts +57 -0
  151. package/src/reports/moh-705a/type.ts +6 -0
  152. package/src/reports/moh-706/moh-706-header.component.tsx +66 -0
  153. package/src/reports/moh-706/moh-706.component.tsx +150 -24
  154. package/src/reports/moh-706/moh-706.scss +119 -11
  155. package/src/reports/moh-706/sub-reports/bacteriology/bacteriology.component.tsx +35 -28
  156. package/src/reports/moh-706/sub-reports/blood-chemistry/blood-chemistry.component.tsx +229 -305
  157. package/src/reports/moh-706/sub-reports/haematology/haematology.component.tsx +26 -19
  158. package/src/reports/moh-706/sub-reports/histology-and-cytology/histology-and-cytology.component.tsx +23 -23
  159. package/src/reports/moh-706/sub-reports/parasitology/parasitology.component.tsx +25 -18
  160. package/src/reports/moh-706/sub-reports/serology/serology.component.tsx +21 -14
  161. package/src/reports/moh-706/sub-reports/specimen-referral-to-higher-levels/specimen-referral-to-higher-levels.component.tsx +2 -2
  162. package/src/reports/moh-706/sub-reports/urine-analysis/urine-analysis.component.tsx +27 -20
  163. package/src/reports/moh-710/moh-710.component.tsx +815 -632
  164. package/src/reports/moh-710/moh-710.scss +142 -21
  165. package/src/reports/moh-710/registers/moh-413/moh-413-columns.ts +22 -0
  166. package/src/reports/moh-710/registers/moh-413/moh-413.component.tsx +140 -0
  167. package/src/reports/moh-710/registers/moh-413/moh-413.scss +64 -0
  168. package/src/reports/moh-710/registers/moh-510/moh-510.columns.ts +40 -0
  169. package/src/reports/moh-710/registers/moh-510/moh-510.component.tsx +191 -0
  170. package/src/reports/moh-710/registers/moh-510/moh-510.scss +130 -0
  171. package/src/reports/moh-710/registers/moh-511-710-register.component.tsx +268 -0
  172. package/src/reports/moh-710/registers/moh-511-710.columns.ts +52 -0
  173. package/src/reports/moh-710/registers/type.ts +31 -0
  174. package/src/reports/moh-711/moh-711.component.tsx +153 -1269
  175. package/src/reports/moh-711/moh711.scss +135 -20
  176. package/src/reports/moh-711/registers/moh-333-register.component.tsx +680 -0
  177. package/src/reports/moh-711/registers/moh-333.columns.ts +119 -0
  178. package/src/reports/moh-711/registers/moh-405-register.component.tsx +566 -0
  179. package/src/reports/moh-711/registers/moh-405.columns.ts +120 -0
  180. package/src/reports/moh-711/registers/moh-406-register.component.tsx +581 -0
  181. package/src/reports/moh-711/registers/moh-406.columns.ts +133 -0
  182. package/src/reports/moh-711/registers/moh-407-register.component.tsx +157 -0
  183. package/src/reports/moh-711/registers/moh-407.columns.ts +24 -0
  184. package/src/reports/moh-711/registers/moh-407.scss +64 -0
  185. package/src/reports/moh-711/registers/moh-510-register.component.tsx +55 -0
  186. package/src/reports/moh-711/registers/moh-511-register.component.tsx +270 -0
  187. package/src/reports/moh-711/registers/moh-511.columns.ts +59 -0
  188. package/src/reports/moh-711/registers/moh-512-columns.ts +94 -0
  189. package/src/reports/moh-711/registers/moh-512.component.tsx +191 -0
  190. package/src/reports/moh-711/registers/moh-512.scss +64 -0
  191. package/src/reports/moh-711/registers/tb-register-columns.ts +17 -0
  192. package/src/reports/moh-711/registers/tb-register.component.tsx +96 -0
  193. package/src/reports/moh-711/registers/tb-register.scss +64 -0
  194. package/src/reports/moh-711/registers/type.ts +192 -0
  195. package/src/reports/moh-711/sections/anc.component.tsx +159 -0
  196. package/src/reports/moh-711/sections/cervical-cancer.component.tsx +148 -0
  197. package/src/reports/moh-711/sections/chanis.component.tsx +389 -0
  198. package/src/reports/moh-711/sections/family-planning.component.tsx +299 -0
  199. package/src/reports/moh-711/sections/gbv.component.tsx +115 -0
  200. package/src/reports/moh-711/sections/maternity.component.tsx +321 -0
  201. package/src/reports/moh-711/sections/medical-social-work.component.tsx +73 -0
  202. package/src/reports/moh-711/sections/other.component.tsx +47 -0
  203. package/src/reports/moh-711/sections/physiotherapy.component.tsx +61 -0
  204. package/src/reports/moh-711/sections/pnc.component.tsx +127 -0
  205. package/src/reports/moh-711/sections/post-abortion.component.tsx +42 -0
  206. package/src/reports/moh-711/sections/rehabilitation.component.tsx +57 -0
  207. package/src/reports/moh-711/sections/report-compiled-by.component.tsx +50 -0
  208. package/src/reports/moh-711/sections/tb-screening.component.tsx +94 -0
  209. package/src/reports/moh-717/moh-717.component.tsx +149 -985
  210. package/src/reports/moh-717/moh717.scss +217 -21
  211. package/src/reports/moh-717/registers/nutrition-register.component.tsx +48 -0
  212. package/src/reports/moh-717/sections/finance.component.tsx +42 -0
  213. package/src/reports/moh-717/sections/inpatient.component.tsx +374 -0
  214. package/src/reports/moh-717/sections/maternity.component.tsx +126 -0
  215. package/src/reports/moh-717/sections/medical-records.component.tsx +35 -0
  216. package/src/reports/moh-717/sections/mortuary.component.tsx +43 -0
  217. package/src/reports/moh-717/sections/operations.component.tsx +53 -0
  218. package/src/reports/moh-717/sections/orthopaedic-trauma.component.tsx +98 -0
  219. package/src/reports/moh-717/sections/outpatient.component.tsx +597 -0
  220. package/src/reports/moh-717/sections/pharmacy.component.tsx +43 -0
  221. package/src/reports/moh-717/sections/preparedby.component.tsx +52 -0
  222. package/src/reports/moh-717/sections/special-services.component.tsx +114 -0
  223. package/src/reports/moh-729b/moh-729b-form.component.tsx +385 -0
  224. package/src/reports/moh-729b/moh-729b-linelist.component.tsx +205 -0
  225. package/src/reports/moh-729b/moh-729b-summary.component.tsx +258 -0
  226. package/src/reports/moh-729b/moh-729b-summary.config.ts +229 -0
  227. package/src/reports/moh-729b/moh-729b.component.tsx +157 -0
  228. package/src/reports/moh-729b/moh-729b.config.ts +235 -0
  229. package/src/reports/moh-729b/moh-729b.scss +276 -0
  230. package/src/reports/moh-729b/moh-729b.types.ts +111 -0
  231. package/src/reports/moh-731/linelist/moh-731-indicators.ts +1122 -0
  232. package/src/reports/moh-731/linelist/moh-731-linelist-sections.ts +472 -0
  233. package/src/reports/moh-731/linelist/moh-731-linelist.component.tsx +102 -0
  234. package/src/reports/moh-731/linelist/use-open-moh-731-linelist.ts +50 -0
  235. package/src/reports/moh-731/moh-731.component.tsx +269 -0
  236. package/src/reports/moh-731/moh-731.scss +496 -0
  237. package/src/reports/moh-731/registers/moh-366.columns.ts +38 -0
  238. package/src/reports/moh-731/registers/moh-366.component.tsx +471 -0
  239. package/src/reports/moh-731/registers/prep-register.component.tsx +284 -0
  240. package/src/reports/moh-731/registers/prep.columns.ts +34 -0
  241. package/src/reports/moh-731/sections/hiv-and-tb-treatment.component.tsx +1206 -0
  242. package/src/reports/moh-731/sections/hiv-testing-and-pre-exposure.component.tsx +727 -0
  243. package/src/reports/moh-731/sections/pmtct.component.tsx +572 -0
  244. package/src/reports/moh-731/summary/moh-731-summary.component.tsx +313 -0
  245. package/src/reports/moh-731/summary/moh-731-summary.config.ts +527 -0
  246. package/src/reports/moh-731/summary/moh-731-summary.scss +247 -0
  247. package/src/reports/moh-740/moh-740.component.scss +202 -0
  248. package/src/reports/moh-740/moh-740.component.tsx +1332 -0
  249. package/src/reports/moh-740/moh-740.resource.ts +54 -0
  250. package/src/reports/moh-740/registers/moh-222-daily-register/moh-222-daily-register.tsx +149 -0
  251. package/src/reports/moh-740/registers/moh-270-permanent-register/moh-270-permanent-register.tsx +123 -0
  252. package/src/reports/moh-740/registers/moh-740-patient-list.scss +0 -0
  253. package/src/reports/moh-740/registers/moh-740-patient-list.tsx +60 -0
  254. package/src/reports/moh-740/registers/moh-740.columns.ts +54 -0
  255. package/src/reports/moh-740/shared/data-cell/data-cell.scss +6 -0
  256. package/src/reports/moh-740/shared/data-cell/data-cell.tsx +23 -0
  257. package/src/reports/moh-740/shared/utils/indicator-register-map.ts +159 -0
  258. package/src/reports/moh-740/types/index.ts +223 -0
  259. package/src/reports/moh-745/moh-745.component.tsx +2058 -0
  260. package/src/reports/moh-745/moh-745.scss +142 -0
  261. package/src/reports/moh-745/registers/moh-412-register.component.tsx +249 -0
  262. package/src/reports/moh-745/registers/moh-412.columns.ts +52 -0
  263. package/src/reports/moh-745/registers/type.ts +223 -0
  264. package/src/reports/table-wrapper/table-row-mapper.component.tsx +20 -5
  265. package/src/reports/table-wrapper/table-wrapper.component.tsx +23 -14
  266. package/src/reports/table-wrapper/table-wrapper.scss +1 -16
  267. package/src/resources/moh-267.resource.ts +27 -0
  268. package/src/resources/moh-362.resource.ts +27 -0
  269. package/src/resources/moh-505.resource.ts +69 -0
  270. package/src/resources/moh-705.resource.ts +118 -0
  271. package/src/resources/moh-706.resource.ts +80 -0
  272. package/src/resources/moh-710.resource.ts +60 -9
  273. package/src/resources/moh-711.resource.ts +206 -9
  274. package/src/resources/moh-717.resource.ts +26 -9
  275. package/src/resources/moh-729b.resource.ts +25 -0
  276. package/src/resources/moh-731.resource.ts +90 -0
  277. package/src/resources/moh-745.resource.ts +76 -0
  278. package/src/resources/patient-list-page.ts +66 -0
  279. package/src/resources/presumptive-tb.resource.ts +27 -0
  280. package/src/root.component.tsx +79 -8
  281. package/src/root.scss +36 -0
  282. package/src/routes.json +3 -1
  283. package/src/utils/format-indicator.ts +39 -0
  284. package/src/utils/get-base-url.ts +39 -7
  285. package/src/utils/utils.ts +30 -1
  286. package/tsconfig.json +1 -1
  287. package/webpack.config.js +22 -1
  288. package/dist/138.js +0 -2
  289. package/dist/138.js.LICENSE.txt +0 -20
  290. package/dist/138.js.map +0 -1
  291. package/dist/184.js +0 -2
  292. package/dist/184.js.LICENSE.txt +0 -14
  293. package/dist/184.js.map +0 -1
  294. package/dist/205.js +0 -1
  295. package/dist/205.js.map +0 -1
  296. package/dist/812.js +0 -1
  297. package/dist/812.js.map +0 -1
  298. package/dist/879.js +0 -1
  299. package/dist/879.js.map +0 -1
  300. package/dist/ampath-esm-reports-app.js.buildmanifest.json +0 -539
  301. package/dist/main.js +0 -1
  302. package/dist/main.js.map +0 -1
@@ -0,0 +1,62 @@
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';
6
+ import { useLocationDetails } from '../../common/report-header';
7
+ import styles from './moh-240.scss';
8
+
9
+ interface MOH240HeaderProps {
10
+ facility?: string;
11
+ startDate?: string;
12
+ endDate?: string;
13
+ }
14
+
15
+ const asDate = (value?: string) => (value ? dayjs(value).format('DD/MM/YYYY') : '');
16
+
17
+ const MOH240Header: React.FC<MOH240HeaderProps> = ({ facility = '', startDate, endDate }) => {
18
+ const { county, subCounty, kmhflCode } = useLocationDetails();
19
+
20
+ const tableRows = useMemo(() => {
21
+ return [
22
+ {
23
+ tableCells: [getCell('', 'County:', 1, 1, true), getCell('', county ?? '', 3)],
24
+ },
25
+ {
26
+ tableCells: [getCell('', 'Sub-County:', 1, 1, true), getCell('', subCounty ?? '', 3)],
27
+ },
28
+ {
29
+ tableCells: [getCell('', 'Health Facility:', 1, 1, true), getCell('', facility, 3)],
30
+ },
31
+ {
32
+ tableCells: [getCell('', 'KMHFL Code:', 1, 1, true), getCell('', kmhflCode ?? '', 3)],
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('', asDate(startDate)),
46
+ getCell('', 'End date:', 1, 1, true),
47
+ getCell('', asDate(endDate)),
48
+ ],
49
+ },
50
+ ];
51
+ }, [county, subCounty, kmhflCode, facility, startDate, endDate]);
52
+
53
+ return (
54
+ <div className={styles.headerSection}>
55
+ <TableWrapper className={styles.formTable}>
56
+ <TableRowMapper tableRows={tableRows} />
57
+ </TableWrapper>
58
+ </div>
59
+ );
60
+ };
61
+
62
+ export default MOH240Header;
@@ -0,0 +1,113 @@
1
+ import { type RegisterColumn } from '../../common/report-register';
2
+ import dayjs from 'dayjs';
3
+
4
+ /** The register's columns, in the order the printed MOH 240 prints them */
5
+ export const MOH_240_HEADERS = [
6
+ { key: 'date', header: 'Date (DD/MM/YYYY)' },
7
+ { key: 'opd_ip_ref_no', header: 'OPD / IPD Ref. No.' },
8
+ { key: 'lab_no', header: 'Lab. No. (new client)' },
9
+ { key: 'revisit_no', header: 'Revisit No.' },
10
+ { key: 'full_name', header: 'Full Names (Three names)' },
11
+ { key: 'age', header: 'Age' },
12
+ { key: 'sex', header: 'Sex' },
13
+ { key: 'county_sub_county', header: 'County / Sub County' },
14
+ { key: 'village_estate_landmark', header: 'Village / Estate / Landmark' },
15
+ { key: 'telephone_number', header: 'Telephone Number' },
16
+ { key: 'clinical_diagnosis', header: 'Clinical Diagnosis' },
17
+ { key: 'prior_treatment', header: 'Prior Treatment' },
18
+ { key: 'type_of_specimen', header: 'Type of Specimen' },
19
+ { key: 'condition_of_specimen', header: 'Condition of Specimen' },
20
+ { key: 'investigation_required', header: 'Investigation Required' },
21
+ { key: 'test_datetime', header: 'Date Sample Collected' },
22
+ { key: 'date_sample_received', header: 'Date Sample Received' },
23
+ { key: 'clinician_name', header: 'Clinician Name' },
24
+ { key: 'date_sample_analysed', header: 'Date Sample Analysed' },
25
+ { key: 'results', header: 'Results' },
26
+ { key: 'date_results_dispatched', header: 'Date Results Dispatched' },
27
+ { key: 'amount_charged', header: 'Amount Charged' },
28
+ { key: 'receipt_number', header: 'Receipt Number' },
29
+ { key: 'referrals', header: 'Referrals (From Other HF / To Other HF / 3rd Tier Reference Laboratories)' },
30
+ { key: 'comments', header: 'Comments' },
31
+ { key: 'testing_officer', header: 'Name of Analysing/Testing Officer' },
32
+ { key: 'signature', header: 'Signature' },
33
+ ] as const;
34
+
35
+ /** The column letters the printed register runs across the top */
36
+ export const MOH_240_SUB_HEADERS = MOH_240_HEADERS.map((_, i) =>
37
+ i < 26 ? String.fromCharCode(65 + i) : `A${String.fromCharCode(65 + i - 26)}`,
38
+ );
39
+
40
+ /**
41
+ * Columns whose values must stay text in the CSV: identifiers lose leading
42
+ * zeros and phone numbers open as `#NAME?` formulas when Excel parses them
43
+ * as numbers.
44
+ */
45
+ export const MOH_240_TEXT_KEYS = ['lab_no', 'opd_ip_ref_no', 'telephone_number', 'receipt_number'];
46
+
47
+ /**
48
+ * Prose columns allowed to wrap on screen; everything else stays `nowrap` so
49
+ * one long value cannot stretch the 27-column row past the fold.
50
+ * `results` wraps because full-panel rows (v1.2) compose every analyte,
51
+ * including 'Not done' placeholders, into one long string.
52
+ */
53
+ export const MOH_240_WRAP_KEYS = [
54
+ 'clinical_diagnosis',
55
+ 'type_of_specimen',
56
+ 'referrals',
57
+ 'comments',
58
+ 'results',
59
+ ];
60
+
61
+ /**
62
+ * The results column carries whichever indicator the drill-down was opened for,
63
+ * so it is read from a field named by that indicator rather than from `results`.
64
+ */
65
+ export function resultFieldFor(indicator: string): string {
66
+ if (indicator.startsWith('min_') || indicator.startsWith('max_')) {
67
+ return indicator.substring(4);
68
+ }
69
+ if (indicator.startsWith('total_')) {
70
+ return indicator.substring(6);
71
+ }
72
+ if (indicator.startsWith('positive_')) {
73
+ return indicator.substring(9);
74
+ }
75
+ return indicator;
76
+ }
77
+
78
+ /**
79
+ * Formats a datetime column the way the printed form reads it. Values the
80
+ * payload already sends as `DD/MM/YYYY` pass through untouched; only raw ISO
81
+ * datetimes (`2026-08-19T10:18:14.000Z`) are reformatted, so screen and CSV
82
+ * agree no matter which shape the endpoint returns.
83
+ */
84
+ export function formatRegisterDate(value: unknown): string {
85
+ if (value === null || value === undefined || value === '') {
86
+ return '';
87
+ }
88
+ const text = String(value).trim();
89
+ return /^\d{4}-\d{2}-\d{2}/.test(text) ? dayjs(text).format('DD/MM/YYYY') : text;
90
+ }
91
+
92
+ /** Exported with the register's own headings, so the CSV matches the form */
93
+ export function moh240Columns(indicator: string): RegisterColumn[] {
94
+ const resultField = resultFieldFor(indicator);
95
+
96
+ return MOH_240_HEADERS.map(({ key, header }) => ({
97
+ header,
98
+ value: (row: Record<string, any>) => {
99
+ if (key === 'results') {
100
+ // The lab-706 register sends the row's translated result directly;
101
+ // the per-indicator field remains the fallback for payloads that
102
+ // only carry the test slots.
103
+ return row.results ?? row[resultField] ?? '';
104
+ }
105
+ if (key === 'test_datetime') {
106
+ return formatRegisterDate(row[key]);
107
+ }
108
+ return row[key] ?? '';
109
+ },
110
+ text: (MOH_240_TEXT_KEYS as readonly string[]).includes(key) || undefined,
111
+ wrap: (MOH_240_WRAP_KEYS as readonly string[]).includes(key) || undefined,
112
+ }));
113
+ }
@@ -1,12 +1,75 @@
1
- import React from "react";
2
- import Moh240Register from "./sub-reports/moh-240-register.component";
3
- import Moh240PageSummary from "./sub-reports/page-summary.component";
1
+ import React from 'react';
2
+ import { useSearchParams } from 'react-router-dom';
3
+ import { useSession } from '@openmrs/esm-framework';
4
+
5
+ import Moh240Register from './sub-reports/moh-240-register.component';
6
+ import Moh240PageSummary from './sub-reports/page-summary.component';
7
+ import MOH240Header from './moh-240-header.component';
8
+ import { MOH_240_SUB_HEADERS, moh240Columns } from './moh-240.columns';
9
+ import { getMoh706PatientList } from '../../resources/moh-706.resource';
10
+ import { getMoh505PatientList } from '../../resources/moh-505.resource';
11
+ import { RegisterLayout, usePatientList } from '../../common/report-register';
12
+ import styles from './moh-240.scss';
13
+
14
+ /** The reports that drill down into this register */
15
+ const PARENTS: Record<string, { label: string; path: string }> = {
16
+ 'moh-505': { label: 'MOH-505 Report', path: '/moh-505' },
17
+ 'moh-706': { label: 'MOH-706 Report', path: '/moh-706' },
18
+ };
4
19
 
5
20
  const Moh240Report: React.FC = () => {
6
- return <>
7
- <Moh240Register />
8
- <Moh240PageSummary />
9
- </>
10
- }
21
+ const [searchParams] = useSearchParams();
22
+ const session = useSession();
23
+
24
+ const locationUuids = searchParams.get('locationUuids') ?? '';
25
+ const startDate = searchParams.get('startDate') ?? '';
26
+ const endDate = searchParams.get('endDate') ?? '';
27
+ const indicators = searchParams.get('indicators') ?? '';
28
+ const report = searchParams.get('report') || 'moh-706';
29
+
30
+ const parent = PARENTS[report] ?? PARENTS['moh-706'];
31
+
32
+ const {
33
+ rows: patientList,
34
+ total,
35
+ isTotalExact,
36
+ isLoading,
37
+ page,
38
+ pageSize,
39
+ onPageChange,
40
+ fetchAll,
41
+ } = usePatientList(
42
+ ({ startIndex, limit }) => {
43
+ const params = { locationUuids, startDate, endDate, indicators, startIndex, limit };
44
+
45
+ return report === 'moh-505' ? getMoh505PatientList(params) : getMoh706PatientList(params);
46
+ },
47
+ [locationUuids, startDate, endDate, indicators, report],
48
+ );
49
+
50
+ return (
51
+ <RegisterLayout
52
+ parentLabel={parent.label}
53
+ parentPath={parent.path}
54
+ title="Laboratory (LAB) Register MOH 240"
55
+ isLoading={isLoading}
56
+ isEmpty={patientList.length === 0}
57
+ page={page}
58
+ pageSize={pageSize}
59
+ total={total}
60
+ isTotalExact={isTotalExact}
61
+ onPageChange={onPageChange}
62
+ fetchAll={fetchAll}
63
+ columns={moh240Columns(indicators)}
64
+ subHeaders={MOH_240_SUB_HEADERS}
65
+ >
66
+ <div className={styles.sheet}>
67
+ <MOH240Header facility={session?.sessionLocation?.display ?? ''} startDate={startDate} endDate={endDate} />
68
+ <Moh240Register patientList={patientList} indicator={indicators} />
69
+ <Moh240PageSummary rows={patientList} />
70
+ </div>
71
+ </RegisterLayout>
72
+ );
73
+ };
11
74
 
12
- export default Moh240Report;
75
+ export default Moh240Report;
@@ -0,0 +1,40 @@
1
+ /* MOH-240 is a drill-down line list, so its table comes from the shared
2
+ register stylesheet. What is styled here is the printed register's own
3
+ furniture: the facility block above the list and the page summary below it.
4
+
5
+ Both render through TableWrapper, whose cell rules are single-class, so
6
+ scoping these under `.sheet` (a class plus an element) wins deterministically
7
+ rather than by module load order. The wrapper is asked for a plain table so
8
+ Carbon's data-table rules, which are far more specific, never apply. */
9
+
10
+ $ink: #000;
11
+ $rule: 1px solid $ink;
12
+
13
+ $text: 0.75rem;
14
+
15
+ .sheet {
16
+ .formTable table {
17
+ width: 100%;
18
+ border-collapse: collapse;
19
+ }
20
+
21
+ .formTable td,
22
+ .formTable th {
23
+ height: auto;
24
+ min-width: 0;
25
+ padding: 0.25rem 0.375rem;
26
+ overflow-wrap: anywhere;
27
+ font-size: $text;
28
+ line-height: 1.3;
29
+ text-align: left;
30
+ border: $rule;
31
+ }
32
+ }
33
+
34
+ .headerSection {
35
+ margin-bottom: 0.75rem;
36
+ }
37
+
38
+ .summarySection {
39
+ margin-top: 0.75rem;
40
+ }
@@ -1,42 +1,36 @@
1
- import React from "react";
2
- import DatatableWrapper from "../../datatable-wrapper/datatable-wrapper.component";
1
+ import React from 'react';
2
+ import DatatableWrapper from '../../datatable-wrapper/datatable-wrapper.component';
3
+ import { MOH_240_HEADERS, MOH_240_SUB_HEADERS, MOH_240_WRAP_KEYS, formatRegisterDate } from '../moh-240.columns';
4
+ import tableStyles from '../../../common/report-register/register-table.scss';
5
+ import classNames from 'classnames';
3
6
 
4
- const Moh240Register: React.FC = () => {
5
- const headers = [
6
- { key: 'date', header: 'Date (DD/MM/YYYY)' },
7
- { key: 'opd_ipd_no', header: 'OPD / IPD Ref. No.' },
8
- { key: 'lab_no', header: 'Lab. No. (new client)' },
9
- { key: 'revisit_no', header: 'Revisit No.' },
10
- { key: 'full_name', header: 'Full Names (Three names)' },
11
- { key: 'age', header: 'Age' },
12
- { key: 'sex', header: 'Sex' },
13
- { key: 'county_sub_county', header: 'County / Sub County' },
14
- { key: 'village_estate_landmark', header: 'Village / Estate / Landmark' },
15
- { key: 'telephone', header: 'Telephone Number' },
16
- { key: 'clinical_diagnosis', header: 'Clinical Diagnosis' },
17
- { key: 'prior_treatment', header: 'Prior Treatment' },
18
- { key: 'type_of_specimen', header: 'Type of Specimen' },
19
- { key: 'condition_of_specimen', header: 'Condition of Specimen' },
20
- { key: 'investigation_required', header: 'Investigation Required' },
21
- { key: 'date_sample_collected', header: 'Date Sample Collected' },
22
- { key: 'date_sample_received', header: 'Date Sample Received' },
23
- { key: 'clinician_name', header: 'Clinician Name' },
24
- { key: 'date_sample_analysed', header: 'Date Sample Analysed' },
25
- { key: 'results', header: 'Results' },
26
- { key: 'date_results_dispatched', header: 'Date Results Dispatched' },
27
- { key: 'amount_charged', header: 'Amount Charged' },
28
- { key: 'receipt_number', header: 'Receipt Number' },
29
- { key: 'referrals', header: 'Referrals (From Other HF / To Other HF / 3rd Tier Reference Laboratories)' },
30
- { key: 'comments', header: 'Comments' },
31
- { key: 'analysing_officer', header: 'Name of Analysing/Testing Officer' },
32
- { key: 'signature', header: 'Signature' }
33
- ];
7
+ interface Moh240RegisterProps {
8
+ patientList?: any[];
9
+ indicator?: string;
10
+ }
34
11
 
35
- const subHeaders = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 'AA'];
12
+ const Moh240Register: React.FC<Moh240RegisterProps> = ({ patientList = [], indicator = '' }) => {
13
+ const rows = patientList.map((patient, index) => {
14
+ const row: { id: string } & Record<string, any> = { id: String(index) };
36
15
 
37
- const rows = [];
16
+ MOH_240_HEADERS.forEach(({ key }) => {
17
+ row[key] = (key === 'test_datetime' ? formatRegisterDate(patient[key]) : patient[key]) || '';
18
+ });
38
19
 
39
- return <DatatableWrapper headers={headers} rows={rows} subHeaders={subHeaders}/>
40
- }
20
+ return row;
21
+ });
22
+
23
+ return (
24
+ <div className={tableStyles.tableContainer}>
25
+ <DatatableWrapper
26
+ headers={[...MOH_240_HEADERS]}
27
+ rows={rows}
28
+ subHeaders={MOH_240_SUB_HEADERS}
29
+ wrapKeys={MOH_240_WRAP_KEYS}
30
+ className={classNames(tableStyles.table, tableStyles.tableBordered, tableStyles.tableStriped)}
31
+ />
32
+ </div>
33
+ );
34
+ };
41
35
 
42
- export default Moh240Register;
36
+ export default Moh240Register;
@@ -1,111 +1,148 @@
1
- import React, { useMemo } from "react";
2
- import { TableRow, TableCell } from '@carbon/react';
3
- import TableWrapper from "../../table-wrapper/table-wrapper.component";
4
- import styles from '../../table-wrapper/table-wrapper.scss';
1
+ import React, { useMemo } from 'react';
2
+ import TableWrapper from '../../table-wrapper/table-wrapper.component';
3
+ import TableRowMapper from '../../table-wrapper/table-row-mapper.component';
4
+ import { getCell } from '../../../utils/utils';
5
+ import styles from '../moh-240.scss';
5
6
 
6
- const Moh240PageSummary: React.FC = () => {
7
- const getCell = (key = "", value = "", colSpan = 1, rowSpan = 1, strong = false) => ({
8
- key,
9
- value,
10
- strong,
11
- colSpan,
12
- rowSpan
13
- });
7
+ /**
8
+ * Encounter types that count as inpatient (IP). The OPD/IP split on this
9
+ * summary depends on the site's encounter dictionary, which this module
10
+ * cannot know; while the set is empty the combined count is shown under OPD
11
+ * and the IP cell stays blank rather than claiming a split.
12
+ */
13
+ const INPATIENT_ENCOUNTER_TYPES: number[] = [];
14
14
 
15
- const tableRows = useMemo(() => {
16
- return [
17
- {
18
- tableCells: [
19
- getCell("", "Page Summary", 8, 1, true),
20
- ]
21
- },
22
- {
23
- tableCells: [
24
- getCell("", "Malaria Testing", 3, 1, true),
25
- getCell("", "Type of test", 2, 1, true),
26
- getCell("", "Referrals", 3, 1, true),
27
- ]
28
- },
29
- {
30
- tableCells: [
31
- getCell("", "", 1, 2, true),
32
- getCell("", "Number", 2, 1, true),
33
- getCell("", "", 1, 2, true),
34
- getCell("", "Number", 1, 2, true),
35
- getCell("", "", 1, 1, true),
36
- getCell("", "Number", 2, 1, true),
37
- ]
38
- },
39
- {
40
- tableCells: [
41
- ,
42
- getCell("", "OPD", 1, 1, true),
43
- getCell("", "IP", 1, 1, true),
44
- ,
45
- ,
46
- getCell(),
47
- getCell("", "Routine", 1, 1, true),
48
- getCell("", "Specialized", 1, 1, true),
49
- ]
50
- },
51
- {
52
- tableCells: [
53
- getCell("", "Malaria BS (Under five years)"),
54
- getCell(),
55
- getCell(),
56
- getCell("", "No. of Routine tests", 1, 2),
57
- getCell("", "", 1, 2),
58
- getCell("", "From Other HF"),
59
- getCell(),
60
- getCell()
61
- ]
62
- },
63
- {
64
- tableCells: [
65
- getCell("", "Malaria BS (5 years and above)"),
66
- getCell(),
67
- getCell(),
68
- ,
69
- ,
70
- getCell("", "To Other HF"),
71
- getCell(),
72
- getCell(),
73
- ]
74
- },
75
- {
76
- tableCells: [
77
- getCell("", "Malaria Rapid Diagnostic Tests (Under five years)"),
78
- getCell(),
79
- getCell(),
80
- getCell("", "No. of Special tests", 1, 2),
81
- getCell("", "", 1, 2),
82
- getCell("", "To Reference Laboratories", 1, 2),
83
- getCell("", "", 1, 2),
84
- getCell("", "", 1, 2)
85
- ]
86
- },
87
- {
88
- tableCells: [
89
- getCell("", "Malaria Rapid Diagnostic Tests (5 years and above)"),
90
- getCell(),
91
- getCell()
92
- ]
93
- },
94
- ]
95
- }, []);
15
+ /** Reference-lab tests count as the form's "special" tests; the rest are routine */
16
+ const SPECIAL_TEST_FLAGS = ['total_cd4', 'total_viral_load_specimens', 'total_tb_culture_specimens'];
96
17
 
97
-
98
- return <TableWrapper>
99
- {tableRows.map((tR) => (
100
- <TableRow>
101
- {tR.tableCells.map((tC) => (
102
- <TableCell className={styles.dataCell} colSpan={tC.colSpan} {...({ rowSpan: tC.rowSpan } as any)}>
103
- {tC.strong ? <strong>{tC.value}</strong> : tC.value}
104
- </TableCell>
105
- ))}
106
- </TableRow>
107
- ))}
108
- </TableWrapper>
18
+ interface Moh240PageSummaryProps {
19
+ /** The register rows currently fetched; the printed form summarises a page */
20
+ rows?: Array<Record<string, any>>;
109
21
  }
110
22
 
111
- export default Moh240PageSummary;
23
+ const Moh240PageSummary: React.FC<Moh240PageSummaryProps> = ({ rows = [] }) => {
24
+ const flagCount = (flag: string, inpatient: boolean) =>
25
+ rows.filter(
26
+ (row) => Number(row[flag]) === 1 && INPATIENT_ENCOUNTER_TYPES.includes(Number(row.encounter_type)) === inpatient,
27
+ ).length;
28
+
29
+ /* combined OPD+IP under the OPD cell while the split is undeterminable */
30
+ const malariaCell = (flag: string, inpatient: boolean) =>
31
+ INPATIENT_ENCOUNTER_TYPES.length === 0
32
+ ? inpatient
33
+ ? ''
34
+ : String(flagCount(flag, false) + flagCount(flag, true))
35
+ : String(flagCount(flag, inpatient));
36
+
37
+ const summary = useMemo(
38
+ () => ({
39
+ bsUnderFive: [malariaCell('total_malaria_bs_under_5', false), malariaCell('total_malaria_bs_under_5', true)],
40
+ bsFiveAndAbove: [
41
+ malariaCell('total_malaria_bs_5_and_above', false),
42
+ malariaCell('total_malaria_bs_5_and_above', true),
43
+ ],
44
+ rdtUnderFive: [malariaCell('total_malaria_rdt_under_5', false), malariaCell('total_malaria_rdt_under_5', true)],
45
+ rdtFiveAndAbove: [
46
+ malariaCell('total_malaria_rdt_5_and_above', false),
47
+ malariaCell('total_malaria_rdt_5_and_above', true),
48
+ ],
49
+ routineTests: rows.filter(
50
+ (row) => Number(row.total_exam) === 1 && !SPECIAL_TEST_FLAGS.some((flag) => Number(row[flag]) === 1),
51
+ ).length,
52
+ specialTests: rows.filter((row) => SPECIAL_TEST_FLAGS.some((flag) => Number(row[flag]) === 1)).length,
53
+ }),
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps
55
+ [rows],
56
+ );
57
+
58
+ const tableRows = useMemo(
59
+ () => [
60
+ {
61
+ tableCells: [getCell('', 'Page Summary', 8, 1, true)],
62
+ },
63
+ {
64
+ tableCells: [
65
+ getCell('', 'Malaria Testing', 3, 1, true),
66
+ getCell('', 'Type of test', 2, 1, true),
67
+ getCell('', 'Referrals', 3, 1, true),
68
+ ],
69
+ },
70
+ {
71
+ tableCells: [
72
+ getCell('', '', 1, 2, true),
73
+ getCell('', 'Number', 2, 1, true),
74
+ getCell('', '', 1, 2, true),
75
+ getCell('', 'Number', 1, 2, true),
76
+ getCell('', '', 1, 1, true),
77
+ getCell('', 'Number', 2, 1, true),
78
+ ],
79
+ },
80
+ {
81
+ tableCells: [
82
+ ,
83
+ getCell('', 'OPD', 1, 1, true),
84
+ getCell('', 'IP', 1, 1, true),
85
+ ,
86
+ ,
87
+ getCell(),
88
+ getCell('', 'Routine', 1, 1, true),
89
+ getCell('', 'Specialized', 1, 1, true),
90
+ ],
91
+ },
92
+ {
93
+ tableCells: [
94
+ getCell('', 'Malaria BS (Under five years)'),
95
+ getCell('', summary.bsUnderFive[0]),
96
+ getCell('', summary.bsUnderFive[1]),
97
+ getCell('', 'No. of Routine tests', 1, 2),
98
+ getCell('', String(summary.routineTests), 1, 2),
99
+ getCell('', 'From Other HF'),
100
+ getCell(),
101
+ getCell(),
102
+ ],
103
+ },
104
+ {
105
+ tableCells: [
106
+ getCell('', 'Malaria BS (5 years and above)'),
107
+ getCell('', summary.bsFiveAndAbove[0]),
108
+ getCell('', summary.bsFiveAndAbove[1]),
109
+ ,
110
+ ,
111
+ getCell('', 'To Other HF'),
112
+ getCell(),
113
+ getCell(),
114
+ ],
115
+ },
116
+ {
117
+ tableCells: [
118
+ getCell('', 'Malaria Rapid Diagnostic Tests (Under five years)'),
119
+ getCell('', summary.rdtUnderFive[0]),
120
+ getCell('', summary.rdtUnderFive[1]),
121
+ getCell('', 'No. of Special tests', 1, 2),
122
+ getCell('', String(summary.specialTests), 1, 2),
123
+ getCell('', 'To Reference Laboratories', 1, 2),
124
+ getCell('', '', 1, 2),
125
+ getCell('', '', 1, 2),
126
+ ],
127
+ },
128
+ {
129
+ tableCells: [
130
+ getCell('', 'Malaria Rapid Diagnostic Tests (5 years and above)'),
131
+ getCell('', summary.rdtFiveAndAbove[0]),
132
+ getCell('', summary.rdtFiveAndAbove[1]),
133
+ ],
134
+ },
135
+ ],
136
+ [summary],
137
+ );
138
+
139
+ return (
140
+ <div className={styles.summarySection}>
141
+ <TableWrapper className={styles.formTable}>
142
+ <TableRowMapper tableRows={tableRows} />
143
+ </TableWrapper>
144
+ </div>
145
+ );
146
+ };
147
+
148
+ export default Moh240PageSummary;