@kenyaemr/esm-ward-app 8.1.1-pre.118 → 8.1.1-pre.121

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 (149) hide show
  1. package/.turbo/turbo-build.log +16 -20
  2. package/dist/124.js +1 -0
  3. package/dist/124.js.map +1 -0
  4. package/dist/125.js +1 -1
  5. package/dist/125.js.map +1 -1
  6. package/dist/130.js +1 -1
  7. package/dist/130.js.map +1 -1
  8. package/dist/153.js +1 -0
  9. package/dist/153.js.map +1 -0
  10. package/dist/372.js +1 -1
  11. package/dist/372.js.map +1 -1
  12. package/dist/471.js +1 -0
  13. package/dist/471.js.map +1 -0
  14. package/dist/481.js +1 -0
  15. package/dist/481.js.map +1 -0
  16. package/dist/53.js +1 -1
  17. package/dist/53.js.map +1 -1
  18. package/dist/559.js +1 -1
  19. package/dist/559.js.map +1 -1
  20. package/dist/574.js +1 -1
  21. package/dist/{500.js → 576.js} +1 -1
  22. package/dist/576.js.map +1 -0
  23. package/dist/577.js +1 -1
  24. package/dist/577.js.map +1 -1
  25. package/dist/649.js +2 -0
  26. package/dist/{161.js.LICENSE.txt → 649.js.LICENSE.txt} +0 -6
  27. package/dist/649.js.map +1 -0
  28. package/dist/{659.js → 662.js} +1 -1
  29. package/dist/662.js.map +1 -0
  30. package/dist/67.js +2 -0
  31. package/dist/67.js.LICENSE.txt +5 -0
  32. package/dist/67.js.map +1 -0
  33. package/dist/920.js +1 -0
  34. package/dist/920.js.map +1 -0
  35. package/dist/921.js +1 -0
  36. package/dist/921.js.map +1 -0
  37. package/dist/922.js +1 -1
  38. package/dist/922.js.map +1 -1
  39. package/dist/kenyaemr-esm-ward-app.js +1 -1
  40. package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +148 -165
  41. package/dist/kenyaemr-esm-ward-app.js.map +1 -1
  42. package/dist/main.js +1 -1
  43. package/dist/main.js.LICENSE.txt +0 -10
  44. package/dist/main.js.map +1 -1
  45. package/dist/routes.json +1 -1
  46. package/mock.tsx +8 -0
  47. package/package.json +1 -1
  48. package/src/beds/empty-bed-skeleton.tsx +3 -3
  49. package/src/beds/empty-bed.component.tsx +3 -3
  50. package/src/beds/ward-bed.component.tsx +41 -0
  51. package/src/beds/ward-bed.scss +45 -0
  52. package/src/beds/{occupied-bed.test.tsx → ward-bed.test.tsx} +27 -16
  53. package/src/config-schema.ts +196 -75
  54. package/src/hooks/useAssignedBedByPatient.ts +9 -0
  55. package/src/hooks/useInpatientAdmission.ts +1 -1
  56. package/src/hooks/useMotherAndChildren.ts +2 -2
  57. package/src/hooks/useObs.ts +2 -2
  58. package/src/hooks/useWardPatientGrouping.ts +2 -0
  59. package/src/index.ts +10 -29
  60. package/src/root.component.tsx +3 -0
  61. package/src/routes.json +6 -11
  62. package/src/types/index.ts +29 -14
  63. package/src/ward-patient-card/card-rows/admission-request-note-row.component.tsx +38 -0
  64. package/src/ward-patient-card/card-rows/coded-obs-tags-row.component.tsx +108 -0
  65. package/src/ward-patient-card/card-rows/mother-child-row.component.tsx +84 -0
  66. package/src/ward-patient-card/card-rows/{pending-items-car-row.extension.tsx → pending-items-row.component.tsx} +12 -8
  67. package/src/ward-patient-card/row-elements/ward-patient-coded-obs-tags.tsx +12 -7
  68. package/src/ward-patient-card/row-elements/ward-patient-header-address.tsx +5 -5
  69. package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +18 -40
  70. package/src/ward-patient-card/row-elements/ward-patient-obs.resource.ts +2 -2
  71. package/src/ward-patient-card/row-elements/ward-patient-obs.tsx +15 -8
  72. package/src/ward-patient-card/ward-patient-card.component.tsx +16 -54
  73. package/src/ward-patient-card/ward-patient-card.scss +7 -1
  74. package/src/ward-view/default-ward/default-ward-beds.component.tsx +42 -0
  75. package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +32 -0
  76. package/src/ward-view/default-ward/default-ward-patient-card.component.tsx +31 -0
  77. package/src/ward-view/default-ward/default-ward-pending-patients.component.tsx +52 -0
  78. package/src/ward-view/default-ward/default-ward-unassigned-patients.component.tsx +32 -0
  79. package/src/ward-view/default-ward/default-ward-view.component.tsx +31 -0
  80. package/src/ward-view/materal-ward/maternal-ward-beds.component.tsx +65 -0
  81. package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +30 -0
  82. package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +93 -0
  83. package/src/{beds/occupied-bed.scss → ward-view/materal-ward/maternal-ward-patient-card.scss} +4 -10
  84. package/src/ward-view/materal-ward/maternal-ward-patient-card.test.tsx +47 -0
  85. package/src/ward-view/materal-ward/maternal-ward-pending-patients.component.tsx +48 -0
  86. package/src/ward-view/materal-ward/maternal-ward-unassigned-patients.component.tsx +33 -0
  87. package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +38 -0
  88. package/src/ward-view/materal-ward/maternal-ward-view.resource.ts +89 -0
  89. package/src/ward-view/ward-view.component.tsx +11 -151
  90. package/src/ward-view/ward-view.resource.ts +78 -6
  91. package/src/ward-view/ward-view.scss +1 -0
  92. package/src/ward-view/ward-view.test.tsx +10 -8
  93. package/src/ward-view/ward.component.tsx +106 -0
  94. package/src/ward-view-header/admission-requests-bar.component.tsx +10 -6
  95. package/src/ward-view-header/admission-requests-bar.test.tsx +5 -4
  96. package/src/ward-view-header/ward-metrics.component.tsx +12 -11
  97. package/src/ward-view-header/ward-metrics.test.tsx +4 -58
  98. package/src/ward-view-header/ward-view-header.component.tsx +6 -4
  99. package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +7 -4
  100. package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +9 -21
  101. package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +9 -3
  102. package/src/ward-workspace/admission-request-card/admission-request-card.scss +6 -1
  103. package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +11 -38
  104. package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +8 -38
  105. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +80 -89
  106. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +21 -13
  107. package/src/ward-workspace/patient-banner/patient-banner.component.tsx +5 -12
  108. package/src/ward-workspace/patient-details/ward-patient-action-button.extension.tsx +2 -2
  109. package/src/ward-workspace/patient-details/ward-patient.workspace.tsx +13 -6
  110. package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +6 -6
  111. package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +7 -7
  112. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +6 -6
  113. package/translations/en.json +7 -1
  114. package/dist/126.js +0 -1
  115. package/dist/126.js.map +0 -1
  116. package/dist/161.js +0 -2
  117. package/dist/161.js.map +0 -1
  118. package/dist/2.js +0 -1
  119. package/dist/2.js.map +0 -1
  120. package/dist/269.js +0 -1
  121. package/dist/269.js.map +0 -1
  122. package/dist/466.js +0 -1
  123. package/dist/466.js.map +0 -1
  124. package/dist/500.js.map +0 -1
  125. package/dist/557.js +0 -1
  126. package/dist/557.js.map +0 -1
  127. package/dist/659.js.map +0 -1
  128. package/dist/701.js +0 -1
  129. package/dist/701.js.map +0 -1
  130. package/dist/749.js +0 -1
  131. package/dist/749.js.map +0 -1
  132. package/dist/908.js +0 -1
  133. package/dist/908.js.map +0 -1
  134. package/src/beds/empty-bed.scss +0 -24
  135. package/src/beds/occupied-bed.component.tsx +0 -35
  136. package/src/beds/unassigned-patient.component.tsx +0 -20
  137. package/src/beds/unassigned-patient.scss +0 -6
  138. package/src/config-schema-admission-request-note.ts +0 -9
  139. package/src/config-schema-extension-colored-obs-tags.ts +0 -91
  140. package/src/config-schema-mother-child-row.ts +0 -26
  141. package/src/config-schema-pending-items-extension.ts +0 -29
  142. package/src/hooks/useCurrentWardCardConfig.ts +0 -32
  143. package/src/ward-patient-card/card-rows/admission-request-note.extension.tsx +0 -32
  144. package/src/ward-patient-card/card-rows/colored-obs-tags-card-row.extension.tsx +0 -13
  145. package/src/ward-patient-card/card-rows/mother-child-row.extension.tsx +0 -110
  146. package/src/ward-patient-card/ward-patient-card-element.component.tsx +0 -69
  147. package/src/ward-patient-card/ward-patient-resource.ts +0 -15
  148. package/src/ward-view/ward-bed.component.tsx +0 -14
  149. /package/src/ward-patient-card/row-elements/{ward-pateint-skeleton-text.tsx → ward-patient-skeleton-text.tsx} +0 -0
