Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/patient list app pagination #28

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading