Creating a customized medication dashboard in NuxtJS
Tags: javascript, programming, vue, frontend
Published: 2023-03-22 10:57:10

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](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog), 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](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676963742100_medication-deshboard.jpg)


## GitHub

Check out the complete source code in [this repo](https://github.com/Terieyenike/Appwrite-Dashboard-with-Pink).


## 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](https://www.docker.com/get-started/)
- Appwrite instance; check [this article](https://dev.to/hackmamba/create-a-local-appwrite-instance-in-3-steps-19n9) 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](https://pink.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) 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:

```bash
    localhost:80
```

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


![Appwrite projects](https://user-images.githubusercontent.com/25850598/230134886-c64e3670-6092-43f8-9a8a-a00913c9ed86.jpg)



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](https://user-images.githubusercontent.com/25850598/230136490-72ec4ada-3c98-4d8b-97cb-9db1d7eceabc.jpg)



**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](https://user-images.githubusercontent.com/25850598/230138207-56dbb6c6-cf8d-47fa-aa6c-e4c60ebc9bf9.jpg)


**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](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676969859608_image.png)

![Document attributes](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676969522273_image.png)


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


![Add Document](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676970134050_image.png)

**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](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676973224871_image.png)



## 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:

```bash
    npx nuxi init <project-name>
```

For this project, the <project-name> is named **medications-dashboard**.

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

```bash
    npm install
```

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

```bash
    npm run dev -- -o
```

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.

```bash
    npm install appwrite
    npm install @appwrite.io/pink
```

Check the installed dependencies in the `package.json` file:


![dependency file](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676974900038_package.json.jpg)



## 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](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676976055744_pink.jpg)


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:

```js
// 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>
```

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


```js
    // 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>
```

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


```js
// 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>
```

In this component, the code does the following:

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

```js
    // 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>
```

For this code block, we included the **<script setup>** 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 **<p>** 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:

```js
    // pages/index.vue
    
    <template>
      <nav-bar />
      <user-info />
      <medical-details />
      <patient-info />
    </template>
    
    <script setup>
    ...
    useHead({
      title: 'Medications Dashboard',
    })
    </script>
```

The code above does the following:


- Imports each of the components in **<template>.**
- 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](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676984110010_image.png)


**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:

```js
    // 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]');
```

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: 

```js

     // 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>
```

The code block above does the following:

Using the Appwrite [**List Documents**](https://appwrite.io/docs/client/databases?sdk=web-default#databasesListDocuments) 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](https://paper-attachments.dropboxusercontent.com/s_86FC69EB234E809235CAF602F8719EFA6CEFA00AF606C38975517ABA52C4FB1A_1676987323905_image.png)



## Conclusion

The [Pink Design](https://pink.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) 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
- [Appwrite's Pink design system](https://github.com/appwrite/pink/?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Nuxt documentation](https://nuxt.com/)
- [Appwrite Documentation](https://appwrite.io/docs/getting-started-for-web?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Get user's documents in Appwrite](https://appwrite.io/docs/client/databases?sdk=web-default#databasesListDocuments)