@kenyaemr/esm-ward-app 8.1.2-pre.214 → 8.5.1-pre.18

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 (356) hide show
  1. package/.turbo/turbo-build.log +25 -35
  2. package/README.md +38 -0
  3. package/dist/1119.js +1 -0
  4. package/dist/1197.js +1 -0
  5. package/dist/1663.js +1 -0
  6. package/dist/1663.js.map +1 -0
  7. package/dist/1741.js +1 -0
  8. package/dist/1741.js.map +1 -0
  9. package/dist/1776.js +1 -0
  10. package/dist/1776.js.map +1 -0
  11. package/dist/1879.js +1 -0
  12. package/dist/1879.js.map +1 -0
  13. package/dist/1899.js +1 -0
  14. package/dist/1899.js.map +1 -0
  15. package/dist/1917.js +1 -0
  16. package/dist/1917.js.map +1 -0
  17. package/dist/2146.js +1 -0
  18. package/dist/2372.js +1 -0
  19. package/dist/2372.js.map +1 -0
  20. package/dist/2470.js +1 -0
  21. package/dist/2470.js.map +1 -0
  22. package/dist/2537.js +1 -0
  23. package/dist/2537.js.map +1 -0
  24. package/dist/2557.js +1 -0
  25. package/dist/2557.js.map +1 -0
  26. package/dist/2690.js +1 -0
  27. package/dist/2728.js +2 -0
  28. package/dist/{372.js.LICENSE.txt → 2728.js.LICENSE.txt} +2 -2
  29. package/dist/2728.js.map +1 -0
  30. package/dist/2775.js +2 -0
  31. package/dist/2775.js.LICENSE.txt +59 -0
  32. package/dist/2775.js.map +1 -0
  33. package/dist/2913.js +2 -0
  34. package/dist/2913.js.map +1 -0
  35. package/dist/2932.js +1 -0
  36. package/dist/2932.js.map +1 -0
  37. package/dist/2948.js +1 -0
  38. package/dist/2948.js.map +1 -0
  39. package/dist/3099.js +1 -0
  40. package/dist/3161.js +2 -0
  41. package/dist/{649.js.LICENSE.txt → 3161.js.LICENSE.txt} +2 -2
  42. package/dist/3161.js.map +1 -0
  43. package/dist/3365.js +1 -0
  44. package/dist/3365.js.map +1 -0
  45. package/dist/3373.js +2 -0
  46. package/dist/3373.js.LICENSE.txt +5 -0
  47. package/dist/3373.js.map +1 -0
  48. package/dist/3399.js +1 -0
  49. package/dist/3399.js.map +1 -0
  50. package/dist/3413.js +1 -0
  51. package/dist/3413.js.map +1 -0
  52. package/dist/3423.js +1 -0
  53. package/dist/3423.js.map +1 -0
  54. package/dist/3584.js +1 -0
  55. package/dist/3737.js +1 -0
  56. package/dist/3737.js.map +1 -0
  57. package/dist/3982.js +1 -0
  58. package/dist/3982.js.map +1 -0
  59. package/dist/4041.js +2 -0
  60. package/dist/4041.js.map +1 -0
  61. package/dist/4055.js +1 -0
  62. package/dist/4132.js +1 -0
  63. package/dist/4300.js +1 -0
  64. package/dist/4335.js +1 -0
  65. package/dist/4430.js +2 -0
  66. package/dist/4430.js.LICENSE.txt +29 -0
  67. package/dist/4430.js.map +1 -0
  68. package/dist/4618.js +1 -0
  69. package/dist/465.js +1 -0
  70. package/dist/465.js.map +1 -0
  71. package/dist/4652.js +1 -0
  72. package/dist/4701.js +2 -0
  73. package/dist/4701.js.LICENSE.txt +9 -0
  74. package/dist/4701.js.map +1 -0
  75. package/dist/4743.js +2 -0
  76. package/dist/4743.js.LICENSE.txt +9 -0
  77. package/dist/4743.js.map +1 -0
  78. package/dist/4944.js +1 -0
  79. package/dist/5173.js +1 -0
  80. package/dist/5241.js +1 -0
  81. package/dist/5442.js +1 -0
  82. package/dist/5661.js +1 -0
  83. package/dist/6012.js +2 -0
  84. package/dist/6012.js.LICENSE.txt +5 -0
  85. package/dist/6012.js.map +1 -0
  86. package/dist/6022.js +1 -0
  87. package/dist/6468.js +1 -0
  88. package/dist/6679.js +1 -0
  89. package/dist/6840.js +1 -0
  90. package/dist/6859.js +1 -0
  91. package/dist/7097.js +1 -0
  92. package/dist/7159.js +1 -0
  93. package/dist/7179.js +2 -0
  94. package/dist/7179.js.LICENSE.txt +9 -0
  95. package/dist/7179.js.map +1 -0
  96. package/dist/723.js +1 -0
  97. package/dist/7232.js +2 -0
  98. package/dist/7232.js.LICENSE.txt +9 -0
  99. package/dist/7232.js.map +1 -0
  100. package/dist/7524.js +1 -0
  101. package/dist/7524.js.map +1 -0
  102. package/dist/7617.js +1 -0
  103. package/dist/7661.js +1 -0
  104. package/dist/7661.js.map +1 -0
  105. package/dist/7886.js +1 -0
  106. package/dist/7886.js.map +1 -0
  107. package/dist/795.js +1 -0
  108. package/dist/8163.js +1 -0
  109. package/dist/8205.js +1 -0
  110. package/dist/8205.js.map +1 -0
  111. package/dist/8317.js +2 -0
  112. package/dist/8317.js.LICENSE.txt +15 -0
  113. package/dist/8317.js.map +1 -0
  114. package/dist/8349.js +1 -0
  115. package/dist/8501.js +1 -0
  116. package/dist/8501.js.map +1 -0
  117. package/dist/8522.js +1 -0
  118. package/dist/8522.js.map +1 -0
  119. package/dist/8618.js +1 -0
  120. package/dist/8622.js +1 -0
  121. package/dist/8622.js.map +1 -0
  122. package/dist/89.js +1 -0
  123. package/dist/89.js.map +1 -0
  124. package/dist/890.js +1 -0
  125. package/dist/9045.js +1 -0
  126. package/dist/9045.js.map +1 -0
  127. package/dist/9117.js +1 -0
  128. package/dist/9117.js.map +1 -0
  129. package/dist/9214.js +1 -0
  130. package/dist/9538.js +1 -0
  131. package/dist/9569.js +1 -0
  132. package/dist/986.js +1 -0
  133. package/dist/9876.js +2 -0
  134. package/dist/9876.js.LICENSE.txt +9 -0
  135. package/dist/9876.js.map +1 -0
  136. package/dist/9879.js +1 -0
  137. package/dist/9880.js +1 -0
  138. package/dist/9880.js.map +1 -0
  139. package/dist/9895.js +1 -0
  140. package/dist/9900.js +1 -0
  141. package/dist/9913.js +1 -0
  142. package/dist/kenyaemr-esm-ward-app.js +1 -1
  143. package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +1479 -235
  144. package/dist/kenyaemr-esm-ward-app.js.map +1 -1
  145. package/dist/main.js +1 -1
  146. package/dist/main.js.LICENSE.txt +0 -35
  147. package/dist/main.js.map +1 -1
  148. package/dist/routes.json +1 -1
  149. package/mock.tsx +15 -2
  150. package/package.json +10 -5
  151. package/src/beds/{empty-bed-skeleton.tsx → empty-bed-skeleton.component.tsx} +2 -2
  152. package/src/config-schema.ts +48 -0
  153. package/src/declarations.d.ts +8 -0
  154. package/src/hooks/useAdmissionLocation.ts +24 -4
  155. package/src/hooks/useInpatientAdmission.ts +14 -10
  156. package/src/hooks/useInpatientAdmissionByPatients.ts +29 -0
  157. package/src/hooks/useInpatientRequest.ts +5 -1
  158. package/src/hooks/useInpatientRequestByPatients.ts +34 -0
  159. package/src/hooks/useIpdDischargeEncounter.ts +137 -0
  160. package/src/hooks/usePatientPendingOrders.ts +1 -1
  161. package/src/hooks/useRestPatient.ts +11 -3
  162. package/src/hooks/useSummaryMetrics.ts +103 -0
  163. package/src/hooks/useWardLocation.test.ts +1 -1
  164. package/src/hooks/useWardLocation.ts +18 -5
  165. package/src/hooks/useWardPatientGrouping.ts +63 -10
  166. package/src/index.ts +24 -4
  167. package/src/location-selector/location-selector.component.tsx +38 -5
  168. package/src/root.component.tsx +2 -2
  169. package/src/routes.json +60 -26
  170. package/src/types/index.ts +17 -6
  171. package/src/ward-patient-card/card-rows/admission-request-note-row.component.tsx +1 -1
  172. package/src/ward-patient-card/card-rows/coded-obs-tags-row.component.tsx +4 -4
  173. package/src/ward-patient-card/card-rows/mother-child-row.component.tsx +6 -6
  174. package/src/ward-patient-card/card-rows/pending-items-row.component.tsx +2 -3
  175. package/src/ward-patient-card/row-elements/{ward-patient-coded-obs-tags.tsx → ward-patient-coded-obs-tags.component.tsx} +5 -5
  176. package/src/ward-patient-card/row-elements/{ward-patient-header-address.tsx → ward-patient-header-address.component.tsx} +2 -2
  177. package/src/ward-patient-card/row-elements/{ward-patient-identifier.tsx → ward-patient-identifier.component.tsx} +7 -1
  178. package/src/ward-patient-card/row-elements/ward-patient-identifier.scss +3 -0
  179. package/src/ward-patient-card/row-elements/{ward-patient-obs.tsx → ward-patient-obs.component.tsx} +5 -5
  180. package/src/ward-patient-card/row-elements/{ward-patient-pending-transfer.tsx → ward-patient-pending-transfer.component.tsx} +3 -5
  181. package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.component.tsx +73 -0
  182. package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.component.tsx +29 -0
  183. package/src/ward-patient-card/ward-patient-card.component.tsx +5 -5
  184. package/src/ward-patient-card/ward-patient-card.scss +2 -6
  185. package/src/ward-patients/admitted-patients.tsx +218 -0
  186. package/src/ward-patients/awaiting-admission-patients.tsx +158 -0
  187. package/src/ward-patients/discharge-in-patients.tsx +183 -0
  188. package/src/ward-patients/discharge-patients.tsx +129 -0
  189. package/src/ward-patients/patient-cells.tsx +75 -0
  190. package/src/ward-patients/table-state-components.tsx +40 -0
  191. package/src/ward-patients/ward-patient.scss +24 -0
  192. package/src/ward-patients/ward-patients-table.tsx +38 -0
  193. package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +8 -8
  194. package/src/ward-view/default-ward/default-ward-pending-patients.component.tsx +3 -3
  195. package/src/ward-view/default-ward/default-ward-view.component.tsx +33 -6
  196. package/src/ward-view/linelist-wards/Filters.tsx +25 -0
  197. package/src/ward-view/linelist-wards/Header.tsx +27 -0
  198. package/src/ward-view/linelist-wards/LineListTable.tsx +145 -0
  199. package/src/ward-view/linelist-wards/Metrics.tsx +21 -0
  200. package/src/ward-view/linelist-wards/WardPendingOutCell.tsx +15 -0
  201. package/src/ward-view/linelist-wards/WardsLineList.tsx +30 -0
  202. package/src/ward-view/linelist-wards/linelist-wards.scss +100 -0
  203. package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +8 -8
  204. package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +2 -2
  205. package/src/ward-view/materal-ward/maternal-ward-patient-card.test.tsx +1 -1
  206. package/src/ward-view/materal-ward/maternal-ward-pending-patients.component.tsx +1 -1
  207. package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +4 -4
  208. package/src/ward-view/ward-view-content-wrapper.tsx +36 -0
  209. package/src/ward-view/ward-view.resource.ts +26 -8
  210. package/src/ward-view/ward-view.scss +15 -8
  211. package/src/ward-view/ward-view.test.tsx +8 -8
  212. package/src/ward-view/ward.component.tsx +2 -2
  213. package/src/ward-view-header/admission-requests-bar.component.tsx +18 -8
  214. package/src/ward-view-header/admission-requests-bar.test.tsx +3 -3
  215. package/src/ward-view-header/ward-metric.component.tsx +2 -3
  216. package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +12 -14
  217. package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +5 -5
  218. package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +1 -1
  219. package/src/ward-workspace/admission-request-workspace/admission-requests-action-button.extension.tsx +18 -0
  220. package/src/ward-workspace/admission-request-workspace/admission-requests-context.ts +20 -0
  221. package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +7 -6
  222. package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +15 -25
  223. package/src/ward-workspace/admit-patient-button.component.tsx +41 -18
  224. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +14 -16
  225. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +2 -2
  226. package/src/ward-workspace/bed-selector.component.tsx +1 -1
  227. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.test.tsx +1 -1
  228. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.workspace.tsx +4 -6
  229. package/src/ward-workspace/create-admission-encounter/create-admission-encounter-action-button.extension.tsx +46 -0
  230. package/src/ward-workspace/create-admission-encounter/create-admission-encounter.test.tsx +241 -0
  231. package/src/ward-workspace/create-admission-encounter/create-admission-encounter.workspace.tsx +152 -0
  232. package/src/ward-workspace/kenya-emr-patient-discharge/discharge-workspace-siderail.component.tsx +23 -0
  233. package/src/ward-workspace/kenya-emr-patient-discharge/patient-discharge.resource.tsx +123 -0
  234. package/src/ward-workspace/kenya-emr-patient-discharge/patient-discharge.workspace.tsx +101 -0
  235. package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +6 -15
  236. package/src/ward-workspace/patient-transfer-bed-swap/{patient-transfer-request-form.component.tsx → patient-admit-or-transfer-request-form.component.tsx} +56 -37
  237. package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +13 -3
  238. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +11 -5
  239. package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.scss +5 -0
  240. package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.workspace.tsx +20 -6
  241. package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +2 -1
  242. package/src/ward-workspace/ward-patient-notes/history/note.component.tsx +3 -3
  243. package/src/ward.resource.ts +9 -3
  244. package/translations/am.json +123 -0
  245. package/translations/ar.json +123 -0
  246. package/translations/ar_SY.json +123 -0
  247. package/translations/bn.json +123 -0
  248. package/translations/de.json +123 -0
  249. package/translations/en.json +31 -3
  250. package/translations/en_US.json +123 -0
  251. package/translations/es.json +123 -0
  252. package/translations/es_MX.json +123 -0
  253. package/translations/fr.json +123 -0
  254. package/translations/he.json +123 -0
  255. package/translations/hi.json +123 -0
  256. package/translations/hi_IN.json +123 -0
  257. package/translations/id.json +123 -0
  258. package/translations/it.json +123 -0
  259. package/translations/ka.json +123 -0
  260. package/translations/km.json +123 -0
  261. package/translations/ku.json +123 -0
  262. package/translations/ky.json +123 -0
  263. package/translations/lg.json +123 -0
  264. package/translations/ne.json +123 -0
  265. package/translations/pl.json +123 -0
  266. package/translations/pt.json +123 -0
  267. package/translations/pt_BR.json +123 -0
  268. package/translations/qu.json +123 -0
  269. package/translations/ro_RO.json +123 -0
  270. package/translations/ru_RU.json +123 -0
  271. package/translations/si.json +123 -0
  272. package/translations/sw.json +123 -0
  273. package/translations/sw_KE.json +123 -0
  274. package/translations/tr.json +123 -0
  275. package/translations/tr_TR.json +123 -0
  276. package/translations/uk.json +123 -0
  277. package/translations/uz.json +123 -0
  278. package/translations/uz@Latn.json +123 -0
  279. package/translations/uz_UZ.json +123 -0
  280. package/translations/vi.json +123 -0
  281. package/translations/zh.json +123 -0
  282. package/translations/zh_CN.json +123 -0
  283. package/dist/109.js +0 -1
  284. package/dist/109.js.map +0 -1
  285. package/dist/124.js +0 -1
  286. package/dist/124.js.map +0 -1
  287. package/dist/125.js +0 -1
  288. package/dist/125.js.map +0 -1
  289. package/dist/126.js +0 -1
  290. package/dist/126.js.map +0 -1
  291. package/dist/130.js +0 -2
  292. package/dist/130.js.LICENSE.txt +0 -5
  293. package/dist/130.js.map +0 -1
  294. package/dist/146.js +0 -1
  295. package/dist/146.js.map +0 -1
  296. package/dist/15.js +0 -1
  297. package/dist/15.js.map +0 -1
  298. package/dist/325.js +0 -1
  299. package/dist/325.js.map +0 -1
  300. package/dist/348.js +0 -1
  301. package/dist/348.js.map +0 -1
  302. package/dist/362.js +0 -1
  303. package/dist/362.js.map +0 -1
  304. package/dist/372.js +0 -2
  305. package/dist/372.js.map +0 -1
  306. package/dist/443.js +0 -1
  307. package/dist/443.js.map +0 -1
  308. package/dist/471.js +0 -1
  309. package/dist/471.js.map +0 -1
  310. package/dist/481.js +0 -1
  311. package/dist/481.js.map +0 -1
  312. package/dist/53.js +0 -1
  313. package/dist/53.js.map +0 -1
  314. package/dist/559.js +0 -1
  315. package/dist/559.js.map +0 -1
  316. package/dist/574.js +0 -1
  317. package/dist/576.js +0 -1
  318. package/dist/576.js.map +0 -1
  319. package/dist/577.js +0 -1
  320. package/dist/577.js.map +0 -1
  321. package/dist/591.js +0 -2
  322. package/dist/591.js.map +0 -1
  323. package/dist/598.js +0 -1
  324. package/dist/598.js.map +0 -1
  325. package/dist/649.js +0 -2
  326. package/dist/649.js.map +0 -1
  327. package/dist/662.js +0 -1
  328. package/dist/662.js.map +0 -1
  329. package/dist/767.js +0 -1
  330. package/dist/767.js.map +0 -1
  331. package/dist/784.js +0 -2
  332. package/dist/784.js.map +0 -1
  333. package/dist/921.js +0 -1
  334. package/dist/921.js.map +0 -1
  335. package/dist/922.js +0 -1
  336. package/dist/922.js.map +0 -1
  337. package/dist/925.js +0 -2
  338. package/dist/925.js.LICENSE.txt +0 -40
  339. package/dist/925.js.map +0 -1
  340. package/dist/940.js +0 -1
  341. package/dist/940.js.map +0 -1
  342. package/dist/969.js +0 -1
  343. package/dist/969.js.map +0 -1
  344. package/dist/983.js +0 -1
  345. package/dist/983.js.map +0 -1
  346. package/package-lock.json +0 -5001
  347. package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.tsx +0 -22
  348. package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.tsx +0 -22
  349. /package/dist/{591.js.LICENSE.txt → 2913.js.LICENSE.txt} +0 -0
  350. /package/dist/{784.js.LICENSE.txt → 4041.js.LICENSE.txt} +0 -0
  351. /package/src/ward-patient-card/row-elements/{ward-patient-age.tsx → ward-patient-age.component.tsx} +0 -0
  352. /package/src/ward-patient-card/row-elements/{ward-patient-bed-number.tsx → ward-patient-bed-number.component.tsx} +0 -0
  353. /package/src/ward-patient-card/row-elements/{ward-patient-location.tsx → ward-patient-location.component.tsx} +0 -0
  354. /package/src/ward-patient-card/row-elements/{ward-patient-name.tsx → ward-patient-name.component.tsx} +0 -0
  355. /package/src/ward-patient-card/row-elements/{ward-patient-responsive-tooltip.tsx → ward-patient-responsive-tooltip.component.tsx} +0 -0
  356. /package/src/ward-patient-card/row-elements/{ward-patient-skeleton-text.tsx → ward-patient-skeleton-text.component.tsx} +0 -0
