diff --git a/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx b/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx index 0643765339f..e1e72c2f936 100644 --- a/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx +++ b/src/Components/Facility/ConsultationDetails/ConsultationMedicinesTab.tsx @@ -1,20 +1,18 @@ import { ConsultationTabProps } from "./index"; -import PrescriptionAdministrationsTable from "../../Medicine/PrescriptionAdministrationsTable"; import PageTitle from "../../Common/PageHeadTitle"; +import MedicineAdministrationSheet from "../../Medicine/MedicineAdministrationSheet"; export const ConsultationMedicinesTab = (props: ConsultationTabProps) => { return (
{/* eslint-disable-next-line i18next/no-literal-string */} - -
diff --git a/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx new file mode 100644 index 00000000000..ddfc5b63c12 --- /dev/null +++ b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventCell.tsx @@ -0,0 +1,181 @@ +import { Disclosure, Popover, Transition } from "@headlessui/react"; +import dayjs from "../../../Utils/dayjs"; +import { MedicineAdministrationRecord, Prescription } from "../models"; +import CareIcon from "../../../CAREUI/icons/CareIcon"; +import { Fragment } from "react"; +import { classNames, formatDateTime, formatTime } from "../../../Utils/utils"; + +interface Props { + administrations: MedicineAdministrationRecord[]; + interval: { start: Date; end: Date }; + prescription: Prescription; +} + +export default function AdministrationEventCell({ + administrations, + interval: { start, end }, + prescription, +}: Props) { + // Check if cell belongs to an administered prescription + const administered = administrations + .filter((administration) => + dayjs(administration.administered_date).isBetween(start, end) + ) + .sort( + (a, b) => + new Date(a.administered_date!).getTime() - + new Date(b.administered_date!).getTime() + ); + + const hasComment = administered.some((obj) => !!obj.notes); + + if (administered.length) { + return ( + + +
+
+ + {administered.length > 1 && ( + + {administered.length} + + )} +
+ {hasComment && ( + + )} + + {administered.length === 1 ? ( +

+ Administered on{" "} + + {formatTime(administered[0].administered_date)} + +

+ ) : ( +

+ {administered.length} administrations +

+ )} +

Click to view details

+
+
+
+ + + +
+
+ {administered.map((administration) => ( +
+ + {({ open }) => ( + <> + + + Administered on{" "} + + {formatTime(administration.administered_date)} + + + {administration.notes && ( + + )} + + + +
+ Administered by:{" "} + + {administration.administered_by?.first_name}{" "} + {administration.administered_by?.last_name} + +
+
+ Notes:{" "} + + {administration.notes || ( + + No notes + + )} + +
+
+ + )} +
+
+ ))} +
+
+
+
+
+ ); + } + + // Check if cell belongs to a discontinued prescription + if ( + prescription.discontinued && + dayjs(end).isAfter(prescription.discontinued_date) + ) { + if (!dayjs(prescription.discontinued_date).isBetween(start, end)) return; + + return ( +
+ + +

+ Discontinued on{" "} + {formatDateTime(prescription.discontinued_date)} +

+

+ Reason:{" "} + {prescription.discontinued_reason ? ( + {prescription.discontinued_reason} + ) : ( + Not specified + )} +

+
+
+ ); + } +} diff --git a/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventSeperator.tsx b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventSeperator.tsx new file mode 100644 index 00000000000..e38e558e6d5 --- /dev/null +++ b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationEventSeperator.tsx @@ -0,0 +1,22 @@ +import { formatDateTime } from "../../../Utils/utils"; + +export default function AdministrationEventSeperator({ date }: { date: Date }) { + // Show date if it's 00:00 + if (date.getHours() === 0) { + return ( +
+ +

{formatDateTime(date, "DD/MM")}

+
+
+ ); + } + + return ( +
+ +

{formatDateTime(date, "HH")}

+
+
+ ); +} diff --git a/src/Components/Medicine/MedicineAdministrationSheet/AdministrationTable.tsx b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationTable.tsx new file mode 100644 index 00000000000..0417a0e93c0 --- /dev/null +++ b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationTable.tsx @@ -0,0 +1,104 @@ +import { useTranslation } from "react-i18next"; +import CareIcon from "../../../CAREUI/icons/CareIcon"; +import useRangePagination from "../../../Common/hooks/useRangePagination"; +import { classNames, formatDateTime } from "../../../Utils/utils"; +import ButtonV2 from "../../Common/components/ButtonV2"; +import { Prescription } from "../models"; +import MedicineAdministrationTableRow from "./AdministrationTableRow"; + +interface Props { + prescriptions: Prescription[]; + pagination: ReturnType; + onRefetch: () => void; +} + +export default function MedicineAdministrationTable({ + pagination, + prescriptions, + onRefetch, +}: Props) { + const { t } = useTranslation(); + + return ( + + + + + + + {pagination.slots?.map(({ start }, index) => ( + <> + + + + + + + + + {prescriptions.map((obj) => ( + + ))} + +
+
+ {t("medicine")} + +

Dosage &

+

{!prescriptions[0]?.is_prn ? "Frequency" : "Indicator"}

+
+
+
+ + + + + {formatDateTime( + start, + start.getHours() === 0 ? "DD/MM" : "HH:mm" + )} + + + ))} + + + + +
+ ); +} diff --git a/src/Components/Medicine/MedicineAdministrationSheet/AdministrationTableRow.tsx b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationTableRow.tsx new file mode 100644 index 00000000000..326f6072e38 --- /dev/null +++ b/src/Components/Medicine/MedicineAdministrationSheet/AdministrationTableRow.tsx @@ -0,0 +1,244 @@ +import { useTranslation } from "react-i18next"; +import { Prescription } from "../models"; +import { useState } from "react"; +import useQuery from "../../../Utils/request/useQuery"; +import MedicineRoutes from "../routes"; +import { classNames, formatDateTime } from "../../../Utils/utils"; +import useSlug from "../../../Common/hooks/useSlug"; +import DiscontinuePrescription from "../DiscontinuePrescription"; +import AdministerMedicine from "../AdministerMedicine"; +import DialogModal from "../../Common/Dialog"; +import PrescriptionDetailCard from "../PrescriptionDetailCard"; +import ButtonV2, { Cancel, Submit } from "../../Common/components/ButtonV2"; +import CareIcon from "../../../CAREUI/icons/CareIcon"; +import EditPrescriptionForm from "../EditPrescriptionForm"; +import AdministrationEventSeperator from "./AdministrationEventSeperator"; +import AdministrationEventCell from "./AdministrationEventCell"; + +interface Props { + prescription: Prescription; + intervals: { start: Date; end: Date }[]; + refetch: () => void; +} + +export default function MedicineAdministrationTableRow({ + prescription, + ...props +}: Props) { + const { t } = useTranslation(); + const consultation = useSlug("consultation"); + // const [showActions, setShowActions] = useState(false); + const [showDetails, setShowDetails] = useState(false); + const [showEdit, setShowEdit] = useState(false); + const [showAdminister, setShowAdminister] = useState(false); + const [showDiscontinue, setShowDiscontinue] = useState(false); + + const { data, loading } = useQuery(MedicineRoutes.listAdministrations, { + pathParams: { consultation }, + query: { + prescription: prescription.id, + + administered_date_after: formatDateTime( + props.intervals[0].start, + "YYYY-MM-DD" + ), + administered_date_before: formatDateTime( + props.intervals[props.intervals.length - 1].end, + "YYYY-MM-DD" + ), + }, + }); + + return ( + + {showDiscontinue && ( + { + setShowDiscontinue(false); + if (success) { + props.refetch(); + } + }} + /> + )} + {showAdminister && ( + { + setShowAdminister(false); + if (success) { + props.refetch(); + } + }} + /> + )} + {showDetails && ( + setShowDetails(false)} + className="w-full md:max-w-4xl" + show + > +
+ +
+ setShowDetails(false)} + label={t("close")} + /> + setShowDiscontinue(true)} + > + + {t("discontinue")} + + { + setShowDetails(false); + setShowEdit(true); + }} + > + + {t("edit")} + + setShowAdminister(true)} + > + + {t("administer")} + +
+
+
+ )} + {showEdit && ( + setShowEdit(false)} + show={showEdit} + title={`${t("edit")} ${t( + prescription.is_prn ? "prn_prescription" : "prescription_medication" + )}: ${ + prescription.medicine_object?.name ?? prescription.medicine_old + }`} + description={ +
+ + {t("edit_caution_note")} +
+ } + className="w-full max-w-3xl lg:min-w-[600px]" + > + { + setShowEdit(false); + if (success) { + props.refetch(); + } + }} + /> +
+ )} + setShowDetails(true)} + > +
+
+ + {prescription.medicine_object?.name ?? prescription.medicine_old} + + + {prescription.discontinued && ( + + {t("discontinued")} + + )} + + {prescription.route && ( + + {t(prescription.route)} + + )} +
+ +
+

{prescription.dosage}

+

+ {!prescription.is_prn + ? t("PRESCRIPTION_FREQUENCY_" + prescription.frequency) + : prescription.indicator} +

+
+
+ + + + + {/* Administration Cells */} + {props.intervals.map(({ start, end }, index) => ( + <> + + + + + + {data?.results === undefined ? ( + + ) : ( + + )} + + + ))} + + + {/* Action Buttons */} + + setShowAdminister(true)} + > + {t("administer")} + + + + ); +} diff --git a/src/Components/Medicine/MedicineAdministrationSheet/index.tsx b/src/Components/Medicine/MedicineAdministrationSheet/index.tsx new file mode 100644 index 00000000000..16b1f78c85d --- /dev/null +++ b/src/Components/Medicine/MedicineAdministrationSheet/index.tsx @@ -0,0 +1,139 @@ +import { useTranslation } from "react-i18next"; +import useSlug from "../../../Common/hooks/useSlug"; +import useQuery from "../../../Utils/request/useQuery"; +import MedicineRoutes from "../routes"; +import { useMemo, useState } from "react"; +import { computeActivityBounds } from "./utils"; +import useBreakpoints from "../../../Common/hooks/useBreakpoints"; +import SubHeading from "../../../CAREUI/display/SubHeading"; +import ButtonV2 from "../../Common/components/ButtonV2"; +import CareIcon from "../../../CAREUI/icons/CareIcon"; +import BulkAdminister from "./BulkAdminister"; +import useRangePagination from "../../../Common/hooks/useRangePagination"; +import MedicineAdministrationTable from "./AdministrationTable"; + +interface Props { + readonly?: boolean; + is_prn: boolean; +} + +const DEFAULT_BOUNDS = { start: new Date(), end: new Date() }; + +const MedicineAdministrationSheet = ({ readonly, is_prn }: Props) => { + const { t } = useTranslation(); + const consultation = useSlug("consultation"); + + const [showDiscontinued, setShowDiscontinued] = useState(false); + + const filters = { is_prn, prescription_type: "REGULAR", limit: 100 }; + + const { data, refetch } = useQuery(MedicineRoutes.listPrescriptions, { + pathParams: { consultation }, + query: { ...filters, discontinued: showDiscontinued ? undefined : false }, + }); + + const discontinuedCount = useQuery(MedicineRoutes.listPrescriptions, { + pathParams: { consultation }, + query: { ...filters, discontinued: true }, + prefetch: !showDiscontinued, + }).data?.count; + + const { activityTimelineBounds, prescriptions } = useMemo( + () => ({ + prescriptions: data?.results?.sort( + (a, b) => +a.discontinued - +b.discontinued + ), + activityTimelineBounds: data + ? computeActivityBounds(data.results) + : undefined, + }), + [data] + ); + + const daysPerPage = useBreakpoints({ default: 1, "2xl": 2 }); + const pagination = useRangePagination({ + bounds: activityTimelineBounds ?? DEFAULT_BOUNDS, + perPage: daysPerPage * 24 * 60 * 60 * 1000, + slots: (daysPerPage * 24) / 4, // Grouped by 4 hours + defaultEnd: true, + }); + + return ( + <> + + + + + {t("edit_prescriptions")} + + {t("edit")} + + refetch()} + /> + + ) + } + /> + +
+ {prescriptions?.length === 0 && } + + {prescriptions?.length && ( + + )} + + {!showDiscontinued && !!discontinuedCount && ( + setShowDiscontinued(true)} + > + + + + Show {discontinuedCount} other discontinued + prescription(s) + + + + )} +
+ + ); +}; + +export default MedicineAdministrationSheet; + +const NoPrescriptions = ({ prn }: { prn: boolean }) => { + return ( +
+ +

+ {prn + ? "No PRN Prescriptions Prescribed" + : "No Prescriptions Prescribed"} +

+
+ ); +}; diff --git a/src/Components/Medicine/PrescriptionAdministrationsTable.tsx b/src/Components/Medicine/PrescriptionAdministrationsTable.tsx index a454df96b2c..981be72e8ce 100644 --- a/src/Components/Medicine/PrescriptionAdministrationsTable.tsx +++ b/src/Components/Medicine/PrescriptionAdministrationsTable.tsx @@ -1,769 +1,769 @@ -import { Fragment, useCallback, useEffect, useMemo, useState } from "react"; -import { PrescriptionActions } from "../../Redux/actions"; -import { useDispatch } from "react-redux"; -import { MedicineAdministrationRecord, Prescription } from "./models"; -import CareIcon from "../../CAREUI/icons/CareIcon"; -import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; -import SlideOver from "../../CAREUI/interactive/SlideOver"; -import MedicineAdministration from "./MedicineAdministration"; -import DiscontinuePrescription from "./DiscontinuePrescription"; -import AdministerMedicine from "./AdministerMedicine"; -import DialogModal from "../Common/Dialog"; -import PrescriptionDetailCard from "./PrescriptionDetailCard"; -import { useTranslation } from "react-i18next"; -import SubHeading from "../../CAREUI/display/SubHeading"; -import dayjs from "../../Utils/dayjs"; -import { classNames, formatDateTime, formatTime } from "../../Utils/utils"; -import useRangePagination from "../../Common/hooks/useRangePagination"; -import EditPrescriptionForm from "./EditPrescriptionForm"; -import useBreakpoints from "../../Common/hooks/useBreakpoints"; -import { Disclosure, Popover, Transition } from "@headlessui/react"; - -interface DateRange { - start: Date; - end: Date; -} - -interface Props { - prn: boolean; - prescription_type?: Prescription["prescription_type"]; - consultation_id: string; - readonly?: boolean; -} - -interface State { - prescriptions: Prescription[]; - administrationsTimeBounds: DateRange; -} - -export default function PrescriptionAdministrationsTable({ - prn, - consultation_id, - readonly, -}: Props) { - const dispatch = useDispatch(); - const { t } = useTranslation(); - - const [state, setState] = useState(); - const [showDiscontinued, setShowDiscontinued] = useState(false); - const [discontinuedCount, setDiscontinuedCount] = useState(); - const daysPerPage = useBreakpoints({ default: 1, "2xl": 2 }); - const pagination = useRangePagination({ - bounds: state?.administrationsTimeBounds ?? { - start: new Date(), - end: new Date(), - }, - perPage: daysPerPage * 24 * 60 * 60 * 1000, - slots: (daysPerPage * 24) / 4, // Grouped by 4 hours - defaultEnd: true, - }); - const [showBulkAdminister, setShowBulkAdminister] = useState(false); - - const { list, prescription } = useMemo( - () => PrescriptionActions(consultation_id), - [consultation_id] - ); - - const refetch = useCallback(async () => { - const filters = { - is_prn: prn, - prescription_type: "REGULAR", - limit: 100, - }; - - const res = await dispatch( - list(showDiscontinued ? filters : { ...filters, discontinued: false }) - ); - - setState({ - prescriptions: (res.data.results as Prescription[]).sort( - (a, b) => (a.discontinued ? 1 : 0) - (b.discontinued ? 1 : 0) - ), - administrationsTimeBounds: getAdministrationBounds(res.data.results), - }); - - if (showDiscontinued === false) { - const discontinuedRes = await dispatch( - list({ ...filters, discontinued: true, limit: 0 }) - ); - setDiscontinuedCount(discontinuedRes.data.count); - } - }, [consultation_id, showDiscontinued, dispatch]); - - useEffect(() => { - refetch(); - }, [refetch]); - - return ( -
- {state?.prescriptions && ( - - { - setShowBulkAdminister(false); - refetch(); - }} - /> - - )} - - - - - - {t("edit_prescriptions")} - - {t("edit")} - - setShowBulkAdminister(true)} - className="w-full" - disabled={ - state === undefined || state.prescriptions.length === 0 - } - > - - - {t("administer_medicines")} - - {t("administer")} - - - ) - } - /> - -
- {state?.prescriptions.length === 0 ? ( -
- -

- {prn - ? "No PRN Prescriptions Prescribed" - : "No Prescriptions Prescribed"} -

-
- ) : ( - - - - - - - {state === undefined - ? Array.from({ length: 12 }, (_, i) => i).map((i) => ( - - )) - : pagination.slots?.map(({ start }, index) => ( - <> - - - - - - - - - {state?.prescriptions?.map((item) => ( - - ))} - -
-
- {t("medicine")} - -

Dosage &

-

- {!state?.prescriptions[0]?.is_prn - ? "Frequency" - : "Indicator"} -

-
-
-
- - - - -

-

- {formatDateTime( - start, - start.getHours() === 0 ? "DD/MM" : "HH:mm" - )} - - - ))} - - - - -
- )} - - {showDiscontinued === false && !!discontinuedCount && ( - setShowDiscontinued(true)} - > - - - - Show {discontinuedCount} other discontinued - prescription(s) - - - - )} -
-
- ); -} - -interface PrescriptionRowProps { - prescription: Prescription; - intervals: DateRange[]; - actions: ReturnType["prescription"]>; - refetch: () => void; -} - -const PrescriptionRow = ({ prescription, ...props }: PrescriptionRowProps) => { - const dispatch = useDispatch(); - const { t } = useTranslation(); - // const [showActions, setShowActions] = useState(false); - const [showDetails, setShowDetails] = useState(false); - const [showEdit, setShowEdit] = useState(false); - const [showAdminister, setShowAdminister] = useState(false); - const [showDiscontinue, setShowDiscontinue] = useState(false); - const [administrations, setAdministrations] = - useState(); - - useEffect(() => { - setAdministrations(undefined); - - const getAdministrations = async () => { - const res = await dispatch( - props.actions.listAdministrations({ - administered_date_after: formatDateTime( - props.intervals[0].start, - "YYYY-MM-DD" - ), - administered_date_before: formatDateTime( - props.intervals[props.intervals.length - 1].end, - "YYYY-MM-DD" - ), - }) - ); - - setAdministrations(res.data.results); - }; - - getAdministrations(); - }, [prescription.id, dispatch, props.intervals]); - - return ( - - {showDiscontinue && ( - { - setShowDiscontinue(false); - if (success) { - props.refetch(); - } - }} - /> - )} - {showAdminister && ( - { - setShowAdminister(false); - if (success) { - props.refetch(); - } - }} - /> - )} - {showDetails && ( - setShowDetails(false)} - className="w-full md:max-w-4xl" - show - > -
- -
- setShowDetails(false)} - label={t("close")} - /> - setShowDiscontinue(true)} - > - - {t("discontinue")} - - { - setShowDetails(false); - setShowEdit(true); - }} - > - - {t("edit")} - - setShowAdminister(true)} - > - - {t("administer")} - -
-
-
- )} - {showEdit && ( - setShowEdit(false)} - show={showEdit} - title={`${t("edit")} ${t( - prescription.is_prn ? "prn_prescription" : "prescription_medication" - )}: ${ - prescription.medicine_object?.name ?? prescription.medicine_old - }`} - description={ -
- - {t("edit_caution_note")} -
- } - className="w-full max-w-3xl lg:min-w-[600px]" - > - { - setShowEdit(false); - if (success) { - props.refetch(); - } - }} - /> -
- )} - setShowDetails(true)} - > -
-
- - {prescription.medicine_object?.name ?? prescription.medicine_old} - - - {prescription.discontinued && ( - - {t("discontinued")} - - )} - - {prescription.route && ( - - {t(prescription.route)} - - )} -
- -
-

