---
title:Heart-Health-Devs
creator:David Perez(CoozMoo Technologies)
---
Notes for Mobile Developer (This is also added to the Web App Project ReadMe.md)
## Project Description
This application consists of two primary models, the Doctor and the Patients.
The Web App focuses on the Doctor end, where they will manage treatement for their patients,
setup consulting hours and calls. They can communicate in real time with any of their patients
with the chat functionality.
They can upload didactic and exercise material for their patients to read and follow.
To start adding the backend to the app you need to setup the project depending on your platform. For this you need to be added as a developer on the project to be able to add the `GoogleService-Info.plist` file into your project.
Remember to check the Firebase docs for project setup:
[Firebase Docs](https://firebase.google.com/docs)
## Firestore
The Firestore backend consists of Collections and Documents.
### Patient Document
The Patient App should only handle the `patients` collection, which has the following structure for each Patient document:

```JSON
"data":{
"age": 55,
"assessment": {
"3 Minute Step Test": 20,
"5 Times Sit To Stand": 40 seconds,
"6 Minute Walk Test": 100 mts,
"MLFHQ": 40 / 100
},
"current_goal": {
"fx_goal": "improve to 2",
"goal description": "goal",
"qol_goal": "Decrease from 50 to 20"
},
"doctor": "id",
"hasComments": false,
"hasMessages": true,
"id": {patientId},
"phone": 32064244,
"initial": false,
"initial_consult": 2020 - 07 - 10 03: 08: 42.137,
"last_consult": 2020 - 07 - 16 13: 24: 10.138,
"medical_status": {
"heart": {
"borg": "**" ,
"functional": 3,
"nyha": "III"
}
},
"name": "Evan",
"overview": {
"diagnostic": "Heart Failure",
"ef": 30,
"goal": "goal"
},
"status": true,
"surname": "Grace",
"vitals": {
"Blood Pressure": "120 / 80",
"Heart Rate": 80,
"Oxygenation": 85
},
"consultation": true,
"next_consult": null
}
```
You may need to edit any of these, so remeber to use `merge:true` if you are using the `set()` function:
```javascript=
//JS
const updatePatient = (patient) => {
//_firestore is your instance of firestore.
const patientRef = _firestore.collection("patients").doc(patient.id);
const result = await patientRef.set(patient.toJson, {"merge":true}); // merge only changes new elements and doesn't erase old one
console.log(result)
}
```
```typescript=
//TS
const updatePatient: Function = (patient: Patient) => {
const patientRef = _firestore.collection("patients").doc(patient.id);
const result = await patientRef.set(patient.toJson, {"merge":true});
console.log(result);
}
```
## Patient Subcollections
The Patient document contains several collections, which are going to feed your data stream.
Each of the collections are arranged in the following way:
## Calendar
The first an most complex is the `calendar` collection.
This collection consists of separate event documents which each handle a different type of activity.

Each activity has the following structure:
```json=
{
"activities": [String],
"day": TimeStamp,
"morning": bool,
"id": String,
"type": String
}
```
1. The activities is an array of strings, it was initially created to handle all of the day activities. But these where later changed to be more dynamic. So it only handles the 1 element of the array as in: `activities[0]` is the element you should be using.
2. Next is `day` this is a date and it should use the UTC TimeStamp that Firebase uses.
3. The `morning` item is a boolean, it handles wheter the activity is in the morning or afternoon.
4. Type lets the application filter exercises from instructional and vice-versa. It can only be `Exercise` or `Instructional`, this is case-sensitive.
If you are using js or ts you can use this collection like this:
```javascript=
//JS
const getCalendar = (patient) => {
//_firestore is your instance of firestore.
const calendar = _firestore.collection("patients").doc(patient.id).collection("calendar");
calendar.forEach((e) => {
console.log(e.toString());
})
}
```
```typescript=
//TS
const getCaledar: Function = (patient: Patient) => {
const calendar = _firestore.collection("patients").doc(patient.id).collection("calendar");
calendar.forEach((e) => {
console.log(e.toString());
})
}
```
After receiving the activity objects now you have to search for the video element in the `video` collection.
This collection is called "video" since initially it was only going to be video media. But the media type is now varied (mp4, pdf, jpeg);

After you have parsed the calendar element, you can call the info for the event in the following way:
```javascript=
//JS
const getCaledarEvent = (eventId) => {
const event = _firestore.collection("video").doc(eventId)
console.log(event);
}
```
```typescript=
//TS
const getCaledarEvent: Function = (eventId: string) => {
const event = _firestore.collection("video").doc(eventId)
console.log(event);
}
```
The retrieved element has to different possible data:
Exercise:
```JSON
{
"content":"This is the item content body",
"title":"This is the item title",
"doctor":"{doctorId}", //this is only useful for the Doctor app
"level":1, // A number for the level
"id":"{videoId}", // This elements id
"type": "Exercise"
}
```
Instructional:
```JSON
{
"content":"This is the item content body",
"title":"This is the item title",
"doctor":"{doctorId}", //this is only useful for the Doctor app
"id":"{videoId}", // This elements id
"type": "Instructional"
}
```
As you can see both differ in that the Exercise contains a `level` property.
Now that you have the content you need to load the media.
To load the Media you need to access the Storage. Since the media is varied you need to sift throught the possible urls since the element has to be called by the exact name. So in my case I made a sifter that combs through the URLs to get the correct URL.
```dart
//dart (Flutter)
Future<String> siftURLs(
{String id, int level}) async {
var stringList = [".jpg", ".pdf", ".mp4"];
for (var i = 0; i < stringList.length; i++) {
String ext = stringList[i];
var url = await _storage
.ref("videos/level$level/$id$ext")
.getDownloadURL()
.then((val) => val.toString())
.catchError((e) => e.toString());
print(url.toLowerCase());
print(!url.toLowerCase().contains("exist"));
if (!url.toLowerCase().contains("exist")) {
print(url);
return url;
}
}
}
```
In this snippet you can see the `_storage` instance has a ref element where you pass the path to the media element `ref("videos/level$level/$id$ext")` since the
element is an exercise and Storage is handled in traditional file system. The video folder has separate level folder (level1, level2, level3) and inside those folders you have the media types, each may be either a .jpg, .pdf or .mp4 so you need to handle the error each time one isn't found and go to the other.
Now you have both the content and the media for the content.
## Chat
The chat collection is structured in the following way:

Since message editing is used you can use the Firestore auto-ID for the document ids.
This is an example JSON from the object:
```json
{
"body":"",
"doctor": "", //The doctor that is assigned to the patient
"from":"{senderId}",
"to":"{receiverId}",
"timestamp": TimeStamp,
}
```
Now that you have the previous snippets this is just a case of substitution.
## Comments
The comments collection looks like this:

the JSON object looks like this:
```json=
{
"body":"",
"doctor": "{doctorId}",
"elementId": "elementUrl",
"level": 1,
"timestamp":TimeStamp
}
```
This is pretty straightforward, the only difference with the Chat is that this should have the reffered to media element url in the elementId. Since you shoudl already have the URl when you loaded it previously in the ***Calendar***.
## Stats
This collection looks like this:

The data depends on the collection type. Currently only the 2_min_step, 6_min_walk and qol should be read.
The received data is a map with the `[week number : value]`
example:
```jsonld=
{
"1":"30", //week 1 equals 30
"2":"40",
}
```
The values are Strings since they could be other values in the future, so you need to parse them into numbers on your end. (Sorry)
## Medications & Past Medical History
Both of these are lists of documents with a 'medical_history_item' data

You add a new document per item, meaning only one document should have a single medical_history_item.