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

Ayush | 1207086955567553 | Refactor: removed hard coded concept names in Vitals Display Control #188

Merged
merged 1 commit into from
Apr 25, 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
12 changes: 11 additions & 1 deletion public/i18n/locale_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,15 @@
"CURRENT_SHIFT": "Current Shift",
"NOT_CURRENT_PERIOD_MESSAGE": "You're not viewing the current period",
"NO_IO_DATA_MESSAGE": "No intake output data is available for the patient in this period",
"SCHEDULE_TREATMENTS": "Schedule Treatments"
"SCHEDULE_TREATMENTS": "Schedule Treatments",
"DATE_TIME_HEADER": "Date and Time",
"PULSE_HEADER": "Pulse ({unit})",
"SPO2_HEADER": "SPO2 ({unit})",
"RESPIRATORY_RATE_HEADER": "R.rate ({unit})",
"TEMPERATURE_HEADER": "Temp ({unit})",
"BLOOD_PRESSURE_HEADER": "BP ({unit})",
"HEIGHT_HEADER": "Height ({unit})",
"WEIGHT_HEADER": "Weight ({unit})",
"BMI_HEADER": "BMI ({unit})",
"MUAC": "MUAC ({unit})"
}
128 changes: 85 additions & 43 deletions src/features/DisplayControls/Vitals/components/Vitals.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useEffect } from "react";
import React, { useEffect, useContext } from "react";
import { Column, Row, Tile, SkeletonText, Link } from "carbon-components-react";
import {
getPatientVitals,
getPatientVitalsHistory,
mapVitalsData,
mapVitalsHistory,
mapBiometricsHistory,
vitalsHistoryHeaders,
biometricsHistoryHeaders,
getVitalsHistoryHeaders,
getBiometricsHistoryHeaders,
} from "../utils/VitalsUtils";
import { useState } from "react";
import PropTypes from "prop-types";
Expand All @@ -16,19 +16,26 @@ import { FormattedMessage } from "react-intl";
import VitalsHistory from "./VitalsHistory";
import BiometricsHistory from "./BiometricsHistory";
import { vitalsHeaders } from "../utils/VitalsUtils";
import { ChevronDown20,ChevronUp20 } from "@carbon/icons-react";
import { ChevronDown20, ChevronUp20 } from "@carbon/icons-react";
import { IPDContext } from "../../../../context/IPDContext";

