@openmrs/esm-ward-app 9.2.1-pre.6635 → 9.2.1-pre.6637

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 (44) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/dist/1058.js +2 -0
  3. package/dist/1058.js.map +1 -0
  4. package/dist/1369.js +1 -1
  5. package/dist/2557.js +1 -1
  6. package/dist/2728.js +1 -1
  7. package/dist/283.js +1 -1
  8. package/dist/3365.js +1 -1
  9. package/dist/3365.js.map +1 -1
  10. package/dist/3737.js +1 -1
  11. package/dist/380.js +1 -0
  12. package/dist/380.js.map +1 -0
  13. package/dist/4300.js +1 -1
  14. package/dist/5734.js +1 -1
  15. package/dist/5734.js.map +1 -1
  16. package/dist/5885.js +1 -1
  17. package/dist/5885.js.map +1 -1
  18. package/dist/6012.js +1 -1
  19. package/dist/6012.js.map +1 -1
  20. package/dist/7179.js +1 -1
  21. package/dist/7524.js +1 -1
  22. package/dist/7661.js +1 -1
  23. package/dist/7661.js.map +1 -1
  24. package/dist/9045.js +1 -1
  25. package/dist/9294.js +1 -1
  26. package/dist/9775.js +1 -1
  27. package/dist/main.js +1 -1
  28. package/dist/main.js.map +1 -1
  29. package/dist/openmrs-esm-ward-app.js +1 -1
  30. package/dist/openmrs-esm-ward-app.js.buildmanifest.json +92 -67
  31. package/dist/openmrs-esm-ward-app.js.map +1 -1
  32. package/dist/routes.json +1 -1
  33. package/package.json +1 -1
  34. package/src/types/index.ts +6 -0
  35. package/src/ward-patient-card/ward-patient-card.component.tsx +8 -1
  36. package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +7 -2
  37. package/src/ward-workspace/patient-transfer-bed-swap/patient-admit-or-transfer-request-form.component.tsx +57 -9
  38. package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +76 -28
  39. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.scss +6 -0
  40. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +4 -0
  41. package/translations/en.json +2 -0
  42. package/dist/4739.js +0 -2
  43. package/dist/4739.js.map +0 -1
  44. /package/dist/{4739.js.LICENSE.txt → 1058.js.LICENSE.txt} +0 -0
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  Button,
3
3
  ButtonSet,
4
+ Checkbox,
5
+ CheckboxGroup,
4
6
  Form,
5
7
  InlineNotification,
6
8
  RadioButton,
@@ -15,11 +17,12 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
15
17
  import { Controller, useForm } from 'react-hook-form';
16
18
  import { useTranslation } from 'react-i18next';
17
19
  import { z } from 'zod';
18
- import useWardLocation from '../../hooks/useWardLocation';
19
20
  import LocationSelector from '../../location-selector/location-selector.component';
20
21
  import type { ObsPayload, WardPatientWorkspaceProps, WardViewContext } from '../../types';
21
22
  import { useCreateEncounter } from '../../ward.resource';
22
23
  import styles from './patient-transfer-swap.scss';
24
+ import WardPatientName from '../../ward-patient-card/row-elements/ward-patient-name.component';
25
+ import WardPatientIdentifier from '../../ward-patient-card/row-elements/ward-patient-identifier.component';
23
26
 
