Fakultas Ilmu Komputer UI

Commit dfa1ac48 authored by Doan Andreas Nathanael's avatar Doan Andreas Nathanael
Browse files

Merge branch 'staging' of...

Merge branch 'staging' of https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2021/DD/pt-gizi-sehat-dietela/dietela-mobile into PBI-10-diet_profile_ntr_form
parents 88cc3d39 7155e4dd
# localhost
API_BASE_URL=http://localhost:8000/
GOOGLE_CLIENT_ID=813112248680-ulv0amtocut652j31qbpvubtclbd2c7o.apps.googleusercontent.com
# staging
API_BASE_URL=https://dietela-backend.herokuapp.com/
GOOGLE_CLIENT_ID=
# production
API_BASE_URL=
GOOGLE_CLIENT_ID=
API_BASE_URL=http://localhost:8000
GOOGLE_CLIENT_ID=813112248680-ulv0amtocut652j31qbpvubtclbd2c7o.apps.googleusercontent.com
API_BASE_URL=https://dietela-backend.herokuapp.com
GOOGLE_CLIENT_ID=813112248680-ulv0amtocut652j31qbpvubtclbd2c7o.apps.googleusercontent.com
......@@ -8,7 +8,14 @@
Dietela is an Android-based application that provides personalised diet and online nutritionist consultation services.
Check out Dietela app by downloading the APK file [here](https://drive.google.com/drive/folders/1Irc2aiSuvhysRSDDd6pwAAfbgUkkobmk?usp=sharing)!
## Installation Manual
## Table of Contents
- [Getting Started](#getting-started)
- [Environment Configuration](#environment-configuration)
- [Current Features (PBIs)](#current-features-pbis)
- [Developers](#developers)
## Getting Started
* Install npm (version 6 or later).
* Install yarn by `npm install --global yarn`.
......@@ -16,43 +23,32 @@ Check out Dietela app by downloading the APK file [here](https://drive.google.co
* Clone the repository.
* Enter the project directory with `cd dietela-mobile`.
* Build the dependencies with `yarn install`.
* Create `.env` file based on `.env.example`.
* Create `.env` file by following the [environment configuration](#environment-configuration) instructions.
* Run and build the app in development node by running `yarn android`.
* View it in your Android emulator or physical device.
## Current Features
- PBI 1: Dietela Quiz & Profile Dietku (Client)
Clients are required to fill out a quiz related to the design needs of the diet program that will be made by Dietela team
- PBI 2: Dietela Quiz & Profile Dietku (Dietela team)
Dietela team can store client data to provide quiz results containing programs and nutritionists recommendation to clients
- PBI 3: Choose Plan
Clients can continue by choosing recommended diet program that is suitable for their needs
- PBI 4: Registration
Clients can register an account to access Dietela's authenticated-only features
- PBI 5: Login
Clients can do authentication using a registered account to access Dietela's authenticated-only features
- PBI 6: Logout
## Environment Configuration
Clients can sign out from the Dietela app
We have three different environment settings:
- PBI 7: Checkout
| Environment | Branch | Example file | Which env should I use? |
| ------------- | ---------- | ------------------------ | --------------------------------------------------------------------- |
| Localhost | - | `.env.local.example` | You are a backend developer wanting to test your code changes locally |
| Staging | staging | `.env.staging.example` | You are a mobile developer wanting to update the app codebase |
| Production | master | - | NOT for development purposes |
Clients can choose a diet program and a nutritionist then proceed to do the payment
For more granular configurations, use `.env.example` to get all needed environment variables and insert the missing values.
- PBI 8: Payment Integration
## Current Features (PBIs)
Clients can perform payment using a third party payment gateway (Midtrans)
1. Dietela Quiz & Profile Dietku (Client) - Clients are required to fill out a quiz related to the design needs of the diet program that will be made by Dietela team.
2. Dietela Quiz & Profile Dietku (Dietela team) - Dietela team can provide results containing diet assessment and program recommendations based on the clients' quiz answers.
3. Choose Plan - Clients can choose recommended diet program and nutritionist suitable for their needs.
4. Registration - Clients can create an account to access Dietela's premium features.
5. Login - Clients can sign in with a registered account or via Google authentication to access Dietela's premium features.
6. Logout - Clients can sign out from the Dietela app.
7. Checkout - Clients can view their chosen diet program and nutritionist and proceed to pay.
8. Payment Integration - Clients can perform payment using a third-party payment gateway (Midtrans).
## Developers
......
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>dietela_mobile</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
......@@ -3,6 +3,8 @@
package="com.dietela_mobile">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".MainApplication"
......
......@@ -4,6 +4,7 @@ import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.rnfs.RNFSPackage;
import com.reactnativecommunity.asyncstorage.AsyncStoragePackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactInstanceManager;
......
rootProject.name = 'dietela_mobile'
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
......
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.75 0V3.5H12.25L8.75 0Z" fill="black"/>
<path d="M8.75 4.375C8.26788 4.375 7.875 3.98213 7.875 3.5V0H2.625C2.14288 0 1.75 0.392875 1.75 0.875V13.125C1.75 13.608 2.14288 14 2.625 14H11.375C11.858 14 12.25 13.608 12.25 13.125V4.375H8.75ZM5.25 12.25H3.5V9.625H5.25V12.25ZM7.875 12.25H6.125V7.875H7.875V12.25ZM10.5 12.25H8.75V6.125H10.5V12.25Z" fill="black"/>
</svg>
......@@ -5,3 +5,6 @@ export const default_nutritionist = require('./default_nutritionist.png');
export const googleLogo = require('./google_logo.png');
export const dietelaLogo = require('./dietela_logo.png');
export const diet_report = require('./diet_report.png');
export const chat = require('./chat.png');
......@@ -16,6 +16,8 @@ target 'dietela_mobile' do
pod 'RNGoogleSignin', :path => "../node_modules/@react-native-google-signin/google-signin"
pod 'RNFS', :path => '../node_modules/react-native-fs'
target 'dietela_mobileTests' do
inherit! :complete
# Pods for testing
......
import {
DietQuestionnaireResponse,
DietQuestionnaireRequest,
} from 'services/dietQuestionnaire/models';
import { authResponse } from './auth';
const validFormValues: DietQuestionnaireRequest = {
agree_to_all_statements_consent: 1,
personal_data_consent: 1,
general_purpose: 1,
date_of_birth: '1995-12-30',
city_and_area_of_residence: 'yang jauh disana',
handphone_no: '081234567890',
whatsapp_no: '080987654321',
profession: 4,
last_education: 5,
meal_preference: 2,
waist_size: 60,
dietary_change: 2,
has_weigher: 1,
breakfast_frequency: 3,
breakfast_meal_type: 2,
sweet_tea_consumption_frequency: 9,
coffee_consumption_frequency: 9,
milk_consumption_frequency: 9,
other_drink_consumption_frequency: 9,
additional_sugar_in_a_day: 7,
liquid_consumption_frequency: 3,
meal_consumed_almost_every_day: 'gaada',
unliked_food: 'semua',
preferred_food_taste: 'gaada',
expected_food_on_breakfast: 'makanan mahal',
expected_food_on_lunch_dinner: 'makanan murah',
breakfast_meal_explanation: 'jadi, makan pagi saya tuh ga teratur hehe bye',
morning_snack_explanation: 'ga nyemil',
lunch_meal_explanation: 'yg penting enak',
evening_snack_explanation: 'gtw',
dinner_meal_explanation: 'makan enak',
night_snack_explanation: 'indomi',
food_alergies: 'kl banyak mo apa hah',
diet_drinks: 'hah',
meal_provider: [1, 2, 3],
cigarette_alcohol_condition: [],
multivitamin_tablet_suplement: 'gatau',
physical_activity: [1, 2],
other_physical_activity: 'another one',
diet_and_life_style_story: 'kepo bgt si',
disease: [17],
complaint: [1, 2, 3, 4, 5],
regular_drug_consumption: 'obatobatan',
other_disease: 'dis-ease',
motivation_using_dietela: 'biar kurus',
dietela_nutritionist_expectation: 'yg jago ya',
dietela_program_expectation: 'bikin sy kurus ya, kl gagal balikin duit lho',
};
export const mockDietQuestionnaire: DietQuestionnaireResponse = {
id: 7,
...validFormValues,
finished_steps: [],
user: authResponse.user,
};
export const mockDietRecommendation = {
id: 1,
client_plan_meal: '',
nutritional_advice: 'good job',
lifestyle_advice: 'haiya',
nutritionist: 1,
client: 1,
};
jest.mock('react-native-fs', () => {
return {
mkdir: jest.fn(),
moveFile: jest.fn(),
copyFile: jest.fn(),
pathForBundle: jest.fn(),
pathForGroup: jest.fn(),
getFSInfo: jest.fn(),
getAllExternalFilesDirs: jest.fn(),
unlink: jest.fn(),
exists: jest.fn(),
stopDownload: jest.fn(),
resumeDownload: jest.fn(),
isResumable: jest.fn(),
stopUpload: jest.fn(),
completeHandlerIOS: jest.fn(),
readDir: jest.fn(),
readDirAssets: jest.fn(),
existsAssets: jest.fn(),
readdir: jest.fn(),
setReadable: jest.fn(),
stat: jest.fn(),
readFile: jest.fn(),
read: jest.fn(),
readFileAssets: jest.fn(),
hash: jest.fn(),
copyFileAssets: jest.fn(),
copyFileAssetsIOS: jest.fn(),
copyAssetsVideoIOS: jest.fn(),
writeFile: jest.fn(),
appendFile: jest.fn(),
write: jest.fn(),
downloadFile: jest.fn(),
uploadFiles: jest.fn(),
touch: jest.fn(),
MainBundlePath: jest.fn(),
CachesDirectoryPath: jest.fn(),
DocumentDirectoryPath: jest.fn(),
ExternalDirectoryPath: jest.fn(),
ExternalStorageDirectoryPath: jest.fn(),
TemporaryDirectoryPath: jest.fn(),
LibraryDirectoryPath: jest.fn(),
PicturesDirectoryPath: jest.fn(),
};
});
export {};
......@@ -2,13 +2,16 @@ import * as ROUTES from 'constants/routes';
import {
publicNavigation,
unpaidClientNavigation,
onboardingClientNavigation,
clientNavigation,
nutritionistNavigation,
} from 'constants/navigation';
import { User, UserRole } from 'services/auth/models';
import { UserRole, AuthUserResponse } from 'services/auth/models';
import { TransactionStatus } from 'services/payment/models';
export const getNavigation = (isAuthenticated: boolean, user: User) => {
export const getNavigation = (
isAuthenticated: boolean,
user: AuthUserResponse,
) => {
if (isAuthenticated) {
if (user.role === UserRole.CLIENT) {
if (user.transaction_status === TransactionStatus.UNPAID) {
......@@ -16,17 +19,20 @@ export const getNavigation = (isAuthenticated: boolean, user: User) => {
initialRoute: ROUTES.checkout,
navigation: unpaidClientNavigation,
};
} else if (!user.has_profile) {
return {
initialRoute: ROUTES.extendedQuestionnaire,
navigation: onboardingClientNavigation,
};
}
return {
initialRoute: ROUTES.clientProfile,
initialRoute: user.is_finished_onboarding
? ROUTES.clientProfile
: ROUTES.extendedQuestionnaire,
navigation: clientNavigation,
};
}
if (user.role === UserRole.NUTRITIONIST) {
return {
initialRoute: ROUTES.clientListForNutritionist,
navigation: nutritionistNavigation,
};
}
}
return {
initialRoute: ROUTES.initial,
......
import React from 'react';
import { render } from '@testing-library/react-native';
import EmptyDataPage from '.';
describe('EmptyDataPage', () => {
it('renders correctly', () => {
render(<EmptyDataPage text="No data" />);
});
});
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment