Skip to content
65 changes: 52 additions & 13 deletions src/components/Medicine/PrescriptionListSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { cn } from "@/lib/utils";
import { useQuery } from "@tanstack/react-query";
import * as React from "react";

import { CardListSkeleton } from "@/components/Common/SkeletonLoading";
Expand All @@ -18,8 +17,11 @@ import prescriptionApi from "@/types/emr/prescription/prescriptionApi";
import { TagConfig } from "@/types/emr/tagConfig/tagConfig";
import query from "@/Utils/request/query";
import { formatDateTime, formatName } from "@/Utils/utils";
import { useInfiniteQuery } from "@tanstack/react-query";
import { ChevronDown, ReceiptTextIcon } from "lucide-react";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { useInView } from "react-intersection-observer";

function PrescriptionTags({ tags }: { tags?: TagConfig[] }) {
if (!tags || tags.length === 0) return null;
Expand Down Expand Up @@ -56,14 +58,35 @@ export default function PrescriptionListSelector({
}: PrescriptionListSelectorProps) {
const { t } = useTranslation();
const [openDrawer, setOpenDrawer] = React.useState(false);
const { data: prescriptions, isLoading } = useQuery({
queryKey: ["prescriptions", patientId, encounterId],
queryFn: query(prescriptionApi.list, {
pathParams: { patientId },
queryParams: { encounter: encounterId, facility: facilityId },
}),
enabled: !!patientId && !!encounterId,
});
const { ref, inView } = useInView();
const PAGE_LIMIT = 14;
Comment thread
NikhilA8606 marked this conversation as resolved.
Outdated

const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
useInfiniteQuery({
Comment thread
NikhilA8606 marked this conversation as resolved.
Outdated
queryKey: ["infinite-prescriptions", patientId, encounterId],
Comment thread
NikhilA8606 marked this conversation as resolved.
Outdated
Comment thread
NikhilA8606 marked this conversation as resolved.
Outdated
queryFn: async ({ pageParam = 0, signal }) => {
Comment thread
NikhilA8606 marked this conversation as resolved.
Comment thread
NikhilA8606 marked this conversation as resolved.
const response = await query(prescriptionApi.list, {
pathParams: { patientId },
queryParams: {
encounter: encounterId,
facility: facilityId,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
limit: String(PAGE_LIMIT),
offset: String(pageParam),
},
})({
signal,
});
return response;
},
enabled: !!patientId && !!encounterId,
initialPageParam: 0,
getNextPageParam: (lastPage, allPages) => {
const currentOffset = allPages.length * PAGE_LIMIT;
return currentOffset < lastPage.count ? currentOffset : null;
},
});

const prescriptions = data?.pages.flatMap((page) => page.results) ?? [];

const handleSelectPrescription = React.useCallback(
(prescription: PrescritionList | undefined) => {
Expand All @@ -73,6 +96,12 @@ export default function PrescriptionListSelector({
[onSelectPrescription],
);

useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView, hasNextPage, fetchNextPage]);

Comment thread
NikhilA8606 marked this conversation as resolved.
Outdated
if (isLoading) {
return (
<div className="space-y-3 w-60">
Expand All @@ -82,7 +111,7 @@ export default function PrescriptionListSelector({
}

const selectedPrescription = selectedPrescriptionId
? prescriptions?.results.find((pres) => pres.id === selectedPrescriptionId)
? prescriptions.find((pres) => pres.id === selectedPrescriptionId)
: undefined;
Comment thread
NikhilA8606 marked this conversation as resolved.

const isAllSelected = selectedPrescriptionId === undefined;
Expand All @@ -91,9 +120,11 @@ export default function PrescriptionListSelector({
<>
<div className="hidden lg:block h-full overflow-y-auto pr-1">
<PrescriptionList
prescriptions={prescriptions?.results ?? []}
prescriptions={prescriptions}
selectedPrescriptionId={selectedPrescriptionId}
onSelectPrescription={onSelectPrescription}
ref={ref}
isFetchingNextPage={isFetchingNextPage}
/>
</div>
<div className="lg:hidden">
Expand Down Expand Up @@ -154,7 +185,9 @@ export default function PrescriptionListSelector({
</DrawerHeader>
<div className="overflow-y-auto pr-2">
<PrescriptionList
prescriptions={prescriptions?.results ?? []}
ref={ref}
isFetchingNextPage={isFetchingNextPage}
prescriptions={prescriptions}
selectedPrescriptionId={selectedPrescriptionId}
onSelectPrescription={handleSelectPrescription}
/>
Expand All @@ -176,10 +209,14 @@ function PrescriptionList({
prescriptions,
selectedPrescriptionId,
onSelectPrescription,
isFetchingNextPage,
ref,
}: {
prescriptions: PrescritionList[];
selectedPrescriptionId: string | undefined;
onSelectPrescription: (prescription: PrescritionList | undefined) => void;
isFetchingNextPage: boolean;
ref: (node?: Element | null) => void;
Comment thread
NikhilA8606 marked this conversation as resolved.
Outdated
}) {
const { t } = useTranslation();

Expand All @@ -199,7 +236,7 @@ function PrescriptionList({

return (
<div className="space-y-2 p-2">
{items.map((item) => {
{items.map((item, i) => {
const isSelected = selectedPrescriptionId === item.id;

return (
Expand All @@ -214,6 +251,7 @@ function PrescriptionList({
onClick={() =>
onSelectPrescription(prescriptions.find((p) => p.id === item.id))
}
ref={i === items.length - 1 ? ref : undefined}
>
{isSelected && (
<div className="absolute right-0 h-8 w-1 bg-primary-600 rounded-l inset-y-1/2 -translate-y-1/2" />
Expand All @@ -240,6 +278,7 @@ function PrescriptionList({
</Card>
);
})}
{isFetchingNextPage && <CardListSkeleton count={5} />}
</div>
);
}
Loading