@kenyaemr/esm-express-workflow-app 5.4.4-pre.43 → 5.4.4-pre.430

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 (627) hide show
  1. package/.turbo/turbo-build.log +14 -7
  2. package/dist/1084.js +1 -0
  3. package/dist/1084.js.map +1 -0
  4. package/dist/1278.js +1 -0
  5. package/dist/1278.js.map +1 -0
  6. package/dist/1324.js +1 -0
  7. package/dist/1324.js.map +1 -0
  8. package/dist/1375.js +66 -0
  9. package/dist/1375.js.map +1 -0
  10. package/dist/1402.js +1 -0
  11. package/dist/1402.js.map +1 -0
  12. package/dist/1442.js +1 -0
  13. package/dist/1442.js.map +1 -0
  14. package/dist/1520.js +1 -0
  15. package/dist/1520.js.map +1 -0
  16. package/dist/1559.js +1 -0
  17. package/dist/1559.js.map +1 -0
  18. package/dist/1593.js +1 -0
  19. package/dist/1593.js.map +1 -0
  20. package/dist/162.js +1 -0
  21. package/dist/162.js.map +1 -0
  22. package/dist/1620.js +1 -0
  23. package/dist/1620.js.map +1 -0
  24. package/dist/1658.js +1 -0
  25. package/dist/1658.js.map +1 -0
  26. package/dist/1659.js +1 -0
  27. package/dist/1659.js.map +1 -0
  28. package/dist/1789.js +1 -0
  29. package/dist/1789.js.map +1 -0
  30. package/dist/1827.js +1 -0
  31. package/dist/1827.js.map +1 -0
  32. package/dist/1831.js +1 -0
  33. package/dist/1831.js.map +1 -0
  34. package/dist/1854.js +1 -0
  35. package/dist/1854.js.map +1 -0
  36. package/dist/196.js +1 -0
  37. package/dist/196.js.map +1 -0
  38. package/dist/2127.js +1 -0
  39. package/dist/2127.js.map +1 -0
  40. package/dist/2152.js +1 -0
  41. package/dist/2152.js.map +1 -0
  42. package/dist/2202.js +1 -0
  43. package/dist/2202.js.map +1 -0
  44. package/dist/221.js +1 -0
  45. package/dist/221.js.map +1 -0
  46. package/dist/2269.js +1 -0
  47. package/dist/2269.js.map +1 -0
  48. package/dist/2293.js +1 -0
  49. package/dist/2293.js.map +1 -0
  50. package/dist/234.js +1 -0
  51. package/dist/234.js.map +1 -0
  52. package/dist/2412.js +1 -1
  53. package/dist/2412.js.map +1 -1
  54. package/dist/2466.js +1 -0
  55. package/dist/2466.js.map +1 -0
  56. package/dist/2534.js +1 -1
  57. package/dist/2534.js.map +1 -1
  58. package/dist/2553.js +1 -0
  59. package/dist/2553.js.map +1 -0
  60. package/dist/2556.js +1 -0
  61. package/dist/2556.js.map +1 -0
  62. package/dist/2648.js +1 -0
  63. package/dist/2648.js.map +1 -0
  64. package/dist/274.js +1 -0
  65. package/dist/274.js.map +1 -0
  66. package/dist/2788.js +1 -0
  67. package/dist/2788.js.map +1 -0
  68. package/dist/2842.js +1 -0
  69. package/dist/2842.js.map +1 -0
  70. package/dist/2874.js +1 -0
  71. package/dist/2874.js.map +1 -0
  72. package/dist/2916.js +1 -0
  73. package/dist/2916.js.map +1 -0
  74. package/dist/2947.js +1 -1
  75. package/dist/2947.js.map +1 -1
  76. package/dist/3012.js +1 -0
  77. package/dist/3012.js.map +1 -0
  78. package/dist/3087.js +1 -0
  79. package/dist/3087.js.map +1 -0
  80. package/dist/3335.js +1 -0
  81. package/dist/3335.js.map +1 -0
  82. package/dist/3378.js +1 -0
  83. package/dist/3378.js.map +1 -0
  84. package/dist/3504.js +1 -0
  85. package/dist/3504.js.map +1 -0
  86. package/dist/3509.js +1 -1
  87. package/dist/3509.js.map +1 -1
  88. package/dist/356.js +1 -0
  89. package/dist/356.js.map +1 -0
  90. package/dist/3690.js +1 -0
  91. package/dist/3690.js.map +1 -0
  92. package/dist/371.js +1 -0
  93. package/dist/371.js.map +1 -0
  94. package/dist/3747.js +1 -0
  95. package/dist/3747.js.map +1 -0
  96. package/dist/3819.js +1 -0
  97. package/dist/3819.js.map +1 -0
  98. package/dist/3820.js +1 -0
  99. package/dist/3820.js.map +1 -0
  100. package/dist/3910.js +1 -0
  101. package/dist/3910.js.map +1 -0
  102. package/dist/393.js +6 -0
  103. package/dist/393.js.map +1 -0
  104. package/dist/3933.js +1 -0
  105. package/dist/3933.js.map +1 -0
  106. package/dist/3989.js +1 -0
  107. package/dist/3989.js.map +1 -0
  108. package/dist/3995.js +1 -0
  109. package/dist/3995.js.map +1 -0
  110. package/dist/4032.js +1 -0
  111. package/dist/4032.js.map +1 -0
  112. package/dist/4145.js +1 -1
  113. package/dist/4145.js.map +1 -1
  114. package/dist/4178.js +1 -1
  115. package/dist/4178.js.map +1 -1
  116. package/dist/4191.js +1 -0
  117. package/dist/4191.js.map +1 -0
  118. package/dist/4212.js +1 -0
  119. package/dist/4212.js.map +1 -0
  120. package/dist/4215.js +1 -0
  121. package/dist/4215.js.map +1 -0
  122. package/dist/4523.js +1 -0
  123. package/dist/4523.js.map +1 -0
  124. package/dist/4588.js +1 -0
  125. package/dist/4588.js.map +1 -0
  126. package/dist/4617.js +1 -0
  127. package/dist/4617.js.map +1 -0
  128. package/dist/466.js +1 -1
  129. package/dist/466.js.map +1 -1
  130. package/dist/4688.js +1 -0
  131. package/dist/{7288.js.map → 4688.js.map} +1 -1
  132. package/dist/470.js +1 -0
  133. package/dist/470.js.map +1 -0
  134. package/dist/4759.js +1 -0
  135. package/dist/4759.js.map +1 -0
  136. package/dist/4818.js +1 -1
  137. package/dist/4818.js.map +1 -1
  138. package/dist/5086.js +1 -1
  139. package/dist/5086.js.map +1 -1
  140. package/dist/5093.js +1 -0
  141. package/dist/5093.js.map +1 -0
  142. package/dist/5097.js +1 -0
  143. package/dist/5097.js.map +1 -0
  144. package/dist/510.js +1 -0
  145. package/dist/510.js.map +1 -0
  146. package/dist/5117.js +1 -0
  147. package/dist/5117.js.map +1 -0
  148. package/dist/5279.js +1 -0
  149. package/dist/5279.js.map +1 -0
  150. package/dist/5434.js +1 -0
  151. package/dist/5434.js.map +1 -0
  152. package/dist/5514.js +1 -0
  153. package/dist/5514.js.map +1 -0
  154. package/dist/5568.js +1 -0
  155. package/dist/5568.js.map +1 -0
  156. package/dist/5576.js +1 -1
  157. package/dist/5576.js.map +1 -1
  158. package/dist/5630.js +1 -0
  159. package/dist/5630.js.map +1 -0
  160. package/dist/5676.js +1 -1
  161. package/dist/5676.js.map +1 -1
  162. package/dist/5695.js +1 -0
  163. package/dist/5695.js.map +1 -0
  164. package/dist/5697.js +1 -1
  165. package/dist/5697.js.map +1 -1
  166. package/dist/5728.js +1 -0
  167. package/dist/5728.js.map +1 -0
  168. package/dist/5809.js +1 -1
  169. package/dist/5809.js.map +1 -1
  170. package/dist/585.js +1 -0
  171. package/dist/585.js.map +1 -0
  172. package/dist/5887.js +1 -0
  173. package/dist/5887.js.map +1 -0
  174. package/dist/5958.js +1 -0
  175. package/dist/5958.js.map +1 -0
  176. package/dist/5964.js +1 -0
  177. package/dist/5964.js.map +1 -0
  178. package/dist/6008.js +1 -0
  179. package/dist/602.js +1 -0
  180. package/dist/602.js.map +1 -0
  181. package/dist/6020.js +1 -0
  182. package/dist/6020.js.map +1 -0
  183. package/dist/6161.js +1 -0
  184. package/dist/6161.js.map +1 -0
  185. package/dist/6273.js +1 -0
  186. package/dist/6273.js.map +1 -0
  187. package/dist/6337.js +1 -0
  188. package/dist/6337.js.map +1 -0
  189. package/dist/6427.js +1 -1
  190. package/dist/6427.js.map +1 -1
  191. package/dist/6429.js +1 -0
  192. package/dist/6429.js.map +1 -0
  193. package/dist/6478.js +7 -0
  194. package/dist/6478.js.map +1 -0
  195. package/dist/6508.js +1 -0
  196. package/dist/6508.js.map +1 -0
  197. package/dist/6634.js +1 -0
  198. package/dist/6634.js.map +1 -0
  199. package/dist/6767.js +1 -0
  200. package/dist/6767.js.map +1 -0
  201. package/dist/6783.js +1 -0
  202. package/dist/6783.js.map +1 -0
  203. package/dist/6868.js +1 -1
  204. package/dist/6868.js.map +1 -1
  205. package/dist/688.js +1 -0
  206. package/dist/688.js.map +1 -0
  207. package/dist/689.js +1 -1
  208. package/dist/689.js.map +1 -1
  209. package/dist/694.js +1 -0
  210. package/dist/694.js.map +1 -0
  211. package/dist/6987.js +1 -0
  212. package/dist/6987.js.map +1 -0
  213. package/dist/7061.js +1 -0
  214. package/dist/7061.js.map +1 -0
  215. package/dist/7078.js +1 -0
  216. package/dist/7078.js.map +1 -0
  217. package/dist/710.js +1 -0
  218. package/dist/710.js.map +1 -0
  219. package/dist/7128.js +1 -0
  220. package/dist/7128.js.map +1 -0
  221. package/dist/7209.js +1 -0
  222. package/dist/7209.js.map +1 -0
  223. package/dist/7424.js +1 -0
  224. package/dist/7424.js.map +1 -0
  225. package/dist/770.js +1 -0
  226. package/dist/770.js.map +1 -0
  227. package/dist/7707.js +1 -0
  228. package/dist/7707.js.map +1 -0
  229. package/dist/7784.js +1 -0
  230. package/dist/7784.js.map +1 -0
  231. package/dist/781.js +1 -1
  232. package/dist/781.js.map +1 -1
  233. package/dist/7824.js +1 -0
  234. package/dist/7824.js.map +1 -0
  235. package/dist/7832.js +1 -0
  236. package/dist/7832.js.map +1 -0
  237. package/dist/8178.js +1 -0
  238. package/dist/8178.js.map +1 -0
  239. package/dist/820.js +1 -0
  240. package/dist/820.js.map +1 -0
  241. package/dist/8224.js +1 -0
  242. package/dist/8224.js.map +1 -0
  243. package/dist/8225.js +1 -0
  244. package/dist/8225.js.map +1 -0
  245. package/dist/8240.js +1 -1
  246. package/dist/8240.js.map +1 -1
  247. package/dist/8258.js +1 -0
  248. package/dist/8258.js.map +1 -0
  249. package/dist/8702.js +1 -0
  250. package/dist/8702.js.map +1 -0
  251. package/dist/8725.js +1 -0
  252. package/dist/8725.js.map +1 -0
  253. package/dist/8762.js +1 -0
  254. package/dist/8762.js.map +1 -0
  255. package/dist/8763.js +1 -0
  256. package/dist/8763.js.map +1 -0
  257. package/dist/8815.js +1 -0
  258. package/dist/8815.js.map +1 -0
  259. package/dist/8882.js +1 -0
  260. package/dist/8882.js.map +1 -0
  261. package/dist/8924.js +1 -1
  262. package/dist/8924.js.map +1 -1
  263. package/dist/8937.js +1 -0
  264. package/dist/8937.js.map +1 -0
  265. package/dist/9.js +1 -1
  266. package/dist/9.js.map +1 -1
  267. package/dist/9061.js +1 -0
  268. package/dist/9061.js.map +1 -0
  269. package/dist/9087.js +1 -0
  270. package/dist/9087.js.map +1 -0
  271. package/dist/9301.js +1 -0
  272. package/dist/9301.js.map +1 -0
  273. package/dist/9324.js +1 -0
  274. package/dist/9324.js.map +1 -0
  275. package/dist/9497.js +1 -0
  276. package/dist/9497.js.map +1 -0
  277. package/dist/9520.js +1 -1
  278. package/dist/9520.js.map +1 -1
  279. package/dist/9526.js +1 -0
  280. package/dist/9526.js.map +1 -0
  281. package/dist/9621.js +1 -0
  282. package/dist/9621.js.map +1 -0
  283. package/dist/9676.js +17 -0
  284. package/dist/9676.js.map +1 -0
  285. package/dist/977.js +1 -0
  286. package/dist/977.js.map +1 -0
  287. package/dist/9771.js +1 -0
  288. package/dist/9771.js.map +1 -0
  289. package/dist/9806.js +1 -0
  290. package/dist/9806.js.map +1 -0
  291. package/dist/989.js +1 -0
  292. package/dist/989.js.map +1 -0
  293. package/dist/kenyaemr-esm-express-workflow-app.js +6 -5
  294. package/dist/kenyaemr-esm-express-workflow-app.js.buildmanifest.json +1407 -809
  295. package/dist/kenyaemr-esm-express-workflow-app.js.map +1 -1
  296. package/dist/main.js +22 -5
  297. package/dist/main.js.map +1 -1
  298. package/dist/routes.json +1 -1
  299. package/package.json +4 -6
  300. package/src/components/admissions/admissions-dashboard.component.tsx +2 -2
  301. package/src/components/anaesthetic/anaesthetic-dashboard.meta.ts +8 -0
  302. package/src/components/anaesthetic/anaesthetic-data-form.component.tsx +442 -0
  303. package/src/components/anaesthetic/anaesthetic-data-form.scss +278 -0
  304. package/src/components/anaesthetic/anaesthetic-link.component.tsx +21 -0
  305. package/src/components/anaesthetic/anaesthetic.component.tsx +618 -0
  306. package/src/components/anaesthetic/anaesthetic.resource.ts +1503 -0
  307. package/src/components/anaesthetic/anaesthetic.scss +1885 -0
  308. package/src/components/anaesthetic/forms/anaesthetic-form.component.tsx +304 -0
  309. package/src/components/anaesthetic/forms/anaesthetic-record-form.component.tsx +707 -0
  310. package/src/components/anaesthetic/forms/icd11-diagnosis-search.component.tsx +178 -0
  311. package/src/components/anaesthetic/forms/icd11-diagnosis-search.scss +126 -0
  312. package/src/components/anaesthetic/forms/index.ts +2 -0
  313. package/src/components/anaesthetic/forms/interoperative-record-drug-given-form.component.tsx +231 -0
  314. package/src/components/anaesthetic/forms/post-operative-summary-form.component.tsx +171 -0
  315. package/src/components/anaesthetic/forms/time-picker-dropdown.component.tsx +202 -0
  316. package/src/components/anaesthetic/forms/time-picker-dropdown.scss +107 -0
  317. package/src/components/anaesthetic/forms/time-picker-with-clock.component.tsx +174 -0
  318. package/src/components/anaesthetic/forms/time-picker-with-clock.scss +178 -0
  319. package/src/components/anaesthetic/forms/useAnaestheticData.ts +16 -0
  320. package/src/components/anaesthetic/graphs/anaesthetic-graph-wrapper.component.tsx +266 -0
  321. package/src/components/anaesthetic/graphs/anaesthetic-graph.component.tsx +185 -0
  322. package/src/components/anaesthetic/graphs/index.ts +2 -0
  323. package/src/components/anaesthetic/graphs/interoperative-record-drug-given-graph-wrapper.component.tsx +197 -0
  324. package/src/components/anaesthetic/graphs/interoperative-record-drug-given-graph.component.tsx +93 -0
  325. package/src/components/anaesthetic/resources/anaesthetic-amniotic-fluid.resource.ts +277 -0
  326. package/src/components/anaesthetic/resources/anaesthetic-form.resource.ts +716 -0
  327. package/src/components/anaesthetic/resources/anaesthetic.resource.ts +378 -0
  328. package/src/components/anaesthetic/types/index.ts +1349 -0
  329. package/src/components/consultation/clinical-encounter/clinical-encounter.component.tsx +4 -20
  330. package/src/components/consultation/clinical-encounter/encounter-details.component.tsx +9 -9
  331. package/src/components/consultation/clinical-encounter/encounter-details.test.tsx +19 -18
  332. package/src/components/consultation/consultation.utils.tsx +1 -1
  333. package/src/components/consultation/dashboard.component.tsx +0 -2
  334. package/src/components/consultation/index.ts +1 -1
  335. package/src/components/consultation/tabs/index.ts +67 -0
  336. package/src/components/facility-dashboard/components/header/home-header.component.tsx +8 -13
  337. package/src/components/laboratory/index.ts +11 -0
  338. package/src/components/laboratory/lab-table.component.tsx +46 -12
  339. package/src/components/laboratory/laboratory-tabs.component.tsx +3 -17
  340. package/src/components/mch/dashboard.component.tsx +0 -2
  341. package/src/components/mch/mch.component.tsx +1 -3
  342. package/src/components/pharmacy/index.ts +1 -1
  343. package/src/components/pharmacy/orders/pharmacy-orders.component.tsx +44 -6
  344. package/src/components/pharmacy/orders/pharmacy-orders.test.tsx +8 -7
  345. package/src/components/pharmacy/pharmacy-tabs.component.tsx +4 -20
  346. package/src/components/pharmacy/tabs/index.ts +21 -0
  347. package/src/components/preauth/index.ts +22 -0
  348. package/src/components/preauth/preauth-dashboard.component.tsx +20 -0
  349. package/src/components/procedures/index.ts +16 -0
  350. package/src/components/procedures/procedure-queues/index.ts +13 -0
  351. package/src/components/procedures/procedure-queues/procedure-form-extras.component.tsx +33 -0
  352. package/src/components/procedures/procedure-queues/procedure-form-extras.scss +5 -0
  353. package/src/components/procedures/procedure-queues/procedure-queues.component.tsx +35 -0
  354. package/src/components/procedures/procedure-queues/procedure-queues.resources.ts +37 -0
  355. package/src/components/procedures/procedure-queues/procedure-room-tabs.component.tsx +80 -0
  356. package/src/components/procedures/procedure-queues/procedure-rooms.scss +13 -0
  357. package/src/components/procedures/procedure-queues/queue-procedure-tabs.component.tsx +34 -0
  358. package/src/components/procedures/procedure-queues/summary-cards.component.tsx +81 -0
  359. package/src/components/procedures/procedure-queues/summary-cards.scss +35 -0
  360. package/src/components/procedures/procedures-table.component.tsx +77 -19
  361. package/src/components/procedures/procedures-tabs.component.test.tsx +57 -0
  362. package/src/components/procedures/procedures-tabs.component.tsx +3 -18
  363. package/src/components/radiology-and-imaging/index.ts +11 -0
  364. package/src/components/radiology-and-imaging/radiology-and-imaging-table.component.tsx +73 -21
  365. package/src/components/radiology-and-imaging/radiology-and-imaging.component.tsx +3 -19
  366. package/src/components/registration/card/HIE-card/hie-card.component.tsx +32 -44
  367. package/src/components/registration/card/Local-card/local-card.component.tsx +22 -24
  368. package/src/components/registration/checkin-form-extra/checkin-form-extra.extension.tsx +8 -2
  369. package/src/components/registration/checkin-form-extra/queue-fields.component.tsx +18 -19
  370. package/src/components/registration/dependants/dependants.component.tsx +37 -60
  371. package/src/components/registration/dependants/dependants.resource.ts +75 -46
  372. package/src/components/registration/end-visit-modal/end-visit-dialog.modal.tsx +320 -0
  373. package/src/components/registration/end-visit-modal/end-visit-dialog.scss +12 -0
  374. package/src/components/registration/end-visit-modal/end-visit.resource.tsx +59 -0
  375. package/src/components/registration/end-visit-modal/sha-end-visit.resource.ts +285 -0
  376. package/src/components/registration/search-bar/search-bar.resource.ts +32 -93
  377. package/src/components/registration/start-visit-form/hooks/useDefaultFacilityLocation.tsx +15 -0
  378. package/src/components/registration/start-visit-form/hooks/useDefaultVisitLocation.tsx +24 -0
  379. package/src/components/registration/start-visit-form/hooks/useOfflineVisitType.tsx +18 -0
  380. package/src/components/registration/start-visit-form/hooks/useRecommendedVisitTypes.tsx +36 -0
  381. package/src/components/registration/start-visit-form/hooks/useVisitAttributeType.tsx +102 -0
  382. package/src/components/registration/start-visit-form/overflow-menu-extension/custom-end-active-visit.extension.tsx +44 -0
  383. package/src/components/registration/start-visit-form/overflow-menu-extension/overflow-menu-item.extension.tsx +67 -0
  384. package/src/components/registration/start-visit-form/overflow-menu-extension/overflow-menu-item.scss +3 -0
  385. package/src/components/registration/start-visit-form/start-visit-workspace/base-visit-type.component.tsx +126 -0
  386. package/src/components/registration/start-visit-form/start-visit-workspace/base-visit-type.scss +75 -0
  387. package/src/components/registration/start-visit-form/start-visit-workspace/exported-visit-form.workspace.tsx +778 -0
  388. package/src/components/registration/start-visit-form/start-visit-workspace/location-selector.component.tsx +86 -0
  389. package/src/components/registration/start-visit-form/start-visit-workspace/recommended-visit-type.component.tsx +32 -0
  390. package/src/components/registration/start-visit-form/start-visit-workspace/visit-attribute-type.component.tsx +257 -0
  391. package/src/components/registration/start-visit-form/start-visit-workspace/visit-attribute-type.scss +5 -0
  392. package/src/components/registration/start-visit-form/start-visit-workspace/visit-date-time.component.tsx +193 -0
  393. package/src/components/registration/start-visit-form/start-visit-workspace/visit-form.resource.ts +390 -0
  394. package/src/components/registration/start-visit-form/start-visit-workspace/visit-form.scss +144 -0
  395. package/src/components/registration/start-visit-form/visit-form-workspace/visit-form.workspace.tsx +48 -0
  396. package/src/components/registration/type/index.ts +101 -0
  397. package/src/components/reports/index.ts +1 -0
  398. package/src/components/triage/dashboard.component.tsx +0 -2
  399. package/src/config-schema.ts +476 -0
  400. package/src/hooks/useOrders.tsx +2 -2
  401. package/src/hooks/useServiceQueues.tsx +1 -1
  402. package/src/index.ts +81 -15
  403. package/src/routes.json +298 -32
  404. package/src/shared/dashboard-link/dashboard-link.component.tsx +11 -8
  405. package/src/shared/orders/OrderTable.scss +7 -0
  406. package/src/shared/orders/OrderTable.tsx +68 -8
  407. package/src/shared/orders/print-order/print-order.component.tsx +158 -0
  408. package/src/shared/orders/print-order/print-order.scss +225 -0
  409. package/src/shared/orders/print-prescription/print-prescription.component.tsx +65 -0
  410. package/src/shared/orders/print-prescription/print-prescription.resource.ts +45 -0
  411. package/src/shared/orders/print-prescription/print-prescription.scss +25 -0
  412. package/src/shared/otp-verification/index.ts +112 -29
  413. package/src/shared/otp-verification/otp-verification.modal.tsx +1110 -122
  414. package/src/shared/otp-verification/otp-verification.scss +374 -0
  415. package/src/shared/patient-chart/patient-summary-dashboard/patient-summary-dashboard.component.tsx +5 -84
  416. package/src/shared/pin-put/pinput.component.test.tsx +7 -6
  417. package/src/shared/tabs/create-tab-extension.tsx +33 -0
  418. package/src/shared/tabs/extension-tabs.component.tsx +51 -33
  419. package/src/shared/utils/index.ts +140 -5
  420. package/src/types/index.ts +12 -0
  421. package/translations/am.json +443 -131
  422. package/translations/en.json +327 -15
  423. package/translations/fr.json +372 -63
  424. package/translations/sw.json +347 -35
  425. package/tsconfig.json +1 -0
  426. package/dist/1049.js +0 -1
  427. package/dist/1049.js.map +0 -1
  428. package/dist/1072.js +0 -1
  429. package/dist/1072.js.map +0 -1
  430. package/dist/1091.js +0 -1
  431. package/dist/1091.js.map +0 -1
  432. package/dist/1172.js +0 -1
  433. package/dist/1172.js.map +0 -1
  434. package/dist/132.js +0 -1
  435. package/dist/132.js.map +0 -1
  436. package/dist/1354.js +0 -1
  437. package/dist/1354.js.map +0 -1
  438. package/dist/1704.js +0 -1
  439. package/dist/1704.js.map +0 -1
  440. package/dist/1729.js +0 -17
  441. package/dist/1729.js.map +0 -1
  442. package/dist/1757.js +0 -1
  443. package/dist/1757.js.map +0 -1
  444. package/dist/1761.js +0 -1
  445. package/dist/1761.js.map +0 -1
  446. package/dist/1809.js +0 -7
  447. package/dist/1809.js.map +0 -1
  448. package/dist/1842.js +0 -1
  449. package/dist/1874.js +0 -1
  450. package/dist/1874.js.map +0 -1
  451. package/dist/1962.js +0 -1
  452. package/dist/1962.js.map +0 -1
  453. package/dist/2007.js +0 -1
  454. package/dist/2007.js.map +0 -1
  455. package/dist/2024.js +0 -1
  456. package/dist/2024.js.map +0 -1
  457. package/dist/2045.js +0 -1
  458. package/dist/2045.js.map +0 -1
  459. package/dist/2163.js +0 -1
  460. package/dist/2163.js.map +0 -1
  461. package/dist/2191.js +0 -1
  462. package/dist/2191.js.map +0 -1
  463. package/dist/2267.js +0 -1
  464. package/dist/2267.js.map +0 -1
  465. package/dist/231.js +0 -1
  466. package/dist/231.js.map +0 -1
  467. package/dist/236.js +0 -1
  468. package/dist/236.js.map +0 -1
  469. package/dist/2367.js +0 -1
  470. package/dist/2367.js.map +0 -1
  471. package/dist/2463.js +0 -1
  472. package/dist/2463.js.map +0 -1
  473. package/dist/2561.js +0 -1
  474. package/dist/2561.js.map +0 -1
  475. package/dist/2810.js +0 -2
  476. package/dist/2810.js.map +0 -1
  477. package/dist/2867.js +0 -1
  478. package/dist/2867.js.map +0 -1
  479. package/dist/2909.js +0 -1
  480. package/dist/2909.js.map +0 -1
  481. package/dist/2949.js +0 -1
  482. package/dist/2949.js.map +0 -1
  483. package/dist/3040.js +0 -1
  484. package/dist/3119.js +0 -1
  485. package/dist/3119.js.map +0 -1
  486. package/dist/3215.js +0 -1
  487. package/dist/3215.js.map +0 -1
  488. package/dist/322.js +0 -1
  489. package/dist/322.js.map +0 -1
  490. package/dist/3228.js +0 -1
  491. package/dist/3228.js.map +0 -1
  492. package/dist/330.js +0 -1
  493. package/dist/330.js.map +0 -1
  494. package/dist/3472.js +0 -1
  495. package/dist/3472.js.map +0 -1
  496. package/dist/351.js +0 -1
  497. package/dist/351.js.map +0 -1
  498. package/dist/3576.js +0 -1
  499. package/dist/3576.js.map +0 -1
  500. package/dist/397.js +0 -1
  501. package/dist/397.js.map +0 -1
  502. package/dist/4007.js +0 -66
  503. package/dist/4007.js.map +0 -1
  504. package/dist/4200.js +0 -1
  505. package/dist/4200.js.map +0 -1
  506. package/dist/4224.js +0 -1
  507. package/dist/4224.js.map +0 -1
  508. package/dist/43.js +0 -1
  509. package/dist/43.js.map +0 -1
  510. package/dist/4308.js +0 -1
  511. package/dist/4308.js.map +0 -1
  512. package/dist/4399.js +0 -1
  513. package/dist/4399.js.map +0 -1
  514. package/dist/4505.js +0 -1
  515. package/dist/4505.js.map +0 -1
  516. package/dist/4724.js +0 -1
  517. package/dist/4724.js.map +0 -1
  518. package/dist/498.js +0 -1
  519. package/dist/498.js.map +0 -1
  520. package/dist/509.js +0 -1
  521. package/dist/509.js.map +0 -1
  522. package/dist/5096.js +0 -1
  523. package/dist/5096.js.map +0 -1
  524. package/dist/5159.js +0 -13
  525. package/dist/5159.js.map +0 -1
  526. package/dist/5184.js +0 -1
  527. package/dist/5184.js.map +0 -1
  528. package/dist/5270.js +0 -1
  529. package/dist/5270.js.map +0 -1
  530. package/dist/5361.js +0 -1
  531. package/dist/5361.js.map +0 -1
  532. package/dist/5537.js +0 -1
  533. package/dist/5537.js.map +0 -1
  534. package/dist/566.js +0 -1
  535. package/dist/566.js.map +0 -1
  536. package/dist/5733.js +0 -1
  537. package/dist/5733.js.map +0 -1
  538. package/dist/5854.js +0 -1
  539. package/dist/5854.js.map +0 -1
  540. package/dist/5882.js +0 -1
  541. package/dist/6004.js +0 -1
  542. package/dist/6004.js.map +0 -1
  543. package/dist/6121.js +0 -3
  544. package/dist/6121.js.map +0 -1
  545. package/dist/6137.js +0 -1
  546. package/dist/6137.js.map +0 -1
  547. package/dist/6356.js +0 -1
  548. package/dist/6356.js.map +0 -1
  549. package/dist/6571.js +0 -1
  550. package/dist/6571.js.map +0 -1
  551. package/dist/6721.js +0 -1
  552. package/dist/6721.js.map +0 -1
  553. package/dist/6858.js +0 -1
  554. package/dist/6858.js.map +0 -1
  555. package/dist/6925.js +0 -1
  556. package/dist/6925.js.map +0 -1
  557. package/dist/6960.js +0 -1
  558. package/dist/6960.js.map +0 -1
  559. package/dist/7085.js +0 -1
  560. package/dist/7085.js.map +0 -1
  561. package/dist/7127.js +0 -1
  562. package/dist/7176.js +0 -1
  563. package/dist/7176.js.map +0 -1
  564. package/dist/7237.js +0 -1
  565. package/dist/7237.js.map +0 -1
  566. package/dist/725.js +0 -1
  567. package/dist/725.js.map +0 -1
  568. package/dist/7288.js +0 -1
  569. package/dist/7329.js +0 -1
  570. package/dist/7329.js.map +0 -1
  571. package/dist/7334.js +0 -1
  572. package/dist/7334.js.map +0 -1
  573. package/dist/7461.js +0 -1
  574. package/dist/7461.js.map +0 -1
  575. package/dist/7517.js +0 -1
  576. package/dist/7517.js.map +0 -1
  577. package/dist/7837.js +0 -1
  578. package/dist/7837.js.map +0 -1
  579. package/dist/8103.js +0 -1
  580. package/dist/8103.js.map +0 -1
  581. package/dist/8110.js +0 -1
  582. package/dist/8110.js.map +0 -1
  583. package/dist/8179.js +0 -6
  584. package/dist/8179.js.map +0 -1
  585. package/dist/8189.js +0 -1
  586. package/dist/8189.js.map +0 -1
  587. package/dist/8209.js +0 -1
  588. package/dist/8209.js.map +0 -1
  589. package/dist/8249.js +0 -1
  590. package/dist/8249.js.map +0 -1
  591. package/dist/8285.js +0 -1
  592. package/dist/8285.js.map +0 -1
  593. package/dist/8470.js +0 -1
  594. package/dist/8470.js.map +0 -1
  595. package/dist/8502.js +0 -1
  596. package/dist/8502.js.map +0 -1
  597. package/dist/866.js +0 -1
  598. package/dist/866.js.map +0 -1
  599. package/dist/8889.js +0 -11
  600. package/dist/8889.js.map +0 -1
  601. package/dist/8990.js +0 -1
  602. package/dist/8990.js.map +0 -1
  603. package/dist/8994.js +0 -1
  604. package/dist/8994.js.map +0 -1
  605. package/dist/9049.js +0 -1
  606. package/dist/9049.js.map +0 -1
  607. package/dist/9054.js +0 -1
  608. package/dist/9054.js.map +0 -1
  609. package/dist/916.js +0 -1
  610. package/dist/9231.js +0 -1
  611. package/dist/9231.js.map +0 -1
  612. package/dist/9408.js +0 -1
  613. package/dist/9408.js.map +0 -1
  614. package/dist/9425.js +0 -1
  615. package/dist/9466.js +0 -1
  616. package/dist/9466.js.map +0 -1
  617. package/dist/9919.js +0 -1
  618. package/dist/9919.js.map +0 -1
  619. package/dist/9931.js +0 -1
  620. package/dist/9931.js.map +0 -1
  621. package/jest.config.js +0 -3
  622. package/src/shared/orders/OrdersTabs.tsx +0 -58
  623. package/src/shared/patient-chart/patient-chart.component.tsx +0 -61
  624. package/src/shared/patient-chart/patient-chart.resources.ts +0 -180
  625. package/src/shared/patient-chart/patient-chart.scss +0 -15
  626. package/src/shared/patient-chart/useInitialize.ts +0 -24
  627. /package/src/shared/{patient-chart/patient-summary-dashboard → tabs}/patient-summary-dashboard.scss +0 -0
