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 titrated prescription dosage type #6565

Merged
merged 27 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b269eb6
feat: option to add titrated drug dose in prescription
GokulramGHV Oct 24, 2023
382550a
Update prescription model and form to use
GokulramGHV Nov 6, 2023
aade406
Merge branch 'develop' into fix-issue-6432
GokulramGHV Nov 8, 2023
3391b1e
Merge branch 'develop' into fix-issue-6432
GokulramGHV Nov 8, 2023
ba9cf64
Update edit prescription form
GokulramGHV Nov 10, 2023
2a7ea33
Merge branch 'develop' into fix-issue-6432
GokulramGHV Nov 10, 2023
63662fb
Refactor administration dosage validation
GokulramGHV Nov 10, 2023
5fbdd45
Merge branch 'develop' into fix-issue-6432
rithviknishad Nov 14, 2023
f56e7ca
Merge branch 'develop' into fix-issue-6432
GokulramGHV Nov 16, 2023
09d4574
Fix unit validation in PrescriptionFormValidator
GokulramGHV Nov 20, 2023
53feae0
Merge branch 'develop' into fix-issue-6432
GokulramGHV Nov 20, 2023
35413e7
Add dosage information to TimelineNode
GokulramGHV Nov 28, 2023
91c3549
Merge branch 'develop' into fix-issue-6432
GokulramGHV Nov 28, 2023
72f9bdd
Remove dosage from TimelineNode component
GokulramGHV Nov 30, 2023
e843623
Merge branch 'develop' into fix-issue-6432
nihal467 Dec 5, 2023
bf45eda
fix: renamed cypress dosage field selector to base_dosage
GokulramGHV Dec 9, 2023
6e59bdc
Merge branch 'develop' into fix-issue-6432
GokulramGHV Dec 9, 2023
ca6f5df
Merge branch 'develop' into fix-issue-6432
nihal467 Dec 20, 2023
ef24213
Merge branch 'develop' into fix-issue-6432
GokulramGHV Dec 24, 2023
1e9fefa
Merge branch 'develop' into fix-issue-6432
GokulramGHV Dec 24, 2023
68eee13
Merge branch 'develop' into fix-issue-6432
rithviknishad Jan 18, 2024
0813a64
Merge branch 'develop' into fix-issue-6432
GokulramGHV Jan 19, 2024
ffec206
Merge branch 'develop' into fix-issue-6432
rithviknishad Feb 20, 2024
a93819c
Merge branch 'develop' into fix-issue-6432
rithviknishad Feb 26, 2024
115ff7c
update cypress to match new dosage field's id
rithviknishad Feb 26, 2024
f324144
Merge branch 'develop' into fix-issue-6432
rithviknishad Mar 17, 2024
eb8d4ad
fixed linting issue
khavinshankar Mar 19, 2024
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
2 changes: 1 addition & 1 deletion cypress/pageobject/Patient/PatientPrescription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class PatientPrescription {
}

enterDosage(doseAmount: string) {
cy.get("#dosage").type(doseAmount, { force: true });
cy.get("#base_dosage").type(doseAmount, { force: true });
}

