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

TEFCA Viewer Conditions table #1764

Merged
merged 7 commits into from
May 3, 2024
Merged
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
5 changes: 0 additions & 5 deletions containers/tefca-viewer/.env

This file was deleted.

43 changes: 0 additions & 43 deletions containers/tefca-viewer/api-documentation.md

This file was deleted.

4 changes: 2 additions & 2 deletions containers/tefca-viewer/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ const nextConfig = {
async rewrites() {
return [
{
source: "/ecr-viewer/:slug*",
source: "/tefca-viewer/:slug*",
destination: "/:slug*",
},
];
},
output: "standalone",
basePath: process.env.NODE_ENV === "production" ? "/ecr-viewer" : "",
basePath: process.env.NODE_ENV === "production" ? "/tefca-viewer" : "",
};

module.exports = nextConfig;
9 changes: 4 additions & 5 deletions containers/tefca-viewer/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "tefca-viewer",
"description": "The DIBBs eCR Viewer app offers a REST API for processing FHIR messages into an HTML page with key insights.",
"description": "The DIBBs TryTEFCA Viewer is a FHIR client for public health specific queries.",
"version": "1.0.1",
"private": true,
"scripts": {
"dev": "next dev --experimental-https",
"dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 next dev",
"local-dev": "npm run setup-local-env && docker compose up db seed-db -d && docker-compose logs && export DATABASE_URL=postgres://postgres:pw@localhost:5432/ecr_viewer_db && npm run dev",
"setup-local-env": "./setup-env.sh",
"build": "next build",
"start": "next start",
"build": "NODE_TLS_REJECT_UNAUTHORIZED=0 next build",
"start": "NODE_TLS_REJECT_UNAUTHORIZED=0 next start",
"lint": "next lint",
"test": "npm run test:unit && npm run test:integration",
"test:unit": "TZ=America/New_York jest",
Expand Down Expand Up @@ -54,7 +54,6 @@
"autoprefixer": "^10.0.1",
"aws-sdk-client-mock": "^3.0.1",
"chai": "^4.3.10",
"cypress": "^13.6.6",
"eslint": "^8.56.0",
"eslint-config-next": "14.0.3",
"eslint-config-prettier": "^9.1.0",
Expand Down
21 changes: 21 additions & 0 deletions containers/tefca-viewer/src/app/format-service.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CodeableConcept } from "fhir/r4";
/**
* Formats a string.
* @param input - The string to format.
Expand All @@ -15,3 +16,23 @@ export const formatString = (input: string): string => {

return result;
};

/**
* Formats a CodeableConcept object for display. If the object has a coding array,
* the first coding object is used.
* @param concept - The CodeableConcept object.
* @returns The CodeableConcept data formatted for
* display.
*/
export function formatCodeableConcept(concept: CodeableConcept) {
if (!concept.coding || concept.coding.length === 0) {
return concept.text || "";
}
const coding = concept.coding[0];
return (
<>
{" "}
{coding.display} <br /> {coding.code} <br /> {coding.system}{" "}
</>
);
}
11 changes: 6 additions & 5 deletions containers/tefca-viewer/src/app/query-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,12 @@ const FHIR_SERVERS: {
meld: { hostname: "https://gw.interop.community/HeliosConnectathonSa/open/" },
ehealthexchange: {
hostname: "https://concept01.ehealthexchange.org:52780/fhirproxy/r4/",
username: "svc_eHxFHIRSandbox",
password: "willfulStrongStandurd7",
headers: {
Accept: "application/json, application/*+json, */*",
"Accept-Encoding": "gzip, deflate, br",
"Content-Type": "application/fhir+json; charset=UTF-8",
"X-DESTINATION": "CernerHelios",
"X-POU": "TREATMENT",
"X-POU": "PUBHLTH",
"X-Request-Id": uuidv4(),
prefer: "return=representation",
"Cache-Control": "no-cache",
Expand Down Expand Up @@ -224,8 +222,11 @@ async function newbornScreeningQuery(
];
const loincFilter: string = "code=" + loincs.join(",");

const query = `/Observation?subject=${request.patientId}&code=${loincFilter}`;
const response = await fetch(request.fhir_host + query, request.init);
const query = `/Observation?subject=Patient/${request.patientId}&code=${loincFilter}`;
const response = await fetch(request.fhir_host + query, {
headers: request.headers,
...request.init,
});

if (response.status !== 200) {
console.log("response:", response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
AccordianDiv,
} from "../component-utils";
import { UseCaseQueryResponse } from "@/app/query-service";
import ConditionsTable from "./ConditionsTable";

type AccordionContainerProps = {
queryResponse: UseCaseQueryResponse;
Expand All @@ -23,6 +24,7 @@ type AccordionContainerProps = {
const AccordianContainer: React.FC<AccordionContainerProps> = ({
queryResponse,
}) => {
console.log("queryResponse:", queryResponse);
const accordionItems: any[] = [];

const patient =
Expand All @@ -32,6 +34,7 @@ const AccordianContainer: React.FC<AccordionContainerProps> = ({
const observations = queryResponse.observations
? queryResponse.observations
: null;
const conditions = queryResponse.conditions ? queryResponse.conditions : null;

if (patient) {
accordionItems.push({
Expand Down Expand Up @@ -73,6 +76,26 @@ const AccordianContainer: React.FC<AccordionContainerProps> = ({
});
}

if (conditions) {
accordionItems.push({
title: "Conditions",
content: (
<>
<AccordianSection>
<AccordianH4>
<span id="conditions">Conditions</span>
</AccordianH4>
<AccordianDiv>
<ConditionsTable conditions={conditions} />
</AccordianDiv>
</AccordianSection>
</>
),
expanded: true,
headingLevel: "h3",
});
}

//Add id, adjust title
accordionItems.forEach((item, index) => {
let formattedTitle = formatString(item["title"]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";
import { Table } from "@trussworks/react-uswds";
import { Condition } from "fhir/r4";
import { formatCodeableConcept } from "../../format-service";

/**
* The props for the ConditionTable component.
*/
export interface ConditionTableProps {
conditions: Condition[];
}

/**
* Displays a table of data from array of Condition resources.
* @param props - Condition table props.
* @param props.conditions - The array of Condition resources.
* @returns - The ConditionTable component.
*/
const ConditionsTable: React.FC<ConditionTableProps> = ({ conditions }) => {
return (
<Table>
<thead>
<tr>
<th>Condition</th>
<th>Status</th>
<th>Onset</th>
<th>Resolution</th>
</tr>
</thead>
<tbody>
{conditions.map((condition) => (
<tr key={condition.id}>
<td>{formatCodeableConcept(condition.code ?? {})}</td>
<td>{formatCodeableConcept(condition.clinicalStatus ?? {})}</td>
<td>{condition.onsetDateTime}</td>
<td>{condition.abatementDateTime}</td>
</tr>
))}
</tbody>
</Table>
);
};

export default ConditionsTable;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { Table } from "@trussworks/react-uswds";
import { Observation, CodeableConcept } from "fhir/r4";

import { Observation } from "fhir/r4";
import { formatCodeableConcept } from "../../format-service";
/**
* The props for the ObservationTable component.
*/
Expand Down Expand Up @@ -49,26 +49,6 @@ const ObservationTable: React.FC<ObservationTableProps> = ({
};
export default ObservationTable;

/**
* Formats a CodeableConcept object for display. If the object has a coding array,
* the first coding object is used.
* @param concept - The CodeableConcept object.
* @returns The CodeableConcept data formatted for
* display.
*/
function formatCodeableConcept(concept: CodeableConcept) {
if (!concept.coding || concept.coding.length === 0) {
return concept.text || "";
}
const coding = concept.coding[0];
return (
<>
{" "}
{coding.display} <br /> {coding.code} <br /> {coding.system}{" "}
</>
);
}

/**
* Formats the value of an Observation object for display.
* @param obs - The Observation object.
Expand Down
4 changes: 4 additions & 0 deletions containers/tefca-viewer/src/styles/custom-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,8 @@ body {
margin-top: 2.0rem;
margin-bottom: 4.0rem;
max-width: 11em;
}

.usa-table {
width: 100%;
}
23 changes: 23 additions & 0 deletions containers/tefca-viewer/src/styles/uswds-settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,26 @@ $ASSET_PREFIX: "";
$theme-hero-image: "#{$ASSET_PREFIX}/uswds/img/hero.webp",
$utilities-use-important: true,
);

/* https://designsystem.digital.gov/documentation/settings/ */
// @use "uswds-core" with (
// // General
// $theme-show-compile-warnings: true,
// $theme-show-notifications: false,
// $theme-image-path: "../../../../../../dist/img",

// // Color

// // Component
// $theme-hero-image: "../../../../dist/img/hero.jpg",
// $theme-accordion-button-background-color: 'blue-cool-60',

// // Spacing

// // Typography
// $theme-font-path: "../../../../../../dist/fonts",


// // Utilities

// );
Loading