Chapter 1: Simple Readout for FHIR Resources

By following this guide we will
  • Create a structure using pieces of the Commure component library to display patient information.

Prerequisites

In order to complete this tutorial, the following is necessary:

  • You must have followed and completed the Build Your First App tutorial.
  • This tutorial assumes a Unix (Mac or Linux) environment. It should be possible to complete on Windows, but you may need to translate some commands yourself.

Seeding the data

Throughout this tutorial, our code will be interacting with a curated set of sample data. To seed your tenant's sample data, login to your Commure Developer account and start by opening Tools > Data Library.

Scroll down to select the [Getting Started] Patient Chart Guide: Starter Kit data bundle, and submit it.

data library uploading patient chart guide kit

You can proceed through the tutorial and leave the upload running in the background - it may take a few minutes.

Upgrading the repo structure

Before we dig in with React, let’s create a directory structure and upgrade the CSS tooling in our repository. We will begin by creating the following directories within/src:
  • src/components/
  • src/styles/

Using Sass modules

To enable Sass styling, we will need to install node-sass:

yarn add node-sass@^4 --dev

After doing so, you will also probably want to rename App.css to App.scss and update the path referenced in App.tsx to refer to the new .scss file extension in order to get everything to compile. Note, though, that we will soon be discarding this App.scss file, so you can also delete it now, if you prefer.

A note about styling options

This tutorial uses Sass modules, but there are other options. We recommend using Sass modules plus the BEM convention for your stylesheet creation. If you instead prefer a CSS-in-JS approach, Styled Components is an alternative.

Displaying a list of patients

We will begin by using some pre-built React components to form an interface that shows patient data in a way that provides healthcare providers an optimal user experience.

Using the FhirHumanName component

Let’s display a simple list of patients. To do this, we will query the list of all patients using FhirDataQuery and then instantiate a FhirHumanName component, which handles the complexities of proper name display, including prefixes, suffixes, and name assembly order. For this particular use case, we will override name assembly order, since we want the list to be easily visually scanned.

The following is created as a new file, src/components/PatientList/PatientList.tsx:

src/components/PatientList/PatientList.tsx
1import React from "react";
2import { FhirDataQuery } from "@commure/components-data";
3import { Bundle, Patient } from "@commure/fhir-types/r4/types";
4import { FhirHumanName } from "@commure/components-core";
5
6export const PatientList: React.FC = () => (
7 <ul className="patient-list">
8 <FhirDataQuery queryString="Patient">
9 {({ loading, error, data: dataUntyped }) => {
10 const data = dataUntyped as Bundle | undefined;
11
12 return (
13 <>
14 {loading && <p>Loading...</p>}
15 {error && <p>An error occurred while fetching the patients</p>}
16 {data?.entry?.map(({ resource }) => {
17 const patient = resource as Patient;
18
19 return (
20 <li className="patient-list__item" key={patient.id}>
21 <FhirHumanName
22 className="patient-menu-item__name"
23 nameAssemblyOrder="G"
24 hidePrefixes
25 value={(patient.name || [])[0]}
26 />
27 </li>
28 );
29 })}
30 </>
31 );
32 }}
33 </FhirDataQuery>
34 </ul>
35);

There is also some associated styling; let’s add it to src/components/PatientList/patientList.scss:

src/components/PatientList/patientList.scss
1.patient-list {
2 list-style-type: none;
3 max-height: 100vh;
4 overflow-y: auto;
5
6 &__item {
7 padding: 1em 2em;
8 background-color: white;
9 }
10
11 &__name {
12 text-transform: uppercase;
13 color: darkgrey;
14 margin-bottom: 0.5em;
15 }
16
17 &__date {
18 color: lightgray;
19 margin: 0;
20 }
21}

Wiring it up to <App />

To display this PatientList, we need to modify src/App.tsx. We also reorganize the order of imports to improve the readability of the code.

src/App.tsx
1import React from "react";
2
3import { AppHeader } from "@commure/components-core";
4import { CommureSmartApp } from "@commure/components-data";
5import SMARTClient from "@commure/smart-core";
6import { PatientList } from "./components/PatientList/PatientList";
7
8import "./App.scss";
9import { smartConfig } from "./config";
10
11const smartClient = new SMARTClient(smartConfig);
12
13function App() {
14 return (
15 <CommureSmartApp client={smartClient}>
16 <AppHeader appName="My First Commure App" fixedToTop />
17 <div className="app-container">
18 <PatientList />
19 </div>
20 </CommureSmartApp>
21 );
22}
23
24export default App;

As for styling, let’s do some reorganization. We don’t need App.scss anymore since it was only necessary for Hello World, so we can delete that.

1rm App.scss

After doing so, be sure to remove the import of the now-deleted App.scss from App.tsx. We can also create a single entry point for all Sass styles, which joins together individual components’ styling. To do that, let’s create the file src/styles/all.scss:

src/styles/all.scss
1@import "./_styles.scss"; // Global styles
2
3// Component styles:
4@import "../components/PatientList/patientList.scss";

and import it in App.tsx:

src/App.tsx
1import React from "react";
2
3import { AppHeader } from "@commure/components-core";
4import { CommureSmartApp } from "@commure/components-data";
5import SMARTClient from "@commure/smart-core";
6import { PatientList } from "./components/PatientList/PatientList";
7
8import "./styles/all.scss";
9import { smartConfig } from "./config";

Note that we referenced a thus-far uncreated file src/styles/_styles.scss; let’s go ahead and define that:

src/styles/_styles.scss
1body {
2 margin: 0;
3}
4
5.app-container {
6 padding-top: 60px;
7}

This file is where extraneous global styles which don’t belong in any specific component’s directory will go. We need this Sass rule in order to produce some space at the top to prevent overlap with the floating AppHeader bar.

Viewing in the browser

If you have not already done so, you can now see the fruits of our labor in the browser; simply run yarn start and navigate to the URL it prints in the console (probably http://localhost:1234/). You should see something like this:

patient list

Adding date of birth

We need to show the patient’s date of birth. For this, we will use the FhirDateTime component that displays a FHIR date value.

Modifications to src/components/PatientList/PatientList.tsx:

src/components/PatientList/PatientList.tsx
1import { FhirDateTime, FhirHumanName } from "@commure/components-core";
2
3[code omitted]
4
5return (
6 <li className="patient-list__item" key={patient.id}>
7 <FhirHumanName
8 className="patient-menu-item__name"
9 nameAssemblyOrder="G"
10 hidePrefixes
11 value={(patient.name || [])[0]}
12 />
13 <p className="patient-list__date">
14 DOB: <FhirDateTime value={patient.birthDate} inline />
15 </p>
16 </li>
17);

This will show in the browser as:

patient list with DOB

box icon

Conclusion

In this chapter, we explored a simple way to use the component library to create a nice readout for patient FHIR resources. In the next chapters, we will explore how to use FHIR resources to create a more complex application.

We will see you there!