-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A-1205516692048401 | To add Allergies display control in new IPD dash…
…board (#21) * Abinaya|Tanya add. allergies dislay cntrl Co-authored-by: Tanya-tw <[email protected]> * Abinaya|Tanya add. styles adn test for allergies display cntrl Co-authored-by: Tanya-tw <[email protected]> * Abinaya|Tanya add. datatable-skeleton on loading * Abinaya|Tanya refactor. updated allergy display controls with early returns * [Tanya|Abinaya] add allergies under display control and refactor the names and severity * [Tanya|Abinaya] remove allergies display control from entries and update no allergen message * Update webpack.config.js * [Tanya|Abinaya] add updated snapshot * [Tanya|Abinaya] add. test case for no allergen message * [Tanya|Abinaya] update file structure for allergies component * [Tanya|Abinaya] add updated snapshot --------- Co-authored-by: Abinaya U <[email protected]>
- Loading branch information
Showing
14 changed files
with
589 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
src/features/DisplayControls/Allergies/components/Allergies.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { | ||
DataTable, | ||
DataTableSkeleton, | ||
Table, | ||
TableBody, | ||
TableCell, | ||
TableHead, | ||
TableHeader, | ||
TableRow, | ||
} from "carbon-components-react"; | ||
import React, { useEffect, useState } from "react"; | ||
import { useFetchAllergiesIntolerance } from "../hooks/useFetchAllergiesIntolerance"; | ||
import PropTypes from "prop-types"; | ||
import "../styles/Allergies.scss"; | ||
import { FormattedMessage } from "react-intl"; | ||
|
||
const Allergies = (props) => { | ||
const { patientId } = props; | ||
|
||
const { allergiesData, isLoading } = useFetchAllergiesIntolerance(patientId); | ||
const [rows, setRows] = useState([]); | ||
const NoAllergenMessage = ( | ||
<FormattedMessage | ||
id={"NO_ALLERGENS_MESSAGE"} | ||
defaultMessage={"No Allergen is captured for this patient yet."} | ||
/> | ||
); | ||
|
||
useEffect(() => { | ||
if (allergiesData && allergiesData.entry) { | ||
const allergies = []; | ||
allergiesData.entry?.map((allergy) => { | ||
allergies.push({ | ||
allergen: allergy.resource.code.coding[0].display, | ||
id: allergy.resource.id, | ||
severity: getSeverity(allergy.resource.criticality), | ||
reaction: getAllergyReactions(allergy.resource.reaction), | ||
comments: getComments(allergy.resource.note), | ||
sortWeight: getSortingWait(getSeverity(allergy.resource.criticality)), | ||
}); | ||
}); | ||
setRows(sortedRow(allergies)); | ||
} | ||
}, [allergiesData]); | ||
|
||
const getSortingWait = (severity) => { | ||
if (severity === "Severe") return -1; | ||
if (severity === "Moderate") return 0; | ||
return 1; | ||
}; | ||
|
||
const getSeverity = (criticality) => { | ||
if (criticality == "unable-to-assess") return "Moderate"; | ||
else if (criticality == "high") return "Severe"; | ||
else return "Mild"; | ||
}; | ||
|
||
const getComments = (notes) => | ||
notes && notes.length > 0 ? notes[0].text : ""; | ||
|
||
const getAllergyReactions = (reactions) => { | ||
let allergyReactions = ""; | ||
if (reactions && reactions.length > 0) { | ||
reactions[0].manifestation.map((reaction) => { | ||
allergyReactions = | ||
allergyReactions != "" | ||
? `${allergyReactions}, ${reaction.coding[0].display}` | ||
: `${reaction.coding[0].display}`; | ||
}); | ||
} | ||
return allergyReactions; | ||
}; | ||
|
||
const headers = [ | ||
{ | ||
key: "allergen", | ||
header: "Allergen", | ||
}, | ||
{ | ||
key: "severity", | ||
header: "Severity", | ||
}, | ||
{ | ||
key: "reaction", | ||
header: "Reaction", | ||
}, | ||
{ | ||
key: "comments", | ||
header: "Comments", | ||
}, | ||
]; | ||
|
||
const sortedRow = (rows) => { | ||
const sortedRows = rows | ||
.sort((a, b) => { | ||
if (a === b) return 0; | ||
return a.allergen > b.allergen ? 1 : -1; | ||
}) | ||
.sort((a, b) => a.sortWeight - b.sortWeight); | ||
return sortedRows; | ||
}; | ||
|
||
if (isLoading) | ||
return ( | ||
<DataTableSkeleton | ||
data-testid="datatable-skeleton" | ||
headers={headers} | ||
aria-label="sample table" | ||
zebra="true" | ||
/> | ||
); | ||
|
||
return allergiesData.entry === undefined ? ( | ||
<div className="no-allergen-message"> {NoAllergenMessage} </div> | ||
) : ( | ||
<DataTable | ||
rows={rows} | ||
headers={headers} | ||
useZebraStyles={true} | ||
data-testid="datatable" | ||
> | ||
{({ rows, headers, getTableProps, getHeaderProps, getRowProps }) => ( | ||
<Table {...getTableProps()} useZebraStyles> | ||
<TableHead> | ||
<TableRow> | ||
{headers.map((header, index) => ( | ||
<TableHeader | ||
key={index + header.key} | ||
{...getHeaderProps({ header })} | ||
isSortable={header.key === "severity"} | ||
> | ||
{header.header} | ||
</TableHeader> | ||
))} | ||
</TableRow> | ||
</TableHead> | ||
<TableBody> | ||
{rows.map((row, index) => ( | ||
<TableRow | ||
key={index + row.id} | ||
{...getRowProps({ row })} | ||
data-testid="table-body-row" | ||
> | ||
{row.cells.map((cell) => ( | ||
<TableCell | ||
key={cell.id} | ||
className={ | ||
cell.id.includes("severity") && cell.value == "Severe" | ||
? "high-severity-color" | ||
: "" | ||
} | ||
> | ||
{cell.value} | ||
</TableCell> | ||
))} | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
)} | ||
</DataTable> | ||
); | ||
}; | ||
|
||
Allergies.propTypes = { | ||
patientId: PropTypes.string.isRequired, | ||
}; | ||
|
||
export default Allergies; |
87 changes: 87 additions & 0 deletions
87
src/features/DisplayControls/Allergies/components/Allergies.spec.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { render, waitFor, screen } from "@testing-library/react"; | ||
import axios from "axios"; | ||
import React from "react"; | ||
import { mockAllergiesIntolerenceResponse } from "./AllergiesTestUtils"; | ||
import Allergies from "./Allergies"; | ||
import "@testing-library/jest-dom/extend-expect"; | ||
|
||
jest.mock("axios"); | ||
describe("Allergies", () => { | ||
it("should render Allergies", () => { | ||
axios.get.mockResolvedValue(mockAllergiesIntolerenceResponse); | ||
render(<Allergies patientId={"__test_patient_uuid__"} />); | ||
expect(screen.getByText("Allergen")).toBeInTheDocument(); | ||
}); | ||
|
||
it("should show data in the table", async () => { | ||
axios.get.mockResolvedValue(mockAllergiesIntolerenceResponse); | ||
render(<Allergies patientId={"__test_patient_uuid__"} />); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId(/datatable/i)).toBeInTheDocument(); | ||
}); | ||
expect(screen.getByText("Beef")).toBeInTheDocument(); | ||
expect(screen.getByText(/test comment/i)).toBeInTheDocument(); | ||
}); | ||
|
||
it("should highlight severity column when the value is high", async () => { | ||
axios.get.mockResolvedValue(mockAllergiesIntolerenceResponse); | ||
render(<Allergies patientId={"__test_patient_uuid__"} />); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId(/datatable/i)).toBeInTheDocument(); | ||
}); | ||
expect(screen.getAllByRole("cell", { name: /severe/i })[0]).toHaveClass( | ||
"high-severity-color" | ||
); | ||
expect(screen.getAllByRole("cell", { name: /mild/i })[0]).not.toHaveClass( | ||
"high-severity-color" | ||
); | ||
}); | ||
|
||
it("should sort Allergen in ASC order based on severity", async () => { | ||
axios.get.mockResolvedValue(mockAllergiesIntolerenceResponse); | ||
render(<Allergies patientId={"__test_patient_uuid__"} />); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId(/datatable/i)).toBeInTheDocument(); | ||
}); | ||
|
||
expect(screen.getAllByTestId("table-body-row")[0]).toHaveTextContent( | ||
"Beef" | ||
); | ||
expect(screen.getAllByTestId("table-body-row")[0]).toHaveTextContent( | ||
"Severe" | ||
); | ||
expect(screen.getAllByTestId("table-body-row")[1]).toHaveTextContent( | ||
"Milk product" | ||
); | ||
expect(screen.getAllByTestId("table-body-row")[1]).toHaveTextContent( | ||
"Severe" | ||
); | ||
}); | ||
|
||
it("should show table skeleton on loading", async () => { | ||
axios.get.mockResolvedValue(mockAllergiesIntolerenceResponse); | ||
render(<Allergies patientId={"__test_patient_uuid__"} />); | ||
|
||
expect(screen.getByTestId("datatable-skeleton")).toBeInTheDocument(); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId(/datatable/i)).toBeInTheDocument(); | ||
}); | ||
|
||
expect(screen.queryByTestId("datatable-skeleton")).not.toBeInTheDocument(); | ||
}); | ||
|
||
it("should show no data message when there is no data", async () => { | ||
axios.get.mockResolvedValue({ data: { entry: undefined } }); | ||
render(<Allergies patientId={"__test_patient_uuid__"} />); | ||
|
||
await waitFor(() => { | ||
expect( | ||
screen.getByText(/No Allergen is captured for this patient yet/i) | ||
).toBeInTheDocument(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.