Crio Projects - Companion App: A mental health tracker built using Flutter and Firebase. | Crio.Do | Project-Based Learning Platform for Developers

Objective

The project focuses on building a mental health tracker. You will try to get an idea of the mental state of your user (in the least intrusive ways), find out if they are suffering and then suggest measures they can take to get out of their present condition. A user answers some questions and based on the answers that they provide, you will suggest tasks to them and maintain a record of their mental state for displaying on a dashboard.

Project Context

Mental health is an important issue in the world today. With a large population now working from home and staying away from loved ones, the mental health situation has deteriorated. As such, it becomes important to track and remedy any problems before they get too serious. We try achieving this using the Companion App.


Keeping in mind that users might be suffering from mental illness and wouldn't want to engage much with an app, you'll have to design the app to be very friendly and welcoming.


By the end of this project, you'll have a beautiful and fast app that is fun to use and also serves your goal. Try implementing the best practices while building the app; the following sections will detail the implementation goals and suggest some ways to achieve them.


The app's walkthrough can be seen here:



The file structure for the completed app would be similar to the image below. You can come back to this image to understand what part of the app you've built and the files that are yet to be written.

image

Project Stages

CrioCompanionArch

The project can be broadly classified into three sections:

  1. Setting up the UI with the custom tabbar, fullscreen questions and other screens.
  2. Adding login and user profile features.
  3. Using Firebase Storage to track user information and the state.

Each of these sections have multiple tasks and are covered in detail later.


High-Level Approach

  • Build the UI, with the custom tabbar and the Tasks, Dashboard, and Doctor screens.
  • Add the questions screen and figure out fullscreen mode. Add double tap to disappear on the cards.
  • Write a simple algorithm to display tasks based on user answers.
  • Set-up your Firebase project for authentication and storage.
  • Add Google sign-in feature to track user profile.
  • Connect your local variables to the Firebase storage to make your app cloud-enabled.

Applications

  • This application can be built into a full-fledged health-care app with proper research and a few additions.
  • The skills learnt while building this app will allow you to build commercial and useful apps in the future.

Objective

The project focuses on building a mental health tracker. You will try to get an idea of the mental state of your user (in the least intrusive ways), find out if they are suffering and then suggest measures they can take to get out of their present condition. A user answers some questions and based on the answers that they provide, you will suggest tasks to them and maintain a record of their mental state for displaying on a dashboard.

Project Context

Mental health is an important issue in the world today. With a large population now working from home and staying away from loved ones, the mental health situation has deteriorated. As such, it becomes important to track and remedy any problems before they get too serious. We try achieving this using the Companion App.


Keeping in mind that users might be suffering from mental illness and wouldn't want to engage much with an app, you'll have to design the app to be very friendly and welcoming.


By the end of this project, you'll have a beautiful and fast app that is fun to use and also serves your goal. Try implementing the best practices while building the app; the following sections will detail the implementation goals and suggest some ways to achieve them.


The app's walkthrough can be seen here:



The file structure for the completed app would be similar to the image below. You can come back to this image to understand what part of the app you've built and the files that are yet to be written.

image

Project Stages

CrioCompanionArch

The project can be broadly classified into three sections:

  1. Setting up the UI with the custom tabbar, fullscreen questions and other screens.
  2. Adding login and user profile features.
  3. Using Firebase Storage to track user information and the state.

Each of these sections have multiple tasks and are covered in detail later.


High-Level Approach

  • Build the UI, with the custom tabbar and the Tasks, Dashboard, and Doctor screens.
  • Add the questions screen and figure out fullscreen mode. Add double tap to disappear on the cards.
  • Write a simple algorithm to display tasks based on user answers.
  • Set-up your Firebase project for authentication and storage.
  • Add Google sign-in feature to track user profile.
  • Connect your local variables to the Firebase storage to make your app cloud-enabled.

Applications

  • This application can be built into a full-fledged health-care app with proper research and a few additions.
  • The skills learnt while building this app will allow you to build commercial and useful apps in the future.

Start building your screens

We will set up the basic skeleton of the app first. Use your creativity to build an intuitive app and design the elements in such a way that they are appealing to people of all backgrounds. Make sure the workflow is easy to understand and follow. Ditch any design choice that would require the user to take a complex route to achieving a goal that can be done in a simpler way.


If you are building a Flutter app for the first time, refer this page. I recommend installing VSCode and the Flutter and Dart plugins to start developing apps.