{prescription.dosage}

-

- {!prescription.is_prn - ? t("PRESCRIPTION_FREQUENCY_" + prescription.frequency) - : prescription.indicator} -

-
-
- - - - {/* Administration Cells */} - {props.intervals.map(({ start, end }, index) => ( - <> - - - - - {administrations === undefined ? ( - - ) : ( - - )} - - - ))} - - - {/* Action Buttons */} - - setShowAdminister(true)} - > - {t("administer")} - - - - ); -}; - -const AdministrationCellSeperator = ({ date }: { date: Date }) => { - // Show date if it's 00:00 - if (date.getHours() === 0) { - return ( -
- -

{formatDateTime(date, "DD/MM")}

-
-
- ); - } - - return ( -
- -

{formatDateTime(date, "HH")}

-
-
- ); -}; - -interface AdministrationCellProps { - administrations: MedicineAdministrationRecord[]; - interval: DateRange; - prescription: Prescription; -} - -const AdministrationCell = ({ - administrations, - interval: { start, end }, - prescription, -}: AdministrationCellProps) => { - // Check if cell belongs to an administered prescription - const administered = administrations - .filter((administration) => - dayjs(administration.administered_date).isBetween(start, end) - ) - .sort( - (a, b) => - new Date(a.administered_date!).getTime() - - new Date(b.administered_date!).getTime() - ); - - const hasComment = administered.some((obj) => !!obj.notes); - - if (administered.length) { - return ( - - -
-
- - {administered.length > 1 && ( - - {administered.length} - - )} -
- {hasComment && ( - - )} - - {administered.length === 1 ? ( -

- Administered on{" "} - - {formatTime(administered[0].administered_date)} - -

- ) : ( -

- {administered.length} administrations -

- )} -

Click to view details

-
-
-
- - - -
-
- {administered.map((administration) => ( -
- - {({ open }) => ( - <> - - - Administered on{" "} - - {formatTime(administration.administered_date)} - - - {administration.notes && ( - - )} - - - -
- Administered by:{" "} - - {administration.administered_by?.first_name}{" "} - {administration.administered_by?.last_name} - -
-
- Notes:{" "} - - {administration.notes || ( - - No notes - - )} - -
-
- - )} -
-
- ))} -
-
-
-
-
- ); - } - - // Check if cell belongs to a discontinued prescription - if ( - prescription.discontinued && - dayjs(end).isAfter(prescription.discontinued_date) - ) { - if (!dayjs(prescription.discontinued_date).isBetween(start, end)) return; - - return ( -
- - -