@@ -1,15 +1,15 @@
1
- import { openmrsFetch, showSnackbar, useAppContext, useFeatureFlag, useSession } from '@openmrs/esm-framework';
1
+ import { showSnackbar, useAppContext, useFeatureFlag, useSession } from '@openmrs/esm-framework';
2
2
  import { screen } from '@testing-library/react';
3
3
  import userEvent from '@testing-library/user-event';
4
4
  import React from 'react';
5
5
  import { mockAdmissionLocation, mockLocationInpatientWard, mockPatientAlice } from '../../../../../__mocks__';
6
6
  import { renderWithSwr } from '../../../../../tools';
7
- import { mockWardPatientGroupDetails } from '../../../mock';
8
- import { useAdmissionLocation } from '../../hooks/useAdmissionLocation';
7
+ import { mockWardPatientGroupDetails, mockWardViewContext } from '../../../mock';
8
+ import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
9
9
  import useEmrConfiguration from '../../hooks/useEmrConfiguration';
10
- import { useInpatientRequest } from '../../hooks/useInpatientRequest';
11
10
  import useWardLocation from '../../hooks/useWardLocation';
12
- import type { DispositionType } from '../../types';
11
+ import type { DispositionType, WardViewContext } from '../../types';
12
+ import { assignPatientToBed, createEncounter, removePatientFromBed } from '../../ward.resource';
13
13
  import AdmitPatientFormWorkspace from './admit-patient-form.workspace';
14
14
  import type { AdmitPatientFormWorkspaceProps } from './types';
15
15
 
@@ -33,14 +33,27 @@ jest.mock('../../hooks/useInpatientAdmission', () => ({
33
33
  useInpatientAdmission: jest.fn(),
34
34
  }));
35
35
 
36
+ jest.mock('../../hooks/useAssignedBedByPatient', () => ({
37
+ useAssignedBedByPatient: jest.fn(),
38
+ }));
39
+
40
+ jest.mock('../../ward.resource', () => ({
41
+ createEncounter: jest.fn(),
42
+ assignPatientToBed: jest.fn(),
43
+ removePatientFromBed: jest.fn(),
44
+ }));
45
+
36
46
  const mockedUseEmrConfiguration = jest.mocked(useEmrConfiguration);
37
47
  const mockedUseWardLocation = jest.mocked(useWardLocation);
38
- const mockedOpenmrsFetch = jest.mocked(openmrsFetch);
39
48
  const mockedUseFeatureFlag = jest.mocked(useFeatureFlag);
40
49
  const mockedShowSnackbar = jest.mocked(showSnackbar);
41
50
  const mockedUseSession = jest.mocked(useSession);
51
+ const mockedUseAssignedBedByPatient = jest.mocked(useAssignedBedByPatient);
52
+ const mockedAssignPatientToBed = jest.mocked(assignPatientToBed);
53
+ const mockedCreateEncounter = jest.mocked(createEncounter);
54
+ const mockedRemovePatientFromBed = jest.mocked(removePatientFromBed);
42
55
 
43
- jest.mocked(useAppContext).mockReturnValue(mockWardPatientGroupDetails());
56
+ jest.mocked(useAppContext<WardViewContext>).mockReturnValue(mockWardViewContext);
44
57
 
45
58
  const mockWorkspaceProps: AdmitPatientFormWorkspaceProps = {
46
59
  patient: mockPatientAlice,
@@ -49,9 +62,6 @@ const mockWorkspaceProps: AdmitPatientFormWorkspaceProps = {
49
62
  promptBeforeClosing: jest.fn(),
50
63
  setTitle: jest.fn(),
51
64
  dispositionType: 'ADMIT',
52
- setCancelTitle: jest.fn(),
53
- setCancelMessage: jest.fn(),
54
- setCancelConfirmText: jest.fn(),
55
65
  };
56
66
 
57
67
  function renderAdmissionForm(dispositionType: DispositionType = 'ADMIT') {
@@ -96,6 +106,39 @@ describe('Testing AdmitPatientForm', () => {
96
106
  isLoadingLocation: false,
97
107
  errorFetchingLocation: null,
98
108
  });
109
+ mockedUseAssignedBedByPatient.mockReturnValue({
110
+ data: {
111
+ data: {
112
+ results: [
113
+ {
114
+ bedId: 1,
115
+ bedNumber: 1,
116
+ bedType: null,
117
+ patients: [mockPatientAlice],
118
+ physicalLocation: mockLocationInpatientWard,
119
+ },
120
+ ],
121
+ },
122
+ },
123
+ } as ReturnType<typeof useAssignedBedByPatient>);
124
+
125
+ // @ts-ignore - we only need these two keys for now
126
+ mockedCreateEncounter.mockResolvedValue({
127
+ ok: true,
128
+ data: {
129
+ uuid: 'encounter-uuid',
130
+ },
131
+ });
132
+
133
+ // @ts-ignore - we only need the ok key for now
134
+ mockedAssignPatientToBed.mockResolvedValue({
135
+ ok: true,
136
+ });
137
+
138
+ // @ts-ignore - we only need the ok key for now
139
+ mockedRemovePatientFromBed.mockResolvedValue({
140
+ ok: true,
141
+ });
99
142
  });
100
143
 
