Skip to content

Commit

Permalink
Send patient-view hook on page load and add refresh button to resend …
Browse files Browse the repository at this point in the history
…patient-view hook
  • Loading branch information
jtquach1 committed Nov 20, 2023
1 parent 4d6d119 commit 3b0faab
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 73 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Development URLS

REACT_APP_REMS_ADMIN_SERVER_BASE = http://localhost:8090
REACT_APP_REMS_HOOKS_PATH = /cds-services/rems-order-select
REACT_APP_REMS_HOOKS_PATH = /cds-services/rems-
REACT_APP_PHARMACY_SERVER_BASE = http://localhost:5051
REACT_APP_ETASU_STATUS_ENABLED = true
REACT_APP_PHARMACY_STATUS_ENABLED = true
Expand Down
92 changes: 26 additions & 66 deletions src/views/Patient/MedReqDropDown/MedReqDropDown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import RefreshIcon from '@mui/icons-material/Refresh';
import Box from '@mui/material/Box';
import axios from 'axios';
import { BundleEntry, Patient, MedicationRequest, Practitioner } from 'fhir/r4';
import { BundleEntry, Patient, MedicationRequest, Practitioner, Resource } from 'fhir/r4';
import Client from 'fhirclient/lib/Client';
import { ReactElement, useEffect, useState } from 'react';
import example from '../../../cds-hooks/prefetch/exampleHookService.json'; // TODO: Replace with request to CDS service
Expand All @@ -34,88 +34,63 @@ import EtasuStatus from './etasuStatus/EtasuStatus';
// Adding in Pharmacy
import PharmacyStatus from './pharmacyStatus/PharmacyStatus';
import sendRx from './rxSend/rxSend';

interface MedicationBundle {
data: MedicationRequest[];
reference: Patient;
}
import { HooksAction, MedicationBundle } from '../PatientView';

