Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) O3-3250: Add in-patient notes workspace #1238

Merged
merged 16 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(
usamaidrsk marked this conversation as resolved.
Show resolved Hide resolved
() => 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 {
mogoodrich marked this conversation as resolved.
Show resolved Hide resolved
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 })
vasharma05 marked this conversation as resolved.
Show resolved Hide resolved
}>
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) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will defer to @chibongho when he gets back on this part...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chibongho I hope you can now take a look at this. Thanks

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
Loading