@kenyaemr/esm-ward-app 8.1.1-pre.114 → 8.1.1-pre.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/.turbo/turbo-build.log +18 -17
  2. package/dist/109.js +1 -0
  3. package/dist/109.js.map +1 -0
  4. package/dist/125.js +1 -0
  5. package/dist/125.js.map +1 -0
  6. package/dist/126.js +1 -0
  7. package/dist/126.js.map +1 -0
  8. package/dist/130.js +1 -1
  9. package/dist/130.js.map +1 -1
  10. package/dist/146.js +1 -0
  11. package/dist/146.js.map +1 -0
  12. package/dist/15.js +1 -0
  13. package/dist/15.js.map +1 -0
  14. package/dist/161.js +2 -0
  15. package/dist/161.js.map +1 -0
  16. package/dist/269.js +1 -1
  17. package/dist/269.js.map +1 -1
  18. package/dist/466.js +1 -1
  19. package/dist/466.js.map +1 -1
  20. package/dist/500.js +1 -0
  21. package/dist/500.js.map +1 -0
  22. package/dist/53.js +1 -0
  23. package/dist/53.js.map +1 -0
  24. package/dist/557.js +1 -0
  25. package/dist/557.js.map +1 -0
  26. package/dist/559.js +1 -0
  27. package/dist/559.js.map +1 -0
  28. package/dist/574.js +1 -1
  29. package/dist/577.js +1 -1
  30. package/dist/577.js.map +1 -1
  31. package/dist/659.js +1 -1
  32. package/dist/659.js.map +1 -1
  33. package/dist/701.js +1 -0
  34. package/dist/701.js.map +1 -0
  35. package/dist/749.js +1 -1
  36. package/dist/749.js.map +1 -1
  37. package/dist/908.js +1 -0
  38. package/dist/908.js.map +1 -0
  39. package/dist/922.js +1 -0
  40. package/dist/922.js.map +1 -0
  41. package/dist/969.js +1 -0
  42. package/dist/969.js.map +1 -0
  43. package/dist/kenyaemr-esm-ward-app.js +1 -1
  44. package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +294 -74
  45. package/dist/kenyaemr-esm-ward-app.js.map +1 -1
  46. package/dist/main.js +1 -1
  47. package/dist/main.js.map +1 -1
  48. package/dist/routes.json +1 -1
  49. package/mock.tsx +54 -0
  50. package/package.json +1 -1
  51. package/src/action-menu-buttons/clinical-forms-workspace-siderail.component.tsx +37 -0
  52. package/src/action-menu-buttons/discharge-workspace-siderail.component.tsx +20 -0
  53. package/src/beds/empty-bed-skeleton.tsx +2 -1
  54. package/src/beds/empty-bed.scss +0 -4
  55. package/src/beds/occupied-bed.scss +1 -0
  56. package/src/config-schema-mother-child-row.ts +26 -0
  57. package/src/config-schema-pending-items-extension.ts +29 -0
  58. package/src/config-schema.ts +12 -14
  59. package/src/hooks/useAdmissionLocation.ts +22 -4
  60. package/src/hooks/useBeds.ts +3 -4
  61. package/src/hooks/useConcept.ts +3 -4
  62. package/src/hooks/useEmrConfiguration.ts +5 -0
  63. package/src/hooks/useInpatientAdmission.ts +9 -14
  64. package/src/hooks/useInpatientRequest.ts +4 -15
  65. package/src/hooks/useLocations.ts +8 -51
  66. package/src/hooks/useMotherAndChildren.ts +46 -0
  67. package/src/hooks/useObs.ts +2 -6
  68. package/src/hooks/usePatientPendingOrders.ts +16 -0
  69. package/src/hooks/useWardPatientGrouping.ts +25 -0
  70. package/src/index.ts +50 -3
  71. package/src/location-selector/location-selector.component.tsx +18 -21
  72. package/src/routes.json +43 -0
  73. package/src/types/index.ts +34 -0
  74. package/src/ward-patient-card/card-rows/admission-request-note.extension.tsx +7 -2
  75. package/src/ward-patient-card/card-rows/mother-child-row.extension.tsx +110 -0
  76. package/src/ward-patient-card/card-rows/mother-child-row.scss +22 -0
  77. package/src/ward-patient-card/card-rows/pending-items-car-row.extension.tsx +50 -0
  78. package/src/ward-patient-card/row-elements/ward-pateint-skeleton-text.tsx +9 -0
  79. package/src/ward-patient-card/row-elements/ward-patient-age.tsx +1 -1
  80. package/src/ward-patient-card/row-elements/ward-patient-coded-obs-tags.tsx +54 -36
  81. package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +2 -3
  82. package/src/ward-patient-card/row-elements/ward-patient-location.tsx +19 -0
  83. package/src/ward-patient-card/row-elements/ward-patient-obs.resource.ts +36 -32
  84. package/src/ward-patient-card/row-elements/ward-patient-obs.tsx +15 -9
  85. package/src/ward-patient-card/row-elements/ward-patient-pending-order.component.tsx +45 -0
  86. package/src/ward-patient-card/row-elements/ward-patient-pending-transfer.tsx +38 -0
  87. package/src/ward-patient-card/row-elements/ward-patient-responsive-tooltip.tsx +32 -0
  88. package/src/ward-patient-card/ward-patient-card-element.component.tsx +4 -0
  89. package/src/ward-patient-card/ward-patient-card.component.tsx +21 -14
  90. package/src/ward-patient-card/ward-patient-card.scss +61 -8
  91. package/src/ward-patient-card/ward-patient-resource.ts +15 -0
  92. package/src/ward-view/ward-view.component.tsx +124 -132
  93. package/src/ward-view/ward-view.resource.ts +121 -1
  94. package/src/ward-view/ward-view.scss +16 -6
  95. package/src/ward-view/ward-view.test.tsx +27 -42
  96. package/src/ward-view-header/admission-requests-bar.component.tsx +8 -7
  97. package/src/ward-view-header/admission-requests-bar.test.tsx +8 -21
  98. package/src/ward-view-header/admission-requests.scss +1 -1
  99. package/src/ward-view-header/ward-metric.component.tsx +24 -0
  100. package/src/ward-view-header/ward-metric.scss +25 -0
  101. package/src/ward-view-header/ward-metrics.component.tsx +77 -0
  102. package/src/ward-view-header/ward-metrics.scss +8 -0
  103. package/src/ward-view-header/ward-metrics.test.tsx +91 -0
  104. package/src/ward-view-header/ward-view-header.component.tsx +3 -0
  105. package/src/ward-view-header/ward-view-header.scss +0 -1
  106. package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +11 -3
  107. package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +4 -5
  108. package/src/ward-workspace/admission-request-card/admission-request-card.scss +8 -4
  109. package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +8 -3
  110. package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +2 -0
  111. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +29 -61
  112. package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +37 -21
  113. package/src/ward-workspace/patient-banner/patient-banner.component.tsx +3 -3
  114. package/src/ward-workspace/patient-clinical-forms-workspace/patient-clinical-forms.workspace.tsx +23 -0
  115. package/src/{ward-patient-workspace → ward-workspace/patient-details}/ward-patient-action-button.extension.tsx +2 -1
  116. package/src/{ward-patient-workspace → ward-workspace/patient-details}/ward-patient.workspace.tsx +7 -5
  117. package/src/ward-workspace/patient-discharge/patient-discharge.scss +41 -0
  118. package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +120 -0
  119. package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +40 -30
  120. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +29 -22
  121. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.scss +12 -2
  122. package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +2 -2
  123. package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.workspace.tsx +11 -0
  124. package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +1 -1
  125. package/src/ward-workspace/ward-patient-notes/form/notes-form.test.tsx +1 -1
  126. package/src/ward-workspace/ward-patient-notes/history/notes-container.component.tsx +2 -2
  127. package/src/ward-workspace/ward-patient-notes/notes.resource.ts +5 -7
  128. package/src/ward-workspace/ward-patient-notes/notes.workspace.tsx +1 -1
  129. package/src/ward-workspace/ward-patient-notes/types.ts +0 -4
  130. package/src/ward.resource.ts +6 -0
  131. package/translations/en.json +18 -1
  132. package/dist/346.js +0 -1
  133. package/dist/346.js.map +0 -1
  134. package/dist/76.js +0 -1
  135. package/dist/76.js.map +0 -1
  136. package/dist/803.js +0 -1
  137. package/dist/803.js.map +0 -1
  138. package/dist/958.js +0 -2
  139. package/dist/958.js.map +0 -1
  140. package/dist/960.js +0 -1
  141. package/dist/960.js.map +0 -1
  142. /package/dist/{958.js.LICENSE.txt → 161.js.LICENSE.txt} +0 -0
  143. /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 { openmrsFetch, restBaseUrl, type Concept } from '@openmrs/esm-framework';
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
- // fetch the members of the concept sets and process the data
17
- // to return conceptToTagColorMap (wrapped in a promise).
18
- // Let swr cache the result of this function.
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
- return openmrsFetch<{ results: Array<Concept> }>(url).then((data) => {
31
- const conceptSets = data.data.results;
32
- const conceptToTagColorMap = new Map<string, string>();
33
- if (conceptSets) {
34
- for (const conceptSet of conceptSets) {
35
- for (const concept of conceptSet.setMembers) {
36
- if (!conceptToTagColorMap.has(concept.uuid)) {
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
- return conceptToTagColorMap;
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 conceptToTagColorMap = useSWRImmutable(apiUrl, fetchAndMap);
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 { type OpenmrsResource, type Patient, translateFrom, type Visit } from '@openmrs/esm-framework';
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 { moduleName } from '../../constant';
9
- import { obsCustomRepresentation } from './ward-patient-obs.resource';
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, labelI18nModule: labelModule } = config;
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?.data?.results
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
- return <span key={o.uuid}> {display} </span>;
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.wardPatientCardRow, styles.wardPatientCardExtensionSlot)}
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
- launchWorkspace<WardPatientWorkspaceProps>('ward-patient-workspace', {
54
- wardPatient,
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
- .wardPatientCardRow:empty {
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-wrap: wrap;
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
+ }