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

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 (350) 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/1899.js +1 -0
  12. package/dist/1899.js.map +1 -0
  13. package/dist/2146.js +1 -0
  14. package/dist/2372.js +1 -0
  15. package/dist/2372.js.map +1 -0
  16. package/dist/2470.js +1 -0
  17. package/dist/2470.js.map +1 -0
  18. package/dist/2499.js +2 -0
  19. package/dist/{372.js.LICENSE.txt → 2499.js.LICENSE.txt} +2 -2
  20. package/dist/2499.js.map +1 -0
  21. package/dist/2537.js +1 -0
  22. package/dist/2537.js.map +1 -0
  23. package/dist/2557.js +1 -0
  24. package/dist/2557.js.map +1 -0
  25. package/dist/2690.js +1 -0
  26. package/dist/2728.js +2 -0
  27. package/dist/{649.js.LICENSE.txt → 2728.js.LICENSE.txt} +2 -2
  28. package/dist/2728.js.map +1 -0
  29. package/dist/2775.js +2 -0
  30. package/dist/2775.js.LICENSE.txt +59 -0
  31. package/dist/2775.js.map +1 -0
  32. package/dist/2904.js +2 -0
  33. package/dist/2904.js.LICENSE.txt +15 -0
  34. package/dist/2904.js.map +1 -0
  35. package/dist/2913.js +2 -0
  36. package/dist/2913.js.map +1 -0
  37. package/dist/2932.js +1 -0
  38. package/dist/2932.js.map +1 -0
  39. package/dist/2941.js +1 -0
  40. package/dist/2941.js.map +1 -0
  41. package/dist/2948.js +1 -0
  42. package/dist/2948.js.map +1 -0
  43. package/dist/3099.js +1 -0
  44. package/dist/3103.js +1 -0
  45. package/dist/3103.js.map +1 -0
  46. package/dist/3296.js +2 -0
  47. package/dist/3296.js.LICENSE.txt +9 -0
  48. package/dist/3296.js.map +1 -0
  49. package/dist/3365.js +1 -0
  50. package/dist/3365.js.map +1 -0
  51. package/dist/3373.js +2 -0
  52. package/dist/3373.js.LICENSE.txt +5 -0
  53. package/dist/3373.js.map +1 -0
  54. package/dist/3399.js +1 -0
  55. package/dist/3399.js.map +1 -0
  56. package/dist/3413.js +1 -0
  57. package/dist/3413.js.map +1 -0
  58. package/dist/3584.js +1 -0
  59. package/dist/3737.js +1 -0
  60. package/dist/3737.js.map +1 -0
  61. package/dist/3982.js +1 -0
  62. package/dist/3982.js.map +1 -0
  63. package/dist/4041.js +2 -0
  64. package/dist/4041.js.map +1 -0
  65. package/dist/4055.js +1 -0
  66. package/dist/4132.js +1 -0
  67. package/dist/4300.js +1 -0
  68. package/dist/4335.js +1 -0
  69. package/dist/4430.js +2 -0
  70. package/dist/4430.js.LICENSE.txt +29 -0
  71. package/dist/4430.js.map +1 -0
  72. package/dist/4618.js +1 -0
  73. package/dist/4652.js +1 -0
  74. package/dist/4701.js +2 -0
  75. package/dist/4701.js.LICENSE.txt +9 -0
  76. package/dist/4701.js.map +1 -0
  77. package/dist/4944.js +1 -0
  78. package/dist/5173.js +1 -0
  79. package/dist/5241.js +1 -0
  80. package/dist/5442.js +1 -0
  81. package/dist/559.js +1 -1
  82. package/dist/559.js.map +1 -1
  83. package/dist/5661.js +1 -0
  84. package/dist/6012.js +2 -0
  85. package/dist/6012.js.LICENSE.txt +5 -0
  86. package/dist/6012.js.map +1 -0
  87. package/dist/6022.js +1 -0
  88. package/dist/6468.js +1 -0
  89. package/dist/6679.js +1 -0
  90. package/dist/6840.js +1 -0
  91. package/dist/6859.js +1 -0
  92. package/dist/7097.js +1 -0
  93. package/dist/7159.js +1 -0
  94. package/dist/7179.js +2 -0
  95. package/dist/7179.js.LICENSE.txt +9 -0
  96. package/dist/7179.js.map +1 -0
  97. package/dist/723.js +1 -0
  98. package/dist/7232.js +2 -0
  99. package/dist/7232.js.LICENSE.txt +9 -0
  100. package/dist/7232.js.map +1 -0
  101. package/dist/7524.js +1 -0
  102. package/dist/7524.js.map +1 -0
  103. package/dist/7617.js +1 -0
  104. package/dist/7661.js +1 -0
  105. package/dist/7661.js.map +1 -0
  106. package/dist/7886.js +1 -0
  107. package/dist/7886.js.map +1 -0
  108. package/dist/795.js +1 -0
  109. package/dist/8163.js +1 -0
  110. package/dist/8205.js +1 -0
  111. package/dist/8205.js.map +1 -0
  112. package/dist/8349.js +1 -0
  113. package/dist/8501.js +1 -0
  114. package/dist/8501.js.map +1 -0
  115. package/dist/8522.js +1 -0
  116. package/dist/8522.js.map +1 -0
  117. package/dist/8618.js +1 -0
  118. package/dist/8622.js +1 -0
  119. package/dist/8622.js.map +1 -0
  120. package/dist/89.js +1 -0
  121. package/dist/89.js.map +1 -0
  122. package/dist/890.js +1 -0
  123. package/dist/9045.js +1 -0
  124. package/dist/9045.js.map +1 -0
  125. package/dist/9117.js +1 -0
  126. package/dist/9117.js.map +1 -0
  127. package/dist/9214.js +1 -0
  128. package/dist/9538.js +1 -0
  129. package/dist/9569.js +1 -0
  130. package/dist/986.js +1 -0
  131. package/dist/9876.js +2 -0
  132. package/dist/9876.js.LICENSE.txt +9 -0
  133. package/dist/9876.js.map +1 -0
  134. package/dist/9879.js +1 -0
  135. package/dist/9880.js +1 -0
  136. package/dist/9880.js.map +1 -0
  137. package/dist/9895.js +1 -0
  138. package/dist/9900.js +1 -0
  139. package/dist/9913.js +1 -0
  140. package/dist/kenyaemr-esm-ward-app.js +1 -1
  141. package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +1457 -237
  142. package/dist/kenyaemr-esm-ward-app.js.map +1 -1
  143. package/dist/main.js +1 -1
  144. package/dist/main.js.LICENSE.txt +0 -35
  145. package/dist/main.js.map +1 -1
  146. package/dist/routes.json +1 -1
  147. package/mock.tsx +15 -2
  148. package/package.json +10 -5
  149. package/src/beds/{empty-bed-skeleton.tsx → empty-bed-skeleton.component.tsx} +2 -2
  150. package/src/config-schema.ts +48 -0
  151. package/src/declarations.d.ts +8 -0
  152. package/src/hooks/useAdmissionLocation.ts +22 -1
  153. package/src/hooks/useInpatientAdmission.ts +12 -8
  154. package/src/hooks/useInpatientAdmissionByPatients.ts +29 -0
  155. package/src/hooks/useInpatientRequest.ts +3 -0
  156. package/src/hooks/useInpatientRequestByPatients.ts +34 -0
  157. package/src/hooks/useIpdDischargeEncounter.ts +137 -0
  158. package/src/hooks/usePatientPendingOrders.ts +1 -1
  159. package/src/hooks/useRestPatient.ts +11 -3
  160. package/src/hooks/useWardLocation.test.ts +1 -1
  161. package/src/hooks/useWardLocation.ts +15 -2
  162. package/src/hooks/useWardPatientGrouping.ts +60 -7
  163. package/src/index.ts +24 -4
  164. package/src/location-selector/location-selector.component.tsx +38 -5
  165. package/src/root.component.tsx +2 -2
  166. package/src/routes.json +60 -26
  167. package/src/types/index.ts +17 -6
  168. package/src/ward-patient-card/card-rows/admission-request-note-row.component.tsx +1 -1
  169. package/src/ward-patient-card/card-rows/coded-obs-tags-row.component.tsx +4 -4
  170. package/src/ward-patient-card/card-rows/mother-child-row.component.tsx +6 -6
  171. package/src/ward-patient-card/card-rows/pending-items-row.component.tsx +2 -3
  172. package/src/ward-patient-card/row-elements/{ward-patient-coded-obs-tags.tsx → ward-patient-coded-obs-tags.component.tsx} +5 -5
  173. package/src/ward-patient-card/row-elements/{ward-patient-header-address.tsx → ward-patient-header-address.component.tsx} +2 -2
  174. package/src/ward-patient-card/row-elements/{ward-patient-identifier.tsx → ward-patient-identifier.component.tsx} +7 -1
  175. package/src/ward-patient-card/row-elements/ward-patient-identifier.scss +3 -0
  176. package/src/ward-patient-card/row-elements/{ward-patient-obs.tsx → ward-patient-obs.component.tsx} +5 -5
  177. package/src/ward-patient-card/row-elements/{ward-patient-pending-transfer.tsx → ward-patient-pending-transfer.component.tsx} +3 -5
  178. package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.component.tsx +73 -0
  179. package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.component.tsx +29 -0
  180. package/src/ward-patient-card/ward-patient-card.component.tsx +5 -5
  181. package/src/ward-patient-card/ward-patient-card.scss +2 -6
  182. package/src/ward-patients/admitted-patients.tsx +218 -0
  183. package/src/ward-patients/awaiting-admission-patients.tsx +158 -0
  184. package/src/ward-patients/discharge-in-patients.tsx +183 -0
  185. package/src/ward-patients/discharge-patients.tsx +129 -0
  186. package/src/ward-patients/patient-cells.tsx +75 -0
  187. package/src/ward-patients/table-state-components.tsx +40 -0
  188. package/src/ward-patients/ward-patient.scss +24 -0
  189. package/src/ward-patients/ward-patients-table.tsx +38 -0
  190. package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +8 -8
  191. package/src/ward-view/default-ward/default-ward-pending-patients.component.tsx +3 -3
  192. package/src/ward-view/default-ward/default-ward-view.component.tsx +31 -6
  193. package/src/ward-view/linelist-wards/Filters.tsx +25 -0
  194. package/src/ward-view/linelist-wards/Header.tsx +27 -0
  195. package/src/ward-view/linelist-wards/LineListTable.tsx +147 -0
  196. package/src/ward-view/linelist-wards/Metrics.tsx +21 -0
  197. package/src/ward-view/linelist-wards/WardsLineList.tsx +29 -0
  198. package/src/ward-view/linelist-wards/linelist-wards.scss +100 -0
  199. package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +8 -8
  200. package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +2 -2
  201. package/src/ward-view/materal-ward/maternal-ward-patient-card.test.tsx +1 -1
  202. package/src/ward-view/materal-ward/maternal-ward-pending-patients.component.tsx +1 -1
  203. package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +4 -4
  204. package/src/ward-view/ward-view-content-wrapper.tsx +36 -0
  205. package/src/ward-view/ward-view.resource.ts +26 -8
  206. package/src/ward-view/ward-view.scss +15 -8
  207. package/src/ward-view/ward-view.test.tsx +8 -8
  208. package/src/ward-view/ward.component.tsx +2 -2
  209. package/src/ward-view-header/admission-requests-bar.component.tsx +18 -8
  210. package/src/ward-view-header/admission-requests-bar.test.tsx +3 -3
  211. package/src/ward-view-header/ward-metric.component.tsx +2 -3
  212. package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +12 -14
  213. package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +5 -5
  214. package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +1 -1
  215. package/src/ward-workspace/admission-request-workspace/admission-requests-action-button.extension.tsx +18 -0
  216. package/src/ward-workspace/admission-request-workspace/admission-requests-context.ts +20 -0
  217. package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +7 -6
  218. package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +15 -25
  219. package/src/ward-workspace/admit-patient-button.component.tsx +41 -18
  220. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +14 -16
  221. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +2 -2
  222. package/src/ward-workspace/bed-selector.component.tsx +1 -1
  223. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.test.tsx +1 -1
  224. package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.workspace.tsx +4 -6
  225. package/src/ward-workspace/create-admission-encounter/create-admission-encounter-action-button.extension.tsx +46 -0
  226. package/src/ward-workspace/create-admission-encounter/create-admission-encounter.test.tsx +241 -0
  227. package/src/ward-workspace/create-admission-encounter/create-admission-encounter.workspace.tsx +152 -0
  228. package/src/ward-workspace/kenya-emr-patient-discharge/discharge-workspace-siderail.component.tsx +23 -0
  229. package/src/ward-workspace/kenya-emr-patient-discharge/patient-discharge.resource.tsx +123 -0
  230. package/src/ward-workspace/kenya-emr-patient-discharge/patient-discharge.workspace.tsx +101 -0
  231. package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +6 -15
  232. package/src/ward-workspace/patient-transfer-bed-swap/{patient-transfer-request-form.component.tsx → patient-admit-or-transfer-request-form.component.tsx} +56 -37
  233. package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +13 -3
  234. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +11 -5
  235. package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.scss +5 -0
  236. package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.workspace.tsx +20 -6
  237. package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +2 -1
  238. package/src/ward-workspace/ward-patient-notes/history/note.component.tsx +3 -3
  239. package/src/ward.resource.ts +9 -3
  240. package/translations/am.json +123 -0
  241. package/translations/ar.json +123 -0
  242. package/translations/ar_SY.json +123 -0
  243. package/translations/bn.json +123 -0
  244. package/translations/de.json +123 -0
  245. package/translations/en.json +31 -3
  246. package/translations/en_US.json +123 -0
  247. package/translations/es.json +123 -0
  248. package/translations/es_MX.json +123 -0
  249. package/translations/fr.json +123 -0
  250. package/translations/he.json +123 -0
  251. package/translations/hi.json +123 -0
  252. package/translations/hi_IN.json +123 -0
  253. package/translations/id.json +123 -0
  254. package/translations/it.json +123 -0
  255. package/translations/ka.json +123 -0
  256. package/translations/km.json +123 -0
  257. package/translations/ku.json +123 -0
  258. package/translations/ky.json +123 -0
  259. package/translations/lg.json +123 -0
  260. package/translations/ne.json +123 -0
  261. package/translations/pl.json +123 -0
  262. package/translations/pt.json +123 -0
  263. package/translations/pt_BR.json +123 -0
  264. package/translations/qu.json +123 -0
  265. package/translations/ro_RO.json +123 -0
  266. package/translations/ru_RU.json +123 -0
  267. package/translations/si.json +123 -0
  268. package/translations/sw.json +123 -0
  269. package/translations/sw_KE.json +123 -0
  270. package/translations/tr.json +123 -0
  271. package/translations/tr_TR.json +123 -0
  272. package/translations/uk.json +123 -0
  273. package/translations/uz.json +123 -0
  274. package/translations/uz@Latn.json +123 -0
  275. package/translations/uz_UZ.json +123 -0
  276. package/translations/vi.json +123 -0
  277. package/translations/zh.json +123 -0
  278. package/translations/zh_CN.json +123 -0
  279. package/dist/109.js +0 -1
  280. package/dist/109.js.map +0 -1
  281. package/dist/124.js +0 -1
  282. package/dist/124.js.map +0 -1
  283. package/dist/125.js +0 -1
  284. package/dist/125.js.map +0 -1
  285. package/dist/126.js +0 -1
  286. package/dist/126.js.map +0 -1
  287. package/dist/130.js +0 -2
  288. package/dist/130.js.LICENSE.txt +0 -5
  289. package/dist/130.js.map +0 -1
  290. package/dist/146.js +0 -1
  291. package/dist/146.js.map +0 -1
  292. package/dist/15.js +0 -1
  293. package/dist/15.js.map +0 -1
  294. package/dist/325.js +0 -1
  295. package/dist/325.js.map +0 -1
  296. package/dist/348.js +0 -1
  297. package/dist/348.js.map +0 -1
  298. package/dist/362.js +0 -1
  299. package/dist/362.js.map +0 -1
  300. package/dist/372.js +0 -2
  301. package/dist/372.js.map +0 -1
  302. package/dist/443.js +0 -1
  303. package/dist/443.js.map +0 -1
  304. package/dist/471.js +0 -1
  305. package/dist/471.js.map +0 -1
  306. package/dist/481.js +0 -1
  307. package/dist/481.js.map +0 -1
  308. package/dist/53.js +0 -1
  309. package/dist/53.js.map +0 -1
  310. package/dist/574.js +0 -1
  311. package/dist/576.js +0 -1
  312. package/dist/576.js.map +0 -1
  313. package/dist/577.js +0 -1
  314. package/dist/577.js.map +0 -1
  315. package/dist/591.js +0 -2
  316. package/dist/591.js.map +0 -1
  317. package/dist/598.js +0 -1
  318. package/dist/598.js.map +0 -1
  319. package/dist/649.js +0 -2
  320. package/dist/649.js.map +0 -1
  321. package/dist/662.js +0 -1
  322. package/dist/662.js.map +0 -1
  323. package/dist/767.js +0 -1
  324. package/dist/767.js.map +0 -1
  325. package/dist/784.js +0 -2
  326. package/dist/784.js.map +0 -1
  327. package/dist/921.js +0 -1
  328. package/dist/921.js.map +0 -1
  329. package/dist/922.js +0 -1
  330. package/dist/922.js.map +0 -1
  331. package/dist/925.js +0 -2
  332. package/dist/925.js.LICENSE.txt +0 -40
  333. package/dist/925.js.map +0 -1
  334. package/dist/940.js +0 -1
  335. package/dist/940.js.map +0 -1
  336. package/dist/969.js +0 -1
  337. package/dist/969.js.map +0 -1
  338. package/dist/983.js +0 -1
  339. package/dist/983.js.map +0 -1
  340. package/package-lock.json +0 -5001
  341. package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.tsx +0 -22
  342. package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.tsx +0 -22
  343. /package/dist/{591.js.LICENSE.txt → 2913.js.LICENSE.txt} +0 -0
  344. /package/dist/{784.js.LICENSE.txt → 4041.js.LICENSE.txt} +0 -0
  345. /package/src/ward-patient-card/row-elements/{ward-patient-age.tsx → ward-patient-age.component.tsx} +0 -0
  346. /package/src/ward-patient-card/row-elements/{ward-patient-bed-number.tsx → ward-patient-bed-number.component.tsx} +0 -0
  347. /package/src/ward-patient-card/row-elements/{ward-patient-location.tsx → ward-patient-location.component.tsx} +0 -0
  348. /package/src/ward-patient-card/row-elements/{ward-patient-name.tsx → ward-patient-name.component.tsx} +0 -0
  349. /package/src/ward-patient-card/row-elements/{ward-patient-responsive-tooltip.tsx → ward-patient-responsive-tooltip.component.tsx} +0 -0
  350. /package/src/ward-patient-card/row-elements/{ward-patient-skeleton-text.tsx → ward-patient-skeleton-text.component.tsx} +0 -0
