+ >
+ );
+};
+
+export default RequestBox;
diff --git a/src/components/SMARTBox/EHRLaunchBox.js b/src/components/SMARTBox/EHRLaunchBox.js
index d7095727..d6080865 100644
--- a/src/components/SMARTBox/EHRLaunchBox.js
+++ b/src/components/SMARTBox/EHRLaunchBox.js
@@ -1,33 +1,27 @@
-import React, { Component } from 'react';
-import { fhir } from '../../util/fhir';
+import React from 'react';
import './smart.css';
import env from 'env-var';
-export default class EHRLaunchBox extends Component {
- constructor(props) {
- super(props);
- this.state = {};
- }
-
- render() {
- return (
+const EHRLaunchBox = () => {
+ return (
+
+
EHR Launch Settings
-
EHR Launch Settings
-
-
Select EHR:
-
- Local
-
-
- Note: Only the local EHR is supported at this time for EHR launch
-
-
Username:
-
-
-
Password:
-
+
Select EHR:
+
+ Local
+
+
+ Note: Only the local EHR is supported at this time for EHR launch
+
Username:
+
+
+
Password:
+
- );
- }
-}
+
+ );
+};
+
+export default EHRLaunchBox;
diff --git a/src/components/SMARTBox/PatientBox.js b/src/components/SMARTBox/PatientBox.js
index 11a71519..8d8e4bf0 100644
--- a/src/components/SMARTBox/PatientBox.js
+++ b/src/components/SMARTBox/PatientBox.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { useEffect, useState } from 'react';
import { getAge, getDrugCodeFromMedicationRequest } from '../../util/fhir';
import './smart.css';
import { Button } from '@mui/material';
@@ -13,10 +13,9 @@ import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import { retrieveLaunchContext } from '../../util/util';
-export default class PatientBox extends Component {
- constructor(props) {
- super(props);
- this.state = {
+const PatientBox = (props) => {
+ const [state, setState] = useState(
+ {
request: '',
deviceRequests: {},
medicationRequests: {},
@@ -29,30 +28,40 @@ export default class PatientBox extends Component {
questionnaireTitles: {},
showMedications: false,
showQuestionnaires: false,
- numInProgressForms: 0
- };
+ numInProgressForms: 0,
+ name: 'N/A',
+ fullName: 'N/A',
+ formatBirthdate: '',
+ options: [],
+ responseOptions: []
+ }
+ );
+
+ const { patient, callback, clearCallback, defaultUser, client, callbackMap,
+ updatePrefetchCallback, responseExpirationDays, request, launchUrl } = props;
+
+ const medicationColumns = [
+ { id: 'name', label: 'Medication' },
+ { id: 'code', label: 'Request #' }
+ ];
+ const questionnaireColumns = [
+ { id: 'name', label: 'Title' },
+ { id: 'time', label: 'Created' }
+ ];
+ const medicationTooltip =
+ state.options.length === 0 ? 'No medications found.' : `${state.options.length} medications available`;
+ const formTooltip =
+ state.numInProgressForms === 0 ? 'No In-Progress Forms' : 'Open In-Progress Forms';
+
+ useEffect(() => {
- this.handleRequestChange = this.handleRequestChange.bind(this);
-
- this.updatePrefetchRequest = this.updatePrefetchRequest.bind(this);
- this.getDeviceRequest = this.getDeviceRequest.bind(this);
- this.getServiceRequest = this.getServiceRequest.bind(this);
- this.getMedicationRequest = this.getMedicationRequest.bind(this);
- this.getMedicationDispense = this.getMedicationDispense.bind(this);
- this.getRequests = this.getRequests.bind(this);
- this.getResponses = this.getResponses.bind(this);
- this.getQuestionnaireTitles = this.getQuestionnaireTitles.bind(this);
- this.makeQROption = this.makeQROption.bind(this);
- this.handleResponseChange = this.handleResponseChange.bind(this);
- }
-
- componentDidMount() {
// get requests and responses on open of patients
- this.getRequests();
- this.getResponses(); // TODO: PatientBox should not be rendering itself, needs to receive its state from parent
- }
+ getRequests();
+ getResponses(); // TODO: PatientBox should not be rendering itself, needs to receive its state from parent
+ getPatientInfo();
+ }, []);
- getCoding(resource) {
+ const getCoding =(resource) => {
let code = null;
if (resource.resourceType === 'DeviceRequest') {
code = resource?.codeCodeableConcept.coding[0];
@@ -84,10 +93,11 @@ export default class PatientBox extends Component {
};
}
return code;
- }
+ };
- makeOption(request, options) {
- const code = this.getCoding(request);
+ const makeOption = (request, options) => {
+ const code = getCoding(request);
+ const tempOptions = options;
let option = {
key: request.id,
@@ -96,61 +106,62 @@ export default class PatientBox extends Component {
name: code.display,
value: JSON.stringify(request)
};
- options.push(option);
- }
-
- updateValues(patient) {
- this.props.callback('patient', patient);
- this.props.callback('expanded', false);
- this.props.clearCallback();
- if (this.state.request) {
- const request = JSON.parse(this.state.request);
+ tempOptions.push(option);
+ setState(prevState => ({ ...prevState, options: tempOptions}));
+ };
+
+ const updateValues = (patient) => {
+ callback('patient', patient);
+ callback('expanded', false);
+ clearCallback();
+ if (state.request) {
+ const request = JSON.parse(state.request);
if (
request.resourceType === 'DeviceRequest' ||
request.resourceType === 'ServiceRequest' ||
request.resourceType === 'MedicationRequest' ||
request.resourceType === 'MedicationDispense'
) {
- this.updatePrefetchRequest(request, patient, this.props.defaultUser);
+ updatePrefetchRequest(request, patient, defaultUser);
} else {
- this.props.clearCallback();
+ clearCallback();
}
} else {
- this.updatePrefetchRequest(null, patient, this.props.defaultUser);
- this.props.callback('request', {});
- this.props.callback('code', null);
- this.props.callback('codeSystem', null);
- this.props.callback('display', null);
+ updatePrefetchRequest(null, patient, defaultUser);
+ callback('request', {});
+ callback('code', null);
+ callback('codeSystem', null);
+ callback('display', null);
}
- if (this.state.response) {
- const response = JSON.parse(this.state.response);
- this.updateQRResponse(response);
+ if (state.response) {
+ const response = JSON.parse(state.response);
+ updateQRResponse(response);
}
- }
+ };
- updatePatient(patient) {
- this.props.callback('patient', patient);
- }
+ const updatePatient = (patient) => {
+ callback('patient', patient);
+ };
- updateQRResponse(response) {
- this.props.callback('response', response);
- }
+ const updateQRResponse = (response) => {
+ callback('response', response);
+ };
- fetchResources(queries) {
- var requests = [];
- this.props.callback('prefetchCompleted', false);
+ const fetchResources = (queries) => {
+ let requests = [];
+ callback('prefetchCompleted', false);
queries.forEach((query, queryKey) => {
const urlQuery = '/' + query;
requests.push(
- this.props.client
+ client
.request(urlQuery)
.then(response => {
console.log(response);
return response;
})
.then(resource => {
- this.props.callbackMap('prefetchedResources', queryKey, resource);
+ callbackMap('prefetchedResources', queryKey, resource);
})
);
});
@@ -158,20 +169,20 @@ export default class PatientBox extends Component {
Promise.all(requests)
.then(() => {
console.log('fetchResourcesSync: finished');
- this.props.callback('prefetchCompleted', true);
+ callback('prefetchCompleted', true);
})
.catch(function (err) {
console.log('fetchResourcesSync: failed to wait for all the prefetch to populate');
console.log(err);
});
- }
+ };
- updatePrefetchRequest(request, patient, user) {
+ const updatePrefetchRequest = (request, patient, user) => {
const patientReference = 'Patient/' + patient?.id;
const userReference = 'Practitioner/' + user;
if (request) {
- this.props.callback(request.resourceType, request);
- const queries = this.props.updatePrefetchCallback(
+ callback(request.resourceType, request);
+ const queries = updatePrefetchCallback(
request,
patientReference,
userReference,
@@ -179,15 +190,15 @@ export default class PatientBox extends Component {
'patient',
'practitioner'
);
- this.fetchResources(queries);
+ fetchResources(queries);
- this.props.callback('request', request);
- const coding = this.getCoding(request);
- this.props.callback('code', coding.code);
- this.props.callback('codeSystem', coding.system);
- this.props.callback('display', coding.display);
+ callback('request', request);
+ const coding = getCoding(request);
+ callback('code', coding.code);
+ callback('codeSystem', coding.system);
+ callback('display', coding.display);
} else {
- const queries = this.props.updatePrefetchCallback(
+ const queries = updatePrefetchCallback(
request,
patientReference,
userReference,
@@ -195,36 +206,43 @@ export default class PatientBox extends Component {
'practitioner',
'medicationRequests'
);
- this.fetchResources(queries);
+ fetchResources(queries);
}
- }
+ };
- getDeviceRequest(patientId) {
- this.props.client
+ const getDeviceRequest = (patientId) => {
+ client
.request(`DeviceRequest?subject=Patient/${patientId}`, {
resolveReferences: ['subject', 'performer'],
graph: false,
flat: true
})
.then(result => {
- this.setState({ deviceRequests: result });
+ setState(prevState => ({...prevState, deviceRequests: result}));
+ // now take results and make option
+ result.data.forEach(e => {
+ makeOption(e, state.options);
+ });
});
- }
+ };
- getServiceRequest(patientId) {
- this.props.client
+ const getServiceRequest = (patientId) => {
+ client
.request(`ServiceRequest?subject=Patient/${patientId}`, {
resolveReferences: ['subject', 'performer'],
graph: false,
flat: true
})
.then(result => {
- this.setState({ serviceRequests: result });
+ setState(prevState => ({...prevState, serviceRequests: result}));
+ result.data.forEach(e => {
+ makeOption(e, state.options);
+ });
});
- }
+ };
- getMedicationRequest(patientId) {
- this.props.client
+ const getMedicationRequest = (patientId) => {
+ client
.request(`MedicationRequest?subject=Patient/${patientId}`, {
resolveReferences: ['subject', 'performer', 'medicationReference'],
graph: false,
@@ -262,34 +280,41 @@ export default class PatientBox extends Component {
}
}
});
-
- this.setState({ medicationRequests: result });
+ setState(prevState => ({...prevState, medicationRequests: result}));
+ result.data.forEach(e => {
+ makeOption(e, state.options);
+ });
});
- }
+ };
- getMedicationDispense(patientId) {
- this.props.client
+ const getMedicationDispense = (patientId) => {
+ client
.request(`MedicationDispense?subject=Patient/${patientId}`, {
resolveReferences: ['subject', 'performer'],
graph: false,
flat: true
})
.then(result => {
- this.setState({ medicationDispenses: result });
+ setState(prevState => ({...prevState, medicationDispenses: result}));
+ result.data.forEach(e => {
+ makeOption(e, state.options);
+ });
});
- }
+ };
- handleRequestChange(data, patient) {
+ const handleRequestChange = (data, patient) => {
if (data) {
- let coding = this.getCoding(JSON.parse(data));
- this.setState({
+ let coding = getCoding(JSON.parse(data));
+
+ setState(prevState => ({
+ ...prevState,
request: data,
code: coding.code,
system: coding.system,
display: coding.display,
response: ''
- });
- this.props.callback('response', '');
+ }));
+ callback('response', '');
// update prefetch request for the medication
const request = JSON.parse(data);
if (
@@ -298,128 +323,145 @@ export default class PatientBox extends Component {
request.resourceType === 'MedicationRequest' ||
request.resourceType === 'MedicationDispense'
) {
- this.updatePrefetchRequest(request, patient, this.props.defaultUser);
+ updatePrefetchRequest(request, patient, defaultUser);
} else {
- this.props.clearCallback();
+ clearCallback();
}
// close the accordian after selecting a medication, can change if we want to keep open
- this.props.callback('expanded', false);
+ callback('expanded', false);
} else {
- this.setState({
+ setState(prevState => ({
+ ...prevState,
request: ''
- });
+ }));
}
- }
+ };
- handleResponseChange(data) {
+ const handleResponseChange = (data) => {
if (data) {
- this.setState({
+ setState(prevState => ({
+ ...prevState,
response: data
- });
+ }));
const response = JSON.parse(data);
- this.updateQRResponse(response);
+ updateQRResponse(response);
} else {
- this.setState({
+ setState(prevState => ({
+ ...prevState,
response: ''
- });
+ }));
}
- }
+ };
- getRequests() {
- const patientId = this.props.patient.id;
- this.getDeviceRequest(patientId);
- this.getServiceRequest(patientId);
- this.getMedicationRequest(patientId);
- this.getMedicationDispense(patientId);
- }
+ const getRequests = () => {
+ const patientId = patient.id;
+ getDeviceRequest(patientId);
+ getServiceRequest(patientId);
+ getMedicationRequest(patientId);
+ getMedicationDispense(patientId);
+ };
/**
* Retrieve QuestionnaireResponse
*/
- getResponses() {
- const patientId = this.props.patient.id;
+ const getResponses = () => {
+ const patientId = patient.id;
let updateDate = new Date();
- updateDate.setDate(updateDate.getDate() - this.props.responseExpirationDays);
+ updateDate.setDate(updateDate.getDate() - responseExpirationDays);
const searchParameters = [
`_lastUpdated=gt${updateDate.toISOString().split('T')[0]}`,
'status=in-progress',
`subject=Patient/${patientId}`,
'_sort=-authored'
];
- this.props.client
+ client
.request(`QuestionnaireResponse?${searchParameters.join('&')}`, {
resolveReferences: ['subject'],
graph: false,
flat: true
})
.then(result => {
- this.setState({ questionnaireResponses: result });
- this.setState({ numInProgressForms: result.data.length });
- })
- .then(() => this.getQuestionnaireTitles());
- }
+ setState(prevState => ({
+ ...prevState,
+ questionnaireResponses: result,
+ numInProgressForms: result.data.length
+ }));
+ getQuestionnaireTitles(result);
+ });
+ };
- getQuestionnaireTitles() {
+ const getQuestionnaireTitles = (qResponse) => {
const promises = [];
- if (this.state.questionnaireResponses.data) {
- if (this.state.questionnaireResponses.data.length > 0) {
- for (const canonical of this.state.questionnaireResponses.data.map(
+ if (qResponse.data) {
+ if (qResponse.data.length > 0) {
+ for (const canonical of qResponse.data.map(
questionnaireResponse => questionnaireResponse.questionnaire
)) {
promises.push(
- this.props.client
+ client
.request(canonical)
.then(questionnaire => [canonical, questionnaire.title || canonical])
);
}
Promise.all(promises).then(pairs => {
- this.setState({ questionnaireTitles: Object.fromEntries(pairs) });
+ setState(prevState => ({
+ ...prevState, questionnaireTitles: Object.fromEntries(pairs) }));
+ // call get response options from here, to pass in the questionnaireResponses data and questionnaireTitles
+ // before state variables are set
+ getResponseOptions(qResponse.data, Object.fromEntries(pairs));
});
}
}
- }
+};
+
+ const getResponseOptions = (data, title) => {
+ const temp = data.map(qr => makeQROption(qr, title));
+ setState(prevState => ({
+ ...prevState,
+ responseOptions: temp
+ }));
+ };
- makeQROption(qr) {
- const questionnaireTitle = this.state.questionnaireTitles[qr.questionnaire];
- // const display = `${questionnaireTitle}: created at ${qr.authored}`;
+ const makeQROption = (qr, questionnaireTitles) => {
+ const questionnaireTitle = questionnaireTitles[qr.questionnaire];
return {
key: qr.id,
text: questionnaireTitle,
time: qr.authored,
value: JSON.stringify(qr)
};
- }
+ };
- isOrderNotSelected() {
- return Object.keys(this.props.request).length === 0;
- }
+ const isOrderNotSelected = () => {
+ return Object.keys(request).length === 0;
+ };
/**
* Launch In progress Form
*/
- relaunch = data => {
- this.handleResponseChange(data);
- this.props.callback('expanded', false);
- this.buildLaunchLink(data).then(link => {
+ const relaunch = data => {
+ handleResponseChange(data);
+ callback('expanded', false);
+ buildLaunchLink(data).then(link => {
//e.preventDefault();
window.open(link.url, '_blank');
});
};
- async buildLaunchLink(data) {
+ const buildLaunchLink = async (data) => {
// build appContext and URL encode it
let appContext = '';
let order = undefined,
coverage = undefined,
response = undefined;
- if (!this.isOrderNotSelected()) {
- if (Object.keys(this.props.request).length > 0) {
- order = `${this.props.request.resourceType}/${this.props.request.id}`;
- if (this.props.request.insurance && this.props.request.insurance.length > 0) {
- coverage = `${this.props.request.insurance[0].reference}`;
+ if (!isOrderNotSelected()) {
+ if (Object.keys(request).length > 0) {
+ order = `${request.resourceType}/${request.id}`;
+ if (request.insurance && request.insurance.length > 0) {
+ coverage = `${request.insurance[0].reference}`;
}
}
}
@@ -447,21 +489,21 @@ export default class PatientBox extends Component {
const link = {
appContext: encodeURIComponent(appContext),
type: 'smart',
- url: this.props.launchUrl
+ url: launchUrl
};
let linkCopy = Object.assign({}, link);
const result = await retrieveLaunchContext(
linkCopy,
- this.props.patient.id,
- this.props.client.state
+ patient.id,
+ client.state
);
linkCopy = result;
return linkCopy;
- }
+ };
- makeResponseTable(columns, options, type, patient) {
+ const makeResponseTable = (columns, options, type, patient) => {
return (
this.handleRequestChange(row.value, patient)}
+ onClick={() => handleRequestChange(row.value, patient)}
>
{row.name}
@@ -497,9 +539,9 @@ export default class PatientBox extends Component {
);
- }
+ };
- makeQuestionnaireTable(columns, options, type, patient) {
+ const makeQuestionnaireTable = (columns, options, type, patient) => {
return (
{options.map(row => (
-
+
this.relaunch(row.value)}
+ onClick={() => relaunch(row.value)}
className="hover-row"
>
@@ -536,172 +578,123 @@ export default class PatientBox extends Component {
);
- }
+ };
- render() {
- const patient = this.props.patient;
- if (!patient) {
- return <>>;
- }
- let name = '';
- let fullName = '';
- let formatBirthdate = '';
+ const getPatientInfo = () => {
if (patient.name) {
- name =
{`${patient.name[0].given[0]} ${patient.name[0].family}`} ;
- fullName =
{`${patient.name[0].given.join(' ')} ${patient.name[0].family}`} ;
+ setState(prevState => ({ ...prevState, name: `${patient.name[0].given[0]} ${patient.name[0].family}`}));
+ setState(prevState => ({ ...prevState, fullName: `${patient.name[0].given.join(' ')} ${patient.name[0].family}`}));
}
if (patient.birthDate) {
- formatBirthdate = new Date(patient.birthDate).toDateString();
- }
-
- // add all of the requests to the list of options
- let options = [];
- let responseOptions = [];
- if (this.state.deviceRequests.data) {
- this.state.deviceRequests.data.forEach(e => {
- this.makeOption(e, options);
- });
- }
- if (this.state.serviceRequests.data) {
- this.state.serviceRequests.data.forEach(e => {
- this.makeOption(e, options);
- });
- }
- if (this.state.medicationRequests.data) {
- this.state.medicationRequests.data.forEach(e => {
- this.makeOption(e, options);
- });
+ setState(prevState => ({ ...prevState, formatBirthdate: new Date(patient.birthDate).toDateString()}));
}
+ };
- if (this.state.medicationDispenses.data) {
- this.state.medicationDispenses.data.forEach(e => {
- this.makeOption(e, options);
- });
- }
-
- if (this.state.questionnaireResponses.data) {
- responseOptions = this.state.questionnaireResponses.data.map(qr => this.makeQROption(qr));
- }
-
- const medicationColumns = [
- { id: 'name', label: 'Medication' },
- { id: 'code', label: 'Request #' }
- ];
-
- const questionnaireColumns = [
- { id: 'name', label: 'Title' },
- { id: 'time', label: 'Created' }
- ];
-
- const medicationTooltip =
- options.length === 0 ? 'No medications found.' : `${options.length} medications available`;
- const formTooltip =
- this.state.numInProgressForms === 0 ? 'No In-Progress Forms' : 'Open In-Progress Forms';
-
- return (
-
-
- {name ? name : 'N/A'} {' '}
- {`(ID: ${patient.id})`}
-
-
-
-
- Full Name : {fullName}
-
-
- Gender :{' '}
- {patient.gender.charAt(0).toUpperCase() + patient.gender.slice(1)}
-
-
- DoB/Age : {formatBirthdate} (
- {getAge(patient.birthDate)} years old)
-
+ return (
+
+
+ {state.name} {' '}
+ {`(ID: ${patient.id})`}
+
+
+
+
+ Full Name : {state.fullName}
-
- {this.state.showMedications ? (
-
}
- onClick={() => this.setState({ showMedications: false })}
- >
- Close Medications
-
- ) : (
-
-
- }
- disabled={options.length === 0}
- onClick={() => {
- this.updatePatient(patient);
- this.setState({ showMedications: true, showQuestionnaires: false });
- }}
- >
- Request New Medication
-
-
-
- )}
- {this.state.showQuestionnaires ? (
-
}
- onClick={() => this.setState({ showQuestionnaires: false })}
- >
- Close In Progress Forms
-
- ) : (
-
-
- }
- disabled={this.state.numInProgressForms === 0}
- onClick={() => {
- this.updatePatient(patient);
- this.setState({ showQuestionnaires: true, showMedications: false });
- }}
- >
- {this.state.numInProgressForms} Form(s) In Progress
-
-
-
- )}
+
+ Gender :{' '}
+ {patient.gender.charAt(0).toUpperCase() + patient.gender.slice(1)}
+
+
+ DoB/Age : {state.formatBirthdate} (
+ {getAge(patient.birthDate)} years old)
+
+
+
+ {state.showMedications ? (
this.updateValues(patient)}
+ className="big-button"
+ startIcon={ }
+ onClick={() => setState(prevState => ({ ...prevState, showMedications: false }))}
>
- Select Patient
+ Close Medications
-
+ ) : (
+
+
+ }
+ disabled={state.options.length === 0}
+ onClick={() => {
+ updatePatient(patient);
+ setState(prevState => ({ ...prevState, showMedications: true, showQuestionnaires: false }));
+ }}
+ >
+ Request New Medication
+
+
+
+ )}
+ {state.showQuestionnaires ? (
+
}
+ onClick={() => setState(prevState => ({...prevState, showQuestionnaires: false }))}
+ >
+ Close In Progress Forms
+
+ ) : (
+
+
+ }
+ disabled={state.numInProgressForms === 0}
+ onClick={() => {
+ updatePatient(patient);
+ setState(prevState => ({ ...prevState, showQuestionnaires: true, showMedications: false }));
+ }}
+ >
+ {state.numInProgressForms} Form(s) In Progress
+
+
+
+ )}
+
updateValues(patient)}
+ >
+ Select Patient
+
- {this.state.showMedications ? (
-
- {this.makeResponseTable(medicationColumns, options, 'medication', patient)}
-
- ) : (
-
- )}
- {this.state.showQuestionnaires ? (
-
- {this.makeQuestionnaireTable(
- questionnaireColumns,
- responseOptions,
- 'questionnaire',
- patient
- )}
-
- ) : (
-
- )}
- );
- }
-}
+ {state.showMedications ? (
+
+ {makeResponseTable(medicationColumns, state.options, 'medication', patient)}
+
+ ) : (
+
+ )}
+ {state.showQuestionnaires ? (
+
+ {makeQuestionnaireTable(
+ questionnaireColumns,
+ state.responseOptions,
+ 'questionnaire',
+ patient
+ )}
+
+ ) : (
+
+ )}
+
+ );
+};
+
+export default PatientBox;
\ No newline at end of file
diff --git a/src/containers/RequestBuilder.js b/src/containers/RequestBuilder.js
index 7904d594..ce568aa7 100644
--- a/src/containers/RequestBuilder.js
+++ b/src/containers/RequestBuilder.js
@@ -1,67 +1,66 @@
-import React, { Component } from 'react';
-import { Button, Box, Grid, IconButton, Modal, DialogTitle } from '@mui/material';
+import React, { useState, useEffect } from 'react';
+import { Button, Box, Grid, IconButton } from '@mui/material';
import PersonIcon from '@mui/icons-material/Person';
import RefreshIcon from '@mui/icons-material/Refresh';
-import PersonSearchIcon from '@mui/icons-material/PersonSearch';
import DisplayBox from '../components/DisplayBox/DisplayBox';
import '../index.css';
import RequestBox from '../components/RequestBox/RequestBox';
import buildRequest from '../util/buildRequest.js';
-import { types, defaultValues as codeValues, headerDefinitions } from '../util/data.js';
+import { types } from '../util/data.js';
import { createJwt } from '../util/auth';
-import env from 'env-var';
-import FHIR from 'fhirclient';
import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
import AccordionDetails from '@mui/material/AccordionDetails';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
-import SettingsIcon from '@mui/icons-material/Settings';
import PatientSearchBar from '../components/RequestBox/PatientSearchBar/PatientSearchBar';
import { MedicationStatus } from '../components/MedicationStatus/MedicationStatus.jsx';
import { actionTypes } from './ContextProvider/reducer.js';
import axios from 'axios';
-export default class RequestBuilder extends Component {
- constructor(props) {
- super(props);
- this.state = {
- loading: false,
- logs: [],
- patient: {},
- expanded: true,
- patientList: [],
- response: {},
- code: null,
- codeSystem: null,
- display: null,
- prefetchedResources: new Map(),
- request: {},
- showSettings: false,
- token: null,
- client: this.props.client,
- medicationDispense: null,
- lastCheckedMedicationTime: null
- };
+const RequestBuilder = (props) => {
+ const { globalState, dispatch, client } = props;
+ const [state, setState] = useState({
+ loading: false,
+ patient: {},
+ expanded: true,
+ patientList: [],
+ response: {},
+ code: null,
+ codeSystem: null,
+ display: null,
+ prefetchedResources: new Map(),
+ request: {},
+ showSettings: false,
+ token: null,
+ client: client,
+ medicationDispense: null,
+ lastCheckedMedicationTime: null
+ });
+ const displayRequestBox = !!globalState.patient?.id;
- this.updateStateElement = this.updateStateElement.bind(this);
- this.submitInfo = this.submitInfo.bind(this);
- this.consoleLog = this.consoleLog.bind(this);
- this.takeSuggestion = this.takeSuggestion.bind(this);
- this.requestBox = React.createRef();
- }
+ const isOrderNotSelected = () => {
+ return Object.keys(state.request).length === 0;
+ };
- getMedicationStatus = () => {
- this.setState({ lastCheckedMedicationTime: Date.now() });
+ const disableGetMedicationStatus = isOrderNotSelected() || state.loading;
+ const getMedicationStatus = () => {
+ setState(prevState => ({
+ ...prevState,
+ lastCheckedMedicationTime: Date.now()
+ }));
axios
.get(
- `${this.props.globalState.ehrUrl}/MedicationDispense?prescription=${this.state.request.id}`
+ `${globalState.ehrUrl}/MedicationDispense?prescription=${state.request.id}`
)
.then(
response => {
const bundle = response.data;
- this.setState({ medicationDispense: bundle.entry?.[0].resource });
+ setState(prevState => ({
+ ...prevState,
+ medicationDispense: bundle.entry?.[0].resource
+ }));
},
error => {
console.log('Was not able to get medication status', error);
@@ -69,97 +68,78 @@ export default class RequestBuilder extends Component {
);
};
- componentDidMount() {
- if (!this.state.client) {
- this.reconnectEhr();
- } else {
+ useEffect(() => {
+ if (state.client) {
// Call patients on load of page
- this.getPatients();
- this.props.dispatch({
+ getPatients();
+ dispatch({
type: actionTypes.updateSetting,
settingId: 'baseUrl',
- value: this.state.client.state.serverUrl
+ value: state.client.state.serverUrl
});
- this.props.dispatch({
+ dispatch({
type: actionTypes.updateSetting,
settingId: 'ehrUrl',
- value: this.state.client.state.serverUrl
+ value: state.client.state.serverUrl
});
}
- }
-
- consoleLog(content, type) {
- console.log(content);
- let jsonContent = {
- content: content,
- type: type
- };
- this.setState(prevState => ({
- logs: [...prevState.logs, jsonContent]
- }));
- }
+ }, []);
- updateStateElement = (elementName, text) => {
+ const updateStateElement = (elementName, text) => {
if (elementName === 'patient') {
- this.props.dispatch({
+ dispatch({
type: actionTypes.updatePatient,
value: text
});
} else {
- this.setState({ [elementName]: text });
+ setState(prevState => ({
+ ...prevState,
+ [elementName]: text
+ }));
}
- // if the patientFhirQuery is updated, make a call to get the patients
- if (elementName === 'patientFhirQuery') {
- setTimeout(() => {
- this.getPatients();
- }, 1000);
- }
- };
-
- timeout = time => {
- let controller = new AbortController();
- setTimeout(() => controller.abort(), time * 1000);
- return controller;
};
- submitInfo(prefetch, request, patient, hook) {
- this.setState({ loading: true });
- this.consoleLog('Initiating form submission', types.info);
- this.setState({ patient });
+ const submitInfo = (prefetch, request, patient, hook) => {
+ console.log('Initiating form submission ', types.info);
+ setState(prevState => ({
+ ...prevState,
+ loading: true,
+ patient
+ }));
const hookConfig = {
- includeConfig: this.props.globalState.includeConfig,
- alternativeTherapy: this.props.globalState.alternativeTherapy
+ includeConfig: globalState.includeConfig,
+ alternativeTherapy: globalState.alternativeTherapy
};
- let user = this.props.globalState.defaultUser;
+ let user = globalState.defaultUser;
let json_request = buildRequest(
request,
user,
patient,
- this.props.globalState.ehrUrlSentToRemsAdminForPreFetch,
- this.state.client.state.tokenResponse,
+ globalState.ehrUrlSentToRemsAdminForPreFetch,
+ state.client.state.tokenResponse,
prefetch,
- this.props.globalState.sendPrefetch,
+ globalState.sendPrefetch,
hook,
hookConfig
);
- let cdsUrl = this.props.globalState.cdsUrl;
+ let cdsUrl =globalState.cdsUrl;
if (hook === 'order-sign') {
- cdsUrl = cdsUrl + '/' + this.props.globalState.orderSign;
+ cdsUrl = cdsUrl + '/' + globalState.orderSign;
} else if (hook === 'order-select') {
- cdsUrl = cdsUrl + '/' + this.props.globalState.orderSelect;
+ cdsUrl = cdsUrl + '/' + globalState.orderSelect;
} else if (hook === 'patient-view') {
- cdsUrl = cdsUrl + '/' + this.props.globalState.patientView;
+ cdsUrl = cdsUrl + '/' + globalState.patientView;
} else {
- this.consoleLog("ERROR: unknown hook type: '", hook, "'");
+ console.log("ERROR: unknown hook type: '", hook);
return;
}
- let baseUrl = this.props.globalState.baseUrl;
+ let baseUrl = globalState.baseUrl;
const headers = {
'Content-Type': 'application/json'
};
- if (this.props.globalState.generateJsonToken) {
+ if (globalState.generateJsonToken) {
const jwt = 'Bearer ' + createJwt(baseUrl, cdsUrl);
headers.authorization = jwt;
}
@@ -168,198 +148,178 @@ export default class RequestBuilder extends Component {
fetch(cdsUrl, {
method: 'POST',
headers: new Headers(headers),
- body: JSON.stringify(json_request),
- signal: this.timeout(10).signal //Timeout set to 10 seconds
+ body: JSON.stringify(json_request)
})
.then(response => {
- clearTimeout(this.timeout);
response.json().then(fhirResponse => {
console.log(fhirResponse);
if (fhirResponse?.status) {
- this.consoleLog(
- 'Server returned status ' + fhirResponse.status + ': ' + fhirResponse.error,
- types.error
- );
- this.consoleLog(fhirResponse.message, types.error);
+ console.log('Server returned status ' + fhirResponse.status + ': ' + fhirResponse.error);
+ console.log(fhirResponse.message);
} else {
- this.setState({ response: fhirResponse });
+ setState(prevState => ({ ...prevState, response: fhirResponse }));
}
- this.setState({ loading: false });
+ setState(prevState => ({ ...prevState, loading: false }));
});
})
.catch(() => {
- this.consoleLog('No response received from the server', types.error);
- this.setState({ response: {} });
- this.setState({ loading: false });
+ console.log('No response received from the server', types.error);
+ setState(prevState => ({ ...prevState, response: {}, loading: false }));
});
} catch (error) {
- this.setState({ loading: false });
- this.consoleLog('Unexpected error occurred', types.error);
+
+ setState(prevState => ({ ...prevState, loading: false }));
+ console.log('Unexpected error occurred', types.error);
if (error instanceof TypeError) {
- this.consoleLog(error.name + ': ' + error.message, types.error);
+ console.log(error.name + ': ' + error.message);
}
- this.setState({ loading: false });
}
- }
-
- takeSuggestion(resource) {
- // when a suggestion is taken, call into the requestBox to resubmit the CRD request with the new request
- this.requestBox.current.replaceRequestAndSubmit(resource);
- }
+ };
- getPatients = () => {
- if (this.props.globalState.patientFhirQuery) {
- this.props.client
- .request(this.props.globalState.patientFhirQuery, { flat: true })
+ const getPatients = () => {
+ setState(prevState => ({ ...prevState, expanded: false}));
+ if (globalState.patientFhirQuery) {
+ client
+ .request(globalState.patientFhirQuery, { flat: true })
.then(result => {
- this.setState({
- patientList: result
- });
+ setState(prevState => ({ ...prevState, patientList: result, expanded: true }));
})
.catch(e => {
- this.setState({
- patientList: e
- });
+ setState(prevState => ({ ...prevState, patientList: e }));
+ console.log(e);
});
}
};
- updateStateList = (elementName, text) => {
- this.setState(prevState => {
- return { [elementName]: [...prevState[elementName], text] };
- });
- };
-
- updateStateMap = (elementName, key, text) => {
- this.setState(prevState => {
- if (!prevState[elementName][key]) {
- prevState[elementName][key] = [];
- }
- return { [elementName]: { ...prevState[elementName], [key]: text } };
- });
+ const updateStateMap = (elementName, key, text) => {
+ setState(prevState => ({
+ ...prevState,
+ [elementName]: { ...prevState[elementName], [key]: text }
+ }));
};
- clearState = () => {
- this.setState({
+ const clearState = () => {
+ setState(prevState => ({
+ ...prevState,
prefetchedResources: new Map(),
practitioner: {},
coverage: {},
response: {}
- });
+ }));
};
- handleChange = () => (event, isExpanded) => {
- this.setState({ expanded: isExpanded ? true : false });
+ const handleChange = () => (event, isExpanded) => {
+ setState(prevState => ({
+ ...prevState,
+ expanded: isExpanded ? true : false
+ }));
};
- isOrderNotSelected() {
- return Object.keys(this.state.request).length === 0;
- }
-
- render() {
- const displayRequestBox = !!this.props.globalState.patient?.id;
- const disableGetMedicationStatus = this.isOrderNotSelected() || this.state.loading;
-
+ const renderError = () => {
return (
- <>
-
-
-
- }
- aria-controls="panel1a-content"
- id="panel1a-header"
- style={{ marginLeft: '45%' }}
- >
- }>
- Select a patient
-
-
-
- {this.state.patientList.length > 0 && this.state.expanded && (
-
- {this.state.patientList instanceof Error ? (
- this.renderError()
- ) : (
-
- )}
-
- )}
-
-
-
-
- this.getPatients()} size="large">
-
-
-
+
+ Encountered Error: Try Refreshing The Client {state.patientList.message}{' '}
+
+ );
+ };
+
+ return (
+ <>
+
+
+
+ }
+ aria-controls="panel1a-content"
+ id="panel1a-header"
+ style={{ marginLeft: '45%' }}
+ >
+ }>
+ Select a patient
+
+
+
+ {state.patientList.length > 0 && state.expanded && (
+
+ {state.patientList instanceof Error ? (
+ renderError()
+ ) : (
+
+ )}
+
+ )}
+
+
+
+
+ getPatients()} size="large">
+
+
+
-
- {displayRequestBox && (
-
-
-
- )}
- {!disableGetMedicationStatus && (
-
-
-
- )}
-
+
+ {displayRequestBox && (
+
+
+
+ )}
+ {!disableGetMedicationStatus && (
+
+
+
+ )}
+
-
-
-
+
+
- >
- );
- }
-}
+
+ >
+ );
+};
+
+export default RequestBuilder;