Skip to content

Instantly share code, notes, and snippets.

@amosmachora
Created October 3, 2024 12:07
Show Gist options
  • Save amosmachora/33e4e372778f75cde62183503f227b2b to your computer and use it in GitHub Desktop.
Save amosmachora/33e4e372778f75cde62183503f227b2b to your computer and use it in GitHub Desktop.
Session approach to storing and updating date ranges
import { openmrsFetch, restBaseUrl, useConfig } from '@openmrs/esm-framework';
import { Order } from '@openmrs/esm-patient-common-lib';
import { useMemo } from 'react';
import useSWR from 'swr';
import { useSessionStorage } from './hooks/use-session-storage';
import { 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] = useSessionStorage<Array<Date>>('lab-orders-date-range');
const { laboratoryOrderTypeUuid } = useConfig();
const fulfillerStatus = useMemo(() => (status === 'NEW' ? null : status), [status]);
const newOrdersOnly = status === 'NEW';
let url = `${restBaseUrl}/order?orderTypes=${laboratoryOrderTypeUuid}&v=full`;
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 =
Array.isArray(dateRange) && dateRange.length === 2 && dateRange[0] instanceof Date && dateRange[1] instanceof Date
? `${url}&activatedOnOrAfterDate=${dateRange[0].toISOString()}&activatedOnOrBeforeDate=${dateRange[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,
},
});
}
import { DatePicker, DatePickerInput } from '@carbon/react';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useSessionStorage } from '../../hooks/use-session-storage';
import styles from './orders-date-range-picker.scss';
export const OrdersDateRangePicker = () => {
const currentDate = new Date();
const { t } = useTranslation();
const [dateRange, updateDateRange] = useSessionStorage('lab-orders-date-range');
const handleOrdersDateRangeChange = (dates: Date[]) => {
updateDateRange(dates);
};
return (
<div className={styles.datePickerWrapper}>
<p>{t('dateRange', 'Date range')}:</p>
<DatePicker
datePickerType="range"
className={styles.dateRangePicker}
onClose={handleOrdersDateRangeChange}
maxDate={currentDate.toISOString()}
value={dateRange}
>
<DatePickerInput id="date-picker-input-id-start" placeholder="mm/dd/yyyy" size="md" />
<DatePickerInput id="date-picker-input-id-finish" placeholder="mm/dd/yyyy" size="md" />
</DatePicker>
</div>
);
};
import React, { useEffect, useState } from 'react';
function getDefaultValue<T>(key: string, initialValue: T | null): T | null {
const storedValue: string | null = sessionStorage.getItem(key);
if (storedValue) {
return JSON.parse(storedValue);
}
if (initialValue instanceof Function) {
return initialValue();
}
return initialValue;
}
export function useSessionStorage<T>(
key: string,
initialValue?: T | null,
): [T | null, React.Dispatch<React.SetStateAction<T | null>>] {
const [value, setValue] = useState<T | null>(getDefaultValue(key, initialValue));
useEffect(() => {
if (value) {
sessionStorage.setItem(key, JSON.stringify(value));
}
if (value === null) {
sessionStorage.removeItem(key);
}
}, [key, value]);
return [value, setValue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment