@bathiran212/esm-patient-chart-app 7.0.0

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 (382) hide show
  1. package/README.md +3 -0
  2. package/dist/108.js +1 -0
  3. package/dist/108.js.map +1 -0
  4. package/dist/1339.js +1 -0
  5. package/dist/1339.js.map +1 -0
  6. package/dist/1480.js +1 -0
  7. package/dist/1480.js.map +1 -0
  8. package/dist/1543.js +1 -0
  9. package/dist/1543.js.map +1 -0
  10. package/dist/1582.js +1 -0
  11. package/dist/1582.js.map +1 -0
  12. package/dist/1646.js +1 -0
  13. package/dist/1646.js.map +1 -0
  14. package/dist/1797.js +1 -0
  15. package/dist/1797.js.map +1 -0
  16. package/dist/1869.js +1 -0
  17. package/dist/1869.js.map +1 -0
  18. package/dist/1877.js +1 -0
  19. package/dist/1877.js.map +1 -0
  20. package/dist/2020.js +1 -0
  21. package/dist/2020.js.map +1 -0
  22. package/dist/2246.js +1 -0
  23. package/dist/2246.js.map +1 -0
  24. package/dist/2317.js +1 -0
  25. package/dist/2317.js.map +1 -0
  26. package/dist/2416.js +1 -0
  27. package/dist/2416.js.map +1 -0
  28. package/dist/2790.js +1 -0
  29. package/dist/2790.js.map +1 -0
  30. package/dist/282.js +1 -0
  31. package/dist/282.js.map +1 -0
  32. package/dist/2881.js +1 -0
  33. package/dist/2881.js.map +1 -0
  34. package/dist/3137.js +1 -0
  35. package/dist/3137.js.map +1 -0
  36. package/dist/3378.js +1 -0
  37. package/dist/3378.js.map +1 -0
  38. package/dist/3390.js +1 -0
  39. package/dist/3390.js.map +1 -0
  40. package/dist/3536.js +1 -0
  41. package/dist/3536.js.map +1 -0
  42. package/dist/3720.js +1 -0
  43. package/dist/3720.js.map +1 -0
  44. package/dist/3857.js +1 -0
  45. package/dist/3857.js.map +1 -0
  46. package/dist/3925.js +1 -0
  47. package/dist/3925.js.map +1 -0
  48. package/dist/3963.js +1 -0
  49. package/dist/3963.js.map +1 -0
  50. package/dist/3989.js +1 -0
  51. package/dist/3989.js.map +1 -0
  52. package/dist/4092.js +1 -0
  53. package/dist/4092.js.map +1 -0
  54. package/dist/4106.js +1 -0
  55. package/dist/4106.js.map +1 -0
  56. package/dist/4111.js +1 -0
  57. package/dist/4111.js.map +1 -0
  58. package/dist/4145.js +1 -0
  59. package/dist/4145.js.map +1 -0
  60. package/dist/434.js +1 -0
  61. package/dist/434.js.map +1 -0
  62. package/dist/4348.js +1 -0
  63. package/dist/4348.js.map +1 -0
  64. package/dist/4383.js +1 -0
  65. package/dist/4383.js.map +1 -0
  66. package/dist/4540.js +1 -0
  67. package/dist/4540.js.map +1 -0
  68. package/dist/4658.js +1 -0
  69. package/dist/4658.js.map +1 -0
  70. package/dist/466.js +1 -0
  71. package/dist/466.js.map +1 -0
  72. package/dist/4913.js +1 -0
  73. package/dist/4913.js.map +1 -0
  74. package/dist/4928.js +1 -0
  75. package/dist/4928.js.map +1 -0
  76. package/dist/5069.js +1 -0
  77. package/dist/5069.js.map +1 -0
  78. package/dist/5117.js +1 -0
  79. package/dist/5117.js.map +1 -0
  80. package/dist/5132.js +1 -0
  81. package/dist/5132.js.map +1 -0
  82. package/dist/5145.js +1 -0
  83. package/dist/5145.js.map +1 -0
  84. package/dist/52.js +1 -0
  85. package/dist/52.js.map +1 -0
  86. package/dist/5422.js +1 -0
  87. package/dist/5422.js.map +1 -0
  88. package/dist/5503.js +1 -0
  89. package/dist/5503.js.map +1 -0
  90. package/dist/5549.js +1 -0
  91. package/dist/5549.js.map +1 -0
  92. package/dist/556.js +1 -0
  93. package/dist/556.js.map +1 -0
  94. package/dist/5644.js +1 -0
  95. package/dist/5644.js.map +1 -0
  96. package/dist/5697.js +1 -0
  97. package/dist/5697.js.map +1 -0
  98. package/dist/5793.js +1 -0
  99. package/dist/5793.js.map +1 -0
  100. package/dist/5940.js +1 -0
  101. package/dist/5940.js.map +1 -0
  102. package/dist/5952.js +1 -0
  103. package/dist/5952.js.map +1 -0
  104. package/dist/6047.js +1 -0
  105. package/dist/6047.js.map +1 -0
  106. package/dist/6371.js +1 -0
  107. package/dist/6371.js.map +1 -0
  108. package/dist/6377.js +1 -0
  109. package/dist/6377.js.map +1 -0
  110. package/dist/6444.js +1 -0
  111. package/dist/6444.js.map +1 -0
  112. package/dist/6479.js +1 -0
  113. package/dist/6479.js.map +1 -0
  114. package/dist/6508.js +1 -0
  115. package/dist/6508.js.map +1 -0
  116. package/dist/6724.js +1 -0
  117. package/dist/6724.js.map +1 -0
  118. package/dist/6759.js +27 -0
  119. package/dist/6759.js.map +1 -0
  120. package/dist/689.js +1 -0
  121. package/dist/689.js.map +1 -0
  122. package/dist/6904.js +1 -0
  123. package/dist/6904.js.map +1 -0
  124. package/dist/7045.js +1 -0
  125. package/dist/7045.js.map +1 -0
  126. package/dist/7175.js +1 -0
  127. package/dist/7175.js.map +1 -0
  128. package/dist/7182.js +1 -0
  129. package/dist/7182.js.map +1 -0
  130. package/dist/7302.js +1 -0
  131. package/dist/7302.js.map +1 -0
  132. package/dist/7646.js +17 -0
  133. package/dist/7646.js.map +1 -0
  134. package/dist/7742.js +1 -0
  135. package/dist/7742.js.map +1 -0
  136. package/dist/7912.js +1 -0
  137. package/dist/7912.js.map +1 -0
  138. package/dist/8105.js +21 -0
  139. package/dist/8105.js.map +1 -0
  140. package/dist/8202.js +1 -0
  141. package/dist/8202.js.map +1 -0
  142. package/dist/8349.js +1 -0
  143. package/dist/8349.js.map +1 -0
  144. package/dist/8358.js +1 -0
  145. package/dist/8358.js.map +1 -0
  146. package/dist/8359.js +1 -0
  147. package/dist/8359.js.map +1 -0
  148. package/dist/8695.js +1 -0
  149. package/dist/8695.js.map +1 -0
  150. package/dist/8702.js +1 -0
  151. package/dist/8702.js.map +1 -0
  152. package/dist/8894.js +1 -0
  153. package/dist/8894.js.map +1 -0
  154. package/dist/8958.js +1 -0
  155. package/dist/8958.js.map +1 -0
  156. package/dist/903.js +1 -0
  157. package/dist/903.js.map +1 -0
  158. package/dist/9061.js +1 -0
  159. package/dist/9061.js.map +1 -0
  160. package/dist/9072.js +1 -0
  161. package/dist/9072.js.map +1 -0
  162. package/dist/9105.js +1 -0
  163. package/dist/9105.js.map +1 -0
  164. package/dist/9107.js +1 -0
  165. package/dist/9107.js.map +1 -0
  166. package/dist/9456.js +1 -0
  167. package/dist/9456.js.map +1 -0
  168. package/dist/9586.js +1 -0
  169. package/dist/9586.js.map +1 -0
  170. package/dist/9712.js +1 -0
  171. package/dist/9712.js.map +1 -0
  172. package/dist/9771.js +1 -0
  173. package/dist/9771.js.map +1 -0
  174. package/dist/9806.js +1 -0
  175. package/dist/9806.js.map +1 -0
  176. package/dist/9873.js +1 -0
  177. package/dist/9873.js.map +1 -0
  178. package/dist/9927.js +1 -0
  179. package/dist/9927.js.map +1 -0
  180. package/dist/main.js +6 -0
  181. package/dist/main.js.map +1 -0
  182. package/dist/openmrs-esm-patient-chart-app.js +6 -0
  183. package/dist/openmrs-esm-patient-chart-app.js.buildmanifest.json +2386 -0
  184. package/dist/openmrs-esm-patient-chart-app.js.map +1 -0
  185. package/dist/routes.json +1 -0
  186. package/package.json +63 -0
  187. package/rspack.config.js +1 -0
  188. package/src/actions-buttons/action-button.scss +3 -0
  189. package/src/actions-buttons/delete-visit.component.tsx +41 -0
  190. package/src/actions-buttons/delete-visit.test.tsx +26 -0
  191. package/src/actions-buttons/mark-patient-alive.component.tsx +42 -0
  192. package/src/actions-buttons/mark-patient-deceased.component.tsx +35 -0
  193. package/src/actions-buttons/start-visit.component.tsx +41 -0
  194. package/src/actions-buttons/start-visit.test.tsx +44 -0
  195. package/src/actions-buttons/stop-visit.component.tsx +39 -0
  196. package/src/actions-buttons/stop-visit.test.tsx +27 -0
  197. package/src/clinical-views/encounter-list/encounter-list-tabs.extension.tsx +78 -0
  198. package/src/clinical-views/encounter-list/encounter-list-tabs.scss +7 -0
  199. package/src/clinical-views/encounter-list/encounter-list.component.tsx +306 -0
  200. package/src/clinical-views/encounter-list/encounter-list.scss +36 -0
  201. package/src/clinical-views/encounter-list/table.component.tsx +63 -0
  202. package/src/clinical-views/encounter-list/table.scss +11 -0
  203. package/src/clinical-views/encounter-list/tag.component.test.tsx +307 -0
  204. package/src/clinical-views/encounter-list/tag.component.tsx +43 -0
  205. package/src/clinical-views/encounter-tile/clinical-views-summary.component.tsx +40 -0
  206. package/src/clinical-views/encounter-tile/encounter-tile.component.tsx +94 -0
  207. package/src/clinical-views/encounter-tile/tile.scss +82 -0
  208. package/src/clinical-views/hooks/index.ts +3 -0
  209. package/src/clinical-views/hooks/useEncounterRows.ts +60 -0
  210. package/src/clinical-views/hooks/useEncountersByVisit.ts +13 -0
  211. package/src/clinical-views/hooks/useFormsJson.ts +15 -0
  212. package/src/clinical-views/hooks/useLastEncounter.ts +29 -0
  213. package/src/clinical-views/types.ts +305 -0
  214. package/src/clinical-views/utils/concept-utils.ts +24 -0
  215. package/src/clinical-views/utils/encounter-list-config-builder.ts +160 -0
  216. package/src/clinical-views/utils/encounter-list.resource.ts +26 -0
  217. package/src/clinical-views/utils/helpers.ts +226 -0
  218. package/src/clinical-views/utils/index.ts +90 -0
  219. package/src/config-schema.ts +235 -0
  220. package/src/constants.ts +11 -0
  221. package/src/dashboard.meta.ts +15 -0
  222. package/src/data.resource.ts +117 -0
  223. package/src/declarations.d.ts +4 -0
  224. package/src/index.ts +204 -0
  225. package/src/loader/loader.component.tsx +11 -0
  226. package/src/loader/loader.scss +9 -0
  227. package/src/mark-patient-alive/mark-patient-alive.modal.tsx +54 -0
  228. package/src/mark-patient-deceased/mark-patient-deceased-form.scss +175 -0
  229. package/src/mark-patient-deceased/mark-patient-deceased-form.test.tsx +203 -0
  230. package/src/mark-patient-deceased/mark-patient-deceased-form.workspace.tsx +295 -0
  231. package/src/offline.ts +41 -0
  232. package/src/patient-banner-tags/visit-attribute-tags.extension.tsx +62 -0
  233. package/src/patient-banner-tags/visit-attribute-tags.scss +8 -0
  234. package/src/patient-chart/chart-review/chart-review.component.tsx +138 -0
  235. package/src/patient-chart/chart-review/chart-review.test.tsx +77 -0
  236. package/src/patient-chart/chart-review/dashboard-view.component.tsx +85 -0
  237. package/src/patient-chart/chart-review/dashboard-view.scss +84 -0
  238. package/src/patient-chart/patient-chart.component.tsx +71 -0
  239. package/src/patient-chart/patient-chart.resources.test.ts +238 -0
  240. package/src/patient-chart/patient-chart.resources.ts +231 -0
  241. package/src/patient-chart/patient-chart.scss +65 -0
  242. package/src/patient-details-tile/patient-details-tile.component.tsx +25 -0
  243. package/src/patient-details-tile/patient-details-tile.scss +24 -0
  244. package/src/root.component.tsx +35 -0
  245. package/src/root.scss +54 -0
  246. package/src/routes.json +267 -0
  247. package/src/side-nav/side-menu.component.tsx +10 -0
  248. package/src/side-nav/side-menu.scss +38 -0
  249. package/src/side-nav/side-menu.test.tsx +27 -0
  250. package/src/utils.test.ts +17 -0
  251. package/src/utils.ts +5 -0
  252. package/src/visit/hooks/useDefaultFacilityLocation.tsx +15 -0
  253. package/src/visit/hooks/useDefaultVisitLocation.tsx +24 -0
  254. package/src/visit/hooks/useDeleteVisit.test.tsx +267 -0
  255. package/src/visit/hooks/useDeleteVisit.tsx +103 -0
  256. package/src/visit/hooks/useOfflineVisitType.tsx +18 -0
  257. package/src/visit/hooks/useRecommendedVisitTypes.tsx +34 -0
  258. package/src/visit/hooks/useVisitAttributeType.tsx +102 -0
  259. package/src/visit/start-visit-button.component.tsx +47 -0
  260. package/src/visit/start-visit-button.test.tsx +32 -0
  261. package/src/visit/visit-action-items/delete-visit-action-item.component.tsx +60 -0
  262. package/src/visit/visit-action-items/delete-visit-action-item.test.tsx +48 -0
  263. package/src/visit/visit-action-items/edit-visit-details.component.tsx +79 -0
  264. package/src/visit/visit-form/base-visit-type.component.tsx +121 -0
  265. package/src/visit/visit-form/base-visit-type.scss +75 -0
  266. package/src/visit/visit-form/base-visit-type.test.tsx +153 -0
  267. package/src/visit/visit-form/exported-visit-form.workspace.tsx +755 -0
  268. package/src/visit/visit-form/location-selector.component.tsx +86 -0
  269. package/src/visit/visit-form/location-selector.test.tsx +146 -0
  270. package/src/visit/visit-form/recommended-visit-type.component.tsx +32 -0
  271. package/src/visit/visit-form/visit-attribute-type.component.tsx +258 -0
  272. package/src/visit/visit-form/visit-attribute-type.scss +5 -0
  273. package/src/visit/visit-form/visit-date-time.component.tsx +206 -0
  274. package/src/visit/visit-form/visit-form.resource.ts +401 -0
  275. package/src/visit/visit-form/visit-form.scss +167 -0
  276. package/src/visit/visit-form/visit-form.test.tsx +1233 -0
  277. package/src/visit/visit-form/visit-form.workspace.tsx +61 -0
  278. package/src/visit/visit-form/visit-type.test.tsx +88 -0
  279. package/src/visit/visit-history-table/visit-actions-cell.component.tsx +20 -0
  280. package/src/visit/visit-history-table/visit-actions-cell.scss +4 -0
  281. package/src/visit/visit-history-table/visit-date-cell.component.tsx +19 -0
  282. package/src/visit/visit-history-table/visit-diagnoses-cell.component.tsx +18 -0
  283. package/src/visit/visit-history-table/visit-history-table.component.tsx +145 -0
  284. package/src/visit/visit-history-table/visit-history-table.scss +25 -0
  285. package/src/visit/visit-history-table/visit-type-cell.component.tsx +15 -0
  286. package/src/visit/visit-prompt/delete-visit-dialog.modal.tsx +46 -0
  287. package/src/visit/visit-prompt/delete-visit-dialog.test.tsx +79 -0
  288. package/src/visit/visit-prompt/end-visit-dialog.modal.tsx +82 -0
  289. package/src/visit/visit-prompt/end-visit-dialog.scss +7 -0
  290. package/src/visit/visit-prompt/end-visit-dialog.test.tsx +131 -0
  291. package/src/visit/visit-prompt/modify-visit-date.modal.tsx +40 -0
  292. package/src/visit/visit-prompt/start-visit-dialog.modal.tsx +64 -0
  293. package/src/visit/visit-prompt/start-visit-dialog.scss +10 -0
  294. package/src/visit/visit-prompt/start-visit-dialog.test.tsx +40 -0
  295. package/src/visit/visits-widget/active-visit-buttons/active-visit-buttons.scss +7 -0
  296. package/src/visit/visits-widget/active-visit-buttons/active-visit-buttons.tsx +178 -0
  297. package/src/visit/visits-widget/current-visit-summary.extension.tsx +48 -0
  298. package/src/visit/visits-widget/current-visit-summary.scss +10 -0
  299. package/src/visit/visits-widget/current-visit-summary.test.tsx +85 -0
  300. package/src/visit/visits-widget/encounter-observations/encounter-observations.component.tsx +67 -0
  301. package/src/visit/visits-widget/encounter-observations/index.ts +3 -0
  302. package/src/visit/visits-widget/encounter-observations/styles.scss +22 -0
  303. package/src/visit/visits-widget/past-visits-components/delete-encounter.modal.tsx +47 -0
  304. package/src/visit/visits-widget/past-visits-components/delete-encounter.scss +9 -0
  305. package/src/visit/visits-widget/past-visits-components/encounters-table/all-encounters-table.component.tsx +49 -0
  306. package/src/visit/visits-widget/past-visits-components/encounters-table/completed-forms-table.component.tsx +67 -0
  307. package/src/visit/visits-widget/past-visits-components/encounters-table/completed-forms-table.test.tsx +146 -0
  308. package/src/visit/visits-widget/past-visits-components/encounters-table/encounters-table.component.tsx +452 -0
  309. package/src/visit/visits-widget/past-visits-components/encounters-table/encounters-table.resource.test.ts +156 -0
  310. package/src/visit/visits-widget/past-visits-components/encounters-table/encounters-table.resource.ts +215 -0
  311. package/src/visit/visits-widget/past-visits-components/encounters-table/encounters-table.scss +113 -0
  312. package/src/visit/visits-widget/past-visits-components/encounters-table/encounters-table.test.tsx +432 -0
  313. package/src/visit/visits-widget/past-visits-components/encounters-table/visit-completed-forms-table.component.tsx +61 -0
  314. package/src/visit/visits-widget/past-visits-components/encounters-table/visit-completed-forms-table.test.tsx +125 -0
  315. package/src/visit/visits-widget/past-visits-components/encounters-table/visit-encounters-table.component.tsx +47 -0
  316. package/src/visit/visits-widget/past-visits-components/medications-summary.component.tsx +163 -0
  317. package/src/visit/visits-widget/past-visits-components/notes-summary.component.tsx +66 -0
  318. package/src/visit/visits-widget/past-visits-components/patient-notes-summary.component.tsx +318 -0
  319. package/src/visit/visits-widget/past-visits-components/tests-summary.component.tsx +16 -0
  320. package/src/visit/visits-widget/past-visits-components/visit-summary.component.tsx +192 -0
  321. package/src/visit/visits-widget/past-visits-components/visit-summary.scss +72 -0
  322. package/src/visit/visits-widget/past-visits-components/visit-summary.test.tsx +105 -0
  323. package/src/visit/visits-widget/single-visit-details/visit-timeline/visit-timeline.component.tsx +94 -0
  324. package/src/visit/visits-widget/single-visit-details/visit-timeline/visit-timeline.scss +60 -0
  325. package/src/visit/visits-widget/visit-context/retrospective-data-date-time-picker/restrospective-date-time-picker.scss +35 -0
  326. package/src/visit/visits-widget/visit-context/retrospective-data-date-time-picker/retrospective-date-time-picker.component.tsx +140 -0
  327. package/src/visit/visits-widget/visit-context/visit-context-header.extension.tsx +61 -0
  328. package/src/visit/visits-widget/visit-context/visit-context-header.scss +45 -0
  329. package/src/visit/visits-widget/visit-context/visit-context-header.test.tsx +59 -0
  330. package/src/visit/visits-widget/visit-context/visit-context-info.component.tsx +37 -0
  331. package/src/visit/visits-widget/visit-context/visit-context-info.scss +12 -0
  332. package/src/visit/visits-widget/visit-context/visit-context-switcher.modal.tsx +166 -0
  333. package/src/visit/visits-widget/visit-context/visit-context-switcher.scss +83 -0
  334. package/src/visit/visits-widget/visit-context/visit-context-switcher.test.tsx +79 -0
  335. package/src/visit/visits-widget/visit-detail-overview.component.tsx +67 -0
  336. package/src/visit/visits-widget/visit-detail-overview.scss +301 -0
  337. package/src/visit/visits-widget/visit-detail-overview.test.tsx +205 -0
  338. package/src/visit/visits-widget/visit.resource.tsx +146 -0
  339. package/translations/am.json +209 -0
  340. package/translations/ar.json +209 -0
  341. package/translations/ar_SY.json +209 -0
  342. package/translations/bn.json +209 -0
  343. package/translations/cs.json +209 -0
  344. package/translations/de.json +209 -0
  345. package/translations/en.json +209 -0
  346. package/translations/en_US.json +209 -0
  347. package/translations/es.json +209 -0
  348. package/translations/es_MX.json +209 -0
  349. package/translations/fr.json +209 -0
  350. package/translations/he.json +209 -0
  351. package/translations/hi.json +209 -0
  352. package/translations/hi_IN.json +209 -0
  353. package/translations/id.json +209 -0
  354. package/translations/it.json +209 -0
  355. package/translations/ka.json +209 -0
  356. package/translations/km.json +209 -0
  357. package/translations/ku.json +209 -0
  358. package/translations/ky.json +209 -0
  359. package/translations/lg.json +209 -0
  360. package/translations/ne.json +209 -0
  361. package/translations/pl.json +209 -0
  362. package/translations/pt.json +209 -0
  363. package/translations/pt_BR.json +209 -0
  364. package/translations/qu.json +209 -0
  365. package/translations/ro_RO.json +209 -0
  366. package/translations/ru_RU.json +209 -0
  367. package/translations/si.json +209 -0
  368. package/translations/sq.json +209 -0
  369. package/translations/sw.json +209 -0
  370. package/translations/sw_KE.json +209 -0
  371. package/translations/tr.json +209 -0
  372. package/translations/tr_TR.json +209 -0
  373. package/translations/uk.json +209 -0
  374. package/translations/uz.json +209 -0
  375. package/translations/uz@Latn.json +209 -0
  376. package/translations/uz_UZ.json +209 -0
  377. package/translations/vi.json +209 -0
  378. package/translations/zh.json +209 -0
  379. package/translations/zh_CN.json +209 -0
  380. package/translations/zh_TW.json +209 -0
  381. package/tsconfig.json +4 -0
  382. package/vitest.config.ts +4 -0
@@ -0,0 +1,226 @@
1
+ import { age, formatDate, launchWorkspace2, parseDate, type Visit } from '@openmrs/esm-framework';
2
+ import { launchStartVisitPrompt } from '@openmrs/esm-patient-common-lib';
3
+ import type {
4
+ ConfigConcepts,
5
+ Encounter,
6
+ EncounterPropertyType,
7
+ EncounterTileColumn,
8
+ Form,
9
+ GetObsFromEncounterParams,
10
+ Observation,
11
+ } from '../types';
12
+ import type { TFunction } from 'i18next';
13
+
14
+ export type LaunchAction = 'add' | 'view' | 'edit' | 'embedded-view';
15
+
16
+ export function launchEncounterForm(
17
+ form: Form,
18
+ action: LaunchAction = 'add',
19
+ intent: string = '*',
20
+ requireActiveVisitForEncounterTile: boolean = true,
21
+ visit?: Visit,
22
+ encounterUuid?: string,
23
+ ) {
24
+ if (!visit && requireActiveVisitForEncounterTile) {
25
+ launchStartVisitPrompt();
26
+ } else {
27
+ launchWorkspace2('patient-form-entry-workspace', {
28
+ workspaceTitle: form?.display ?? form?.name,
29
+ form,
30
+ encounterUuid,
31
+ additionalProps: {
32
+ mode: action === 'add' ? 'enter' : action,
33
+ formSessionIntent: intent,
34
+ openClinicalFormsWorkspaceOnFormClose: false,
35
+ },
36
+ });
37
+ }
38
+ }
39
+
40
+ export function getEncounterValues(encounter: Encounter, param: string, isDate?: boolean) {
41
+ if (isDate) return formatDate(encounter[param]);
42
+ else return encounter[param] ?? '--';
43
+ }
44
+
45
+ export function obsArrayDateComparator(left: Observation, right: Observation) {
46
+ return new Date(right.obsDatetime).getTime() - new Date(left.obsDatetime).getTime();
47
+ }
48
+
49
+ export function findObs(encounter: Encounter, obsConcept: string): Observation {
50
+ const allObs = encounter?.obs?.filter((observation) => observation.concept.uuid === obsConcept) || [];
51
+ return allObs?.length == 1 ? allObs[0] : allObs.sort(obsArrayDateComparator)[0];
52
+ }
53
+
54
+ export function getObsFromEncounters(encounters: Encounter, obsConcept: string, config: ConfigConcepts) {
55
+ const filteredEnc = encounters?.find((enc) => enc.obs.find((obs) => obs.concept.uuid === obsConcept));
56
+ return getObsFromEncounter({ encounter: filteredEnc, obsConcept: obsConcept, config: config });
57
+ }
58
+
59
+ export function resolveValueUsingMappings(encounter: Encounter, concept: string, mappings, t: TFunction) {
60
+ const obs = findObs(encounter, concept);
61
+ for (const key in mappings) {
62
+ if (typeof obs?.value === 'object' && 'uuid' in obs.value && mappings[key] === obs?.value?.uuid) {
63
+ return t(key);
64
+ }
65
+ }
66
+ return '--';
67
+ }
68
+
69
+ export function getConditionalConceptValue(
70
+ encounter: Encounter,
71
+ conditionalConceptMappings,
72
+ isDate: boolean,
73
+ config: ConfigConcepts,
74
+ ) {
75
+ const { trueConcept, nonTrueConcept, dependantConcept, conditionalConcept } = conditionalConceptMappings;
76
+ const dependantValue = findObs(encounter, dependantConcept)?.value;
77
+ const dependantUuid =
78
+ typeof dependantValue === 'object' && 'uuid' in dependantValue ? dependantValue.uuid : undefined;
79
+ const finalConcept = dependantUuid === conditionalConcept ? trueConcept : nonTrueConcept;
80
+ return getObsFromEncounter({
81
+ encounter: encounter,
82
+ obsConcept: finalConcept,
83
+ isDate: isDate,
84
+ isTrueFalseConcept: false,
85
+ config: config,
86
+ });
87
+ }
88
+
89
+ export function getConceptFromMappings(encounter: Encounter, concepts: Array<string>) {
90
+ for (const concept of concepts) {
91
+ const obs = findObs(encounter, concept);
92
+ if (obs && obs.value) {
93
+ return concept;
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+
99
+ export function getMultipleObsFromEncounter(encounter: Encounter, obsConcepts: Array<string>, config: ConfigConcepts) {
100
+ let observations = [];
101
+ obsConcepts.map((concept) => {
102
+ const obs = getObsFromEncounter({ encounter: encounter, obsConcept: concept, config: config });
103
+ if (obs !== '--') {
104
+ observations.push(obs);
105
+ }
106
+ });
107
+
108
+ return observations.length ? observations.join(', ') : '--';
109
+ }
110
+
111
+ /**
112
+ * Retrieves and formats an observation from an encounter based on the provided concept and various options.
113
+ *
114
+ * @param encounter - The encounter object from which observations will be extracted.
115
+ * @param obsConcept - The main concept to search for in the encounter's observations.
116
+ * @param isDate - Optional flag to indicate if the observation value should be treated as a date.
117
+ * @param isTrueFalseConcept - Optional flag to check if the observation concept represents a true/false value.
118
+ * @param type - Optional property type for filtering or fetching additional encounter properties.
119
+ * @param fallbackConcepts - Optional list of alternative concepts to use if the primary concept is not found.
120
+ * @param secondaryConcept - Optional secondary concept to check if the primary value matches a specific condition.
121
+ * @param t - Optional translation function.
122
+ * @returns The value of the observation, formatted appropriately, or '--' if not found or applicable.
123
+ */
124
+ export function getObsFromEncounter({
125
+ encounter,
126
+ obsConcept,
127
+ isDate = false,
128
+ isTrueFalseConcept = false,
129
+ type,
130
+ fallbackConcepts = [],
131
+ secondaryConcept,
132
+ config,
133
+ }: GetObsFromEncounterParams) {
134
+ let obs = findObs(encounter, obsConcept);
135
+
136
+ if (!encounter && !obsConcept) {
137
+ return '--';
138
+ }
139
+
140
+ if (isTrueFalseConcept) {
141
+ if (typeof obs?.value === 'object') {
142
+ return obs?.value?.name?.name;
143
+ }
144
+ }
145
+
146
+ // handles things like location, provider, visit type, etc. that are not in the encounter
147
+ if (type) {
148
+ return getEncounterProperty(encounter, type);
149
+ }
150
+
151
+ if (secondaryConcept && typeof obs.value === 'object' && obs.value.names) {
152
+ const primaryValue = obs.value.name.display;
153
+ if (primaryValue === config.otherConceptUuid) {
154
+ const secondaryObs = findObs(encounter, secondaryConcept);
155
+ return secondaryObs ? secondaryObs.value : '--';
156
+ }
157
+ }
158
+
159
+ if (!obs && fallbackConcepts?.length) {
160
+ const concept = fallbackConcepts.find((c) => findObs(encounter, c) != null);
161
+ obs = findObs(encounter, concept);
162
+ }
163
+
164
+ if (!obs) {
165
+ return '--';
166
+ }
167
+
168
+ // format format obs date or datetime based on the obs value's type
169
+ if (isDate) {
170
+ if (typeof obs.value === 'object' && obs.value?.names) {
171
+ return formatDate(parseDate(obs.obsDatetime), { mode: 'wide', time: false });
172
+ } else if (typeof obs.value === 'string') {
173
+ return formatDate(parseDate(obs.value), { mode: 'wide', time: false });
174
+ }
175
+ }
176
+
177
+ if (typeof obs.value === 'object' && obs.value?.name) {
178
+ return obs.value?.name?.display ?? obs.value?.name?.name ?? '--';
179
+ }
180
+ return obs.value;
181
+ }
182
+
183
+ export const groupColumnsByEncounterType = (columns: EncounterTileColumn[]): Record<string, EncounterTileColumn[]> => {
184
+ return columns.reduce((acc: Record<string, EncounterTileColumn[]>, column) => {
185
+ if (!acc[column.encounterTypeUuid]) {
186
+ acc[column.encounterTypeUuid] = [];
187
+ }
188
+ acc[column.encounterTypeUuid].push(column);
189
+ return acc;
190
+ }, {});
191
+ };
192
+
193
+ export const getEncounterProperty = (encounter: Encounter, type: EncounterPropertyType) => {
194
+ if (type === 'location') {
195
+ return encounter.location.display;
196
+ }
197
+
198
+ if (type === 'provider') {
199
+ return encounter.encounterProviders.map((p) => p.provider.name).join(' | ');
200
+ }
201
+
202
+ if (type === 'encounterType') {
203
+ return encounter.encounterType.name;
204
+ }
205
+
206
+ if (type === 'ageAtEncounter') {
207
+ return age(encounter.patient.birthDate, encounter.encounterDatetime);
208
+ }
209
+
210
+ if (type === 'visitDate') {
211
+ if (encounter.visit?.startDatetime) {
212
+ return formatDate(parseDate(encounter.visit.startDatetime), { mode: 'wide' });
213
+ }
214
+ return '--';
215
+ }
216
+
217
+ if (type === 'visitType') {
218
+ return encounter.visit?.visitType?.display ?? '--';
219
+ }
220
+
221
+ if (type === 'encounterDatetime') {
222
+ return formatDate(parseDate(encounter.encounterDatetime), { mode: 'wide' });
223
+ }
224
+ };
225
+
226
+ export const filter = (encounter: Encounter, formUuid: string) => encounter?.form?.uuid === formUuid;
@@ -0,0 +1,90 @@
1
+ import { getConceptFromMappings, getObsFromEncounter } from './helpers';
2
+ import type { Encounter, ColumnDefinition, ConfigConcepts, EncounterTileColumn, MenuCardProps } from '../types';
3
+ import dayjs from 'dayjs';
4
+
5
+ const calculateDateDifferenceInDate = (givenDate: string): string => {
6
+ return `${Math.abs(dayjs().diff(dayjs(givenDate), 'days'))} days`;
7
+ };
8
+
9
+ export const getEncounterTileColumns = (tileDefinition: MenuCardProps, config: ConfigConcepts) => {
10
+ const columns: Array<EncounterTileColumn> = tileDefinition.columns?.map((column: ColumnDefinition) => ({
11
+ key: column.title,
12
+ header: column.title,
13
+ concept: column.concept,
14
+ encounterTypeUuid: column.encounterType,
15
+ hasSummary: column.hasSummary || false,
16
+ summaryConcept: column.summaryConcept,
17
+ getObsValue: (encounter: Encounter) => {
18
+ let obsValue;
19
+ if (column.conceptMappings) {
20
+ const concept = getConceptFromMappings(encounter, column.conceptMappings);
21
+ obsValue = getObsFromEncounter({
22
+ encounter: encounter,
23
+ obsConcept: concept,
24
+ isDate: column.isDate,
25
+ isTrueFalseConcept: column.isTrueFalseConcept,
26
+ type: column.type,
27
+ fallbackConcepts: column.fallbackConcepts,
28
+ secondaryConcept: column.summaryConcept?.secondaryConcept,
29
+ config: config,
30
+ });
31
+ } else {
32
+ obsValue = getObsFromEncounter({
33
+ encounter: encounter,
34
+ obsConcept: column.concept,
35
+ isDate: column.isDate,
36
+ config: config,
37
+ });
38
+ }
39
+ return typeof obsValue === 'string' || (typeof obsValue === 'number' && !isNaN(obsValue))
40
+ ? obsValue
41
+ : obsValue?.name?.name ?? '--';
42
+ },
43
+ getSummaryObsValue: column.hasSummary
44
+ ? (encounter: Encounter) => {
45
+ let summaryValue;
46
+
47
+ if (column.summaryConcept?.secondaryConcept) {
48
+ const primaryConceptType = getObsFromEncounter({
49
+ encounter: encounter,
50
+ obsConcept: column.summaryConcept.primaryConcept,
51
+ config: config,
52
+ });
53
+
54
+ if (primaryConceptType !== '--') {
55
+ summaryValue = primaryConceptType;
56
+ } else {
57
+ summaryValue = getObsFromEncounter({
58
+ encounter: encounter,
59
+ obsConcept: column.summaryConcept.secondaryConcept,
60
+ config: config,
61
+ });
62
+ }
63
+ } else if (column.summaryConcept?.hasCalculatedDate) {
64
+ const primaryDate = getObsFromEncounter({
65
+ encounter: encounter,
66
+ obsConcept: column.summaryConcept.primaryConcept,
67
+ isDate: false,
68
+ config,
69
+ });
70
+
71
+ if (typeof primaryDate === 'string' && primaryDate !== '--') {
72
+ summaryValue = calculateDateDifferenceInDate(primaryDate);
73
+ } else {
74
+ summaryValue = '--';
75
+ }
76
+ } else {
77
+ summaryValue = getObsFromEncounter({
78
+ encounter: encounter,
79
+ obsConcept: column.summaryConcept?.primaryConcept,
80
+ isDate: column.summaryConcept?.isDate,
81
+ config: config,
82
+ type: column.summaryConcept?.type,
83
+ });
84
+ }
85
+ return typeof summaryValue === 'string' ? summaryValue : summaryValue?.name?.name || '--';
86
+ }
87
+ : null,
88
+ }));
89
+ return columns;
90
+ };
@@ -0,0 +1,235 @@
1
+ import { Type } from '@openmrs/esm-framework';
2
+
3
+ export const esmPatientChartSchema = {
4
+ defaultFacilityUrl: {
5
+ _type: Type.String,
6
+ _default: '',
7
+ _description: 'Custom URL to load default facility if it is not in the session',
8
+ },
9
+ disableChangingVisitLocation: {
10
+ _type: Type.Boolean,
11
+ _description: 'Whether the visit location field in the Start Visit form should be view-only.',
12
+ _default: false,
13
+ },
14
+ disableEmptyTabs: {
15
+ _type: Type.Boolean,
16
+ _default: false,
17
+ _description: 'Disable notes/tests/medications/encounters tabs when empty',
18
+ },
19
+ encounterEditableDuration: {
20
+ _type: Type.Number,
21
+ _default: 0,
22
+ _description:
23
+ 'The number of minutes an encounter is editable after it is created. 0 means the encounter is editable forever.',
24
+ },
25
+ encounterEditableDurationOverridePrivileges: {
26
+ _type: Type.Array,
27
+ _elements: {
28
+ _type: Type.String,
29
+ },
30
+ _default: [],
31
+ _description:
32
+ 'The privileges that allow users to edit encounters even after the editable duration (set by `encounterEditableDuration`) has expired. Any privilege in the list is sufficient to edit the encounter.',
33
+ },
34
+ freeTextFieldConceptUuid: {
35
+ _type: Type.ConceptUuid,
36
+ _default: '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
37
+ },
38
+ logo: {
39
+ alt: {
40
+ _type: Type.String,
41
+ _default: 'Logo',
42
+ _description: 'Alt text, shown on hover',
43
+ },
44
+ name: {
45
+ _type: Type.String,
46
+ _default: '',
47
+ _description: 'The organization name displayed when image is absent',
48
+ },
49
+ src: {
50
+ _type: Type.String,
51
+ _default: '',
52
+ _description: 'A path or URL to an image. Defaults to the OpenMRS SVG sprite.',
53
+ },
54
+ },
55
+ notesConceptUuids: {
56
+ _type: Type.Array,
57
+ _elements: {
58
+ _type: Type.ConceptUuid,
59
+ },
60
+ _default: ['162169AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'],
61
+ },
62
+ obsConceptUuidsToHide: {
63
+ _type: Type.Array,
64
+ _elements: {
65
+ _type: Type.ConceptUuid,
66
+ },
67
+ _description:
68
+ 'An array of concept UUIDs. If an observation has a concept UUID that matches any of the ones in this array, it will be hidden from the observations list in the Encounters summary table.',
69
+ _default: [],
70
+ },
71
+ offlineVisitTypeUuid: {
72
+ _type: Type.UUID,
73
+ _description: 'The UUID of the visit type to be used for the automatically created offline visits.',
74
+ _default: 'a22733fa-3501-4020-a520-da024eeff088',
75
+ },
76
+ restrictByVisitLocationTag: {
77
+ _type: Type.Boolean,
78
+ _description:
79
+ 'On the start visit form, whether to restrict the visit location to locations with the Visit Location tag',
80
+ _default: false,
81
+ },
82
+ showAllEncountersTab: {
83
+ _type: Type.Boolean,
84
+ _description: 'Shows the All Encounters Tab of Patient Visits section in Patient Chart',
85
+ _default: true,
86
+ },
87
+ showRecommendedVisitTypeTab: {
88
+ _type: Type.Boolean,
89
+ _description: 'Whether start visit form should display recommended visit type tab. Requires `visitTypeResourceUrl`',
90
+ _default: false,
91
+ },
92
+ showServiceQueueFields: {
93
+ _type: Type.Boolean,
94
+ _description: 'Whether start visit form should display service queue fields`',
95
+ _default: false,
96
+ },
97
+ showUpcomingAppointments: {
98
+ _type: Type.Boolean,
99
+ _description: 'Whether start visit form should display upcoming appointments',
100
+ _default: false,
101
+ },
102
+ visitAttributeTypes: {
103
+ _type: Type.Array,
104
+ _elements: {
105
+ _type: Type.Object,
106
+ uuid: {
107
+ _type: Type.UUID,
108
+ _description: 'UUID of the visit attribute type',
109
+ },
110
+ required: {
111
+ _type: Type.Boolean,
112
+ _description: 'Whether the attribute type field is required or not',
113
+ _default: false,
114
+ },
115
+ displayInThePatientBanner: {
116
+ _type: Type.Boolean,
117
+ _description: "Whether we should show this visit attribute's value in the patient banner",
118
+ _default: true,
119
+ },
120
+ },
121
+ _description: 'List of visit attribute types shown when filling the visit form',
122
+ _default: [
123
+ {
124
+ uuid: '57ea0cbb-064f-4d09-8cf4-e8228700491c',
125
+ required: false,
126
+ displayInThePatientBanner: true,
127
+ },
128
+ {
129
+ uuid: 'aac48226-d143-4274-80e0-264db4e368ee',
130
+ required: false,
131
+ displayInThePatientBanner: true,
132
+ },
133
+ ],
134
+ },
135
+ visitDiagnosisConceptUuid: {
136
+ _type: Type.ConceptUuid,
137
+ _default: '159947AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
138
+ },
139
+ visitTypeResourceUrl: {
140
+ _type: Type.String,
141
+ _default: '/etl-latest/etl/patient/',
142
+ _description: 'Custom URL to load resources required for showing recommended visit types',
143
+ },
144
+ trueConceptUuid: {
145
+ _type: Type.ConceptUuid,
146
+ _description: 'Default concept uuid for true in forms',
147
+ _default: '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
148
+ },
149
+ falseConceptUuid: {
150
+ _type: Type.ConceptUuid,
151
+ _description: 'Default concept uuid for false in forms',
152
+ _default: '1066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
153
+ },
154
+ otherConceptUuid: {
155
+ _type: Type.ConceptUuid,
156
+ _description: 'Default concept uuid for other in forms',
157
+ _default: '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
158
+ },
159
+ tileDefinitions: {
160
+ _type: Type.Array,
161
+ _default: [
162
+ {
163
+ title: 'Weight and Height',
164
+ columns: [
165
+ {
166
+ title: 'Weight',
167
+ concept: '5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
168
+ encounterType: '67a71486-1a54-468f-ac3e-7091a9a79584',
169
+ hasSummary: true,
170
+ },
171
+ {
172
+ title: 'Height',
173
+ concept: '5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
174
+ encounterType: '67a71486-1a54-468f-ac3e-7091a9a79584',
175
+ hasSummary: true,
176
+ },
177
+ ],
178
+ },
179
+ ],
180
+ _description: 'Definitions for clinical summary tiles with their concepts and encounter types',
181
+ },
182
+ requireActiveVisitForEncounterTile: {
183
+ _type: Type.Boolean,
184
+ _description: 'Whether to require an active visit for the encounter tile',
185
+ _default: true,
186
+ },
187
+ drugOrderTypeUUID: {
188
+ _type: Type.UUID,
189
+ _description: "UUID for the 'Drug' order type to fetch medications",
190
+ _default: '131168f4-15f5-102d-96e4-000c29c2a5d7',
191
+ },
192
+ };
193
+
194
+ export interface ChartConfig {
195
+ defaultFacilityUrl: string;
196
+ disableChangingVisitLocation: boolean;
197
+ disableEmptyTabs: boolean;
198
+ encounterEditableDuration: number;
199
+ encounterEditableDurationOverridePrivileges: Array<string>;
200
+ freeTextFieldConceptUuid: string;
201
+ logo: {
202
+ alt: string;
203
+ name: string;
204
+ src: string;
205
+ };
206
+ notesConceptUuids: string[];
207
+ offlineVisitTypeUuid: string;
208
+ restrictByVisitLocationTag: boolean;
209
+ showAllEncountersTab: boolean;
210
+ showRecommendedVisitTypeTab: boolean;
211
+ showServiceQueueFields: boolean; // used by extension from esm-service-queues-app
212
+ showUpcomingAppointments: boolean; // used by extension from esm-appointments-app
213
+ visitTypeResourceUrl: string;
214
+ visitAttributeTypes: Array<{
215
+ displayInThePatientBanner: boolean;
216
+ required: boolean;
217
+ showWhenExpression?: string;
218
+ uuid: string;
219
+ }>;
220
+ visitDiagnosisConceptUuid: string;
221
+ requireActiveVisitForEncounterTile: boolean;
222
+ trueConceptUuid: string;
223
+ falseConceptUuid: string;
224
+ tileDefinitions: Array<{
225
+ title: string;
226
+ columns: Array<{
227
+ title: string;
228
+ concept: string;
229
+ encounterType: string;
230
+ hasSummary?: boolean;
231
+ }>;
232
+ }>;
233
+ otherConceptUuid: string;
234
+ drugOrderTypeUUID: string;
235
+ }
@@ -0,0 +1,11 @@
1
+ export const clinicalFormsWorkspace = 'clinical-forms-workspace';
2
+ export const formEntryWorkspace = 'patient-form-entry-workspace';
3
+ export const spaRoot = window['getOpenmrsSpaBase']();
4
+ export const basePath = '/patient/:patientUuid/chart';
5
+ export const dashboardPath = `${basePath}/:view/*`;
6
+ export const spaBasePath = `${window.spaBase}${basePath}`;
7
+ export const moduleName = '@openmrs/esm-patient-chart-app';
8
+ export const patientChartWorkspaceSlot = 'patient-chart-workspace-slot';
9
+ export const patientChartWorkspaceHeaderSlot = 'patient-chart-workspace-header-slot';
10
+ export const omrsDateFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZZ';
11
+ export const jsonSchemaResourceName = 'JSON schema';
@@ -0,0 +1,15 @@
1
+ import { type DashboardLinkConfig } from '@openmrs/esm-patient-common-lib';
2
+
3
+ export const summaryDashboardMeta: DashboardLinkConfig & { slot: string } = {
4
+ slot: 'patient-chart-summary-dashboard-slot',
5
+ path: 'patient-summary',
6
+ title: 'Patient Summary',
7
+ icon: 'omrs-icon-report',
8
+ };
9
+
10
+ export const encountersDashboardMeta: DashboardLinkConfig & { slot: string } = {
11
+ slot: 'patient-chart-encounters-dashboard-slot',
12
+ path: 'visits',
13
+ title: 'Visits',
14
+ icon: 'omrs-icon-calendar-heat-map',
15
+ };
@@ -0,0 +1,117 @@
1
+ import { useMemo } from 'react';
2
+ import useSWR from 'swr';
3
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
4
+
5
+ interface CauseOfDeathFetchResponse {
6
+ uuid: string;
7
+ value: string;
8
+ }
9
+
10
+ export interface ConceptAnswer {
11
+ display: string;
12
+ name: string;
13
+ uuid: string;
14
+ }
15
+
16
+ interface ConceptAnswersResponse {
17
+ answers?: Array<ConceptAnswer>;
18
+ }
19
+
20
+ interface CauseOfDeathPayload {
21
+ causeOfDeath?: string;
22
+ causeOfDeathNonCoded?: string;
23
+ dead: boolean;
24
+ deathDate?: Date;
25
+ }
26
+
27
+ export function useCausesOfDeath() {
28
+ const { isCauseOfDeathLoading, isCauseOfDeathValidating, value: causeOfDeathConcept } = useCauseOfDeathConcept();
29
+ const { isConceptLoading, isConceptAnswerValidating, conceptAnswers } = useConceptAnswers(causeOfDeathConcept);
30
+
31
+ return {
32
+ causesOfDeath: conceptAnswers,
33
+ isLoading: isCauseOfDeathLoading || isConceptLoading,
34
+ isValidating: isConceptAnswerValidating || isCauseOfDeathValidating,
35
+ };
36
+ }
37
+
38
+ const changePatientDeathStatus = (personUuid: string, payload: CauseOfDeathPayload) => {
39
+ const abortController = new AbortController();
40
+
41
+ return openmrsFetch(`${restBaseUrl}/person/${personUuid}`, {
42
+ headers: {
43
+ 'Content-type': 'application/json',
44
+ },
45
+ method: 'POST',
46
+ body: payload,
47
+ signal: abortController.signal,
48
+ });
49
+ };
50
+
51
+ export function markPatientDeceased(
52
+ deceasedDate: Date,
53
+ personUuid: string,
54
+ selectedCauseOfDeathValue: string | undefined,
55
+ nonCodedCauseOfDeath?: string | undefined,
56
+ ) {
57
+ const payload: CauseOfDeathPayload = {
58
+ dead: true,
59
+ deathDate: deceasedDate || null,
60
+ ...(nonCodedCauseOfDeath
61
+ ? { causeOfDeathNonCoded: nonCodedCauseOfDeath }
62
+ : {
63
+ causeOfDeath: selectedCauseOfDeathValue,
64
+ }),
65
+ };
66
+
67
+ return changePatientDeathStatus(personUuid, payload);
68
+ }
69
+
70
+ export function markPatientAlive(personUuid: string) {
71
+ return changePatientDeathStatus(personUuid, {
72
+ causeOfDeath: null,
73
+ causeOfDeathNonCoded: null,
74
+ dead: false,
75
+ deathDate: null,
76
+ });
77
+ }
78
+
79
+ export function useConceptAnswers(conceptUuid: string) {
80
+ const { data, error, isLoading, isValidating } = useSWR<{ data: ConceptAnswersResponse }, Error>(
81
+ `${restBaseUrl}/concept/${conceptUuid}`,
82
+ (url) => (conceptUuid ? openmrsFetch(url) : undefined),
83
+ {
84
+ shouldRetryOnError(err) {
85
+ return err instanceof Response && err.status !== 404;
86
+ },
87
+ },
88
+ );
89
+
90
+ return {
91
+ conceptAnswers: data?.data?.answers ?? ([] as ConceptAnswer[]),
92
+ isConceptLoading: isLoading,
93
+ conceptError: error,
94
+ isConceptAnswerValidating: isValidating,
95
+ };
96
+ }
97
+
98
+ export function useCauseOfDeathConcept() {
99
+ const { data, error, isLoading, isValidating } = useSWR<{ data: CauseOfDeathFetchResponse }, Error>(
100
+ `${restBaseUrl}/systemsetting/concept.causeOfDeath`,
101
+ openmrsFetch,
102
+ {
103
+ shouldRetryOnError(err) {
104
+ return err instanceof Response && err.status !== 404;
105
+ },
106
+ },
107
+ );
108
+ const result = useMemo(() => {
109
+ return {
110
+ value: data?.data?.value ?? undefined,
111
+ isCauseOfDeathLoading: isLoading,
112
+ isCauseOfDeathValidating: isValidating,
113
+ error,
114
+ };
115
+ }, [data?.data?.value, error, isLoading, isValidating]);
116
+ return result;
117
+ }
@@ -0,0 +1,4 @@
1
+ declare module '*.scss' {
2
+ const content: { [className: string]: string };
3
+ export default content;
4
+ }