DEV Community

Cover image for Enhancing user experience with real-time health data insights in Nuxt.js
Moronfolu Olufunke for Hackmamba

Posted on • Edited on

Enhancing user experience with real-time health data insights in Nuxt.js

Real-time data processing involves almost instantaneous feedback after program execution. This type of processing is critically important in the health field to track and monitor items such as user dosage or patient test results to decide on a patient's health status.

In this article, we will demonstrate the use of Appwrite to build application in Nuxt.js that allows tracking and enhancing user experience by leveraging on Appwrite's real-time feature. Appwrite is a self-hosted backend-as-a-service platform that provides developers with all the core APIs required to build any application

GitHub

Check out the complete source code here.

Prerequisites

Understanding this article requires the following:

  • Installation of Node.js
  • Basic knowledge of JavaScript and Vue.js
  • Docker installation
  • An Appwrite instance; check out this article on how to set up an instance locally or via one-click install on DigitalOcean or Gitpod
  • Installation of the Appwrite CLI

Creating a Nuxt project

Use npx create-nuxt-app <project-name> to create a new Nuxt.js project.
Scaffolding the Nuxt.js project provides a list of options, from which we will pick the one that best suits our preferences.

We can start our Nuxt3 application by running the following command:

cd <project name>
npm run dev
Enter fullscreen mode Exit fullscreen mode

Nuxt.js will, in turn, start a hot-reloading development environment that is accessible by default at http://localhost:3000.

Creating an Appwrite project

To create a new project, we will start the Appwrite instance on our machine and navigate to the specified hostname and port http://localhost:80. Next, we must log into our account or create an account if we don't have one.

Appwrite signup page

Learn more about setting up Appwrite here. On the console, click on the Create Project button.

Appwrite project creation page

The project dashboard becomes visible on the console after the project creation. We can access the inner page from the Settings tab at the bottom of the page.

Appwrite project setting

The inner page allows us to copy the Project ID and API Endpoint for our Nuxt application.

Adding Appwrite Web SDK to Nuxt.js

We will then proceed to create an init.js file in our Nuxt.js application's root directory to initialize the Appwrite Web SDK by adding the code block below:

import { Client, Account, functions } from "appwrite";
export const client = new Client();
export const account = new Account(client);
client
    .setEndpoint('http://localhost/v1') // API Endpoint
    .setProject('***') // project ID
;

export const insightFunction = () => {
  const functions = new Functions(client)
  return functions.createExecution('***') // Function ID
}
Enter fullscreen mode Exit fullscreen mode

Creating an Appwrite function

Among Appwrite's supported runtimes for creating a serverless function is Node.js. Appwrite's serverless function gives room to build on and customize Appwrite server functionality by adding and executing our custom code.

Integrating Appwrite function in Nuxt.js

We will start by logging onto Appwrite's server using the Appwrite command-line interface (CLI), like so:

appwrite login
Enter fullscreen mode Exit fullscreen mode

Running the command above requires us to use our Appwrite credentials in the terminal.

After logging into the application, we will initialize and link the Nuxt.js application with the previously created Appwrite project. To do this, we will run the command below:

appwrite init project
Enter fullscreen mode Exit fullscreen mode

Running the command above will display a list of options from which we will pick those appropriate for our project.

Next, let’s create a function in our Nuxt.js application. We will do this by running the command below:

appwrite init function
Enter fullscreen mode Exit fullscreen mode

At the successful execution of the above command, we will see a new folder named functions/<function-name> in our Nuxt.js application.

Deploying the Appwrite function

To deploy the Appwrite function, we will run the command below:

appwrite deploy function
Enter fullscreen mode Exit fullscreen mode

Executing the above command will require us to pick the appropriate function we want to deploy. Upong successful deployment, we will get a message like the one below in our terminal.

 Success Deployed <function-name> ( functionID)
Enter fullscreen mode Exit fullscreen mode

In our Appwrite function console, we will also have a view that looks like the below:

Deploying Appwrite Function

This signifies the successful deployment of our Appwrite function.

We will also update the function's permissions to allow access within the Nuxt.js application. To do this, navigate to the Settings tab and add a role of any to the Executive Access field:

Appwrite Function Permission

Creating the signup page

We will create a signup page where people who will later be assigned roles to perform certain operations within the database can generically create an account. To do this, we will create a components/Sign-up.vue and add the code below:

<template>
  <div class="ba b--light-blue bg-light-blue bw3 vh-100 pv5 ph2 athelas">
    <form @submit.prevent="signUp" class="white bg-navy br3 mw6 w-40-m w-70 w-20-l center pa3 shadow-5">
      <h2 class="ttc tc">Sign up</h2>
      <label for="name" class="db mb1 white">Name</label>
      <input name="name" id="name" type="text" class="db mb3 w-100 br3 pa2 ba bw2" placeholder="John Doe" v-model="name">
      <label for="email" class="db mb1 white">Email</label>
      <input name="email" id="email" type="email" class="db mb3 w-100 br3 pa2 ba bw2" placeholder="example@email.com" v-model="email">
      <label for="password" class="db mb1 white">Password</label>
      <input name="password" id="password" type="password" class="db mb3 w-100 br3 pa2 ba bw2" placeholder="••••••••" v-model="password">
      <label for="confirm-password" class="db mb1 white">Confirm Password</label>
      <input name="confirm-password" id="confirm-password" type="password" class="db mb3 w-100 br3 pa2 ba bw2" v-model="confirmPassword" placeholder="••••••••">
      <button type="submit" class="center db ph4 pv2 bg-navy ba br3 white pointer">Sign up</button>

      <p>Already have an account? <a href="/signin" class="white b">Sign in</a> </p>
    </form>    
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Implementing the code block above, we achieved the following:

  • Created a functional form to handle input from potential users of our dashboard
  • Added the data in the Vue script to manage the username, email, and password of the people who will fill out the form

Adding the signup functionality

Our interface will need to be connected to Appwrite to authenticate users. To do this, we will add the following code in the <script> tag of our components/Sign-up.vue file.

<script lang="ts">
import Vue from 'vue'
import {account} from '~/init'
export default Vue.extend({
  data: () => ({
    name: "",
    email: "",
    password: "",
    confirmPassword: ""
  }),
  methods: {
    signUp: async function(){
      if (this.password.length >= 8){
        if(this.password === this.confirmPassword) {
          try{
            await account.create('unique()', this.email, this.password, this.name)
            alert("account created successfully")
            window.location.href = '/signin'
          } catch (e) {
            console.log(e)
          }
        } else {
          alert("password do not match")
        }
      } else {
        alert("password length should be up to 8 characters")
      }
    },

  }

})
</script>
Enter fullscreen mode Exit fullscreen mode

The code block above achieves the following:

  • Imports the Appwrite SDK initialized in the init.js file.
  • Creates the signUp function in the methods property, which performs the following functions:
    • Verifies that the password length is equal to or greater than eight characters.
    • Confirms that the characters in password and confirmPassword are the same.
    • Accesses Appwrite's services using the account.create to create a new account using the user's email, password, and name.
      • To use Appwrite's create account service, it's mandatory to add the userId; in this case, we used uniqueId to generate one automatically.
      • Adding email and password is also mandatory.
      • The name option is optional; we can create an account without one.
    • window.location.href allowed us to navigate to the insight interface after successful account creation.

Next, let's import the components/Sign-up.vue into the pages/index.vue, like so:

<template>
  <div>
    <Signup/>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

At this point, our signup page should look like the below:

signup page

Creating the sign in interface

We also need to create a sign in page that allows registered users to log in to the dashboard. To do this, we will create a pages/Signin.vue and add the code below:

<template>
  <div class="ba b--light-blue bg-light-blue bw3 vh-100 pv5 ph2 athelas">
    <form @submit.prevent="signIn" class="bg-navy br3 mw6 w-40-m w-70 w-20-l center pa3 shadow-5 white">
      <h2 class="ttc tc">Sign In</h2>
      <label for="email" class="db mb1 white">Email</label>
      <input name="email" id="email" v-model="email" type="email" class="db mb3 w-100 br3 pa2 ba bw2" placeholder="example@email.com">
      <label for="password" class="db mb1 white">Password</label>
      <input name="password" id="password" v-model="password" type="password" class="db mb3 w-100 br3 pa2 ba bw2" placeholder="••••••••">
      <button type="submit" class="center db ph4 pv2 bg-navy ba br3 white pointer">Sign in</button>

    </form>    
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

The code block above achieves the following:

  • Creates a functional form to handle input from registered users
  • Adds the data in the Vue script to manage the email and password

Adding the signin functionality

Our interface must be connected to Appwrite to authenticate users for signing in. To do this, we will add the code below in the Signin.vue.

<script lang="ts">
import Vue from 'vue'
import {account} from '~/init'
export default Vue.extend({
  data: () => ({
    email: "",
    password: "",
  }),
  methods: {
    signIn: async function () {
      try{
        let accountDetails = await account.createEmailSession(this.email, this.password)
        alert("user signed in")
        this.$router.push({ path: `/insight/${accountDetails.userId}`})
      } catch (e){
          console.log(e)
      }
    }
  }

})
</script>
Enter fullscreen mode Exit fullscreen mode

Above, we imported the Appwrite SDK initialized in the init.js file. We also created a function called signIn that does the following:

  • Accesses Appwrite's services using the account.createEmailSession to create a new account session using the user's email and password
  • this.$router.push allows us to navigate to the insight interface after successful user login

At this point, our interface will look like this:

Sign-in page

Setting up Appwrite's database

One of the services offered by Appwrite is the Database Service, which allows us to store data and fetch it as needed.

Creating a database

To create a database in Appwrite, click on the Database option in the menu tab, where we can add a database to the system.

Creating a database

Creating a collection

Appwrite's database services also provide collection services. These collections act as containers for documents. To create a collection, select the desired database from which we can add a new collection.

Creating a collection

Creating an attribute

Our document will have some particular attributes. To create them, we will navigate to the Attributes section. In our case, we will choose the Boolean Attribute. We can then create an Attribute ID with the name "doses".

Creating an attribute

Now, will set the permission roles for the document. Click on the Settings tab, and in the Role input field, pick the role that best describes to whom we are giving access.

Set permission roles

In our case, the role is any, and we will allow all four actions: create, read, update, and delete.

Creating the Insight page

We will be creating a page where we track users' dosages. Every day a user is allowed to take just three doses, after which they are prompted to log in the next day to get access to more doses.

We will start by creating an interface that allows users to log their dosage. To do this, we will create a pages/_insight/insight.vue and add the code below:

<template>
  <div class="bg-light-blue vh-100 pa3 tc">
    <h2 class="ttc">Real Time Health Data analytics with Appwrite</h2>
    <div class="br3 bg-navy ba near-white b--black-10 shadow-3 w-100 w-60-m w-30-l mw6 center mt5 ph4 pv4 h5">
      <p class="f3">Click on this button to get the dosage</p>
        <button class="link br3 pv2 ph2 mt4 dib black fw6 bg-white ba b--navy pointer inline-flex items-center hover-bg-lightest-blue" @click="getDosage">
          <span class="f4 ml2 pr2">Get dosage</span>
        </button>
    </div>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

The code above achieves the following:

  • Creates an interface where users are redirected after sign up or sign in
  • The insight interface allows users to click on a button getDosage to track their dosage journey for each day

Adding the getDosage() functionality

Now we will connect the interface to a working functionality that allows users to log and track their dosage.

<script>
import {client, insightFunction} from '~/init'
import { Databases } from "appwrite";
const databases = new Databases(client);
import moment from "moment";
export default {
  data() {
    return {
      permisssionsArray: [],
    }
  },
  mounted() {
    insightFunction().then((res)=> res).catch((error)=> {
      console.log(error)
    })
    this.checkDosage();
    if(this.$route.params.insight){
      try {
        client.subscribe("documents", (response) => {
          this.checkDosage();
        });
      } catch (error) {
        console.log(error, "error");
      }
    }
  },
  methods: {
    moment,
    async getDosage() {
      await databases.createDocument(
        "63ef7e057f16c9d0b811",
        "63ef7e389fdfbe02d8e9",
        "unique()",
        {
          doses: true,
        }
      );
    },
    async checkDosage() {
      const dosageDetails = await databases.listDocuments(
        "63ef7e057f16c9d0b811",
        "63ef7e389fdfbe02d8e9"
      );
      dosageDetails.documents.filter(obj => {
        if( moment(obj.$createdAt).format("YYYY-MM-DD") === moment().format("YYYY-MM-DD")) {
          obj.$permissions.find(element => {
          if(element.includes(this.$route.params.insight)) {
            this.permisssionsArray.push(element)
            if (this.permisssionsArray.length >= 3){
              this.$swal({icon: 'success', title: 'Wait one day before taking another dose. Take a walk instead', timer: 10000, showConfirmButton: false,});
            }
              return;
            } else {
              return;
            }
          })
        }
      })
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

The code above achieves the following:

  • Imports the dependencies from the init.js file as well as from Appwrite.
  • Installed the moment.js package, which we used for checking and comparing the days for the dosages.
  • The getDosage method accesses the databases method from Appwrite to create a new document in the database. This method takes the database ID, collection ID, Appwrite's ID.unique() method, and the attribute value(s) as parameters. In this case, our attribute value is doses, which we created on the Appwrite admin dashboard.
  • We call the listMessages() function, which lists all the messages that were sent to the Appwrite's database.
  • Checks whether the user has taken up to 3 doses and shows a notification telling the user to come back the next day.

At this point, our application should look like the below:

Final application look

Conclusion

This article discusses enhancing user experience by providing data insights using Appwrite's real-time features.

Resources

Top comments (0)