@kenyaemr/esm-ward-app 8.1.1-pre.116 → 8.1.1-pre.119
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.
- package/.turbo/turbo-build.log +16 -20
- package/dist/124.js +1 -0
- package/dist/124.js.map +1 -0
- package/dist/125.js +1 -1
- package/dist/125.js.map +1 -1
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/153.js +1 -0
- package/dist/153.js.map +1 -0
- package/dist/372.js +1 -1
- package/dist/372.js.map +1 -1
- package/dist/471.js +1 -0
- package/dist/471.js.map +1 -0
- package/dist/481.js +1 -0
- package/dist/481.js.map +1 -0
- package/dist/53.js +1 -1
- package/dist/53.js.map +1 -1
- package/dist/559.js +1 -1
- package/dist/559.js.map +1 -1
- package/dist/574.js +1 -1
- package/dist/{500.js → 576.js} +1 -1
- package/dist/576.js.map +1 -0
- package/dist/577.js +1 -1
- package/dist/577.js.map +1 -1
- package/dist/649.js +2 -0
- package/dist/{161.js.LICENSE.txt → 649.js.LICENSE.txt} +0 -6
- package/dist/649.js.map +1 -0
- package/dist/{659.js → 662.js} +1 -1
- package/dist/662.js.map +1 -0
- package/dist/67.js +2 -0
- package/dist/67.js.LICENSE.txt +5 -0
- package/dist/67.js.map +1 -0
- package/dist/920.js +1 -0
- package/dist/920.js.map +1 -0
- package/dist/921.js +1 -0
- package/dist/921.js.map +1 -0
- package/dist/922.js +1 -1
- package/dist/922.js.map +1 -1
- package/dist/kenyaemr-esm-ward-app.js +1 -1
- package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +148 -165
- package/dist/kenyaemr-esm-ward-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +0 -10
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/mock.tsx +8 -0
- package/package.json +1 -1
- package/src/beds/empty-bed-skeleton.tsx +3 -3
- package/src/beds/empty-bed.component.tsx +3 -3
- package/src/beds/ward-bed.component.tsx +41 -0
- package/src/beds/ward-bed.scss +45 -0
- package/src/beds/{occupied-bed.test.tsx → ward-bed.test.tsx} +27 -16
- package/src/config-schema.ts +196 -75
- package/src/hooks/useAssignedBedByPatient.ts +9 -0
- package/src/hooks/useInpatientAdmission.ts +1 -1
- package/src/hooks/useMotherAndChildren.ts +2 -2
- package/src/hooks/useObs.ts +2 -2
- package/src/hooks/useWardPatientGrouping.ts +2 -0
- package/src/index.ts +10 -29
- package/src/root.component.tsx +3 -0
- package/src/routes.json +6 -11
- package/src/types/index.ts +29 -14
- package/src/ward-patient-card/card-rows/admission-request-note-row.component.tsx +38 -0
- package/src/ward-patient-card/card-rows/coded-obs-tags-row.component.tsx +108 -0
- package/src/ward-patient-card/card-rows/mother-child-row.component.tsx +84 -0
- package/src/ward-patient-card/card-rows/{pending-items-car-row.extension.tsx → pending-items-row.component.tsx} +12 -8
- package/src/ward-patient-card/row-elements/ward-patient-coded-obs-tags.tsx +12 -7
- package/src/ward-patient-card/row-elements/ward-patient-header-address.tsx +5 -5
- package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +18 -40
- package/src/ward-patient-card/row-elements/ward-patient-obs.resource.ts +2 -2
- package/src/ward-patient-card/row-elements/ward-patient-obs.tsx +15 -8
- package/src/ward-patient-card/ward-patient-card.component.tsx +16 -54
- package/src/ward-patient-card/ward-patient-card.scss +7 -1
- package/src/ward-view/default-ward/default-ward-beds.component.tsx +42 -0
- package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +32 -0
- package/src/ward-view/default-ward/default-ward-patient-card.component.tsx +31 -0
- package/src/ward-view/default-ward/default-ward-pending-patients.component.tsx +52 -0
- package/src/ward-view/default-ward/default-ward-unassigned-patients.component.tsx +32 -0
- package/src/ward-view/default-ward/default-ward-view.component.tsx +31 -0
- package/src/ward-view/materal-ward/maternal-ward-beds.component.tsx +65 -0
- package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +30 -0
- package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +93 -0
- package/src/{beds/occupied-bed.scss → ward-view/materal-ward/maternal-ward-patient-card.scss} +4 -10
- package/src/ward-view/materal-ward/maternal-ward-patient-card.test.tsx +47 -0
- package/src/ward-view/materal-ward/maternal-ward-pending-patients.component.tsx +48 -0
- package/src/ward-view/materal-ward/maternal-ward-unassigned-patients.component.tsx +33 -0
- package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +38 -0
- package/src/ward-view/materal-ward/maternal-ward-view.resource.ts +89 -0
- package/src/ward-view/ward-view.component.tsx +11 -151
- package/src/ward-view/ward-view.resource.ts +78 -6
- package/src/ward-view/ward-view.scss +1 -0
- package/src/ward-view/ward-view.test.tsx +10 -8
- package/src/ward-view/ward.component.tsx +106 -0
- package/src/ward-view-header/admission-requests-bar.component.tsx +10 -6
- package/src/ward-view-header/admission-requests-bar.test.tsx +5 -4
- package/src/ward-view-header/ward-metrics.component.tsx +12 -11
- package/src/ward-view-header/ward-metrics.test.tsx +4 -58
- package/src/ward-view-header/ward-view-header.component.tsx +6 -4
- package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +7 -4
- package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +9 -21
- package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +9 -3
- package/src/ward-workspace/admission-request-card/admission-request-card.scss +6 -1
- package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +11 -38
- package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +8 -38
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +80 -89
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +21 -13
- package/src/ward-workspace/patient-banner/patient-banner.component.tsx +5 -12
- package/src/ward-workspace/patient-details/ward-patient-action-button.extension.tsx +2 -2
- package/src/ward-workspace/patient-details/ward-patient.workspace.tsx +13 -6
- package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +6 -6
- package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +7 -7
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +6 -6
- package/translations/en.json +7 -1
- package/dist/126.js +0 -1
- package/dist/126.js.map +0 -1
- package/dist/161.js +0 -2
- package/dist/161.js.map +0 -1
- package/dist/2.js +0 -1
- package/dist/2.js.map +0 -1
- package/dist/269.js +0 -1
- package/dist/269.js.map +0 -1
- package/dist/466.js +0 -1
- package/dist/466.js.map +0 -1
- package/dist/500.js.map +0 -1
- package/dist/557.js +0 -1
- package/dist/557.js.map +0 -1
- package/dist/659.js.map +0 -1
- package/dist/701.js +0 -1
- package/dist/701.js.map +0 -1
- package/dist/749.js +0 -1
- package/dist/749.js.map +0 -1
- package/dist/908.js +0 -1
- package/dist/908.js.map +0 -1
- package/src/beds/empty-bed.scss +0 -24
- package/src/beds/occupied-bed.component.tsx +0 -35
- package/src/beds/unassigned-patient.component.tsx +0 -20
- package/src/beds/unassigned-patient.scss +0 -6
- package/src/config-schema-admission-request-note.ts +0 -9
- package/src/config-schema-extension-colored-obs-tags.ts +0 -91
- package/src/config-schema-mother-child-row.ts +0 -26
- package/src/config-schema-pending-items-extension.ts +0 -29
- package/src/hooks/useCurrentWardCardConfig.ts +0 -32
- package/src/ward-patient-card/card-rows/admission-request-note.extension.tsx +0 -32
- package/src/ward-patient-card/card-rows/colored-obs-tags-card-row.extension.tsx +0 -13
- package/src/ward-patient-card/card-rows/mother-child-row.extension.tsx +0 -110
- package/src/ward-patient-card/ward-patient-card-element.component.tsx +0 -69
- package/src/ward-patient-card/ward-patient-resource.ts +0 -15
- package/src/ward-view/ward-bed.component.tsx +0 -14
- /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 {
|
|
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 {
|
|
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(
|
|
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(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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,
|
|
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
|
|
29
|
-
const { isLoading, mutate: mutateAdmissionLocation } =
|
|
30
|
-
const { mutate: mutateInpatientRequest } =
|
|
31
|
-
const { mutate: mutateInpatientAdmission } =
|
|
32
|
-
const
|
|
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
|
|
96
|
-
|
|
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 (!
|
|
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={
|
|
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 {
|
|
11
|
-
const {
|
|
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
|
-
{
|
|
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 {
|
|
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={() =>
|
|
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
|
|
10
|
+
export default function WardPatientWorkspace({ setTitle, wardPatient }: WardPatientWorkspaceProps) {
|
|
11
11
|
useEffect(() => {
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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
|
|
21
|
-
const { mutate: mutateAdmissionLocation } =
|
|
22
|
-
const { mutate: mutateInpatientRequest } =
|
|
23
|
-
const { mutate: mutateInpatientAdmission } =
|
|
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 (!
|
|
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,
|
|
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
|
|
36
|
-
const { isLoading, mutate: mutateAdmissionLocation } =
|
|
37
|
-
const { mutate: mutateInpatientRequest } =
|
|
38
|
-
const { mutate: mutateInpatientAdmission } =
|
|
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 =
|
|
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 (!
|
|
148
|
+
if (!wardPatientGroupDetails) return <></>;
|
|
149
149
|
return (
|
|
150
150
|
<Form
|
|
151
151
|
onSubmit={handleSubmit(onSubmit, onError)}
|
package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx
CHANGED
|
@@ -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,
|
|
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
|
|
33
|
-
const { mutate: mutateAdmissionLocation } =
|
|
34
|
-
const { mutate: mutateInpatientAdmission } =
|
|
35
|
-
const { mutate: mutateInpatientRequest } =
|
|
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 (!
|
|
160
|
+
if (!wardPatientGroupDetails) return <></>;
|
|
161
161
|
return (
|
|
162
162
|
<Form
|
|
163
163
|
onSubmit={handleSubmit(onSubmit, onError)}
|
package/translations/en.json
CHANGED
|
@@ -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",
|