24
27
  /**
25
28
  * Form to fill out for:
@@ -31,6 +34,7 @@ export default function PatientAdmitOrTransferForm({
31
34
  closeWorkspaceWithSavedChanges,
32
35
  wardPatient,
33
36
  promptBeforeClosing,
37
+ relatedTransferPatients,
34
38
  }: WardPatientWorkspaceProps) {
35
39
  const { t } = useTranslation();
36
40
  const { patient, inpatientRequest, visit } = wardPatient ?? {};
@@ -44,6 +48,7 @@ export default function PatientAdmitOrTransferForm({
44
48
  );
45
49
  const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
46
50
  const currentAdmission = wardPatientGroupDetails?.inpatientAdmissionsByPatientUuid?.get(patient?.uuid);
51
+ const [selectedRelatedPatient, setCheckedRelatedPatient] = useState<string[]>([]);
47
52
 
48
53
  const zodSchema = useMemo(
49
54
  () =>
@@ -112,12 +117,28 @@ export default function PatientAdmitOrTransferForm({
112
117
  });
113
118
  }
114
119
 
115
- createEncounter(patient, emrConfiguration.transferRequestEncounterType, visit?.uuid, [
116
- {
117
- concept: emrConfiguration.dispositionDescriptor.dispositionSetConcept.uuid,
118
- groupMembers: obs,
119
- },
120
- ])
120
+ const wardPatientsToTransfer = [
121
+ wardPatient,
122
+ ...relatedTransferPatients.filter((rp) => selectedRelatedPatient.includes(rp.patient.uuid)),
123
+ ];
124
+
125
+ Promise.all(
126
+ wardPatientsToTransfer.map(async (wardPatientToTransfer) => {
127
+ const { patient: patientToTransfer, visit: patientToTransferVisit } = wardPatientToTransfer;
128
+
129
+ return createEncounter(
130
+ patientToTransfer,
131
+ emrConfiguration.transferRequestEncounterType,
132
+ patientToTransferVisit?.uuid,
133
+ [
134
+ {
135
+ concept: emrConfiguration.dispositionDescriptor.dispositionSetConcept.uuid,
136
+ groupMembers: obs,
137
+ },
138
+ ],
139
+ );
140
+ }),
141
+ )
121
142
  .then(() => {
122
143
  showSnackbar({
123
144
  title: t('patientTransferRequestCreated', 'Patient transfer request created'),
@@ -142,10 +163,11 @@ export default function PatientAdmitOrTransferForm({
142
163
  createEncounter,
143
164
  dispositionsWithTypeTransfer,
144
165
  emrConfiguration,
145
- patient,
146
166
  t,
147
167
  wardPatientGroupDetails,
148
- visit?.uuid,
168
+ selectedRelatedPatient,
169
+ relatedTransferPatients,
170
+ wardPatient,
149
171
  ],
150
172
  );
151
173
 
@@ -195,6 +217,32 @@ export default function PatientAdmitOrTransferForm({
195
217
  title={t('patientCurrentlyNotAdmitted', 'Patient currently not admitted')}
196
218
  />
197
219
  )}
220
+ {relatedTransferPatients?.length > 0 && (
221
+ <div>
222
+ <CheckboxGroup legendText={t('alsoTransfer', 'Also transfer:')}>
223
+ {relatedTransferPatients?.map(({ patient: relatedPatient }) => (
224
+ <Checkbox
225
+ checked={selectedRelatedPatient.includes(relatedPatient.uuid)}
226
+ className={styles.checkbox}
227
+ id={relatedPatient.uuid}
228
+ key={'also-transfer-' + relatedPatient.uuid}
229
+ labelText={
230
+ <div className={styles.relatedPatientTransferSwapOption}>
231
+ <WardPatientName patient={relatedPatient} />
232
+ <WardPatientIdentifier id="patient-identifier" patient={relatedPatient} />
233
+ </div>
234
+ }
235
+ onChange={(_, { checked, id }) => {
236
+ const currentValue = selectedRelatedPatient;
237
+ setCheckedRelatedPatient(
238
+ checked ? [...currentValue, id] : currentValue.filter((item) => item !== id),
239
+ );
240
+ }}
241
+ />
242
+ ))}
243
+ </CheckboxGroup>
244
+ </div>
245
+ )}
198
246
  <div className={styles.field}>
199
247
  <h2 className={styles.productiveHeading02}>{t('selectALocation', 'Select a location')}</h2>
200
248
  <Controller
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
- import { Button, ButtonSet, Form, InlineNotification } from '@carbon/react';
2
+ import { Button, ButtonSet, Form, InlineNotification , CheckboxGroup , Checkbox , Stack } from '@carbon/react';
3
3
  import classNames from 'classnames';
4
4
  import { zodResolver } from '@hookform/resolvers/zod';
5
5
  import { Controller, useForm } from 'react-hook-form';
@@ -10,11 +10,14 @@ import type { WardPatientWorkspaceProps, WardViewContext } from '../../types';
10
10
  import { assignPatientToBed, useCreateEncounter, removePatientFromBed } from '../../ward.resource';
11
11
  import BedSelector from '../bed-selector.component';
12
12
  import styles from './patient-transfer-swap.scss';
13
+ import WardPatientIdentifier from '../../ward-patient-card/row-elements/ward-patient-identifier.component';
14
+ import WardPatientName from '../../ward-patient-card/row-elements/ward-patient-name.component';
13
15
 
14
16
  export default function PatientBedSwapForm({
15
17
  promptBeforeClosing,
16
18
  closeWorkspaceWithSavedChanges,
17
19
  wardPatient,
20
+ relatedTransferPatients,
18
21
  }: WardPatientWorkspaceProps) {
19
22
  const { patient, visit } = wardPatient;
20
23
  const { t } = useTranslation();
@@ -24,6 +27,7 @@ export default function PatientBedSwapForm({
24
27
  const [isSubmitting, setIsSubmitting] = useState(false);
25
28
  const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
26
29
  const { isLoading } = wardPatientGroupDetails?.admissionLocationResponse ?? {};
30
+ const [selectedRelatedPatient, setCheckedRelatedPatient] = useState<string[]>([]);
27
31
 
28
32
  const zodSchema = useMemo(
29
33
  () =>
@@ -56,27 +60,40 @@ export default function PatientBedSwapForm({
56
60
  const bedSelected = beds.find((bed) => bed.bedId === values.bedId);
57
61
  setIsSubmitting(true);
58
62
  setShowErrorNotifications(false);
59
- createEncounter(patient, emrConfiguration.bedAssignmentEncounterType, visit.uuid)
60
- .then(async (response) => {
63
+ const wardPatientsToSwap = [
64
+ wardPatient,
65
+ ...relatedTransferPatients.filter((rp) => selectedRelatedPatient.includes(rp.patient.uuid)),
66
+ ];
67
+
68
+ Promise.all(
69
+ wardPatientsToSwap.map(async (wardPatientToSwap) => {
70
+ const { patient: patientToSwap, visit: patientToSwapVisit } = wardPatientToSwap;
71
+
72
+ const response = await createEncounter(
73
+ patientToSwap,
74
+ emrConfiguration.bedAssignmentEncounterType,
75
+ patientToSwapVisit.uuid,
76
+ );
61
77
  if (response.ok) {
62
78
  if (bedSelected) {
63
- return assignPatientToBed(values.bedId, patient.uuid, response.data.uuid);
79
+ return assignPatientToBed(values.bedId, patientToSwap.uuid, response.data.uuid);
64
80
  } else {
65
81
  // get the bed that the patient is currently assigned to
66
82
  const bedAssignedToPatient = beds.find((bed) =>
67
- bed.patients.some((bedPatient) => bedPatient.uuid == patient.uuid),
83
+ bed.patients.some((bedPatient) => bedPatient.uuid == patientToSwap.uuid),
68
84
  );
69
85
  if (bedAssignedToPatient) {
70
- return removePatientFromBed(bedAssignedToPatient.bedId, patient.uuid);
86
+ return removePatientFromBed(bedAssignedToPatient.bedId, patientToSwap.uuid);
71
87
  } else {
72
88
  // no-op
73
89
  return Promise.resolve({ ok: true });
74
90
  }
75
91
  }
76
92
  }
77
- })
78
- .then((response) => {
79
- if (response && response?.ok) {
93
+ }),
94
+ )
95
+ .then((responses) => {
96
+ if (responses.every((response) => response?.ok)) {
80
97
  if (bedSelected) {
81
98
  showSnackbar({
82
99
  kind: 'success',
@@ -118,7 +135,9 @@ export default function PatientBedSwapForm({
118
135
  t,
119
136
  wardPatientGroupDetails,
120
137
  closeWorkspaceWithSavedChanges,
121
- visit.uuid,
138
+ selectedRelatedPatient,
139
+ relatedTransferPatients,
140
+ wardPatient,
122
141
  ],
123
142
  );
124
143
 
@@ -131,7 +150,7 @@ export default function PatientBedSwapForm({
131
150
  <Form
132
151
  onSubmit={handleSubmit(onSubmit, onError)}
133
152
  className={classNames(styles.formContainer, styles.workspaceContent)}>
134
- <div>
153
+ <Stack gap={4}>
135
154
  {errorFetchingEmrConfiguration && (
136
155
  <div className={styles.formError}>
137
156
  <InlineNotification
@@ -146,22 +165,51 @@ export default function PatientBedSwapForm({
146
165
  />
147
166
  </div>
148
167
  )}
149
- <h2 className={styles.productiveHeading02}>{t('selectABed', 'Select a bed')}</h2>
150
- <Controller
151
- name="bedId"
152
- control={control}
153
- render={({ field: { onChange, value }, fieldState: { error } }) => (
154
- <BedSelector
155
- beds={beds}
156
- isLoadingBeds={isLoading}
157
- currentPatient={patient}
158
- selectedBedId={value}
159
- error={error}
160
- control={control}
161
- onChange={onChange}
162
- />
163
- )}
164
- />
168
+ {relatedTransferPatients?.length > 0 && (
169
+ <div>
170
+ <CheckboxGroup legendText={t('alsoSwap', 'Also swap:')}>
171
+ {relatedTransferPatients?.map(({ patient: relatedPatient }) => (
172
+ <div key={'also-swap-' + relatedPatient.uuid}>
173
+ <Checkbox
174
+ checked={selectedRelatedPatient.includes(relatedPatient.uuid)}
175
+ className={styles.checkbox}
176
+ id={relatedPatient.uuid}
177
+ labelText={
178
+ <div className={styles.relatedPatientTransferSwapOption}>
179
+ <WardPatientName patient={relatedPatient} />
180
+ <WardPatientIdentifier id="patient-identifier" patient={relatedPatient} />
181
+ </div>
182
+ }
183
+ onChange={(_, { checked, id }) => {
184
+ const currentValue = selectedRelatedPatient;
185
+ setCheckedRelatedPatient(
186
+ checked ? [...currentValue, id] : currentValue.filter((item) => item !== id),
187
+ );
188
+ }}
189
+ />
190
+ </div>
191
+ ))}
192
+ </CheckboxGroup>
193
+ </div>
194
+ )}
195
+ <div className={styles.field}>
196
+ <h2 className={styles.productiveHeading02}>{t('selectABed', 'Select a bed')}</h2>
197
+ <Controller
198
+ name="bedId"
199
+ control={control}
200
+ render={({ field: { onChange, value }, fieldState: { error } }) => (
201
+ <BedSelector
202
+ beds={beds}
203
+ isLoadingBeds={isLoading}
204
+ currentPatient={patient}
205
+ selectedBedId={value}
206
+ error={error}
207
+ control={control}
208
+ onChange={onChange}
209
+ />
210
+ )}
211
+ />
212
+ </div>
165
213
  {showErrorNotifications && (
166
214
  <div className={styles.notifications}>
167
215
  {Object.values(errors).map((error) => (
@@ -169,7 +217,7 @@ export default function PatientBedSwapForm({
169
217
  ))}
170
218
  </div>
171
219
  )}
172
- </div>
220
+ </Stack>
173
221
  <ButtonSet className={styles.buttonSet}>
174
222
  <Button size="xl" kind="secondary" onClick={closeWorkspaceWithSavedChanges}>
175
223
  {t('cancel', 'Cancel')}
@@ -85,3 +85,9 @@
85
85
  .notifications {
86
86
  margin-top: layout.$spacing-05;
87
87
  }
88
+
89
+ .relatedPatientTransferSwapOption {
90
+ display: flex;
91
+ flex-wrap: wrap;
92
+ gap: layout.$spacing-05;
93
+ }
@@ -15,6 +15,10 @@ const TransferSection = {
15
15
 
16
16
  type TransferSectionValues = (typeof TransferSection)[keyof typeof TransferSection];
17
17
 
18
+ /**
19
+ * This workspace opens the form to either transfer a patient to a different ward location
20
+ * or to change their currently assigned bed
21
+ */
18
22
  export default function PatientTransferAndSwapWorkspace(props: WardPatientWorkspaceProps) {
19
23
  const { t } = useTranslation();
20
24
  const [selectedSection, setSelectedSection] = useState<TransferSectionValues>(TransferSection.TRANSFER);
@@ -7,6 +7,8 @@
7
7
  "admitElsewhere": "Admit elsewhere",
8
8
  "admitPatient": "Admit patient",
9
9
  "admitting": "Admitting...",
10
+ "alsoSwap": "Also swap:",
11
+ "alsoTransfer": "Also transfer:",
10
12
  "backToSearchResults": "Back to search results",
11
13
  "bedShare": "Bed share",
12
14
  "bedSwap": "Bed swap",