@kenyaemr/esm-ward-app 8.1.1-pre.114 → 8.1.1-pre.116
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 +18 -17
- package/dist/109.js +1 -0
- package/dist/109.js.map +1 -0
- package/dist/125.js +1 -0
- package/dist/125.js.map +1 -0
- 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 -0
- package/dist/146.js.map +1 -0
- package/dist/15.js +1 -0
- package/dist/15.js.map +1 -0
- package/dist/161.js +2 -0
- package/dist/161.js.map +1 -0
- package/dist/269.js +1 -1
- package/dist/269.js.map +1 -1
- package/dist/466.js +1 -1
- package/dist/466.js.map +1 -1
- package/dist/500.js +1 -0
- package/dist/500.js.map +1 -0
- package/dist/53.js +1 -0
- package/dist/53.js.map +1 -0
- package/dist/557.js +1 -0
- package/dist/557.js.map +1 -0
- package/dist/559.js +1 -0
- package/dist/559.js.map +1 -0
- package/dist/574.js +1 -1
- package/dist/577.js +1 -1
- package/dist/577.js.map +1 -1
- package/dist/659.js +1 -1
- package/dist/659.js.map +1 -1
- package/dist/701.js +1 -0
- package/dist/701.js.map +1 -0
- package/dist/749.js +1 -1
- package/dist/749.js.map +1 -1
- package/dist/908.js +1 -0
- package/dist/908.js.map +1 -0
- package/dist/922.js +1 -0
- package/dist/922.js.map +1 -0
- package/dist/969.js +1 -0
- package/dist/969.js.map +1 -0
- package/dist/kenyaemr-esm-ward-app.js +1 -1
- package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +294 -74
- package/dist/kenyaemr-esm-ward-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/mock.tsx +54 -0
- package/package.json +1 -1
- package/src/action-menu-buttons/clinical-forms-workspace-siderail.component.tsx +37 -0
- package/src/action-menu-buttons/discharge-workspace-siderail.component.tsx +20 -0
- package/src/beds/empty-bed-skeleton.tsx +2 -1
- package/src/beds/empty-bed.scss +0 -4
- package/src/beds/occupied-bed.scss +1 -0
- package/src/config-schema-mother-child-row.ts +26 -0
- package/src/config-schema-pending-items-extension.ts +29 -0
- package/src/config-schema.ts +12 -14
- package/src/hooks/useAdmissionLocation.ts +22 -4
- package/src/hooks/useBeds.ts +3 -4
- package/src/hooks/useConcept.ts +3 -4
- package/src/hooks/useEmrConfiguration.ts +5 -0
- package/src/hooks/useInpatientAdmission.ts +9 -14
- package/src/hooks/useInpatientRequest.ts +4 -15
- package/src/hooks/useLocations.ts +8 -51
- package/src/hooks/useMotherAndChildren.ts +46 -0
- package/src/hooks/useObs.ts +2 -6
- package/src/hooks/usePatientPendingOrders.ts +16 -0
- package/src/hooks/useWardPatientGrouping.ts +25 -0
- package/src/index.ts +50 -3
- package/src/location-selector/location-selector.component.tsx +18 -21
- package/src/routes.json +43 -0
- package/src/types/index.ts +34 -0
- package/src/ward-patient-card/card-rows/admission-request-note.extension.tsx +7 -2
- package/src/ward-patient-card/card-rows/mother-child-row.extension.tsx +110 -0
- package/src/ward-patient-card/card-rows/mother-child-row.scss +22 -0
- package/src/ward-patient-card/card-rows/pending-items-car-row.extension.tsx +50 -0
- package/src/ward-patient-card/row-elements/ward-pateint-skeleton-text.tsx +9 -0
- package/src/ward-patient-card/row-elements/ward-patient-age.tsx +1 -1
- package/src/ward-patient-card/row-elements/ward-patient-coded-obs-tags.tsx +54 -36
- package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +2 -3
- package/src/ward-patient-card/row-elements/ward-patient-location.tsx +19 -0
- package/src/ward-patient-card/row-elements/ward-patient-obs.resource.ts +36 -32
- package/src/ward-patient-card/row-elements/ward-patient-obs.tsx +15 -9
- package/src/ward-patient-card/row-elements/ward-patient-pending-order.component.tsx +45 -0
- package/src/ward-patient-card/row-elements/ward-patient-pending-transfer.tsx +38 -0
- package/src/ward-patient-card/row-elements/ward-patient-responsive-tooltip.tsx +32 -0
- package/src/ward-patient-card/ward-patient-card-element.component.tsx +4 -0
- package/src/ward-patient-card/ward-patient-card.component.tsx +21 -14
- package/src/ward-patient-card/ward-patient-card.scss +61 -8
- package/src/ward-patient-card/ward-patient-resource.ts +15 -0
- package/src/ward-view/ward-view.component.tsx +124 -132
- package/src/ward-view/ward-view.resource.ts +121 -1
- package/src/ward-view/ward-view.scss +16 -6
- package/src/ward-view/ward-view.test.tsx +27 -42
- package/src/ward-view-header/admission-requests-bar.component.tsx +8 -7
- package/src/ward-view-header/admission-requests-bar.test.tsx +8 -21
- package/src/ward-view-header/admission-requests.scss +1 -1
- package/src/ward-view-header/ward-metric.component.tsx +24 -0
- package/src/ward-view-header/ward-metric.scss +25 -0
- package/src/ward-view-header/ward-metrics.component.tsx +77 -0
- package/src/ward-view-header/ward-metrics.scss +8 -0
- package/src/ward-view-header/ward-metrics.test.tsx +91 -0
- package/src/ward-view-header/ward-view-header.component.tsx +3 -0
- package/src/ward-view-header/ward-view-header.scss +0 -1
- package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +11 -3
- package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +4 -5
- package/src/ward-workspace/admission-request-card/admission-request-card.scss +8 -4
- package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +8 -3
- package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +2 -0
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +29 -61
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +37 -21
- package/src/ward-workspace/patient-banner/patient-banner.component.tsx +3 -3
- package/src/ward-workspace/patient-clinical-forms-workspace/patient-clinical-forms.workspace.tsx +23 -0
- package/src/{ward-patient-workspace → ward-workspace/patient-details}/ward-patient-action-button.extension.tsx +2 -1
- package/src/{ward-patient-workspace → ward-workspace/patient-details}/ward-patient.workspace.tsx +7 -5
- package/src/ward-workspace/patient-discharge/patient-discharge.scss +41 -0
- package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +120 -0
- package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +40 -30
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +29 -22
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.scss +12 -2
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +2 -2
- package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.workspace.tsx +11 -0
- package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +1 -1
- package/src/ward-workspace/ward-patient-notes/form/notes-form.test.tsx +1 -1
- package/src/ward-workspace/ward-patient-notes/history/notes-container.component.tsx +2 -2
- package/src/ward-workspace/ward-patient-notes/notes.resource.ts +5 -7
- package/src/ward-workspace/ward-patient-notes/notes.workspace.tsx +1 -1
- package/src/ward-workspace/ward-patient-notes/types.ts +0 -4
- package/src/ward.resource.ts +6 -0
- package/translations/en.json +18 -1
- package/dist/346.js +0 -1
- package/dist/346.js.map +0 -1
- package/dist/76.js +0 -1
- package/dist/76.js.map +0 -1
- package/dist/803.js +0 -1
- package/dist/803.js.map +0 -1
- package/dist/958.js +0 -2
- package/dist/958.js.map +0 -1
- package/dist/960.js +0 -1
- package/dist/960.js.map +0 -1
- /package/dist/{958.js.LICENSE.txt → 161.js.LICENSE.txt} +0 -0
- /package/src/{ward-patient-workspace → ward-workspace/patient-details}/ward-patient.style.scss +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type InpatientAdmission } from '../../types';
|
|
3
|
+
|
|
4
|
+
export interface WardPatientIdentifierProps {
|
|
5
|
+
inpatientAdmission: InpatientAdmission;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const WardPatientLocation: React.FC<WardPatientIdentifierProps> = ({ inpatientAdmission }) => {
|
|
9
|
+
const locationDisplay = inpatientAdmission?.encounterAssigningToCurrentInpatientLocation.location?.display;
|
|
10
|
+
return locationDisplay ? (
|
|
11
|
+
<div>
|
|
12
|
+
<span>{locationDisplay}</span>
|
|
13
|
+
</div>
|
|
14
|
+
) : (
|
|
15
|
+
<></>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default WardPatientLocation;
|
|
@@ -1,52 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import useSWRImmutable from 'swr/immutable';
|
|
1
|
+
import { restBaseUrl, useOpenmrsFetchAll, type Concept } from '@openmrs/esm-framework';
|
|
3
2
|
import { type TagConfigObject } from '../../config-schema-extension-colored-obs-tags';
|
|
3
|
+
import { type Observation } from '../../types';
|
|
4
|
+
import { type TFunction } from 'i18next';
|
|
4
5
|
|
|
5
6
|
// prettier-ignore
|
|
6
7
|
export const obsCustomRepresentation =
|
|
7
8
|
'custom:(uuid,display,obsDatetime,value,' +
|
|
8
9
|
'concept:(uuid,display),' +
|
|
9
|
-
'encounter:(uuid,display,' +
|
|
10
|
+
'encounter:(uuid,display,encounterType,encounterDatetime,' +
|
|
10
11
|
'visit:(uuid,display)))';
|
|
11
12
|
|
|
12
13
|
// get the setMembers of a concept set
|
|
13
14
|
const conceptSetCustomRepresentation = 'custom:(uuid,setMembers:(uuid))';
|
|
14
15
|
|
|
15
16
|
export function useConceptToTagColorMap(tags: Array<TagConfigObject>) {
|
|
16
|
-
//
|
|
17
|
-
// to
|
|
18
|
-
//
|
|
19
|
-
const fetchAndMap = (url: string) => {
|
|
20
|
-
const conceptSetToTagColorMap = new Map<string, string>();
|
|
21
|
-
for (const tag of tags) {
|
|
22
|
-
const { color, appliedToConceptSets } = tag;
|
|
23
|
-
for (const answer of appliedToConceptSets ?? []) {
|
|
24
|
-
if (!conceptSetToTagColorMap.has(answer)) {
|
|
25
|
-
conceptSetToTagColorMap.set(answer, color);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
17
|
+
// The TacConfigObject allows us to specify the mapping of
|
|
18
|
+
// concept sets to colors. However, we also need to build a map of
|
|
19
|
+
// concepts to colors. This function does that.
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
conceptToTagColorMap.set(concept.uuid, conceptSetToTagColorMap.get(conceptSet.uuid));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
21
|
+
// TODO: We should cache this map to be re-usable app-wide
|
|
22
|
+
const conceptSetToTagColorMap = new Map<string, string>();
|
|
23
|
+
for (const tag of tags) {
|
|
24
|
+
const { color, appliedToConceptSets } = tag;
|
|
25
|
+
for (const answer of appliedToConceptSets ?? []) {
|
|
26
|
+
if (!conceptSetToTagColorMap.has(answer)) {
|
|
27
|
+
conceptSetToTagColorMap.set(answer, color);
|
|
41
28
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
46
31
|
|
|
47
32
|
const conceptSetUuids = tags.flatMap((tag) => tag.appliedToConceptSets);
|
|
48
33
|
const apiUrl = `${restBaseUrl}/concept?references=${conceptSetUuids.join()}&v=${conceptSetCustomRepresentation}`;
|
|
49
|
-
const
|
|
34
|
+
const { data: conceptSets } = useOpenmrsFetchAll<Concept>(apiUrl);
|
|
35
|
+
|
|
36
|
+
const conceptToTagColorMap = new Map<string, string>();
|
|
37
|
+
if (conceptSets) {
|
|
38
|
+
for (const conceptSet of conceptSets) {
|
|
39
|
+
for (const concept of conceptSet.setMembers) {
|
|
40
|
+
if (!conceptToTagColorMap.has(concept.uuid)) {
|
|
41
|
+
conceptToTagColorMap.set(concept.uuid, conceptSetToTagColorMap.get(conceptSet.uuid));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
50
46
|
|
|
51
47
|
return conceptToTagColorMap;
|
|
52
48
|
}
|
|
49
|
+
|
|
50
|
+
export function getObsEncounterString(obs: Observation, t: TFunction) {
|
|
51
|
+
return t('encounterDisplay', '{{encounterType}} {{encounterDate}}', {
|
|
52
|
+
encounterType: obs.encounter.encounterType.display,
|
|
53
|
+
encounterDate: new Date(obs.encounter.encounterDatetime).toLocaleDateString(),
|
|
54
|
+
interpolation: { escapeValue: false },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { SkeletonText } from '@carbon/react';
|
|
2
|
-
import {
|
|
1
|
+
import { SkeletonText, Toggletip, ToggletipButton, ToggletipContent } from '@carbon/react';
|
|
2
|
+
import { Information } from '@carbon/react/icons';
|
|
3
|
+
import { type OpenmrsResource, type Patient, type Visit } from '@openmrs/esm-framework';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { useTranslation } from 'react-i18next';
|
|
5
6
|
import { type ObsElementDefinition } from '../../config-schema';
|
|
6
7
|
import { useObs } from '../../hooks/useObs';
|
|
7
8
|
import styles from '../ward-patient-card.scss';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
9
|
+
import { getObsEncounterString, obsCustomRepresentation } from './ward-patient-obs.resource';
|
|
10
|
+
import WardPatientResponsiveTooltip from './ward-patient-responsive-tooltip';
|
|
10
11
|
|
|
11
12
|
export interface WardPatientObsProps {
|
|
12
13
|
config: ObsElementDefinition;
|
|
@@ -15,14 +16,14 @@ export interface WardPatientObsProps {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
const WardPatientObs: React.FC<WardPatientObsProps> = ({ config, patient, visit }) => {
|
|
18
|
-
const { conceptUuid, onlyWithinCurrentVisit, orderBy, limit, label
|
|
19
|
+
const { conceptUuid, onlyWithinCurrentVisit, orderBy, limit, label } = config;
|
|
19
20
|
const { data, isLoading } = useObs({ patient: patient.uuid, concept: conceptUuid }, obsCustomRepresentation);
|
|
20
21
|
const { t } = useTranslation();
|
|
21
22
|
|
|
22
23
|
if (isLoading) {
|
|
23
24
|
return <SkeletonText />;
|
|
24
25
|
} else {
|
|
25
|
-
const obsToDisplay = data
|
|
26
|
+
const obsToDisplay = data
|
|
26
27
|
?.filter((o) => {
|
|
27
28
|
const matchVisit = !onlyWithinCurrentVisit || o.encounter.visit?.uuid == visit?.uuid;
|
|
28
29
|
return matchVisit;
|
|
@@ -32,13 +33,18 @@ const WardPatientObs: React.FC<WardPatientObsProps> = ({ config, patient, visit
|
|
|
32
33
|
})
|
|
33
34
|
?.slice(0, limit == 0 ? Number.MAX_VALUE : limit);
|
|
34
35
|
|
|
35
|
-
const labelToDisplay =
|
|
36
|
-
label != null ? translateFrom(labelModule ?? moduleName, label) : obsToDisplay?.[0]?.concept?.display;
|
|
36
|
+
const labelToDisplay = label != null ? t(label) : obsToDisplay?.[0]?.concept?.display;
|
|
37
37
|
|
|
38
38
|
const obsNodes = obsToDisplay?.map((o) => {
|
|
39
39
|
const { value } = o;
|
|
40
40
|
const display: any = (value as OpenmrsResource)?.display ?? o.value;
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
const tooltipContent = getObsEncounterString(o, t);
|
|
43
|
+
return (
|
|
44
|
+
<WardPatientResponsiveTooltip key={o.uuid} tooltipContent={tooltipContent}>
|
|
45
|
+
<span title={tooltipContent}>{display} </span>
|
|
46
|
+
</WardPatientResponsiveTooltip>
|
|
47
|
+
);
|
|
42
48
|
});
|
|
43
49
|
|
|
44
50
|
if (obsNodes?.length > 0) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { ChemistryReference } from '@carbon/react/icons';
|
|
3
|
+
import styles from '../ward-patient-card.scss';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { type WardPatient } from '../../types';
|
|
6
|
+
import { usePatientPendingOrders } from '../../hooks/usePatientPendingOrders';
|
|
7
|
+
|
|
8
|
+
export interface WardPatientPendingOrderProps {
|
|
9
|
+
wardPatient: WardPatient;
|
|
10
|
+
orderUuid: string;
|
|
11
|
+
label: string;
|
|
12
|
+
onOrderCount: (count: number) => void; // New prop for notifying parent
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const WardPatientPendingOrder: React.FC<WardPatientPendingOrderProps> = ({
|
|
16
|
+
wardPatient,
|
|
17
|
+
orderUuid,
|
|
18
|
+
label,
|
|
19
|
+
onOrderCount,
|
|
20
|
+
}) => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const { count, isLoading } = usePatientPendingOrders(
|
|
23
|
+
wardPatient?.patient?.uuid,
|
|
24
|
+
orderUuid,
|
|
25
|
+
wardPatient?.visit?.startDatetime.split('T')[0],
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!isLoading) {
|
|
30
|
+
onOrderCount(count); // Notify parent when count is available
|
|
31
|
+
}
|
|
32
|
+
}, [count, isLoading, onOrderCount]);
|
|
33
|
+
|
|
34
|
+
if (isLoading || !count || count == 0) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const labelToDisplay = label ? t(label) : t('Orders', 'Orders');
|
|
39
|
+
return (
|
|
40
|
+
<div className={styles.wardPatientCardDispositionTypeContainer}>
|
|
41
|
+
<ChemistryReference className={styles.chemistryReferenceIcon} size="24" />
|
|
42
|
+
{count} {labelToDisplay}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Movement } from '@carbon/react/icons';
|
|
3
|
+
import styles from '../ward-patient-card.scss';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { type WardPatient } from '../../types';
|
|
6
|
+
|
|
7
|
+
export interface WardPatientTransferProps {
|
|
8
|
+
wardPatient: WardPatient;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const WardPatientPendingTransfer: React.FC<WardPatientTransferProps> = ({ wardPatient }) => {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
|
|
14
|
+
const { dispositionType, dispositionLocation } = wardPatient?.inpatientRequest;
|
|
15
|
+
const message = useMemo(() => {
|
|
16
|
+
if (dispositionType === 'TRANSFER') {
|
|
17
|
+
if (dispositionLocation) {
|
|
18
|
+
return t('transferToDispositionLocation', 'Transfer to {{location}}', { location: dispositionLocation.name });
|
|
19
|
+
}
|
|
20
|
+
return t('pendingTransfer', 'Pending Transfer');
|
|
21
|
+
}
|
|
22
|
+
if (dispositionType === 'DISCHARGE') {
|
|
23
|
+
return t('pendingDischarge', 'Pending Discharge');
|
|
24
|
+
}
|
|
25
|
+
return '';
|
|
26
|
+
}, [dispositionType, dispositionLocation]);
|
|
27
|
+
|
|
28
|
+
if (!(dispositionType === 'TRANSFER' || dispositionType === 'DISCHARGE')) return null;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className={styles.wardPatientCardDispositionTypeContainer}>
|
|
32
|
+
<Movement className={styles.movementIcon} size="24" />
|
|
33
|
+
{message}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default WardPatientPendingTransfer;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Toggletip, ToggletipButton, ToggletipContent, Tooltip } from '@carbon/react';
|
|
2
|
+
import { isDesktop, useLayoutType } from '@openmrs/esm-framework';
|
|
3
|
+
import React, { type ReactNode } from 'react';
|
|
4
|
+
import styles from '../ward-patient-card.scss';
|
|
5
|
+
|
|
6
|
+
interface WardPatientResponsiveTooltipProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
tooltipContent: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This component acts as a Tooltip on desktop and a Toggletip on mobile.
|
|
13
|
+
*/
|
|
14
|
+
const WardPatientResponsiveTooltip: React.FC<WardPatientResponsiveTooltipProps> = ({ children, tooltipContent }) => {
|
|
15
|
+
const layout = useLayoutType();
|
|
16
|
+
if (isDesktop(layout)) {
|
|
17
|
+
return (
|
|
18
|
+
<Tooltip description={tooltipContent} className={styles.responsiveTooltip}>
|
|
19
|
+
{children}
|
|
20
|
+
</Tooltip>
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
return (
|
|
24
|
+
<Toggletip className={styles.responsiveTooltip}>
|
|
25
|
+
<ToggletipButton>{children}</ToggletipButton>
|
|
26
|
+
<ToggletipContent>{tooltipContent}</ToggletipContent>
|
|
27
|
+
</Toggletip>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default WardPatientResponsiveTooltip;
|
|
@@ -10,6 +10,7 @@ import WardPatientIdentifier from './row-elements/ward-patient-identifier';
|
|
|
10
10
|
import WardPatientObs from './row-elements/ward-patient-obs';
|
|
11
11
|
import WardPatientTimeOnWard from './row-elements/ward-patient-time-on-ward';
|
|
12
12
|
import WardPatientTimeSinceAdmission from './row-elements/ward-patient-time-since-admission';
|
|
13
|
+
import WardPatientLocation from './row-elements/ward-patient-location';
|
|
13
14
|
|
|
14
15
|
export interface WardPatientCardElementProps extends WardPatient {
|
|
15
16
|
elementId: string;
|
|
@@ -39,6 +40,9 @@ export const WardPatientCardElement: React.FC<WardPatientCardElementProps> = ({
|
|
|
39
40
|
case 'time-since-admission': {
|
|
40
41
|
return <WardPatientTimeSinceAdmission firstAdmissionOrTransferEncounter={firstAdmissionOrTransferEncounter} />;
|
|
41
42
|
}
|
|
43
|
+
case 'patient-location': {
|
|
44
|
+
return <WardPatientLocation inpatientAdmission={inpatientAdmission} />;
|
|
45
|
+
}
|
|
42
46
|
default: {
|
|
43
47
|
const obsConfig = obsElementDefinitions.find((elementDef) => elementDef.id === elementId);
|
|
44
48
|
const idConfig = identifierElementDefinitions.find((elementDef) => elementDef.id === elementId);
|
|
@@ -7,6 +7,7 @@ import WardPatientBedNumber from './row-elements/ward-patient-bed-number';
|
|
|
7
7
|
import WardPatientName from './row-elements/ward-patient-name';
|
|
8
8
|
import { WardPatientCardElement } from './ward-patient-card-element.component';
|
|
9
9
|
import styles from './ward-patient-card.scss';
|
|
10
|
+
import { launchPatientWorkspace, setWardPatient } from './ward-patient-resource';
|
|
10
11
|
|
|
11
12
|
const WardPatientCard: WardPatientCard = (wardPatient) => {
|
|
12
13
|
const { patient, bed } = wardPatient;
|
|
@@ -32,27 +33,33 @@ const WardPatientCard: WardPatientCard = (wardPatient) => {
|
|
|
32
33
|
))}
|
|
33
34
|
<ExtensionSlot name={headerExtensionSlotName} state={wardPatient} />
|
|
34
35
|
</div>
|
|
36
|
+
{footerRowElements.length > 0 && (
|
|
37
|
+
<div className={styles.wardPatientCardRow}>
|
|
38
|
+
{footerRowElements.map((elementId, i) => (
|
|
39
|
+
<WardPatientCardElement
|
|
40
|
+
key={`ward-card-${patient.uuid}-footer-${i}`}
|
|
41
|
+
elementId={elementId}
|
|
42
|
+
{...wardPatient}
|
|
43
|
+
/>
|
|
44
|
+
))}
|
|
45
|
+
<ExtensionSlot name={footerExtensionSlotName} state={wardPatient} />
|
|
46
|
+
</div>
|
|
47
|
+
)}
|
|
48
|
+
<ExtensionSlot
|
|
49
|
+
name="ward-patient-card-pending-items-slot"
|
|
50
|
+
state={wardPatient}
|
|
51
|
+
className={styles.wardPatientCardExtensionSlot}
|
|
52
|
+
/>
|
|
35
53
|
<ExtensionSlot
|
|
36
54
|
name={rowsExtensionSlotName}
|
|
37
55
|
state={wardPatient}
|
|
38
|
-
className={classNames(styles.
|
|
56
|
+
className={classNames(styles.wardPatientCardExtensionSlot)}
|
|
39
57
|
/>
|
|
40
|
-
<div className={styles.wardPatientCardRow}>
|
|
41
|
-
{footerRowElements.map((elementId, i) => (
|
|
42
|
-
<WardPatientCardElement
|
|
43
|
-
key={`ward-card-${patient.uuid}-footer-${i}`}
|
|
44
|
-
elementId={elementId}
|
|
45
|
-
{...wardPatient}
|
|
46
|
-
/>
|
|
47
|
-
))}
|
|
48
|
-
<ExtensionSlot name={footerExtensionSlotName} state={wardPatient} />
|
|
49
|
-
</div>
|
|
50
58
|
<button
|
|
51
59
|
className={styles.wardPatientCardButton}
|
|
52
60
|
onClick={() => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
61
|
+
setWardPatient(wardPatient);
|
|
62
|
+
launchPatientWorkspace();
|
|
56
63
|
}}>
|
|
57
64
|
{/* Name will not be displayed; just there for a11y */}
|
|
58
65
|
{getPatientName(patient.person)}
|
|
@@ -14,10 +14,6 @@
|
|
|
14
14
|
background-color: $ui-02;
|
|
15
15
|
|
|
16
16
|
position: relative; // this allows positioning the button correctly
|
|
17
|
-
|
|
18
|
-
> .wardPatientCardRow:not(:first-child) {
|
|
19
|
-
border-top: 1px colors.$gray-20 solid;
|
|
20
|
-
}
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
.wardPatientCardButton {
|
|
@@ -59,24 +55,51 @@
|
|
|
59
55
|
.wardPatientCardRow {
|
|
60
56
|
width: 100%;
|
|
61
57
|
padding: layout.$spacing-04;
|
|
58
|
+
border-top: 1px colors.$gray-20 solid;
|
|
59
|
+
|
|
60
|
+
&:empty {
|
|
61
|
+
border-top: 0px;
|
|
62
|
+
display: none;
|
|
63
|
+
}
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
.
|
|
66
|
+
.wardPatientPendingOrdersRow:empty {
|
|
65
67
|
display: none;
|
|
68
|
+
margin-left: layout.$spacing-04;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
.wardPatientCardExtensionSlot {
|
|
69
72
|
display: none;
|
|
73
|
+
width: 100%;
|
|
70
74
|
|
|
71
75
|
&:has(div:not(:empty)) {
|
|
72
76
|
display: block;
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
.wardPatientCardPendingItemsRow:empty {
|
|
81
|
+
display: none;
|
|
82
|
+
margin-left: layout.$spacing-04;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.wardPatientCardPendingItemsRow {
|
|
86
|
+
@extend .wardPatientCardRow;
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
flex-flow: row wrap;
|
|
90
|
+
color: $ui-02;
|
|
91
|
+
background-color: colors.$gray-80;
|
|
92
|
+
}
|
|
93
|
+
|
|
76
94
|
.wardPatientCardHeader {
|
|
77
95
|
@extend .dotSeparatedChildren;
|
|
96
|
+
border-top: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.wardPatientCardDispositionTypeContainer {
|
|
78
100
|
display: flex;
|
|
79
|
-
flex-
|
|
101
|
+
flex-flow: row;
|
|
102
|
+
align-items: center;
|
|
80
103
|
}
|
|
81
104
|
|
|
82
105
|
.wardPatientName {
|
|
@@ -112,10 +135,26 @@
|
|
|
112
135
|
align-items: center;
|
|
113
136
|
}
|
|
114
137
|
|
|
138
|
+
.movementIcon {
|
|
139
|
+
padding: layout.$spacing-02;
|
|
140
|
+
border-radius: 50%;
|
|
141
|
+
fill: $ui-03;
|
|
142
|
+
background-color: $color-blue-60-2;
|
|
143
|
+
margin-left: layout.$spacing-03;
|
|
144
|
+
margin-right: layout.$spacing-02;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.chemistryReferenceIcon {
|
|
148
|
+
padding: layout.$spacing-02;
|
|
149
|
+
border-radius: 50%;
|
|
150
|
+
fill: $ui-03;
|
|
151
|
+
background-color: #a2191f;
|
|
152
|
+
margin-left: layout.$spacing-03;
|
|
153
|
+
margin-right: layout.$spacing-02;
|
|
154
|
+
}
|
|
155
|
+
|
|
115
156
|
.wardPatientAddress {
|
|
116
157
|
@extend .dotSeparatedChildren;
|
|
117
|
-
display: flex;
|
|
118
|
-
flex-wrap: wrap;
|
|
119
158
|
align-items: center;
|
|
120
159
|
gap: layout.$spacing-02;
|
|
121
160
|
}
|
|
@@ -124,7 +163,17 @@
|
|
|
124
163
|
padding-right: layout.$spacing-02;
|
|
125
164
|
}
|
|
126
165
|
|
|
166
|
+
.responsiveTooltip {
|
|
167
|
+
z-index: 2;
|
|
168
|
+
& :global(.cds--tag) {
|
|
169
|
+
border: 0;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
127
173
|
.dotSeparatedChildren {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-wrap: wrap;
|
|
176
|
+
|
|
128
177
|
> div:not(div:first-of-type):not(:empty) {
|
|
129
178
|
display: flex;
|
|
130
179
|
align-items: center;
|
|
@@ -135,3 +184,7 @@
|
|
|
135
184
|
}
|
|
136
185
|
}
|
|
137
186
|
}
|
|
187
|
+
|
|
188
|
+
.skeletonText {
|
|
189
|
+
width: 6.25rem;
|
|
190
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { launchWorkspace } from '@openmrs/esm-framework';
|
|
2
|
+
import { type WardPatient, type WardPatientWorkspaceProps } from '../types';
|
|
3
|
+
|
|
4
|
+
//To keep track of current patient when clicked on ward-patient-card and pass
|
|
5
|
+
//it as a prop to launch workspace
|
|
6
|
+
let wardPatient: WardPatient = null;
|
|
7
|
+
export function setWardPatient(currentWardPatient: WardPatient) {
|
|
8
|
+
wardPatient = currentWardPatient;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function launchPatientWorkspace() {
|
|
12
|
+
launchWorkspace<WardPatientWorkspaceProps>('ward-patient-workspace', {
|
|
13
|
+
wardPatient,
|
|
14
|
+
});
|
|
15
|
+
}
|