@@ -0,0 +1,778 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import classNames from 'classnames';
3
+ import { Controller, FormProvider, useForm, useWatch } from 'react-hook-form';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { useSWRConfig } from 'swr';
6
+ import {
7
+ Button,
8
+ ButtonSet,
9
+ ContentSwitcher,
10
+ Form,
11
+ FormGroup,
12
+ InlineLoading,
13
+ InlineNotification,
14
+ RadioButton,
15
+ RadioButtonGroup,
16
+ Row,
17
+ Stack,
18
+ Switch,
19
+ } from '@carbon/react';
20
+ import { zodResolver } from '@hookform/resolvers/zod';
21
+ import {
22
+ Extension,
23
+ ExtensionSlot,
24
+ OpenmrsFetchError,
25
+ saveVisit,
26
+ showSnackbar,
27
+ updateVisit,
28
+ useConfig,
29
+ useConnectivity,
30
+ useEmrConfiguration,
31
+ useFeatureFlag,
32
+ useLayoutType,
33
+ useVisit,
34
+ Workspace2,
35
+ type AssignedExtension,
36
+ type NewVisitPayload,
37
+ type Visit,
38
+ type Workspace2DefinitionProps,
39
+ } from '@openmrs/esm-framework';
40
+ import {
41
+ createOfflineVisitForPatient,
42
+ invalidateCurrentVisit,
43
+ invalidateVisitAndEncounterData,
44
+ useActivePatientEnrollment,
45
+ } from '@openmrs/esm-patient-common-lib';
46
+ import { MemoizedRecommendedVisitType } from './recommended-visit-type.component';
47
+ import {
48
+ convertToDate,
49
+ createVisitAttribute,
50
+ deleteVisitAttribute,
51
+ extractErrorMessagesFromResponse,
52
+ updateVisitAttribute,
53
+ useAllowOverlappingVisits,
54
+ useConditionalVisitTypes,
55
+ useEarliestAllowedVisitStartDate,
56
+ useVisitFormCallbacks,
57
+ useVisitFormSchemaAndDefaultValues,
58
+ visitStatuses,
59
+ type ErrorObject,
60
+ type VisitFormCallbacks,
61
+ type VisitFormData,
62
+ } from './visit-form.resource';
63
+ import { useVisitAttributeTypes } from '../hooks/useVisitAttributeType';
64
+ import BaseVisitType from './base-visit-type.component';
65
+ import LocationSelector from './location-selector.component';
66
+ import VisitAttributeTypeFields from './visit-attribute-type.component';
67
+ import VisitDateTimeSection from './visit-date-time.component';
68
+ import styles from './visit-form.scss';
69
+ import { ExpressWorkflowConfig } from '../../../../config-schema';
70
+
71
+ interface VisitAttribute {
72
+ attributeType: string;
73
+ value: string;
74
+ }
75
+
76
+ export interface ExtraVisitInfo {
77
+ handleCreateExtraVisitInfo?: () => void | Promise<void>;
78
+ attributes?: Array<VisitAttribute>;
79
+ }
80
+
81
+ export interface ExportedVisitFormProps {
82
+ openedFrom: string;
83
+ showPatientHeader?: boolean;
84
+ onVisitStarted?: (visit: Visit) => void;
85
+ patient: fhir.Patient;
86
+ patientUuid: string;
87
+ visitContext: Visit | null;
88
+ }
89
+
90
+ interface VisitAttributeResource {
91
+ attributeType: { uuid: string; display: string };
92
+ uuid: string;
93
+ value: unknown;
94
+ }
95
+
96
+ const ExportedVisitForm: React.FC<Workspace2DefinitionProps<ExportedVisitFormProps, {}, {}>> = ({
97
+ closeWorkspace,
98
+ workspaceProps,
99
+ }) => {
100
+ const {
101
+ openedFrom = '',
102
+ showPatientHeader = false,
103
+ onVisitStarted,
104
+ patient,
105
+ patientUuid = '',
106
+ visitContext: visitToEdit = null,
107
+ } = workspaceProps ?? {};
108
+
109
+ const { t } = useTranslation();
110
+ const isTablet = useLayoutType() === 'tablet';
111
+ const isOnline = useConnectivity();
112
+ const config = useConfig<ExpressWorkflowConfig>();
113
+ const { emrConfiguration } = useEmrConfiguration();
114
+ const [visitTypeContentSwitcherIndex, setVisitTypeContentSwitcherIndex] = useState(
115
+ config?.showRecommendedVisitTypeTab ? 0 : 1,
116
+ );
117
+ const visitHeaderSlotState = useMemo(() => ({ patientUuid, patient }), [patientUuid, patient]);
118
+ const { activePatientEnrollment, isLoading } = useActivePatientEnrollment(patientUuid);
119
+ const { activeVisit, isLoading: isLoadingVisit } = useVisit(patientUuid);
120
+ const { allowOverlappingVisits, isLoading: isLoadingOverlapSetting } = useAllowOverlappingVisits();
121
+ const { mutate: globalMutate } = useSWRConfig();
122
+ const allVisitTypes = useConditionalVisitTypes();
123
+ const { earliestAllowedStartDate, isLoading: isLoadingBirthdateCheck } =
124
+ useEarliestAllowedVisitStartDate(patientUuid);
125
+ const hieFeatureFlags = useFeatureFlag('healthInformationExchange');
126
+
127
+ const [errorFetchingResources, setErrorFetchingResources] = useState<{
128
+ blockSavingForm: boolean;
129
+ } | null>(null);
130
+
131
+ const [isAwaitingOtp, setIsAwaitingOtp] = useState(false);
132
+
133
+ const setErrorFetchingResourcesAdapter = useCallback((action: React.SetStateAction<{ blockSavingForm: boolean }>) => {
134
+ setErrorFetchingResources((prev) => {
135
+ const prevNonNull = prev ?? { blockSavingForm: false };
136
+ return typeof action === 'function' ? action(prevNonNull) : action;
137
+ });
138
+ }, []) as React.Dispatch<React.SetStateAction<{ blockSavingForm: boolean }>>;
139
+
140
+ const { visitAttributeTypes } = useVisitAttributeTypes();
141
+ const [visitFormCallbacks, setVisitFormCallbacks] = useVisitFormCallbacks();
142
+ const [extraVisitInfo, setExtraVisitInfo] = useState<ExtraVisitInfo | null>(null);
143
+
144
+ const { visitFormSchema, defaultValues, firstEncounterDateTime, lastEncounterDateTime } =
145
+ useVisitFormSchemaAndDefaultValues(visitToEdit ?? undefined, earliestAllowedStartDate);
146
+
147
+ const methods = useForm<VisitFormData>({
148
+ mode: 'all',
149
+ resolver: zodResolver(visitFormSchema),
150
+ defaultValues,
151
+ });
152
+
153
+ const {
154
+ handleSubmit,
155
+ control,
156
+ getValues,
157
+ formState: { errors, isDirty, isSubmitting },
158
+ reset,
159
+ } = methods;
160
+
161
+ const visitStatus = useWatch({ control, name: 'visitStatus' });
162
+ const visitType = useWatch({ control, name: 'visitType' });
163
+ const hasActiveVisitConflict = !visitToEdit && visitStatus !== 'past' && !!activeVisit && !allowOverlappingVisits;
164
+
165
+ const isSHAVisit = useMemo(
166
+ () => [...visitFormCallbacks.values()].some((cb) => cb.isSHAVisit === true),
167
+ [visitFormCallbacks],
168
+ );
169
+
170
+ const isElectiveNotApproved = useMemo(
171
+ () => [...visitFormCallbacks.values()].some((cb) => cb.isElectiveNotApproved === true),
172
+ [visitFormCallbacks],
173
+ );
174
+ const isCoverageExhausted = useMemo(
175
+ () => [...visitFormCallbacks.values()].some((cb) => cb.isCoverageExhausted === true),
176
+ [visitFormCallbacks],
177
+ );
178
+
179
+ useEffect(() => {
180
+ reset(defaultValues, {
181
+ keepDirty: true,
182
+ keepDirtyValues: true,
183
+ keepErrors: true,
184
+ keepTouched: true,
185
+ });
186
+ }, [defaultValues, reset]);
187
+
188
+ const getErrorDescription = useCallback(
189
+ (error: unknown) => {
190
+ if (OpenmrsFetchError && error instanceof OpenmrsFetchError) {
191
+ return typeof error.responseBody === 'string'
192
+ ? error.responseBody
193
+ : extractErrorMessagesFromResponse(error.responseBody as ErrorObject, t);
194
+ }
195
+ return (error as Error)?.message;
196
+ },
197
+ [t],
198
+ );
199
+
200
+ const handleVisitAttributes = useCallback(
201
+ (visitAttributes: { [p: string]: string }, visitUuid: string) => {
202
+ const existingVisitAttributeTypes =
203
+ visitToEdit?.attributes?.map((attribute) => attribute.attributeType.uuid) || [];
204
+ const promises: Array<Promise<unknown>> = [];
205
+
206
+ for (const [attributeType, value] of Object.entries(visitAttributes)) {
207
+ if (attributeType && existingVisitAttributeTypes.includes(attributeType)) {
208
+ const attributeToEdit = (visitToEdit?.attributes as Array<VisitAttributeResource> | undefined)?.find(
209
+ (attr) => attr.attributeType.uuid === attributeType,
210
+ );
211
+ if (attributeToEdit) {
212
+ const isSameValue =
213
+ typeof attributeToEdit.value === 'object' &&
214
+ attributeToEdit.value !== null &&
215
+ 'uuid' in (attributeToEdit.value as object)
216
+ ? (attributeToEdit.value as { uuid: string }).uuid === value
217
+ : attributeToEdit.value === value;
218
+ if (isSameValue) {
219
+ continue;
220
+ }
221
+ if (value) {
222
+ promises.push(
223
+ updateVisitAttribute(visitUuid, attributeToEdit.uuid, value).catch((error) => {
224
+ showSnackbar({
225
+ title: t('errorUpdatingVisitAttribute', 'Error updating the {{attributeName}} visit attribute', {
226
+ attributeName: attributeToEdit.attributeType.display,
227
+ }),
228
+ kind: 'error',
229
+ isLowContrast: false,
230
+ subtitle: getErrorDescription(error),
231
+ });
232
+ return Promise.reject(error);
233
+ }),
234
+ );
235
+ } else {
236
+ promises.push(
237
+ deleteVisitAttribute(visitUuid, attributeToEdit.uuid).catch((error) => {
238
+ showSnackbar({
239
+ title: t('errorDeletingVisitAttribute', 'Error deleting the {{attributeName}} visit attribute', {
240
+ attributeName: attributeToEdit.attributeType.display,
241
+ }),
242
+ kind: 'error',
243
+ isLowContrast: false,
244
+ subtitle: getErrorDescription(error),
245
+ });
246
+ return Promise.reject(error);
247
+ }),
248
+ );
249
+ }
250
+ }
251
+ } else {
252
+ if (value) {
253
+ promises.push(
254
+ createVisitAttribute(visitUuid, attributeType, value).catch((error) => {
255
+ showSnackbar({
256
+ title: t('errorCreatingVisitAttribute', 'Error creating the {{attributeName}} visit attribute', {
257
+ attributeName: visitAttributeTypes?.find((type) => type.uuid === attributeType)?.display,
258
+ }),
259
+ kind: 'error',
260
+ isLowContrast: false,
261
+ subtitle: getErrorDescription(error),
262
+ });
263
+ return Promise.reject(error);
264
+ }),
265
+ );
266
+ }
267
+ }
268
+ }
269
+ return Promise.all(promises);
270
+ },
271
+ [getErrorDescription, visitToEdit, t, visitAttributeTypes],
272
+ );
273
+ const onSubmit = useCallback(
274
+ async (data: VisitFormData) => {
275
+ if (isCoverageExhausted) {
276
+ showSnackbar({
277
+ title: t('coverageExhausted', 'Coverage exhausted'),
278
+ subtitle: t(
279
+ 'cannotStartVisitCoverageExhausted',
280
+ 'One or more selected interventions have exhausted their coverage limit. Remove them to proceed.',
281
+ ),
282
+ kind: 'error',
283
+ isLowContrast: false,
284
+ });
285
+ return;
286
+ }
287
+
288
+ const {
289
+ visitStatus,
290
+ visitStartTimeFormat,
291
+ visitStartDate,
292
+ visitLocation,
293
+ visitStartTime,
294
+ visitType,
295
+ visitAttributes,
296
+ visitStopDate,
297
+ visitStopTime,
298
+ visitStopTimeFormat,
299
+ } = data;
300
+
301
+ const { handleCreateExtraVisitInfo, attributes: extraAttributes } = extraVisitInfo ?? {};
302
+ const hasStartTime = ['ongoing', 'past'].includes(visitStatus);
303
+ const hasStopTime = 'past' === visitStatus;
304
+ const startDatetime = convertToDate(visitStartDate, visitStartTime, visitStartTimeFormat);
305
+ const stopDatetime = convertToDate(visitStopDate, visitStopTime, visitStopTimeFormat);
306
+
307
+ const formAttributes = !visitToEdit
308
+ ? Object.entries(visitAttributes)
309
+ .filter(([, value]) => value)
310
+ .map(([attributeType, value]) => ({ attributeType, value }))
311
+ : [];
312
+
313
+ const formAttributeTypes = new Set(formAttributes.map((attr) => attr.attributeType));
314
+ const deduplicatedExtraAttributes = (extraAttributes ?? []).filter(
315
+ (attr: VisitAttribute) => attr?.attributeType && !formAttributeTypes.has(attr.attributeType),
316
+ );
317
+ const inlineAttributes = !visitToEdit
318
+ ? [...formAttributes, ...deduplicatedExtraAttributes].filter(
319
+ (attr: VisitAttribute) => attr?.attributeType?.length > 0 && attr?.value?.length > 0,
320
+ )
321
+ : [];
322
+
323
+ const locationUuid = visitLocation?.uuid ?? '';
324
+ const payload: NewVisitPayload = {
325
+ visitType,
326
+ location: locationUuid,
327
+ startDatetime: (hasStartTime ? startDatetime : null) as Date,
328
+ stopDatetime: (hasStopTime ? stopDatetime : null) as Date,
329
+ ...(!visitToEdit && { patient: patientUuid }),
330
+ ...(inlineAttributes.length > 0 && { attributes: inlineAttributes }),
331
+ };
332
+
333
+ const abortController = new AbortController();
334
+
335
+ if (isOnline) {
336
+ if (hieFeatureFlags) {
337
+ setIsAwaitingOtp(true);
338
+ try {
339
+ for (const [, callbacks] of visitFormCallbacks) {
340
+ if (typeof callbacks.onBeforeVisitSave === 'function') {
341
+ const canProceed = await callbacks.onBeforeVisitSave();
342
+ if (!canProceed) {
343
+ return;
344
+ }
345
+ }
346
+ }
347
+ } finally {
348
+ setIsAwaitingOtp(false);
349
+ }
350
+ }
351
+
352
+ const visitRequest = visitToEdit?.uuid
353
+ ? updateVisit(visitToEdit.uuid, payload, abortController)
354
+ : saveVisit(payload, abortController);
355
+
356
+ await visitRequest
357
+ .then((response) => {
358
+ showSnackbar({
359
+ isLowContrast: true,
360
+ kind: 'success',
361
+ subtitle: !visitToEdit
362
+ ? t('visitStartedSuccessfully', '{{visit}} started successfully', {
363
+ visit: response?.data?.visitType?.display ?? t('visit', 'Visit'),
364
+ })
365
+ : t('visitDetailsUpdatedSuccessfully', '{{visit}} updated successfully', {
366
+ visit: response?.data?.visitType?.display ?? t('pastVisit', 'Past visit'),
367
+ }),
368
+ title: !visitToEdit
369
+ ? t('visitStarted', 'Visit started')
370
+ : t('visitDetailsUpdated', 'Visit details updated'),
371
+ });
372
+ return response;
373
+ })
374
+ .catch((error) => {
375
+ showSnackbar({
376
+ title: !visitToEdit
377
+ ? t('startVisitError', 'Error starting visit')
378
+ : t('errorUpdatingVisitDetails', 'Error updating visit details'),
379
+ kind: 'error',
380
+ isLowContrast: false,
381
+ subtitle: getErrorDescription(error),
382
+ });
383
+ return Promise.reject(error);
384
+ })
385
+ .then(async (response) => {
386
+ const visit = response.data;
387
+
388
+ invalidateVisitAndEncounterData(globalMutate as any, patientUuid);
389
+ invalidateCurrentVisit(globalMutate as any, patientUuid);
390
+ globalMutate(
391
+ (key) =>
392
+ typeof key === 'string' &&
393
+ (key.includes(`/visit?patient=${patientUuid}`) ||
394
+ key.includes(`/patient/${patientUuid}`) ||
395
+ key.includes('/queue') ||
396
+ key.includes('/visit/')),
397
+ undefined,
398
+ { revalidate: true },
399
+ );
400
+
401
+ const visitAttributesRequest = visitToEdit
402
+ ? handleVisitAttributes(visitAttributes, response.data.uuid).then((visitAttributesResponses) => {
403
+ if (visitAttributesResponses.length > 0) {
404
+ showSnackbar({
405
+ isLowContrast: true,
406
+ kind: 'success',
407
+ title: t(
408
+ 'additionalVisitInformationUpdatedSuccessfully',
409
+ 'Additional visit information updated successfully',
410
+ ),
411
+ });
412
+ }
413
+ })
414
+ : Promise.resolve();
415
+
416
+ const onVisitCreatedOrUpdatedRequests = [...visitFormCallbacks.values()].map((callbacks) =>
417
+ callbacks.onVisitCreatedOrUpdated(visit),
418
+ );
419
+
420
+ await Promise.all([visitAttributesRequest, ...onVisitCreatedOrUpdatedRequests]);
421
+ await handleCreateExtraVisitInfo?.();
422
+ await closeWorkspace({ discardUnsavedChanges: true });
423
+ onVisitStarted?.(visit);
424
+ })
425
+ .catch(() => {});
426
+ } else {
427
+ await createOfflineVisitForPatient(
428
+ patientUuid,
429
+ locationUuid,
430
+ config.offlineVisitTypeUuid,
431
+ payload.startDatetime,
432
+ ).then(
433
+ async (visit) => {
434
+ invalidateVisitAndEncounterData(globalMutate as any, patientUuid);
435
+ invalidateCurrentVisit(globalMutate as any, patientUuid);
436
+ globalMutate(
437
+ (key) =>
438
+ typeof key === 'string' &&
439
+ (key.includes(`/visit?patient=${patientUuid}`) ||
440
+ key.includes(`/patient/${patientUuid}`) ||
441
+ key.includes('/queue')),
442
+ undefined,
443
+ { revalidate: true },
444
+ );
445
+ showSnackbar({
446
+ isLowContrast: true,
447
+ kind: 'success',
448
+ subtitle: t('visitStartedSuccessfully', '{{visit}} started successfully', {
449
+ visit: t('offlineVisit', 'Offline Visit'),
450
+ }),
451
+ title: t('visitStarted', 'Visit started'),
452
+ });
453
+ await closeWorkspace({ discardUnsavedChanges: true });
454
+ onVisitStarted?.(visit);
455
+ },
456
+ (error: Error) => {
457
+ showSnackbar({
458
+ title: t('startVisitError', 'Error starting visit'),
459
+ kind: 'error',
460
+ isLowContrast: false,
461
+ subtitle: error?.message,
462
+ });
463
+ },
464
+ );
465
+ }
466
+ },
467
+ [
468
+ closeWorkspace,
469
+ config.offlineVisitTypeUuid,
470
+ extraVisitInfo,
471
+ getErrorDescription,
472
+ globalMutate,
473
+ handleVisitAttributes,
474
+ hieFeatureFlags,
475
+ isOnline,
476
+ onVisitStarted,
477
+ patientUuid,
478
+ t,
479
+ visitFormCallbacks,
480
+ visitToEdit,
481
+ ],
482
+ );
483
+
484
+ if (!workspaceProps) {
485
+ return null;
486
+ }
487
+
488
+ const isBusy = isAwaitingOtp || isSubmitting;
489
+
490
+ return (
491
+ <Workspace2
492
+ title={visitToEdit ? t('editVisit', 'Edit visit') : t('startVisitWorkspaceTitle', 'Start a visit')}
493
+ hasUnsavedChanges={isDirty}>
494
+ <FormProvider {...methods}>
495
+ <Form className={styles.form} onSubmit={handleSubmit(onSubmit)} data-openmrs-role="Start Visit Form">
496
+ {showPatientHeader && patient && (
497
+ <ExtensionSlot name="patient-header-slot" state={{ patient, patientUuid, hideActionsOverflow: true }} />
498
+ )}
499
+ {errorFetchingResources && (
500
+ <InlineNotification
501
+ kind={errorFetchingResources?.blockSavingForm ? 'error' : 'warning'}
502
+ lowContrast
503
+ className={styles.inlineNotification}
504
+ title={t('partOfFormDidntLoad', 'Part of the form did not load')}
505
+ subtitle={t('refreshToTryAgain', 'Please refresh to try again')}
506
+ />
507
+ )}
508
+ <div>
509
+ {isTablet && (
510
+ <Row className={styles.headerGridRow}>
511
+ <ExtensionSlot
512
+ name="visit-form-header-slot"
513
+ className={styles.dataGridRow}
514
+ state={visitHeaderSlotState}
515
+ />
516
+ </Row>
517
+ )}
518
+ <Stack gap={4} className={styles.container}>
519
+ <section>
520
+ <FormGroup legendText={t('theVisitIs', 'The visit is')}>
521
+ <Controller
522
+ name="visitStatus"
523
+ control={control}
524
+ render={({ field: { onChange, value } }) => {
525
+ const validVisitStatuses = visitToEdit ? ['ongoing', 'past'] : visitStatuses;
526
+ const idx = validVisitStatuses.indexOf(value);
527
+ const selectedIndex = idx >= 0 ? idx : 0;
528
+ return visitToEdit ? (
529
+ <ContentSwitcher
530
+ selectedIndex={selectedIndex}
531
+ onChange={({ name }) => onChange(name)}
532
+ size="md">
533
+ <Switch name="ongoing">{t('ongoing', 'Ongoing')}</Switch>
534
+ <Switch name="past">{t('ended', 'Ended')}</Switch>
535
+ </ContentSwitcher>
536
+ ) : (
537
+ <ContentSwitcher
538
+ selectedIndex={selectedIndex}
539
+ onChange={({ name }) => onChange(name)}
540
+ size="md">
541
+ <Switch name="new">{t('new', 'New')}</Switch>
542
+ <Switch name="ongoing">{t('ongoing', 'Ongoing')}</Switch>
543
+ <Switch name="past">{t('inThePast', 'In the past')}</Switch>
544
+ </ContentSwitcher>
545
+ );
546
+ }}
547
+ />
548
+ </FormGroup>
549
+ </section>
550
+ {hasActiveVisitConflict && (
551
+ <InlineNotification
552
+ className={styles.inlineNotification}
553
+ kind="info"
554
+ lowContrast
555
+ title={t('activeVisitExists', 'This patient already has an active visit')}
556
+ subtitle={t('endActiveVisitFirst', 'You must end the current visit before starting a new one.')}
557
+ />
558
+ )}
559
+ {!hasActiveVisitConflict && (
560
+ <>
561
+ <VisitDateTimeSection
562
+ {...{ control, firstEncounterDateTime, lastEncounterDateTime }}
563
+ earliestStartDate={earliestAllowedStartDate?.getTime()}
564
+ />
565
+ {config.showUpcomingAppointments && (
566
+ <section>
567
+ <div className={styles.sectionField}>
568
+ <VisitFormExtensionSlot
569
+ name="visit-form-top-slot"
570
+ visitStatus={visitStatus}
571
+ patientUuid={patientUuid}
572
+ visitFormOpenedFrom={openedFrom}
573
+ setVisitFormCallbacks={setVisitFormCallbacks}
574
+ />
575
+ </div>
576
+ </section>
577
+ )}
578
+ <LocationSelector control={control} />
579
+ {config.showRecommendedVisitTypeTab && (
580
+ <section>
581
+ <h1 className={styles.sectionTitle}>{t('program', 'Program')}</h1>
582
+ <FormGroup
583
+ legendText={t('selectProgramType', 'Select program type')}
584
+ className={styles.sectionField}>
585
+ <Controller
586
+ name="programType"
587
+ control={control}
588
+ render={({ field: { onChange } }) => (
589
+ <RadioButtonGroup
590
+ orientation="vertical"
591
+ onChange={(selection: string | number | undefined) =>
592
+ onChange(
593
+ activePatientEnrollment.find(
594
+ ({ program }) => program.uuid === String(selection ?? ''),
595
+ )?.uuid,
596
+ )
597
+ }
598
+ name="program-type-radio-group">
599
+ {activePatientEnrollment.map(({ uuid, display, program }) => (
600
+ <RadioButton
601
+ key={uuid}
602
+ className={styles.radioButton}
603
+ id={uuid}
604
+ labelText={display}
605
+ value={program.uuid}
606
+ />
607
+ ))}
608
+ </RadioButtonGroup>
609
+ )}
610
+ />
611
+ </FormGroup>
612
+ </section>
613
+ )}
614
+ {!emrConfiguration?.atFacilityVisitType && (
615
+ <section>
616
+ <h1 className={styles.sectionTitle}>{t('visitType_title', 'Visit Type')}</h1>
617
+ <div className={styles.sectionField}>
618
+ {config.showRecommendedVisitTypeTab ? (
619
+ <>
620
+ <ContentSwitcher
621
+ selectedIndex={visitTypeContentSwitcherIndex}
622
+ onChange={({ index }) => setVisitTypeContentSwitcherIndex(index ?? 0)}
623
+ size="md">
624
+ <Switch name="recommended">{t('recommended', 'Recommended')}</Switch>
625
+ <Switch name="all">{t('all', 'All')}</Switch>
626
+ </ContentSwitcher>
627
+ {visitTypeContentSwitcherIndex === 0 &&
628
+ !isLoading &&
629
+ (() => {
630
+ const enrollment = activePatientEnrollment?.find(
631
+ ({ program }) => program.uuid === getValues('programType'),
632
+ );
633
+ const locationUuid = getValues('visitLocation')?.uuid;
634
+ return enrollment && locationUuid ? (
635
+ <MemoizedRecommendedVisitType
636
+ patientUuid={patientUuid}
637
+ patientProgramEnrollment={enrollment}
638
+ locationUuid={locationUuid}
639
+ />
640
+ ) : null;
641
+ })()}
642
+ {visitTypeContentSwitcherIndex === 1 && <BaseVisitType visitTypes={allVisitTypes} />}
643
+ </>
644
+ ) : (
645
+ <BaseVisitType visitTypes={allVisitTypes} />
646
+ )}
647
+ </div>
648
+ {errors?.visitType && (
649
+ <section>
650
+ <div className={styles.sectionField}>
651
+ <InlineNotification
652
+ role="alert"
653
+ style={{ margin: '0', minWidth: '100%' }}
654
+ kind="error"
655
+ lowContrast={true}
656
+ title={t('missingVisitType', 'Missing visit type')}
657
+ subtitle={t('selectVisitType', 'Please select a Visit Type')}
658
+ />
659
+ </div>
660
+ </section>
661
+ )}
662
+ </section>
663
+ )}
664
+ <ExtensionSlot state={{ patientUuid, setExtraVisitInfo }} name="extra-visit-attribute-slot" />
665
+ <section>
666
+ <div className={styles.sectionField}>
667
+ <VisitAttributeTypeFields setErrorFetchingResources={setErrorFetchingResourcesAdapter} />
668
+ </div>
669
+ </section>
670
+ {!visitToEdit && (
671
+ <section>
672
+ <div className={styles.sectionField}>
673
+ <VisitFormExtensionSlot
674
+ name="visit-form-bottom-slot"
675
+ visitStatus={visitStatus}
676
+ patientUuid={patientUuid}
677
+ visitFormOpenedFrom={openedFrom}
678
+ setVisitFormCallbacks={setVisitFormCallbacks}
679
+ visitTypeUuid={visitType}
680
+ />
681
+ </div>
682
+ </section>
683
+ )}
684
+ </>
685
+ )}
686
+ </Stack>
687
+ </div>
688
+ <ButtonSet
689
+ className={classNames(styles.buttonSet, { [styles.tablet]: isTablet, [styles.desktop]: !isTablet })}>
690
+ <Button className={styles.button} kind="secondary" onClick={() => closeWorkspace()}>
691
+ {t('discard', 'Discard')}
692
+ </Button>
693
+ <Button
694
+ className={styles.button}
695
+ disabled={
696
+ isBusy ||
697
+ isLoadingVisit ||
698
+ isLoadingBirthdateCheck ||
699
+ isLoadingOverlapSetting ||
700
+ errorFetchingResources?.blockSavingForm ||
701
+ hasActiveVisitConflict ||
702
+ isElectiveNotApproved ||
703
+ isCoverageExhausted
704
+ }
705
+ kind="primary"
706
+ type="submit">
707
+ {isBusy ? (
708
+ <InlineLoading
709
+ className={styles.spinner}
710
+ description={
711
+ visitToEdit
712
+ ? t('updatingVisit', 'Updating visit') + '...'
713
+ : hieFeatureFlags && isAwaitingOtp
714
+ ? t('sendingOtp', 'Sending OTP') + '...'
715
+ : t('startingVisit', 'Starting visit') + '...'
716
+ }
717
+ />
718
+ ) : (
719
+ <span>
720
+ {visitToEdit
721
+ ? t('updateVisit', 'Update visit')
722
+ : isElectiveNotApproved
723
+ ? t('awaitingApproval', 'Awaiting approval')
724
+ : hieFeatureFlags && isSHAVisit
725
+ ? t('verifyAndStartVisit', 'Verify & Start Visit')
726
+ : t('startVisit', 'Start visit')}
727
+ </span>
728
+ )}
729
+ </Button>
730
+ </ButtonSet>
731
+ </Form>
732
+ </FormProvider>
733
+ </Workspace2>
734
+ );
735
+ };
736
+
737
+ interface VisitFormExtensionSlotProps {
738
+ name: string;
739
+ patientUuid: string;
740
+ visitStatus: string;
741
+ visitFormOpenedFrom: string;
742
+ setVisitFormCallbacks: React.Dispatch<React.SetStateAction<Map<string, VisitFormCallbacks>>>;
743
+ visitTypeUuid?: string;
744
+ }
745
+
746
+ type VisitFormExtensionState = {
747
+ patientUuid: string;
748
+ setVisitFormCallbacks: (callbacks: VisitFormCallbacks) => void;
749
+ visitFormOpenedFrom: string;
750
+ visitStatus: string;
751
+ patientChartConfig: ExpressWorkflowConfig;
752
+ visitTypeUuid?: string;
753
+ };
754
+
755
+ const VisitFormExtensionSlot: React.FC<VisitFormExtensionSlotProps> = React.memo(
756
+ ({ name, patientUuid, visitFormOpenedFrom, setVisitFormCallbacks, visitStatus, visitTypeUuid }) => {
757
+ const config = useConfig<ExpressWorkflowConfig>();
758
+ return (
759
+ <ExtensionSlot name={name}>
760
+ {(extension: AssignedExtension) => {
761
+ const state: VisitFormExtensionState = {
762
+ patientUuid,
763
+ setVisitFormCallbacks: (callbacks: VisitFormCallbacks): void => {
764
+ setVisitFormCallbacks((old) => new Map(old).set(extension.id, callbacks));
765
+ },
766
+ visitFormOpenedFrom,
767
+ visitStatus,
768
+ patientChartConfig: config,
769
+ visitTypeUuid,
770
+ };
771
+ return <Extension state={state} />;
772
+ }}
773
+ </ExtensionSlot>
774
+ );
775
+ },
776
+ );
777
+
778
+ export default ExportedVisitForm;