101
144
  it('should render admit patient form', async () => {
@@ -157,13 +200,6 @@ describe('Testing AdmitPatientForm', () => {
157
200
  });
158
201
 
159
202
  it('should submit the form, create encounter and submit bed', async () => {
160
- // @ts-ignore - we only need these two keys for now
161
- mockedOpenmrsFetch.mockResolvedValue({
162
- ok: true,
163
- data: {
164
- uuid: 'encounter-uuid',
165
- },
166
- });
167
203
  const user = userEvent.setup();
168
204
  renderAdmissionForm();
169
205
  const combobox = screen.getByRole('combobox', {
@@ -175,35 +211,19 @@ describe('Testing AdmitPatientForm', () => {
175
211
  const admitButton = screen.getByRole('button', { name: 'Admit' });
176
212
  expect(admitButton).toBeEnabled();
177
213
  await user.click(admitButton);
178
- expect(mockedOpenmrsFetch).toHaveBeenCalledTimes(2);
179
- expect(mockedOpenmrsFetch).toHaveBeenCalledWith('/ws/rest/v1/encounter', {
180
- method: 'POST',
181
- headers: {
182
- 'content-type': 'application/json',
183
- },
184
- body: {
185
- patient: mockPatientAlice.uuid,
186
- encounterType: 'admission-encounter-type-uuid',
187
- location: mockAdmissionLocation.ward.uuid,
188
- obs: [],
189
- encounterProviders: [
190
- {
191
- provider: 'current-provider-uuid',
192
- encounterRole: 'clinician-encounter-role-uuid',
193
- },
194
- ],
195
- },
196
- });
197
- expect(mockedOpenmrsFetch).toHaveBeenCalledWith('/ws/rest/v1/beds/3', {
198
- method: 'POST',
199
- headers: {
200
- 'content-type': 'application/json',
201
- },
202
- body: {
203
- patientUuid: mockPatientAlice.uuid,
204
- encounterUuid: 'encounter-uuid',
205
- },
214
+ expect(mockedCreateEncounter).toHaveBeenCalledWith({
215
+ patient: mockPatientAlice.uuid,
216
+ encounterType: 'admission-encounter-type-uuid',
217
+ location: mockAdmissionLocation.ward.uuid,
218
+ obs: [],
219
+ encounterProviders: [
220
+ {
221
+ provider: 'current-provider-uuid',
222
+ encounterRole: 'clinician-encounter-role-uuid',
223
+ },
224
+ ],
206
225
  });
226
+ expect(mockedAssignPatientToBed).toHaveBeenCalledWith(3, mockPatientAlice.uuid, 'encounter-uuid');
207
227
  expect(mockedShowSnackbar).toHaveBeenCalledWith({
208
228
  kind: 'success',
209
229
  subtitle: '{{patientName}} has been successfully admitted and assigned to bed bed3',
@@ -212,7 +232,7 @@ describe('Testing AdmitPatientForm', () => {
212
232
  });
213
233
 
214
234
  it('should show snackbar if there was an issue creating an encounter', async () => {
215
- mockedOpenmrsFetch.mockRejectedValue(new Error('Failed to create encounter'));
235
+ mockedCreateEncounter.mockRejectedValue(new Error('Failed to create encounter'));
216
236
  const user = userEvent.setup();
217
237
  renderAdmissionForm();
218
238
  const combobox = screen.getByRole('combobox', {
@@ -224,7 +244,6 @@ describe('Testing AdmitPatientForm', () => {
224
244
  const admitButton = screen.getByRole('button', { name: 'Admit' });
225
245
  expect(admitButton).toBeEnabled();
226
246
  await user.click(admitButton);
227
- expect(mockedOpenmrsFetch).toHaveBeenCalledTimes(1);
228
247
  expect(mockedShowSnackbar).toHaveBeenCalledWith({
229
248
  kind: 'error',
230
249
  title: 'Failed to admit patient',
@@ -233,18 +252,7 @@ describe('Testing AdmitPatientForm', () => {
233
252
  });
234
253
 
235
254
  it('should show warning snackbar if encounter was created and bed assignment was not successful', async () => {
236
- // @ts-ignore - matching whole FetchResponse type is not necessary
237
- mockedOpenmrsFetch.mockImplementation((url) => {
238
- if (url.startsWith('/ws/rest/v1/beds')) {
239
- return Promise.reject(new Error('Failed to assign bed'));
240
- }
241
- return Promise.resolve({
242
- ok: true,
243
- data: {
244
- uuid: 'encounter-uuid',
245
- },
246
- });
247
- });
255
+ mockedAssignPatientToBed.mockRejectedValue(new Error('Failed to assign bed'));
248
256
 
249
257
  const user = userEvent.setup();
250
258
  renderAdmissionForm();
@@ -257,7 +265,6 @@ describe('Testing AdmitPatientForm', () => {
257
265
  const admitButton = screen.getByRole('button', { name: 'Admit' });
258
266
  expect(admitButton).toBeEnabled();
259
267
  await user.click(admitButton);
260
- expect(mockedOpenmrsFetch).toHaveBeenCalledTimes(2);
261
268
  expect(mockedShowSnackbar).toHaveBeenCalledWith({
262
269
  kind: 'warning',
263
270
  title: 'Patient admitted successfully',
@@ -265,41 +272,25 @@ describe('Testing AdmitPatientForm', () => {
265
272
  });
266
273
  });
267
274
 
268
- it('should admit patient if no beds are configured', async () => {
269
- // @ts-ignore - we only need these two keys for now
270
- mockedOpenmrsFetch.mockResolvedValue({
271
- ok: true,
272
- data: {
273
- uuid: 'encounter-uuid',
274
- },
275
- });
275
+ it('should admit patient if no bed is selected', async () => {
276
276
  const user = userEvent.setup();
277
277
  renderAdmissionForm();
278
278
  const admitButton = screen.getByRole('button', { name: 'Admit' });
279
279
  expect(admitButton).toBeEnabled();
280
280
  await user.click(admitButton);
281
- expect(mockedOpenmrsFetch).toHaveBeenCalledTimes(2);
282
- expect(mockedOpenmrsFetch).toHaveBeenCalledWith('/ws/rest/v1/encounter', {
283
- method: 'POST',
284
- headers: {
285
- 'content-type': 'application/json',
286
- },
287
- body: {
288
- patient: mockPatientAlice.uuid,
289
- encounterType: 'admission-encounter-type-uuid',
290
- location: mockAdmissionLocation.ward.uuid,
291
- obs: [],
292
- encounterProviders: [
293
- {
294
- provider: 'current-provider-uuid',
295
- encounterRole: 'clinician-encounter-role-uuid',
296
- },
297
- ],
298
- },
299
- });
300
- expect(mockedOpenmrsFetch).toHaveBeenCalledWith(`/ws/rest/v1/beds/1?patientUuid=${mockPatientAlice.uuid}`, {
301
- method: 'DELETE',
281
+ expect(mockedCreateEncounter).toHaveBeenCalledWith({
282
+ patient: mockPatientAlice.uuid,
283
+ encounterType: 'admission-encounter-type-uuid',
284
+ location: mockAdmissionLocation.ward.uuid,
285
+ obs: [],
286
+ encounterProviders: [
287
+ {
288
+ provider: 'current-provider-uuid',
289
+ encounterRole: 'clinician-encounter-role-uuid',
290
+ },
291
+ ],
302
292
  });
293
+ expect(mockedRemovePatientFromBed).toHaveBeenCalledWith(1, mockPatientAlice.uuid);
303
294
  expect(mockedShowSnackbar).toHaveBeenCalledWith({
304
295
  kind: 'success',
305
296
  subtitle: 'Patient admitted successfully to Inpatient Ward',
@@ -7,10 +7,11 @@ import { useTranslation } from 'react-i18next';
7
7
  import { z } from 'zod';
8
8
  import useEmrConfiguration from '../../hooks/useEmrConfiguration';
9
9
  import useWardLocation from '../../hooks/useWardLocation';
10
- import type { BedLayout, WardPatientGroupDetails } from '../../types';
10
+ import type { BedLayout, WardViewContext } from '../../types';
11
11
  import { assignPatientToBed, createEncounter, removePatientFromBed } from '../../ward.resource';
12
12
  import styles from './admit-patient-form.scss';
13
13
  import type { AdmitPatientFormWorkspaceProps } from './types';
14
+ import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
14
15
 
15
16
  const AdmitPatientFormWorkspace: React.FC<AdmitPatientFormWorkspaceProps> = ({
16
17
  patient,
@@ -25,11 +26,14 @@ const AdmitPatientFormWorkspace: React.FC<AdmitPatientFormWorkspaceProps> = ({
25
26
  const [isSubmitting, setIsSubmitting] = useState(false);
26
27
  const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
27
28
  const [showErrorNotifications, setShowErrorNotifications] = useState(false);
28
- const wardPatientGrouping = useAppContext<WardPatientGroupDetails>('ward-patients-group');
29
- const { isLoading, mutate: mutateAdmissionLocation } = wardPatientGrouping?.admissionLocationResponse ?? {};
30
- const { mutate: mutateInpatientRequest } = wardPatientGrouping?.inpatientRequestResponse ?? {};
31
- const { mutate: mutateInpatientAdmission } = wardPatientGrouping?.inpatientAdmissionResponse ?? {};
32
- const beds = isLoading ? [] : wardPatientGrouping?.bedLayouts ?? [];
29
+ const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
30
+ const { isLoading, mutate: mutateAdmissionLocation } = wardPatientGroupDetails?.admissionLocationResponse ?? {};
31
+ const { mutate: mutateInpatientRequest } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
32
+ const { mutate: mutateInpatientAdmission } = wardPatientGroupDetails?.inpatientAdmissionResponse ?? {};
33
+ const { data: bedsAssignedToPatient, isLoading: isLoadingBedsAssignedToPatient } = useAssignedBedByPatient(
34
+ patient.uuid,
35
+ );
36
+ const beds = isLoading ? [] : wardPatientGroupDetails?.bedLayouts ?? [];
33
37
  const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');
34
38
  const getBedRepresentation = useCallback((bedLayout: BedLayout) => {
35
39
  const bedNumber = bedLayout.bedNumber;
@@ -92,11 +96,9 @@ const AdmitPatientFormWorkspace: React.FC<AdmitPatientFormWorkspaceProps> = ({
92
96
  if (bedSelected) {
93
97
  return assignPatientToBed(values.bedId, patient.uuid, response.data.uuid);
94
98
  } else {
95
- const bed = wardPatientGrouping.bedLayouts.find((bedLayout) =>
96
- bedLayout.patients.some((p) => p.uuid == patient.uuid),
97
- );
98
- if (bed) {
99
- return removePatientFromBed(bed.bedId, patient.uuid);
99
+ const assignedBedId = bedsAssignedToPatient?.data?.results?.[0]?.bedId;
100
+ if (assignedBedId) {
101
+ return removePatientFromBed(assignedBedId, patient.uuid);
100
102
  }
101
103
  return response;
102
104
  }
@@ -180,7 +182,7 @@ const AdmitPatientFormWorkspace: React.FC<AdmitPatientFormWorkspaceProps> = ({
180
182
  setIsSubmitting(false);
181
183
  }, []);
182
184
 
183
- if (!wardPatientGrouping) return <></>;
185
+ if (!wardPatientGroupDetails) return <></>;
184
186
  return (
185
187
  <Form control={control} className={styles.form} onSubmit={handleSubmit(onSubmit, onError)}>
186
188
  <div className={styles.formContent}>
@@ -272,7 +274,13 @@ const AdmitPatientFormWorkspace: React.FC<AdmitPatientFormWorkspaceProps> = ({
272
274
  <Button
273
275
  type="submit"
274
276
  size="xl"
275
- disabled={isSubmitting || isLoadingEmrConfiguration || errorFetchingEmrConfiguration}>
277
+ disabled={
278
+ isSubmitting ||
279
+ isLoadingEmrConfiguration ||
280
+ errorFetchingEmrConfiguration ||
281
+ isLoading ||
282
+ isLoadingBedsAssignedToPatient
283
+ }>
276
284
  {!isSubmitting ? t('admit', 'Admit') : t('admitting', 'Admitting...')}
277
285
  </Button>
278
286
  </ButtonSet>
@@ -1,14 +1,11 @@
1
+ import { useAppContext } from '@openmrs/esm-framework';
1
2
  import React from 'react';
2
- import type { WardPatient } from '../../types';
3
- import { WardPatientCardElement } from '../../ward-patient-card/ward-patient-card-element.component';
4
- import { useCurrentWardCardConfig } from '../../hooks/useCurrentWardCardConfig';
3
+ import type { WardPatient, WardViewContext } from '../../types';
5
4
  import styles from './style.scss';
6
- import WardPatientBedNumber from '../../ward-patient-card/row-elements/ward-patient-bed-number';
7
- import WardPatientName from '../../ward-patient-card/row-elements/ward-patient-name';
8
5
 
9
6
  const WardPatientWorkspaceBanner = (wardPatient: WardPatient) => {
10
- const { headerRowElements } = useCurrentWardCardConfig();
11
- const { patient, bed } = wardPatient;
7
+ const { patient } = wardPatient;
8
+ const {WardPatientHeader} = useAppContext<WardViewContext>('ward-view-context') ?? {};
12
9
 
13
10
  if (!patient) {
14
11
  console.warn('Patient details were not received by the ward workspace');
@@ -17,11 +14,7 @@ const WardPatientWorkspaceBanner = (wardPatient: WardPatient) => {
17
14
 
18
15
  return (
19
16
  <div className={styles.patientBanner}>
20
- {bed ? <WardPatientBedNumber bed={bed} /> : null}
21
- <WardPatientName patient={patient} />
22
- {headerRowElements.map((elementId, i) => (
23
- <WardPatientCardElement key={`ward-card-${patient.uuid}-header-${i}`} elementId={elementId} {...wardPatient} />
24
- ))}
17
+ {WardPatientHeader && <WardPatientHeader {...wardPatient} />}
25
18
  </div>
26
19
  );
27
20
  };
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { UserAvatarIcon } from '@openmrs/esm-framework';
4
4
  import { ActionMenuButton, launchWorkspace } from '@openmrs/esm-framework';
5
- import { launchPatientWorkspace } from '../../ward-patient-card/ward-patient-resource';
5
+ import type { WardPatientWorkspaceProps } from '../../types';
6
6
 
7
7
  export default function WardPatientActionButton() {
8
8
  const { t } = useTranslation();
@@ -12,7 +12,7 @@ export default function WardPatientActionButton() {
12
12
  getIcon={(props) => <UserAvatarIcon {...props} />}
13
13
  label={t('Patient', 'patient')}
14
14
  iconDescription={t('Patient', 'patient')}
15
- handler={() => launchPatientWorkspace()}
15
+ handler={() => launchWorkspace<WardPatientWorkspaceProps>('ward-patient-workspace')}
16
16
  type={'ward'}
17
17
  />
18
18
  );
@@ -7,15 +7,22 @@ import { getGender } from '../../ward-patient-card/row-elements/ward-patient-gen
7
7
 
8
8
  attach('ward-patient-workspace-header-slot', 'patient-vitals-info');
9
9
 
10
- export default function WardPatientWorkspace({ setTitle, wardPatient: { patient } }: WardPatientWorkspaceProps) {
10
+ export default function WardPatientWorkspace({ setTitle, wardPatient }: WardPatientWorkspaceProps) {
11
11
  useEffect(() => {
12
- setTitle(patient.person.display, <PatientWorkspaceTitle key={patient.uuid} patient={patient} />);
13
- }, [patient.uuid]);
12
+ if (wardPatient) {
13
+ const { patient } = wardPatient;
14
+ setTitle(patient.person.display, <PatientWorkspaceTitle key={patient.uuid} patient={patient} />);
15
+ }
16
+ }, [wardPatient]);
14
17
 
15
18
  return (
16
- <div className={styles.workspaceContainer}>
17
- <WardPatientWorkspaceView patient={patient} />
18
- </div>
19
+ <>
20
+ {wardPatient && (
21
+ <div className={styles.workspaceContainer}>
22
+ <WardPatientWorkspaceView patient={wardPatient.patient} />
23
+ </div>
24
+ )}
25
+ </>
19
26
  );
20
27
  }
21
28
 
@@ -5,7 +5,7 @@ import React, { useCallback, useState } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import useEmrConfiguration from '../../hooks/useEmrConfiguration';
7
7
  import useWardLocation from '../../hooks/useWardLocation';
8
- import { type WardPatientGroupDetails, type WardPatientWorkspaceProps } from '../../types';
8
+ import { type WardViewContext, type WardPatientWorkspaceProps } from '../../types';
9
9
  import { createEncounter, removePatientFromBed } from '../../ward.resource';
10
10
  import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
11
11
  import styles from './patient-discharge.scss';
@@ -17,10 +17,10 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
17
17
  const { currentProvider } = useSession();
18
18
  const { location } = useWardLocation();
19
19
  const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
20
- const wardGroupingDetails = useAppContext<WardPatientGroupDetails>('ward-patients-group');
21
- const { mutate: mutateAdmissionLocation } = wardGroupingDetails?.admissionLocationResponse ?? {};
22
- const { mutate: mutateInpatientRequest } = wardGroupingDetails?.inpatientRequestResponse ?? {};
23
- const { mutate: mutateInpatientAdmission } = wardGroupingDetails?.inpatientAdmissionResponse ?? {};
20
+ const {wardPatientGroupDetails} = useAppContext<WardViewContext>('ward-view-context') ?? {};
21
+ const { mutate: mutateAdmissionLocation } = wardPatientGroupDetails?.admissionLocationResponse ?? {};
22
+ const { mutate: mutateInpatientRequest } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
23
+ const { mutate: mutateInpatientAdmission } = wardPatientGroupDetails?.inpatientAdmissionResponse ?? {};
24
24
 
25
25
  const submitDischarge = useCallback(() => {
26
26
  setIsSubmitting(true);
@@ -78,7 +78,7 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
78
78
  mutateInpatientAdmission,
79
79
  ]);
80
80
 
81
- if (!wardGroupingDetails) return <></>;
81
+ if (!wardPatientGroupDetails) return <></>;
82
82
  return (
83
83
  <div className={styles.workspaceContent}>
84
84
  <div className={styles.patientWorkspaceBanner}>
@@ -16,7 +16,7 @@ import { useTranslation } from 'react-i18next';
16
16
  import { z } from 'zod';
17
17
  import useEmrConfiguration from '../../hooks/useEmrConfiguration';
18
18
  import useWardLocation from '../../hooks/useWardLocation';
19
- import type { BedLayout, WardPatientGroupDetails, WardPatientWorkspaceProps } from '../../types';
19
+ import type { BedLayout, WardViewContext, WardPatientWorkspaceProps } from '../../types';
20
20
  import { assignPatientToBed, createEncounter } from '../../ward.resource';
21
21
  import styles from './patient-transfer-swap.scss';
22
22
 
@@ -32,10 +32,10 @@ export default function PatientBedSwapForm({
32
32
  const [isSubmitting, setIsSubmitting] = useState(false);
33
33
  const { currentProvider } = useSession();
34
34
  const { location } = useWardLocation();
35
- const wardGroupingDetails = useAppContext<WardPatientGroupDetails>('ward-patients-group');
36
- const { isLoading, mutate: mutateAdmissionLocation } = wardGroupingDetails?.admissionLocationResponse ?? {};
37
- const { mutate: mutateInpatientRequest } = wardGroupingDetails?.inpatientRequestResponse ?? {};
38
- const { mutate: mutateInpatientAdmission } = wardGroupingDetails?.inpatientAdmissionResponse ?? {};
35
+ const {wardPatientGroupDetails} = useAppContext<WardViewContext>('ward-view-context') ?? {};
36
+ const { isLoading, mutate: mutateAdmissionLocation } = wardPatientGroupDetails?.admissionLocationResponse ?? {};
37
+ const { mutate: mutateInpatientRequest } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
38
+ const { mutate: mutateInpatientAdmission } = wardPatientGroupDetails?.inpatientAdmissionResponse ?? {};
39
39
 
40
40
  const zodSchema = useMemo(
41
41
  () =>
@@ -70,7 +70,7 @@ export default function PatientBedSwapForm({
70
70
  [t],
71
71
  );
72
72
 
73
- const beds = wardGroupingDetails?.bedLayouts ?? [];
73
+ const beds = wardPatientGroupDetails?.bedLayouts ?? [];
74
74
  const bedDetails = useMemo(
75
75
  () =>
76
76
  beds.map((bed) => {
@@ -145,7 +145,7 @@ export default function PatientBedSwapForm({
145
145
  setShowErrorNotifications(true);
146
146
  }, []);
147
147
 
148
- if (!wardGroupingDetails) return <></>;
148
+ if (!wardPatientGroupDetails) return <></>;
149
149
  return (
150
150
  <Form
151
151
  onSubmit={handleSubmit(onSubmit, onError)}
@@ -9,7 +9,7 @@ import { z } from 'zod';
9
9
  import useEmrConfiguration from '../../hooks/useEmrConfiguration';
10
10
  import useWardLocation from '../../hooks/useWardLocation';
11
11
  import LocationSelector from '../../location-selector/location-selector.component';
12
- import type { ObsPayload, WardPatientGroupDetails, WardPatientWorkspaceProps } from '../../types';
12
+ import type { ObsPayload, WardViewContext, WardPatientWorkspaceProps } from '../../types';
13
13
  import { createEncounter } from '../../ward.resource';
14
14
  import styles from './patient-transfer-swap.scss';
15
15
 
@@ -29,10 +29,10 @@ export default function PatientTransferForm({
29
29
  () => emrConfiguration?.dispositions.filter(({ type }) => type === 'TRANSFER'),
30
30
  [emrConfiguration],
31
31
  );
32
- const wardGroupingDetails = useAppContext<WardPatientGroupDetails>('ward-patients-group');
33
- const { mutate: mutateAdmissionLocation } = wardGroupingDetails?.admissionLocationResponse ?? {};
34
- const { mutate: mutateInpatientAdmission } = wardGroupingDetails?.inpatientAdmissionResponse ?? {};
35
- const { mutate: mutateInpatientRequest } = wardGroupingDetails?.inpatientRequestResponse ?? {};
32
+ const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
33
+ const { mutate: mutateAdmissionLocation } = wardPatientGroupDetails?.admissionLocationResponse ?? {};
34
+ const { mutate: mutateInpatientAdmission } = wardPatientGroupDetails?.inpatientAdmissionResponse ?? {};
35
+ const { mutate: mutateInpatientRequest } = wardPatientGroupDetails?.inpatientRequestResponse ?? {};
36
36
 
37
37
  const zodSchema = useMemo(
38
38
  () =>
@@ -157,7 +157,7 @@ export default function PatientTransferForm({
157
157
  setShowErrorNotifications(true);
158
158
  }, []);
159
159
 
160
- if (!wardGroupingDetails) return <></>;
160
+ if (!wardPatientGroupDetails) return <></>;
161
161
  return (
162
162
  <Form
163
163
  onSubmit={handleSubmit(onSubmit, onError)}
@@ -14,16 +14,22 @@
14
14
  "chooseAnOption": "Choose an option",
15
15
  "clinicalForms": "Clinical forms",
16
16
  "clinicalNoteLabel": "Write your notes",
17
+ "countItems_one": "{{count}} {{item}}",
18
+ "countItems_other": "{{count}} {{item}}",
17
19
  "discharge": "Discharge",
18
20
  "empty": "Empty",
19
21
  "emptyBed": "Empty bed",
20
22
  "emptyText": "Empty",
21
23
  "encounterDisplay": "{{encounterType}} {{encounterDate}}",
22
24
  "errorAssigningBedToPatient": "Error assigning bed to patient",
25
+ "errorConfiguringPatientCard": "Error configuring patient card",
26
+ "errorConfiguringPatientCardMessage": "Unable to find configuration for {{elementType}}, id: {{id}}",
23
27
  "errorCreatingEncounter": "Failed to admit patient",
24
28
  "errorCreatingTransferRequest": "Error creating transfer request",
25
29
  "errorDischargingPatient": "Error discharging patient",
26
30
  "errorLoadingBedDetails": "Error loading bed details",
31
+ "errorLoadingChildren": "Error loading children info",
32
+ "errorLoadingMother": "Error loading mother info",
27
33
  "errorLoadingPatientAdmissionRequests": "Error loading patient admission requests",
28
34
  "errorLoadingPatients": "Error loading admitted patients",
29
35
  "errorLoadingWardLocation": "Error loading ward location",
@@ -33,11 +39,11 @@
33
39
  "freeBeds": "Free beds",
34
40
  "freeBedsMetricValue": "{{ metricValue }}",
35
41
  "inpatientNotesWorkspaceTitle": "In-patient notes",
36
- "invalidElementIdCopy": "The configuration provided is invalid. It contains the following unknown element ID:",
37
42
  "invalidLocationSpecified": "Invalid location specified",
38
43
  "invalidWardLocation": "Invalid ward location: {{location}}",
39
44
  "male": "Male",
40
45
  "manage": "Manage",
46
+ "motherChildBedShare": "Mother / Child",
41
47
  "nextPage": "Next page",
42
48
  "noBedsConfigured": "No beds configured for this location",
43
49
  "noBedsConfiguredForLocation": "No beds configured for {{location}} location",