@kenyaemr/esm-ward-app 8.1.1-pre.129 → 8.1.2-pre.152
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 +25 -22
- package/dist/109.js +1 -1
- package/dist/109.js.map +1 -1
- package/dist/124.js +1 -1
- package/dist/124.js.map +1 -1
- package/dist/125.js +1 -1
- package/dist/125.js.map +1 -1
- package/dist/126.js +1 -0
- package/dist/126.js.map +1 -0
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/146.js +1 -1
- package/dist/146.js.map +1 -1
- package/dist/15.js +1 -1
- package/dist/15.js.map +1 -1
- package/dist/348.js +1 -1
- package/dist/362.js +1 -0
- package/dist/362.js.map +1 -0
- package/dist/443.js +1 -0
- package/dist/443.js.map +1 -0
- package/dist/471.js +1 -1
- package/dist/471.js.map +1 -1
- package/dist/481.js +1 -1
- package/dist/481.js.map +1 -1
- package/dist/53.js +1 -1
- package/dist/53.js.map +1 -1
- package/dist/534.js +1 -0
- package/dist/534.js.map +1 -0
- package/dist/559.js +1 -1
- package/dist/559.js.map +1 -1
- package/dist/574.js +1 -1
- package/dist/576.js +1 -1
- package/dist/576.js.map +1 -1
- package/dist/577.js +1 -1
- package/dist/577.js.map +1 -1
- package/dist/598.js +1 -0
- package/dist/598.js.map +1 -0
- package/dist/662.js +1 -1
- package/dist/662.js.map +1 -1
- package/dist/767.js +1 -1
- package/dist/921.js +1 -1
- package/dist/921.js.map +1 -1
- package/dist/922.js +1 -1
- package/dist/922.js.map +1 -1
- package/dist/925.js +2 -0
- package/dist/925.js.LICENSE.txt +40 -0
- package/dist/925.js.map +1 -0
- package/dist/kenyaemr-esm-ward-app.js +1 -1
- package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +169 -139
- package/dist/kenyaemr-esm-ward-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +35 -0
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/mock.tsx +5 -4
- package/package-lock.json +2 -2
- package/package.json +4 -4
- package/src/action-menu-buttons/clinical-forms-workspace-siderail.component.tsx +1 -1
- package/src/action-menu-buttons/discharge-workspace-siderail.component.tsx +1 -1
- package/src/beds/bed-share-divider.component.tsx +21 -0
- package/src/beds/bed-share-divider.scss +18 -0
- package/src/beds/ward-bed.component.tsx +7 -17
- package/src/beds/ward-bed.scss +1 -15
- package/src/beds/ward-bed.test.tsx +3 -3
- package/src/config-schema.ts +6 -0
- package/src/hooks/useEmrConfiguration.ts +8 -0
- package/src/index.ts +6 -6
- package/src/location-selector/location-selector.component.tsx +8 -7
- package/src/root.component.tsx +0 -2
- package/src/routes.json +20 -6
- package/src/types/index.ts +9 -4
- package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +2 -2
- package/src/ward-patient-card/row-elements/ward-patient-pending-transfer.tsx +22 -4
- package/src/ward-patient-card/ward-patient-card.component.tsx +24 -6
- package/src/ward-patient-card/ward-patient-card.scss +6 -0
- package/src/ward-view/default-ward/default-ward-beds.component.tsx +3 -5
- package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +1 -1
- package/src/ward-view/default-ward/default-ward-patient-card.component.tsx +2 -2
- package/src/ward-view/default-ward/default-ward-unassigned-patients.component.tsx +2 -2
- package/src/ward-view/materal-ward/maternal-ward-beds.component.tsx +9 -2
- package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +1 -1
- package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +2 -2
- package/src/ward-view/materal-ward/maternal-ward-view.resource.ts +7 -7
- package/src/ward-view/ward-view.component.tsx +1 -2
- package/src/ward-view/ward.component.tsx +19 -11
- package/src/ward-view-header/admission-requests-bar.component.tsx +4 -2
- package/src/ward-view-header/admission-requests.scss +11 -1
- package/src/ward-view-header/ward-metrics.test.tsx +5 -13
- package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +17 -62
- package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +1 -1
- package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +2 -2
- package/src/ward-workspace/admit-patient-button.component.tsx +82 -0
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.scss +7 -0
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +28 -13
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +72 -66
- package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.scss +55 -0
- package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.test.tsx +99 -0
- package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.workspace.tsx +174 -0
- package/src/ward-workspace/patient-banner/patient-banner.component.tsx +9 -7
- package/src/ward-workspace/patient-banner/style.scss +3 -19
- package/src/ward-workspace/patient-clinical-forms-workspace/patient-clinical-forms.workspace.tsx +8 -2
- package/src/ward-workspace/patient-details/ward-patient-action-button.extension.tsx +2 -3
- package/src/ward-workspace/patient-details/ward-patient.style.scss +12 -0
- package/src/ward-workspace/patient-details/ward-patient.workspace.tsx +18 -47
- package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +14 -24
- package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +12 -34
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +48 -35
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.scss +4 -0
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +1 -1
- package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +30 -25
- package/src/ward-workspace/ward-patient-notes/notes.workspace.tsx +1 -1
- package/src/ward.resource.ts +32 -22
- package/translations/en.json +7 -1
- package/dist/153.js +0 -1
- package/dist/153.js.map +0 -1
- package/dist/169.js +0 -1
- package/dist/169.js.map +0 -1
- package/dist/303.js +0 -2
- package/dist/303.js.LICENSE.txt +0 -5
- package/dist/303.js.map +0 -1
- package/dist/501.js +0 -1
- package/dist/501.js.map +0 -1
- package/dist/920.js +0 -1
- package/dist/920.js.map +0 -1
- package/src/ward-workspace/admit-patient-form-workspace/types.ts +0 -7
|
@@ -1,60 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import React
|
|
3
|
-
import styles from './ward-patient.style.scss';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
1
|
+
import { attach, ExtensionSlot, useConfig } from '@openmrs/esm-framework';
|
|
2
|
+
import React from 'react';
|
|
5
3
|
import { type WardPatientWorkspaceProps } from '../../types';
|
|
6
|
-
import
|
|
4
|
+
import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
|
|
5
|
+
import styles from './ward-patient.style.scss';
|
|
6
|
+
import { type WardConfigObject } from '../../config-schema';
|
|
7
|
+
import classNames from 'classnames';
|
|
7
8
|
|
|
8
9
|
attach('ward-patient-workspace-header-slot', 'patient-vitals-info');
|
|
9
10
|
|
|
10
|
-
export default function WardPatientWorkspace({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
setTitle(patient.person.display, <PatientWorkspaceTitle key={patient.uuid} patient={patient} />);
|
|
15
|
-
}
|
|
16
|
-
}, [wardPatient]);
|
|
11
|
+
export default function WardPatientWorkspace({ wardPatient }: WardPatientWorkspaceProps) {
|
|
12
|
+
const { patient } = wardPatient ?? {};
|
|
13
|
+
const { hideWorkspaceVitalsLinks } = useConfig<WardConfigObject>();
|
|
14
|
+
const extensionSlotState = { patient, patientUuid: patient?.uuid, hideLinks: hideWorkspaceVitalsLinks };
|
|
17
15
|
|
|
18
16
|
return (
|
|
19
17
|
<>
|
|
20
18
|
{wardPatient && (
|
|
21
|
-
<div className={styles.workspaceContainer}>
|
|
22
|
-
<
|
|
19
|
+
<div className={classNames(styles.workspaceContainer, styles.patientWorkspace)}>
|
|
20
|
+
<WardPatientWorkspaceBanner {...{ wardPatient }} />
|
|
21
|
+
<ExtensionSlot name="ward-patient-workspace-header-slot" state={extensionSlotState} />
|
|
22
|
+
<ExtensionSlot
|
|
23
|
+
name="ward-patient-workspace-content-slot"
|
|
24
|
+
state={extensionSlotState}
|
|
25
|
+
className={styles.patientWorkspaceContentSlot}
|
|
26
|
+
/>
|
|
23
27
|
</div>
|
|
24
28
|
)}
|
|
25
29
|
</>
|
|
26
30
|
);
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
interface WardPatientWorkspaceViewProps {
|
|
30
|
-
patient: Patient;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const WardPatientWorkspaceView: React.FC<WardPatientWorkspaceViewProps> = ({ patient }) => {
|
|
34
|
-
const extensionSlotState = { patient, patientUuid: patient.uuid };
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<>
|
|
38
|
-
<div>
|
|
39
|
-
<ExtensionSlot name="ward-patient-workspace-header-slot" state={extensionSlotState} />
|
|
40
|
-
</div>
|
|
41
|
-
<div>
|
|
42
|
-
<ExtensionSlot name="ward-patient-workspace-content-slot" state={extensionSlotState} />
|
|
43
|
-
</div>
|
|
44
|
-
</>
|
|
45
|
-
);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const PatientWorkspaceTitle: React.FC<WardPatientWorkspaceViewProps> = ({ patient }) => {
|
|
49
|
-
const { t } = useTranslation();
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<>
|
|
53
|
-
<div>{patient.person.display} </div>
|
|
54
|
-
<div className={styles.headerPatientDetail}>· {getGender(t, patient.person?.gender)}</div>
|
|
55
|
-
{patient.person?.birthdate && (
|
|
56
|
-
<div className={styles.headerPatientDetail}>· {age(patient.person?.birthdate)}</div>
|
|
57
|
-
)}
|
|
58
|
-
</>
|
|
59
|
-
);
|
|
60
|
-
};
|
|
@@ -1,39 +1,28 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
1
2
|
import { Button, ButtonSet, InlineNotification } from '@carbon/react';
|
|
2
3
|
import { Exit } from '@carbon/react/icons';
|
|
3
|
-
import { ExtensionSlot, showSnackbar, useAppContext, useSession } from '@openmrs/esm-framework';
|
|
4
|
-
import React, { useCallback, useState } from 'react';
|
|
5
4
|
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import
|
|
7
|
-
import useWardLocation from '../../hooks/useWardLocation';
|
|
5
|
+
import { ExtensionSlot, showSnackbar, useAppContext, useSession } from '@openmrs/esm-framework';
|
|
8
6
|
import { type WardPatientWorkspaceProps, type WardViewContext } from '../../types';
|
|
9
|
-
import {
|
|
7
|
+
import { removePatientFromBed, useCreateEncounter } from '../../ward.resource';
|
|
8
|
+
import useWardLocation from '../../hooks/useWardLocation';
|
|
10
9
|
import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
|
|
11
10
|
import styles from './patient-discharge.scss';
|
|
12
11
|
|
|
13
12
|
export default function PatientDischargeWorkspace(props: WardPatientWorkspaceProps) {
|
|
14
13
|
const { wardPatient, closeWorkspaceWithSavedChanges } = props;
|
|
15
14
|
const { t } = useTranslation();
|
|
16
|
-
const [isSubmitting, setIsSubmitting] = useState
|
|
15
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
17
16
|
const { currentProvider } = useSession();
|
|
18
17
|
const { location } = useWardLocation();
|
|
19
|
-
const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
18
|
+
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
19
|
+
useCreateEncounter();
|
|
20
20
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
21
21
|
|
|
22
22
|
const submitDischarge = useCallback(() => {
|
|
23
23
|
setIsSubmitting(true);
|
|
24
24
|
|
|
25
|
-
createEncounter(
|
|
26
|
-
patient: wardPatient?.patient?.uuid,
|
|
27
|
-
encounterType: emrConfiguration.exitFromInpatientEncounterType.uuid,
|
|
28
|
-
location: location.uuid,
|
|
29
|
-
encounterProviders: [
|
|
30
|
-
{
|
|
31
|
-
encounterRole: emrConfiguration.clinicianEncounterRole.uuid,
|
|
32
|
-
provider: currentProvider?.uuid,
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
obs: [],
|
|
36
|
-
})
|
|
25
|
+
createEncounter(wardPatient?.patient, emrConfiguration.exitFromInpatientEncounterType)
|
|
37
26
|
.then((response) => {
|
|
38
27
|
if (response?.ok) {
|
|
39
28
|
if (wardPatient?.bed?.id) {
|
|
@@ -63,11 +52,12 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
|
|
|
63
52
|
wardPatientGroupDetails.mutate();
|
|
64
53
|
});
|
|
65
54
|
}, [
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
createEncounter,
|
|
56
|
+
wardPatient?.patient,
|
|
57
|
+
wardPatient.bed.id,
|
|
68
58
|
emrConfiguration,
|
|
69
|
-
|
|
70
|
-
|
|
59
|
+
t,
|
|
60
|
+
closeWorkspaceWithSavedChanges,
|
|
71
61
|
wardPatientGroupDetails,
|
|
72
62
|
]);
|
|
73
63
|
|
|
@@ -75,7 +65,7 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
|
|
|
75
65
|
return (
|
|
76
66
|
<div className={styles.workspaceContent}>
|
|
77
67
|
<div className={styles.patientWorkspaceBanner}>
|
|
78
|
-
<WardPatientWorkspaceBanner {
|
|
68
|
+
<WardPatientWorkspaceBanner wardPatient={props?.wardPatient} />
|
|
79
69
|
</div>
|
|
80
70
|
<div className={styles.workspaceForm}>
|
|
81
71
|
<div>
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
1
2
|
import { Button, ButtonSet, Form, InlineNotification } from '@carbon/react';
|
|
2
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
3
|
-
import { showSnackbar, useAppContext, useSession } from '@openmrs/esm-framework';
|
|
4
3
|
import classNames from 'classnames';
|
|
5
|
-
import
|
|
4
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
6
5
|
import { Controller, useForm } from 'react-hook-form';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
7
|
import { z } from 'zod';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import { assignPatientToBed, createEncounter, removePatientFromBed } from '../../ward.resource';
|
|
8
|
+
import { showSnackbar, useAppContext } from '@openmrs/esm-framework';
|
|
9
|
+
import type { WardPatientWorkspaceProps, WardViewContext } from '../../types';
|
|
10
|
+
import { assignPatientToBed, useCreateEncounter, removePatientFromBed } from '../../ward.resource';
|
|
13
11
|
import BedSelector from '../bed-selector.component';
|
|
14
12
|
import styles from './patient-transfer-swap.scss';
|
|
15
13
|
|
|
@@ -21,10 +19,9 @@ export default function PatientBedSwapForm({
|
|
|
21
19
|
const { patient } = wardPatient;
|
|
22
20
|
const { t } = useTranslation();
|
|
23
21
|
const [showErrorNotifications, setShowErrorNotifications] = useState(false);
|
|
24
|
-
const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
22
|
+
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
23
|
+
useCreateEncounter();
|
|
25
24
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
26
|
-
const { currentProvider } = useSession();
|
|
27
|
-
const { location } = useWardLocation();
|
|
28
25
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
29
26
|
const { isLoading } = wardPatientGroupDetails?.admissionLocationResponse ?? {};
|
|
30
27
|
|
|
@@ -50,35 +47,16 @@ export default function PatientBedSwapForm({
|
|
|
50
47
|
useEffect(() => {
|
|
51
48
|
promptBeforeClosing(() => isDirty);
|
|
52
49
|
return () => promptBeforeClosing(null);
|
|
53
|
-
}, [isDirty]);
|
|
54
|
-
|
|
55
|
-
const getBedInformation = useCallback(
|
|
56
|
-
(bed: BedLayout) => {
|
|
57
|
-
const patients = bed.patients.map((bedPatient) => bedPatient?.person?.preferredName?.display);
|
|
58
|
-
const bedNumber = bed.bedNumber;
|
|
59
|
-
return [bedNumber, ...(patients.length ? patients : [t('empty', 'Empty')])].join(' · ');
|
|
60
|
-
},
|
|
61
|
-
[t],
|
|
62
|
-
);
|
|
50
|
+
}, [isDirty, promptBeforeClosing]);
|
|
63
51
|
|
|
64
|
-
const beds = wardPatientGroupDetails?.bedLayouts ?? [];
|
|
52
|
+
const beds = useMemo(() => wardPatientGroupDetails?.bedLayouts ?? [], [wardPatientGroupDetails]);
|
|
65
53
|
|
|
66
54
|
const onSubmit = useCallback(
|
|
67
55
|
(values: FormValues) => {
|
|
68
56
|
const bedSelected = beds.find((bed) => bed.bedId === values.bedId);
|
|
57
|
+
setIsSubmitting(true);
|
|
69
58
|
setShowErrorNotifications(false);
|
|
70
|
-
createEncounter(
|
|
71
|
-
patient: patient.uuid,
|
|
72
|
-
encounterType: emrConfiguration.transferWithinHospitalEncounterType.uuid,
|
|
73
|
-
location: location?.uuid,
|
|
74
|
-
encounterProviders: [
|
|
75
|
-
{
|
|
76
|
-
provider: currentProvider?.uuid,
|
|
77
|
-
encounterRole: emrConfiguration.clinicianEncounterRole.uuid,
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
obs: [],
|
|
81
|
-
})
|
|
59
|
+
createEncounter(patient, emrConfiguration.bedAssignmentEncounterType)
|
|
82
60
|
.then(async (response) => {
|
|
83
61
|
if (response.ok) {
|
|
84
62
|
if (bedSelected) {
|
|
@@ -132,7 +110,7 @@ export default function PatientBedSwapForm({
|
|
|
132
110
|
closeWorkspaceWithSavedChanges();
|
|
133
111
|
});
|
|
134
112
|
},
|
|
135
|
-
[
|
|
113
|
+
[beds, createEncounter, patient, emrConfiguration, t, wardPatientGroupDetails, closeWorkspaceWithSavedChanges],
|
|
136
114
|
);
|
|
137
115
|
|
|
138
116
|
const onError = useCallback(() => {
|
package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { Button, ButtonSet, Form, InlineNotification, RadioButton, RadioButtonGroup, TextArea } from '@carbon/react';
|
|
2
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
3
|
-
import { ResponsiveWrapper, showSnackbar, useAppContext, useSession } from '@openmrs/esm-framework';
|
|
4
|
-
import classNames from 'classnames';
|
|
5
1
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { Button, ButtonSet, Form, InlineNotification, RadioButton, RadioButtonGroup, TextArea } from '@carbon/react';
|
|
6
5
|
import { Controller, useForm } from 'react-hook-form';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
7
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
8
|
+
import { ResponsiveWrapper, showSnackbar, useAppContext, useLayoutType, useSession } from '@openmrs/esm-framework';
|
|
9
|
+
import { useCreateEncounter } from '../../ward.resource';
|
|
10
|
+
import type { ObsPayload, WardPatientWorkspaceProps, WardViewContext } from '../../types';
|
|
10
11
|
import useWardLocation from '../../hooks/useWardLocation';
|
|
12
|
+
import AdmissionPatientButton from '../admit-patient-button.component';
|
|
11
13
|
import LocationSelector from '../../location-selector/location-selector.component';
|
|
12
|
-
import type { ObsPayload, WardPatientWorkspaceProps, WardViewContext } from '../../types';
|
|
13
|
-
import { createEncounter } from '../../ward.resource';
|
|
14
14
|
import styles from './patient-transfer-swap.scss';
|
|
15
15
|
|
|
16
16
|
export default function PatientTransferForm({
|
|
@@ -18,11 +18,12 @@ export default function PatientTransferForm({
|
|
|
18
18
|
wardPatient,
|
|
19
19
|
promptBeforeClosing,
|
|
20
20
|
}: WardPatientWorkspaceProps) {
|
|
21
|
-
const { patient } = wardPatient ?? {};
|
|
22
21
|
const { t } = useTranslation();
|
|
22
|
+
const { patient, inpatientAdmission } = wardPatient ?? {};
|
|
23
23
|
const [showErrorNotifications, setShowErrorNotifications] = useState(false);
|
|
24
24
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
25
|
-
const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
25
|
+
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
26
|
+
useCreateEncounter();
|
|
26
27
|
const { currentProvider } = useSession();
|
|
27
28
|
const { location } = useWardLocation();
|
|
28
29
|
const dispositionsWithTypeTransfer = useMemo(
|
|
@@ -30,6 +31,8 @@ export default function PatientTransferForm({
|
|
|
30
31
|
[emrConfiguration],
|
|
31
32
|
);
|
|
32
33
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
34
|
+
const responsiveSize = useLayoutType() === 'tablet' ? 'lg' : 'md';
|
|
35
|
+
const isAdmitted = inpatientAdmission != null;
|
|
33
36
|
|
|
34
37
|
const zodSchema = useMemo(
|
|
35
38
|
() =>
|
|
@@ -69,12 +72,12 @@ export default function PatientTransferForm({
|
|
|
69
72
|
if (dispositionsWithTypeTransfer?.length === 1) {
|
|
70
73
|
setValue('transferType', dispositionsWithTypeTransfer[0].uuid);
|
|
71
74
|
}
|
|
72
|
-
}, [dispositionsWithTypeTransfer]);
|
|
75
|
+
}, [dispositionsWithTypeTransfer, setValue]);
|
|
73
76
|
|
|
74
77
|
useEffect(() => {
|
|
75
78
|
promptBeforeClosing(() => isDirty);
|
|
76
79
|
return () => promptBeforeClosing(null);
|
|
77
|
-
}, [isDirty]);
|
|
80
|
+
}, [isDirty, promptBeforeClosing]);
|
|
78
81
|
|
|
79
82
|
const onSubmit = useCallback(
|
|
80
83
|
(values: FormValues) => {
|
|
@@ -98,23 +101,12 @@ export default function PatientTransferForm({
|
|
|
98
101
|
});
|
|
99
102
|
}
|
|
100
103
|
|
|
101
|
-
createEncounter(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
encounterRole: emrConfiguration.clinicianEncounterRole.uuid,
|
|
108
|
-
provider: currentProvider?.uuid,
|
|
109
|
-
},
|
|
110
|
-
],
|
|
111
|
-
obs: [
|
|
112
|
-
{
|
|
113
|
-
concept: emrConfiguration.dispositionDescriptor.dispositionSetConcept.uuid,
|
|
114
|
-
groupMembers: obs,
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
})
|
|
104
|
+
createEncounter(patient, emrConfiguration.transferRequestEncounterType, [
|
|
105
|
+
{
|
|
106
|
+
concept: emrConfiguration.dispositionDescriptor.dispositionSetConcept.uuid,
|
|
107
|
+
groupMembers: obs,
|
|
108
|
+
},
|
|
109
|
+
])
|
|
118
110
|
.then(() => {
|
|
119
111
|
showSnackbar({
|
|
120
112
|
title: t('patientTransferRequestCreated', 'Patient transfer request created'),
|
|
@@ -135,12 +127,12 @@ export default function PatientTransferForm({
|
|
|
135
127
|
});
|
|
136
128
|
},
|
|
137
129
|
[
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
location,
|
|
141
|
-
emrConfiguration,
|
|
142
|
-
patient?.uuid,
|
|
130
|
+
closeWorkspaceWithSavedChanges,
|
|
131
|
+
createEncounter,
|
|
143
132
|
dispositionsWithTypeTransfer,
|
|
133
|
+
emrConfiguration,
|
|
134
|
+
patient,
|
|
135
|
+
t,
|
|
144
136
|
wardPatientGroupDetails,
|
|
145
137
|
],
|
|
146
138
|
);
|
|
@@ -150,7 +142,28 @@ export default function PatientTransferForm({
|
|
|
150
142
|
setShowErrorNotifications(true);
|
|
151
143
|
}, []);
|
|
152
144
|
|
|
153
|
-
if (!wardPatientGroupDetails)
|
|
145
|
+
if (!wardPatientGroupDetails) {
|
|
146
|
+
return <></>;
|
|
147
|
+
}
|
|
148
|
+
if (!isAdmitted) {
|
|
149
|
+
return (
|
|
150
|
+
<div className={styles.workspaceContent}>
|
|
151
|
+
<div className={styles.formError}>
|
|
152
|
+
<InlineNotification
|
|
153
|
+
kind="info"
|
|
154
|
+
title={t('unableToTransferPatient', 'Unable to transfer patient')}
|
|
155
|
+
subtitle={t(
|
|
156
|
+
'unableToTransferPatientNotYetAdmitted',
|
|
157
|
+
'This patient is not admitted to this ward. Admit this patient before transferring them to a different location.',
|
|
158
|
+
)}
|
|
159
|
+
lowContrast
|
|
160
|
+
hideCloseButton
|
|
161
|
+
/>
|
|
162
|
+
</div>
|
|
163
|
+
<AdmissionPatientButton wardPatient={wardPatient} onAdmitPatientSuccess={closeWorkspaceWithSavedChanges} />
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
154
167
|
return (
|
|
155
168
|
<Form
|
|
156
169
|
onSubmit={handleSubmit(onSubmit, onError)}
|
|
@@ -23,7 +23,7 @@ export default function PatientTransferAndSwapWorkspace(props: WardPatientWorksp
|
|
|
23
23
|
return (
|
|
24
24
|
<div className={styles.flexWrapper}>
|
|
25
25
|
<div className={styles.patientWorkspaceBanner}>
|
|
26
|
-
<WardPatientWorkspaceBanner {
|
|
26
|
+
<WardPatientWorkspaceBanner wardPatient={props?.wardPatient} />
|
|
27
27
|
</div>
|
|
28
28
|
{isBedManagementModuleInstalled && (
|
|
29
29
|
<div className={styles.contentSwitcherWrapper}>
|
|
@@ -5,7 +5,6 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
5
5
|
import { Controller, useForm } from 'react-hook-form';
|
|
6
6
|
import { Button, Column, Form, InlineLoading, InlineNotification, Row, Stack, TextArea } from '@carbon/react';
|
|
7
7
|
import {
|
|
8
|
-
createErrorHandler,
|
|
9
8
|
type DefaultWorkspaceProps,
|
|
10
9
|
type PatientUuid,
|
|
11
10
|
ResponsiveWrapper,
|
|
@@ -13,13 +12,17 @@ import {
|
|
|
13
12
|
translateFrom,
|
|
14
13
|
useSession,
|
|
15
14
|
} from '@openmrs/esm-framework';
|
|
16
|
-
import { savePatientNote } from '../notes.resource';
|
|
17
|
-
import styles from './notes-form.scss';
|
|
18
15
|
import { moduleName } from '../../../constant';
|
|
16
|
+
import { savePatientNote } from '../notes.resource';
|
|
19
17
|
import useEmrConfiguration from '../../../hooks/useEmrConfiguration';
|
|
18
|
+
import styles from './notes-form.scss';
|
|
20
19
|
|
|
21
20
|
type NotesFormData = z.infer<typeof noteFormSchema>;
|
|
22
21
|
|
|
22
|
+
interface PatientNotesFormProps extends DefaultWorkspaceProps {
|
|
23
|
+
patientUuid: PatientUuid;
|
|
24
|
+
}
|
|
25
|
+
|
|
23
26
|
const noteFormSchema = z.object({
|
|
24
27
|
wardClinicalNote: z.string().refine((val) => val.trim().length > 0, {
|
|
25
28
|
//t('clinicalNoteErrorMessage','Clinical note is required')
|
|
@@ -27,10 +30,6 @@ const noteFormSchema = z.object({
|
|
|
27
30
|
}),
|
|
28
31
|
});
|
|
29
32
|
|
|
30
|
-
interface PatientNotesFormProps extends DefaultWorkspaceProps {
|
|
31
|
-
patientUuid: PatientUuid;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
33
|
const PatientNotesForm: React.FC<PatientNotesFormProps> = ({
|
|
35
34
|
closeWorkspaceWithSavedChanges,
|
|
36
35
|
patientUuid,
|
|
@@ -39,8 +38,9 @@ const PatientNotesForm: React.FC<PatientNotesFormProps> = ({
|
|
|
39
38
|
const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
|
|
40
39
|
const { t } = useTranslation();
|
|
41
40
|
const session = useSession();
|
|
41
|
+
|
|
42
42
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
43
|
-
const [rows, setRows] = useState
|
|
43
|
+
const [rows, setRows] = useState(0);
|
|
44
44
|
|
|
45
45
|
const {
|
|
46
46
|
control,
|
|
@@ -93,26 +93,31 @@ const PatientNotesForm: React.FC<PatientNotesFormProps> = ({
|
|
|
93
93
|
closeWorkspaceWithSavedChanges();
|
|
94
94
|
showSnackbar({
|
|
95
95
|
isLowContrast: true,
|
|
96
|
-
subtitle: t('patientNoteNowVisible', 'It should be now visible in the notes history'),
|
|
97
96
|
kind: 'success',
|
|
97
|
+
subtitle: t('patientNoteNowVisible', 'It should be now visible in the notes history'),
|
|
98
98
|
title: t('visitNoteSaved', 'Patient note saved'),
|
|
99
99
|
});
|
|
100
100
|
})
|
|
101
101
|
.catch((err) => {
|
|
102
|
-
createErrorHandler();
|
|
103
|
-
|
|
104
102
|
showSnackbar({
|
|
105
|
-
title: t('patientNoteSaveError', 'Error saving patient note'),
|
|
106
|
-
kind: 'error',
|
|
107
103
|
isLowContrast: false,
|
|
104
|
+
kind: 'error',
|
|
108
105
|
subtitle: err?.message,
|
|
106
|
+
title: t('patientNoteSaveError', 'Error saving patient note'),
|
|
109
107
|
});
|
|
110
108
|
})
|
|
111
|
-
.finally(() =>
|
|
112
|
-
setIsSubmitting(false);
|
|
113
|
-
});
|
|
109
|
+
.finally(() => setIsSubmitting(false));
|
|
114
110
|
},
|
|
115
|
-
[
|
|
111
|
+
[
|
|
112
|
+
closeWorkspaceWithSavedChanges,
|
|
113
|
+
emrConfiguration?.clinicianEncounterRole.uuid,
|
|
114
|
+
emrConfiguration?.consultFreeTextCommentsConcept.uuid,
|
|
115
|
+
emrConfiguration?.inpatientNoteEncounterType.uuid,
|
|
116
|
+
locationUuid,
|
|
117
|
+
patientUuid,
|
|
118
|
+
providerUuid,
|
|
119
|
+
t,
|
|
120
|
+
],
|
|
116
121
|
);
|
|
117
122
|
|
|
118
123
|
const onError = (errors) => console.error(errors);
|
|
@@ -146,19 +151,19 @@ const PatientNotesForm: React.FC<PatientNotesFormProps> = ({
|
|
|
146
151
|
<ResponsiveWrapper>
|
|
147
152
|
<TextArea
|
|
148
153
|
id="additionalNote"
|
|
149
|
-
rows={rows}
|
|
150
|
-
labelText={t('clinicalNoteLabel', 'Write your notes')}
|
|
151
|
-
placeholder={t('wardClinicalNotePlaceholder', 'Write any notes here')}
|
|
152
|
-
value={value}
|
|
153
|
-
onBlur={onBlur}
|
|
154
154
|
invalid={!!errors.wardClinicalNote}
|
|
155
155
|
invalidText={errors.wardClinicalNote?.message}
|
|
156
|
+
labelText={t('clinicalNoteLabel', 'Write your notes')}
|
|
157
|
+
onBlur={onBlur}
|
|
156
158
|
onChange={(event) => {
|
|
157
159
|
onChange(event);
|
|
158
|
-
const
|
|
159
|
-
const newRows = Math.ceil(event.target.scrollHeight /
|
|
160
|
+
const textAreaLineHeight = 24; // This is the default line height for Carbon's TextArea component
|
|
161
|
+
const newRows = Math.ceil(event.target.scrollHeight / textAreaLineHeight);
|
|
160
162
|
setRows(newRows);
|
|
161
163
|
}}
|
|
164
|
+
placeholder={t('wardClinicalNotePlaceholder', 'Write any notes here')}
|
|
165
|
+
rows={rows}
|
|
166
|
+
value={value}
|
|
162
167
|
/>
|
|
163
168
|
</ResponsiveWrapper>
|
|
164
169
|
)}
|
|
@@ -167,9 +172,9 @@ const PatientNotesForm: React.FC<PatientNotesFormProps> = ({
|
|
|
167
172
|
</Row>
|
|
168
173
|
</Stack>
|
|
169
174
|
<Button
|
|
170
|
-
kind="primary"
|
|
171
175
|
className={styles.saveButton}
|
|
172
176
|
disabled={isSubmitting || isLoadingEmrConfiguration || errorFetchingEmrConfiguration}
|
|
177
|
+
kind="primary"
|
|
173
178
|
type="submit">
|
|
174
179
|
{isSubmitting ? <InlineLoading description={t('saving', 'Saving...')} /> : <span>{t('save', 'Save')}</span>}
|
|
175
180
|
</Button>
|
|
@@ -15,7 +15,7 @@ const WardPatientNotesWorkspace: React.FC<WardPatientWorkspaceProps> = (props) =
|
|
|
15
15
|
|
|
16
16
|
return (
|
|
17
17
|
<div>
|
|
18
|
-
<WardPatientWorkspaceBanner {...wardPatient} />
|
|
18
|
+
<WardPatientWorkspaceBanner {...{ wardPatient }} />
|
|
19
19
|
<PatientNotesForm {...notesFormState} />
|
|
20
20
|
<PatientNotesHistory patientUuid={patientUuid} visitUuid={wardPatient?.visit?.uuid} />
|
|
21
21
|
</div>
|
package/src/ward.resource.ts
CHANGED
|
@@ -1,32 +1,17 @@
|
|
|
1
|
-
import { openmrsFetch, type Patient, restBaseUrl, useSession } from '@openmrs/esm-framework';
|
|
2
|
-
import type { DispositionType, Encounter, EncounterPayload } from './types';
|
|
1
|
+
import { openmrsFetch, type OpenmrsResource, type Patient, restBaseUrl, useSession } from '@openmrs/esm-framework';
|
|
2
|
+
import type { DispositionType, Encounter, EncounterPayload, ObsPayload } from './types';
|
|
3
3
|
import useEmrConfiguration from './hooks/useEmrConfiguration';
|
|
4
4
|
import useWardLocation from './hooks/useWardLocation';
|
|
5
5
|
|
|
6
|
-
export function
|
|
7
|
-
return openmrsFetch<Encounter>(`${restBaseUrl}/encounter`, {
|
|
8
|
-
method: 'POST',
|
|
9
|
-
headers: {
|
|
10
|
-
'content-type': 'application/json',
|
|
11
|
-
},
|
|
12
|
-
body: encounterPayload,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function useAdmitPatient() {
|
|
6
|
+
export function useCreateEncounter() {
|
|
17
7
|
const { location } = useWardLocation();
|
|
18
8
|
const { currentProvider } = useSession();
|
|
19
9
|
const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
|
|
20
10
|
|
|
21
|
-
const
|
|
22
|
-
|
|
11
|
+
const createEncounter = (patient: Patient, encounterType: OpenmrsResource, obs: ObsPayload[] = []) => {
|
|
12
|
+
const encounterPayload = {
|
|
23
13
|
patient: patient.uuid,
|
|
24
|
-
encounterType
|
|
25
|
-
dispositionType === 'ADMIT'
|
|
26
|
-
? emrConfiguration.admissionEncounterType.uuid
|
|
27
|
-
: dispositionType === 'TRANSFER'
|
|
28
|
-
? emrConfiguration.transferWithinHospitalEncounterType.uuid
|
|
29
|
-
: null,
|
|
14
|
+
encounterType,
|
|
30
15
|
location: location?.uuid,
|
|
31
16
|
encounterProviders: [
|
|
32
17
|
{
|
|
@@ -34,10 +19,35 @@ export function useAdmitPatient() {
|
|
|
34
19
|
encounterRole: emrConfiguration.clinicianEncounterRole.uuid,
|
|
35
20
|
},
|
|
36
21
|
],
|
|
37
|
-
obs
|
|
22
|
+
obs,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return openmrsFetch<Encounter>(`${restBaseUrl}/encounter`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
headers: {
|
|
28
|
+
'content-type': 'application/json',
|
|
29
|
+
},
|
|
30
|
+
body: encounterPayload,
|
|
38
31
|
});
|
|
39
32
|
};
|
|
40
33
|
|
|
34
|
+
return { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function useAdmitPatient() {
|
|
38
|
+
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
39
|
+
useCreateEncounter();
|
|
40
|
+
|
|
41
|
+
const admitPatient = (patient: Patient, dispositionType: DispositionType) => {
|
|
42
|
+
const encounterType =
|
|
43
|
+
dispositionType === 'ADMIT'
|
|
44
|
+
? emrConfiguration.admissionEncounterType
|
|
45
|
+
: dispositionType === 'TRANSFER'
|
|
46
|
+
? emrConfiguration.transferWithinHospitalEncounterType
|
|
47
|
+
: null;
|
|
48
|
+
return createEncounter(patient, encounterType);
|
|
49
|
+
};
|
|
50
|
+
|
|
41
51
|
return { admitPatient, isLoadingEmrConfiguration, errorFetchingEmrConfiguration };
|
|
42
52
|
}
|
|
43
53
|
|
package/translations/en.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"admissionRequestCancelled": "Admission request cancelled.",
|
|
2
3
|
"admissionRequests": "Admission requests",
|
|
3
4
|
"admissionRequestsCount_one": "{{count}} admission request",
|
|
4
5
|
"admissionRequestsCount_other": "{{count}} admission requests",
|
|
@@ -8,18 +9,20 @@
|
|
|
8
9
|
"bedShare": "Bed share",
|
|
9
10
|
"bedSwap": "Bed swap",
|
|
10
11
|
"cancel": "Cancel",
|
|
12
|
+
"cancelAdmissionRequest": "Cancel admission request",
|
|
11
13
|
"capacity": "Capacity",
|
|
12
14
|
"capacityMetricValue": "{{ metricValue }} %",
|
|
13
15
|
"chooseAnOption": "Choose an option",
|
|
14
16
|
"clinicalForms": "Clinical forms",
|
|
15
17
|
"clinicalNoteLabel": "Write your notes",
|
|
18
|
+
"clinicalNotes": "Clinical notes",
|
|
16
19
|
"countItems_one": "{{count}} {{item}}",
|
|
17
20
|
"countItems_other": "{{count}} {{item}}",
|
|
18
21
|
"discharge": "Discharge",
|
|
19
|
-
"empty": "Empty",
|
|
20
22
|
"emptyBed": "Empty bed",
|
|
21
23
|
"emptyText": "Empty",
|
|
22
24
|
"encounterDisplay": "{{encounterType}} {{encounterDate}}",
|
|
25
|
+
"Error cancelling admission request": "Error cancelling admission request",
|
|
23
26
|
"errorChangingPatientBedAssignment": "Error changing patient bed assignment",
|
|
24
27
|
"errorConfiguringPatientCard": "Error configuring patient card",
|
|
25
28
|
"errorConfiguringPatientCardMessage": "Unable to find configuration for {{elementType}}, id: {{id}}",
|
|
@@ -50,6 +53,7 @@
|
|
|
50
53
|
"noLocationsFound": "No locations found",
|
|
51
54
|
"note": "Note",
|
|
52
55
|
"notes": "Notes",
|
|
56
|
+
"notesRequiredForCancellingRequest": "Notes required for cancelling admission or transfer request",
|
|
53
57
|
"Orders": "Orders",
|
|
54
58
|
"other": "Other",
|
|
55
59
|
"patientAdmittedButBedNotAssigned": "Patient admitted successfully but fail to assign bed to patient",
|
|
@@ -89,6 +93,8 @@
|
|
|
89
93
|
"transfers": "Transfers",
|
|
90
94
|
"transferType": "Transfer type",
|
|
91
95
|
"typeOfTransfer": "Type of transfer",
|
|
96
|
+
"unableToTransferPatient": "Unable to transfer patient",
|
|
97
|
+
"unableToTransferPatientNotYetAdmitted": "This patient is not admitted to this ward. Admit this patient before transferring them to a different location.",
|
|
92
98
|
"unknown": "Unknown",
|
|
93
99
|
"visitNoteSaved": "Patient note saved",
|
|
94
100
|
"wardClinicalNotePlaceholder": "Write any notes here",
|