Requirements

  • Research about good design practices. Learn how you can make your app more accessible and user friendly.

  • Evaluate your choice of widgets to use; fancier ones are appealing but keep utility in mind while making the choice. Check here for some cool widgets.

  • Create a Flutter project and start designing your screens.

  • Build a custom tabbar as shown in the image. To achieve that, you can look up code online. You don't need to write one on your own. image

  • Add the Tasks screen, which shows tasks only when your algorithm (see Task 3) tells it to.

  • Add the Dashboard screen; you will show comparison data over a week (or some other period) here; for instance, "User met x more people this week compared to the last one".

  • Research about the drawer layout options in Flutter and add one to your app.

    ...

Expected Outcome

All the screens should be built as shown in the images. The app doesn't have any logic implemented yet, just the facade. Dashboard.dart, Tasks.dart and CustomTabBar.dart should be written by this stage.

Bring it On!

  • Implement double back press to exit as shown in image below.

Questions Screen and UI refinement

This task focuses on making the app friendly to its target audience. You have to remember that potential users of this app would be suffering from mental illness and as such it won't be wrong to assume that asking a lot of questions won't be the best choice. In addition, the mechanism adopted for asking said questions need to be the least intrusive one you can think of. That way, we get the required information at minimum inconvenience to the end-user.


Another detail worth mentioning is the double-tap to disappear feature. Once the user is done with a task, the user can get rid of it from the screen using just a double-tap. Easy, intuitive and satisfying - just the way we want it!


An important thing to note while building the screens and using the variables that power your app, is state management.


State Management

There are different options you can take to manage state in your application. I'll list a few of them below:


Streams (BLoC)

The BLoC principle can be used to provide fast, reactive state management. The changes in variables are reflected almost instantly.


It however, requires some initial set-up and boilerplate code to get it running. Research articles on how to build reactive apps on Flutter and this might help you get started on it.


Redux

A familiar way to manage state for web developers. You can look up resources that can get you up to speed with it.


The Redux package on pub.dev is linked here.


Constructors

You can transfer variables between different screens using their constructors. It is the easiest way to achieve state management.


It however gets a bit complex with increasing state variables and might lead to complications, further into development.


You can compare both approaches and see which one works best. You're also free to find out other best practices to achieve the goal.

Requirements

  • Create a full-screen experience for the Questions UI. This is done to avoid any distractions and make the user focus on just the question on the screen.

  • Find out what widgets can be used to get answers from the user in a fun way.

  • The questions tab at the top of the Tasks section should only appear once in a day. Figure out how to implement this.

  • The tasks to be done are displayed as cards in the Tasks section. Implement gesture controlled removal of them once they are completed by the user.

    dt-gif

  • Use appropriate local variables to enable toggling of the cards visibility and for storing the answers to the questions (these variables will later be connected to cloud storage). Refer the state management practices while creating and using these variables.

Tip

  • Use bright colors for your questions screen to make them appealing.
  • Use widgets like sliders to avoid typing for answers. You are free to use other good options as well.
  • Use animations between the different questions to add flavour to the app. Refer to the walkthrough video at the top to see what animations I've used.
  • Displaying questions only once a day : To achieve this, you can add a variable that tracks the time at which the questions were answered. Save it along with other state variables in your cloud database. The code for this could be similar to this block:
Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        (!client.answered && !timeUp) ? askQuestion() : Container()],
     )

NOTE: The answered variable is true when the questions have been answered for the day. timeUp is true when 24 hours have passed since the questions were last displayed.

Bring it On!

  • Are there better ways to frame the questions?
  • Can you display virtual rewards on completing a question? (Similar to those that pop up after submitting assignments on the Microsoft Teams app)

Expected Outcome

The UI should be complete by now. Dummy cards in the Tasks section can be removed by double tapping on them. The questions appear once a day and the UI for asking questions is complete.


Implementing logic for displaying the tasks and checking if the questions have been answered for the day, will be completed in the next steps. The Questions directory should be completed by this stage. The file Tasks.dart would have been modified to implement the changes mentioned in the Requirements section.

Write a simple algorithm

Once you have all the answers to the questions, you will need to determine whether the person needs help or not. In other words, whether you need to suggest some tasks for them to feel better. How you achieve this algorithm is largely up to you; the complexity can range from a simple comparative check to more advanced classification techniques.

Requirements

  • Find out the different ways in which you can predict an outcome from a set of known variables (here, the user answers).
  • Implement one of the methods in your app. Add the logic to the Tasks.dart file to show the activity cards selectively.

