Skip to content

HACK-A-THON-IMPROVE-NODE-JS-REACT-SAMPLE-APP #14

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
237 changes: 226 additions & 11 deletions client/src/components/records.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,42 @@ export type EOBRecord = {
amount: number
}

export type DiagnosisRecord = {
id: string,
sequence: string,
diagnosisCode: string,
diagnosisDisplay: string,
typeCode: string,
typeDisplay: string
}

export type PatientRecord = {
id: string,
name: string,
gender: string,
dateOfBirth: string,
addressState: string,
addressZip: string
}

export type CoverageRecord = {
id: string,
subscriberId: string,
status: string,
beneRef: string,
payor: string
}

export type ErrorResponse = {
type: string,
content: string,
}

export default function Records() {
const [records, setRecords] = useState<EOBRecord[]>([]);
const [eobs, setRecords] = useState<EOBRecord[]>([]);
const [diagnosis, setDiagnosis] = useState<DiagnosisRecord[]>([]);
const [patients, setPatients] = useState<PatientRecord[]>([]);
const [coverages, setCoverages] = useState<CoverageRecord[]>([]);
const [message, setMessage] = useState<ErrorResponse>();
/*
* DEVELOPER NOTES:
Expand All @@ -33,12 +62,12 @@ export default function Records() {
* Carrier Claims, SNF, HHA, Hospice, Inpatient, and Outpatient
*/
useEffect(() => {
fetch('/api/data/benefit')
fetch('/api/data/beneficiary_data')
.then(res => {
return res.json();
}).then(eobData => {
if (eobData.entry) {
const records: EOBRecord[] = eobData.entry.map((resourceData: any) => {
}).then(beneData => {
if (beneData.eobData && beneData.eobData.entry) {
const records: EOBRecord[] = beneData.eobData.entry.map((resourceData: any) => {
const resource = resourceData.resource;
return {
id: resource.id,
Expand All @@ -47,12 +76,73 @@ export default function Records() {
amount: resource.item[0]?.adjudication[7]?.amount?.value || '0'
}
});

setRecords(records);

const diagnosisRecords: DiagnosisRecord[] = beneData.eobData.entry.filter((resourceData: any) => {
const resource = resourceData.resource;
if (resource.diagnosis) {
return true;
}
else {
return false;
}
}).map((resourceData: any) => {
const resource = resourceData.resource;
return {
id: resource.id,
sequence: resource?.diagnosis[0]?.sequence || 'Unknown',
diagnosisCode: resource?.diagnosis[0]?.diagnosisCodeableConcept?.coding[0]?.code || 'Unknown',
diagnosisDisplay: resource?.diagnosis[0]?.diagnosisCodeableConcept?.coding[0]?.display || 'Unknown',
typeCode: resource?.diagnosis[0]?.type[0]?.coding[0]?.code || 'Unknown',
typeDisplay: resource?.diagnosis[0]?.type[0]?.coding[0]?.display || 'Unknown',
}
});
setDiagnosis(diagnosisRecords);
}
else {
if (eobData.message) {
setMessage({"type": "error", "content": eobData.message || "Unknown"})
}

if (beneData.patient && beneData.patient.entry) {
const records: PatientRecord[] = beneData.patient.entry.map((resourceData: any) => {
const resource = resourceData.resource;
return {
id: resource.id,
name: resource?.name[0]?.family || 'Unknown',
gender: resource?.gender || 'Unknown Gender',
dateOfBirth: resource?.birthDate || 'Unknown DOB',
addressState: resource?.address[0]?.state || 'Unknown State',
addressZip: resource?.address[0]?.postalCode || 'Unknown ZIP',
}
});
setPatients(records);
}

if (beneData.coverage && beneData.coverage.entry) {
const records: CoverageRecord[] = beneData.coverage.entry.map((resourceData: any) => {
const resource = resourceData.resource;
if (resource.payor) {
return {
id: resource.id,
subscriberId: resource?.subscriberId || 'Unknown',
status: resource?.status || 'Unknown Status',
beneRef: resource?.beneficiary?.reference || 'Unknown Beneficiary',
payor: resource?.payor[0]?.identifier?.value || 'Unknown Payor',
}
}
else {
return {
id: resource.id,
subscriberId: resource?.subscriberId || 'Undefined',
status: resource?.status || 'Undefined',
beneRef: resource?.beneficiary?.reference || 'Undefined',
payor: 'Undefined',
}
}
});
setCoverages(records);
}

if (beneData.eobData && beneData.eobData.message) {
setMessage({"type": "error", "content": beneData.eobData.message || "Unknown"})
}
});
}, [])
Expand Down Expand Up @@ -83,20 +173,103 @@ export default function Records() {
);
} else {
return (
<div className='full-width-card'>
<div className='full-width-card'>
<Table className="ds-u-margin-top--2" stackable stackableBreakpoint="md">
<TableCaption>Medicare Patient Info</TableCaption>
<TableHead>
<TableRow>
<TableCell id="column_0">ID</TableCell>
<TableCell id="column_1">Name</TableCell>
<TableCell id="column_2">Gender</TableCell>
<TableCell id="column_3">Birth Date</TableCell>
<TableCell id="column_4">Address State</TableCell>
<TableCell id="column_5">Address ZIP</TableCell>
</TableRow>
</TableHead>
<TableBody>
{patients.map(record => {
return (
<TableRow key={record.id}>
<TableCell stackedTitle="ID" headers="column_0">
{record.id}
</TableCell>
<TableCell stackedTitle="Name" headers="column_1">
{record.name}
</TableCell>
<TableCell stackedTitle="Gender" headers="column_2">
{record.gender}
</TableCell>
<TableCell stackedTitle="Birth Date" headers="column_3">
{record.dateOfBirth}
</TableCell>
<TableCell stackedTitle="Address State" headers="column_4">
{record.addressState}
</TableCell>
<TableCell stackedTitle="Address ZIP" headers="column_5">
{record.addressZip}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</div>
<div className='full-width-card'>
<Table className="ds-u-margin-top--2" stackable stackableBreakpoint="md">
<TableCaption>Medicare Coverage Info</TableCaption>
<TableHead>
<TableRow>
<TableCell id="column_0">ID</TableCell>
<TableCell id="column_1">Subscriber ID</TableCell>
<TableCell id="column_2">Status</TableCell>
<TableCell id="column_3">Beneficiary Reference</TableCell>
<TableCell id="column_4">Payor</TableCell>
</TableRow>
</TableHead>
<TableBody>
{coverages.map(record => {
return (
<TableRow key={record.id}>
<TableCell stackedTitle="ID" headers="column_0">
{record.id}
</TableCell>
<TableCell stackedTitle="Subscriber ID" headers="column_1">
{record.subscriberId}
</TableCell>
<TableCell stackedTitle="Status" headers="column_2">
{record.status}
</TableCell>
<TableCell stackedTitle="Beneficiary Reference" headers="column_3">
{record.beneRef}
</TableCell>
<TableCell stackedTitle="Payor" headers="column_4">
{record.payor}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</div>
<div className='full-width-card'>
<Table className="ds-u-margin-top--2" stackable stackableBreakpoint="md">
<TableCaption>Medicare Prescription Drug Claims Data</TableCaption>
<TableHead>
<TableRow>
<TableCell id="column_0">ID</TableCell>
<TableCell id="column_1">NDC Code</TableCell>
<TableCell id="column_2">Prescription Drug Name</TableCell>
<TableCell id="column_3">Cost</TableCell>
</TableRow>
</TableHead>
<TableBody>
{records.map(record => {
{eobs.map(record => {
return (
<TableRow key={record.id}>
<TableCell stackedTitle="ID" headers="column_0">
{record.id}
</TableCell>
<TableCell stackedTitle="NDC Code" headers="column_1">
{record.code}
</TableCell>
Expand All @@ -112,6 +285,48 @@ export default function Records() {
</TableBody>
</Table>
</div>
);
<div className='full-width-card'>
<Table className="ds-u-margin-top--2" stackable stackableBreakpoint="md">
<TableCaption>Medicare Diagnosis Data</TableCaption>
<TableHead>
<TableRow>
<TableCell id="column_0">ID</TableCell>
<TableCell id="column_1">Sequence</TableCell>
<TableCell id="column_2">Code</TableCell>
<TableCell id="column_3">Name</TableCell>
<TableCell id="column_4">Type Code</TableCell>
<TableCell id="column_5">Type Name</TableCell>
</TableRow>
</TableHead>
<TableBody>
{diagnosis.map(record => {
return (
<TableRow key={record.id}>
<TableCell stackedTitle="ID" headers="column_0">
{record.id}
</TableCell>
<TableCell stackedTitle="Sequence" headers="column_1">
{record.sequence}
</TableCell>
<TableCell stackedTitle="Code" headers="column_2">
{record.diagnosisCode}
</TableCell>
<TableCell stackedTitle="Name" headers="column_3">
{record.diagnosisDisplay}
</TableCell>
<TableCell stackedTitle="Type Code" headers="column_4">
{record.typeCode}
</TableCell>
<TableCell stackedTitle="Type Name" headers="column_5">
{record.typeDisplay}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</div>
</div>
);
}
};
2 changes: 1 addition & 1 deletion server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ RUN yarn install

EXPOSE 3001

CMD ["yarn","start:dev"]
CMD ["yarn","start:debug"]
9 changes: 6 additions & 3 deletions server/src/routes/Authorize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AuthorizationToken from '../entities/AuthorizationToken';
import Settings from '../entities/Settings';
import db from '../utils/db';
import { getAccessToken, generateAuthorizeUrl } from '../utils/bb2';
import { getBenefitData } from './Data';
import { getExplanationOfBenefitData, getPatientJSON, getCoverageJSON } from './Data';
import logger from '@shared/Logger';
import { clearBB2Data, getLoggedInUser } from 'src/utils/user';

Expand Down Expand Up @@ -56,12 +56,15 @@ export async function authorizationCallback(req: Request, res: Response) {
* You could also request data for the Patient endpoint and/or the Coverage endpoint here
* using similar functionality
*/
const eobData = await getBenefitData( req, res);
loggedInUser.eobData = eobData;
loggedInUser.eobData = await getExplanationOfBenefitData( req, res);
loggedInUser.patient = await getPatientJSON( req, res);
loggedInUser.coverage = await getCoverageJSON( req, res);
}
else {
// send generic error message to FE
loggedInUser.eobData = JSON.parse('{"message": "Unable to load EOB Data - authorization failed."}');
loggedInUser.patient = JSON.parse('{"message": "Unable to load Patient Data - authorization failed."}');
loggedInUser.coverage = JSON.parse('{"message": "Unable to load Coverage Data - authorization failed."}');
}

} catch (e) {
Expand Down
33 changes: 25 additions & 8 deletions server/src/routes/Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { refreshAccessToken } from 'src/utils/bb2';

// this function is used to query eob data for the authenticated Medicare.gov
// user and returned - we are then storing in a mocked DB
export async function getBenefitData(req: Request, res: Response) {
export async function getExplanationOfBenefitData(req: Request, res: Response) {
const loggedInUser = getLoggedInUser(db);
const envConfig = config[db.settings.env];
const BB2_BENEFIT_URL = envConfig.bb2BaseUrl + '/' + db.settings.version + '/fhir/ExplanationOfBenefit/';
Expand Down Expand Up @@ -49,28 +49,44 @@ export async function getBenefitData(req: Request, res: Response) {
* This would be replaced by a persistence service layer for whatever
* DB you would choose to use
*/
export async function getBenefitDataEndPoint(req: Request, res: Response) {
export async function getBeneficiaryDataEndPoint(req: Request, res: Response) {
const loggedInUser = getLoggedInUser(db);
const data = loggedInUser.eobData;
if ( data ) {
res.json(data)
const beneData = {'eobData': loggedInUser.eobData, 'patient': loggedInUser.patient, 'coverage': loggedInUser.coverage};
if ( beneData ) {
res.json(beneData);
}
}

export async function getPatientData(req: Request, res: Response) {
// const loggedInUser = getLoggedInUser(db);
// const envConfig = config[db.settings.env];
// get Patient end point
const data = await getPatientJSON(req, res);
res.json(data);
}

export async function getPatientJSON(req: Request, res: Response) {
const loggedInUser = getLoggedInUser(db);
const envConfig = config[db.settings.env];
// get Patient end point
const response = await get(`${envConfig.bb2BaseUrl}/${db.settings.version}/fhir/Patient/`, req.query, `${loggedInUser.authToken?.access_token}`);
res.json(response.data);
return response.data;
}

export async function getCoverageData(req: Request, res: Response) {
// const loggedInUser = getLoggedInUser(db);
// const envConfig = config[db.settings.env];
// get Coverage end point
const data = await getCoverageJSON(req, res);
res.json(data);
}

export async function getCoverageJSON(req: Request, res: Response) {
const loggedInUser = getLoggedInUser(db);
const envConfig = config[db.settings.env];
// get Coverage end point
const response = await get(`${envConfig.bb2BaseUrl}/${db.settings.version}/fhir/Coverage/`, req.query, `${loggedInUser.authToken?.access_token}`);
res.json(response.data);
return response.data;
}

export async function getUserProfileData(req: Request, res: Response) {
Expand All @@ -83,7 +99,8 @@ export async function getUserProfileData(req: Request, res: Response) {

const router = Router();

router.get('/benefit', getBenefitDataEndPoint);
router.get('/beneficiary_data', getBeneficiaryDataEndPoint);
router.get('/eob', getExplanationOfBenefitData);
router.get('/patient', getPatientData);
router.get('/coverage', getCoverageData);
router.get('/userprofile', getUserProfileData);
Expand Down
Loading