@openmrs/esm-laboratory-app
Version:
An O3 frontend module for managing laboratory requests and queues
95 lines (85 loc) • 3.96 kB
text/typescript
import { useMemo } from 'react';
import dayjs from 'dayjs';
import useSWR from 'swr';
import { openmrsFetch, restBaseUrl, useAppContext, useConfig } from '@openmrs/esm-framework';
import { type Order } from '@openmrs/esm-patient-common-lib';
import type { DateFilterContext, FulfillerStatus, GroupedOrders } from './types';
/**
* Custom hook for retrieving laboratory orders based on the specified status.
*
* @param status - The status of the orders to retrieve
* @param excludeCanceled - Whether to exclude canceled, discontinued and expired orders
*/
export function useLabOrders(status: 'NEW' | FulfillerStatus = null, excludeCanceled = true) {
const { dateRange } = useAppContext<DateFilterContext>('laboratory-date-filter') ?? {
dateRange: [dayjs().startOf('day').toDate(), new Date()],
};
const { laboratoryOrderTypeUuid } = useConfig();
const fulfillerStatus = useMemo(() => (status === 'NEW' ? null : status), [status]);
const newOrdersOnly = status === 'NEW';
const customRepresentation =
'custom:(uuid,orderNumber,patient:(uuid,display,person:(uuid,display,age,gender)),concept:(uuid,display),action,careSetting:(uuid,display,description,careSettingType,display),previousOrder,dateActivated,scheduledDate,dateStopped,autoExpireDate,encounter:(uuid,display),orderer:(uuid,display),orderReason,orderReasonNonCoded,orderType:(uuid,display,name,description,conceptClasses,parent),urgency,instructions,commentToFulfiller,display,fulfillerStatus,fulfillerComment,specimenSource,laterality,clinicalHistory,frequency,numberOfRepeats)';
let url = `${restBaseUrl}/order?orderTypes=${laboratoryOrderTypeUuid}&v=${customRepresentation}`;
url = fulfillerStatus ? url + `&fulfillerStatus=${fulfillerStatus}` : url;
url = excludeCanceled ? `${url}&excludeCanceledAndExpired=true&excludeDiscontinueOrders=true` : url;
// The usage of SWR's mutator seems to only suffice for cases where we don't apply a status filter
url = dateRange
? `${url}&activatedOnOrAfterDate=${dateRange.at(0).toISOString()}&activatedOnOrBeforeDate=${dateRange
.at(1)
.toISOString()}`
: url;
const { data, error, mutate, isLoading, isValidating } = useSWR<{
data: { results: Array<Order> };
}>(`${url}`, openmrsFetch);
const filteredOrders =
data?.data &&
newOrdersOnly &&
data.data.results.filter((order) => order?.action === 'NEW' && order?.fulfillerStatus === null);
return {
labOrders: filteredOrders || data?.data.results || [],
isLoading,
isError: error,
mutate,
isValidating,
};
}
export function useSearchGroupedResults(data: Array<GroupedOrders>, searchString: string) {
const searchResults = useMemo(() => {
if (searchString && searchString.trim() !== '') {
// Normalize the search string to lowercase
const lowerSearchString = searchString.toLowerCase();
return data.filter((orderGroup) =>
orderGroup.orders.some(
(order) =>
order.orderNumber.toLowerCase().includes(lowerSearchString) ||
order.patient.display.toLowerCase().includes(lowerSearchString),
),
);
}
return data;
}, [searchString, data]);
return searchResults;
}
export function setFulfillerStatus(orderId: string, status: FulfillerStatus, abortController: AbortController) {
return openmrsFetch(`${restBaseUrl}/order/${orderId}/fulfillerdetails/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
signal: abortController.signal,
body: { fulfillerStatus: status },
});
}
export function rejectLabOrder(orderId: string, comment: string, abortController: AbortController) {
return openmrsFetch(`${restBaseUrl}/order/${orderId}/fulfillerdetails/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
signal: abortController.signal,
body: {
fulfillerStatus: 'DECLINED',
fulfillerComment: comment,
},
});
}