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

MF-641: Patient List Modal #22

Closed
64 changes: 36 additions & 28 deletions packages/esm-patient-list-app/src/AddPatientToList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,62 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useMemo, useCallback } from 'react';
import Search from 'carbon-components-react/lib/components/Search';
import Button from 'carbon-components-react/lib/components/Button';
import Checkbox from 'carbon-components-react/lib/components/Checkbox';
import { usePatientListData } from '../patientListData';
import { useTranslation } from 'react-i18next';
import styles from './add-patient-to-list.scss';

import { OpenmrsCohort, addPatientToList } from '../patientListData/api';
import { OpenmrsCohort, addPatientToList, getPatientListsForPatient } from '../patientListData/api';
import SkeletonText from 'carbon-components-react/es/components/SkeletonText';
import { toOmrsIsoString } from '@openmrs/esm-framework';

const CheckboxedPatientList = ({ name, uuid, checked, handleChange }) => {
return (
<div className={styles.checkbox}>
<Checkbox checked={checked} labelText={name} id={uuid} onChange={(e) => handleChange(uuid, e)} />
</div>
);
};

const AddPatient: React.FC<{ close: () => void; patientUuid: string }> = ({ close, patientUuid }) => {
const { t } = useTranslation();
const [searchValue, setSearchValue] = React.useState('');
const { loading, data } = usePatientListData(undefined, undefined, undefined, searchValue);
const [searchValue, setSearchValue] = useState('');
const { loading, data } = usePatientListData(undefined, undefined, undefined, undefined);
const [selectedLists, setSelectedList] = useState({});

useEffect(() => {
const lists = {};
if (data) {
data.map((patientList, ind) => {
data.map((patientList) => {
lists[patientList.uuid] = false;
});
}
setSelectedList(lists);
}, [data]);

const handleChange = (uuid, e) => {
const searchResults = useMemo(() => {
if (data) {
if (searchValue && searchValue.trim() !== '') {
const search = searchValue.toLowerCase();
return data.filter((patientList) => patientList.name.toLowerCase().includes(search));
} else {
return data;
}
} else {
return [];
}
}, [searchValue, data]);

const handleChange = useCallback((uuid, e) => {
setSelectedList((selectedLists) => ({
...selectedLists,
[uuid]: e,
}));
};
}, []);

const handleSubmit = () => {
const handleSubmit = useCallback(() => {
data.map((patientList) => {
if (selectedLists[patientList.uuid]) {
addPatientToList({
patient: 'b2f86b28-7998-4812-83a9-7f8ad3c47e66',
patient: patientUuid,
cohort: patientList.uuid,
startDate: toOmrsIsoString(new Date()),
});
}
});
};
}, []);

return (
<div className={styles.modalContent}>
@@ -65,6 +70,7 @@ const AddPatient: React.FC<{ close: () => void; patientUuid: string }> = ({ clos
<Search
style={{ backgroundColor: 'white', borderBottom: '1px solid #e0e0e0' }}
labelText={t('searchForList', 'Search for a list')}
placeholder="Filter list"
onChange={({ target }) => {
setSearchValue(target.value);
}}
@@ -79,16 +85,18 @@ const AddPatient: React.FC<{ close: () => void; patientUuid: string }> = ({ clos
<div className={styles.patientListList}>
<fieldset className="bx--fieldset">
<p className="bx--label">Patient Lists</p>
{!loading && data ? (
data.length > 0 ? (
data.map((patientList, ind) => (
<CheckboxedPatientList
key={ind}
handleChange={handleChange}
checked={selectedLists[patientList.uuid] === undefined}
name={patientList.name}
uuid={patientList.uuid}
/>
{!loading && searchResults ? (
searchResults.length > 0 ? (
searchResults.map((patientList, ind) => (
<div key={ind} className={styles.checkbox}>
<Checkbox
key={ind}
onChange={(e) => handleChange(patientList.uuid, e)}
checked={selectedLists[patientList.uuid]}
labelText={patientList.name}
id={patientList.uuid}
/>
</div>
))
) : (
<p className={styles.bodyLong01}>No patient list found</p>
8 changes: 5 additions & 3 deletions packages/esm-patient-list-app/src/patient-list-action.tsx
Original file line number Diff line number Diff line change
@@ -3,9 +3,11 @@ import { useTranslation } from 'react-i18next';
import Modal from './Modal';
import AddPatientToList from './AddPatientToList';

interface AddPastVisitOverflowMenuItemProps {}
interface AddPastVisitOverflowMenuItemProps {
patientUuid: string;
}

const AddPastVisitOverflowMenuItem: React.FC<AddPastVisitOverflowMenuItemProps> = () => {
const AddPastVisitOverflowMenuItem: React.FC<AddPastVisitOverflowMenuItemProps> = ({ patientUuid }) => {
const { t } = useTranslation();
const [modalOpen, setModalOpen] = React.useState(false);
const handleClick = React.useCallback(() => {
@@ -30,7 +32,7 @@ const AddPastVisitOverflowMenuItem: React.FC<AddPastVisitOverflowMenuItemProps>
</li>
{modalOpen && (
<Modal close={closeModal}>
<AddPatientToList close={closeModal} patientUuid="" />
<AddPatientToList close={closeModal} patientUuid={patientUuid} />
</Modal>
)}
</>
41 changes: 21 additions & 20 deletions packages/esm-patient-list-app/src/patientListData/api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Location, OpenmrsResource } from '@openmrs/esm-api';
import { Location, OpenmrsResource, openmrsFetch } from '@openmrs/esm-framework';
import { PATIENT_LIST_TYPE } from './types';

async function postData(url = '', data = {}) {
const response = await fetch(url, {
const response = await openmrsFetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
@@ -14,7 +14,7 @@ async function postData(url = '', data = {}) {
referrerPolicy: 'no-referrer',
body: JSON.stringify(data),
});
return response.json();
return response.data;
}

export interface OpenmrsCohort {
@@ -50,26 +50,33 @@ export async function getAllPatientLists(filter?: PATIENT_LIST_TYPE, stared?: bo
}: {
results: Array<OpenmrsCohort>;
error: Error;
} = await (await fetch('/openmrs/ws/rest/v1/cohortm/cohort?v=default')).json();
} = await (
await openmrsFetch<{ results: Array<OpenmrsCohort>; error: Error }>('/ws/rest/v1/cohortm/cohort?v=default')
).data;

if (error) throw error;

return results;
}

async function getPatientListMembers(cohortUuid: string) {
export async function getPatientListMembers(cohortUuid: string) {
const {
results,
error,
}: {
results: Array<OpenmrsCohortMember>;
error: Error;
} = await (await fetch(`/openmrs/ws/rest/v1/cohortm/cohortmember?cohort=${cohortUuid}&v=default`)).json();
} = await (
await openmrsFetch<{
results: Array<OpenmrsCohortMember>;
error: Error;
}>(`/ws/rest/v1/cohortm/cohortmember?cohort=${cohortUuid}&v=default`)
).data;

if (error) throw error;

const patients: Array<OpenmrsResource> = (
await fetch('/openmrs/ws/fhir2/R4/Patient/_search?_id=' + results.map((p) => p.patient.uuid).join(','), {
await openmrsFetch('/ws/fhir2/R4/Patient/_search?_id=' + results.map((p) => p.patient.uuid).join(','), {
method: 'POST',
}).then((res) => res.json())
).entry.map((e) => e.resource);
@@ -84,33 +91,27 @@ export async function getPatientListsForPatient(patientUuid: string) {
}: {
results: Array<OpenmrsCohortMember>;
error: Error;
} = await (await fetch(`/openmrs/ws/rest/v1/cohortm/cohortmember?patient=${patientUuid}&v=default`)).json();
} = await (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await await?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(the data is already resolved - no need for the outer await)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'll remove the outer one.

await openmrsFetch<{ results: Array<OpenmrsCohortMember>; error: Error }>(
`/ws/rest/v1/cohortm/cohortmember?patient=${patientUuid}&v=default`,
)
).data;

if (error) throw error;

return results;
}

export async function addPatientToList(data: { patient: string; cohort: string; startDate: string }) {
return postData('/openmrs/ws/rest/v1/cohortm/cohortmember', data);
return postData('/ws/rest/v1/cohortm/cohortmember', data);
}

export async function createPatientList(cohort: { name: string }) {
return postData('/openmrs/ws/rest/v1/cohortm/cohort', {
return postData('/ws/rest/v1/cohortm/cohort', {
...cohort,
cohortType: '6df786bf-f15a-49c2-8d2b-1832d961c270',
location: 'aff27d58-a15c-49a6-9beb-d30dcfc0c66e',
startDate: '2020-01-01',
groupCohort: true,
});
}

globalThis.api = {
createPatientList,
addPatientToList,
getPatientListMembers,
getAllPatientLists,
getPatientListsForPatient,
};

export default globalThis.api;