Creating a customized medication dashboard in NuxtJS

teri - Mar 22 '23 - - Dev Community

Dashboards, graphical user interfaces comprising a composition of data visually presented to users, are essential to modern web and mobile applications. They are everywhere — from laptops displaying our screen time to mobile phones— and all everyday tools and technologies have dashboards.

In this article, we will build a dashboard using Appwrite, a backend-as-a-service (BaaS) platform, to manage and display the data on the client side of the customized medication dashboard using its core APIs in a Nuxt project.

Our final app will look something like this:

medic dashboard

GitHub

Check out the complete source code in this repo.

Prerequisites

To follow along with this tutorial, the following are required:

  • Node and node package manager (npm) installed on our machine
  • Basic knowledge of Vue, JavaScript, and CSS
  • Docker installation
  • Appwrite instance; check this article on setup

What is Appwrite Pink Design system?

Companies create design systems with a set of reusable components for developer ease of use and to create beautiful experiences and interfaces more quickly.

Pink Design is an open-source design system for prioritizing collaboration and improving the accessibility of web and mobile apps through carefully created components and styles.

Setting up Appwrite

To get started, we need to log in to our Appwrite console. Use this command to run the Appwrite instance in the browser:



    localhost:80


Enter fullscreen mode Exit fullscreen mode

Now, create a new project by clicking the Create Project button. Name this project Medications Dashboard.

Appwrite projects

Next, navigate into the new project to create a database, collections, and add attributes.

Creating a database
In the left pane of the Appwrite console dashboard, click Databases and create a new database with the name medications.

Database

Creating collections
After clicking the created database, medications, we will create a collection to serve as a container for our documents. Give the new collection the name medications collection.

Collections

Adding attributes
Attributes represent the fields in our database. To create attributes, click the Attributes tab to add a new attribute.

Here is the final result for each attribute:

Enum attribute

Document attributes

Let's fill in each of these fields. Click the Documents tab and "AddDocument".

Add Document

Update permissions
Here, we will configure permissions for our collection. Under the Permissions section, update the role to Any and check Read. Afterwards, click the Update button to confirm the selection.

Permissions

Scaffolding a Nuxt App

Nuxt is a progressive frontend framework built on top of Vue. We'll first want to scaffold a Nuxt development environment to get started. Do so quickly by using this command:



    npx nuxi init <project-name>


Enter fullscreen mode Exit fullscreen mode

For this project, the is named medications-dashboard.

Next, navigate to the project directory and run the following to install the project dependencies:



    npm install


Enter fullscreen mode Exit fullscreen mode

Start the frontend server in development mode when the project’s dependencies have finished installing with the command:



    npm run dev -- -o


Enter fullscreen mode Exit fullscreen mode

View the scaffolded application at http://localhost:3000.

Installing Dependencies

Let's install the following packages to our project: the Appwrite software development kit (SDK) and the Pink Design.



    npm install appwrite
    npm install @appwrite.io/pink


Enter fullscreen mode Exit fullscreen mode

Check the installed dependencies in the package.json file:

dependency file

Building a customized dashboard

Before creating the UI, let's import the Pink Design library into our project, giving us access to the Pink Design classes. Inside the pages folder, add the following imports in the index.vue file:

app entry point

The second import with pink-icons is applicable when we need to add icons to our app.

Creating project components
In the Nuxt root project directory, create a folder named components and create the following files: MedicalDetails.vue, NavBar.vue, PatientInfo.vue, and UserInfo.vue.

For each of these components, copy and paste the following code:



// components/MedicalDetails.vue

    <template>
      <div class="container">
        <div>
          <h2 class="eyebrow-heading-2">Medication History</h2>
          <ul class="list">
            <li
              class="list-item">
              <span class="icon-arrow-circle-right" aria-hidden="true"></span>
              <span class="text">Pain in the chest region</span>
            </li>
            <li
              class="list-item">
              <span class="icon-arrow-circle-right" aria-hidden="true"></span>
              <span class="text">Cortisol levels</span>
            </li>
            <li class="list-item"></li>
          </ul>
        </div>
        <div>
          <h2 class="eyebrow-heading-2">Upcoming Doses</h2>
          <ul class="list">
            <li class="list-item">
              <span class="text u-bold">Check in:</span>
              February 28, 2023
            </li>
            <li class="list-item">
              <span class="text u-bold">Doctor to see:</span>
              Dr. Tolu Hernandez
            </li>
            <li class="list-item">
              <span class="text u-bold">Shot:</span>
              Vaccination
            </li>
          </ul>
        </div>
      </div>
    </template>


Enter fullscreen mode Exit fullscreen mode

The code above within the <template> does the following:

  • container holds the content of the other elements
  • eyebrow-heading-2 is a typography feature that supports the main heading
  • list used to group related content in a list
  • list-item ****is a necessary class when list items begin with an icon
  • icon-arrow-circle-right is a class to add an icon within the list-item element
  • text represents body text


    // components/NavBar.vue

    <template>
      <div class="container">
        <header class="u-flex u-main-space-between u-cross-center">
          <NuxtLink to="/" class="u-bold">Med</NuxtLink>
          <img
            class="avatar"
            src="https://res.cloudinary.com/terieyenike/image/upload/v1666716203/teri.jpg"
            alt="portrait - teri" />
        </header>
      </div>
    </template>


