Skip to content

Commit

Permalink
Feat/patient list app pagination
Browse files Browse the repository at this point in the history
Feat/patient list app pagination
  • Loading branch information
Michaelndula authored Jul 19, 2024
2 parents 6c748b6 + 72aec25 commit ef2707e
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 175 deletions.
2 changes: 1 addition & 1 deletion packages/esm-patient-list-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sjthc/esm-patient-list-app",
"version": "1.1.8",
"version": "1.1.9",
"license": "MPL-2.0",
"description": "Custom Patient list microfrontend for the OpenMRS SPA",
"browser": "dist/sjthc-esm-patient-list-app.js",
Expand Down
11 changes: 11 additions & 0 deletions packages/esm-patient-list-app/src/helpers/dateOps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const getPaddedDateString = (date) => {
const dateObject = new Date(date);

const day = dateObject.getDate() < 10 ? `0${dateObject.getDate()}` : dateObject.getDate();

const month = dateObject.getMonth() + 1 < 10 ? `0${dateObject.getMonth() + 1}`: dateObject.getMonth() + 1;

return `${day}-${month}-${dateObject.getFullYear()}`


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import styles from "./home-dashboard.scss";
import { useTranslation } from "react-i18next";
import {useTranslation} from "react-i18next";
import PatientQueueIllustration from "./patient-queue-illustration.component";
import MetricsCard from "./dashboard-card/dashboard-card.component";
import {
Expand All @@ -10,35 +10,30 @@ import {
Tile,
SkeletonPlaceholder
} from "@carbon/react";
import { usePatientList } from "../hooks/usePatientList";
import {usePatientList} from "../hooks/usePatientList";
import DataTable from "react-data-table-component";

type PatientListHomeProps = {
patientUuid?: string;
};

const PatientListHome: React.FC<PatientListHomeProps> = () => {
const { t } = useTranslation();

const [dateRange, setDateRange] = React.useState({ start: null, end: null });
const {t} = useTranslation();

const {
patient,
isLoading,
isError,
filterData,
filteredData,
data,
tableColumns,
customStyles
customStyles,
setDateRange,
dateRange,
currentPaginationState,
getAllClients,
clear,
} = usePatientList();

const totalPatients = patient?.total || 0;

const totalPatients = 0;

const clear = () => {
filterData({});
setDateRange({ start: null, end: null });
};
return (
<>
{isLoading ? (
Expand All @@ -49,7 +44,7 @@ const PatientListHome: React.FC<PatientListHomeProps> = () => {
>
<div className={styles.header} data-testid="patient-queue-header">
<div className={styles["left-justified-items"]}>
<PatientQueueIllustration />
<PatientQueueIllustration/>
<div className={styles["page-labels"]}>
<p className={styles.title}>{t("patients", "Patients")}</p>
<p className={styles.subTitle}>{t("dashboard", "Dashboard")}</p>
Expand All @@ -61,16 +56,16 @@ const PatientListHome: React.FC<PatientListHomeProps> = () => {
data-testid="registered-patients"
>
<Tile className={styles.tileContainer}>
<SkeletonPlaceholder />
<SkeletonPlaceholder/>
</Tile>
</div>
<br />
<br/>
</div>
) : (
<>
<div className={styles.header} data-testid="patient-queue-header">
<div className={styles["left-justified-items"]}>
<PatientQueueIllustration />
<PatientQueueIllustration/>
<div className={styles["page-labels"]}>
<p className={styles.title}>{t("patients", "Patients")}</p>
<p className={styles.subTitle}>{t("dashboard", "Dashboard")}</p>
Expand All @@ -93,7 +88,7 @@ const PatientListHome: React.FC<PatientListHomeProps> = () => {
<div className={styles.listFilter}>
<DatePicker
onChange={(value) =>
setDateRange({ start: value[0], end: value[1] })
setDateRange({start: value[0], end: value[1]})
}
value={[dateRange.start, dateRange.end]}
datePickerType="range"
Expand All @@ -112,13 +107,6 @@ const PatientListHome: React.FC<PatientListHomeProps> = () => {
size="md"
/>
</DatePicker>
<Button
onClick={() => filterData({ ...dateRange })}
kind="primary"
style={styles.FilterButton}
>
Search
</Button>
<Button
onClick={clear}
kind="secondary"
Expand All @@ -128,8 +116,9 @@ const PatientListHome: React.FC<PatientListHomeProps> = () => {
</Button>
</div>
<DataTable
paginationPerPage={15}
columns={tableColumns}
data={filteredData}
data={data}
responsive
pagination
customStyles={customStyles}
Expand Down
149 changes: 86 additions & 63 deletions packages/esm-patient-list-app/src/hooks/usePatientList.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,88 @@
import { useEffect, useState } from "react";
import useSWR from "swr";
import { openmrsFetch } from "@openmrs/esm-framework";
import React, {useEffect, useState} from "react";
import {openmrsFetch} from "@openmrs/esm-framework";
import {getPaddedDateString} from "../helpers/dateOps";
import {Link} from "@carbon/react";

export function usePatientList() {
const [filteredData, setFilteredData] = useState<[]>([]);
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [currentPaginationState, setCurrentPaginationState] = useState({
size: 50,
page: 0
});
const [dateRange, setDateRange] = React.useState({
start: `01-01-${new Date().getFullYear()}`,
end: `${new Date().getDate()}-${new Date().getMonth() + 1}-${new Date().getFullYear()}`
});

const fetcher = async (url: string) => {
const response = await openmrsFetch(url);
return response.json();
};
const getAllClients = async ({page, size}) => {
try {
if (page === 0) setLoading(true);

const { data, error } = useSWR(`/ws/fhir2/R4/Patient?_count=1000`, fetcher);
let startString =dateRange.start;
let endString =dateRange.end;

const filterData = ({ start = null, end = null }) => {
let filteredArray = data.entry;
if(typeof dateRange.start === "object"){
const dateObject = new Date(dateRange.start);
startString = getPaddedDateString(dateObject);
}

if (start && end) {
filteredArray = filteredArray.filter(
(item) =>
new Date(item.resource.meta.lastUpdated) >= new Date(start) &&
new Date(item.resource.meta.lastUpdated) <= new Date(end)
);
}
if(typeof dateRange.end === "object"){
const dateObject = new Date(dateRange.end);
endString = getPaddedDateString(dateObject)
}

filteredArray = filteredArray.map((item: any) => {
const givenName =
item?.resource?.name[0]?.given[0] +
(item?.resource?.name[0]?.given[1]
? " " + item.resource?.name[0]?.given[1]
: "");

const gender = item.resource.gender
? item.resource.gender.charAt(0).toUpperCase()
: "";

return {
fullName: givenName + " " + item.resource?.name[0]?.family,
age:
new Date().getFullYear() -
new Date(item.resource.birthDate).getFullYear(),
gender: gender,
openmrsID: item.resource?.identifier?.find(
(id) => id.type?.text === "OpenMRS ID"
)?.value,
opdNumber: item.resource?.identifier?.find(
(id) => id.type.text === "Unique OPD Number"
)?.value,
dateRegistered: new Date(
item.resource?.meta?.lastUpdated
).toLocaleDateString(),
timeRegistered: new Date(
item.resource?.meta?.lastUpdated
).toLocaleTimeString(),
};
});

filteredArray.sort((a, b) => {
const dateA = new Date(a.dateRegistered + " " + a.timeRegistered);
const dateB = new Date(b.dateRegistered + " " + b.timeRegistered);
return (dateB as unknown as number) - (dateA as unknown as number);
});
const url = `/ws/rest/v1/ehospital/allClients?startDate=${startString}&endDate=${endString}&page=${page}&size=${size}`;
const {data} = await openmrsFetch(url);

setFilteredData(filteredArray);
};
if (data.results.length > 0) {
setData(prev => [...prev, ...data.results.map(result => ({
...result,
fullName: result?.name,
age: result?.age,
gender: result?.sex,
openmrsID: result.identifiers.find(item => item.identifierType.toLowerCase()?.includes("openmrs"))?.identifier,
opdNumber: result.identifiers.find(item => item.identifierType.toLowerCase()?.includes("opd"))?.identifier,
}))]);
}

if (data.results.length === size)
setCurrentPaginationState(prev => ({
...prev,
page: ++prev.page
}))

} catch (e) {
return e
} finally {
setLoading(false);
}
}


useEffect(() => {
getAllClients({...currentPaginationState})
}, [currentPaginationState.page]);

useEffect(() => {
if (data?.entry) filterData({});
}, [data]);
setCurrentPaginationState(prev => ({...prev, page: 0}))
setData([]);
getAllClients({...currentPaginationState})
}, [dateRange]);

const tableColumns = [
{
name: "Name",
selector: (row) => row.fullName,
cell: (row) => (
<Link
href={`${window.getOpenmrsSpaBase()}patient/${
row.uuid
}/chart/Patient%20Summary`}
>
{row.fullName}
</Link>
),
},
{
name: "ID",
Expand Down Expand Up @@ -99,6 +110,15 @@ export function usePatientList() {
},
];


const clear = () => {
setDateRange({
start: `01-01-${new Date().getFullYear()}`,
end: `${new Date().getDate()}-${new Date().getMonth() + 1}-${new Date().getFullYear()}`
});
setData([]);
getAllClients({...currentPaginationState})
};
const customStyles = {
cells: {
style: {
Expand All @@ -118,10 +138,13 @@ export function usePatientList() {
return {
customStyles,
tableColumns,
filterData,
filteredData,
data,
patient: data,
isLoading: !error && !data,
isError: error,
isLoading: loading,
dateRange,
setDateRange,
getAllClients,
currentPaginationState,
clear
};
}
Loading

0 comments on commit ef2707e

Please sign in to comment.