@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
|
@@ -6,12 +6,12 @@ import WardPatientCard from '../../ward-patient-card/ward-patient-card.component
|
|
|
6
6
|
import styles from '../../ward-patient-card/ward-patient-card.scss';
|
|
7
7
|
import DefaultWardPatientCardHeader from './default-ward-patient-card-header.component';
|
|
8
8
|
|
|
9
|
-
const DefaultWardPatientCard: WardPatientCardType = (wardPatient) => {
|
|
9
|
+
const DefaultWardPatientCard: WardPatientCardType = ({ wardPatient }) => {
|
|
10
10
|
const { bed } = wardPatient;
|
|
11
11
|
|
|
12
12
|
const card = (
|
|
13
13
|
<WardPatientCard wardPatient={wardPatient}>
|
|
14
|
-
<DefaultWardPatientCardHeader {...wardPatient} />
|
|
14
|
+
<DefaultWardPatientCardHeader {...{ wardPatient }} />
|
|
15
15
|
<PendingItemsRow id={'pending-items'} wardPatient={wardPatient} />
|
|
16
16
|
<AdmissionRequestNoteRow id={'admission-request-note'} wardPatient={wardPatient} />
|
|
17
17
|
</WardPatientCard>
|
|
@@ -8,13 +8,13 @@ import DefaultWardPatientCard from './default-ward-patient-card.component';
|
|
|
8
8
|
* @returns
|
|
9
9
|
*/
|
|
10
10
|
function DefaultWardUnassignedPatients() {
|
|
11
|
-
const {wardPatientGroupDetails} = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
11
|
+
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
12
12
|
const { wardUnassignedPatientsList } = wardPatientGroupDetails ?? {};
|
|
13
13
|
|
|
14
14
|
const wardUnassignedPatients = wardUnassignedPatientsList?.map((inpatientAdmission) => {
|
|
15
15
|
return (
|
|
16
16
|
<DefaultWardPatientCard
|
|
17
|
-
{
|
|
17
|
+
wardPatient={{
|
|
18
18
|
patient: inpatientAdmission.patient,
|
|
19
19
|
visit: inpatientAdmission.visit,
|
|
20
20
|
bed: null,
|
|
@@ -6,7 +6,7 @@ import { bedLayoutToBed } from '../ward-view.resource';
|
|
|
6
6
|
import MaternalWardPatientCard from './maternal-ward-patient-card.component';
|
|
7
7
|
|
|
8
8
|
const MaternalWardBeds: React.FC<MotherChildRelationships> = (motherChildRelationships) => {
|
|
9
|
-
const { motherByChildUuid } = motherChildRelationships ?? {};
|
|
9
|
+
const { motherByChildUuid, isLoading: isLoadingMotherChildRelationships } = motherChildRelationships ?? {};
|
|
10
10
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
11
11
|
const { bedLayouts, wardAdmittedPatientsWithBed } = wardPatientGroupDetails ?? {};
|
|
12
12
|
|
|
@@ -56,7 +56,14 @@ const MaternalWardBeds: React.FC<MotherChildRelationships> = (motherChildRelatio
|
|
|
56
56
|
/>
|
|
57
57
|
));
|
|
58
58
|
|
|
59
|
-
return
|
|
59
|
+
return (
|
|
60
|
+
<WardBed
|
|
61
|
+
key={bed.uuid}
|
|
62
|
+
bed={bed}
|
|
63
|
+
patientCards={patientCards}
|
|
64
|
+
isLoadingDivider={isLoadingMotherChildRelationships}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
60
67
|
});
|
|
61
68
|
|
|
62
69
|
return <>{wardBeds}</>;
|
|
@@ -10,7 +10,7 @@ import WardPatientObs from '../../ward-patient-card/row-elements/ward-patient-ob
|
|
|
10
10
|
import WardPatientTimeSinceAdmission from '../../ward-patient-card/row-elements/ward-patient-time-since-admission';
|
|
11
11
|
import styles from '../../ward-patient-card/ward-patient-card.scss';
|
|
12
12
|
|
|
13
|
-
const MaternalWardPatientCardHeader: WardPatientCardType = (wardPatient) => {
|
|
13
|
+
const MaternalWardPatientCardHeader: WardPatientCardType = ({ wardPatient }) => {
|
|
14
14
|
const { patient, bed, visit, inpatientAdmission } = wardPatient;
|
|
15
15
|
const { firstAdmissionOrTransferEncounter } = inpatientAdmission ?? {};
|
|
16
16
|
|
|
@@ -43,7 +43,7 @@ const MaternalWardPatientCard: React.FC<MaternalWardPatientCardProps> = (props)
|
|
|
43
43
|
const card = (
|
|
44
44
|
<>
|
|
45
45
|
<WardPatientCard wardPatient={wardPatient}>
|
|
46
|
-
<MaternalWardPatientCardHeader {...wardPatient} />
|
|
46
|
+
<MaternalWardPatientCardHeader {...{ wardPatient }} />
|
|
47
47
|
<div className={classNames(styles.wardPatientCardRow, styles.dotSeparatedChildren)}>
|
|
48
48
|
<WardPatientTimeOnWard
|
|
49
49
|
encounterAssigningToCurrentInpatientLocation={encounterAssigningToCurrentInpatientLocation}
|
|
@@ -59,7 +59,7 @@ const MaternalWardPatientCard: React.FC<MaternalWardPatientCardProps> = (props)
|
|
|
59
59
|
<React.Fragment key={childWardPatient.patient.uuid}>
|
|
60
60
|
<MotherChildBedShareDivider />
|
|
61
61
|
<WardPatientCard wardPatient={childWardPatient}>
|
|
62
|
-
<MaternalWardPatientCardHeader {
|
|
62
|
+
<MaternalWardPatientCardHeader wardPatient={childWardPatient} />
|
|
63
63
|
<PendingItemsRow id={'pending-items'} wardPatient={childWardPatient} />
|
|
64
64
|
</WardPatientCard>
|
|
65
65
|
</React.Fragment>
|
|
@@ -2,12 +2,15 @@ import { showNotification } from '@openmrs/esm-framework';
|
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { useMotherAndChildren, type MothersAndChildrenSearchCriteria } from '../../hooks/useMotherAndChildren';
|
|
5
|
-
import { type PatientAndAdmission } from '../../types';
|
|
5
|
+
import { type MotherChildRelationships, type PatientAndAdmission } from '../../types';
|
|
6
6
|
|
|
7
7
|
const motherAndChildrenRep =
|
|
8
8
|
'custom:(childAdmission,mother:(person,identifiers:full,uuid),child:(person,identifiers:full,uuid),motherAdmission)';
|
|
9
9
|
|
|
10
|
-
export function useMotherChildrenRelationshipsByPatient(
|
|
10
|
+
export function useMotherChildrenRelationshipsByPatient(
|
|
11
|
+
allWardPatientUuids: string[],
|
|
12
|
+
fetch: boolean,
|
|
13
|
+
): MotherChildRelationships {
|
|
11
14
|
const { t } = useTranslation();
|
|
12
15
|
|
|
13
16
|
const getChildrenRequestParams: MothersAndChildrenSearchCriteria = {
|
|
@@ -53,12 +56,9 @@ export function useMotherChildrenRelationshipsByPatient(allWardPatientUuids: str
|
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
const relationships = useMemo(() => {
|
|
56
|
-
if (isLoadingChildrenData || isLoadingMotherData) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
59
|
const motherByChildUuid = new Map<string, PatientAndAdmission>();
|
|
61
60
|
const childrenByMotherUuid = new Map<string, PatientAndAdmission[]>();
|
|
61
|
+
const isLoading = isLoadingChildrenData || isLoadingMotherData;
|
|
62
62
|
|
|
63
63
|
for (const { child, childAdmission, mother, motherAdmission } of motherData ?? []) {
|
|
64
64
|
motherByChildUuid.set(child.uuid, { patient: mother, currentAdmission: motherAdmission });
|
|
@@ -82,7 +82,7 @@ export function useMotherChildrenRelationshipsByPatient(allWardPatientUuids: str
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
return { motherByChildUuid, childrenByMotherUuid };
|
|
85
|
+
return { motherByChildUuid, childrenByMotherUuid, isLoading };
|
|
86
86
|
}, [childrenData, motherData, isLoadingChildrenData, isLoadingMotherData]);
|
|
87
87
|
|
|
88
88
|
return relationships;
|
|
@@ -13,7 +13,6 @@ const WardView: React.FC<{}> = () => {
|
|
|
13
13
|
const { t } = useTranslation();
|
|
14
14
|
|
|
15
15
|
const locationUuid = location?.uuid;
|
|
16
|
-
const isVertical = useFeatureFlag('ward-view-vertical-tiling');
|
|
17
16
|
const wardConfig = useWardConfig(locationUuid);
|
|
18
17
|
|
|
19
18
|
if (isLoadingLocation) {
|
|
@@ -27,7 +26,7 @@ const WardView: React.FC<{}> = () => {
|
|
|
27
26
|
const wardId = wardConfig.id;
|
|
28
27
|
|
|
29
28
|
return (
|
|
30
|
-
<div className={classNames(styles.wardView,
|
|
29
|
+
<div className={classNames(styles.wardView, styles.verticalTiling)}>
|
|
31
30
|
<ExtensionSlot name={wardId} />
|
|
32
31
|
</div>
|
|
33
32
|
);
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import { InlineNotification } from '@carbon/react';
|
|
2
|
-
import { useAppContext, useFeatureFlag } from '@openmrs/esm-framework';
|
|
3
|
-
import classNames from 'classnames';
|
|
4
1
|
import React, { useEffect, useRef, type ReactNode } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { InlineNotification } from '@carbon/react';
|
|
5
4
|
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import
|
|
7
|
-
import useWardLocation from '../hooks/useWardLocation';
|
|
5
|
+
import { useAppContext, useFeatureFlag } from '@openmrs/esm-framework';
|
|
8
6
|
import { type WardViewContext } from '../types';
|
|
7
|
+
import useWardLocation from '../hooks/useWardLocation';
|
|
8
|
+
import EmptyBedSkeleton from '../beds/empty-bed-skeleton';
|
|
9
9
|
import styles from './ward-view.scss';
|
|
10
10
|
|
|
11
11
|
const Ward = ({ wardBeds, wardUnassignedPatients }: { wardBeds: ReactNode; wardUnassignedPatients: ReactNode }) => {
|
|
12
12
|
const { location } = useWardLocation();
|
|
13
13
|
const { t } = useTranslation();
|
|
14
|
-
const isVertical = useFeatureFlag('ward-view-vertical-tiling');
|
|
15
14
|
|
|
16
|
-
const {wardPatientGroupDetails} = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
15
|
+
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
17
16
|
const { bedLayouts } = wardPatientGroupDetails ?? {};
|
|
18
17
|
const { isLoading: isLoadingAdmissionLocation, error: errorLoadingAdmissionLocation } =
|
|
19
|
-
|
|
18
|
+
wardPatientGroupDetails?.admissionLocationResponse ?? {};
|
|
20
19
|
const {
|
|
21
20
|
isLoading: isLoadingInpatientAdmissions,
|
|
22
21
|
error: errorLoadingInpatientAdmissions,
|
|
@@ -44,19 +43,28 @@ const Ward = ({ wardBeds, wardUnassignedPatients }: { wardBeds: ReactNode; wardU
|
|
|
44
43
|
if (scrollToLoadMoreTrigger.current) {
|
|
45
44
|
observer.observe(scrollToLoadMoreTrigger.current);
|
|
46
45
|
}
|
|
46
|
+
|
|
47
47
|
return () => {
|
|
48
48
|
if (scrollToLoadMoreTrigger.current) {
|
|
49
|
+
// TODO: Fix this more meaningfully
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
51
|
observer.unobserve(scrollToLoadMoreTrigger.current);
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
54
|
},
|
|
53
|
-
[
|
|
55
|
+
[
|
|
56
|
+
errorLoadingInpatientAdmissions,
|
|
57
|
+
hasMoreInpatientAdmissions,
|
|
58
|
+
isLoadingInpatientAdmissions,
|
|
59
|
+
loadMoreInpatientAdmissions,
|
|
60
|
+
scrollToLoadMoreTrigger,
|
|
61
|
+
],
|
|
54
62
|
);
|
|
55
63
|
|
|
56
64
|
if (!wardPatientGroupDetails) return <></>;
|
|
57
65
|
|
|
58
66
|
return (
|
|
59
|
-
<div className={classNames(styles.wardViewMain,
|
|
67
|
+
<div className={classNames(styles.wardViewMain, styles.verticalTiling)}>
|
|
60
68
|
{wardBeds}
|
|
61
69
|
{bedLayouts?.length == 0 && isBedManagementModuleInstalled && (
|
|
62
70
|
<InlineNotification
|
|
@@ -103,4 +111,4 @@ const EmptyBeds = () => {
|
|
|
103
111
|
);
|
|
104
112
|
};
|
|
105
113
|
|
|
106
|
-
export default Ward;
|
|
114
|
+
export default Ward;
|
|
@@ -16,7 +16,7 @@ const AdmissionRequestsBar: React.FC<AdmissionRequestsBarProps> = ({ wardPending
|
|
|
16
16
|
const { t } = useTranslation();
|
|
17
17
|
const layout = useLayoutType();
|
|
18
18
|
|
|
19
|
-
if (isLoading || !inpatientRequests
|
|
19
|
+
if (isLoading || !inpatientRequests) {
|
|
20
20
|
return null;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -31,7 +31,9 @@ const AdmissionRequestsBar: React.FC<AdmissionRequestsBarProps> = ({ wardPending
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return (
|
|
34
|
-
<div className={styles.admissionRequestsContainer}
|
|
34
|
+
<div className={`${styles.admissionRequestsContainer} ${
|
|
35
|
+
inpatientRequests?.length ? styles.blackBackground : styles.lightBlueBackground
|
|
36
|
+
}`}>
|
|
35
37
|
<Movement className={styles.movementIcon} size="24" />
|
|
36
38
|
<span className={styles.content}>
|
|
37
39
|
{t('admissionRequestsCount', '{{count}} admission request', {
|
|
@@ -30,8 +30,18 @@
|
|
|
30
30
|
margin-right: layout.$spacing-03;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
.blackBackground {
|
|
34
|
+
background-color: #393939;
|
|
35
|
+
color: white;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.lightBlueBackground {
|
|
39
|
+
background-color: $color-blue-10;
|
|
40
|
+
border-left: 4px solid $color-blue-60-2;
|
|
41
|
+
color: #393939;
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
.content {
|
|
34
45
|
@include type.type-style('heading-compact-01');
|
|
35
|
-
color: $ui-02;
|
|
36
46
|
margin-right: layout.$spacing-03;
|
|
37
47
|
}
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
+
import { useAppContext } from '@openmrs/esm-framework';
|
|
2
|
+
import { screen } from '@testing-library/react';
|
|
1
3
|
import React from 'react';
|
|
2
|
-
import WardMetrics from './ward-metrics.component';
|
|
3
4
|
import { renderWithSwr } from '../../../../tools/test-utils';
|
|
4
|
-
import {
|
|
5
|
-
createAndGetWardPatientGrouping,
|
|
6
|
-
getInpatientAdmissionsUuidMap,
|
|
7
|
-
getWardMetrics,
|
|
8
|
-
} from '../ward-view/ward-view.resource';
|
|
9
|
-
import { useAdmissionLocation } from '../hooks/useAdmissionLocation';
|
|
10
|
-
import { mockAdmissionLocation, mockInpatientAdmissions, mockInpatientRequest } from '__mocks__';
|
|
11
|
-
import { useInpatientAdmission } from '../hooks/useInpatientAdmission';
|
|
12
|
-
import useWardLocation from '../hooks/useWardLocation';
|
|
13
|
-
import { screen } from '@testing-library/react';
|
|
14
|
-
import { useAppContext } from '@openmrs/esm-framework';
|
|
15
|
-
import { type WardViewContext } from '../types';
|
|
16
5
|
import { mockWardViewContext } from '../../mock';
|
|
6
|
+
import { type WardViewContext } from '../types';
|
|
7
|
+
import { getWardMetrics } from '../ward-view/ward-view.resource';
|
|
8
|
+
import WardMetrics from './ward-metrics.component';
|
|
17
9
|
|
|
18
10
|
const wardMetrics = [
|
|
19
11
|
{ name: 'patients', key: 'patients', defaultTranslation: 'Patients' },
|
package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx
CHANGED
|
@@ -1,34 +1,17 @@
|
|
|
1
1
|
import { Button } from '@carbon/react';
|
|
2
|
-
import {
|
|
3
|
-
ArrowRightIcon,
|
|
4
|
-
launchWorkspace,
|
|
5
|
-
showSnackbar,
|
|
6
|
-
useAppContext,
|
|
7
|
-
useFeatureFlag,
|
|
8
|
-
useLayoutType,
|
|
9
|
-
} from '@openmrs/esm-framework';
|
|
2
|
+
import { launchWorkspace, useAppContext, useLayoutType } from '@openmrs/esm-framework';
|
|
10
3
|
import React, { useCallback, useContext } from 'react';
|
|
11
4
|
import { useTranslation } from 'react-i18next';
|
|
12
|
-
import useWardLocation from '../../hooks/useWardLocation';
|
|
13
5
|
import type { WardPatientCardType, WardPatientWorkspaceProps, WardViewContext } from '../../types';
|
|
14
6
|
import { useAdmitPatient } from '../../ward.resource';
|
|
15
7
|
import { AdmissionRequestsWorkspaceContext } from '../admission-request-workspace/admission-requests.workspace';
|
|
16
|
-
import
|
|
8
|
+
import AdmissionPatientButton from '../admit-patient-button.component';
|
|
17
9
|
import styles from './admission-request-card.scss';
|
|
18
10
|
|
|
19
|
-
const AdmissionRequestCardActions: WardPatientCardType = (wardPatient) => {
|
|
20
|
-
const { patient, inpatientRequest } = wardPatient;
|
|
21
|
-
const { dispositionType } = inpatientRequest;
|
|
11
|
+
const AdmissionRequestCardActions: WardPatientCardType = ({ wardPatient }) => {
|
|
22
12
|
const { t } = useTranslation();
|
|
23
|
-
const { location } = useWardLocation();
|
|
24
13
|
const responsiveSize = useLayoutType() === 'tablet' ? 'lg' : 'md';
|
|
25
|
-
const { WardPatientHeader
|
|
26
|
-
const { admitPatient, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useAdmitPatient();
|
|
27
|
-
|
|
28
|
-
const launchPatientAdmissionForm = useCallback(
|
|
29
|
-
() => launchWorkspace<AdmitPatientFormWorkspaceProps>('admit-patient-form-workspace', { patient, dispositionType }),
|
|
30
|
-
[],
|
|
31
|
-
);
|
|
14
|
+
const { WardPatientHeader } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
32
15
|
|
|
33
16
|
const launchPatientTransferForm = useCallback(() => {
|
|
34
17
|
launchWorkspace<WardPatientWorkspaceProps>('patient-transfer-request-workspace', {
|
|
@@ -36,56 +19,28 @@ const AdmissionRequestCardActions: WardPatientCardType = (wardPatient) => {
|
|
|
36
19
|
WardPatientHeader,
|
|
37
20
|
});
|
|
38
21
|
}, [wardPatient, WardPatientHeader]);
|
|
39
|
-
const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');
|
|
40
|
-
const { closeWorkspaceWithSavedChanges } = useContext(AdmissionRequestsWorkspaceContext);
|
|
41
22
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} else {
|
|
48
|
-
admitPatient(patient, dispositionType)
|
|
49
|
-
.then(
|
|
50
|
-
(response) => {
|
|
51
|
-
if (response && response?.ok) {
|
|
52
|
-
showSnackbar({
|
|
53
|
-
kind: 'success',
|
|
54
|
-
title: t('patientAdmittedSuccessfully', 'Patient admitted successfully'),
|
|
55
|
-
subtitle: t('patientAdmittedWoBed', 'Patient admitted successfully to {{location}}', {
|
|
56
|
-
location: location?.display,
|
|
57
|
-
}),
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
(err: Error) => {
|
|
62
|
-
showSnackbar({
|
|
63
|
-
kind: 'error',
|
|
64
|
-
title: t('errorCreatingEncounter', 'Failed to admit patient'),
|
|
65
|
-
subtitle: err.message,
|
|
66
|
-
});
|
|
67
|
-
},
|
|
68
|
-
)
|
|
69
|
-
.finally(() => {
|
|
70
|
-
wardPatientGroupDetails?.mutate?.();
|
|
71
|
-
closeWorkspaceWithSavedChanges();
|
|
72
|
-
});
|
|
73
|
-
}
|
|
23
|
+
const launchCancelAdmissionForm = () => {
|
|
24
|
+
launchWorkspace<WardPatientWorkspaceProps>('cancel-admission-request-workspace', {
|
|
25
|
+
wardPatient,
|
|
26
|
+
WardPatientHeader,
|
|
27
|
+
});
|
|
74
28
|
};
|
|
75
29
|
|
|
30
|
+
const { closeWorkspaceWithSavedChanges } = useContext(AdmissionRequestsWorkspaceContext);
|
|
31
|
+
|
|
76
32
|
return (
|
|
77
33
|
<div className={styles.admissionRequestActionBar}>
|
|
78
34
|
<Button kind="ghost" size={responsiveSize} onClick={launchPatientTransferForm}>
|
|
79
35
|
{t('transferElsewhere', 'Transfer elsewhere')}
|
|
80
36
|
</Button>
|
|
81
|
-
<Button
|
|
82
|
-
|
|
83
|
-
renderIcon={ArrowRightIcon}
|
|
84
|
-
size={responsiveSize}
|
|
85
|
-
disabled={isLoadingEmrConfiguration || errorFetchingEmrConfiguration}
|
|
86
|
-
onClick={onAdmit}>
|
|
87
|
-
{t('admitPatient', 'Admit patient')}
|
|
37
|
+
<Button kind="ghost" size={responsiveSize} onClick={launchCancelAdmissionForm}>
|
|
38
|
+
{t('cancel', 'Cancel')}
|
|
88
39
|
</Button>
|
|
40
|
+
<AdmissionPatientButton
|
|
41
|
+
wardPatient={wardPatient}
|
|
42
|
+
onAdmitPatientSuccess={() => closeWorkspaceWithSavedChanges()}
|
|
43
|
+
/>
|
|
89
44
|
</div>
|
|
90
45
|
);
|
|
91
46
|
};
|
package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import WardPatientIdentifier from '../../ward-patient-card/row-elements/ward-pat
|
|
|
8
8
|
import WardPatientName from '../../ward-patient-card/row-elements/ward-patient-name';
|
|
9
9
|
import styles from './admission-request-card.scss';
|
|
10
10
|
|
|
11
|
-
const AdmissionRequestCardHeader: WardPatientCardType = (wardPatient) => {
|
|
11
|
+
const AdmissionRequestCardHeader: WardPatientCardType = ({ wardPatient }) => {
|
|
12
12
|
const { inpatientRequest } = wardPatient;
|
|
13
13
|
const { dispositionEncounter } = inpatientRequest;
|
|
14
14
|
const { patient } = wardPatient;
|
|
@@ -12,9 +12,9 @@ interface AdmissionRequestCardProps {
|
|
|
12
12
|
const AdmissionRequestCard: React.FC<AdmissionRequestCardProps> = ({ wardPatient, children }) => {
|
|
13
13
|
return (
|
|
14
14
|
<div className={styles.admissionRequestCard}>
|
|
15
|
-
<AdmissionRequestCardHeader {...wardPatient} />
|
|
15
|
+
<AdmissionRequestCardHeader {...{ wardPatient }} />
|
|
16
16
|
{children}
|
|
17
|
-
<AdmissionRequestCardActions {...wardPatient} />
|
|
17
|
+
<AdmissionRequestCardActions {...{ wardPatient }} />
|
|
18
18
|
</div>
|
|
19
19
|
);
|
|
20
20
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Button } from '@carbon/react';
|
|
2
|
+
import {
|
|
3
|
+
ArrowRightIcon,
|
|
4
|
+
launchWorkspace,
|
|
5
|
+
showSnackbar,
|
|
6
|
+
useAppContext,
|
|
7
|
+
useFeatureFlag,
|
|
8
|
+
useLayoutType,
|
|
9
|
+
} from '@openmrs/esm-framework';
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { useTranslation } from 'react-i18next';
|
|
12
|
+
import useWardLocation from '../hooks/useWardLocation';
|
|
13
|
+
import type { WardPatient, WardPatientWorkspaceProps, WardViewContext } from '../types';
|
|
14
|
+
import { useAdmitPatient } from '../ward.resource';
|
|
15
|
+
|
|
16
|
+
interface AdmissionPatientButtonProps {
|
|
17
|
+
wardPatient: WardPatient;
|
|
18
|
+
onAdmitPatientSuccess();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const AdmissionPatientButton: React.FC<AdmissionPatientButtonProps> = ({ wardPatient, onAdmitPatientSuccess }) => {
|
|
22
|
+
const { patient, inpatientRequest, bed } = wardPatient ?? {};
|
|
23
|
+
const dispositionType = inpatientRequest?.dispositionType ?? 'ADMIT';
|
|
24
|
+
const { t } = useTranslation();
|
|
25
|
+
const { location } = useWardLocation();
|
|
26
|
+
const responsiveSize = useLayoutType() === 'tablet' ? 'lg' : 'md';
|
|
27
|
+
const { WardPatientHeader, wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
28
|
+
const { admitPatient, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useAdmitPatient();
|
|
29
|
+
|
|
30
|
+
const launchPatientAdmissionForm = () =>
|
|
31
|
+
launchWorkspace<WardPatientWorkspaceProps>('admit-patient-form-workspace', { wardPatient, WardPatientHeader });
|
|
32
|
+
|
|
33
|
+
const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');
|
|
34
|
+
|
|
35
|
+
// If bed management module is installed and the patient does not currently assigned a bed,
|
|
36
|
+
// open the next form for bed selection. If not, admit patient directly
|
|
37
|
+
// (Note that it is possible, albeit an edge case, for a patient to have a bed assigned while not admitted)
|
|
38
|
+
const onAdmit = () => {
|
|
39
|
+
if (isBedManagementModuleInstalled && !bed) {
|
|
40
|
+
launchPatientAdmissionForm();
|
|
41
|
+
} else {
|
|
42
|
+
admitPatient(patient, dispositionType)
|
|
43
|
+
.then(
|
|
44
|
+
(response) => {
|
|
45
|
+
if (response && response?.ok) {
|
|
46
|
+
showSnackbar({
|
|
47
|
+
kind: 'success',
|
|
48
|
+
title: t('patientAdmittedSuccessfully', 'Patient admitted successfully'),
|
|
49
|
+
subtitle: t('patientAdmittedWoBed', 'Patient admitted successfully to {{location}}', {
|
|
50
|
+
location: location?.display,
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
(err: Error) => {
|
|
56
|
+
showSnackbar({
|
|
57
|
+
kind: 'error',
|
|
58
|
+
title: t('errorCreatingEncounter', 'Failed to admit patient'),
|
|
59
|
+
subtitle: err.message,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
.finally(() => {
|
|
64
|
+
wardPatientGroupDetails?.mutate?.();
|
|
65
|
+
onAdmitPatientSuccess();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<Button
|
|
72
|
+
kind="ghost"
|
|
73
|
+
renderIcon={ArrowRightIcon}
|
|
74
|
+
size={responsiveSize}
|
|
75
|
+
disabled={isLoadingEmrConfiguration || errorFetchingEmrConfiguration}
|
|
76
|
+
onClick={onAdmit}>
|
|
77
|
+
{t('admitPatient', 'Admit patient')}
|
|
78
|
+
</Button>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default AdmissionPatientButton;
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CloseWorkspaceOptions,
|
|
3
|
+
type DefaultWorkspaceProps,
|
|
4
|
+
showSnackbar,
|
|
5
|
+
useAppContext,
|
|
6
|
+
useFeatureFlag,
|
|
7
|
+
useSession,
|
|
8
|
+
} from '@openmrs/esm-framework';
|
|
2
9
|
import { screen } from '@testing-library/react';
|
|
3
10
|
import userEvent from '@testing-library/user-event';
|
|
4
11
|
import React from 'react';
|
|
5
|
-
import { mockLocationInpatientWard, mockPatientAlice } from '../../../../../__mocks__';
|
|
12
|
+
import { mockInpatientRequestAlice, mockLocationInpatientWard, mockPatientAlice } from '../../../../../__mocks__';
|
|
6
13
|
import { renderWithSwr } from '../../../../../tools';
|
|
7
14
|
import { mockWardPatientGroupDetails, mockWardViewContext } from '../../../mock';
|
|
8
15
|
import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
|
|
9
16
|
import useWardLocation from '../../hooks/useWardLocation';
|
|
10
|
-
import type { DispositionType, WardViewContext } from '../../types';
|
|
17
|
+
import type { DispositionType, WardPatient, WardViewContext } from '../../types';
|
|
11
18
|
import { assignPatientToBed, removePatientFromBed, useAdmitPatient } from '../../ward.resource';
|
|
12
19
|
import AdmitPatientFormWorkspace from './admit-patient-form.workspace';
|
|
13
|
-
import type { AdmitPatientFormWorkspaceProps } from './types';
|
|
14
20
|
|
|
15
21
|
jest.mock('../../hooks/useAdmissionLocation', () => ({
|
|
16
22
|
useAdmissionLocation: jest.fn(),
|
|
@@ -35,7 +41,6 @@ jest.mock('../../hooks/useAssignedBedByPatient', () => ({
|
|
|
35
41
|
}));
|
|
36
42
|
|
|
37
43
|
jest.mock('../../ward.resource', () => ({
|
|
38
|
-
createEncounter: jest.fn(),
|
|
39
44
|
useAdmitPatient: jest.fn(),
|
|
40
45
|
assignPatientToBed: jest.fn(),
|
|
41
46
|
removePatientFromBed: jest.fn(),
|
|
@@ -52,25 +57,35 @@ const mockedUseAdmitPatient = jest.mocked(useAdmitPatient);
|
|
|
52
57
|
|
|
53
58
|
jest.mocked(useAppContext<WardViewContext>).mockReturnValue(mockWardViewContext);
|
|
54
59
|
|
|
60
|
+
const mockedAdmitPatient = jest.fn();
|
|
55
61
|
const mockUseAdmitPatientObj: ReturnType<typeof useAdmitPatient> = {
|
|
56
|
-
admitPatient:
|
|
62
|
+
admitPatient: mockedAdmitPatient,
|
|
57
63
|
isLoadingEmrConfiguration: false,
|
|
58
64
|
errorFetchingEmrConfiguration: false,
|
|
59
65
|
};
|
|
60
66
|
jest.mocked(useAdmitPatient).mockReturnValue(mockUseAdmitPatientObj);
|
|
61
|
-
const mockedAdmitPatient = mockUseAdmitPatientObj.admitPatient;
|
|
62
67
|
|
|
63
|
-
const mockWorkspaceProps:
|
|
64
|
-
patient: mockPatientAlice,
|
|
65
|
-
closeWorkspace: jest.fn(),
|
|
68
|
+
const mockWorkspaceProps: DefaultWorkspaceProps = {
|
|
66
69
|
closeWorkspaceWithSavedChanges: jest.fn(),
|
|
67
70
|
promptBeforeClosing: jest.fn(),
|
|
68
71
|
setTitle: jest.fn(),
|
|
69
|
-
|
|
72
|
+
closeWorkspace: jest.fn(),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const mockWardPatientAliceProps: WardPatient = {
|
|
76
|
+
visit: mockInpatientRequestAlice.visit,
|
|
77
|
+
patient: mockPatientAlice,
|
|
78
|
+
bed: null,
|
|
79
|
+
inpatientAdmission: null,
|
|
80
|
+
inpatientRequest: mockInpatientRequestAlice,
|
|
70
81
|
};
|
|
71
82
|
|
|
72
|
-
function renderAdmissionForm(
|
|
73
|
-
renderWithSwr(
|
|
83
|
+
function renderAdmissionForm() {
|
|
84
|
+
renderWithSwr(
|
|
85
|
+
<AdmitPatientFormWorkspace
|
|
86
|
+
{...{ ...mockWorkspaceProps, wardPatient: mockWardPatientAliceProps, WardPatientHeader: jest.fn() }}
|
|
87
|
+
/>,
|
|
88
|
+
);
|
|
74
89
|
}
|
|
75
90
|
|
|
76
91
|
describe('Testing AdmitPatientForm', () => {
|