- Discontinued on{" "} - {formatDateTime(prescription.discontinued_date)} -

-

- Reason:{" "} - {prescription.discontinued_reason ? ( - {prescription.discontinued_reason} - ) : ( - Not specified - )} -

-
-
- ); - } - - // Check if cell belongs to after prescription.created_date - // if (dayjs(start).isAfter(prescription.created_date)) { - // return ; - // } - - // Check if prescription.created_date is between start and end - // if (dayjs(prescription.created_date).isBetween(start, end)) { - // return ( - //
- // - // - //

- // Prescribed on{" "} - // {formatDateTime(prescription.created_date)} - //

- //
- //
- // ); - // } -}; - -function getAdministrationBounds(prescriptions: Prescription[]) { - // get start by finding earliest of all presciption's created_date - const start = new Date( - prescriptions.reduce( - (earliest, curr) => - earliest < curr.created_date ? earliest : curr.created_date, - prescriptions[0]?.created_date ?? new Date() - ) - ); - - // get end by finding latest of all presciption's last_administered_on - const end = new Date( - prescriptions - .filter((prescription) => prescription.last_administered_on) - .reduce( - (latest, curr) => - curr.last_administered_on && curr.last_administered_on > latest - ? curr.last_administered_on - : latest, - prescriptions[0]?.created_date ?? new Date() - ) - ); - - // floor start to 00:00 of the day - start.setHours(0, 0, 0, 0); - - // ceil end to 00:00 of the next day - end.setHours(0, 0, 0, 0); - end.setDate(end.getDate() + 1); - - return { start, end }; -} +// import { Fragment, useCallback, useEffect, useMemo, useState } from "react"; +// import { PrescriptionActions } from "../../Redux/actions"; +// import { useDispatch } from "react-redux"; +// import { MedicineAdministrationRecord, Prescription } from "./models"; +// import CareIcon from "../../CAREUI/icons/CareIcon"; +// import ButtonV2, { Cancel, Submit } from "../Common/components/ButtonV2"; +// import SlideOver from "../../CAREUI/interactive/SlideOver"; +// import MedicineAdministration from "./MedicineAdministration"; +// import DiscontinuePrescription from "./DiscontinuePrescription"; +// import AdministerMedicine from "./AdministerMedicine"; +// import DialogModal from "../Common/Dialog"; +// import PrescriptionDetailCard from "./PrescriptionDetailCard"; +// import { useTranslation } from "react-i18next"; +// import SubHeading from "../../CAREUI/display/SubHeading"; +// import dayjs from "../../Utils/dayjs"; +// import { classNames, formatDateTime, formatTime } from "../../Utils/utils"; +// import useRangePagination from "../../Common/hooks/useRangePagination"; +// import EditPrescriptionForm from "./EditPrescriptionForm"; +// import useBreakpoints from "../../Common/hooks/useBreakpoints"; +// import { Disclosure, Popover, Transition } from "@headlessui/react"; + +// interface DateRange { +// start: Date; +// end: Date; +// } + +// interface Props { +// prn: boolean; +// prescription_type?: Prescription["prescription_type"]; +// consultation_id: string; +// readonly?: boolean; +// } + +// interface State { +// prescriptions: Prescription[]; +// administrationsTimeBounds: DateRange; +// } + +// export default function PrescriptionAdministrationsTable({ +// prn, +// consultation_id, +// readonly, +// }: Props) { +// const dispatch = useDispatch(); +// const { t } = useTranslation(); + +// const [state, setState] = useState(); +// const [showDiscontinued, setShowDiscontinued] = useState(false); +// const [discontinuedCount, setDiscontinuedCount] = useState(); +// const daysPerPage = useBreakpoints({ default: 1, "2xl": 2 }); +// const pagination = useRangePagination({ +// bounds: state?.administrationsTimeBounds ?? { +// start: new Date(), +// end: new Date(), +// }, +// perPage: daysPerPage * 24 * 60 * 60 * 1000, +// slots: (daysPerPage * 24) / 4, // Grouped by 4 hours +// defaultEnd: true, +// }); +// const [showBulkAdminister, setShowBulkAdminister] = useState(false); + +// const { list, prescription } = useMemo( +// () => PrescriptionActions(consultation_id), +// [consultation_id] +// ); + +// const refetch = useCallback(async () => { +// const filters = { +// is_prn: prn, +// prescription_type: "REGULAR", +// limit: 100, +// }; + +// const res = await dispatch( +// list(showDiscontinued ? filters : { ...filters, discontinued: false }) +// ); + +// setState({ +// prescriptions: (res.data.results as Prescription[]).sort( +// (a, b) => +a.discontinued - +b.discontinued +// ), +// administrationsTimeBounds: getAdministrationBounds(res.data.results), +// }); + +// if (showDiscontinued === false) { +// const discontinuedRes = await dispatch( +// list({ ...filters, discontinued: true, limit: 0 }) +// ); +// setDiscontinuedCount(discontinuedRes.data.count); +// } +// }, [consultation_id, showDiscontinued, dispatch]); + +// useEffect(() => { +// refetch(); +// }, [refetch]); + +// return ( +//
+// {state?.prescriptions && ( +// +// { +// setShowBulkAdminister(false); +// refetch(); +// }} +// /> +// +// )} + +// +// +// +// +// {t("edit_prescriptions")} +// +// {t("edit")} +// +// setShowBulkAdminister(true)} +// className="w-full" +// disabled={ +// state === undefined || state.prescriptions.length === 0 +// } +// > +// +// +// {t("administer_medicines")} +// +// {t("administer")} +// +// +// ) +// } +// /> + +//
+// {state?.prescriptions.length === 0 ? ( +//
+// +//

+// {prn +// ? "No PRN Prescriptions Prescribed" +// : "No Prescriptions Prescribed"} +//

+//
+// ) : ( +// +// +// +// + +// +// {state === undefined +// ? Array.from({ length: 12 }, (_, i) => i).map((i) => ( +// +// )) +// : pagination.slots?.map(({ start }, index) => ( +// <> +// +// + +// +// +// + +// +// {state?.prescriptions?.map((item) => ( +// +// ))} +// +//
+//
+// {t("medicine")} +// +//

Dosage &

+//

+// {!state?.prescriptions[0]?.is_prn +// ? "Frequency" +// : "Indicator"} +//

+//
+//
+//
+// +// +// +// +//

+//

+// {formatDateTime( +// start, +// start.getHours() === 0 ? "DD/MM" : "HH:mm" +// )} +// +// +// ))} +// +// +// +// +//
+// )} + +// {showDiscontinued === false && !!discontinuedCount && ( +// setShowDiscontinued(true)} +// > +// +// +// +// Show {discontinuedCount} other discontinued +// prescription(s) +// +// +// +// )} +//
+//
+// ); +// } + +// interface PrescriptionRowProps { +// prescription: Prescription; +// intervals: DateRange[]; +// actions: ReturnType["prescription"]>; +// refetch: () => void; +// } + +// const PrescriptionRow = ({ prescription, ...props }: PrescriptionRowProps) => { +// const dispatch = useDispatch(); +// const { t } = useTranslation(); +// // const [showActions, setShowActions] = useState(false); +// const [showDetails, setShowDetails] = useState(false); +// const [showEdit, setShowEdit] = useState(false); +// const [showAdminister, setShowAdminister] = useState(false); +// const [showDiscontinue, setShowDiscontinue] = useState(false); +// const [administrations, setAdministrations] = +// useState(); + +// useEffect(() => { +// setAdministrations(undefined); + +// const getAdministrations = async () => { +// const res = await dispatch( +// props.actions.listAdministrations({ +// administered_date_after: formatDateTime( +// props.intervals[0].start, +// "YYYY-MM-DD" +// ), +// administered_date_before: formatDateTime( +// props.intervals[props.intervals.length - 1].end, +// "YYYY-MM-DD" +// ), +// }) +// ); + +// setAdministrations(res.data.results); +// }; + +// getAdministrations(); +// }, [prescription.id, dispatch, props.intervals]); + +// return ( +// +// {showDiscontinue && ( +// { +// setShowDiscontinue(false); +// if (success) { +// props.refetch(); +// } +// }} +// /> +// )} +// {showAdminister && ( +// { +// setShowAdminister(false); +// if (success) { +// props.refetch(); +// } +// }} +// /> +// )} +// {showDetails && ( +// setShowDetails(false)} +// className="w-full md:max-w-4xl" +// show +// > +//
+// +//
+// setShowDetails(false)} +// label={t("close")} +// /> +// setShowDiscontinue(true)} +// > +// +// {t("discontinue")} +// +// { +// setShowDetails(false); +// setShowEdit(true); +// }} +// > +// +// {t("edit")} +// +// setShowAdminister(true)} +// > +// +// {t("administer")} +// +//
+//
+//
+// )} +// {showEdit && ( +// setShowEdit(false)} +// show={showEdit} +// title={`${t("edit")} ${t( +// prescription.is_prn ? "prn_prescription" : "prescription_medication" +// )}: ${ +// prescription.medicine_object?.name ?? prescription.medicine_old +// }`} +// description={ +//
+// +// {t("edit_caution_note")} +//
+// } +// className="w-full max-w-3xl lg:min-w-[600px]" +// > +// { +// setShowEdit(false); +// if (success) { +// props.refetch(); +// } +// }} +// /> +//
+// )} +// setShowDetails(true)} +// > +//
+//
+// +// {prescription.medicine_object?.name ?? prescription.medicine_old} +// + +// {prescription.discontinued && ( +// +// {t("discontinued")} +// +// )} + +// {prescription.route && ( +// +// {t(prescription.route)} +// +// )} +//
+ +//
+//

{prescription.dosage}

+//

+// {!prescription.is_prn +// ? t("PRESCRIPTION_FREQUENCY_" + prescription.frequency) +// : prescription.indicator} +//

+//
+//
+// + +// +// {/* Administration Cells */} +// {props.intervals.map(({ start, end }, index) => ( +// <> +// +// +// +// +// {administrations === undefined ? ( +// +// ) : ( +// +// )} +// +// +// ))} +// + +// {/* Action Buttons */} +// +// setShowAdminister(true)} +// > +// {t("administer")} +// +// +// +// ); +// }; + +// const AdministrationCellSeperator = ({ date }: { date: Date }) => { +// // Show date if it's 00:00 +// if (date.getHours() === 0) { +// return ( +//
+// +//

{formatDateTime(date, "DD/MM")}

+//
+//
+// ); +// } + +// return ( +//
+// +//

{formatDateTime(date, "HH")}

+//
+//
+// ); +// }; + +// interface AdministrationCellProps { +// administrations: MedicineAdministrationRecord[]; +// interval: DateRange; +// prescription: Prescription; +// } + +// const AdministrationCell = ({ +// administrations, +// interval: { start, end }, +// prescription, +// }: AdministrationCellProps) => { +// // Check if cell belongs to an administered prescription +// const administered = administrations +// .filter((administration) => +// dayjs(administration.administered_date).isBetween(start, end) +// ) +// .sort( +// (a, b) => +// new Date(a.administered_date!).getTime() - +// new Date(b.administered_date!).getTime() +// ); + +// const hasComment = administered.some((obj) => !!obj.notes); + +// if (administered.length) { +// return ( +// +// +//
+//
+// +// {administered.length > 1 && ( +// +// {administered.length} +// +// )} +//
+// {hasComment && ( +// +// )} +// +// {administered.length === 1 ? ( +//

+// Administered on{" "} +// +// {formatTime(administered[0].administered_date)} +// +//

+// ) : ( +//

+// {administered.length} administrations +//

+// )} +//

Click to view details

+//
+//
+//
+ +// +// +//
+//
+// {administered.map((administration) => ( +//
+// +// {({ open }) => ( +// <> +// +// +// Administered on{" "} +// +// {formatTime(administration.administered_date)} +// +// +// {administration.notes && ( +// +// )} +// +// +// +//
+// Administered by:{" "} +// +// {administration.administered_by?.first_name}{" "} +// {administration.administered_by?.last_name} +// +//
+//
+// Notes:{" "} +// +// {administration.notes || ( +// +// No notes +// +// )} +// +//
+//
+// +// )} +//
+//
+// ))} +//
+//
+//
+//
+//
+// ); +// } + +// // Check if cell belongs to a discontinued prescription +// if ( +// prescription.discontinued && +// dayjs(end).isAfter(prescription.discontinued_date) +// ) { +// if (!dayjs(prescription.discontinued_date).isBetween(start, end)) return; + +// return ( +//
+// +// +//

+// Discontinued on{" "} +// {formatDateTime(prescription.discontinued_date)} +//

+//

+// Reason:{" "} +// {prescription.discontinued_reason ? ( +// {prescription.discontinued_reason} +// ) : ( +// Not specified +// )} +//

