DEV Community

loading...

Build a Hospital Management System with React and Fauna

kayfortune profile image Fortune Kelechi Updated on ・9 min read

Alt Text

Hospital management systems are a very important part of hospitals, And due to the pandemic, hospitals have experienced an all time high in the number of cases and patients. In this tutorial, we will be building a hospital management system using FaunaDB as a serverless database and React for the UI needs. FaunaDB provides a developer-friendly database that is flexible and secure, With Fauna we can create a global database with no limits on traffic.

Our hospital management system will have three main users: patients, doctors and hospital administrators. In the coming section, we will list the role of each of the users.

Users

Patients: Patients will be able to do the following:

  • File cases
  • See Doctors assigned to them
  • A history of their past and present cases

Doctors: Doctors should be able to do the roles below

  • See all patients they’ve been assigned to
  • See all the cases they manage

Admin: Hospital Administrators should be able to do the following below

  • Read and update Patient and Doctor’s info
  • Assign Doctors to Patients

Note: This is a basic set of rules and roles for our application, in a real-world scenario, An MVP will contain more rules and features than our application.

Database Structure

With FaunaDB we can model relationships between collections and also iterate as our database grows. In our database, we will be modelling relationships such as one-to-many and many-to-many relationships, A Doctor can be assigned to more than one case and a case can have more than one doctor, Also certain wards in the hospital are for specific cases example an A&E department can only take accidents and emergencies.

Getting Started

As stated, we will be using React for the frontend of our project, FaunaDB for our database and Auth0 for our authentication flow. However, it’s important to note that to better understand this tutorial, you already understand the basic concepts of JavaScript, React and No-SQL databases.

Without further ado, let’s start!

Setting Up Your Database

In this section, we will be setting up our FaunaDB database. First, before we create a local database, you’d need to create a FaunaDB account if you don’t have one, you can do that here. To better communicate with our database, we will be using the fauna shell, the fauna shell allows us to communicate with our faunaDB database from the terminal, Let’s do that in the code block below:

npm install -g fauna-shell 
fauna cloud-login
Enter fullscreen mode Exit fullscreen mode

The above command installs fauna-shell globally on our local machine, the second line of code connects our shell to our fauna database, After the second line of code, fauna will ask for our login details and once we input those, our shell will be automatically connected to our shell.

Next, Let’s create our database below

fauna create-database hms 
fauna shell hms 
Enter fullscreen mode Exit fullscreen mode

The above command initiates a node-like environment where we can run and execute our queries, in our case FaunaDB has what they call the Fauna Query Language (FQL) which is the native API for querying Fauna, With this you don’t have to build APIs to use your database.

Let’s create our first collection below:

CreateCollection({ name: "Patients" })
Enter fullscreen mode Exit fullscreen mode

The above line will create a collection called Patients, A collection is similar to a table in a relational database such as Portgres, however in a No-SQL database, document is stored instead of rolls and has a liberal data structure. Having done this, Let’s create other collections for our database, similar to what we did above:

CreateCollection({ name: "Doctors" })
CreateCollection({ name: "Admin" })
CreateCollection({ name: "Cases" })
CreateCollection ({ name: "Wards" })
Enter fullscreen mode Exit fullscreen mode

The above creates collections for our application, Next let’s add some documents to any of the collections.

Creating A Document

To add a document to a collection, we use the create method from FQL. Let’s create a document and add it to our patient collection below:

Create(Collection("Patients"), {
  data: {
    firstName: "Omo",
    lastName: "Azula",
    email: "omoazula@hms.org",
  },
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we created a document in the patients collection and added the patients personal details such as names and email, you can add more details such as phone numbers and age.

The above lines of code should return something like this:

{
  ref: Ref(Collection("Patients"), "288396838045745665"),
  ts: 1611295507460000,
  data: { firstName: 'Omo', lastName: 'Azula', email: 'omoazula@hms.org'}
}
Enter fullscreen mode Exit fullscreen mode

The above is a confirmatio that the document have been added to the collection, here it references the collection which in our case is Patients and the id of the patient which in our case is 288396838045745665.

Indexes

Indexes are a very crucial part of databases, they are used to sort and reverse data of documents. Indexes can be used to make some specific data in a document unique, they can also be used to improve search for data in a document.

For example, to find users by email from the Patients or Doctor collections, we’d need to build an index that adds the fields to be searched in the terms prop and user’s email can be searched in FQL as an array path, let’s do this below:

CreateIndex({
 name: "users_by_email",
 source: [
 {collection: Collection("Patients")},
 {collection: Collection("Doctors")},
{collection: Collection("Admin")},
 ],
 terms: [{ field: ["data", "email"] }]
});
Enter fullscreen mode Exit fullscreen mode

Just like before, the above command will return the object below to signify a successful index.

{
  ref: Index("users_by_email"),
  ts: 1611301111530000,
  active: false,
  serialized: true,
  name: 'users_by_email',
  source: [
    { collection: Collection("Patients") },
    { collection: Collection("Doctors") },
    {collection: Collection("Admin")}
  ],
  terms: [ { field: [ 'data', 'email' ] } ],
  partitions: 1
}
Enter fullscreen mode Exit fullscreen mode

To prove our index is ready to use, we can try to search for a user by email on our fauna shell, we can do this using the FQL Match, let’s do that in the code block below:

Get(Match(Index("users_by_email"), "omoazula@hms.org"))
Enter fullscreen mode Exit fullscreen mode

This should return an object similar to the one below if successful

{
 ref: Ref(Collection("Patients"), "288396838045745665"),
 ts: 1611295507460000
  data: {
  "firstName": 'Omo',
   "lastName": 'Azula',
   "email": 'omoazula@hms.org',
   "currentWard": Ref(Collection("Wards"), "288396838045745665")
  }
}
Enter fullscreen mode Exit fullscreen mode

To better understand indexes and their use cases, You can check it out here. Next is to setup our Auth0 for authentication in our application, we’d do that in the next section.

Auth0 Setup

In this section, we are going to setup our authentication flow using Auth0. With Auth0 we can setup our authentication rules and only allow access to users on our FaunaDB database, Also we will setup restrictions on some of our collections, this will make it easier to define set rules and authorisations for collections, e.g a patient won’t be able to see an admin dashboard and vice versa.

To get started, first create a free Auth0 account here and proceed to create a single page application next add React as your library of choice and choose any name for your application. Next we will create a new rule for your application, you can learn more about Auth0 rules here.

To complete our rules, Let’s insert this code from my friend Vicradon as our rule and save as FaunaLogin, the code returns an object and our fauna secret, However to complete our rules we need to add our fauna database secret. We will also add our Fauna database secret in Auth0's environmental configuration, if its done correctly it should look like the image below:

Alt Text

In order for our Auth0 to work with our Fauna database, we need to add our fauna secret, to do that let’s run the command below on our fauna shell.

CreateKey({ role: "server" })
Enter fullscreen mode Exit fullscreen mode

it should return something like this

{
  ref: Ref(Keys(), "288428811249254919"),
  ts: 1611325999422000,
  role: 'server',
  secret: 'fnAEALR5xYACB6HhVTV0OOzqvdirYz_tyGulYSZ2',
  hashed_secret: '$2a$05$ywIG1KVTCcYhl8Y51Q7w4OLG0vAzMtMoOcS0ahpSyEqYqOsycMuaS'
}
Enter fullscreen mode Exit fullscreen mode

Connecting Auth0 to React Application

Here, we will connect our Auth0 configuration to our React application, to do this, Navigate to the applications settings tab on the Auth0 dashboard and add the URL http://localhost:3000/ to the

1. Allowed Callback URLs
2. Allowed Logout URLs 
3. Allowed Web Origins fields
Enter fullscreen mode Exit fullscreen mode

It should look like the image below

Alt Text

Be sure to save changes at the bottom of the page after you’ve added the link addresses. You will need the Client ID and Domain from the top of our applications page, So copy the values and add them to your .env file in React application.

Setting up UI

In this section, we will couple our React app with our FaunaDB and use Auth0 to authenticate our users. First, you need to clone this repo and initialize the project using the commands below

git clone https://github.com/iamfortune/hms.git
cd hms 
npm install 
Enter fullscreen mode Exit fullscreen mode

The above command initializes the project in our local machine, installs the node packages. Next, let’s create a file called .env in the root of our project directory, it will hold our app keys and secrets, our env file should have a similar format to the one below

REACT_APP_DOMAIN={ your app domain from auth0 goes here}
REACT_APP_CLIENT_ID={your client ID from auth0 goes here too}
FAUNA_SERVER_SECRET={your fauna secret goes here}
Enter fullscreen mode Exit fullscreen mode

When you’ve added these steps, start your development server using the command below

npm start
Enter fullscreen mode Exit fullscreen mode

Authenticating a Patient

Here, we will add roles for a patient and build functions for viewing a patients history and cases. You can create a patient profile using the details below


Email: kaycodev@hms.org
Password: Hms12345
Enter fullscreen mode Exit fullscreen mode

We should get a dashboard similar to the image below:

Alt Text

After a successful signup, next is for us to define the roles of a patient and give permissions to him/her. A Patient role is created using the FQL function below

CreateRole({
  name: "Patient",
  privileges: [
    {
      resource: Collection("Cases"),
      actions: { read: true },
    },
    {
      resource: Collection("Doctors"),
      actions: { read: true, write: true },
    },
    {
      resource: Collection("Wards"),
      actions: { read: true },
    },
    {
      resource: Collection("Patients"),
      actions: { read: true },
    },
  ],
  membership: [{ resource: Collection("Patients") }],
});

# this should return something similar to this
# {
#  ref: Role("Patient"),
# ts: 1611386788793000,
#  name: 'Patient',
#  privileges: [
#    { resource: Collection("Cases"), actions: { read: true } },
#    {
#      resource: Collection("Doctors"),
#      actions: { read: true, write: true }
#    },
#    { resource: Collection("Wards"), actions: { read: true } },
#    { resource: Collection("Patients"), actions: { read: true } }
#  ],
#  membership: [ { resource: Collection("Patients") } ]
#}
Enter fullscreen mode Exit fullscreen mode

The patient role is assigned to every patient, Here we gave write permissions to the Doctor, Patients are only permitted to read their cases and not write or update them. Our Patient dashboard should look like the image below when we are done.

Alt Text

Doctors Section

First, signup as a doctor using the credentials below

Email: drfortune@hms.org
Password: Hms12345
Enter fullscreen mode Exit fullscreen mode

Now Let's create a role for our doctor

CreateRole({
  name: "Doctor",
  privileges: [
    {
      resource: Collection("Cases"),
      actions: { read: true },
    },
    {
      resource: Collection("Patients"),
      actions: { read: true },
    },
    {
      resource: Collection("Wards"),
      actions: { read: true },
    },
    {
      resource: Collection("Doctors"),
      actions: {
        read: true,
        write: Query(
          Lambda("ref", Equals(Identity(), Var("ref")))
        ),
      },
    },
  ],
  membership: [
    {
      resource: Collection("Doctors"),
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

Our Doctors dashboard page will show the patients whose cases the doctor is handling and the cases the Doctor have been assigned to.

Alt Text

Hospital Admin Section

The hospital admin should be able to create, read, update and delete activities of the other collections, to start, let’s create an Admin role for our application below.


CreateRole({
  name: "Admin",
  privileges: [
    {
      resource: Collection("Cases"),
      actions: { read: true, write: true, create: true, delete: true },
    },
    {
      resource: Collection("Doctors"),
      actions: { read: true, write: true, create: true, delete: true },
    },
    {
      resource: Collection("Patients"),
      actions: { read: true, write: true, create: true, delete: true },
    },
    {
      resource: Collection("Wards"),
      actions: { read: true, write: true, create: true, delete: true },
    },
  ],
  membership: [
    {
      resource: Collection("Admin"),
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

In the FQL command above, we gave CRUD privileges of all our other collections to the hospital admin, with this they can have control over creating and seeing the activities, next is to register an admin with the details below to see our admin dashboard,

Email: admin@hms.org
Password: Admin1234
Enter fullscreen mode Exit fullscreen mode

Once we sign in, we should able to see a dashboard similar to the one below

Alt Text

Conclusion

In this article, You’ve learnt how to set up a FaunaDB database, Use Auth0 rules, Creating roles and indexes in FaunaDB. You can take this further and add more functionalities to the app, or build new things with FaunaDB. It’s important to note that FaunaDB was built with scalability in mind and so will scale automatically as your application’s database needs grows. You can learn more about FaunaDB from the references below.

RESOURCES AND RERENCES

Discussion (4)

pic
Editor guide
Collapse
ogurinkaben profile image
Ogurinka Benjamin

Good read! Precise and easy to understand... I learned a lot going through it.
Great stuff

Collapse
kayfortune profile image
Fortune Kelechi Author

I'm glad you like it

Collapse
umavictor6 profile image
uma victor

Thanks for this tutorial. I have been looking to start using fauna.

Collapse
kayfortune profile image
Fortune Kelechi Author

Glad you like it