Tip

  • You can use a simple threshold check (say, if answer1 > some threshold) to start off. The algorithm can be tweaked later. It is not the primary focus of the project.
  • If you plan on using more sophisticated measures, you'll also need to find a source of data that complies with your chosen questions. Only then will you be able to accurately predict outcomes.

Expected Outcome

You should have an algorithm ready that chooses to show or hide the task cards depending on the answers provided by the user.

Set up your Firebase project

We need a backend for our application to provide services like authentication, cloud storage etc. Firebase is one of the easiest ways to get started with building a backend. You can learn more about Firebase from the links provided in the References section.

Requirements

  • Research about Firebase and the features it offers.

  • Learn about other alternatives and why Firebase is being used, in particular.

  • Set up your Firebase project for use in future steps and complete configuring your Flutter app with Firebase.

    firebase-console-add-project-3-1536x870

Expected Outcome

You must have created a new project in Firebase and configured your app to work with the project. See the references for the steps to do the same.

Add Google sign-in feature

Requirements

  • Create the login page. I've used the default provided by the library. Add the code in the Login.dart file.

  • Figure out how to set up Google sign-in. Write the code for authentication in a separate file and plug it into the login page. The code that enables this goes into the authentication.dart file.

  • Verify that you can log a user in and get their information.

References

  • Firebase Authentication links1 and 2.
  • Login page idea

Tip

  • You don't have to design the login page yourselves. Avoid writing code that is easily available on the internet. I've only added one link for the design, you can find multiple others, some of which are really cool. Feel free to play around with those ideas.

Bring it On!

  • Can you implement password based authentication in your app? Learn more here.
  • You can then implement features like sign-up and password reset.
  • Try adding other authentication providers (Facebook, Microsoft and such) to supply options to the user.

Expected Outcome

You should have the login page ready and your app must support logging users in by now. None of the functionality in the app currently has anything to do with the user currently. We'll make that connection in the next task.

Connect local variables to Firebase storage.

Local variables like the answers to the questions, scores and suggestions for the users should be tied to the current user account. This can be done by creating cloudstore documents for the answers.


You should be tracking parameters like when the last answer was provided (recall that you have to show questions only once in a day), which tasks have been completed by the user and a record of the mental states and tasks completed over a period of time (say, a week) to show on the Dashboard. All files that have variables which need to be persisted or to be made available across the app should have code implemented to connect these variables to Cloud Firestore.


Developers use the Firebase SDKs for Cloud Storage to upload and download files directly from clients. Cloud Storage stores your files in a Google Cloud Storage bucket, making them accessible through both Firebase and Google Cloud.

Requirements

  • Explore Cloud Firestore in Firebase. Find out how it's different from a Realtime Database.
  • Design a structure for the documents to be stored on the database.
  • Make sure to link the data with the current user.
  • Research about using the Firebase library in Flutter to handle Cloud firestore transactions.
  • Connect all local variables to the ones in the document on firestore and implement code to perform transactions (for example, when the value changes you have to update the cloud version of the variable too; or fetching the cloud version of the variable for use in some part of the app).
  • Verify that updates from the app are reflected in your Firebase console.

Tip

  • image

Here's one way to design the document. The fields have the following meanings:

  1. answered: tracks if all the questions have been answered.
  2. hour: tracks at what hour they were answered. Used in the app to figure out if the next batch of questions has to be displayed yet or not.
  3. notDoneX: whether the X number task has been completed by the user or not.
  4. uid: The user id to which all these variables belong to.

Bring it On!

  • A challenge to solve could be using MySQL instead, for storage. This version would have local storage and can address privacy concerns and shield against poor network problems. An implementation of a local database in MySQL can easily be found online and then integrated into your own app.

Expected Outcome

Your app must be fully ready by now. The user states are saved and tasks are displayed for each user subject to the answers provided by them.

Build for release

Once you have run the app in debug mode on your phone or emulator and you feel that it is ready to be deployed, we can go ahead with deployment. An optional step before building your app for release is obfuscating your code.Obfuscation hides function and class names in your compiled Dart code, making it difficult for an attacker to reverse engineer your proprietary app. Your application backend is already deployed on Firebase.

Requirements

  • Make sure your Cloud Firestore has the correct rules for deployment. Check this link to learn more about Firebase security and rules.
  • Follow the steps here to build your Android app for release.
  • Follow the steps here to build your iOS app for release.

Bring it On!

  • Set up a continuous delivery pipeline for your Flutter app. Refer this link to learn more.

Expected Outcome

Your app must now be ready to be rolled into app stores.