Skip to content

Commit

Permalink
(feat) O3-3250: Add in-patient notes workspace (#1238)
Browse files Browse the repository at this point in the history
  • Loading branch information
usamaidrsk authored Aug 2, 2024
1 parent 52605c0 commit 020cde3
Show file tree
Hide file tree
Showing 21 changed files with 557 additions and 41 deletions.
6 changes: 6 additions & 0 deletions __mocks__/emr-configuration.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const emrConfigurationMock = {
clinicianEncounterRole: { uuid: '240b26f9-dd88-4172-823d-4a8bfeb7841f' },
consultFreeTextCommentsConcept: { uuid: '162169AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' },
visitNoteEncounterType: { uuid: 'd7151f82-c1f3-4152-a605-2f9ea7414a79' },
admissionEncounterType: { uuid: 'e8151f82-c1f3-4152-a605-2f9ea7414a79' },
};
1 change: 1 addition & 0 deletions __mocks__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './active-visits.mock';
export * from './address.mock';
export * from './appointments.mock';
export * from './auto-generation-options.mock';
export * from './emr-configuration.mock';
export * from './identifier-types.mock';
export * from './identifiers.mock';
export * from './locations.mock';
Expand Down
4 changes: 2 additions & 2 deletions packages/esm-ward-app/src/config-schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Type, validators, type ConfigSchema, type PersonAddress } from '@openmrs/esm-framework';
import { patientCardElementTypes, type PatientCardElementType } from './types';
import { type ConfigSchema, type PersonAddress, Type, validators } from '@openmrs/esm-framework';
import { type PatientCardElementType, patientCardElementTypes } from './types';

