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

Add Medicine Prescription Log Summary Section #7584

Merged
merged 16 commits into from
May 28, 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
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ConsultationTabProps } from "./index";
import PageTitle from "../../Common/PageHeadTitle";
import MedicineAdministrationSheet from "../../Medicine/MedicineAdministrationSheet";
import { MedicinePrescriptionSummary } from "../../Medicine/MedicinePrescriptionSummary";

export const ConsultationMedicinesTab = (props: ConsultationTabProps) => {
return (
Expand All @@ -15,6 +16,7 @@ export const ConsultationMedicinesTab = (props: ConsultationTabProps) => {
is_prn={true}
readonly={!!props.consultationData.discharge_date}
/>
<MedicinePrescriptionSummary consultation={props.consultationId} />
</div>
);
};
372 changes: 372 additions & 0 deletions src/Components/Medicine/MedicinePrescriptionSummary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,372 @@
import MedicineRoutes from "../Medicine/routes";
import useQuery from "../../Utils/request/useQuery";
import DialogModal from "../Common/Dialog";
import { useState } from "react";
import { lazy } from "react";
import Timeline, { TimelineNode } from "../../CAREUI/display/Timeline";
import { MedibaseMedicine, Prescription } from "../Medicine/models";
import { useTranslation } from "react-i18next";

const Loading = lazy(() => import("../Common/Loading"));

interface MedicinePrescriptionSummaryProps {
consultation: string;
}

export const MedicinePrescriptionSummary = ({
consultation,
}: MedicinePrescriptionSummaryProps) => {
const { t } = useTranslation();
const [showMedicineModal, setShowMedicineModal] = useState({
open: false,
name: "",
medicineId: "",
});
const { data } = useQuery(MedicineRoutes.listPrescriptions, {
pathParams: { consultation },
query: { limit: 100 },
});

const closeMedicineModal = () => {
setShowMedicineModal({ ...showMedicineModal, open: false });
};

function extractUniqueMedicineObjects(
prescriptions: Prescription[],
): MedibaseMedicine[] {
const uniqueMedicineObjects: Set<string> = new Set();
const uniqueMedicines: MedibaseMedicine[] = [];

prescriptions.forEach((prescription: Prescription) => {
if (prescription?.medicine_object) {
const medicineId = prescription?.medicine_object.id;

if (!uniqueMedicineObjects.has(medicineId)) {
uniqueMedicineObjects.add(medicineId);
uniqueMedicines.push(prescription?.medicine_object);
}
}
});

return uniqueMedicines;
}

const medicinesList: MedibaseMedicine[] = extractUniqueMedicineObjects(
data?.results ?? [],
);

return (
<div className="pt-6">
<p className="text-xl font-bold text-gray-700">{t("summary")}</p>
<div className="flex flex-col gap-2 pt-4">
{medicinesList && medicinesList.length > 0 ? (
medicinesList?.map((med: MedibaseMedicine) => (
<div
key={med.id}
className="flex cursor-pointer items-center justify-between rounded-lg border bg-white p-4 shadow hover:bg-gray-200"
>
<div>{med.name}</div>
<button
onClick={() =>
setShowMedicineModal({
open: true,
name: med.name,
medicineId: med.id,
})
}
className="btn btn-default"
>
View
</button>
</div>
))
) : (
<div className="rounded-lg border shadow">
<div className="my-16 flex w-full flex-col items-center justify-center gap-4 text-gray-500">
<h3 className="text-lg font-medium">{"No Medicine Summary"}</h3>
</div>
</div>
)}
</div>

<DialogModal
title={
<p>
{showMedicineModal.name}: {t("prescription_logs")}
</p>
}
show={showMedicineModal.open}
onClose={closeMedicineModal}
fixedWidth={false}
className="md:w-3/4"
>
<ConsultationMedicineLogs
consultationId={consultation}
medicineId={showMedicineModal.medicineId}
/>
</DialogModal>
</div>
);
};

interface ConsultationMedicineLogsProps {
consultationId: string;
medicineId: string;
}

export default function ConsultationMedicineLogs({
consultationId,
medicineId,
}: ConsultationMedicineLogsProps) {
const { data, loading } = useQuery(MedicineRoutes.listPrescriptions, {
pathParams: { consultation: consultationId },
query: {
medicine: medicineId,
},
});

if (loading) {
return <Loading />;
}

const getDetailsMessage = (prescription: Prescription) => {
const message = `Details: ${
prescription.base_dosage != null
? `${prescription.dosage_type === "TITRATED" ? "Start Dosage" : "Dosage"}: ${prescription.base_dosage}, `
: ""
}${prescription.route != null ? `Route: ${prescription.route}, ` : ""}${
prescription.target_dosage != null
? `Target Dosage: ${prescription.target_dosage}, `
: ""
}${
prescription.instruction_on_titration != null
? `Instruction on Titration: ${prescription.instruction_on_titration}, `
: ""
}${
prescription.frequency != null
? `Frequency: ${prescription.frequency}, `
: ""
}${prescription.days != null ? `Days: ${prescription.days}, ` : ""}${
prescription.indicator != null
? `Indicator: ${prescription.indicator}, `
: ""
}${
prescription.max_dosage != null
? `Max Dosage: ${prescription.max_dosage}, `
: ""
}${
prescription.min_hours_between_doses != null
? `Min Hours Between Doses: ${prescription.min_hours_between_doses}, `
: ""
}${prescription.discontinued ? "Discontinued: Yes, " : ""}${
prescription.dosage_type
? `Prescription Type: ${prescription.dosage_type}, `
: ""
}`.replace(/, $/, "");

return message;
};

const calculateChanges = (prescriptions: Prescription[]) => {
prescriptions = prescriptions.reverse();
const changes = [];

const message = getDetailsMessage(prescriptions[0]);

changes.push({
prescriptionId: prescriptions[0].id,
changeMessage: message,
prescribed_by: prescriptions[0].prescribed_by,
created_date: prescriptions[0].created_date,
});

if (prescriptions[0].discontinued) {
changes.push({
prescriptionId: prescriptions[0].id,
changeMessage: "This prescription has been discontinued",
prescribed_by: prescriptions[0].prescribed_by,
created_date: prescriptions[0].discontinued_date,
});
}

for (let i = 1; i < prescriptions.length; i++) {
const prevPrescription = prescriptions[i - 1];
const currentPrescription = prescriptions[i];

const changesForPrescription: string[] = [];

// Check for changes in base dosage
if (prevPrescription.base_dosage !== currentPrescription.base_dosage) {
changesForPrescription.push(
`Base dosage changed to ${currentPrescription.base_dosage} from ${prevPrescription.base_dosage}`,
);
}

// Check for changes in route
if (prevPrescription.route !== currentPrescription.route) {
changesForPrescription.push(
`Route changed to ${
currentPrescription.route ?? "Not specified"
} from ${prevPrescription.route ?? "Not specified"}`,
);
}

// Check for changes in dosage type
if (prevPrescription.dosage_type !== currentPrescription.dosage_type) {
changesForPrescription.push(
`Dosage type changed to ${
currentPrescription.dosage_type ?? "Not specified"
} from ${prevPrescription.dosage_type ?? "Not specified"}`,
);
}

// Check for changes in target dosage
if (
prevPrescription.target_dosage !== currentPrescription.target_dosage
) {
changesForPrescription.push(
`Target dosage changed to ${
currentPrescription.target_dosage ?? "Not specified"
} from ${prevPrescription.target_dosage ?? "Not specified"}`,
);
}

// Check for changes in instruction on titration
if (
prevPrescription.instruction_on_titration !==
currentPrescription.instruction_on_titration
) {
changesForPrescription.push(
`Instruction on titration changed to ${
currentPrescription.instruction_on_titration ?? "Not specified"
} from ${
prevPrescription.instruction_on_titration ?? "Not specified"
}`,
);
}

// Check for changes in frequency
if (prevPrescription.frequency !== currentPrescription.frequency) {
changesForPrescription.push(
`Frequency changed to ${
currentPrescription.frequency ?? "Not specified"
} from ${prevPrescription.frequency ?? "Not specified"}`,
);
}

// Check for changes in days
if (prevPrescription.days !== currentPrescription.days) {
changesForPrescription.push(
`Days changed to ${
currentPrescription.days ?? "Not specified"
} from ${prevPrescription.days ?? "Not specified"}`,
);
}

// Check for changes in indicator
if (prevPrescription.indicator !== currentPrescription.indicator) {
changesForPrescription.push(
`Indicator changed to ${
currentPrescription.indicator ?? "Not specified"
} from ${prevPrescription.indicator ?? "Not specified"}`,
);
}

// Check for changes in max dosage
if (prevPrescription.max_dosage !== currentPrescription.max_dosage) {
changesForPrescription.push(
`Max dosage changed to ${
currentPrescription.max_dosage ?? "Not specified"
} from ${prevPrescription.max_dosage ?? "Not specified"}`,
);
}

// Check for changes in min hours between doses
if (
prevPrescription.min_hours_between_doses !==
currentPrescription.min_hours_between_doses
) {
changesForPrescription.push(
`Min hours between doses changed to ${
currentPrescription.min_hours_between_doses ?? "Not specified"
} from ${prevPrescription.min_hours_between_doses ?? "Not specified"}`,
);
}

// Check if discontinued
if (currentPrescription.discontinued && !prevPrescription.discontinued) {
changesForPrescription.push("Prescription was discontinued");
}

// Check if prescription type is changed
if (
prevPrescription.prescription_type !==
currentPrescription.prescription_type
) {
changesForPrescription.push(
`Prescription Type changed from ${prevPrescription.prescription_type} to ${currentPrescription.prescription_type}`,
);
}

// If there are changes, add them to the changes array
if (changesForPrescription.length > 0 && !prevPrescription.discontinued) {
const message = `Changes: ${changesForPrescription.join(", ")}`;
changes.push({
prescriptionId: currentPrescription.id,
changeMessage: message,
prescribed_by: currentPrescription.prescribed_by,
created_date: currentPrescription.created_date,
});
} else {
// If no changes, just list out the details of the prescription
const message = getDetailsMessage(currentPrescription);

changes.push({
prescriptionId: currentPrescription.id,
changeMessage: message,
prescribed_by: currentPrescription.prescribed_by,
created_date: currentPrescription.created_date,
});
}

if (currentPrescription.discontinued) {
changes.push({
prescriptionId: currentPrescription.id,
changeMessage: "This prescription has been discontinued",
prescribed_by: currentPrescription.prescribed_by,
created_date: currentPrescription.discontinued_date,
});
}
}

return changes.reverse();
};

return (
<div>
<Timeline
className="rounded-lg bg-white p-2 shadow"
name={data?.results[0].medicine_object?.name ?? ""}
>
{data?.results &&
(() => {
const changesArray = calculateChanges(data?.results);
return changesArray.map((changes, index) => (
<TimelineNode
key={changes.prescriptionId}
event={{
type: "prescribed",
timestamp: changes.created_date,
by: changes.prescribed_by,
icon: "l-syringe",
}}
isLast={index === changesArray.length - 1}
>
<p>{changes?.changeMessage}</p>
</TimelineNode>
));
})()}
</Timeline>
</div>
);
}
1 change: 1 addition & 0 deletions src/Locale/en/Medicine.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"prescription_discontinued": "Prescription discontinued",
"administration_notes": "Administration Notes",
"last_administered": "Last administered",
"prescription_logs": "Prescription Logs",
"modification_caution_note": "No modifications possible once added",
"discontinue_caution_note": "Are you sure you want to discontinue this prescription?",
"edit_caution_note": "A new prescription will be added to the consultation with the edited details and the current prescription will be discontinued.",
Expand Down
Loading