diff --git a/package.json b/package.json index b9a1807..1d1e7e9 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "react-dom": "^17.0.0", "react-markdown": "^8.0.7", "react-router-dom": "^6.17.0", + "uuid": "^9.0.1", "vite": "^5.1.6", "vite-tsconfig-paths": "^4.3.2" }, diff --git a/src/components/Dashboard/ListSelections/NotificationsSection.jsx b/src/components/Dashboard/ListSelections/NotificationsSection.jsx index 4e17d25..b36bdcc 100644 --- a/src/components/Dashboard/ListSelections/NotificationsSection.jsx +++ b/src/components/Dashboard/ListSelections/NotificationsSection.jsx @@ -3,31 +3,77 @@ import useStyles from '../styles'; import { SettingsContext } from '../../../containers/ContextProvider/SettingsProvider'; import { EtasuStatusComponent } from '../../EtasuStatus/EtasuStatusComponent'; import axios from 'axios'; +import { createMedicationFromMedicationRequest } from '../../../util/fhir'; +import { standardsBasedGetEtasu } from '../../../util/util'; const NotificationsSection = () => { const [globalState, _] = useContext(SettingsContext); const classes = useStyles(); const [etasu, setEtasu] = useState([]); + const [medications, setMedications] = useState([]); useEffect(() => { - const patientFirstName = globalState.patient?.name?.at(0)?.given?.at(0); - const patientLastName = globalState.patient?.name?.at(0)?.family; - const patientDOB = globalState.patient?.birthDate; + setEtasu([]); + getMedicationRequest(); + }, []); + + useEffect(() => { + getAllEtasu(); + }, [medications]); - const etasuUrl = `${globalState.remsAdminServer}/etasu/met/patient/${patientFirstName}/${patientLastName}/${patientDOB}`; + const getMedicationRequest = () => { + const patientsMedications = []; axios({ method: 'get', - url: etasuUrl - }).then((response) => { - setEtasu(response.data); + url: `${globalState.baseUrl}/MedicationRequest?subject=Patient/${globalState.patient.id}` + }).then((result) => { + result?.data.entry.forEach((m) => { + const medication = createMedicationFromMedicationRequest(m.resource); + patientsMedications.push(medication); + }) + setMedications(patientsMedications); }, (error) =>{ console.error(error); - }) - }, []); + }); + }; + + const compileResponses = (newRequest, body) => { + if (newRequest.contained) { + newRequest.body = body; + setEtasu(prevState => [ ...prevState, newRequest]); + } + } + + const getAllEtasu = () => { + medications.forEach((medication) => { + const body = makeBody(medication); + const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`; + standardsBasedGetEtasu(standardEtasuUrl, body, compileResponses); + }); + + } + + const makeBody = (medication) => { + return { + resourceType: "Parameters", + parameter: [ + { + name: 'patient', + resource: globalState.patient + }, + { + name: 'medication', + resource: medication + } + ] + } + } + return (

Notifications

{etasu.map((remsCase) => { - return + const display = remsCase.body.parameter[1]?.resource.code.coding[0].display; + return })}
); diff --git a/src/components/EtasuStatus/EtasuStatus.jsx b/src/components/EtasuStatus/EtasuStatus.jsx index 2b0f996..97417ab 100644 --- a/src/components/EtasuStatus/EtasuStatus.jsx +++ b/src/components/EtasuStatus/EtasuStatus.jsx @@ -1,43 +1,55 @@ -import { EtasuStatusButton } from './EtasuStatusButton.jsx'; -import { EtasuStatusModal } from './EtasuStatusModal.jsx'; import { useState, useEffect, useContext } from 'react'; -import { Card, Typography } from '@mui/material'; import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider.jsx'; -import axios from 'axios'; import { EtasuStatusComponent } from './EtasuStatusComponent.jsx'; -import { getEtasu } from '../../util/util.js'; +import { standardsBasedGetEtasu } from '../../util/util.js'; +import { createMedicationFromMedicationRequest } from '../../util/fhir.js'; // converts code into etasu for the component to render // simplifies usage for applications that only know the code, not the case they want to display export const EtasuStatus = props => { const [globalState, _] = useContext(SettingsContext); - const { code } = - props; + const { code, request } = props; const [remsAdminResponse, setRemsAdminResponse] = useState({}); - useEffect(() => getEtasuStatus(), [code]); - const getEtasuStatus = () => { - const patientFirstName = globalState.patient?.name?.at(0)?.given?.at(0); - const patientLastName = globalState.patient?.name?.at(0)?.family; - const patientDOB = globalState.patient?.birthDate; - - console.log( - 'get Etastu Status: ' + - patientFirstName + - ' ' + - patientLastName + - ' - ' + - patientDOB + - ' - ' + - code - ); - const etasuUrl = `${globalState.remsAdminServer}/etasu/met/patient/${patientFirstName}/${patientLastName}/${patientDOB}/drugCode/${code}`; - getEtasu(etasuUrl, setRemsAdminResponse); + const [etasuData, setEtasuData] = useState({}); + const [display, setDisplay] = useState(''); + + useEffect(() => { + const medication = createMedicationFromMedicationRequest(request); + getEtasuStatus(medication); + }, [code]); + + const getEtasuStatus = (medication) => { + const body = makeBody(medication); + setEtasuData(body); + const display = body.parameter[1]?.resource.code.coding[0].display; + setDisplay(display); + const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`; + standardsBasedGetEtasu(standardEtasuUrl, body, setRemsAdminResponse); + }; + + const makeBody = (medication) => { + console.log('patient -- > ', globalState.patient); + return { + resourceType: "Parameters", + parameter: [ + { + name: 'patient', + resource: globalState.patient + }, + { + name: 'medication', + resource: medication + } + ] + } + } + return ( <> - {remsAdminResponse.case_number ? : ""} + {remsAdminResponse.contained ? : ""} ); }; diff --git a/src/components/EtasuStatus/EtasuStatusButton.jsx b/src/components/EtasuStatus/EtasuStatusButton.jsx index 06aa189..ed87d7c 100644 --- a/src/components/EtasuStatus/EtasuStatusButton.jsx +++ b/src/components/EtasuStatus/EtasuStatusButton.jsx @@ -12,7 +12,7 @@ export const EtasuStatusButton = props => { ETASU: - {remsAdminResponse?.status || 'Not Started'} + {convertStatus(remsAdminResponse?.status)} {renderTimestamp(lastCheckedEtasuTime)} @@ -62,3 +62,13 @@ const convertTimeDifference = start => { } return `Last checked ${prefix} ago`; }; + +export const convertStatus = status => { + if (status === 'success') { + return 'Approved'; + } else if (status === 'data-required') { + return 'Pending'; + } else { + return 'Not Started'; + } +} diff --git a/src/components/EtasuStatus/EtasuStatusComponent.jsx b/src/components/EtasuStatus/EtasuStatusComponent.jsx index 2e863b9..17e541d 100644 --- a/src/components/EtasuStatus/EtasuStatusComponent.jsx +++ b/src/components/EtasuStatus/EtasuStatusComponent.jsx @@ -3,13 +3,12 @@ import { EtasuStatusModal } from './EtasuStatusModal.jsx'; import { useState, useEffect, useContext } from 'react'; import { Card, Typography } from '@mui/material'; import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider.jsx'; -import axios from 'axios'; -import { getEtasu } from '../../util/util.js'; +import { standardsBasedGetEtasu } from '../../util/util.js'; export const EtasuStatusComponent = props => { const [globalState, _] = useContext(SettingsContext); - const { remsAdminResponseInit } = + const { remsAdminResponseInit, data, display } = props; const [remsAdminResponse, setRemsAdminResponse] = useState(remsAdminResponseInit); @@ -30,15 +29,15 @@ export const EtasuStatusComponent = props => { const refreshEtasu = () => { if(remsAdminResponse) { - const etasuUrl = `${globalState.remsAdminServer}/etasu/met/patient/${remsAdminResponse.patientFirstName}/${remsAdminResponse.patientLastName}/${remsAdminResponse.patientDOB}/drugCode/${remsAdminResponse.drugCode}`; - getEtasu(etasuUrl, setRemsAdminResponse); + const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`; + standardsBasedGetEtasu(standardEtasuUrl, data, setRemsAdminResponse); setLastCheckedEtasuTime(Date.now()); } } return ( - {remsAdminResponse?.drugName} + {display} { export const getStatusColor = status => { switch (status) { - case 'Approved': + case 'success': return 'green'; - case 'Pending': + case 'data-required': return '#f0ad4e'; default: return '#0c0c0c'; diff --git a/src/components/EtasuStatus/EtasuStatusModal.jsx b/src/components/EtasuStatus/EtasuStatusModal.jsx index 713b5af..d025fda 100644 --- a/src/components/EtasuStatus/EtasuStatusModal.jsx +++ b/src/components/EtasuStatus/EtasuStatusModal.jsx @@ -5,8 +5,7 @@ import { getStatusColor } from './EtasuStatusComponent'; import './EtasuStatusModal.css'; import CheckCircle from '@mui/icons-material/CheckCircle'; import Close from '@mui/icons-material/Close'; - -const getIdText = remsAdminResponse => remsAdminResponse?.case_number || 'N/A'; +import { convertStatus } from './EtasuStatusButton'; export const EtasuStatusModal = props => { const { callback, onClose, remsAdminResponse, update } = props; @@ -28,10 +27,7 @@ export const EtasuStatusModal = props => {
-
- Case Number: {getIdText(remsAdminResponse)} -
-
Status: {remsAdminResponse.status || 'N/A'}
+
Status: {convertStatus(remsAdminResponse.status)}
@@ -51,26 +47,26 @@ export const EtasuStatusModal = props => {

ETASU

- {remsAdminResponse ? ( + {remsAdminResponse && remsAdminResponse.contained ? ( - {remsAdminResponse?.metRequirements?.map((metRequirements) => ( + {remsAdminResponse?.contained[0]?.parameter.map((metRequirements) => ( - {metRequirements.completed ? ( + {metRequirements.resource.status === 'success' ? ( ) : ( )} - {metRequirements.completed ? ( - + {metRequirements.resource.status === 'success' ? ( + ) : ( )} diff --git a/src/containers/RequestBuilder.jsx b/src/containers/RequestBuilder.jsx index 76d176c..1d41e01 100644 --- a/src/containers/RequestBuilder.jsx +++ b/src/containers/RequestBuilder.jsx @@ -306,6 +306,7 @@ const RequestBuilder = props => { )} diff --git a/src/util/fhir.js b/src/util/fhir.js index 0cbb845..3fdcb31 100644 --- a/src/util/fhir.js +++ b/src/util/fhir.js @@ -80,10 +80,21 @@ function createMedicationDispenseFromMedicationRequest(medicationRequest) { return medicationDispense; } +function createMedicationFromMedicationRequest(medicationRequest) { + let medication = {}; + medication.resourceType = 'Medication'; + medication.id = medicationRequest?.id + '-med'; + if (medicationRequest.medicationCodeableConcept) { + medication.code = medicationRequest.medicationCodeableConcept; + } + return medication; +} + export { fhir, getAge, getDrugCodeableConceptFromMedicationRequest, getDrugCodeFromMedicationRequest, - createMedicationDispenseFromMedicationRequest + createMedicationDispenseFromMedicationRequest, + createMedicationFromMedicationRequest }; diff --git a/src/util/util.js b/src/util/util.js index b76c684..44b9286 100644 --- a/src/util/util.js +++ b/src/util/util.js @@ -66,30 +66,29 @@ function retrieveLaunchContext(link, patientId, clientState) { }); } -function getEtasu(etasuUrl, responseCallback) { +function standardsBasedGetEtasu(etasuUrl, body, responseCallback) { axios({ - method: 'get', - url: etasuUrl - }).then( - response => { + method: 'post', + url: etasuUrl, + data: body + }).then(response => { // Sorting an array mutates the data in place. const remsMetRes = response.data; - if (remsMetRes.metRequirements) { - remsMetRes.metRequirements.sort((first, second) => { + if (remsMetRes?.parameter[0]?.resource?.contained) { + remsMetRes.parameter[0].resource.contained[0].parameter.sort((first, second) => { // Keep the other forms unsorted. - if (second.requirementName.includes('Patient Status Update')) { + if (second.name.includes('Patient Status Update')) { // Sort the Patient Status Update forms in descending order of timestamp. - return second.requirementName.localeCompare(first.requirementName); + return second.name.localeCompare(first.name); } return 0; }); } - responseCallback(response.data); - }, - error => { - console.log(error); + responseCallback(response.data.parameter[0].resource, body); + }, error => { + console.log('error -- > ', error); } - ); + ) } const getMedicationSpecificRemsAdminUrl = (request, globalState, hook) => { @@ -118,4 +117,4 @@ const getMedicationSpecificRemsAdminUrl = (request, globalState, hook) => { return cdsUrl; }; -export { retrieveLaunchContext, getEtasu, getMedicationSpecificRemsAdminUrl }; +export { retrieveLaunchContext, standardsBasedGetEtasu, getMedicationSpecificRemsAdminUrl };