selectDosageFrequency(frequency: string) {
Expand Down
14 changes: 14 additions & 0 deletions src/Components/Form/FormFields/DosageFormField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { DOSAGE_UNITS } from "../../Medicine/models";
import NumericWithUnitsFormField from "./NumericWithUnitsFormField";
import { FormFieldBaseProps } from "./Utils";

type Props = FormFieldBaseProps<string> & {
placeholder?: string;
autoComplete?: string;
min?: string | number;
max?: string | number;
};

export default function DosageFormField(props: Props) {
return <NumericWithUnitsFormField {...props} units={DOSAGE_UNITS} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default function NumericWithUnitsFormField(props: Props) {
autoComplete={props.autoComplete}
required={field.required}
value={numValue}
disabled={props.disabled}
onChange={(e) =>
field.handleChange(Number(e.target.value) + " " + unitValue)
}
Expand All @@ -48,6 +49,7 @@ export default function NumericWithUnitsFormField(props: Props) {
onChange={(e) =>
field.handleChange(numValue + " " + e.target.value)
}
disabled={props.disabled}
>
{props.units.map((unit) => (
<option key={unit}>{unit}</option>
Expand Down
52 changes: 49 additions & 3 deletions src/Components/Medicine/AdministerMedicine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import dayjs from "../../Utils/dayjs";
import useSlug from "../../Common/hooks/useSlug";
import request from "../../Utils/request/request";
import MedicineRoutes from "./routes";
import DosageFormField from "../Form/FormFields/DosageFormField";
import { AdministrationDosageValidator } from "./validators";

interface Props {
prescription: Prescription;
Expand All @@ -24,6 +26,8 @@ export default function AdministerMedicine({ prescription, ...props }: Props) {
const consultation = useSlug("consultation");
const [isLoading, setIsLoading] = useState(false);
const [notes, setNotes] = useState<string>("");
const [dosage, setDosage] = useState<string | undefined>();
const [error, setError] = useState<string>();
const [isCustomTime, setIsCustomTime] = useState(false);
const [customTime, setCustomTime] = useState<string>(
dayjs().format("YYYY-MM-DDTHH:mm")
Expand All @@ -41,21 +45,45 @@ export default function AdministerMedicine({ prescription, ...props }: Props) {
description={
<div className="text-sm font-semibold leading-relaxed text-gray-600">
<CareIcon className="care-l-history-alt pr-1" /> Last administered
<span className="pl-1">
{prescription.last_administered_on
? formatDateTime(prescription.last_administered_on)
<span className="whitespace-nowrap pl-2">
<CareIcon className="care-l-clock" />{" "}
{prescription.last_administration?.administered_date
? formatDateTime(
prescription.last_administration.administered_date
)
: t("never")}
</span>
{prescription.dosage_type === "TITRATED" && (
<span className="whitespace-nowrap pl-2">
<CareIcon className="care-l-syringe" /> {t("dosage")}
{":"} {prescription.last_administration?.dosage ?? "NA"}
</span>
)}
<span className="whitespace-nowrap pl-2">
<CareIcon className="care-l-user" /> Administered by:{" "}
{prescription.last_administration?.administered_by?.username ??
"NA"}
</span>
</div>
}
show
onClose={() => props.onClose(false)}
onConfirm={async () => {
if (prescription.dosage_type === "TITRATED") {
const error = AdministrationDosageValidator(
prescription.base_dosage,
prescription.target_dosage
)(dosage);
setError(error);
if (error) return;
}

setIsLoading(true);
const { res } = await request(MedicineRoutes.administerPrescription, {
pathParams: { consultation, external_id: prescription.id },
body: {
notes,
dosage,
administered_date: isCustomTime ? customTime : undefined,
},
});
Expand All @@ -70,6 +98,24 @@ export default function AdministerMedicine({ prescription, ...props }: Props) {
<div className="mt-4 flex flex-col gap-8">
<PrescriptionDetailCard prescription={prescription} readonly />

{prescription.dosage_type === "TITRATED" && (
<DosageFormField
name="dosage"
label={
t("dosage") +
` (${prescription.base_dosage} - ${prescription.target_dosage})`
}
value={dosage}
onChange={({ value }) => setDosage(value)}
required
min={prescription.base_dosage}
max={prescription.target_dosage}
disabled={isLoading}
error={error}
errorClassName={error ? "block" : "hidden"}
/>
)}

<div className="flex flex-col gap-4 lg:flex-row lg:gap-6">
<TextAreaFormField
label={t("administration_notes")}
Expand Down
77 changes: 59 additions & 18 deletions src/Components/Medicine/CreatePrescriptionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ import Form from "../Form/Form";
import { SelectFormField } from "../Form/FormFields/SelectFormField";
import TextAreaFormField from "../Form/FormFields/TextAreaFormField";
import TextFormField from "../Form/FormFields/TextFormField";
import {
DOSAGE_UNITS,
MedicineAdministrationRecord,
Prescription,
} from "./models";
import { MedicineAdministrationRecord, Prescription } from "./models";
import { useState } from "react";
import NumericWithUnitsFormField from "../Form/FormFields/NumericWithUnitsFormField";
import { useTranslation } from "react-i18next";
import MedibaseAutocompleteFormField from "./MedibaseAutocompleteFormField";
import dayjs from "../../Utils/dayjs";
import { PrescriptionFormValidator } from "./validators";
import CheckBoxFormField from "../Form/FormFields/CheckBoxFormField";
import MedicineRoutes from "./routes";
import request from "../../Utils/request/request";
import useSlug from "../../Common/hooks/useSlug";
import { Success } from "../../Utils/Notifications";
import DosageFormField from "../Form/FormFields/DosageFormField";

export default function CreatePrescriptionForm(props: {
prescription: Prescription;
Expand Down Expand Up @@ -64,7 +61,27 @@ export default function CreatePrescriptionForm(props: {
{...field("medicine_object", RequiredFieldValidator())}
required
/>
<div className="flex items-center gap-4">
{props.prescription.dosage_type !== "PRN" && (
<CheckBoxFormField
label={t("titrate_dosage")}
name="Titrate Dosage"
value={field("dosage_type").value === "TITRATED"}
onChange={(e) => {
if (e.value) {
field("dosage_type").onChange({
name: "dosage_type",
value: "TITRATED",
});
} else {
field("dosage_type").onChange({
name: "dosage_type",
value: "REGULAR",
});
}
}}
/>
)}
<div className="flex flex-wrap items-center gap-x-4">
<SelectFormField
className="flex-1"
label={t("route")}
Expand All @@ -73,27 +90,44 @@ export default function CreatePrescriptionForm(props: {
optionLabel={(key) => t("PRESCRIPTION_ROUTE_" + key)}
optionValue={(key) => key}
/>
<NumericWithUnitsFormField
className="flex-1"
label={t("dosage")}
{...field("dosage", RequiredFieldValidator())}
required
units={DOSAGE_UNITS}
min={0}
/>
{field("dosage_type").value === "TITRATED" ? (
<div className="flex w-full gap-4">
<DosageFormField
className="flex-1"
label={t("start_dosage")}
{...field("base_dosage", RequiredFieldValidator())}
required
min={0}
/>
<DosageFormField
className="flex-1"
label={t("target_dosage")}
{...field("target_dosage", RequiredFieldValidator())}
required
min={0}
/>
</div>
) : (
<DosageFormField
className="flex-1"
label={t("dosage")}
{...field("base_dosage", RequiredFieldValidator())}
required={field("dosage_type").value !== "TITRATED"}
min={0}
/>
)}
</div>

{props.prescription.is_prn ? (
{props.prescription.dosage_type === "PRN" ? (
<>
<TextFormField
label={t("indicator")}
{...field("indicator", RequiredFieldValidator())}
required
/>
<NumericWithUnitsFormField
<DosageFormField
className="flex-1"
label={t("max_dosage_24_hrs")}
units={DOSAGE_UNITS}
min={0}
{...field("max_dosage")}
/>
Expand Down Expand Up @@ -130,6 +164,13 @@ export default function CreatePrescriptionForm(props: {
</div>
)}

{field("dosage_type").value === "TITRATED" && (
<TextAreaFormField
label={t("instruction_on_titration")}
{...field("instruction_on_titration")}
/>
)}

<TextAreaFormField label={t("notes")} {...field("notes")} />
</>
)}
Expand Down
72 changes: 59 additions & 13 deletions src/Components/Medicine/EditPrescriptionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useState } from "react";
import Form from "../Form/Form";
import { DOSAGE_UNITS, Prescription } from "./models";
import { Prescription } from "./models";
import request from "../../Utils/request/request";
import * as Notification from "../../Utils/Notifications";
import useSlug from "../../Common/hooks/useSlug";
import { RequiredFieldValidator } from "../Form/FieldValidators";
import { useTranslation } from "react-i18next";
import { SelectFormField } from "../Form/FormFields/SelectFormField";
import NumericWithUnitsFormField from "../Form/FormFields/NumericWithUnitsFormField";
import {
PRESCRIPTION_FREQUENCIES,
PRESCRIPTION_ROUTES,
Expand All @@ -16,6 +15,8 @@ import TextFormField from "../Form/FormFields/TextFormField";
import TextAreaFormField from "../Form/FormFields/TextAreaFormField";
import { EditPrescriptionFormValidator } from "./validators";
import MedicineRoutes from "./routes";
import CheckBoxFormField from "../Form/FormFields/CheckBoxFormField";
import DosageFormField from "../Form/FormFields/DosageFormField";

interface Props {
initial: Prescription;
Expand Down Expand Up @@ -88,6 +89,27 @@ export default function EditPrescriptionForm(props: Props) {
{...field("discontinued_reason")}
/>

{props.initial.dosage_type !== "PRN" && (
<CheckBoxFormField
label={t("titrate_dosage")}
name="Titrate Dosage"
value={field("dosage_type").value === "TITRATED"}
onChange={(e) => {
if (e.value) {
field("dosage_type").onChange({
name: "dosage_type",
value: "TITRATED",
});
} else {
field("dosage_type").onChange({
name: "dosage_type",
value: "REGULAR",
});
}
}}
/>
)}

<div className="flex items-center gap-4">
<SelectFormField
className="flex-1"
Expand All @@ -97,27 +119,44 @@ export default function EditPrescriptionForm(props: Props) {
optionLabel={(key) => t("PRESCRIPTION_ROUTE_" + key)}
optionValue={(key) => key}
/>
<NumericWithUnitsFormField
className="flex-1"
label={t("dosage")}
{...field("dosage", RequiredFieldValidator())}
required
units={DOSAGE_UNITS}
min={0}
/>
{field("dosage_type").value === "TITRATED" ? (
<div className="flex w-full gap-4">
<DosageFormField
className="flex-1"
label={t("start_dosage")}
{...field("base_dosage", RequiredFieldValidator())}
required
min={0}
/>
<DosageFormField
className="flex-1"
label={t("target_dosage")}
{...field("target_dosage", RequiredFieldValidator())}
required
min={0}
/>
</div>
) : (
<DosageFormField
className="flex-1"
label={t("dosage")}
{...field("base_dosage", RequiredFieldValidator())}
required={field("dosage_type").value !== "TITRATED"}
min={0}
/>
)}
</div>

{props.initial.is_prn ? (
{props.initial.dosage_type === "PRN" ? (
<>
<TextFormField
label={t("indicator")}
{...field("indicator", RequiredFieldValidator())}
required
/>
<NumericWithUnitsFormField
<DosageFormField
className="flex-1"
label={t("max_dosage_24_hrs")}
units={DOSAGE_UNITS}
min={0}
{...field("max_dosage")}
/>
Expand Down Expand Up @@ -154,6 +193,13 @@ export default function EditPrescriptionForm(props: Props) {
</div>
)}

{field("dosage_type").value === "TITRATED" && (
<TextAreaFormField
label={t("instruction_on_titration")}
{...field("instruction_on_titration")}
/>
)}

<TextAreaFormField label={t("notes")} {...field("notes")} />
</>
)}
Expand Down
Loading
Loading