From ba179e49253838d849ebfe33b0788acc78b18650 Mon Sep 17 00:00:00 2001 From: Usama Idriss Kakumba <53287480+usamaidrsk@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:12:28 +0300 Subject: [PATCH] (feat) O3-3737: Add configurable details about pending orders on the patient card (#1296) * feat: configure pending orders * chore: translations * rename pending-orders to pending-items slot name --- .../config-schema-pending-orders-extension.ts | 25 ++++++++++++++ packages/esm-ward-app/src/config-schema.ts | 9 +++++ .../src/hooks/usePatientPendingOrders.ts | 16 +++++++++ packages/esm-ward-app/src/index.ts | 7 ++++ packages/esm-ward-app/src/routes.json | 5 +++ .../card-rows/pending-orders.extension.tsx | 28 ++++++++++++++++ .../ward-patient-pending-order.component.tsx | 33 +++++++++++++++++++ .../ward-patient-card.component.tsx | 13 ++++++-- .../ward-patient-card/ward-patient-card.scss | 16 ++++++++- packages/esm-ward-app/translations/en.json | 1 + 10 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 packages/esm-ward-app/src/config-schema-pending-orders-extension.ts create mode 100644 packages/esm-ward-app/src/hooks/usePatientPendingOrders.ts create mode 100644 packages/esm-ward-app/src/ward-patient-card/card-rows/pending-orders.extension.tsx create mode 100644 packages/esm-ward-app/src/ward-patient-card/row-elements/ward-patient-pending-order.component.tsx diff --git a/packages/esm-ward-app/src/config-schema-pending-orders-extension.ts b/packages/esm-ward-app/src/config-schema-pending-orders-extension.ts new file mode 100644 index 000000000..ed6ebc540 --- /dev/null +++ b/packages/esm-ward-app/src/config-schema-pending-orders-extension.ts @@ -0,0 +1,25 @@ +import { Type } from '@openmrs/esm-framework'; + +export const pendingOrdersExtensionConfigSchema = { + orderTypes: { + _type: Type.Array, + _description: 'Defines order types displayed on the ward patient card pending items section.', + _default: [{ label: 'Labs', uuid: '52a447d3-a64a-11e3-9aeb-50e549534c5e' }], + _elements: { + uuid: { + _type: Type.UUID, + _description: 'Identifies the order type.', + }, + label: { + _type: Type.String, + _description: "The label or i18n key to the translated label to display. If not provided, defaults to 'Orders'", + _default: null, + }, + }, + }, + enabled: { + _type: Type.Boolean, + _description: 'Optional. Enable pending order visibility on ward card pending items', + _default: true, + }, +}; diff --git a/packages/esm-ward-app/src/config-schema.ts b/packages/esm-ward-app/src/config-schema.ts index c235c2a88..026447013 100644 --- a/packages/esm-ward-app/src/config-schema.ts +++ b/packages/esm-ward-app/src/config-schema.ts @@ -185,11 +185,20 @@ export interface WardConfigObject { export interface WardPatientCardsConfig { obsElementDefinitions: Array; + pendingOrderTypesDefinitions: Array; identifierElementDefinitions: Array; addressElementDefinitions: Array; cardDefinitions: Array; } +export interface PendingOrderTypesDefinition { + enabled: boolean; + orderTypes: Array<{ + label?: string; + uuid: string; + }>; +} + export interface ObsElementDefinition { id: string; conceptUuid: string; diff --git a/packages/esm-ward-app/src/hooks/usePatientPendingOrders.ts b/packages/esm-ward-app/src/hooks/usePatientPendingOrders.ts new file mode 100644 index 000000000..c22761b1c --- /dev/null +++ b/packages/esm-ward-app/src/hooks/usePatientPendingOrders.ts @@ -0,0 +1,16 @@ +import { type FetchResponse, openmrsFetch, type OpenmrsResource, restBaseUrl } from '@openmrs/esm-framework'; +import useSWR from 'swr'; + +export function usePatientPendingOrders(patientUuid: string, orderTypeUUid: string, visitStartDate: string) { + const apiUrl = + patientUuid && orderTypeUUid && visitStartDate + ? `${restBaseUrl}/order?includeNullFulfillerStatus=true&patient=${patientUuid}&orderTypes=${orderTypeUUid}&activatedOnOrAfterDate=${visitStartDate}` + : null; + const { data, ...rest } = useSWR }>, Error>(apiUrl, openmrsFetch); + + return { + orders: data?.data.results, + count: data?.data.results.length, + ...rest, + }; +} diff --git a/packages/esm-ward-app/src/index.ts b/packages/esm-ward-app/src/index.ts index 73e9c9b2e..ce121f2d9 100644 --- a/packages/esm-ward-app/src/index.ts +++ b/packages/esm-ward-app/src/index.ts @@ -12,6 +12,7 @@ import { coloredObsTagsCardRowConfigSchema } from './config-schema-extension-col import { moduleName } from './constant'; import { createDashboardLink } from './createDashboardLink.component'; import rootComponent from './root.component'; +import { pendingOrdersExtensionConfigSchema } from './config-schema-pending-orders-extension'; export const importTranslation = require.context('../translations', false, /.json$/, 'lazy'); @@ -67,6 +68,11 @@ export const admissionRequestNoteRowExtension = getAsyncLifecycle( options, ); +export const pendingOrdersExtension = getAsyncLifecycle( + () => import('./ward-patient-card/card-rows/pending-orders.extension'), + options, +); + // t('transfers', 'Transfers') export const patientTransferAndSwapWorkspace = getAsyncLifecycle( () => import('./ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace'), @@ -100,6 +106,7 @@ export function startupApp() { defineConfigSchema(moduleName, configSchema); defineExtensionConfigSchema('colored-obs-tags-card-row', coloredObsTagsCardRowConfigSchema); defineExtensionConfigSchema('admission-request-note-card-row', admissionRequestNoteRowConfigSchema); + defineExtensionConfigSchema('ward-patient-pending-orders', pendingOrdersExtensionConfigSchema); registerFeatureFlag( 'bedmanagement-module', diff --git a/packages/esm-ward-app/src/routes.json b/packages/esm-ward-app/src/routes.json index b350a4d77..5d651d4de 100644 --- a/packages/esm-ward-app/src/routes.json +++ b/packages/esm-ward-app/src/routes.json @@ -59,6 +59,11 @@ "component": "admissionRequestNoteRowExtension", "name": "admission-request-note-card-row", "slot": "ward-patient-card-slot" + }, + { + "component": "pendingOrdersExtension", + "name": "ward-patient-pending-orders", + "slot": "ward-patient-card-pending-items-slot" } ], "workspaces": [ diff --git a/packages/esm-ward-app/src/ward-patient-card/card-rows/pending-orders.extension.tsx b/packages/esm-ward-app/src/ward-patient-card/card-rows/pending-orders.extension.tsx new file mode 100644 index 000000000..fb7291508 --- /dev/null +++ b/packages/esm-ward-app/src/ward-patient-card/card-rows/pending-orders.extension.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { type WardPatientCard } from '../../types'; +import { useConfig } from '@openmrs/esm-framework'; +import type { PendingOrderTypesDefinition } from '../../config-schema'; +import { WardPatientPendingOrder } from '../row-elements/ward-patient-pending-order.component'; + +const PendingOrdersExtension: WardPatientCard = (wardPatient) => { + const { orderTypes, enabled } = useConfig(); + + if (!enabled || !orderTypes) { + return <>; + } + + return ( + <> + {orderTypes.map(({ uuid, label }) => ( + + ))} + + ); +}; + +export default PendingOrdersExtension; diff --git a/packages/esm-ward-app/src/ward-patient-card/row-elements/ward-patient-pending-order.component.tsx b/packages/esm-ward-app/src/ward-patient-card/row-elements/ward-patient-pending-order.component.tsx new file mode 100644 index 000000000..ca73df645 --- /dev/null +++ b/packages/esm-ward-app/src/ward-patient-card/row-elements/ward-patient-pending-order.component.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { ChemistryReference } from '@carbon/react/icons'; +import styles from '../ward-patient-card.scss'; +import { useTranslation } from 'react-i18next'; +import { type WardPatient } from '../../types'; +import { usePatientPendingOrders } from '../../hooks/usePatientPendingOrders'; + +export interface WardPatientPendingOrderProps { + wardPatient: WardPatient; + orderUuid: string; + label: string; +} + +export const WardPatientPendingOrder: React.FC = ({ wardPatient, orderUuid, label }) => { + const { t } = useTranslation(); + const { count, isLoading } = usePatientPendingOrders( + wardPatient?.patient?.uuid, + orderUuid, + wardPatient?.visit?.startDatetime.split('T')[0], + ); + + if (isLoading || !count || count == 0) { + return null; + } + + const labelToDisplay = label ? t(label) : t('Orders', 'Orders'); + return ( +
+ + {count} {labelToDisplay} +
+ ); +}; diff --git a/packages/esm-ward-app/src/ward-patient-card/ward-patient-card.component.tsx b/packages/esm-ward-app/src/ward-patient-card/ward-patient-card.component.tsx index 07c30fbc6..6b85695b7 100644 --- a/packages/esm-ward-app/src/ward-patient-card/ward-patient-card.component.tsx +++ b/packages/esm-ward-app/src/ward-patient-card/ward-patient-card.component.tsx @@ -1,4 +1,4 @@ -import { ExtensionSlot, getPatientName, launchWorkspace } from '@openmrs/esm-framework'; +import { ExtensionSlot, getPatientName, launchWorkspace, useConfig } from '@openmrs/esm-framework'; import classNames from 'classnames'; import React from 'react'; import { Hourglass } from '@carbon/react/icons'; @@ -9,10 +9,12 @@ import WardPatientName from './row-elements/ward-patient-name'; import { WardPatientCardElement } from './ward-patient-card-element.component'; import styles from './ward-patient-card.scss'; import WardPatientPendingTransfer from './row-elements/ward-patient-pending-transfer'; +import { type PendingOrderTypesDefinition } from '../config-schema'; const WardPatientCard: WardPatientCard = (wardPatient) => { const { patient, bed } = wardPatient; const { id, headerRowElements, footerRowElements } = useCurrentWardCardConfig(); + const { enabled: showPendingOrders } = useConfig(); const headerExtensionSlotName = id == 'default' ? 'ward-patient-card-header-slot' : `ward-patient-card-header-${id}-slot`; @@ -34,10 +36,15 @@ const WardPatientCard: WardPatientCard = (wardPatient) => { ))} - {wardPatient?.inpatientRequest ? ( + {wardPatient?.inpatientRequest || showPendingOrders ? (
: - + + {wardPatient?.inpatientRequest ? : null}
) : null}