interface MedReqDropDownProps {
tabCallback: (n: ReactElement, m: string, o: string) => void;
client: Client;
hooksCards: HooksCard[];
setHooksCards: React.Dispatch<HooksAction>;
medication: MedicationBundle | null;
patient: Patient | null;
user: string | null;
practitioner: Practitioner | null;
getFhirResource: (token: string) => Promise<Resource>;
}
function MedReqDropDown(props: MedReqDropDownProps) {
const client = props.client;

function getFhirResource(token: string) {
console.log('getFhirResource: ' + token);
return props.client.request(token).then((e: any) => {
return e;
});
}

function MedReqDropDown({
tabCallback,
client,
hooksCards,
setHooksCards,
medication,
patient,
user,
practitioner,
getFhirResource
}: MedReqDropDownProps) {
//For dropdown UI
const [selectedOption, setSelectedOption] = useState<string>('');

const handleOptionSelect = (event: SelectChangeEvent<string>) => {
setSelectedOption(event.target.value as string);
};

//Prefetch
const [patient, setPatient] = useState<Patient | null>(null);

const [user, setUser] = useState<string | null>(null);

const [practitioner, setPractitioner] = useState<Practitioner | null>(null);

//CDSHooks
const [cdsHook, setCDSHook] = useState<Hook | null>(null);

//Cards
const [hooksCards, setHooksCards] = useState<HooksCard[]>([]);

//ETASU
const [showEtasu, setShowEtasu] = useState<boolean>(false);

// Pharmacy
const [showPharmacy, setShowPharmacy] = useState<boolean>(false);

const [sendRxEnabled, setSendRxEnabled] = useState<boolean>(false);
useEffect(() => {
client.patient.read().then((patient: any) => setPatient(patient));
if (client.user.id) {
setUser(client.user.id);
client.user.read().then(response => {
const practitioner = response as Practitioner;
setPractitioner(practitioner);
});
} else {
const appContextString = client.state?.tokenResponse?.appContext;
const appContext: { [key: string]: string } = {};
appContextString.split('&').map((e: string) => {
const temp: string[] = e.split('=');
appContext[temp[0]] = temp[1];
});
setUser(appContext?.user);
}
}, [client.patient, client]);

useEffect(() => {
getMedicationRequest();
}, []);

//CDS-Hook Request to REMS-Admin for cards
const submitToREMS = () => {
const hookType = (cdsHook && cdsHook.hook) || 'NO_SUCH_HOOK';
axios({
method: 'post',
url:
`${env.get('REACT_APP_REMS_ADMIN_SERVER_BASE').asString()}` +
`${env.get('REACT_APP_REMS_HOOKS_PATH').asString()}`,
`${env.get('REACT_APP_REMS_HOOKS_PATH').asString()}` +
hookType,
data: cdsHook
}).then(
response => {
console.log(response.data.cards); // cards for REMS-333
setHooksCards(response.data.cards);
console.log(response.data.cards);
setHooksCards({ type: 'replace', value: response.data.cards });
},
error => {
console.log(error);
Expand Down Expand Up @@ -152,21 +127,6 @@ function MedReqDropDown(props: MedReqDropDownProps) {
}
};

// MedicationRequest Prefetching Bundle
const [medication, setMedication] = useState<MedicationBundle | null>(null);

const getMedicationRequest = () => {
client
.request(`MedicationRequest?subject=Patient/${client.patient.id}`, {
resolveReferences: ['subject', 'performer'],
graph: false,
flat: true
})
.then((result: MedicationBundle) => {
setMedication(result);
});
};

const [selectedMedicationCardBundle, setSelectedMedicationCardBundle] =
useState<BundleEntry<MedicationRequest>>();

Expand Down Expand Up @@ -348,7 +308,7 @@ function MedReqDropDown(props: MedReqDropDownProps) {
name={medicationName}
tabIndex={tabIndex}
setTabIndex={setTabIndex}
tabCallback={props.tabCallback}
tabCallback={tabCallback}
/>
)}
</Grid>
Expand Down
153 changes: 147 additions & 6 deletions src/views/Patient/PatientView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,151 @@ import {
Card,
CardContent,
Grid,
IconButton,
Table,
TableBody,
TableCell,
TableContainer,
TableRow,
Typography
} from '@mui/material';
import { Patient } from 'fhir/r4';
import RefreshIcon from '@mui/icons-material/Refresh';
import { MedicationRequest, Patient, Practitioner } from 'fhir/r4';
import Client from 'fhirclient/lib/Client';
import { ReactElement, useEffect, useState } from 'react';
import { ReactElement, useEffect, useReducer, useState } from 'react';
import MedReqDropDown from './MedReqDropDown/MedReqDropDown';
import './PatientView.css';
import { Hook, Card as HooksCard } from '../../cds-hooks/resources/HookTypes';
import axios from 'axios';
import * as env from 'env-var';
import PatientViewHook from '../../cds-hooks/resources/PatientView';
import { hydrate } from '../../cds-hooks/prefetch/PrefetchHydrator';
import example from '../../cds-hooks/prefetch/exampleHookService.json'; // TODO: Replace with request to CDS service

interface PatientViewProps {
client: Client;
tabCallback: (n: ReactElement, m: string, o: string) => void;
}

export interface MedicationBundle {
data: MedicationRequest[];
reference: Patient;
}

export type HooksAction = {
type: 'replace' | 'append';
value: HooksCard[];
};

function reducer(state: HooksCard[], action: HooksAction): HooksCard[] {
switch (action.type) {
case 'replace':
return action.value;
case 'append':
return [...state, ...action.value];
default:
return state;
}
}

function PatientView(props: PatientViewProps) {
function getFhirResource(token: string) {
console.log('getFhirResource: ' + token);
return client.request(token).then((e: any) => {
return e;
});
}

const client = props.client;

const [hooksCards, setHooksCards] = useReducer(reducer, [] as HooksCard[]);

const [cdsHook, setCDSHook] = useState<Hook | null>(null);

//Prefetch
const [patient, setPatient] = useState<Patient | null>(null);

const [user, setUser] = useState<string | null>(null);

const [practitioner, setPractitioner] = useState<Practitioner | null>(null);

useEffect(() => {
client.patient.read().then((patient: any) => setPatient(patient));
if (client.user.id) {
setUser(client.user.id);
client.user.read().then(response => {
const practitioner = response as Practitioner;
setPractitioner(practitioner);
});
} else {
const appContextString = client.state?.tokenResponse?.appContext;
const appContext: { [key: string]: string } = {};
appContextString.split('&').map((e: string) => {
const temp: string[] = e.split('=');
appContext[temp[0]] = temp[1];
});
setUser(appContext?.user);
}
}, [client.patient, client]);

useEffect(() => {
if (patient && patient.id && user) {
const hook = new PatientViewHook(patient.id, user);
const tempHook = hook.generate();

hydrate(getFhirResource, example.prefetch, tempHook).then(() => {
setCDSHook(tempHook);
});
}
}, [patient, user]);

const submitToREMS = () => {
const hookType = (cdsHook && cdsHook.hook) || 'NO_SUCH_HOOK';
axios({
method: 'post',
url:
`${env.get('REACT_APP_REMS_ADMIN_SERVER_BASE').asString()}` +
`${env.get('REACT_APP_REMS_HOOKS_PATH').asString()}` +
hookType,
data: cdsHook
}).then(
response => {
console.log(response.data.cards);
setHooksCards({ type: 'append', value: response.data.cards });
// should I append the order-sign cards on top of the patient-view cards?
// or no, just reuse the GUI element but keep the two types of hooks' cards alone
},
error => {
console.log(error);
}
);
};

useEffect(() => {
if (cdsHook) {
submitToREMS();
}
}, [cdsHook]);

// MedicationRequest Prefetching Bundle
const [medication, setMedication] = useState<MedicationBundle | null>(null);

const getMedicationRequest = () => {
client
.request(`MedicationRequest?subject=Patient/${client.patient.id}`, {
resolveReferences: ['subject', 'performer'],
graph: false,
flat: true
})
.then((result: MedicationBundle) => {
setMedication(result);
});
};

useEffect(() => {
getMedicationRequest();
}, []);

useEffect(() => {
client.patient.read().then((patient: any) => setPatient(patient));
}, [client.patient, client]);
Expand Down Expand Up @@ -53,9 +175,18 @@ function PatientView(props: PatientViewProps) {
{patient ? (
<Card sx={{ bgcolor: 'white' }}>
<CardContent>
<Typography component="h1" variant="h5">
Patient information loaded from patient context
</Typography>
<Grid container>
<Grid item xs={10} sm={11} md={12} lg={10} alignSelf="center">
<Typography component="h1" variant="h5">
Patient information loaded from patient context
</Typography>
</Grid>
<Grid item xs={2} sm={1} md={12} lg={2}>
<IconButton color="primary" onClick={submitToREMS} size="large">
<RefreshIcon fontSize="large" />
</IconButton>
</Grid>
</Grid>
<TableContainer>
<Table>
<TableBody>
Expand All @@ -80,7 +211,17 @@ function PatientView(props: PatientViewProps) {
</Grid>
<Grid item xs={12} md={8}>
{client ? (
<MedReqDropDown client={client} tabCallback={props.tabCallback} />
<MedReqDropDown
client={client}
tabCallback={props.tabCallback}
hooksCards={hooksCards}
setHooksCards={setHooksCards}
medication={medication}
patient={patient}
user={user}
practitioner={practitioner}
getFhirResource={getFhirResource}
/>
) : (
<p>Loading medication request...</p>
)}
Expand Down

0 comments on commit 3b0faab

Please sign in to comment.