Enter fullscreen mode Exit fullscreen mode

Let's break down the code snippet above:

  • In the header element, the class u-flex styles the container as flex, whereas the u-main-space-between distributes the items, the text and image evenly
  • NuxtLink is a component for navigation to the home route
  • u-bold is a class to make the text bold
  • avatar is a class responsible for displaying an image preview


// components/PatientInfo.vue

    <template>
      <div class="container">
        <h2 class="eyebrow-heading-2">Other Information</h2>
        <div class="u-flex u-cross-center u-gap-24">
          <div>
            <p class="u-bold">Sex: <span>Male</span></p>
            <p class="u-bold">Age: <span>31</span></p>
          </div>
          <div>
            <p class="u-bold">Diabetic: <span>No</span></p>
            <p class="u-bold">Blood: <span>O+</span></p>
          </div>
        </div>
      </div>
    </template>


Enter fullscreen mode Exit fullscreen mode

In this component, the code does the following:

  • u-gap-24 adds spacing of 1.5rem from the h2 element


    // components/UserInfo.vue

    <template>
      <div class="container">
        <section class="u-flex u-flex-vertical u-cross-center">
          <h1 class="heading-level-1">Medic Dashboard</h1>
          <p>
            Welcome, <span class="eyebrow-heading-2">{{ name }}!</span>
          </p>
        </section>
      </div>
    </template>

    <script setup>
    const name = 'Teri';
    </script>


Enter fullscreen mode Exit fullscreen mode

For this code block, we included the composition API:

  • In the script section, we assigned a variable
  • Just as in previous components, we are using the Pink Design classes
  • Pass the declared variable in the element

Let's update the code to reflect all the changes made in the components directory in our pages/index.vue file. Copy and paste the following code:



    // pages/index.vue

    <template>
      <nav-bar />
      <user-info />
      <medical-details />
      <patient-info />
    </template>

    <script setup>
    ...
    useHead({
      title: 'Medications Dashboard',
    })
    </script>


Enter fullscreen mode Exit fullscreen mode

The code above does the following:

  • Imports each of the components in .
  • The useHead components in the code above help to bind the metadata, title to the head of the page.

Our app will look like this:

Med dashboard

Integrating Appwrite
With the UI complete, let's create a file named utils.js in our Nuxt project root directory.

Copy and paste the following code:



    // utils.js

    import { Client, Databases } from "appwrite";

    const client = new Client();

    const databases = new Databases(client);

    client
        .setEndpoint('http://localhost/v1') 
        .setProject('[PROJECT_ID]')
    ;

    export const getList = databases.listDocuments('[DATABASE_ID]', '[COLLECTION_ID]');


Enter fullscreen mode Exit fullscreen mode

The code snippet above does the following:

  • Imports the required module, Client, and Databases
  • Creates a new instance for the Client and Databases
  • Initializes the Appwrite web SDK using the client variable, which will interact with Appwrite services

PS: We can get all the required IDs from our Appwrite console when setting up the instance

Updating the UI
Back to the MedicalDetails.vue component, let's update the code with the following:




     // components/MedicalDetails.vue

    <template>
      <div class="container">
        <div>
          <h2 class="eyebrow-heading-2">Medication History</h2>
          <ul class="list" v-for="medication in medications" :key="medication.$id">
            <li
              class="list-item"
              v-for="item in medication.medicationHistory"
              :key="item.$id">
              <span class="icon-arrow-circle-right" aria-hidden="true"></span>
              <span class="text">{{ item }}</span>
            </li>
            <li class="list-item"></li>
          </ul>
        </div>
        <div>
          <h2 class="eyebrow-heading-2">Upcoming Doses</h2>
          <ul class="list" v-for="item in medications" :key="item.$id">
            <li class="list-item">
              <span class="text u-bold">Check in:</span>
              {{ item.date.slice(0, 10) }}
            </li>
            <li class="list-item">
              <span class="text u-bold">Doctor to see:</span>
              {{ item.nameOfDoctor }}
            </li>
            <li class="list-item">
              <span class="text u-bold">Shot:</span>
              {{ item.typeOfDose }}
            </li>
          </ul>
        </div>
      </div>
    </template>

    <script setup>
    import { getList } from '@/utils';

    const medications = ref(null);

    onMounted(() => {
      getList.then(
        function (response) {
          medications.value = response.documents;
        },
        function (error) {
          console.log(error);
        }
      );
    });
    </script>


Enter fullscreen mode Exit fullscreen mode

The code block above does the following:

Using the Appwrite List Documents Databases API,

  • We can query the list of documents from the Appwrite console
  • Display the details using the v-for directives to loop through the object.

Finally, the app should look like this:

Final app view

Conclusion

The Pink Design System is great for developers who need to build customized systems like dashboards for their products. It would help make the process faster and give you control over structuring the look and feel of an app embedded with classes.

Like every other dashboard on the internet, the primary purpose of creating one is to personalise different user profiles. Appwrite comes in handy as one of the best backend servers that populate data to the client side.

In this post, we learned how to use the Appwrite Databases service to query and list documents stored in Appwrite on the client side and Pink, an innovative approach that provides components to build dynamic and usable products.

Resources

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .