Skip to content

Commit

Permalink
(feat) Vitals header UI enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
denniskigen committed Oct 18, 2024
1 parent 3c84dc4 commit 0009056
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 45 deletions.
3 changes: 1 addition & 2 deletions __mocks__/react-i18next.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ useMock.i18n = { language: 'en_US' };

module.exports = {
// this mock makes sure any components using the translate HoC receive the t function as a prop
Trans: ({ children }) => renderNodes(children),
Trans: ({ children }) => (Array.isArray(children) ? renderNodes(children) : renderNodes([children])),
Translation: ({ children }) => children((k) => k, { i18n: {} }),
useTranslation: () => useMock,

// mock if needed
I18nextProvider: reactI18next.I18nextProvider,
initReactI18next: reactI18next.initReactI18next,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
.label {
@include type.type-style('label-01');
color: $text-02;
margin-right: 0.375rem;
}

.danger-icon {
Expand Down Expand Up @@ -78,18 +77,27 @@
}
}

.arrow {
color: colors.$gray-100;
font-weight: 500;
}

.low::after {
@extend .arrow;
content: '';
}

.critically-low::after {
@extend .arrow;
content: ' ↓↓';
}

.high::after {
@extend .arrow;
content: '';
}

.critically-high::after {
@extend .arrow;
content: ' ↑↑';
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import duration from 'dayjs/plugin/duration';
import isToday from 'dayjs/plugin/isToday';
dayjs.extend(isToday);
dayjs.extend(duration);
import { useTranslation } from 'react-i18next';
import { Trans, useTranslation } from 'react-i18next';
import { Button, InlineLoading, Tag } from '@carbon/react';
import { ArrowRight, Time } from '@carbon/react/icons';
import { ArrowRight } from '@carbon/react/icons';
import { ConfigurableLink, formatDate, parseDate, useConfig, useWorkspaces } from '@openmrs/esm-framework';
import { useVisitOrOfflineVisit } from '@openmrs/esm-patient-common-lib';
import {
Expand Down Expand Up @@ -37,13 +37,11 @@ const VitalsHeader: React.FC<VitalsHeaderProps> = ({ patientUuid }) => {
const { currentVisit } = useVisitOrOfflineVisit(patientUuid);
const { workspaces } = useWorkspaces();

const isWorkspaceOpen = useCallback(() => {
return Boolean(workspaces?.length);
}, [workspaces]);
const isWorkspaceOpen = useCallback(() => Boolean(workspaces?.length), [workspaces]);

const launchVitalsAndBiometricsForm = useCallback(
(e: Event) => {
e.stopPropagation();
(event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
launchForm(currentVisit, config);
},
[config, currentVisit],
Expand All @@ -61,19 +59,37 @@ const VitalsHeader: React.FC<VitalsHeaderProps> = ({ patientUuid }) => {
const vitalsOverdue = hasActiveVisit && !vitalsTakenToday;
const now = dayjs();
const vitalsOverdueDayCount = Math.round(dayjs.duration(now.diff(latestVitals?.date)).asDays());
let overdueVitalsTagContent = '';

let overdueVitalsTagContent: React.ReactNode = 'null';

switch (true) {
case vitalsOverdueDayCount >= 1 && vitalsOverdueDayCount <= 7:
overdueVitalsTagContent = t('daysOldVitals', 'These vitals are {{count}} days old', {
count: vitalsOverdueDayCount,
});
overdueVitalsTagContent = (
<Trans i18nKey="daysOldVitals" count={vitalsOverdueDayCount}>
<span>
{/* @ts-ignore Workaround for i18next types issue (see https://github.com/i18next/react-i18next/issues/1543). Additionally, I can't find a way to get the proper plural suffix to be used in the translation file without amending the translation file by hand. */}
These vitals are <strong>{{ count: vitalsOverdueDayCount }} day old</strong>
</span>
</Trans>
);
break;
case vitalsOverdueDayCount >= 8 && vitalsOverdueDayCount <= 14:
overdueVitalsTagContent = t('overOneWeekOldVitals', 'These vitals are over one week old');
overdueVitalsTagContent = (
<Trans i18nKey="overOneWeekOldVitals">
<span>
These vitals are <strong>over one week old</strong>
</span>
</Trans>
);
break;
default:
overdueVitalsTagContent = t('outOfDateVitals', 'These vitals are out of date');
overdueVitalsTagContent = (
<Trans i18nKey="outOfDateVitals">
<span>
These vitals are <strong>out of date</strong>
</span>
</Trans>
);
break;
}

Expand All @@ -86,11 +102,8 @@ const VitalsHeader: React.FC<VitalsHeaderProps> = ({ patientUuid }) => {
{formatDate(parseDate(latestVitals?.date), { day: true, time: true })}
</span>
{vitalsOverdue ? (
<Tag type="red">
<span className={styles.overdueIndicator}>
<Time />
{`${t('overdue', 'Overdue')}: ${overdueVitalsTagContent}`}
</span>
<Tag className={styles.tag} type="red">
<span className={styles.overdueIndicator}>{overdueVitalsTagContent}</span>
</Tag>
) : null}
<ConfigurableLink
Expand Down Expand Up @@ -166,7 +179,7 @@ const VitalsHeader: React.FC<VitalsHeaderProps> = ({ patientUuid }) => {
/>
<VitalsHeaderItem
interpretation={assessValue(
latestVitals.temperature,
latestVitals?.temperature,
getReferenceRangesForConcept(config.concepts.temperatureUuid, conceptMetadata),
)}
unitName={t('temperatureAbbreviated', 'Temp')}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,63 @@
@use '@carbon/colors';
@use '@carbon/layout';
@use '@carbon/type';
@use '@openmrs/esm-styleguide/src/vars' as *;

.container {
background-color: $openmrs-background-grey;
padding: layout.$spacing-03 layout.$spacing-05 layout.$spacing-05;
border-bottom: 1px solid $ui-03;
}

.vitalsHeader {
display: flex;
justify-content: space-between;
align-items: center;
min-height: layout.$spacing-09;
padding-left: layout.$spacing-05;
min-height: layout.$spacing-07;
outline: none;
pointer-events: visibleFill;
}

.emptyStateVitalsHeader {
@extend .vitalsHeader;
background-color: $openmrs-background-grey;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 layout.$spacing-05;
min-height: layout.$spacing-09;
outline: none;
pointer-events: visibleFill;
border-bottom: 1px solid $ui-03;

.container {
border-bottom: none;
padding: 0;
}

.bodyText {
margin-left: layout.$spacing-03;
}
}

.headerItems {
display: flex;
align-items: center;
align-items: baseline;
flex-flow: row wrap;
gap: layout.$spacing-02;
gap: layout.$spacing-02 layout.$spacing-04;
}

.heading {
@include type.type-style('heading-compact-02');
margin-right: layout.$spacing-03;
color: $ui-05 !important;
}

.rowContainer {
width: 100%;
border-bottom: 1px solid $ui-03;
padding-bottom: layout.$spacing-04;
}

.row {
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 layout.$spacing-05;
max-width: 100vw;
}

Expand All @@ -65,10 +77,15 @@
min-height: layout.$spacing-09;
}

.tag {
margin-right: 0;
}

.overdueIndicator {
display: flex;
align-items: center;
min-inline-size: max-content;
color: colors.$red-70;

svg {
margin-right: layout.$spacing-02;
Expand Down Expand Up @@ -97,19 +114,12 @@
margin-left: layout.$spacing-03;
}

.heading {
@include type.type-style('heading-compact-02');
margin-right: layout.$spacing-03;
color: $text-02;
}

.bodyText {
@include type.type-style('label-01');
color: $text-02;
}

.link {
margin-left: layout.$spacing-02;
@extend .bodyText;
text-decoration-line: none;
color: $interactive-01;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import dayjs from 'dayjs';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { type WorkspacesInfo, getDefaultsFromConfigSchema, useConfig, useWorkspaces } from '@openmrs/esm-framework';
Expand Down Expand Up @@ -88,7 +89,7 @@ describe('VitalsHeader', () => {
expect(getByTextWithMarkup(/Height\s*-\s*/i)).toBeInTheDocument();
expect(getByTextWithMarkup(/BMI\s*-\s*/i)).toBeInTheDocument();
expect(getByTextWithMarkup(/Weight\s*-\s*/i)).toBeInTheDocument();
expect(screen.getByText(/overdue: these vitals are out of date/i)).toBeInTheDocument();
expect(getByTextWithMarkup(/these vitals are out of date/i)).toBeInTheDocument();
});

it('launches the vitals form when the `record vitals` button is clicked', async () => {
Expand All @@ -106,6 +107,27 @@ describe('VitalsHeader', () => {
expect(mockLaunchPatientWorkspace).toHaveBeenCalledWith(patientVitalsBiometricsFormWorkspace);
});

it('displays correct overdue tag for vitals 5 days old', async () => {
const fiveDaysAgo = dayjs().subtract(5, 'days').toISOString();
const vitalsData = [
{
...formattedVitals[0],
date: fiveDaysAgo,
},
];

mockUseVitalsAndBiometrics.mockReturnValue({
data: vitalsData,
} as ReturnType<typeof useVitalsAndBiometrics>);

renderWithSwr(<VitalsHeader {...testProps} />);

await waitForLoadingToFinish();

// TODO: Fix pluralization so that the string reads "5 days old"
expect(getByTextWithMarkup(/These vitals are 5 day old/i)).toBeInTheDocument();
});

it('does not flag normal values that lie within the provided reference ranges', async () => {
mockUseVitalsAndBiometrics.mockReturnValue({
data: formattedVitals,
Expand Down
9 changes: 4 additions & 5 deletions packages/esm-patient-vitals-app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"checkForValidity": "Some of the values entered are invalid",
"date": "Date",
"dateAndTime": "Date and time",
"daysOldVitals_one": "These vitals are {{count}} day old",
"daysOldVitals_other": "These vitals are {{count}} days old",
"daysOldVitals_one": "<0>These vitals are <1>{{count}} day old</1></0>",
"daysOldVitals_other": "<0>These vitals are <1>{{count}} days old</1></0>",
"diastolic": "diastolic",
"discard": "Discard",
"error": "Error",
Expand All @@ -28,9 +28,8 @@
"noDataRecorded": "No data has been recorded for this patient",
"notes": "Notes",
"other": "Other",
"outOfDateVitals": "These vitals are out of date",
"overdue": "Overdue",
"overOneWeekOldVitals": "These vitals are over one week old",
"outOfDateVitals": "<0>These vitals are <1>out of date</1></0>",
"overOneWeekOldVitals": "<0>These vitals are <1>over one week old</1></0>",
"oxygenSaturation": "Oxygen saturation",
"pleaseFillField": "Please fill at least one field",
"print": "Print",
Expand Down

0 comments on commit 0009056

Please sign in to comment.