diff --git a/package.json b/package.json
index ca213c58..6aac82ca 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
"carbon-components-react": "^7.25.0",
"carbon-icons": "^7.0.7",
"moment": "^2.29.4",
+ "prop-types": "^15.8.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-intl": "^3.3.2",
diff --git a/public/i18n/locale_en.json b/public/i18n/locale_en.json
index bec45b33..e847e80c 100644
--- a/public/i18n/locale_en.json
+++ b/public/i18n/locale_en.json
@@ -11,5 +11,11 @@
"DRUG_CHART_MODAL_SCHEDULE_ORDER_WARNING": "Times entered should be in ascending order",
"DRUG_CHART_MODAL_EMPTY_SCHEDULE_WARNING": "Please enter Schedule(s)",
"DRUG_CHART_MODAL_EMPTY_START_TIME_WARNING": "Please enter Start Time",
- "DRUG_CHART_MODAL_START_TIME_BEYOND_NEXT_DOSE": "Start Time does not match with the frequency"
+ "DRUG_CHART_MODAL_START_TIME_BEYOND_NEXT_DOSE": "Start Time does not match with the frequency",
+ "ADMINISTERED_LATE": "Administered Late",
+ "NOT_ADMINISTERED": "Not Administered",
+ "LATE": "Late",
+ "ADMINISTERED": "Administered",
+ "PENDING": "Pending",
+ "NOTE": "Note"
}
diff --git a/src/features/Calendar/Calendar.scss b/src/features/Calendar/Calendar.scss
index 54dbfe30..7e61aab2 100644
--- a/src/features/Calendar/Calendar.scss
+++ b/src/features/Calendar/Calendar.scss
@@ -2,7 +2,12 @@
width: max-content;
border-spacing: 0;
margin: 0;
- tbody > tr:nth-child(even) {
- background-color: #f4f4f4;
+ tbody {
+ tr {
+ border-bottom: 0;
+ &:nth-child(even) {
+ background-color: #f4f4f4;
+ }
+ }
}
}
diff --git a/src/features/CalendarHeader/CalendarHeader.scss b/src/features/CalendarHeader/CalendarHeader.scss
index 872e686d..3908af25 100644
--- a/src/features/CalendarHeader/CalendarHeader.scss
+++ b/src/features/CalendarHeader/CalendarHeader.scss
@@ -22,6 +22,7 @@
padding-bottom: 8px;
display: grid;
align-items: end;
+ box-sizing: border-box;
&:last-child {
--additional-borders: 1;
diff --git a/src/features/DrugChart/DrugChart.jsx b/src/features/DrugChart/DrugChart.jsx
index dcb9c236..11ec1131 100644
--- a/src/features/DrugChart/DrugChart.jsx
+++ b/src/features/DrugChart/DrugChart.jsx
@@ -4,24 +4,40 @@ import moment from "moment";
import Calendar from "../Calendar/Calendar";
import CalendarHeader from "../CalendarHeader/CalendarHeader";
import "./DrugChart.scss";
+import DrugList from "../DrugList/DrugList";
+import DrugChartLegend from "../DrugChartLegend/DrugChartLegend";
export const TransformDrugChartData = (drugChartData) => {
+ const drugOrderData = [];
const transformedDrugChartData = drugChartData.map((schedule) => {
- const { slots } = schedule;
+ const { slots, order } = schedule;
const slotData = {};
+ const drugOrder = {
+ drugName: order.drug.display,
+ drugRoute: order.route.display,
+ administrationInfo: [],
+ };
+ if (order.duration) {
+ drugOrder.duration = order.duration + " " + order.durationUnits.display;
+ }
+ if (order.doseUnits.display !== "ml") {
+ drugOrder.dosage = order.dose;
+ drugOrder.doseType = order.doseUnits.display;
+ } else {
+ drugOrder.dosage = order.dose + order.doseUnits.display;
+ }
+ if (order.duration) {
+ drugOrder.duration = order.duration + " " + order.durationUnits.display;
+ }
slots.forEach((slot) => {
const { startDateTime, status } = slot;
const startDateTimeObj = new Date(startDateTime);
- let adminInfo;
+ let adminInfo, administeredTime;
if (slot.admin) {
const { administeredBy, administeredAt } = slot.admin;
- const administeredTime = moment(new Date(administeredAt)).format(
- "HH:mm"
- );
-
+ administeredTime = moment(new Date(administeredAt)).format("HH:mm");
adminInfo = administeredBy + " [" + administeredTime + "]";
}
-
const startHour = startDateTimeObj.getHours();
const startMinutes = startDateTimeObj.getMinutes();
slotData[startHour] = {
@@ -29,10 +45,17 @@ export const TransformDrugChartData = (drugChartData) => {
status: status,
administrationInfo: adminInfo,
};
+ if (status === "Administered" || status === "Administered-Late") {
+ drugOrder.administrationInfo.push({
+ kind: status,
+ time: administeredTime,
+ });
+ }
});
+ drugOrderData.push(drugOrder);
return slotData;
});
- return transformedDrugChartData;
+ return [transformedDrugChartData, drugOrderData];
};
export default function DrugChart(props) {
@@ -49,6 +72,25 @@ export default function DrugChart(props) {
comment: "some comment",
startDate: "2023-08-08T18:30:00.000Z",
endDate: "2023-08-08T18:30:00.000Z",
+ order: {
+ drug: {
+ display: "Paracetamol 120 mg/5 mL Suspension (Liquid)",
+ },
+ route: {
+ uuid: "9d6bc13f-3f10-11e4-adec-0800271c1b75",
+ display: "Oral",
+ },
+ dose: 25,
+ doseUnits: {
+ uuid: "86239663-7b04-4563-b877-d7efc4fe6c46",
+ display: "ml",
+ },
+ duration: 3,
+ durationUnits: {
+ uuid: "9d7437a9-3f10-11e4-adec-0800271c1b75",
+ display: "Day(s)",
+ },
+ },
slots: [
{
id: 1,
@@ -71,7 +113,7 @@ export default function DrugChart(props) {
notes: "some slot text",
admin: {
administeredBy: "Dr. John Doe",
- administeredAt: "2023-08-08T08:30:00.000Z",
+ administeredAt: "2023-08-08T11:35:00.000Z",
adminid: "1234",
},
},
@@ -95,6 +137,20 @@ export default function DrugChart(props) {
comment: "some comment",
scheduleStartDate: "2023-08-08T18:30:00.000Z",
scheduleEndDate: "2023-08-08T18:30:00.000Z",
+ order: {
+ drug: {
+ display: "Ibuprofen 400 mg Tablet",
+ },
+ route: {
+ uuid: "9d6bc13f-3f10-11e4-adec-0800271c1b75",
+ display: "Oral",
+ },
+ dose: 4,
+ doseUnits: {
+ uuid: "86239663-7b04-4563-b877-d7efc4fe6c46",
+ display: "Tablet(s)",
+ },
+ },
slots: [
{
id: 3,
@@ -107,7 +163,7 @@ export default function DrugChart(props) {
notes: "some slot text",
admin: {
administeredBy: "Dr. John Doe",
- administeredAt: "2023-08-08T08:30:00.000Z",
+ administeredAt: "2023-08-08T08:45:00.000Z",
adminid: "1234",
},
},
@@ -136,6 +192,25 @@ export default function DrugChart(props) {
comment: "some comment",
scheduleStartDate: "2023-08-08T18:30:00.000Z",
scheduleEndDate: "2023-08-08T18:30:00.000Z",
+ order: {
+ drug: {
+ display: "Amoxicillin/Clavulanic Acid 1000 mg Tablet (Tablet)",
+ },
+ route: {
+ uuid: "9d6bc13f-3f10-11e4-adec-0800271c1b75",
+ display: "Oral",
+ },
+ dose: "4",
+ doseUnits: {
+ uuid: "86239663-7b04-4563-b877-d7efc4fe6c46",
+ display: "Tablet(s)",
+ },
+ duration: 2,
+ durationUnits: {
+ uuid: "9d7437a9-3f10-11e4-adec-0800271c1b75",
+ display: "Day(s)",
+ },
+ },
slots: [
{
id: 3,
@@ -172,16 +247,45 @@ export default function DrugChart(props) {
comment: "some comment",
startDate: "2023-08-08T18:30:00.000Z",
endDate: "2023-08-08T18:30:00.000Z",
+ order: {
+ drug: {
+ display: "Isoflurane 250 mL Inhalation Anesthetic Liquid (Liquid)",
+ },
+ route: {
+ uuid: "9d6bc13f-3f10-11e4-adec-0800271c1b75",
+ display: "Oral",
+ },
+ dose: 30,
+ doseUnits: {
+ uuid: "86239663-7b04-4563-b877-d7efc4fe6c46",
+ display: "ml",
+ },
+ duration: 4,
+ durationUnits: {
+ uuid: "9d7437a9-3f10-11e4-adec-0800271c1b75",
+ display: "Day(s)",
+ },
+ },
+ dose: 2,
+ doseUnits: {
+ uuid: "86239663-7b04-4563-b877-d7efc4fe6c46",
+ display: "Tablet(s)",
+ },
slots: [
{
id: 1,
uuid: "738aa77d-03fc-438f-a87a-ae8a8867c421",
orderId: 13,
serviceType: "Medication Administration",
- status: "Not-Administered",
+ status: "Administered-Late",
startDateTime: "2023-08-08T10:45:00.000Z",
endDateTime: "2023-08-08T09:30:00.000Z",
notes: "some slot text",
+ admin: {
+ administeredBy: "Dr. John Doe",
+ administeredAt: "2023-08-08T10:50:00.000Z",
+ adminid: "1234",
+ },
},
{
id: 2,
@@ -212,14 +316,19 @@ export default function DrugChart(props) {
},
];
const transformedDrugchartData = TransformDrugChartData(drugChartData);
-
return (
-
-
-
-
-
+
);
}
diff --git a/src/features/DrugChart/DrugChart.scss b/src/features/DrugChart/DrugChart.scss
index d94e6fe0..5e2d67f9 100644
--- a/src/features/DrugChart/DrugChart.scss
+++ b/src/features/DrugChart/DrugChart.scss
@@ -1,3 +1,6 @@
+.drug-chart-dashboard {
+ font-family: "IBM Plex Sans", sans-serif;
+}
.drug-chart {
--time-cell-height: 66px;
--half-hour-width: 21px;
@@ -15,6 +18,34 @@
.drug-chart-left-panel {
border-right: 1px solid #ccc;
+ font-size: 13px;
+ overflow-y: auto;
+ height: 100%;
+ min-width: 225px;
+ .header {
+ height: 63px;
+ background-color: #ededed;
+ position: sticky;
+ top: 0;
+ }
+ table {
+ table-layout: fixed;
+ border-spacing: 0;
+ width: 100%;
+ tbody > tr:nth-child(even) {
+ background-color: #f4f4f4;
+ }
+ tr {
+ height: 66px;
+ border-bottom: 0;
+ td {
+ line-height: 20px;
+ padding: 0 10px;
+ max-width: 100%;
+ border: 0;
+ }
+ }
+ }
}
.drug-chart-content {
diff --git a/src/features/DrugChart/DrugChart.spec.jsx b/src/features/DrugChart/DrugChart.spec.jsx
index 11b54bc0..af760deb 100644
--- a/src/features/DrugChart/DrugChart.spec.jsx
+++ b/src/features/DrugChart/DrugChart.spec.jsx
@@ -25,6 +25,25 @@ const drugChartData = [
comment: "some comment",
startDate: "2023-08-08T18:30:00.000Z",
endDate: "2023-08-08T18:30:00.000Z",
+ order: {
+ drug: {
+ display: "Paracetamol 120 mg/5 mL Suspension (Liquid)",
+ },
+ route: {
+ uuid: "9d6bc13f-3f10-11e4-adec-0800271c1b75",
+ display: "Oral",
+ },
+ dose: 25,
+ doseUnits: {
+ uuid: "86239663-7b04-4563-b877-d7efc4fe6c46",
+ display: "ml",
+ },
+ duration: 3,
+ durationUnits: {
+ uuid: "9d7437a9-3f10-11e4-adec-0800271c1b75",
+ display: "Day(s)",
+ },
+ },
slots: [
{
id: 1,
@@ -85,23 +104,39 @@ describe("TransformDrugChartData", () => {
it("should transform drug chart data", () => {
const TransformedDrugChartData = TransformDrugChartData(drugChartData);
expect(TransformedDrugChartData).toEqual([
- {
- 11: {
- administrationInfo: "Dr. John Doe [11:40]",
- minutes: 30,
- status: "Administered",
- },
- 15: {
- administrationInfo: "Dr. John Doe [15:30]",
- minutes: 30,
- status: "Pending",
+ [
+ {
+ 11: {
+ administrationInfo: "Dr. John Doe [11:40]",
+ minutes: 30,
+ status: "Administered",
+ },
+ 15: {
+ administrationInfo: "Dr. John Doe [15:30]",
+ minutes: 30,
+ status: "Pending",
+ },
+ 8: {
+ administrationInfo: "Dr. John Doe [08:30]",
+ minutes: 30,
+ status: "Not-Administered",
+ },
},
- 8: {
- administrationInfo: "Dr. John Doe [08:30]",
- minutes: 30,
- status: "Not-Administered",
+ ],
+ [
+ {
+ administrationInfo: [
+ {
+ kind: "Administered",
+ time: "11:40",
+ },
+ ],
+ dosage: "25ml",
+ drugName: "Paracetamol 120 mg/5 mL Suspension (Liquid)",
+ drugRoute: "Oral",
+ duration: "3 Day(s)",
},
- },
+ ],
]);
});
});
diff --git a/src/features/DrugChart/__snapshots__/DrugChart.spec.jsx.snap b/src/features/DrugChart/__snapshots__/DrugChart.spec.jsx.snap
index 81703243..954b4f71 100644
--- a/src/features/DrugChart/__snapshots__/DrugChart.spec.jsx.snap
+++ b/src/features/DrugChart/__snapshots__/DrugChart.spec.jsx.snap
@@ -3,19 +3,200 @@
exports[`DrugChart should match snapshot 1`] = `
+ class="drug-chart"
+ >
+
+
+
+
+
+
+
+
+ Paracetamol 120 mg/5 mL Suspension (Liquid)
+
+
+
+ 25ml
+
+
+ - Oral
+
+
+ - 3 Day(s)
+
+
+
+
+
+ 11:35
+
+
+ |
+
+
+
+
+ Ibuprofen 400 mg Tablet
+
+
+
+ 4
+
+
+ - Tablet(s)
+
+
+ - Oral
+
+
+
+
+
+ 08:45
+
+
+ |
+
+
+
+
+ Amoxicillin/Clavulanic Acid 1000 mg Tablet (Tablet)
+
+
+
+ 4
+
+
+ - Tablet(s)
+
+
+ - Oral
+
+
+ - 2 Day(s)
+
+
+
+
+
+ 06:30
+
+
+ |
+
+
+
+
+ Isoflurane 250 mL Inhalation Anesthetic Liquid (Liquid)
+
+
+
+ 30ml
+
+
+ - Oral
+
+
+ - 4 Day(s)
+
+
+
+
+
+ 10:50
+
+ ,
+
+
+
+ 13:40
+
+
+ |
+
+
+
+
+
+
+
+ CalendarHeader
+
+
+ Calendar
+
+
+
- CalendarHeader
+
+ Administered
+
+
+
+ Not Administered
+
+
+
+ Late
+
+
+
+ Administered Late
- Calendar
+
+ Pending
diff --git a/src/features/DrugChartLegend/DrugChartLegend.jsx b/src/features/DrugChartLegend/DrugChartLegend.jsx
new file mode 100644
index 00000000..69a45455
--- /dev/null
+++ b/src/features/DrugChartLegend/DrugChartLegend.jsx
@@ -0,0 +1,41 @@
+import React from "react";
+import AdministeredIcon from "../../icons/administered.svg";
+import AdministeredLateIcon from "../../icons/administered-late.svg";
+import LateIcon from "../../icons/late.svg";
+import NotAdministeredIcon from "../../icons/not-administered.svg";
+import PendingIcon from "../../icons/pending.svg";
+import "./DrugChartLegend.scss";
+import { FormattedMessage } from "react-intl";
+
+export default function DrugChartLegend() {
+ return (
+
+ );
+}
diff --git a/src/features/DrugChartLegend/DrugChartLegend.scss b/src/features/DrugChartLegend/DrugChartLegend.scss
new file mode 100644
index 00000000..6ee96e3c
--- /dev/null
+++ b/src/features/DrugChartLegend/DrugChartLegend.scss
@@ -0,0 +1,12 @@
+.drug-chart-legend {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ padding: 10px;
+ font-size: 12px;
+ > * {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ }
+}
diff --git a/src/features/DrugList/DrugList.jsx b/src/features/DrugList/DrugList.jsx
new file mode 100644
index 00000000..ec2701cd
--- /dev/null
+++ b/src/features/DrugList/DrugList.jsx
@@ -0,0 +1,26 @@
+import React from "react";
+import PropTypes from "prop-types";
+import DrugListCell from "../DrugListCell/DrugListCell.jsx";
+
+export default function DrugList(props) {
+ const { drugDetails } = props;
+ return (
+
+
+
+ {drugDetails.map((drugDetail, index) => {
+ return (
+
+
+
+ );
+ })}
+
+
+
+ );
+}
+
+DrugList.propTypes = {
+ drugDetails: PropTypes.array.isRequired,
+};
diff --git a/src/features/DrugListCell/DrugListCell.jsx b/src/features/DrugListCell/DrugListCell.jsx
new file mode 100644
index 00000000..29c97e4e
--- /dev/null
+++ b/src/features/DrugListCell/DrugListCell.jsx
@@ -0,0 +1,58 @@
+import React from "react";
+import PropTypes from "prop-types";
+import Clock from "../../icons/clock.svg";
+import "./DrugListCell.scss";
+// import { TooltipDefinitionCarbon } from "bahmni-carbon-ui";
+
+export default function DrugListCell(props) {
+ const { drugInfo } = props;
+ const {
+ drugName,
+ dosage,
+ doseType,
+ drugRoute,
+ duration,
+ administrationInfo,
+ } = drugInfo;
+ const drugNameText =
{drugName}
;
+ //TODO: Add tooltip for drug name
+ return (
+
+ {/**/}
+ {drugNameText}
+
+ {dosage}
+ {doseType && - {doseType}}
+ - {drugRoute}
+ {duration && - {duration}}
+
+ {administrationInfo.length >= 1 && (
+
+
+ {administrationInfo.map((adminInfo, index) => {
+ if (adminInfo.kind === "Administered-Late") {
+ return (
+
+ {adminInfo.time}
+ {index !== administrationInfo.length - 1 && (
+ ,
+ )}
+
+ );
+ } else {
+ return (
+
+ {adminInfo.time}
+ {index !== administrationInfo.length - 1 && ,}
+
+ );
+ }
+ })}
+
+ )}
+ |
+ );
+}
+DrugListCell.propTypes = {
+ drugInfo: PropTypes.object.isRequired,
+};
diff --git a/src/features/DrugListCell/DrugListCell.scss b/src/features/DrugListCell/DrugListCell.scss
new file mode 100644
index 00000000..15087bbc
--- /dev/null
+++ b/src/features/DrugListCell/DrugListCell.scss
@@ -0,0 +1,17 @@
+.drug-name {
+ max-width: 85%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-weight: 500;
+ color: #393939;
+ font-style: normal;
+}
+.dosage {
+ font-size: 12px;
+ font-weight: 400;
+ color: #393939;
+ > * {
+ display: inline-block;
+ }
+}
diff --git a/src/icons/clock.svg b/src/icons/clock.svg
new file mode 100644
index 00000000..f0e7a4ac
--- /dev/null
+++ b/src/icons/clock.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index d4b2aaf1..88b3ad7d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4319,10 +4319,10 @@ babel-preset-jest@^29.5.0:
babel-plugin-jest-hoist "^29.5.0"
babel-preset-current-node-syntax "^1.0.0"
-bahmni-carbon-ui@0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/bahmni-carbon-ui/-/bahmni-carbon-ui-0.1.0.tgz#c84cae6109a5cd608a95e3d7c44b702380dd1967"
- integrity sha512-jSE7yKDj4iAI45f2VgpbxfBgFhhDXLmt51I26UpTMpA3dk+S6PMkhkDzCq7o5KLLN17KMKd1q3LSNtEnHKWQAA==
+bahmni-carbon-ui@0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/bahmni-carbon-ui/-/bahmni-carbon-ui-0.1.2.tgz#1fd0282fa7d47ff430f27207404ed7eb92c34bf7"
+ integrity sha512-y3lWKaf3UidWVdBGbSI4ILx6wL+zANb5nzFk31x9i+Tvnf3+qHnJIJXWxXge3jCy4CRa19uoEeWtID1PgJmyfw==
dependencies:
"@storybook/addon-styling" "0.3"
"@storybook/react" "6.5"