@@ -0,0 +1,241 @@
1
+ import { useAppContext, useVisit } from '@openmrs/esm-framework';
2
+ import { screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import {
5
+ mockInpatientAdmissions,
6
+ mockInpatientRequests,
7
+ mockLocationInpatientWard,
8
+ mockLocationMosoriot,
9
+ mockPatientAlice,
10
+ } from '__mocks__';
11
+ import React from 'react';
12
+ import { renderWithSwr } from '../../../../../tools';
13
+ import { mockWardViewContext } from '../../../mock';
14
+ import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
15
+ import useEmrConfiguration from '../../hooks/useEmrConfiguration';
16
+ import { useInpatientAdmissionByPatients } from '../../hooks/useInpatientAdmissionByPatients';
17
+ import { useInpatientRequestByPatients } from '../../hooks/useInpatientRequestByPatients';
18
+ import useRestPatient from '../../hooks/useRestPatient';
19
+ import useWardLocation from '../../hooks/useWardLocation';
20
+ import { type WardViewContext } from '../../types';
21
+ import { useAdmitPatient } from '../../ward.resource';
22
+ import CreateAdmissionEncounterWorkspace from './create-admission-encounter.workspace';
23
+
24
+ jest.mocked(useAppContext<WardViewContext>).mockReturnValue(mockWardViewContext);
25
+
26
+ const mockUseVisit = jest.mocked(useVisit).mockReturnValue({
27
+ activeVisit: {
28
+ encounters: [],
29
+ startDatetime: new Date().toISOString(),
30
+ uuid: 'mock-visit',
31
+ visitType: { display: 'Some Visit Type', uuid: 'some-visit-type-uuid' },
32
+ },
33
+ currentVisit: null,
34
+ currentVisitIsRetrospective: null,
35
+ mutate: jest.fn(),
36
+ error: undefined,
37
+ isLoading: false,
38
+ isValidating: false,
39
+ });
40
+
41
+ jest.mock('../../hooks/useWardLocation', () => jest.fn());
42
+ const mockedUseWardLocation = jest.mocked(useWardLocation);
43
+ mockedUseWardLocation.mockReturnValue({
44
+ location: mockLocationInpatientWard,
45
+ isLoadingLocation: false,
46
+ errorFetchingLocation: null,
47
+ invalidLocation: false,
48
+ });
49
+
50
+ jest.mock('../../hooks/useRestPatient', () => jest.fn());
51
+ const mockUseRestPatient = jest.mocked(useRestPatient).mockReturnValue({
52
+ patient: mockPatientAlice,
53
+ isLoading: false,
54
+ error: null,
55
+ isValidating: false,
56
+ mutate: jest.fn(),
57
+ });
58
+
59
+ jest.mock('../../hooks/useAssignedBedByPatient', () => ({
60
+ useAssignedBedByPatient: jest.fn(),
61
+ }));
62
+ // @ts-ignore - we don't need to mock the entire object
63
+ jest.mocked(useAssignedBedByPatient).mockReturnValue({
64
+ data: {
65
+ data: {
66
+ results: [
67
+ {
68
+ bedId: 1,
69
+ bedNumber: '1',
70
+ bedType: null,
71
+ patients: [mockPatientAlice],
72
+ physicalLocation: mockLocationInpatientWard,
73
+ },
74
+ ],
75
+ },
76
+ },
77
+ isLoading: false,
78
+ });
79
+
80
+ jest.mock('../../hooks/useInpatientAdmissionByPatients', () => ({
81
+ useInpatientAdmissionByPatients: jest.fn(),
82
+ }));
83
+ const mockedUseInpatientAdmissionByPatients = jest.mocked(useInpatientAdmissionByPatients).mockReturnValue({
84
+ data: [],
85
+ hasMore: false,
86
+ loadMore: jest.fn(),
87
+ isValidating: false,
88
+ isLoading: false,
89
+ error: undefined,
90
+ mutate: jest.fn(),
91
+ totalCount: mockInpatientAdmissions.length,
92
+ nextUri: null,
93
+ });
94
+
95
+ jest.mock('../../hooks/useInpatientRequestByPatients', () => ({
96
+ useInpatientRequestByPatients: jest.fn(),
97
+ }));
98
+ const mockedUseInpatientRequestByPatients = jest.mocked(useInpatientRequestByPatients).mockReturnValue({
99
+ inpatientRequests: [],
100
+ hasMore: false,
101
+ loadMore: jest.fn(),
102
+ isValidating: false,
103
+ isLoading: false,
104
+ error: undefined,
105
+ mutate: jest.fn(),
106
+ totalCount: mockInpatientAdmissions.length,
107
+ nextUri: null,
108
+ });
109
+
110
+ jest.mock('../../hooks/useEmrConfiguration', () => jest.fn());
111
+ jest.mocked(useEmrConfiguration).mockReturnValue({
112
+ isLoadingEmrConfiguration: false,
113
+ errorFetchingEmrConfiguration: null,
114
+ // @ts-ignore - we only need these keys for now
115
+ emrConfiguration: {
116
+ admissionEncounterType: {
117
+ uuid: 'admission-encounter-type-uuid',
118
+ display: 'Admission Encounter',
119
+ },
120
+ transferWithinHospitalEncounterType: {
121
+ uuid: 'transfer-within-hospital-encounter-type-uuid',
122
+ display: 'Transfer Within Hospital Encounter Type',
123
+ },
124
+ clinicianEncounterRole: {
125
+ uuid: 'clinician-encounter-role-uuid',
126
+ },
127
+ },
128
+ mutateEmrConfiguration: jest.fn(),
129
+ });
130
+
131
+ jest.mock('../../ward.resource', () => ({
132
+ useAdmitPatient: jest.fn(),
133
+ assignPatientToBed: jest.fn(),
134
+ removePatientFromBed: jest.fn(),
135
+ }));
136
+ const mockedUseAdmitPatient: ReturnType<typeof useAdmitPatient> = {
137
+ admitPatient: jest.fn(),
138
+ isLoadingEmrConfiguration: false,
139
+ errorFetchingEmrConfiguration: false,
140
+ };
141
+ jest.mocked(useAdmitPatient).mockReturnValue(mockedUseAdmitPatient);
142
+ const mockedAdmitPatient = mockedUseAdmitPatient.admitPatient;
143
+ // @ts-ignore - we only need these two keys for now
144
+ mockedAdmitPatient.mockResolvedValue({
145
+ ok: true,
146
+ data: {
147
+ uuid: 'encounter-uuid',
148
+ },
149
+ });
150
+
151
+ describe('CreateAdmissionEncounterWorkspace', () => {
152
+ it('should render patient header and admit patient button', async () => {
153
+ const user = userEvent.setup();
154
+ renderCreateAdmissionEncounterWorkspace(mockPatientAlice.uuid);
155
+ expect(screen.getByText(mockPatientAlice.person?.preferredName?.display)).toBeInTheDocument();
156
+ const admitPatientButton = screen.getByRole('button', { name: /admit patient/i });
157
+ expect(admitPatientButton).toBeEnabled();
158
+
159
+ await user.click(admitPatientButton);
160
+ expect(mockedAdmitPatient).toHaveBeenCalledWith(expect.any(Object), 'ADMIT', 'mock-visit');
161
+ });
162
+ it('should have warning when patient has a pending admission request', async () => {
163
+ mockedUseInpatientRequestByPatients.mockReturnValueOnce({
164
+ inpatientRequests: mockInpatientRequests,
165
+ hasMore: false,
166
+ loadMore: jest.fn(),
167
+ isValidating: false,
168
+ isLoading: false,
169
+ error: undefined,
170
+ mutate: jest.fn(),
171
+ totalCount: mockInpatientAdmissions.length,
172
+ nextUri: null,
173
+ });
174
+ const user = userEvent.setup();
175
+ renderCreateAdmissionEncounterWorkspace(mockPatientAlice.uuid);
176
+ expect(screen.getByText(mockPatientAlice.person?.preferredName?.display)).toBeInTheDocument();
177
+ expect(
178
+ screen.getByText(
179
+ 'Patient already has a pending admission request to location ' + mockLocationInpatientWard.display,
180
+ ),
181
+ ).toBeInTheDocument();
182
+ const admitPatientButton = screen.getByRole('button', { name: /admit patient/i });
183
+ expect(admitPatientButton).toBeEnabled();
184
+
185
+ await user.click(admitPatientButton);
186
+ expect(mockedAdmitPatient).toHaveBeenCalledWith(expect.any(Object), 'ADMIT', 'mock-visit');
187
+ });
188
+
189
+ it('should have warning when patient is already admitted elsewhere', async () => {
190
+ mockedUseInpatientAdmissionByPatients.mockReturnValueOnce({
191
+ data: [{ ...mockInpatientAdmissions[0], currentInpatientLocation: mockLocationMosoriot }],
192
+ hasMore: false,
193
+ loadMore: jest.fn(),
194
+ isValidating: false,
195
+ isLoading: false,
196
+ error: undefined,
197
+ mutate: jest.fn(),
198
+ totalCount: mockInpatientAdmissions.length,
199
+ nextUri: null,
200
+ });
201
+ const user = userEvent.setup();
202
+ renderCreateAdmissionEncounterWorkspace(mockPatientAlice.uuid);
203
+ expect(screen.getByText(mockPatientAlice.person?.preferredName?.display)).toBeInTheDocument();
204
+ expect(screen.getByText('Patient currently admitted to ' + mockLocationMosoriot.display)).toBeInTheDocument();
205
+ const admitPatientButton = screen.getByRole('button', { name: /transfer patient/i });
206
+ expect(admitPatientButton).toBeEnabled();
207
+
208
+ await user.click(admitPatientButton);
209
+ expect(mockedAdmitPatient).toHaveBeenCalledWith(expect.any(Object), 'TRANSFER', 'mock-visit');
210
+ });
211
+
212
+ it('should disable admit patient button when patient is already admitted to current location', () => {
213
+ mockedUseInpatientAdmissionByPatients.mockReturnValueOnce({
214
+ data: mockInpatientAdmissions,
215
+ hasMore: false,
216
+ loadMore: jest.fn(),
217
+ isValidating: false,
218
+ isLoading: false,
219
+ error: undefined,
220
+ mutate: jest.fn(),
221
+ totalCount: mockInpatientAdmissions.length,
222
+ nextUri: null,
223
+ });
224
+ renderCreateAdmissionEncounterWorkspace(mockPatientAlice.uuid);
225
+ expect(screen.getByText(mockPatientAlice.person?.preferredName?.display)).toBeInTheDocument();
226
+ expect(screen.getByText('Patient already admitted to current location')).toBeInTheDocument();
227
+ expect(screen.getByRole('button', { name: /admit patient/i })).toBeDisabled();
228
+ });
229
+ });
230
+
231
+ function renderCreateAdmissionEncounterWorkspace(patentUuid: string) {
232
+ renderWithSwr(
233
+ <CreateAdmissionEncounterWorkspace
234
+ patientUuid={patentUuid}
235
+ closeWorkspace={jest.fn()}
236
+ promptBeforeClosing={jest.fn()}
237
+ closeWorkspaceWithSavedChanges={jest.fn()}
238
+ setTitle={jest.fn()}
239
+ />,
240
+ );
241
+ }
@@ -0,0 +1,152 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, InlineNotification, SkeletonText } from '@carbon/react';
4
+ import { ArrowLeftIcon, type DefaultWorkspaceProps, useVisit } from '@openmrs/esm-framework';
5
+ import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
6
+ import { useInpatientAdmissionByPatients } from '../../hooks/useInpatientAdmissionByPatients';
7
+ import { useInpatientRequestByPatients } from '../../hooks/useInpatientRequestByPatients';
8
+ import useRestPatient from '../../hooks/useRestPatient';
9
+ import useWardLocation from '../../hooks/useWardLocation';
10
+ import type { Bed, WardPatient } from '../../types';
11
+ import AdmitPatientButton from '../admit-patient-button.component';
12
+ import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
13
+
14
+ export interface CreateAdmissionEncounterWorkspaceProps {
15
+ patientUuid: string;
16
+ handleReturnToSearchList?: () => void;
17
+ }
18
+
19
+ /**
20
+ * This is the workspace that opens when clicking on a search result
21
+ * from the workspace triggered by the "Add patient to ward" button.
22
+ * It directly admits them to the current ward locations
23
+ */
24
+ const CreateAdmissionEncounterWorkspace: React.FC<CreateAdmissionEncounterWorkspaceProps & DefaultWorkspaceProps> = ({
25
+ patientUuid,
26
+ handleReturnToSearchList,
27
+ closeWorkspaceWithSavedChanges,
28
+ }) => {
29
+ const { location } = useWardLocation();
30
+ const { patient, isLoading: isLoadingPatient, error: errorLoadingPatient } = useRestPatient(patientUuid);
31
+ const { activeVisit, isLoading: isLoadingVisit, error: errorLoadingVisit } = useVisit(patientUuid);
32
+ const { t } = useTranslation();
33
+ const { data: bedData, isLoading: isLoadingBed, error: errorLoadingBed } = useAssignedBedByPatient(patientUuid);
34
+ const {
35
+ data: inpatientAdmissions,
36
+ isLoading: isLoadingInpatientAdmission,
37
+ error: errorInpatientAdmission,
38
+ } = useInpatientAdmissionByPatients([patientUuid]);
39
+ const {
40
+ inpatientRequests,
41
+ isLoading: isLoadingInpatientRequest,
42
+ error: errorInpatientRequests,
43
+ } = useInpatientRequestByPatients([patientUuid]);
44
+
45
+ const isLoading =
46
+ isLoadingPatient || isLoadingVisit || isLoadingBed || isLoadingInpatientAdmission || isLoadingInpatientRequest;
47
+ const hasError =
48
+ errorLoadingPatient || errorLoadingVisit || errorLoadingBed || errorInpatientAdmission || errorInpatientRequests;
49
+
50
+ if (isLoading) {
51
+ return <SkeletonText />;
52
+ } else if (hasError) {
53
+ return (
54
+ <div>
55
+ <InlineNotification
56
+ kind="error"
57
+ lowContrast={true}
58
+ title={t('errorLoadingPatientInfo', 'Error loading patient info')}
59
+ />
60
+ <Button
61
+ kind="ghost"
62
+ renderIcon={(props) => <ArrowLeftIcon size={24} {...props} />}
63
+ iconDescription={t('backToSearchResults', 'Back to search results')}
64
+ size="sm"
65
+ onClick={() => handleReturnToSearchList?.()}>
66
+ <span>{t('backToSearchResults', 'Back to search results')}</span>
67
+ </Button>
68
+ </div>
69
+ );
70
+ } else {
71
+ const assignedBedDetail = bedData.data.results[0];
72
+ const isAssignedBedAtCurrentLocation = assignedBedDetail?.physicalLocation?.uuid == location.uuid;
73
+ const isAdmittedToCurrentLocation = inpatientAdmissions[0]?.currentInpatientLocation?.uuid == location.uuid;
74
+ const isAdmittedToOtherLocation = inpatientAdmissions[0] && !isAdmittedToCurrentLocation;
75
+
76
+ const wardPatient: WardPatient = {
77
+ patient,
78
+ visit: activeVisit,
79
+ bed: isAssignedBedAtCurrentLocation
80
+ ? ({
81
+ id: assignedBedDetail.bedId,
82
+ bedNumber: assignedBedDetail.bedNumber,
83
+ bedType: assignedBedDetail.bedType,
84
+ } as Bed)
85
+ : null,
86
+ inpatientAdmission: inpatientAdmissions[0],
87
+ inpatientRequest: null,
88
+ };
89
+ return (
90
+ <div>
91
+ <WardPatientWorkspaceBanner wardPatient={wardPatient} />
92
+ {activeVisit ? (
93
+ <div>
94
+ {isAdmittedToCurrentLocation && (
95
+ <InlineNotification
96
+ kind="warning"
97
+ lowContrast={true}
98
+ hideCloseButton={true}
99
+ title={t('patientAlreadyAdmittedToCurrentLocation', 'Patient already admitted to current location')}
100
+ />
101
+ )}
102
+ {isAdmittedToOtherLocation && (
103
+ <InlineNotification
104
+ kind="warning"
105
+ lowContrast={true}
106
+ hideCloseButton={true}
107
+ title={t('patientCurrentlyAdmittedToWardLocation', 'Patient currently admitted to {{wardLocation}}', {
108
+ wardLocation: inpatientAdmissions[0].currentInpatientLocation.display,
109
+ })}
110
+ />
111
+ )}
112
+ {inpatientRequests[0] && (
113
+ <InlineNotification
114
+ kind="warning"
115
+ lowContrast={true}
116
+ hideCloseButton={true}
117
+ title={t(
118
+ 'patientHasPendingAdmissionRequest',
119
+ 'Patient already has a pending admission request to location {{location}}',
120
+ {
121
+ location: inpatientRequests[0].dispositionLocation.display,
122
+ },
123
+ )}
124
+ />
125
+ )}
126
+ <AdmitPatientButton
127
+ wardPatient={wardPatient}
128
+ dispositionType={inpatientAdmissions[0] ? 'TRANSFER' : 'ADMIT'}
129
+ onAdmitPatientSuccess={() => closeWorkspaceWithSavedChanges()}
130
+ disabled={isAdmittedToCurrentLocation}
131
+ />
132
+ </div>
133
+ ) : (
134
+ <div>
135
+ {/* TODO: This is a placeholder, and will likely change with ongoing designs with RDE */}
136
+ {t('patienthasNoActiveVisit', 'Patient has no active visit')}
137
+ </div>
138
+ )}
139
+ <Button
140
+ kind="ghost"
141
+ renderIcon={(props) => <ArrowLeftIcon size={24} {...props} />}
142
+ iconDescription={t('backToSearchResults', 'Back to search results')}
143
+ size="sm"
144
+ onClick={() => handleReturnToSearchList?.()}>
145
+ <span>{t('backToSearchResults', 'Back to search results')}</span>
146
+ </Button>
147
+ </div>
148
+ );
149
+ }
150
+ };
151
+
152
+ export default CreateAdmissionEncounterWorkspace;
@@ -0,0 +1,23 @@
1
+ import { ActionMenuButton, launchWorkspace } from '@openmrs/esm-framework';
2
+ import React from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { Exit } from '@carbon/react/icons';
5
+
6
+ const DischargeIcon = (props) => <Exit {...props} />;
7
+
8
+ export default function PatientDischargeSideRailIcon() {
9
+ const { t } = useTranslation();
10
+ const handler = () => {
11
+ launchWorkspace('patient-care-discharge-workspace');
12
+ };
13
+
14
+ return (
15
+ <ActionMenuButton
16
+ getIcon={DischargeIcon}
17
+ label={t('discharge', 'Discharge')}
18
+ iconDescription={t('discharge', 'Discharge')}
19
+ handler={handler}
20
+ type="ward-patient-discharge"
21
+ />
22
+ );
23
+ }
@@ -0,0 +1,123 @@
1
+ import {
2
+ type Encounter,
3
+ openmrsFetch,
4
+ type OpenmrsResource,
5
+ restBaseUrl,
6
+ showSnackbar,
7
+ useAppContext,
8
+ useSession,
9
+ type Visit,
10
+ } from '@openmrs/esm-framework';
11
+ import { useTranslation } from 'react-i18next';
12
+ import { type WardPatient } from '../../types';
13
+
14
+ export function removePatientFromBed(bedId: number, patientUuid: string) {
15
+ return openmrsFetch(`${restBaseUrl}/beds/${bedId}?patientUuid=${patientUuid}`, {
16
+ method: 'DELETE',
17
+ });
18
+ }
19
+
20
+ const createDischargeEncounterPayload = (
21
+ patientUuid: string,
22
+ encounterType: OpenmrsResource,
23
+ location: OpenmrsResource,
24
+ currentProvider: OpenmrsResource,
25
+ visitUuid: string,
26
+ clinicianEncounterRole: OpenmrsResource,
27
+ ) => {
28
+ const encounterPayload = {
29
+ patient: patientUuid,
30
+ encounterType,
31
+ location: location?.uuid,
32
+ encounterProviders: [
33
+ {
34
+ provider: currentProvider?.uuid,
35
+ encounterRole: clinicianEncounterRole?.uuid,
36
+ },
37
+ ],
38
+ obs: [],
39
+ visit: visitUuid,
40
+ };
41
+ return encounterPayload;
42
+ };
43
+
44
+ const createDischargeEncounter = (encounterPayload: any) => {
45
+ return openmrsFetch(`${restBaseUrl}/encounter`, {
46
+ method: 'POST',
47
+ body: encounterPayload,
48
+ headers: { 'Content-Type': 'application/json' },
49
+ });
50
+ };
51
+
52
+ /**
53
+ * Custom hook for handling patient discharge operations
54
+ *
55
+ * This hook provides functionality to discharge a patient by:
56
+ * 1. Creating a discharge encounter
57
+ * 2. Removing the patient from their bed (if applicable)
58
+ * 3. Updating the ward patient group details
59
+ *
60
+ * @returns {Object} An object containing the handleDischarge function
61
+ * @property {Function} handleDischarge - Function to handle the patient discharge process
62
+ */
63
+ export const usePatientDischarge = () => {
64
+ const { t } = useTranslation();
65
+ const { wardPatientGroupDetails } =
66
+ useAppContext<{ wardPatientGroupDetails: { mutate: () => void } }>('ward-view-context') ?? {};
67
+ const session = useSession();
68
+
69
+ /**
70
+ * Handles the patient discharge process
71
+ *
72
+ * @param {Encounter} encounter - The current encounter
73
+ * @param {WardPatient} wardPatient - The ward patient information
74
+ * @param {Record<string, unknown>} emrConfiguration - EMR configuration containing encounter types and roles
75
+ * @param {Visit} visit - The current visit
76
+ * @returns {Promise<void>} A promise that resolves when the discharge process is complete
77
+ */
78
+ const handleDischarge = async (
79
+ encounter: Encounter,
80
+ wardPatient: WardPatient,
81
+ emrConfiguration: Record<string, unknown>,
82
+ visit: Visit,
83
+ ) => {
84
+ try {
85
+ const encounterPayload = createDischargeEncounterPayload(
86
+ wardPatient.patient.uuid,
87
+ emrConfiguration.exitFromInpatientEncounterType as OpenmrsResource,
88
+ session?.sessionLocation as OpenmrsResource,
89
+ session?.currentProvider as OpenmrsResource,
90
+ visit.uuid,
91
+ emrConfiguration.clinicianEncounterRole as OpenmrsResource,
92
+ );
93
+
94
+ const dischargeResponse = await createDischargeEncounter(encounterPayload);
95
+
96
+ if (!dischargeResponse?.ok) {
97
+ throw new Error('Failed to create discharge encounter');
98
+ }
99
+
100
+ if (wardPatient?.bed?.id) {
101
+ const bedRemovalResponse = await removePatientFromBed(wardPatient.bed.id, wardPatient?.patient?.uuid);
102
+ if (!bedRemovalResponse?.ok) {
103
+ throw new Error('Failed to remove patient from bed');
104
+ }
105
+ }
106
+
107
+ showSnackbar({
108
+ title: t('patientWasDischarged', 'Patient was discharged'),
109
+ kind: 'success',
110
+ });
111
+ } catch (err) {
112
+ showSnackbar({
113
+ title: t('errorDischargingPatient', 'Error discharging patient'),
114
+ subtitle: err instanceof Error ? err.message : 'Unknown error occurred',
115
+ kind: 'error',
116
+ });
117
+ } finally {
118
+ wardPatientGroupDetails?.mutate();
119
+ }
120
+ };
121
+
122
+ return { handleDischarge };
123
+ };
@@ -0,0 +1,101 @@
1
+ import React, { useMemo } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { InlineLoading, InlineNotification } from '@carbon/react';
4
+ import {
5
+ type DefaultWorkspaceProps,
6
+ type Encounter,
7
+ ExtensionSlot,
8
+ useEmrConfiguration,
9
+ usePatient,
10
+ } from '@openmrs/esm-framework';
11
+ import { usePatientDischarge } from './patient-discharge.resource';
12
+ import { type WardPatient } from '../../types';
13
+
14
+ type PatientDischargeWorkspaceProps = DefaultWorkspaceProps & {
15
+ readonly patientUuid: string;
16
+ readonly wardPatient: WardPatient;
17
+ readonly formUuid: string;
18
+ readonly dischargePatientOnSuccesfullSubmission?: boolean;
19
+ };
20
+
21
+ export function PatientDischargeWorkspace(props: PatientDischargeWorkspaceProps) {
22
+ const { t } = useTranslation();
23
+ const {
24
+ patientUuid,
25
+ closeWorkspace,
26
+ closeWorkspaceWithSavedChanges,
27
+ wardPatient,
28
+ promptBeforeClosing,
29
+ formUuid,
30
+ dischargePatientOnSuccesfullSubmission = true,
31
+ } = props;
32
+ const { visit: currentVisit } = wardPatient ?? {};
33
+ const { patient, isLoading: isLoadingPatient, error: patientError } = usePatient(patientUuid);
34
+ const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
35
+
36
+ const { handleDischarge } = usePatientDischarge();
37
+
38
+ const state = useMemo<Record<string, unknown>>(
39
+ () => ({
40
+ view: 'form',
41
+ formUuid,
42
+ visitUuid: currentVisit?.uuid ?? null,
43
+ visitTypeUuid: currentVisit?.visitType?.uuid ?? null,
44
+ patientUuid: patientUuid ?? null,
45
+ patient,
46
+ encounterUuid: '',
47
+ closeWorkspaceWithSavedChanges,
48
+ closeWorkspace,
49
+ promptBeforeClosing,
50
+ handlePostResponse: (encounter: Encounter) => {
51
+ if (dischargePatientOnSuccesfullSubmission)
52
+ handleDischarge(encounter, wardPatient, emrConfiguration as Record<string, unknown>, currentVisit);
53
+ },
54
+ }),
55
+ [
56
+ patientUuid,
57
+ currentVisit,
58
+ patient,
59
+ closeWorkspace,
60
+ promptBeforeClosing,
61
+ emrConfiguration,
62
+ closeWorkspaceWithSavedChanges,
63
+ handleDischarge,
64
+ dischargePatientOnSuccesfullSubmission,
65
+ formUuid,
66
+ wardPatient,
67
+ ],
68
+ );
69
+
70
+ const isLoading = isLoadingPatient || isLoadingEmrConfiguration;
71
+ const error = patientError || errorFetchingEmrConfiguration;
72
+
73
+ if (isLoading) {
74
+ return <InlineLoading description={t('loading', 'Loading')} iconDescription={t('loading', 'Loading data...')} />;
75
+ }
76
+
77
+ if (error) {
78
+ return (
79
+ <InlineNotification
80
+ aria-label={t('error', 'Error')}
81
+ kind="error"
82
+ onClose={() => {}}
83
+ onCloseButtonClick={() => {}}
84
+ statusIconDescription="notification"
85
+ subtitle={t('errorLoadingPatientWorkspace', 'Error loading patient workspace {{errorMessage}}', {
86
+ errorMessage: error?.message,
87
+ })}
88
+ title={t('error', 'Error')}
89
+ />
90
+ );
91
+ }
92
+
93
+ return (
94
+ <div>
95
+ {/* <pre>{JSON.stringify(currentVisit, null, 2)}</pre> */}
96
+ {patient && <ExtensionSlot name="form-widget-slot" state={state} />}
97
+ </div>
98
+ );
99
+ }
100
+
101
+ export default PatientDischargeWorkspace;
@@ -1,11 +1,10 @@
1
1
  import React, { useCallback, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
2
3
  import { Button, ButtonSet, InlineNotification } from '@carbon/react';
3
4
  import { Exit } from '@carbon/react/icons';
4
- import { useTranslation } from 'react-i18next';
5
- import { ExtensionSlot, showSnackbar, useAppContext, useSession } from '@openmrs/esm-framework';
5
+ import { ExtensionSlot, showSnackbar, useAppContext } from '@openmrs/esm-framework';
6
6
  import { type WardPatientWorkspaceProps, type WardViewContext } from '../../types';
7
7
  import { removePatientFromBed, useCreateEncounter } from '../../ward.resource';
8
- import useWardLocation from '../../hooks/useWardLocation';
9
8
  import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
10
9
  import styles from './patient-discharge.scss';
11
10
 
@@ -13,8 +12,6 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
13
12
  const { wardPatient, closeWorkspaceWithSavedChanges } = props;
14
13
  const { t } = useTranslation();
15
14
  const [isSubmitting, setIsSubmitting] = useState(false);
16
- const { currentProvider } = useSession();
17
- const { location } = useWardLocation();
18
15
  const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
19
16
  useCreateEncounter();
20
17
  const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
@@ -22,7 +19,7 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
22
19
  const submitDischarge = useCallback(() => {
23
20
  setIsSubmitting(true);
24
21
 
25
- createEncounter(wardPatient?.patient, emrConfiguration.exitFromInpatientEncounterType)
22
+ createEncounter(wardPatient?.patient, emrConfiguration.exitFromInpatientEncounterType, wardPatient?.visit.uuid)
26
23
  .then((response) => {
27
24
  if (response?.ok) {
28
25
  if (wardPatient?.bed?.id) {
@@ -51,17 +48,11 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
51
48
  closeWorkspaceWithSavedChanges();
52
49
  wardPatientGroupDetails.mutate();
53
50
  });
54
- }, [
55
- createEncounter,
56
- wardPatient?.patient,
57
- wardPatient.bed.id,
58
- emrConfiguration,
59
- t,
60
- closeWorkspaceWithSavedChanges,
61
- wardPatientGroupDetails,
62
- ]);
51
+ }, [createEncounter, wardPatient, emrConfiguration, t, closeWorkspaceWithSavedChanges, wardPatientGroupDetails]);
63
52
 
64
53
  if (!wardPatientGroupDetails) return <></>;
54
+ if (!wardPatient?.visit) return <InlineNotification kind="error" title={t('noVisit', 'No visit found')} />;
55
+
65
56
  return (
66
57
  <div className={styles.workspaceContent}>
67
58
  <div className={styles.patientWorkspaceBanner}>