+//
+//
+// ); +// } + +// // Check if cell belongs to after prescription.created_date +// // if (dayjs(start).isAfter(prescription.created_date)) { +// // return ; +// // } + +// // Check if prescription.created_date is between start and end +// // if (dayjs(prescription.created_date).isBetween(start, end)) { +// // return ( +// //
+// // +// // +// //

+// // Prescribed on{" "} +// // {formatDateTime(prescription.created_date)} +// //

+// //
+// //
+// // ); +// // } +// }; + +// function getAdministrationBounds(prescriptions: Prescription[]) { +// // get start by finding earliest of all presciption's created_date +// const start = new Date( +// prescriptions.reduce( +// (earliest, curr) => +// earliest < curr.created_date ? earliest : curr.created_date, +// prescriptions[0]?.created_date ?? new Date() +// ) +// ); + +// // get end by finding latest of all presciption's last_administered_on +// const end = new Date( +// prescriptions +// .filter((prescription) => prescription.last_administered_on) +// .reduce( +// (latest, curr) => +// curr.last_administered_on && curr.last_administered_on > latest +// ? curr.last_administered_on +// : latest, +// prescriptions[0]?.created_date ?? new Date() +// ) +// ); + +// // floor start to 00:00 of the day +// start.setHours(0, 0, 0, 0); + +// // ceil end to 00:00 of the next day +// end.setHours(0, 0, 0, 0); +// end.setDate(end.getDate() + 1); + +// return { start, end }; +// }