const defaultWardPatientCard: WardPatientCardDefinition = {
id: 'default-card',
Expand Down
17 changes: 15 additions & 2 deletions packages/esm-ward-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
import { configSchema } from './config-schema';
import rootComponent from './root.component';
import { moduleName } from './constant';
import WardPatientActionButton from './ward-patient-workspace/ward-patient-action-button.extension';
import { createDashboardLink } from './createDashboardLink.component';

export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
Expand Down Expand Up @@ -39,7 +38,21 @@ export const wardPatientWorkspace = getAsyncLifecycle(
options,
);

export const wardPatientActionButtonExtension = getSyncLifecycle(WardPatientActionButton, options);
// t("inpatientNotesWorkspaceTitle", "In-patient notes")
export const wardPatientNotesWorkspace = getAsyncLifecycle(
() => import('./ward-workspace/ward-patient-notes/notes.workspace'),
options,
);

export const wardPatientActionButtonExtension = getAsyncLifecycle(
() => import('./ward-patient-workspace/ward-patient-action-button.extension'),
options,
);

export const wardPatientNotesActionButtonExtension = getAsyncLifecycle(
() => import('./ward-workspace/ward-patient-notes/notes-action-button.extension'),
options,
);

export function startupApp() {
registerBreadcrumbs([]);
Expand Down
42 changes: 28 additions & 14 deletions packages/esm-ward-app/src/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"webservices.rest": "^2.2.0",
"emrapi": "^2.0.0 || 2.0.0-SNAPSHOT"
},
"optionalBackendDependencies":{
"bedmanagement":{
"optionalBackendDependencies": {
"bedmanagement": {
"version": "^6.0.0 || 6.0.0-SNAPSHOT",
"feature": {
"flagName": "bedmanagement-module",
"label":"Ward App Patient Service",
"label": "Ward App Patient Service",
"description": "This module, if installed, provides services for managing patients admitted to the ward."
}
}
}
},
"extensions": [
{
Expand All @@ -31,22 +31,36 @@
"slot": "ward-dashboard-slot"
},
{
"component": "wardPatientActionButtonExtension",
"name": "ward-patient-action-button",
"slot": "action-menu-ward-patient-items-slot"
}],
"component": "wardPatientActionButtonExtension",
"name": "ward-patient-action-button",
"slot": "action-menu-ward-patient-items-slot"
},
{
"component": "wardPatientNotesActionButtonExtension",
"name": "ward-inpatient-notes-form-action-button",
"slot": "action-menu-ward-patient-items-slot"
}
],
"workspaces": [
{
"name":"admission-requests-workspace",
"name": "admission-requests-workspace",
"component": "admissionRequestWorkspace",
"title":"admissionRequests",
"type":"admission-requests"
"title": "admissionRequests",
"type": "admission-requests"
},
{
"name": "ward-patient-notes-workspace",
"component": "wardPatientNotesWorkspace",
"type": "ward-patient-notes",
"title": "inpatientNotesWorkspaceTitle",
"sidebarFamily": "ward-patient",
"hasOwnSidebar": true
},
{
"name":"admit-patient-form-workspace",
"name": "admit-patient-form-workspace",
"component": "admitPatientFormWorkspace",
"title":"admissionRequests",
"type":"admission-requests"
"title": "admissionRequests",
"type": "admission-requests"
},
{
"name": "ward-patient-workspace",
Expand Down
28 changes: 25 additions & 3 deletions packages/esm-ward-app/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type {
Concept,
Location,
OpenmrsResource,
OpenmrsResourceStrict,
Patient,
Person,
Visit,
Location,
Patient,
Concept,
} from '@openmrs/esm-framework';
import type React from 'react';

Expand Down Expand Up @@ -47,6 +47,7 @@ export interface AdmissionLocationFetchResponse {
ward: Location;
bedLayouts: Array<BedLayout>;
}

export interface Bed {
id: number;
uuid: string;
Expand Down Expand Up @@ -164,3 +165,24 @@ export interface EncounterRole extends OpenmrsResourceStrict {
description?: string;
retired?: boolean;
}

export interface EncounterPayload {
encounterDatetime?: string;
encounterType: string;
patient: string;
location: string;
encounterProviders?: Array<{ encounterRole: string; provider: string }>;
obs: Array<ObsPayload>;
form?: string;
orders?: Array<any>;
visit?: string;
}

export interface ObsPayload {
concept: Concept;
value?: string;
groupMembers?: Array<{
concept: Concept;
value: string;
}>;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useConfig } from '@openmrs/esm-framework';
import { useMemo } from 'react';
import React, { useMemo } from 'react';
import {
builtInPatientCardElements,
defaultPatientCardElementConfig,
Expand All @@ -11,7 +11,6 @@ import WardPatientAge from './row-elements/ward-patient-age';
import WardPatientBedNumber from './row-elements/ward-patient-bed-number';
import wardPatientAddress from './row-elements/ward-patient-header-address';
import WardPatientName from './row-elements/ward-patient-name';
import React from 'react';
import styles from './ward-patient-card.scss';
import wardPatientObs from './row-elements/ward-patient-obs';
import wardPatientCodedObsTags from './row-elements/ward-patient-coded-obs-tags';
Expand Down
15 changes: 15 additions & 0 deletions packages/esm-ward-app/src/ward-patient-card/ward-patient-card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@
}
}

.activeWardPatientCardButton {
&::before {
content: '';
position: absolute;
inset: 0;
z-index: 1;
cursor: pointer;
border: 2px solid $interactive-01;
transition: border-color 200ms;
}
}

.wardPatientCardRow {
width: 100%;
padding: spacing.$spacing-04;
Expand All @@ -62,6 +74,7 @@
.wardPatientName {
@include type.type-style('heading-compact-02');
color: $text-02;

&::before {
content: '' !important;
}
Expand All @@ -78,6 +91,7 @@
display: flex;
justify-content: center;
align-items: center;

&.empty {
background-color: $color-blue-10;
color: $color-blue-60-2;
Expand Down Expand Up @@ -106,6 +120,7 @@
> div:not(div:first-of-type) {
display: flex;
align-items: center;

&::before {
content: '·';
padding: 0 spacing.$spacing-02;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import { useParams } from 'react-router-dom';
import { type WardPatientCardProps } from '../types';
import { usePatientCardRows } from './ward-patient-card-row.resources';
import styles from './ward-patient-card.scss';
import { getPatientName, launchWorkspace } from '@openmrs/esm-framework';
import { type WardPatientWorkspaceProps } from '../ward-patient-workspace/ward-patient.workspace';
import { type WardPatientWorkspaceProps } from '../ward-patient-workspace/types';

const WardPatientCard: React.FC<WardPatientCardProps> = (props) => {
const patientCardRows = usePatientCardRows();
Expand All @@ -16,9 +15,12 @@ const WardPatientCard: React.FC<WardPatientCardProps> = (props) => {
))}
<button
className={styles.wardPatientCardButton}
onClick={() =>
launchWorkspace<WardPatientWorkspaceProps>('ward-patient-workspace', { patientUuid: props.patient.uuid })
}>
onClick={() => {
launchWorkspace<WardPatientWorkspaceProps>('ward-patient-workspace', {
patientUuid: props.patient.uuid,
...props,
});
}}>
{/* Name will not be displayed; just there for a11y */}
{getPatientName(props.patient.person)}
</button>
Expand Down
6 changes: 6 additions & 0 deletions packages/esm-ward-app/src/ward-patient-workspace/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { DefaultWorkspaceProps, PatientUuid } from '@openmrs/esm-framework';
import type { WardPatientCardProps } from '../types';

export interface WardPatientWorkspaceProps extends DefaultWorkspaceProps, WardPatientCardProps {
patientUuid: PatientUuid;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import React, { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { InlineLoading, InlineNotification } from '@carbon/react';
import {
type DefaultWorkspaceProps,
ExtensionSlot,
attach,
getPatientName,
usePatient,
age,
} from '@openmrs/esm-framework';
import { age, attach, ExtensionSlot, getPatientName, usePatient } from '@openmrs/esm-framework';
import styles from './ward-patient.style.scss';
import { type WardPatientWorkspaceProps } from './types';

attach('ward-patient-workspace-header-slot', 'patient-vitals-info');

export interface WardPatientWorkspaceProps extends DefaultWorkspaceProps {
patientUuid: string;
}

export default function WardPatientWorkspace({ patientUuid, setTitle }: WardPatientWorkspaceProps) {
export default function WardPatientWorkspace({ setTitle, patientUuid }: WardPatientWorkspaceProps) {
const { t } = useTranslation();
const { patient, isLoading, error } = usePatient(patientUuid);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useMemo } from 'react';
import { useConfig } from '@openmrs/esm-framework';
import { defaultPatientCardElementConfig, type WardConfigObject } from '../../config-schema';
import { getPatientCardElementFromDefinition } from '../../ward-patient-card/ward-patient-card-row.resources';
import type { PatientCardElementType, WardPatientCardProps } from '../../types';
import styles from './style.scss';
import useWardLocation from '../../hooks/useWardLocation';

const WardPatientWorkspaceBanner = ({ bed, patient, visit }: WardPatientCardProps) => {
const { location } = useWardLocation();
const { wardPatientCards } = useConfig<WardConfigObject>();
const { cardDefinitions } = wardPatientCards;

// extract configured elements for the patient card header to use for the banner section
const bannerElements = useMemo(() => {
const cardDefinition = cardDefinitions.find((cardDef) => {
const appliedTo = cardDef.appliedTo;

return appliedTo == null || appliedTo.some((criteria) => criteria.location == location.uuid);
});

const headerRow = cardDefinition.rows.find((cardDef) => cardDef.rowType === 'header');

return headerRow.elements.map((elementType: PatientCardElementType) =>
getPatientCardElementFromDefinition({
id: elementType,
elementType,
config: defaultPatientCardElementConfig,
}),
);
}, [cardDefinitions]);

if (!(patient && bed && visit)) return null;

return (
<div className={styles.patientBanner}>
{bannerElements.map((BannerElement) => (
<BannerElement patient={patient} visit={visit} bed={bed} />
))}
</div>
);
};

export default WardPatientWorkspaceBanner;
23 changes: 23 additions & 0 deletions packages/esm-ward-app/src/ward-workspace/patient-banner/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@use '@carbon/layout';
@import '~@openmrs/esm-styleguide/src/vars';

.patientBanner {
@extend .dotSeparatedChildren;
display: flex;
flex-wrap: wrap;
width: 100%;
padding: layout.$spacing-04;
background: $ui-01;
}

.dotSeparatedChildren {
> div:not(div:first-of-type) {
display: flex;
align-items: center;

&::before {
content: '·';
padding: 0 layout.$spacing-02;
}
}
}
Loading

0 comments on commit 020cde3

Please sign in to comment.