const Vitals = (props) => {
const { patientId } = props;
const [showMore, setShowMore] = useState(false);
const [vitals, setVitals] = useState({});
const [vitalsHistory, setVitalsHistory] = useState([]);
const [biometricsHistory, setBiometricsHistory] = useState([]);
const [vitalUnits, setVitalUnits] = useState({});
const [vitalsDate, setVitalsDate] = useState(null);
const [vitalsTime, setVitalsTime] = useState(null);
const [isLoading, updateIsLoading] = useState(true);

const [vitalsHistoryHeaders, setVitalsHistoryHeaders] = useState([]);
const [biometricsHistoryHeaders, setBiometricsHistoryHeaders] = useState([]);

const {
config: { vitalsConfig },
} = useContext(IPDContext);

const NoVitalsMessage = (
<FormattedMessage
id={"NO_VITALS_MESSAGE"}
Expand All @@ -44,29 +51,58 @@ const Vitals = (props) => {
);

const handleShowMore = () => setShowMore(!showMore);
const handleVitalUnits = (units) => {
let updatedUnits = {};

units.forEach((unit) => {
updatedUnits[unit.name] = unit.units;
});
const getConceptDetails = (conceptConfig, conceptDetails) => {
let concepts = {};

setVitalUnits((oldUnits) => {
return {
...oldUnits,
...updatedUnits,
};
Object.keys(conceptConfig).forEach((conceptName) => {
const obj = conceptDetails.find(
(field) =>
field.fullName.toLowerCase() ===
conceptConfig[conceptName].toLowerCase()
);
concepts[conceptName] = { name: obj?.name, unit: obj?.units };
});
return concepts;
};

useEffect(() => {
const getVitals = async () => {
const VitalsList = await getPatientVitals(patientId);
const vitalsHistoryList = await getPatientVitalsHistory(patientId);
handleVitalUnits(VitalsList.conceptDetails);
setVitals(mapVitalsData(VitalsList, vitalsHistoryList,setVitalsDate, setVitalsTime));
setVitalsHistory(mapVitalsHistory(vitalsHistoryList));
setBiometricsHistory(mapBiometricsHistory(vitalsHistoryList));
const VitalsList = await getPatientVitals(
patientId,
vitalsConfig.latestVitalsConceptValues
);
const vitalsHistoryList = await getPatientVitalsHistory(
patientId,
vitalsConfig.vitalsHistoryConceptValues
);
const conceptDetails = getConceptDetails(
vitalsConfig.latestVitalsConceptValues,
vitalsHistoryList.conceptDetails
);
setVitals(
mapVitalsData(
VitalsList,
vitalsHistoryList,
setVitalsDate,
setVitalsTime,
conceptDetails
)
);
const vitalsHistoryDetails = getConceptDetails(
vitalsConfig.vitalsHistoryConceptValues,
vitalsHistoryList.conceptDetails
);
setVitalsHistoryHeaders(getVitalsHistoryHeaders(vitalsHistoryDetails));
setBiometricsHistoryHeaders(
getBiometricsHistoryHeaders(vitalsHistoryDetails)
);
setVitalsHistory(
mapVitalsHistory(vitalsHistoryList, vitalsHistoryDetails)
);
setBiometricsHistory(
mapBiometricsHistory(vitalsHistoryList, vitalsHistoryDetails)
);
updateIsLoading(false);
};

Expand All @@ -82,20 +118,26 @@ const Vitals = (props) => {
) : (
<Tile className="vital-table">
<div className="vital-date-time">
{vitalsDate ? vitalsDate + " ": "-"}
{showMore ? (<Link
kind="tertiary"
className="show-more"
onClick={handleShowMore}
>
{vitalsHistoryMessage}<ChevronUp20/>
</Link>) : (<Link
kind="tertiary"
className="show-more"
onClick={handleShowMore}
>
{vitalsHistoryMessage}<ChevronDown20/>
</Link>)}
{vitalsDate ? vitalsDate + " " : "-"}
{showMore ? (
<Link
kind="tertiary"
className="show-more"
onClick={handleShowMore}
>
{vitalsHistoryMessage}
<ChevronUp20 />
</Link>
) : (
<Link
kind="tertiary"
className="show-more"
onClick={handleShowMore}
>
{vitalsHistoryMessage}
<ChevronDown20 />
</Link>
)}
</div>
<Row>
<Column>
Expand All @@ -108,7 +150,7 @@ const Vitals = (props) => {
<span className="vital-values">
{vitals.HeartRate?.value ? vitals.HeartRate?.value : "-"}{" "}
<span className="vital-units">
{vitals.HeartRate?.value ? vitalUnits.Pulse : " "}
{vitals.HeartRate?.value ? vitals.HeartRate?.unit : " "}
</span>{" "}
</span>
</Tile>
Expand All @@ -123,7 +165,7 @@ const Vitals = (props) => {
<span className="vital-values">
{vitals.SpO2?.value ? vitals.SpO2?.value : "-"}{" "}
<span className="vital-units">
{vitals.SpO2?.value ? vitalUnits.SpO2 : " "}
{vitals.SpO2?.value ? vitals.SpO2?.unit : " "}
</span>{" "}
</span>
</Tile>
Expand All @@ -145,7 +187,7 @@ const Vitals = (props) => {
: "-"}{" "}
<span className="vital-units">
{vitals.RespiratoryRate?.value
? vitalUnits["Respiratory Rate"]
? vitals.RespiratoryRate?.unit
: " "}
</span>{" "}
</span>
Expand All @@ -163,7 +205,7 @@ const Vitals = (props) => {
<span className="vital-values">
{vitals.Temp?.value ? vitals.Temp?.value : "-"}{" "}
<span className="vital-units">
{vitals.Temp?.value ? vitalUnits.Temperature : " "}
{vitals.Temp?.value ? vitals.Temp?.unit : " "}
</span>{" "}
</span>
</Tile>
Expand All @@ -189,7 +231,7 @@ const Vitals = (props) => {
: "-"}{" "}
<span className="vital-units">
{vitals.SystolicPressure?.value
? vitalUnits["Diastolic Blood Pressure"]
? vitals.SystolicPressure?.unit
: " "}
</span>{" "}
</span>
Expand All @@ -205,7 +247,7 @@ const Vitals = (props) => {
<span className="vital-values">
{vitals.Height?.value ? vitals.Height?.value : "-"}{" "}
<span className="vital-units">
{vitals.Height?.value ? vitalUnits.HEIGHT : " "}
{vitals.Height?.value ? vitals.Height?.unit : " "}
</span>{" "}
</span>
</Tile>
Expand All @@ -220,7 +262,7 @@ const Vitals = (props) => {
<span className="vital-values">
{vitals.Weight?.value ? vitals.Weight?.value : "-"}{" "}
<span className="vital-units">
{vitals.Weight?.value ? vitalUnits.WEIGHT : " "}
{vitals.Weight?.value ? vitals.Weight?.unit : " "}
</span>{" "}
</span>
</Tile>
Expand All @@ -235,7 +277,7 @@ const Vitals = (props) => {
<span className="vital-values">
{vitals.BMI?.value ? vitals.BMI?.value : "-"}{" "}
<span className="vital-units">
{vitals.BMI?.value ? vitalUnits.BMI : " "}
{vitals.BMI?.value ? vitals.BMI?.unit : " "}
</span>{" "}
</span>
</Tile>
Expand Down
43 changes: 36 additions & 7 deletions src/features/DisplayControls/Vitals/tests/Vitals.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
act,
} from "@testing-library/react";
import React from "react";
import { IPDContext } from "../../../../context/IPDContext";
import Vitals from "../components/Vitals";
import {
getPatientVitals,
Expand All @@ -16,6 +17,7 @@ import {
mockVitalsData,
mockVitalsHistoryData,
} from "./VitalsMockData";
import { mockConfig } from "../../../../utils/CommonUtils";

jest.mock("../utils/VitalsUtils", () => {
const originalModule = jest.requireActual("../utils/VitalsUtils");
Expand All @@ -34,7 +36,11 @@ describe("Vitals", () => {
it("displays vital and biometrics history after data is fetched", async () => {
getPatientVitals.mockResolvedValueOnce(mockVitalsData);
getPatientVitalsHistory.mockResolvedValueOnce(mockVitalsHistoryData);
const { container } = render(<Vitals patientId="123" />);
const { container } = render(
<IPDContext.Provider value={{ config: mockConfig }}>
<Vitals patientId="123" />
</IPDContext.Provider>
);

await waitFor(() => {
expect(screen.getByText(/Vitals History/i)).toBeTruthy();
Expand All @@ -53,7 +59,11 @@ describe("Vitals", () => {
it("should display vital details after data is fetched", async () => {
getPatientVitals.mockResolvedValueOnce(mockVitalsData);
getPatientVitalsHistory.mockResolvedValueOnce(mockVitalsHistoryData);
const { container } = render(<Vitals patientId="123" />);
const { container } = render(
<IPDContext.Provider value={{ config: mockConfig }}>
<Vitals patientId="123" />
</IPDContext.Provider>
);
await waitFor(() => {
expect(screen.getByText(/Temp/i)).toBeTruthy();
expect(container).toMatchSnapshot();
Expand All @@ -63,7 +73,11 @@ describe("Vitals", () => {
it("should display text when vitals is not present", async () => {
getPatientVitalsHistory.mockResolvedValueOnce(mockVitalsHistoryData);
getPatientVitals.mockResolvedValueOnce(mockNoVitalsData);
render(<Vitals patientId="123" />);
render(
<IPDContext.Provider value={{ config: mockConfig }}>
<Vitals patientId="123" />
</IPDContext.Provider>
);
await waitFor(() =>
expect(
screen.getByText("No Vitals available for this patient")
Expand All @@ -73,18 +87,33 @@ describe("Vitals", () => {

it("renders without crashing", () => {
getPatientVitals.mockResolvedValueOnce(mockVitalsData);
render(<Vitals patientId="123" />);
render(
<IPDContext.Provider value={{ config: mockConfig }}>
<Vitals patientId="123" />
</IPDContext.Provider>
);
});

it("calls getPatientVitals on mount", () => {
getPatientVitals.mockResolvedValueOnce(mockVitalsData);
render(<Vitals patientId="123" />);
expect(getPatientVitals).toHaveBeenCalledWith("123");
render(
<IPDContext.Provider value={{ config: mockConfig }}>
<Vitals patientId="123" />
</IPDContext.Provider>
);
expect(getPatientVitals).toHaveBeenCalledWith(
"123",
mockConfig.vitalsConfig.latestVitalsConceptValues
);
});

it("displays loading skeleton while fetching data", () => {
getPatientVitals.mockResolvedValueOnce(mockVitalsData);
render(<Vitals patientId="123" />);
render(
<IPDContext.Provider value={{ config: mockConfig }}>
<Vitals patientId="123" />
</IPDContext.Provider>
);
expect(screen.getByTestId("header-loading")).toBeTruthy();
});
});
Loading
Loading