@@ -1,8 +1,8 @@
1
- import { getPatientName, useAppContext, launchWorkspaceGroup } from '@openmrs/esm-framework';
1
+ import { getPatientName, launchWorkspaceGroup } from '@openmrs/esm-framework';
2
+ import { getPatientChartStore } from '@openmrs/esm-patient-common-lib';
2
3
  import React, { type ReactNode } from 'react';
3
- import { type WardViewContext, type WardPatient } from '../types';
4
+ import { type WardPatient } from '../types';
4
5
  import styles from './ward-patient-card.scss';
5
- import { getPatientChartStore } from '@openmrs/esm-patient-common-lib';
6
6
 
7
7
  interface Props {
8
8
  children: ReactNode;
@@ -11,7 +11,6 @@ interface Props {
11
11
 
12
12
  const WardPatientCard: React.FC<Props> = ({ children, wardPatient }) => {
13
13
  const { patient } = wardPatient;
14
- const { WardPatientHeader } = useAppContext<WardViewContext>('ward-view-context') ?? {};
15
14
 
16
15
  return (
17
16
  <div className={styles.wardPatientCard}>
@@ -22,7 +21,8 @@ const WardPatientCard: React.FC<Props> = ({ children, wardPatient }) => {
22
21
  launchWorkspaceGroup('ward-patient', {
23
22
  state: {
24
23
  wardPatient,
25
- WardPatientHeader,
24
+ patient,
25
+ patientUuid: patient.uuid,
26
26
  },
27
27
  onWorkspaceGroupLaunch: () => {
28
28
  const store = getPatientChartStore();
@@ -6,13 +6,10 @@
6
6
  .wardPatientCard {
7
7
  @include type.type-style('body-compact-01');
8
8
  color: $text-02;
9
-
10
9
  display: flex;
11
10
  flex-wrap: wrap;
12
11
  align-items: center;
13
- gap: layout.$spacing-02;
14
12
  background-color: $ui-02;
15
-
16
13
  position: relative; // this allows positioning the button correctly
17
14
  }
18
15
 
@@ -114,11 +111,10 @@
114
111
 
115
112
  .wardPatientBedNumber {
116
113
  @include type.type-style('heading-compact-01');
117
- border-radius: 50%;
114
+ border-radius: 50vh;
118
115
  color: $ui-02;
119
116
  background-color: $color-blue-60-2;
120
- padding: layout.$spacing-04;
121
- width: layout.$spacing-04;
117
+ padding: layout.$spacing-04 layout.$spacing-03;
122
118
  height: layout.$spacing-04;
123
119
  display: flex;
124
120
  justify-content: center;
@@ -0,0 +1,218 @@
1
+ import {
2
+ DataTable,
3
+ DataTableSkeleton,
4
+ OverflowMenu,
5
+ OverflowMenuItem,
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableContainer,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ Pagination,
14
+ } from '@carbon/react';
15
+ import {
16
+ formatDatetime,
17
+ launchWorkspace,
18
+ type OpenmrsResource,
19
+ parseDate,
20
+ useAppContext,
21
+ useConfig,
22
+ usePagination,
23
+ } from '@openmrs/esm-framework';
24
+ import dayjs from 'dayjs';
25
+ import React, { useMemo, useState } from 'react';
26
+ import { useTranslation } from 'react-i18next';
27
+ import { type WardPatient, type WardViewContext } from '../types';
28
+ import { bedLayoutToBed, getOpenmrsId } from '../ward-view/ward-view.resource';
29
+ import { EmptyState } from './table-state-components';
30
+ import { usePaginationInfo } from '@openmrs/esm-patient-common-lib';
31
+ import { type WardConfigObject } from '../config-schema';
32
+ const AdmittedPatients = () => {
33
+ const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
34
+ const { bedLayouts, wardAdmittedPatientsWithBed, isLoading } = wardPatientGroupDetails ?? {};
35
+ const { t } = useTranslation();
36
+ const config = useConfig<WardConfigObject>();
37
+ const headers = [
38
+ { key: 'admissionDate', header: t('admissionDate', 'Admission Date') },
39
+ { key: 'idNumber', header: t('idNumber', 'ID Number') },
40
+ { key: 'name', header: t('name', 'Name') },
41
+ { key: 'gender', header: t('gender', 'Gender') },
42
+ { key: 'age', header: t('age', 'Age') },
43
+ { key: 'bedNumber', header: t('bedNumber', 'Bed Number') },
44
+ { key: 'daysAdmitted', header: t('daysInWard', 'Days In Ward') },
45
+ { key: 'action', header: t('action', 'Action') },
46
+ ];
47
+
48
+ const patients = useMemo(() => {
49
+ return (
50
+ bedLayouts
51
+ ?.map((bedLayout) => {
52
+ const { patients } = bedLayout;
53
+ const bed = bedLayoutToBed(bedLayout);
54
+ const wardPatients: WardPatient[] = patients.map((patient): WardPatient => {
55
+ const inpatientAdmission = wardAdmittedPatientsWithBed?.get(patient.uuid);
56
+ if (inpatientAdmission) {
57
+ const { patient, visit, currentInpatientRequest } = inpatientAdmission;
58
+ return { patient, visit, bed, inpatientAdmission, inpatientRequest: currentInpatientRequest || null };
59
+ } else {
60
+ // for some reason this patient is in a bed but not in the list of admitted patients, so we need to use the patient data from the bed endpoint
61
+ return {
62
+ patient: patient,
63
+ visit: null,
64
+ bed,
65
+ inpatientAdmission: null, // populate after BED-13
66
+ inpatientRequest: null,
67
+ };
68
+ }
69
+ });
70
+ return wardPatients;
71
+ })
72
+ ?.flat() ?? []
73
+ ).filter((pat) => {
74
+ const noteEncounter = pat?.visit?.encounters?.find(
75
+ (encounter) => encounter.encounterType?.uuid === config.doctorsnoteEncounterTypeUuid,
76
+ );
77
+ if (!noteEncounter) return true;
78
+ const obs = noteEncounter.obs.find((ob) => ob.concept.uuid === config.referralsConceptUuid);
79
+ if (!obs) return true;
80
+ const isDischargedIn = [config.referringToAnotherFacilityConceptUuid, config.dischargeHomeConceptUuid].includes(
81
+ (obs.value as OpenmrsResource).uuid,
82
+ );
83
+ return isDischargedIn === false;
84
+ });
85
+ }, [bedLayouts, wardAdmittedPatientsWithBed, config]);
86
+
87
+ const [pageSize, setPageSize] = useState(5);
88
+ const { paginated, results, totalPages, currentPage, goTo } = usePagination(patients, pageSize);
89
+ const { pageSizes } = usePaginationInfo(pageSize, totalPages, currentPage, results.length);
90
+ const tableRows = useMemo(() => {
91
+ return results.map((patient, index) => {
92
+ const { encounterAssigningToCurrentInpatientLocation } = patient.inpatientAdmission ?? {};
93
+
94
+ const admissionDate = encounterAssigningToCurrentInpatientLocation?.encounterDatetime
95
+ ? formatDatetime(parseDate(encounterAssigningToCurrentInpatientLocation!.encounterDatetime!))
96
+ : '--';
97
+ const encounterDate = encounterAssigningToCurrentInpatientLocation?.encounterDatetime;
98
+ const daysAdmitted =
99
+ encounterDate && dayjs(encounterDate).isValid()
100
+ ? Math.abs(dayjs().startOf('day').diff(dayjs(encounterDate).startOf('day'), 'days'))
101
+ : '--';
102
+
103
+ return {
104
+ id: patient.patient?.uuid ?? index,
105
+ admissionDate,
106
+ idNumber: getOpenmrsId(patient.patient?.identifiers ?? []) ?? '--',
107
+ name: patient.patient?.person?.display ?? '--',
108
+ gender: patient.patient?.person?.gender ?? '--',
109
+ age: patient.patient?.person?.age ?? '--',
110
+ bedNumber: patient.bed?.bedNumber ?? '--',
111
+ daysAdmitted,
112
+ action: (
113
+ <OverflowMenu size={'sm'} flipped>
114
+ <OverflowMenuItem
115
+ itemText={t('tranfer', 'Tranfer')}
116
+ onClick={() =>
117
+ launchWorkspace('patient-transfer-swap-workspace', {
118
+ workspaceTitle: 'Trasfer',
119
+ wardPatient: patient,
120
+ withContentSwitcher: false,
121
+ defaultTransfersection: 'transfer',
122
+ })
123
+ }
124
+ />
125
+ <OverflowMenuItem
126
+ itemText={t('bedSwap', 'Bed Swap')}
127
+ onClick={() =>
128
+ launchWorkspace('patient-transfer-swap-workspace', {
129
+ workspaceTitle: 'Bed Swap',
130
+ wardPatient: patient,
131
+ withContentSwitcher: false,
132
+ defaultTransfersection: 'bed-swap',
133
+ })
134
+ }
135
+ />
136
+ <OverflowMenuItem
137
+ itemText={t('dischargeIn', 'Discharge In')}
138
+ onClick={() => {
139
+ launchWorkspace('patient-discharge-workspace', {
140
+ wardPatient: patient,
141
+ patientUuid: patient.patient.uuid,
142
+ formUuid: config.doctorsNoteFormUuid,
143
+ workspaceTitle: t('doctorsNote', 'Doctors Note'),
144
+ dischargePatientOnSuccesfullSubmission: false,
145
+ });
146
+ }}
147
+ />
148
+ <OverflowMenuItem
149
+ itemText={t('discharge', 'Discharge')}
150
+ onClick={() => {
151
+ launchWorkspace('patient-discharge-workspace', {
152
+ wardPatient: patient,
153
+ patientUuid: patient.patient.uuid,
154
+ formUuid: config.inpatientDischargeFormUuid,
155
+ });
156
+ }}
157
+ />
158
+ </OverflowMenu>
159
+ ),
160
+ };
161
+ });
162
+ }, [results, config, t]);
163
+
164
+ if (isLoading) return <DataTableSkeleton />;
165
+ if (!patients.length)
166
+ return <EmptyState message={t('noAdmittedPatientsinCurrentward', 'No admitted patients in the current ward')} />;
167
+
168
+ return (
169
+ <DataTable rows={tableRows} headers={headers} isSortable useZebraStyles>
170
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps, getCellProps }) => (
171
+ <TableContainer>
172
+ <Table {...getTableProps()} aria-label="sample table">
173
+ <TableHead>
174
+ <TableRow>
175
+ {headers.map((header) => (
176
+ <TableHeader
177
+ key={header.key}
178
+ {...getHeaderProps({
179
+ header,
180
+ })}>
181
+ {header.header}
182
+ </TableHeader>
183
+ ))}
184
+ </TableRow>
185
+ </TableHead>
186
+ <TableBody>
187
+ {rows.map((row) => {
188
+ return (
189
+ <TableRow key={row.id} {...getRowProps({ row })}>
190
+ {row.cells.map((cell) => (
191
+ <TableCell key={cell.id} {...getCellProps({ cell })}>
192
+ {cell.value}
193
+ </TableCell>
194
+ ))}
195
+ </TableRow>
196
+ );
197
+ })}
198
+ </TableBody>
199
+ </Table>
200
+ {paginated && !isLoading && (
201
+ <Pagination
202
+ page={currentPage}
203
+ pageSize={pageSize}
204
+ pageSizes={pageSizes}
205
+ totalItems={(patients ?? []).length}
206
+ onChange={({ page, pageSize }) => {
207
+ goTo(page);
208
+ setPageSize(pageSize);
209
+ }}
210
+ />
211
+ )}
212
+ </TableContainer>
213
+ )}
214
+ </DataTable>
215
+ );
216
+ };
217
+
218
+ export default AdmittedPatients;
@@ -0,0 +1,158 @@
1
+ import {
2
+ DataTable,
3
+ DataTableSkeleton,
4
+ OverflowMenu,
5
+ OverflowMenuItem,
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableContainer,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ Pagination,
14
+ } from '@carbon/react';
15
+ import { formatDatetime, launchWorkspace, parseDate, useAppContext, usePagination } from '@openmrs/esm-framework';
16
+ import dayjs from 'dayjs';
17
+ import React, { useMemo, useState } from 'react';
18
+ import { useTranslation } from 'react-i18next';
19
+ import { type WardPatient, type WardPatientWorkspaceProps, type WardViewContext } from '../types';
20
+ import { getOpenmrsId } from '../ward-view/ward-view.resource';
21
+ import AdmitPatientButton from '../ward-workspace/admit-patient-button.component';
22
+ import { EmptyState, ErrorState } from './table-state-components';
23
+ import { usePaginationInfo } from '@openmrs/esm-patient-common-lib';
24
+
25
+ const AwaitingAdmissionPatients = () => {
26
+ const { t } = useTranslation();
27
+ const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
28
+ const { inpatientRequests, isLoading, error } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
29
+ const [pageSize, setPageSize] = useState(5);
30
+ const { paginated, results, totalPages, currentPage, goTo } = usePagination(inpatientRequests, pageSize);
31
+ const { pageSizes } = usePaginationInfo(pageSize, totalPages, currentPage, results.length);
32
+
33
+ const headers = [
34
+ { key: 'admissionDate', header: t('dateQueued', 'Date Queued') },
35
+ { key: 'idNumber', header: t('idNumber', 'ID Number') },
36
+ { key: 'name', header: t('name', 'Name') },
37
+ { key: 'gender', header: t('gender', 'Gender') },
38
+ { key: 'age', header: t('age', 'Age') },
39
+ { key: 'bedNumber', header: t('bedNumber', 'Bed Number') },
40
+ { key: 'daysAdmitted', header: t('durationOnWard', 'Days In Queue') },
41
+ { key: 'action', header: t('action', 'Action') },
42
+ ];
43
+
44
+ const launchPatientTransferForm = (wardPatient: WardPatient) => {
45
+ launchWorkspace<WardPatientWorkspaceProps>('patient-transfer-request-workspace', {
46
+ wardPatient,
47
+ });
48
+ };
49
+
50
+ const launchCancelAdmissionForm = (wardPatient: WardPatient) => {
51
+ launchWorkspace<WardPatientWorkspaceProps>('cancel-admission-request-workspace', {
52
+ wardPatient,
53
+ });
54
+ };
55
+ const tableRows = useMemo(() => {
56
+ return results?.map((request, index) => {
57
+ const admissionDate = request.dispositionEncounter?.encounterDatetime
58
+ ? formatDatetime(parseDate(request.dispositionEncounter?.encounterDatetime))
59
+ : '--';
60
+ const encounterDate = request.dispositionEncounter?.encounterDatetime;
61
+ const daysAdmitted =
62
+ encounterDate && dayjs(encounterDate).isValid()
63
+ ? Math.abs(dayjs().startOf('day').diff(dayjs(encounterDate).startOf('day'), 'days'))
64
+ : '--';
65
+ const wardPatient = {
66
+ patient: request.patient,
67
+ visit: request.visit,
68
+ bed: null,
69
+ inpatientRequest: request,
70
+ inpatientAdmission: null,
71
+ };
72
+ const isTransfer = wardPatient.inpatientRequest.dispositionType == 'TRANSFER';
73
+
74
+ return {
75
+ id: request?.patient?.uuid ?? index,
76
+ admissionDate,
77
+ idNumber: getOpenmrsId(request.patient?.identifiers ?? []) ?? '--',
78
+ name: request?.patient?.person?.display ?? '--',
79
+ gender: request?.patient?.person?.gender ?? '--',
80
+ age: request?.patient?.person?.age ?? '--',
81
+ bedNumber: '--',
82
+ daysAdmitted,
83
+ action: (
84
+ <OverflowMenu size={'sm'} flipped>
85
+ <OverflowMenuItem
86
+ itemText={
87
+ isTransfer ? t('transferElsewhere', 'Transfer elsewhere') : t('admitElsewhere', 'Admit elsewhere')
88
+ }
89
+ onClick={() => launchPatientTransferForm(wardPatient)}
90
+ />
91
+ <AdmitPatientButton
92
+ wardPatient={wardPatient}
93
+ dispositionType={wardPatient.inpatientRequest.dispositionType}
94
+ onAdmitPatientSuccess={() => {}}
95
+ component="menu"
96
+ />
97
+ <OverflowMenuItem itemText={t('cancel', 'Cancel')} onClick={() => launchCancelAdmissionForm(wardPatient)} />
98
+ </OverflowMenu>
99
+ ),
100
+ };
101
+ });
102
+ }, [results, t]);
103
+
104
+ if (isLoading) return <DataTableSkeleton />;
105
+ if (error) return <ErrorState error={error} />;
106
+ if (!inpatientRequests || !inpatientRequests.length)
107
+ return <EmptyState message={t('noPatientInAdmisionQueue', 'No patients in admission queue')} />;
108
+ return (
109
+ <DataTable rows={tableRows} headers={headers} isSortable useZebraStyles>
110
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps, getCellProps }) => (
111
+ <TableContainer>
112
+ <Table {...getTableProps()} aria-label="sample table">
113
+ <TableHead>
114
+ <TableRow>
115
+ {headers.map((header) => (
116
+ <TableHeader
117
+ key={header.key}
118
+ {...getHeaderProps({
119
+ header,
120
+ })}>
121
+ {header.header}
122
+ </TableHeader>
123
+ ))}
124
+ </TableRow>
125
+ </TableHead>
126
+ <TableBody>
127
+ {rows.map((row) => {
128
+ return (
129
+ <TableRow key={row.id} {...getRowProps({ row })}>
130
+ {row.cells.map((cell) => (
131
+ <TableCell key={cell.id} {...getCellProps({ cell })}>
132
+ {cell.value}
133
+ </TableCell>
134
+ ))}
135
+ </TableRow>
136
+ );
137
+ })}
138
+ </TableBody>
139
+ </Table>
140
+ {paginated && !isLoading && (
141
+ <Pagination
142
+ page={currentPage}
143
+ pageSize={pageSize}
144
+ pageSizes={pageSizes}
145
+ totalItems={(inpatientRequests ?? []).length}
146
+ onChange={({ page, pageSize }) => {
147
+ goTo(page);
148
+ setPageSize(pageSize);
149
+ }}
150
+ />
151
+ )}
152
+ </TableContainer>
153
+ )}
154
+ </DataTable>
155
+ );
156
+ };
157
+
158
+ export default AwaitingAdmissionPatients;
@@ -0,0 +1,183 @@
1
+ import {
2
+ OverflowMenu,
3
+ OverflowMenuItem,
4
+ DataTable,
5
+ TableContainer,
6
+ Table,
7
+ TableHead,
8
+ TableRow,
9
+ TableHeader,
10
+ TableBody,
11
+ TableCell,
12
+ Pagination,
13
+ } from '@carbon/react';
14
+ import React, { useMemo, useState } from 'react';
15
+ import { useTranslation } from 'react-i18next';
16
+ import { EmptyState } from './table-state-components';
17
+ import {
18
+ formatDatetime,
19
+ launchWorkspace,
20
+ type OpenmrsResource,
21
+ parseDate,
22
+ useAppContext,
23
+ useConfig,
24
+ usePagination,
25
+ } from '@openmrs/esm-framework';
26
+ import { type WardPatient, type WardViewContext } from '../types';
27
+ import { bedLayoutToBed, getOpenmrsId } from '../ward-view/ward-view.resource';
28
+ import dayjs from 'dayjs';
29
+ import { usePaginationInfo } from '@openmrs/esm-patient-common-lib';
30
+ import { type WardConfigObject } from '../config-schema';
31
+
32
+ const DischargeInPatients = () => {
33
+ const { t } = useTranslation();
34
+ const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
35
+ const { bedLayouts, wardAdmittedPatientsWithBed, isLoading } = wardPatientGroupDetails ?? {};
36
+ const config = useConfig<WardConfigObject>();
37
+ const headers = [
38
+ { key: 'admissionDate', header: t('admissionDate', 'Admission Date') },
39
+ { key: 'idNumber', header: t('idNumber', 'ID Number') },
40
+ { key: 'name', header: t('name', 'Name') },
41
+ { key: 'gender', header: t('gender', 'Gender') },
42
+ { key: 'age', header: t('age', 'Age') },
43
+ { key: 'bedNumber', header: t('bedNumber', 'Bed Number') },
44
+ { key: 'daysAdmitted', header: t('durationOnWard', 'Duration on Ward') },
45
+ { key: 'action', header: t('action', 'Action') },
46
+ ];
47
+
48
+ const patients = useMemo(() => {
49
+ return (
50
+ bedLayouts
51
+ ?.map((bedLayout) => {
52
+ const { patients } = bedLayout;
53
+ const bed = bedLayoutToBed(bedLayout);
54
+ const wardPatients: WardPatient[] = patients.map((patient): WardPatient => {
55
+ const inpatientAdmission = wardAdmittedPatientsWithBed?.get(patient.uuid);
56
+ if (inpatientAdmission) {
57
+ const { patient, visit, currentInpatientRequest } = inpatientAdmission;
58
+ return { patient, visit, bed, inpatientAdmission, inpatientRequest: currentInpatientRequest || null };
59
+ } else {
60
+ // for some reason this patient is in a bed but not in the list of admitted patients, so we need to use the patient data from the bed endpoint
61
+ return {
62
+ patient: patient,
63
+ visit: null,
64
+ bed,
65
+ inpatientAdmission: null, // populate after BED-13
66
+ inpatientRequest: null,
67
+ };
68
+ }
69
+ });
70
+ return wardPatients;
71
+ })
72
+ ?.flat() ?? []
73
+ ).filter((pat) => {
74
+ const noteEncounter = pat?.visit?.encounters?.find(
75
+ (encounter) => encounter.encounterType?.uuid === config.doctorsnoteEncounterTypeUuid,
76
+ );
77
+ if (!noteEncounter) return false;
78
+ const obs = noteEncounter.obs.find((ob) => ob.concept.uuid === config.referralsConceptUuid);
79
+ if (!obs) return false;
80
+ const isDischargedIn = [config.referringToAnotherFacilityConceptUuid, config.dischargeHomeConceptUuid].includes(
81
+ (obs.value as OpenmrsResource).uuid,
82
+ );
83
+ return isDischargedIn === true;
84
+ });
85
+ }, [bedLayouts, wardAdmittedPatientsWithBed, config]);
86
+
87
+ const [pageSize, setPageSize] = useState(5);
88
+ const { paginated, results, totalPages, currentPage, goTo } = usePagination(patients, pageSize);
89
+ const { pageSizes } = usePaginationInfo(pageSize, totalPages, currentPage, results.length);
90
+
91
+ const tableRows = useMemo(() => {
92
+ return results.map((patient, index) => {
93
+ const { encounterAssigningToCurrentInpatientLocation } = patient.inpatientAdmission ?? {};
94
+
95
+ const admissionDate = encounterAssigningToCurrentInpatientLocation?.encounterDatetime
96
+ ? formatDatetime(parseDate(encounterAssigningToCurrentInpatientLocation!.encounterDatetime!))
97
+ : '--';
98
+ const daysAdmitted = encounterAssigningToCurrentInpatientLocation?.encounterDatetime
99
+ ? dayjs(encounterAssigningToCurrentInpatientLocation?.encounterDatetime).diff(dayjs(), 'days')
100
+ : '--';
101
+ return {
102
+ id: patient.patient?.uuid ?? index,
103
+ admissionDate,
104
+ idNumber: getOpenmrsId(patient.patient?.identifiers ?? []) ?? '--',
105
+ name: patient.patient?.person?.display ?? '--',
106
+ gender: patient.patient?.person?.gender ?? '--',
107
+ age: patient.patient?.person?.age ?? '--',
108
+ bedNumber: patient.bed?.bedNumber ?? '--',
109
+ daysAdmitted,
110
+ action: (
111
+ <OverflowMenu size={'sm'} flipped>
112
+ <OverflowMenuItem itemText={t('goToBilling', 'Go to Billing')} onClick={() => {}} />
113
+ <OverflowMenuItem itemText={t('waivePatient', 'Waive Patient')} onClick={() => {}} />
114
+ <OverflowMenuItem itemText={t('patientAbscondend', 'Patient Absconded')} onClick={() => {}} />
115
+ <OverflowMenuItem
116
+ itemText={t('discharge', 'Discharge')}
117
+ onClick={() => {
118
+ launchWorkspace('patient-discharge-workspace', {
119
+ wardPatient: patient,
120
+ patientUuid: patient.patient.uuid,
121
+ formUuid: config.inpatientDischargeFormUuid,
122
+ });
123
+ }}
124
+ />
125
+ </OverflowMenu>
126
+ ),
127
+ };
128
+ });
129
+ }, [results, config, t]);
130
+
131
+ if (!patients.length) return <EmptyState message={t('noDischargeInpatients', 'No Discharge in patients')} />;
132
+
133
+ return (
134
+ <DataTable rows={tableRows} headers={headers} isSortable useZebraStyles>
135
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps, getCellProps }) => (
136
+ <TableContainer>
137
+ <Table {...getTableProps()} aria-label="sample table">
138
+ <TableHead>
139
+ <TableRow>
140
+ {headers.map((header) => (
141
+ <TableHeader
142
+ key={header.key}
143
+ {...getHeaderProps({
144
+ header,
145
+ })}>
146
+ {header.header}
147
+ </TableHeader>
148
+ ))}
149
+ </TableRow>
150
+ </TableHead>
151
+ <TableBody>
152
+ {rows.map((row) => {
153
+ return (
154
+ <TableRow key={row.id} {...getRowProps({ row })}>
155
+ {row.cells.map((cell) => (
156
+ <TableCell key={cell.id} {...getCellProps({ cell })}>
157
+ {cell.value}
158
+ </TableCell>
159
+ ))}
160
+ </TableRow>
161
+ );
162
+ })}
163
+ </TableBody>
164
+ </Table>
165
+ {paginated && !isLoading && (
166
+ <Pagination
167
+ page={currentPage}
168
+ pageSize={pageSize}
169
+ pageSizes={pageSizes}
170
+ totalItems={(patients ?? []).length}
171
+ onChange={({ page, pageSize }) => {
172
+ goTo(page);
173
+ setPageSize(pageSize);
174
+ }}
175
+ />
176
+ )}
177
+ </TableContainer>
178
+ )}
179
+ </DataTable>
180
+ );
181
+ };
182
+
183
+ export default DischargeInPatients;