├── .all-contributorsrc ├── .github ├── issue_template.md └── pull_request_template ├── .gitignore ├── LICENSE ├── README.md ├── android ├── .gitignore ├── app │ ├── build.gradle │ ├── google-services.json │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── soochit │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── soochit_android.iml ├── assets ├── fonts │ ├── AirbnbCereal-Bold.ttf │ └── LexendDeca-Regular.ttf └── images │ └── medicine.png ├── code_of_conduct.md ├── ios ├── .DS_Store ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── functions │ ├── notificationPlugin.dart │ └── notificationScreen.dart ├── global │ ├── myColors.dart │ ├── myDimens.dart │ ├── mySpaces.dart │ └── myStrings.dart ├── main.dart ├── pages │ ├── authentication │ │ ├── enterOTP.dart │ │ ├── register.dart │ │ ├── signout-function.dart │ │ └── splashScreen.dart │ ├── doctor-specific │ │ ├── doctorProfile.dart │ │ ├── doctorRegistration.dart │ │ ├── homeDoctor.dart │ │ ├── patientHistory.dart │ │ ├── prescription.dart │ │ └── samplePatientProfile.dart │ ├── login.dart │ ├── patient-specific │ │ ├── homePatient.dart │ │ ├── medicineDeadlines.dart │ │ ├── patientRegistration.dart │ │ └── prescriptionHistory.dart │ └── welcome.dart ├── stores │ ├── login_store.dart │ └── login_store.g.dart └── widgets │ ├── addMedicineDialog.dart │ ├── addPatientDialog.dart │ ├── loaderHud.dart │ ├── medicineDeadlineReminder.dart │ ├── prescriptionHistoryCard.dart │ ├── previousPatientCard.dart │ └── snackbar.dart ├── pubspec.yaml ├── screenshots.md ├── setup-instructions.md ├── soochit.iml └── test └── widget_test.dart /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "dotrachit", 10 | "name": "Rachit Gupta", 11 | "avatar_url": "https://avatars1.githubusercontent.com/u/44428198?v=4", 12 | "profile": "http://rachitgupta.co", 13 | "contributions": [ 14 | "code", 15 | "design" 16 | ] 17 | }, 18 | { 19 | "login": "Imperial-lord", 20 | "name": "AB Satyaprakash", 21 | "avatar_url": "https://avatars0.githubusercontent.com/u/45942031?v=4", 22 | "profile": "https://imperial-lord.github.io/mywebsite/", 23 | "contributions": [ 24 | "code" 25 | ] 26 | }, 27 | { 28 | "login": "Ajitesh13", 29 | "name": "Ajitesh Panda", 30 | "avatar_url": "https://avatars0.githubusercontent.com/u/42615579?v=4", 31 | "profile": "https://bugzilla.mozilla.org/user_profile?user_id=650533", 32 | "contributions": [ 33 | "code" 34 | ] 35 | } 36 | ], 37 | "contributorsPerLine": 7, 38 | "projectName": "soochit", 39 | "projectOwner": "MLH-Fellowship", 40 | "repoType": "github", 41 | "repoHost": "https://github.com", 42 | "skipCi": true 43 | } 44 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | 3 | 4 | 5 | ## Steps to reproduce 6 | 7 | 8 | 9 | ## Expected behaviour 10 | 11 | 12 | 13 | ## Observed behaviour 14 | 15 | 16 | 17 | ## Logcat for the issue 18 | 19 | 20 | 21 | ## Device and OS version 22 | 23 | 27 | 28 | ## Screenshots 29 | 30 | 31 | -------------------------------------------------------------------------------- /.github/pull_request_template: -------------------------------------------------------------------------------- 1 | ## Issue Fix 2 | Fixes #Issue_Number 3 | 4 | ## Screenshots 5 | 6 | 7 | ## Description 8 | 9 | 10 | ## Reviewers 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | build/ 5 | .idea/ 6 | # If you're building an application, you may want to check-in your pubspec.lock 7 | pubspec.lock 8 | 9 | # Directory created by dartdoc 10 | # If you don't generate documentation locally you can remove this line. 11 | doc/api/ 12 | 13 | # Avoid committing generated Javascript files: 14 | *.dart.js 15 | *.info.json # Produced by the --dump-info flag. 16 | *.js # When generated by dart2js. Don't specify *.js if your 17 | # project includes source files written in JavaScript. 18 | *.js_ 19 | *.js.deps 20 | *.js.map 21 | 22 | .DS_Store 23 | 24 | .flutter-plugins 25 | .flutter-plugins-dependencies 26 | 27 | .vscode 28 | 29 | android/.idea 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-) 2 | 3 | 4 | Awesome Flutter 5 | 6 | 7 | 8 | # Soochit 👩‍⚕️ 9 | 10 | Not just another medicine reminder. 11 | 12 | ## Problem Statement 13 | * It's hard for people to keep a physical folder for their medical prescription history. 14 | * People (like us) are lazy enough to procrastinate setting medicine reminders primarily because they have to do the hard task of manually labelling the reminder, setting the time, and setting the frequency of the medicines. 15 | 16 | ## Solution 17 | 18 | Soochit: a fullly automated e-prescription tracker and medicine reminder. 19 | 20 | * The doctor will write digital prescriptions on our app which will be saved on user's profile. 21 | * We will send out automatical reminders for the patients to take their medicines (entirely based off what is written in the prescription.) 22 | 23 | ## Use Cases 24 | 25 | * Patients won't have to set reminders manually. Hence, there is no way for them to procrastinate. 26 | * Patients won't have to keep a physical binder to maintain their medical history. 27 | * Patients won't have to confuse themselves by reading the (mostly incomprehensible) handwriting of the doctor once they forget their medicines, dosage, or timings. 28 | 29 | ## Unique Selling Point (USP) 30 | it is a medicine reminder app, but you don't have to set reminders for your medicines. 😉 31 | 32 | ## Getting Started 33 | In order to setup the project locally, check the defined setup instructions [here](/setup-instructions.md). 34 | 35 | ## Contributors ✨ 36 | 37 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |

Rachit Gupta

💻 🎨

AB Satyaprakash

💻

Ajitesh Panda

💻
49 | 50 | 51 | 52 | 53 | 54 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 55 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'com.google.gms.google-services' 26 | apply plugin: 'kotlin-android' 27 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 28 | 29 | android { 30 | compileSdkVersion 28 31 | 32 | sourceSets { 33 | main.java.srcDirs += 'src/main/kotlin' 34 | } 35 | 36 | lintOptions { 37 | disable 'InvalidPackage' 38 | } 39 | 40 | defaultConfig { 41 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 42 | applicationId "com.example.soochit" 43 | minSdkVersion 16 44 | targetSdkVersion 28 45 | versionCode flutterVersionCode.toInteger() 46 | versionName flutterVersionName 47 | multiDexEnabled true 48 | } 49 | 50 | buildTypes { 51 | release { 52 | // TODO: Add your own signing config for the release build. 53 | // Signing with the debug keys for now, so `flutter run --release` works. 54 | signingConfig signingConfigs.debug 55 | } 56 | } 57 | } 58 | 59 | flutter { 60 | source '../..' 61 | } 62 | 63 | dependencies { 64 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 65 | implementation 'com.google.firebase:firebase-analytics:17.5.0' 66 | } 67 | -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "88365186057", 4 | "firebase_url": "https://soochit-mlh113-team3.firebaseio.com", 5 | "project_id": "soochit-mlh113-team3", 6 | "storage_bucket": "soochit-mlh113-team3.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:88365186057:android:ac423c4e205332d8600cd8", 12 | "android_client_info": { 13 | "package_name": "com.example.soochit" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "88365186057-pb2tv6b3kauansoec1un0b7l54bdqrfq.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.example.soochit", 22 | "certificate_hash": "097bbd52d2016706a57590ef155257cda5af00f7" 23 | } 24 | }, 25 | { 26 | "client_id": "88365186057-p84oj48uvuk60ku0n0cb2qerv4r7fcth.apps.googleusercontent.com", 27 | "client_type": 1, 28 | "android_info": { 29 | "package_name": "com.example.soochit", 30 | "certificate_hash": "b6917d7b9e3447f04ea3c5d20b6b83df827c2c9f" 31 | } 32 | }, 33 | { 34 | "client_id": "88365186057-gdbs9u6c3aouep8pad8ps723ht8tifo5.apps.googleusercontent.com", 35 | "client_type": 3 36 | } 37 | ], 38 | "api_key": [ 39 | { 40 | "current_key": "AIzaSyCchNMEOnCRrsn2kgMusIFXr0mD025Pzng" 41 | } 42 | ], 43 | "services": { 44 | "appinvite_service": { 45 | "other_platform_oauth_client": [ 46 | { 47 | "client_id": "88365186057-gdbs9u6c3aouep8pad8ps723ht8tifo5.apps.googleusercontent.com", 48 | "client_type": 3 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | ], 55 | "configuration_version": "1" 56 | } -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 10 | 11 | 12 | 16 | 23 | 27 | 31 | 36 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/soochit/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.soochit 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.google.gms:google-services:4.3.3' 10 | classpath 'com.android.tools.build:gradle:3.5.0' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /android/soochit_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /assets/fonts/AirbnbCereal-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/assets/fonts/AirbnbCereal-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/LexendDeca-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/assets/fonts/LexendDeca-Regular.ttf -------------------------------------------------------------------------------- /assets/images/medicine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/assets/images/medicine.png -------------------------------------------------------------------------------- /code_of_conduct.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, religion, or sexual identity 11 | and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the 27 | overall community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or 32 | advances of any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email 36 | address, without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series 87 | of actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or 94 | permanent ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within 114 | the community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.0, available at 120 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 121 | 122 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 123 | enforcement ladder](https://github.com/mozilla/diversity). 124 | 125 | [homepage]: https://www.contributor-covenant.org 126 | 127 | For answers to common questions about this code of conduct, see the FAQ at 128 | https://www.contributor-covenant.org/faq. Translations are available at 129 | https://www.contributor-covenant.org/translations. 130 | 131 | -------------------------------------------------------------------------------- /ios/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/.DS_Store -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1020; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | FRAMEWORK_SEARCH_PATHS = ( 293 | "$(inherited)", 294 | "$(PROJECT_DIR)/Flutter", 295 | ); 296 | INFOPLIST_FILE = Runner/Info.plist; 297 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 298 | LIBRARY_SEARCH_PATHS = ( 299 | "$(inherited)", 300 | "$(PROJECT_DIR)/Flutter", 301 | ); 302 | PRODUCT_BUNDLE_IDENTIFIER = com.example.soochit; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 305 | SWIFT_VERSION = 5.0; 306 | VERSIONING_SYSTEM = "apple-generic"; 307 | }; 308 | name = Profile; 309 | }; 310 | 97C147031CF9000F007C117D /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 316 | CLANG_CXX_LIBRARY = "libc++"; 317 | CLANG_ENABLE_MODULES = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 320 | CLANG_WARN_BOOL_CONVERSION = YES; 321 | CLANG_WARN_COMMA = YES; 322 | CLANG_WARN_CONSTANT_CONVERSION = YES; 323 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INFINITE_RECURSION = YES; 328 | CLANG_WARN_INT_CONVERSION = YES; 329 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 330 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 331 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 334 | CLANG_WARN_STRICT_PROTOTYPES = YES; 335 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 336 | CLANG_WARN_UNREACHABLE_CODE = YES; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | COPY_PHASE_STRIP = NO; 340 | DEBUG_INFORMATION_FORMAT = dwarf; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | ENABLE_TESTABILITY = YES; 343 | GCC_C_LANGUAGE_STANDARD = gnu99; 344 | GCC_DYNAMIC_NO_PIC = NO; 345 | GCC_NO_COMMON_BLOCKS = YES; 346 | GCC_OPTIMIZATION_LEVEL = 0; 347 | GCC_PREPROCESSOR_DEFINITIONS = ( 348 | "DEBUG=1", 349 | "$(inherited)", 350 | ); 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 358 | MTL_ENABLE_DEBUG_INFO = YES; 359 | ONLY_ACTIVE_ARCH = YES; 360 | SDKROOT = iphoneos; 361 | TARGETED_DEVICE_FAMILY = "1,2"; 362 | }; 363 | name = Debug; 364 | }; 365 | 97C147041CF9000F007C117D /* Release */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ALWAYS_SEARCH_USER_PATHS = NO; 369 | CLANG_ANALYZER_NONNULL = YES; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 375 | CLANG_WARN_BOOL_CONVERSION = YES; 376 | CLANG_WARN_COMMA = YES; 377 | CLANG_WARN_CONSTANT_CONVERSION = YES; 378 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 379 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 380 | CLANG_WARN_EMPTY_BODY = YES; 381 | CLANG_WARN_ENUM_CONVERSION = YES; 382 | CLANG_WARN_INFINITE_RECURSION = YES; 383 | CLANG_WARN_INT_CONVERSION = YES; 384 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 385 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 386 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 387 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 388 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 389 | CLANG_WARN_STRICT_PROTOTYPES = YES; 390 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 391 | CLANG_WARN_UNREACHABLE_CODE = YES; 392 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 393 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 394 | COPY_PHASE_STRIP = NO; 395 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 396 | ENABLE_NS_ASSERTIONS = NO; 397 | ENABLE_STRICT_OBJC_MSGSEND = YES; 398 | GCC_C_LANGUAGE_STANDARD = gnu99; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 402 | GCC_WARN_UNDECLARED_SELECTOR = YES; 403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 404 | GCC_WARN_UNUSED_FUNCTION = YES; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | SDKROOT = iphoneos; 409 | SUPPORTED_PLATFORMS = iphoneos; 410 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 411 | TARGETED_DEVICE_FAMILY = "1,2"; 412 | VALIDATE_PRODUCT = YES; 413 | }; 414 | name = Release; 415 | }; 416 | 97C147061CF9000F007C117D /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 419 | buildSettings = { 420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 421 | CLANG_ENABLE_MODULES = YES; 422 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 423 | ENABLE_BITCODE = NO; 424 | FRAMEWORK_SEARCH_PATHS = ( 425 | "$(inherited)", 426 | "$(PROJECT_DIR)/Flutter", 427 | ); 428 | INFOPLIST_FILE = Runner/Info.plist; 429 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 430 | LIBRARY_SEARCH_PATHS = ( 431 | "$(inherited)", 432 | "$(PROJECT_DIR)/Flutter", 433 | ); 434 | PRODUCT_BUNDLE_IDENTIFIER = com.example.soochit; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 437 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 438 | SWIFT_VERSION = 5.0; 439 | VERSIONING_SYSTEM = "apple-generic"; 440 | }; 441 | name = Debug; 442 | }; 443 | 97C147071CF9000F007C117D /* Release */ = { 444 | isa = XCBuildConfiguration; 445 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 446 | buildSettings = { 447 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 448 | CLANG_ENABLE_MODULES = YES; 449 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 450 | ENABLE_BITCODE = NO; 451 | FRAMEWORK_SEARCH_PATHS = ( 452 | "$(inherited)", 453 | "$(PROJECT_DIR)/Flutter", 454 | ); 455 | INFOPLIST_FILE = Runner/Info.plist; 456 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 457 | LIBRARY_SEARCH_PATHS = ( 458 | "$(inherited)", 459 | "$(PROJECT_DIR)/Flutter", 460 | ); 461 | PRODUCT_BUNDLE_IDENTIFIER = com.example.soochit; 462 | PRODUCT_NAME = "$(TARGET_NAME)"; 463 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 464 | SWIFT_VERSION = 5.0; 465 | VERSIONING_SYSTEM = "apple-generic"; 466 | }; 467 | name = Release; 468 | }; 469 | /* End XCBuildConfiguration section */ 470 | 471 | /* Begin XCConfigurationList section */ 472 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 97C147031CF9000F007C117D /* Debug */, 476 | 97C147041CF9000F007C117D /* Release */, 477 | 249021D3217E4FDB00AE95B9 /* Profile */, 478 | ); 479 | defaultConfigurationIsVisible = 0; 480 | defaultConfigurationName = Release; 481 | }; 482 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 483 | isa = XCConfigurationList; 484 | buildConfigurations = ( 485 | 97C147061CF9000F007C117D /* Debug */, 486 | 97C147071CF9000F007C117D /* Release */, 487 | 249021D4217E4FDB00AE95B9 /* Profile */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | /* End XCConfigurationList section */ 493 | }; 494 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 495 | } 496 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MLH-Fellowship/soochit/af17ba5a032e69aa1a547fb35898de719b95408a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | soochit 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/functions/notificationPlugin.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ffi'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_local_notifications/flutter_local_notifications.dart'; 5 | import 'package:path_provider/path_provider.dart'; 6 | import 'dart:io' show File, Platform; 7 | import 'package:http/http.dart' as http; 8 | 9 | import 'package:rxdart/subjects.dart'; 10 | import 'package:soochit/global/myColors.dart'; 11 | 12 | class NotificationPlugin { 13 | // 14 | FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin; 15 | final BehaviorSubject 16 | didReceivedLocalNotificationSubject = 17 | BehaviorSubject(); 18 | var initializationSettings; 19 | 20 | NotificationPlugin._() { 21 | init(); 22 | } 23 | 24 | init() async { 25 | flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); 26 | if (Platform.isIOS) { 27 | _requestIOSPermission(); 28 | } 29 | initializePlatformSpecifics(); 30 | } 31 | 32 | initializePlatformSpecifics() { 33 | var initializationSettingsAndroid = 34 | AndroidInitializationSettings('launch_background'); 35 | var initializationSettingsIOS = IOSInitializationSettings( 36 | requestAlertPermission: true, 37 | requestBadgePermission: true, 38 | requestSoundPermission: false, 39 | onDidReceiveLocalNotification: (id, title, body, payload) async { 40 | ReceivedNotification receivedNotification = ReceivedNotification( 41 | id: id, title: title, body: body, payload: payload); 42 | didReceivedLocalNotificationSubject.add(receivedNotification); 43 | }, 44 | ); 45 | 46 | initializationSettings = InitializationSettings( 47 | initializationSettingsAndroid, initializationSettingsIOS); 48 | } 49 | 50 | _requestIOSPermission() { 51 | flutterLocalNotificationsPlugin 52 | .resolvePlatformSpecificImplementation< 53 | IOSFlutterLocalNotificationsPlugin>() 54 | .requestPermissions( 55 | alert: false, 56 | badge: true, 57 | sound: true, 58 | ); 59 | } 60 | 61 | setListenerForLowerVersions(Function onNotificationInLowerVersions) { 62 | didReceivedLocalNotificationSubject.listen((receivedNotification) { 63 | onNotificationInLowerVersions(receivedNotification); 64 | }); 65 | } 66 | 67 | setOnNotificationClick(Function onNotificationClick) async { 68 | await flutterLocalNotificationsPlugin.initialize(initializationSettings, 69 | onSelectNotification: (String payload) async { 70 | onNotificationClick(payload); 71 | }); 72 | } 73 | 74 | Future showNotification() async { 75 | var androidChannelSpecifics = AndroidNotificationDetails( 76 | 'CHANNEL_ID', 77 | 'CHANNEL_NAME', 78 | "CHANNEL_DESCRIPTION", 79 | importance: Importance.Max, 80 | priority: Priority.High, 81 | playSound: true, 82 | styleInformation: DefaultStyleInformation(true, true), 83 | ); 84 | var iosChannelSpecifics = IOSNotificationDetails(); 85 | var platformChannelSpecifics = 86 | NotificationDetails(androidChannelSpecifics, iosChannelSpecifics); 87 | await flutterLocalNotificationsPlugin.show( 88 | 0, 89 | 'Test Title', 90 | 'Test Body', //null 91 | platformChannelSpecifics, 92 | payload: 'New Payload', 93 | ); 94 | } 95 | 96 | Future showDailyAtTime() async { 97 | var time = Time(12, 47, 20); 98 | var androidChannelSpecifics = AndroidNotificationDetails( 99 | 'CHANNEL_ID 4', 100 | 'CHANNEL_NAME 4', 101 | "CHANNEL_DESCRIPTION 4", 102 | importance: Importance.Max, 103 | priority: Priority.High, 104 | ); 105 | var iosChannelSpecifics = IOSNotificationDetails(); 106 | var platformChannelSpecifics = 107 | NotificationDetails(androidChannelSpecifics, iosChannelSpecifics); 108 | await flutterLocalNotificationsPlugin.showDailyAtTime( 109 | 0, 110 | 'Test Title at ${time.hour}:${time.minute}.${time.second}', 111 | 'Test Body', //null 112 | time, 113 | platformChannelSpecifics, 114 | payload: 'Test Payload', 115 | ); 116 | } 117 | 118 | Future showWeeklyAtDayTime() async { 119 | var time = Time(21, 5, 0); 120 | var androidChannelSpecifics = AndroidNotificationDetails( 121 | 'CHANNEL_ID 5', 122 | 'CHANNEL_NAME 5', 123 | "CHANNEL_DESCRIPTION 5", 124 | importance: Importance.Max, 125 | priority: Priority.High, 126 | ); 127 | var iosChannelSpecifics = IOSNotificationDetails(); 128 | var platformChannelSpecifics = 129 | NotificationDetails(androidChannelSpecifics, iosChannelSpecifics); 130 | await flutterLocalNotificationsPlugin.showWeeklyAtDayAndTime( 131 | 0, 132 | 'Test Title at ${time.hour}:${time.minute}.${time.second}', 133 | 'Test Body', //null 134 | Day.Saturday, 135 | time, 136 | platformChannelSpecifics, 137 | payload: 'Test Payload', 138 | ); 139 | } 140 | 141 | Future repeatNotification() async { 142 | var androidChannelSpecifics = AndroidNotificationDetails( 143 | 'CHANNEL_ID 3', 144 | 'CHANNEL_NAME 3', 145 | "CHANNEL_DESCRIPTION 3", 146 | importance: Importance.Max, 147 | priority: Priority.High, 148 | styleInformation: DefaultStyleInformation(true, true), 149 | ); 150 | var iosChannelSpecifics = IOSNotificationDetails(); 151 | var platformChannelSpecifics = 152 | NotificationDetails(androidChannelSpecifics, iosChannelSpecifics); 153 | await flutterLocalNotificationsPlugin.periodicallyShow( 154 | 0, 155 | 'Repeating Test Title', 156 | 'Repeating Test Body', 157 | RepeatInterval.EveryMinute, 158 | platformChannelSpecifics, 159 | payload: 'Test Payload', 160 | ); 161 | } 162 | 163 | Future scheduleNotification() async { 164 | var scheduleNotificationDateTime = DateTime.now().add(Duration(seconds: 5)); 165 | var androidChannelSpecifics = AndroidNotificationDetails( 166 | 'CHANNEL_ID 1', 167 | 'CHANNEL_NAME 1', 168 | "CHANNEL_DESCRIPTION 1", 169 | enableLights: true, 170 | color: MyColors.primaryColor, 171 | ledColor: MyColors.primaryColor, 172 | ledOnMs: 1000, 173 | ledOffMs: 500, 174 | importance: Importance.Max, 175 | priority: Priority.High, 176 | playSound: true, 177 | styleInformation: DefaultStyleInformation(true, true), 178 | ); 179 | var iosChannelSpecifics = IOSNotificationDetails( 180 | sound: 'my_sound.aiff', 181 | ); 182 | var platformChannelSpecifics = NotificationDetails( 183 | androidChannelSpecifics, 184 | iosChannelSpecifics, 185 | ); 186 | await flutterLocalNotificationsPlugin.schedule( 187 | 0, 188 | 'Take Medicines', 189 | "Hey there! It's time to take your prescribed medicines", 190 | scheduleNotificationDateTime, 191 | platformChannelSpecifics, 192 | payload: 'Test Payload', 193 | ); 194 | } 195 | 196 | Future showNotificationWithAttachment() async { 197 | var attachmentPicturePath = await _downloadAndSaveFile( 198 | 'https://via.placeholder.com/800x200', 'attachment_img.jpg'); 199 | var iOSPlatformSpecifics = IOSNotificationDetails( 200 | attachments: [IOSNotificationAttachment(attachmentPicturePath)], 201 | ); 202 | var bigPictureStyleInformation = BigPictureStyleInformation( 203 | FilePathAndroidBitmap(attachmentPicturePath), 204 | contentTitle: 'Attached Image', 205 | htmlFormatContentTitle: true, 206 | summaryText: 'Test Image', 207 | htmlFormatSummaryText: true, 208 | ); 209 | var androidChannelSpecifics = AndroidNotificationDetails( 210 | 'CHANNEL ID 2', 211 | 'CHANNEL NAME 2', 212 | 'CHANNEL DESCRIPTION 2', 213 | importance: Importance.High, 214 | priority: Priority.High, 215 | styleInformation: bigPictureStyleInformation, 216 | ); 217 | var notificationDetails = 218 | NotificationDetails(androidChannelSpecifics, iOSPlatformSpecifics); 219 | await flutterLocalNotificationsPlugin.show( 220 | 0, 221 | 'Title with attachment', 222 | 'Body with Attachment', 223 | notificationDetails, 224 | ); 225 | } 226 | 227 | _downloadAndSaveFile(String url, String fileName) async { 228 | var directory = await getApplicationDocumentsDirectory(); 229 | var filePath = '${directory.path}/$fileName'; 230 | var response = await http.get(url); 231 | var file = File(filePath); 232 | await file.writeAsBytes(response.bodyBytes); 233 | return filePath; 234 | } 235 | 236 | Future getPendingNotificationCount() async { 237 | List p = 238 | await flutterLocalNotificationsPlugin.pendingNotificationRequests(); 239 | return p.length; 240 | } 241 | 242 | Future cancelNotification() async { 243 | await flutterLocalNotificationsPlugin.cancel(0); 244 | } 245 | 246 | Future cancelAllNotification() async { 247 | await flutterLocalNotificationsPlugin.cancelAll(); 248 | } 249 | } 250 | 251 | NotificationPlugin notificationPlugin = NotificationPlugin._(); 252 | 253 | class ReceivedNotification { 254 | final int id; 255 | final String title; 256 | final String body; 257 | final String payload; 258 | 259 | ReceivedNotification({ 260 | @required this.id, 261 | @required this.title, 262 | @required this.body, 263 | @required this.payload, 264 | }); 265 | } 266 | -------------------------------------------------------------------------------- /lib/functions/notificationScreen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class NotificationScreen extends StatefulWidget { 4 | // 5 | final String payload; 6 | 7 | NotificationScreen({this.payload}); 8 | 9 | @override 10 | _NotificationScreenState createState() => _NotificationScreenState(); 11 | } 12 | 13 | class _NotificationScreenState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | appBar: AppBar( 18 | title: Text('Notifications Screen'), 19 | ), 20 | body: Center( 21 | child: Text(widget.payload), 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/global/myColors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class MyColors { 4 | static const Color black = Colors.black; 5 | static const Color white = Colors.white; 6 | static const Color primaryColor = Color(0xFFF7575D); 7 | static const Color accentColor = Color(0xFFFDECED); 8 | static const Color grey = Color(0xFF8D8D8D); 9 | 10 | //shades of pink 11 | static const Color lightPink = Color(0xFFF6B0B3); 12 | static const Color lighterPink = Color(0xFFFCBEC1); 13 | static const Color lightestPink = Color(0xFFFDECED); 14 | 15 | static const Color inputFieldPink = Color(0xFFF87277); 16 | static const Color inputFieldTextPink = Color(0xFFFBB5B8); 17 | } 18 | -------------------------------------------------------------------------------- /lib/global/myDimens.dart: -------------------------------------------------------------------------------- 1 | class MyDimens { 2 | //negative numbers 3 | static const double double_negative_300 = -250; 4 | static const double double_negative_200 = -200; 5 | 6 | //positive numbers 7 | static const double double_1 = 1; 8 | static const double double_2point5 = 2.5; 9 | static const double double_4 = 4; 10 | static const double double_7 = 7; 11 | static const double double_10 = 10; 12 | static const double double_15 = 15; 13 | static const double double_17 = 17; 14 | static const double double_20 = 20; 15 | static const double double_25 = 25; 16 | static const double double_30 = 30; 17 | static const double double_35 = 35; 18 | static const double double_40 = 40; 19 | static const double double_60 = 60; 20 | static const double double_70 = 70; 21 | static const double double_100 = 100; 22 | static const double double_120 = 120; 23 | static const double double_200 = 200; 24 | static const double double_300 = 300; 25 | static const double double_400 = 400; 26 | static const double double_280 = 280; 27 | static const double double_600 = 600; 28 | } 29 | -------------------------------------------------------------------------------- /lib/global/mySpaces.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class MySpaces { 4 | //vertical gaps 5 | static const Widget vSmallestGapInBetween = SizedBox(height: 6); 6 | static const Widget vGapInBetween = SizedBox(height: 12); 7 | static const Widget vSmallGapInBetween = SizedBox(height: 20); 8 | static const Widget vMediumGapInBetween = SizedBox(height: 30); 9 | static const Widget vLargeGapInBetween = SizedBox(height: 38); 10 | 11 | //horizontal gaps 12 | static const Widget hGapInBetween = SizedBox(width: 12); 13 | static const Widget hSmallGapInBetween = SizedBox(width: 20); 14 | static const Widget hMediumGapInBetween = SizedBox(width: 30); 15 | } 16 | -------------------------------------------------------------------------------- /lib/global/myStrings.dart: -------------------------------------------------------------------------------- 1 | class MyStrings { 2 | static const appName = "Soochit"; 3 | static const tagline = "Not just another medicine reminder."; 4 | 5 | // welcome screen 6 | static const welcomeToLabel = "Welcome to"; 7 | static const whoAreYouLabel = "Who are you?"; 8 | static const doctorLabel = "Doctor"; 9 | static const patientLabel = "Patient"; 10 | 11 | // loginAuth screen 12 | static const buttonLabel = "Send Security Code"; 13 | static const phoneRequest = "Enter your mobile number to get an OTP"; 14 | static const placeholderLoginAuth = 'Phone Number (include +91)'; 15 | 16 | // otpAuth screen 17 | static const buttonLabel1 = "Confirm OTP"; 18 | static const otpRequest = "Enter the (6 digit) OTP you have received"; 19 | 20 | // snackBar messages (errors/suggestions) 21 | static const invalidPhoneNumber = 'Please enter a valid phone number'; 22 | static const invalidCodeOrAuth = 'Invalid code/Invalid authentication'; 23 | static const somethingGoneWrong = 'Something has gone wrong, please try later'; 24 | static const invalidPhoneNumberFormat = 'The phone number format is incorrect. Please enter your number in E.164 format i.e. [+][country code][number]'; 25 | static const incorrectOTP = 'Incorrect OTP. Please enter the last code received.'; 26 | 27 | // dummy data 28 | static const patientName = "Rachit Gupta"; 29 | static const paracetamolLabel = "Paracetamol"; 30 | static const crocinLabel = "Crocin"; 31 | static const time = "12:00 PM"; 32 | static const date = "2nd October"; 33 | static const doctorName = "Dr. Rachit Gupta"; 34 | static const phoneNumber = "+91 0000000000"; 35 | 36 | static const registerLabel = 'Register'; // for doc and patients both 37 | static const buttonLabel2 = 'Confirm'; // for doc and patients both 38 | 39 | // >>>>>>>>>>>>>>>>>>>> PATIENT >>>>>>>>>>>>>>>>>>>> 40 | 41 | // home 42 | static const patientMedDeadlines = "$patientName's Medical Deadlines"; 43 | static const genderLabel = 'Gender'; 44 | static const addressLabel = 'Address'; 45 | 46 | // prescription history 47 | static const patientPrescriptionHistoryLabel = 48 | "$patientName's Prescription History"; 49 | 50 | // >>>>>>>>>>>>>>>>>>>> DOCTOR >>>>>>>>>>>>>>>>>>>> 51 | 52 | // home 53 | static const doctorPreviousPatients = "'s Previous Patients"; 54 | static const recentAppointmentDate = "2nd Oct"; 55 | 56 | // FAB 57 | static const addAPatientLabel = "Add a patient"; 58 | static const cancelLabel = "Cancel"; 59 | static const confirmLabel = "Confirm"; 60 | 61 | // patient's profile (doctor's pov) 62 | static const ageLabel = "Age"; 63 | static const phoneNumberLabel = "Phone number"; 64 | static const sampleAge = "21"; 65 | static const yearsOldLabel = "years old"; 66 | static const sampleProblem = "Problem: constant cough"; 67 | static const searchPatientsLabel = 'Search patients'; 68 | 69 | // register page 70 | static const nameLabel = 'Full name'; 71 | static const hospitalNameLabel = 'Hospital name'; 72 | static const hospitalAddressLabel = 'Hospital address'; 73 | static const qualificationsLabel = 'Qualification'; 74 | static const uploadSignatureLabel = 'Upload signature'; 75 | static const signatureLabel = 'Signature'; 76 | 77 | // prescription 78 | static const prescriptionLabel = "Prescription"; 79 | static const problemLabel = "Problem"; 80 | static const descriptionOptionalLabel = "Description (Optional)"; 81 | static const sampleMedName = "Paracetamol"; 82 | static const sampleMedTime = "7AM and 8PM"; 83 | static const medicineNameLabel = "Medicine name"; 84 | static const timingsLabel = "Timings"; 85 | static const addAMedicineLabel = "Add a medicine"; 86 | } 87 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:provider/provider.dart'; 3 | import 'package:soochit/pages/authentication/register.dart'; 4 | import 'package:soochit/pages/authentication/enterOTP.dart'; 5 | import 'package:soochit/pages/authentication/splashScreen.dart'; 6 | import 'package:soochit/pages/doctor-specific/doctorProfile.dart'; 7 | import 'package:soochit/pages/doctor-specific/doctorRegistration.dart'; 8 | import 'package:soochit/pages/doctor-specific/homeDoctor.dart'; 9 | import 'package:soochit/pages/doctor-specific/prescription.dart'; 10 | import 'package:soochit/pages/patient-specific/homePatient.dart'; 11 | import 'package:soochit/pages/patient-specific/patientRegistration.dart'; 12 | import 'package:soochit/stores/login_store.dart'; 13 | import 'functions/localNotificationsScreen.dart'; 14 | import 'pages/welcome.dart'; 15 | import 'pages/login.dart'; 16 | import 'pages/doctor-specific/patientHistory.dart'; 17 | import 'pages/patient-specific/medicineDeadlines.dart'; 18 | import 'pages/patient-specific/prescriptionHistory.dart'; 19 | import 'pages/doctor-specific/samplePatientProfile.dart'; 20 | 21 | 22 | void main() { 23 | runApp(MyApp()); 24 | } 25 | 26 | class MyApp extends StatefulWidget { 27 | @override 28 | _MyAppState createState() => _MyAppState(); 29 | } 30 | 31 | class _MyAppState extends State { 32 | @override 33 | Widget build(BuildContext context) { 34 | // the main here will have a 'splash' as home-screen and other routes 35 | return MultiProvider( 36 | providers: [ 37 | Provider( 38 | create: (_) => LoginStore(), 39 | ) 40 | ], 41 | child: GestureDetector( 42 | // This ensures that the keyboard disappears as soon as the user clicks outside the text filed 43 | onTap: () { 44 | FocusScopeNode currentFocus = FocusScope.of(context); 45 | if (!currentFocus.hasPrimaryFocus && 46 | currentFocus.focusedChild != null) { 47 | FocusManager.instance.primaryFocus.unfocus(); 48 | } 49 | }, 50 | child: MaterialApp( 51 | title: 'Soochit', 52 | debugShowCheckedModeBanner: false, 53 | // home: LocalNotificationScreen(), 54 | home: SplashScreen(), 55 | routes: { 56 | EnterOTP.id: (context) => EnterOTP(), 57 | Register.id: (context) => Register(), 58 | SplashScreen.id: (context) => SplashScreen(), 59 | Welcome.id: (context) => Welcome(), 60 | Login.id: (context) => Login(), 61 | PatientHistory.id: (context) => PatientHistory(), 62 | MedicineDeadlines.id: (context) => MedicineDeadlines(), 63 | PrescriptionHistory.id: (context) => PrescriptionHistory(), 64 | SamplePatientProfile.id: (context) => SamplePatientProfile(), 65 | HomePatient.id: (context) => HomePatient(), 66 | HomeDoctor.id: (context) => HomeDoctor(), 67 | DoctorProfile.id: (context) => DoctorProfile(), 68 | DoctorRegistration.id: (context) => DoctorRegistration(), 69 | PatientRegistration.id: (context) => PatientRegistration(), 70 | Prescription.id: (context) => Prescription(), 71 | }, 72 | ), 73 | ), 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/pages/authentication/enterOTP.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_mobx/flutter_mobx.dart'; 3 | import 'package:numeric_keyboard/numeric_keyboard.dart'; 4 | import 'package:provider/provider.dart'; 5 | import 'package:soochit/global/myDimens.dart'; 6 | import 'package:soochit/global/myStrings.dart'; 7 | import 'package:soochit/stores/login_store.dart'; 8 | import 'package:soochit/widgets/loaderHud.dart'; 9 | import 'package:soochit/global/myColors.dart'; 10 | 11 | class EnterOTP extends StatefulWidget { 12 | static String id="otp_page"; 13 | 14 | EnterOTP({Key key}) : super(key: key); 15 | 16 | @override 17 | _EnterOTPState createState() => _EnterOTPState(); 18 | } 19 | 20 | class _EnterOTPState extends State { 21 | String text = ''; 22 | 23 | void _onKeyboardTap(String value) { 24 | setState(() { 25 | text = text + value; 26 | }); 27 | } 28 | 29 | Widget otpNumberWidget(int position) { 30 | try { 31 | return Container( 32 | height: MyDimens.double_40, 33 | width: MyDimens.double_40, 34 | decoration: BoxDecoration( 35 | color: MyColors.inputFieldPink, 36 | border: Border.all(color: MyColors.lighterPink), 37 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 38 | child: Center( 39 | child: Text( 40 | text[position], 41 | style: Theme.of(context) 42 | .textTheme 43 | .headline6 44 | .copyWith(color: MyColors.lightestPink, fontFamily: 'lexenddeca'), 45 | )), 46 | ); 47 | } catch (e) { 48 | return Container( 49 | height: MyDimens.double_40, 50 | width: MyDimens.double_40, 51 | decoration: BoxDecoration( 52 | color: MyColors.lightPink, 53 | border: Border.all(color: MyColors.lighterPink), 54 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 55 | ); 56 | } 57 | } 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | return Consumer( 62 | builder: (_, loginStore, __) { 63 | return Observer( 64 | builder: (_) => LoaderHUD( 65 | inAsyncCall: loginStore.isOtpLoading, 66 | child: Scaffold( 67 | backgroundColor: MyColors.primaryColor, 68 | key: loginStore.otpScaffoldKey, 69 | appBar: AppBar( 70 | leading: IconButton( 71 | icon: Container( 72 | padding: EdgeInsets.all(MyDimens.double_10), 73 | decoration: BoxDecoration( 74 | borderRadius: 75 | BorderRadius.all(Radius.circular(MyDimens.double_20)), 76 | color: MyColors.lightestPink, 77 | ), 78 | child: Icon( 79 | Icons.arrow_back_ios, 80 | color: MyColors.primaryColor, 81 | size: MyDimens.double_20, 82 | ), 83 | ), 84 | onPressed: () => Navigator.of(context).pop(), 85 | ), 86 | elevation: 0, 87 | backgroundColor: MyColors.primaryColor, 88 | brightness: Brightness.light, 89 | ), 90 | body: SafeArea( 91 | child: Column( 92 | children: [ 93 | Expanded( 94 | child: Column( 95 | children: [ 96 | Expanded( 97 | child: SingleChildScrollView( 98 | child: Padding( 99 | child: Column( 100 | mainAxisAlignment: MainAxisAlignment.center, 101 | children: [ 102 | Container( 103 | margin: EdgeInsets.all(MyDimens.double_20), 104 | child: Align( 105 | alignment: Alignment.centerLeft, 106 | child: Text(MyStrings.otpRequest, 107 | style: Theme.of(context) 108 | .textTheme 109 | .bodyText2 110 | .copyWith( 111 | color: MyColors.white, 112 | fontFamily: 'lexenddeca')), 113 | ), 114 | ), 115 | Container( 116 | constraints: BoxConstraints(maxWidth: MyDimens.double_600), 117 | child: Row( 118 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 119 | children: [ 120 | otpNumberWidget(0), 121 | otpNumberWidget(1), 122 | otpNumberWidget(2), 123 | otpNumberWidget(3), 124 | otpNumberWidget(4), 125 | otpNumberWidget(5), 126 | ], 127 | ), 128 | ), 129 | ], 130 | ), 131 | padding: EdgeInsets.symmetric(vertical: MyDimens.double_100), 132 | ) 133 | ), 134 | ), 135 | Container( 136 | margin: EdgeInsets.symmetric( 137 | horizontal: MyDimens.double_20, vertical: MyDimens.double_10), 138 | constraints: BoxConstraints(maxWidth: MyDimens.double_600), 139 | child: Row( 140 | children: [ 141 | Expanded( 142 | child: OutlineButton( 143 | onPressed: () { 144 | loginStore.validateOtpAndLogin(context, text); 145 | }, 146 | shape: RoundedRectangleBorder( 147 | borderRadius: 148 | BorderRadius.circular(MyDimens.double_4)), 149 | borderSide: BorderSide( 150 | color: MyColors.lighterPink, 151 | width: MyDimens.double_1), 152 | color: MyColors.primaryColor, 153 | child: Padding( 154 | padding: EdgeInsets.only( 155 | top: MyDimens.double_15, 156 | bottom: MyDimens.double_15), 157 | child: Text(MyStrings.buttonLabel1, 158 | style: Theme.of(context) 159 | .textTheme 160 | .subtitle1 161 | .copyWith( 162 | color: MyColors.lighterPink, 163 | fontFamily: 'lexenddeca')), 164 | ), 165 | ), 166 | ), 167 | ], 168 | ), 169 | ), 170 | NumericKeyboard( 171 | onKeyboardTap: _onKeyboardTap, 172 | textColor: MyColors.lightestPink, 173 | rightIcon: Icon( 174 | Icons.backspace, 175 | color: MyColors.lightestPink, 176 | ), 177 | rightButtonFn: () { 178 | setState(() { 179 | text = text.substring(0, text.length - 1); 180 | }); 181 | }, 182 | ) 183 | ], 184 | ), 185 | ) 186 | ], 187 | ), 188 | ), 189 | ), 190 | ), 191 | ); 192 | }, 193 | ); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /lib/pages/authentication/register.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_mobx/flutter_mobx.dart'; 4 | import 'package:provider/provider.dart'; 5 | import 'package:soochit/global/myDimens.dart'; 6 | import 'package:soochit/global/myStrings.dart'; 7 | import 'package:soochit/global/myColors.dart'; 8 | import 'package:soochit/stores/login_store.dart'; 9 | import 'package:soochit/widgets/loaderHud.dart'; 10 | import 'package:soochit/widgets/snackbar.dart'; 11 | 12 | class Register extends StatefulWidget { 13 | static String id = "login_page"; 14 | 15 | Register({Key key}) : super(key: key); 16 | 17 | @override 18 | _RegisterState createState() => _RegisterState(); 19 | } 20 | 21 | class _RegisterState extends State { 22 | TextEditingController phoneController = TextEditingController(); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return Consumer( 27 | builder: (_, loginStore, __) { 28 | return Observer( 29 | builder: (_) => LoaderHUD( 30 | inAsyncCall: loginStore.isLoginLoading, 31 | child: Material( 32 | child: Scaffold( 33 | backgroundColor: MyColors.primaryColor, 34 | key: loginStore.loginScaffoldKey, 35 | body: SafeArea( 36 | child: SingleChildScrollView( 37 | child: Container( 38 | height: MediaQuery.of(context).size.height, 39 | child: Column( 40 | mainAxisAlignment: MainAxisAlignment.center, 41 | children: [ 42 | Column( 43 | children: [ 44 | Container( 45 | margin: EdgeInsets.only( 46 | left: MyDimens.double_30, 47 | right: MyDimens.double_30, 48 | top: MyDimens.double_25 * 2, 49 | ), 50 | child: Column( 51 | // ignore: prefer_const_literals_to_create_immutable 52 | children: [ 53 | // ignore: prefer_const_literals_to_create_immutables, prefer_const_literals_to_create_immutables 54 | ], 55 | ), 56 | ), 57 | Container( 58 | margin: EdgeInsets.symmetric( 59 | horizontal: MyDimens.double_30, 60 | vertical: MyDimens.double_30), 61 | child: Image( 62 | image: AssetImage( 63 | 'assets/images/medicine.png'), 64 | fit: BoxFit.cover, 65 | )), 66 | Container( 67 | margin: EdgeInsets.symmetric( 68 | horizontal: MyDimens.double_30), 69 | child: Align( 70 | alignment: Alignment.centerLeft, 71 | child: Text(MyStrings.phoneRequest, 72 | style: Theme.of(context) 73 | .textTheme 74 | .bodyText2 75 | .copyWith( 76 | color: MyColors.white, 77 | fontFamily: 'lexenddeca')), 78 | ), 79 | ), 80 | Container( 81 | height: 3 * MyDimens.double_20, 82 | constraints: BoxConstraints( 83 | maxWidth: MyDimens.double_600), 84 | margin: EdgeInsets.symmetric( 85 | horizontal: MyDimens.double_30, 86 | vertical: MyDimens.double_20), 87 | child: CupertinoTextField( 88 | padding: EdgeInsets.symmetric( 89 | horizontal: MyDimens.double_15), 90 | decoration: BoxDecoration( 91 | color: MyColors.inputFieldPink, 92 | borderRadius: BorderRadius.all( 93 | Radius.circular( 94 | MyDimens.double_4))), 95 | style: Theme.of(context) 96 | .textTheme 97 | .subtitle1 98 | .copyWith( 99 | color: MyColors.lightestPink, 100 | fontFamily: 'lexenddeca'), 101 | controller: phoneController, 102 | clearButtonMode: 103 | OverlayVisibilityMode.editing, 104 | keyboardType: TextInputType.phone, 105 | maxLines: 1, 106 | placeholder: MyStrings.placeholderLoginAuth, 107 | placeholderStyle: Theme.of(context) 108 | .textTheme 109 | .headline6 110 | .copyWith(fontSize: 18, 111 | color: MyColors.inputFieldTextPink, 112 | fontFamily: 'lexenddeca')), 113 | ), 114 | Container( 115 | margin: EdgeInsets.symmetric( 116 | horizontal: MyDimens.double_30, 117 | vertical: MyDimens.double_10), 118 | constraints: BoxConstraints( 119 | maxWidth: MyDimens.double_600), 120 | child: Row( 121 | children: [ 122 | Expanded( 123 | child: OutlineButton( 124 | onPressed: () { 125 | if (phoneController.text.isNotEmpty) { 126 | loginStore.getCodeWithPhoneNumber( 127 | context, 128 | phoneController.text 129 | .toString()); 130 | } else { 131 | loginStore 132 | .loginScaffoldKey.currentState 133 | .showSnackBar(getSnackBar( 134 | context, 135 | MyStrings 136 | .invalidPhoneNumber)); 137 | } 138 | }, 139 | shape: RoundedRectangleBorder( 140 | borderRadius: BorderRadius.circular( 141 | MyDimens.double_4)), 142 | borderSide: BorderSide( 143 | color: MyColors.lighterPink, 144 | width: MyDimens.double_1), 145 | color: MyColors.primaryColor, 146 | child: Padding( 147 | padding: EdgeInsets.only( 148 | top: MyDimens.double_15, 149 | bottom: MyDimens.double_15), 150 | child: Text(MyStrings.buttonLabel, 151 | style: Theme.of(context) 152 | .textTheme 153 | .subtitle1 154 | .copyWith( 155 | color: 156 | MyColors.lighterPink, 157 | fontFamily: 158 | 'lexenddeca')), 159 | ), 160 | ), 161 | ), 162 | ], 163 | ), 164 | ) 165 | ], 166 | ) 167 | ], 168 | ), 169 | ), 170 | ), 171 | ), 172 | ), 173 | ), 174 | ), 175 | ); 176 | }, 177 | ); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /lib/pages/authentication/signout-function.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_auth/firebase_auth.dart'; 2 | 3 | class Auth { 4 | 5 | static final auth = FirebaseAuth.instance; 6 | 7 | static Future logout() async { 8 | await auth.signOut(); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /lib/pages/authentication/splashScreen.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:provider/provider.dart'; 5 | import 'package:soochit/global/myColors.dart'; 6 | import 'package:soochit/global/myStrings.dart'; 7 | import 'package:soochit/pages/authentication/register.dart'; 8 | import 'package:soochit/pages/doctor-specific/homeDoctor.dart'; 9 | import 'package:soochit/pages/patient-specific/homePatient.dart'; 10 | import 'package:soochit/stores/login_store.dart'; 11 | 12 | class SplashScreen extends StatefulWidget { 13 | static String id="splash_page"; 14 | SplashScreen({Key key}) : super(key: key); 15 | @override 16 | _SplashScreenState createState() => _SplashScreenState(); 17 | } 18 | 19 | class _SplashScreenState extends State { 20 | 21 | void _decideUserRole() async{ 22 | var firebaseUser = await FirebaseAuth.instance.currentUser(); 23 | var collectionRef = Firestore.instance.collection('Doctor'); 24 | var doc = await collectionRef.document(firebaseUser.uid).get(); 25 | if(doc.exists) 26 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => HomeDoctor()), (Route route) => false); 27 | else 28 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => HomePatient()), (Route route) => false); 29 | } 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | Provider.of(context, listen: false).isAlreadyAuthenticated().then((result) { 35 | if (result) { 36 | print(result); 37 | _decideUserRole(); 38 | } else { 39 | Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => Register()), (Route route) => false); 40 | } 41 | }); 42 | } 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | return Scaffold( 47 | backgroundColor: Colors.white, 48 | body: Align( 49 | child: Text( 50 | MyStrings.appName, style: Theme.of(context).textTheme.headline3.copyWith(color: MyColors.primaryColor, fontWeight: FontWeight.bold), 51 | ), 52 | alignment: Alignment.center, 53 | ) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/pages/doctor-specific/doctorProfile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:provider/provider.dart'; 3 | import 'package:soochit/global/myDimens.dart'; 4 | import 'package:soochit/global/mySpaces.dart'; 5 | import 'package:soochit/global/myColors.dart'; 6 | import 'package:soochit/global/myStrings.dart'; 7 | import 'package:firebase_auth/firebase_auth.dart'; 8 | import 'package:cloud_firestore/cloud_firestore.dart'; 9 | import 'package:soochit/stores/login_store.dart'; 10 | 11 | class DoctorProfile extends StatefulWidget { 12 | static String id = "doctorProfile"; 13 | 14 | @override 15 | _DoctorProfileState createState() => _DoctorProfileState(); 16 | } 17 | 18 | class _DoctorProfileState extends State { 19 | @override 20 | Widget build(BuildContext context) { 21 | return Consumer(builder: (_, loginStore, __) { 22 | return Scaffold( 23 | backgroundColor: MyColors.white, 24 | body: SafeArea( 25 | child: Stack( 26 | children: [ 27 | SingleChildScrollView( 28 | child: Container( 29 | margin: EdgeInsets.all(MyDimens.double_30), 30 | child: Column( 31 | children: [ 32 | StreamBuilder( 33 | stream: Firestore.instance 34 | .collection('Doctor') 35 | .snapshots(), 36 | builder: (context, snapshot) { 37 | String doctorName, 38 | doctorPhoneNumber, 39 | hospitalName, 40 | hospitalAddress; 41 | String docUid = loginStore.firebaseUser.uid; 42 | for(int i=0;i now in array 12 | // String name; 13 | // String hospitalName; 14 | // String hospitalAddress; 15 | // String qualifications; 16 | List doctorDetails = ['', '', '', '']; 17 | List textWidgetPlaceholders = [ 18 | MyStrings.nameLabel, 19 | MyStrings.hospitalNameLabel, 20 | MyStrings.hospitalAddressLabel, 21 | MyStrings.qualificationsLabel, 22 | MyStrings.uploadSignatureLabel, 23 | ]; 24 | 25 | class DoctorRegistration extends StatefulWidget { 26 | @override 27 | static String id = 'doctorRegistration'; 28 | FirebaseUser user; 29 | 30 | DoctorRegistration({Key key, @required this.user}) : super(key: key); 31 | 32 | @override 33 | _DoctorRegistrationState createState() => _DoctorRegistrationState(user: user); 34 | } 35 | 36 | class _DoctorRegistrationState extends State { 37 | FirebaseUser user; 38 | 39 | _DoctorRegistrationState({Key key, @required this.user}); 40 | 41 | // this adds the doc details -> ensure it's async and await (wait) for current user. 42 | void _onPressedAddDocDetails() async{ 43 | var firebaseUser = await FirebaseAuth.instance.currentUser(); // finds the current user 44 | // this takes up a firebase instance and makes a collection and a document (if not present already). 45 | // Further it overwrites all data inside that collection and document by the string map we have put 46 | Firestore.instance.collection('Doctor').document(firebaseUser.uid).setData( 47 | { 48 | // the string map to add to FireStore 49 | 'phoneNumber':firebaseUser.phoneNumber, 50 | 'name':doctorDetails[0], 51 | 'hospitalName': doctorDetails[1], 52 | 'hospitalAddress':doctorDetails[2], 53 | 'qualification':doctorDetails[3], 54 | }).then((_){ 55 | print('added doctor details'); // print some message to console to see everything went good! 56 | }); 57 | } 58 | 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | return Material( 63 | color: MyColors.primaryColor, 64 | child: SingleChildScrollView( 65 | child: Container( 66 | color: MyColors.primaryColor, 67 | margin: EdgeInsets.only( 68 | left: MyDimens.double_40, right: MyDimens.double_40, top: MyDimens.double_120), 69 | child: Column( 70 | crossAxisAlignment: CrossAxisAlignment.end, 71 | children: [ 72 | Column( 73 | crossAxisAlignment: CrossAxisAlignment.start, 74 | children: [ 75 | Text(MyStrings.registerLabel, 76 | style: Theme.of(context) 77 | .textTheme 78 | .headline3 79 | .copyWith(color: MyColors.white, fontFamily: 'airbnb')), 80 | MySpaces.vSmallGapInBetween, 81 | _buildCupertinoTextField(0), 82 | MySpaces.vSmallGapInBetween, 83 | _buildCupertinoTextField(1), 84 | MySpaces.vSmallGapInBetween, 85 | _buildCupertinoTextField(2), 86 | MySpaces.vSmallGapInBetween, 87 | _buildCupertinoTextField(3), 88 | MySpaces.vSmallGapInBetween, 89 | _buildCupertinoTextField(4), 90 | MySpaces.vMediumGapInBetween 91 | ], 92 | ), 93 | FlatButton( 94 | onPressed: () { 95 | _onPressedAddDocDetails(); 96 | Navigator.pushNamed(context, HomeDoctor.id); 97 | }, 98 | shape: RoundedRectangleBorder( 99 | borderRadius: BorderRadius.circular(MyDimens.double_4)), 100 | color: MyColors.lighterPink, 101 | child: Padding( 102 | padding: EdgeInsets.symmetric( 103 | vertical: MyDimens.double_15, 104 | horizontal: MyDimens.double_20), 105 | child: Text(MyStrings.buttonLabel2, 106 | style: Theme.of(context).textTheme.subtitle1.copyWith( 107 | color: MyColors.primaryColor, 108 | fontFamily: 'lexenddeca')), 109 | ), 110 | ), 111 | Padding(padding: EdgeInsets.all(MyDimens.double_200),), 112 | ], 113 | ) 114 | ), 115 | ), 116 | ); 117 | } 118 | 119 | Widget _buildCupertinoTextField(int index) { 120 | return CupertinoTextField( 121 | padding: EdgeInsets.symmetric( 122 | horizontal: MyDimens.double_20, vertical: MyDimens.double_15), 123 | decoration: BoxDecoration( 124 | color: MyColors.inputFieldPink, 125 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 126 | style: Theme.of(context) 127 | .textTheme 128 | .subtitle1 129 | .copyWith(color: MyColors.lightestPink, fontFamily: 'lexenddeca'), 130 | maxLines: 1, 131 | cursorColor: MyColors.white, 132 | cursorWidth: 3, 133 | cursorRadius: Radius.circular(50), 134 | placeholder: textWidgetPlaceholders[index], 135 | placeholderStyle: Theme.of(context).textTheme.headline6.copyWith( 136 | fontSize: 18, 137 | color: MyColors.inputFieldTextPink, 138 | fontFamily: 'lexenddeca'), 139 | onChanged: (String value) { 140 | doctorDetails[index] = value; 141 | }, 142 | ); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /lib/pages/doctor-specific/homeDoctor.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_auth/firebase_auth.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:soochit/global/myColors.dart'; 4 | import 'package:soochit/global/myDimens.dart'; 5 | import 'package:soochit/pages/authentication/signout-function.dart'; 6 | import 'package:soochit/pages/authentication/splashScreen.dart'; 7 | import 'package:soochit/pages/doctor-specific/patientHistory.dart'; 8 | import 'package:soochit/pages/doctor-specific/doctorProfile.dart'; 9 | import 'package:soochit/widgets/addPatientDialog.dart'; 10 | 11 | class HomeDoctor extends StatefulWidget { 12 | static String id = "homeDoctor"; 13 | FirebaseUser user; 14 | 15 | HomeDoctor({Key key, @required this.user}) : super(key: key); 16 | @override 17 | _HomeDoctorState createState() => _HomeDoctorState(user: user); 18 | } 19 | 20 | class _HomeDoctorState extends State { 21 | 22 | FirebaseUser user; 23 | _HomeDoctorState({Key key, @required this.user}); 24 | 25 | int pageIndex = 0; 26 | int firstIconColorInt = 0; 27 | int secondIconColorInt = 1; 28 | List _currentPage = [PatientHistory(), DoctorProfile()]; 29 | List _iconColors = [MyColors.white, MyColors.lightPink]; 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | void handleClick(String value) { 34 | switch (value) { 35 | case 'Logout': 36 | Auth.logout(); 37 | Navigator.pushNamed(context, SplashScreen.id); 38 | } 39 | } 40 | return Scaffold( 41 | body: _currentPage[pageIndex], 42 | appBar: AppBar( 43 | backgroundColor: MyColors.primaryColor, 44 | actions: [ 45 | Padding( 46 | padding: EdgeInsets.only(right: MyDimens.double_10), 47 | child: PopupMenuButton( 48 | onSelected: handleClick, 49 | itemBuilder: (BuildContext context) { 50 | return {'Logout'}.map((String choice) { 51 | return PopupMenuItem( 52 | value: choice, 53 | child: Text(choice), 54 | ); 55 | }).toList(); 56 | }, 57 | ), 58 | ) 59 | ], 60 | ), 61 | bottomNavigationBar: BottomAppBar( 62 | clipBehavior: Clip.antiAliasWithSaveLayer, 63 | shape: CircularNotchedRectangle(), 64 | child: Container( 65 | height: MyDimens.double_60, 66 | child: Padding( 67 | padding: EdgeInsets.symmetric(horizontal: MyDimens.double_60), 68 | child: Row( 69 | mainAxisSize: MainAxisSize.max, 70 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 71 | children: [ 72 | IconButton( 73 | icon: Icon( 74 | Icons.history, 75 | color: _iconColors[firstIconColorInt], 76 | ), 77 | onPressed: () { 78 | setState(() { 79 | pageIndex = 0; 80 | firstIconColorInt = 0; 81 | secondIconColorInt = 1; 82 | }); 83 | }, 84 | ), 85 | IconButton( 86 | icon: Icon(Icons.person, 87 | color: _iconColors[secondIconColorInt]), 88 | onPressed: () { 89 | setState(() { 90 | pageIndex = 1; 91 | firstIconColorInt = 1; 92 | secondIconColorInt = 0; 93 | }); 94 | }, 95 | ), 96 | ], 97 | ), 98 | ), 99 | color: MyColors.primaryColor, 100 | ), 101 | ), 102 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 103 | floatingActionButton: FloatingActionButton( 104 | onPressed: () { 105 | showAddPatientDialog(); 106 | }, 107 | backgroundColor: MyColors.primaryColor, 108 | child: Icon(Icons.add, size: 40), 109 | ), 110 | ); 111 | } 112 | Future showAddPatientDialog() { 113 | return showDialog( 114 | context: context, 115 | builder: (BuildContext context) => AddPatientDialog()); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /lib/pages/doctor-specific/patientHistory.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:provider/provider.dart'; 5 | import 'package:soochit/global/myColors.dart'; 6 | import 'package:soochit/global/myDimens.dart'; 7 | import 'package:soochit/global/mySpaces.dart'; 8 | import 'package:soochit/global/myStrings.dart'; 9 | import 'package:soochit/stores/login_store.dart'; 10 | import 'package:soochit/widgets/previousPatientCard.dart'; 11 | 12 | class PatientHistory extends StatefulWidget { 13 | static String id = "patientHistory"; 14 | 15 | @override 16 | _PatientHistoryState createState() => _PatientHistoryState(); 17 | } 18 | 19 | class _PatientHistoryState extends State { 20 | @override 21 | Widget build(BuildContext context) { 22 | return Consumer(builder: (_, loginStore, __) { 23 | return Scaffold( 24 | backgroundColor: MyColors.white, 25 | body: SafeArea( 26 | child: SingleChildScrollView( 27 | child: Container( 28 | margin: EdgeInsets.all(MyDimens.double_30), 29 | child: Column( 30 | children: [ 31 | MySpaces.vMediumGapInBetween, 32 | StreamBuilder( 33 | stream: Firestore.instance.collection('Doctor').snapshots(), 34 | builder: (context, snapshot) { 35 | if (!snapshot.hasData) { 36 | return Center( 37 | child: CircularProgressIndicator( 38 | valueColor: AlwaysStoppedAnimation( 39 | MyColors.primaryColor), 40 | ), 41 | ); 42 | } else { 43 | String name; 44 | String uid = loginStore.firebaseUser.uid; 45 | for (int i = 0; 46 | i < snapshot.data.documents.length; 47 | i++) { 48 | if (snapshot.data.documents[i].documentID == uid) { 49 | name = snapshot.data.documents[i].data['name']; 50 | } 51 | } 52 | return Text( 53 | name + MyStrings.doctorPreviousPatients, 54 | style: Theme.of(context).textTheme.headline4.copyWith( 55 | color: MyColors.primaryColor, 56 | fontFamily: 'airbnb'), 57 | ); 58 | } 59 | }), 60 | MySpaces.vLargeGapInBetween, 61 | Container( 62 | width: MediaQuery.of(context).size.width * 0.80, 63 | margin: EdgeInsets.only(bottom: MyDimens.double_30), 64 | child: TextField( 65 | decoration: InputDecoration( 66 | prefixIcon: Icon( 67 | Icons.search, 68 | color: MyColors.black, 69 | ), 70 | border: OutlineInputBorder( 71 | borderRadius: 72 | BorderRadius.circular(MyDimens.double_7)), 73 | ), 74 | ), 75 | height: 50, 76 | ), 77 | StreamBuilder( 78 | stream: 79 | Firestore.instance.collection('Patient').snapshots(), 80 | builder: (context, snapshot) { 81 | if (!snapshot.hasData) { 82 | return Center( 83 | child: CircularProgressIndicator( 84 | valueColor: AlwaysStoppedAnimation( 85 | MyColors.primaryColor), 86 | ), 87 | ); 88 | } else { 89 | List patientDet = List.generate( 90 | snapshot.data.documents.length, (i) => List(4), 91 | growable: false); // uid, name, phoneNumber, age 92 | for (int i = 0; 93 | i < snapshot.data.documents.length; 94 | i++) { 95 | String uid = snapshot.data.documents[i].documentID; 96 | String name = snapshot.data.documents[i].data['name']; 97 | String phoneNumber = 98 | snapshot.data.documents[i].data['phoneNumber']; 99 | String age = snapshot.data.documents[i].data['age']; 100 | patientDet[i][0] = uid; 101 | patientDet[i][1] = name; 102 | patientDet[i][2] = phoneNumber; 103 | patientDet[i][3] = age; 104 | } 105 | return Column( 106 | children: [ 107 | for (int i = 0; i < patientDet.length; i++) 108 | previousPatientCard(context, patientDet[i]), 109 | ], 110 | ); 111 | } 112 | }), 113 | ], 114 | ), 115 | ), 116 | )), 117 | ); 118 | }); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/pages/doctor-specific/prescription.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:provider/provider.dart'; 6 | import 'package:soochit/global/myDimens.dart'; 7 | import 'package:soochit/global/myColors.dart'; 8 | import 'package:soochit/global/mySpaces.dart'; 9 | import 'package:soochit/global/myStrings.dart'; 10 | import 'package:soochit/pages/doctor-specific/homeDoctor.dart'; 11 | import 'package:soochit/stores/login_store.dart'; 12 | import 'package:soochit/widgets/addMedicineDialog.dart'; 13 | 14 | // Doctor's details -> now in array 15 | // String name; 16 | // String hospitalName; 17 | // String hospitalAddress; 18 | // String qualifications; 19 | List prescriptionDetails = ['', '',]; 20 | List textWidgetPlaceholdersPres = [ 21 | MyStrings.problemLabel, 22 | MyStrings.descriptionOptionalLabel, 23 | ]; 24 | 25 | class Prescription extends StatefulWidget { 26 | @override 27 | static String id = 'prescription'; 28 | FirebaseUser user; 29 | 30 | List patientDet; 31 | 32 | Prescription({Key key, @required this.patientDet}) : super(key: key); 33 | 34 | @override 35 | _PrescriptionState createState() => 36 | _PrescriptionState(patientDet: patientDet); 37 | } 38 | 39 | class _PrescriptionState extends State { 40 | List patientDet; 41 | 42 | _PrescriptionState({Key key, @required this.patientDet}); 43 | 44 | void _onPressedAddPrescriptionDetails() async{ 45 | var firebaseUser = await FirebaseAuth.instance.currentUser(); 46 | Firestore.instance.collection('Prescription').add( 47 | { 48 | // the string map to add to FireStore 49 | 'problem' : prescriptionDetails[0], 50 | 'problemDesc' : prescriptionDetails[1], 51 | 'doctorUID' : firebaseUser.uid, 52 | 'patientUID' : patientDet[0], 53 | 'medicines' : 'Sample Medicine', 54 | }).then((_){ 55 | print('added prescription details'); // print some message to console to see everything went good! 56 | }); 57 | } 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | print(patientDet); 62 | return Consumer( 63 | builder: (_, loginStore, __) { 64 | return Material( 65 | color: MyColors.primaryColor, 66 | child: SingleChildScrollView( 67 | child: Container( 68 | color: MyColors.primaryColor, 69 | margin: EdgeInsets.only( 70 | left: MyDimens.double_40, 71 | right: MyDimens.double_40, 72 | top: MyDimens.double_120), 73 | child: Column( 74 | crossAxisAlignment: CrossAxisAlignment.end, 75 | children: [ 76 | Column( 77 | crossAxisAlignment: CrossAxisAlignment.start, 78 | children: [ 79 | Text(MyStrings.prescriptionLabel, 80 | style: Theme.of(context) 81 | .textTheme 82 | .headline3 83 | .copyWith( 84 | color: MyColors.white, 85 | fontFamily: 'airbnb')), 86 | MySpaces.vSmallGapInBetween, 87 | _buildCupertinoTextField(0), 88 | MySpaces.vSmallGapInBetween, 89 | _buildCupertinoTextField(1), 90 | MySpaces.vSmallGapInBetween, 91 | ], 92 | ), 93 | GestureDetector( 94 | child: Icon( 95 | Icons.add, 96 | color: MyColors.white, 97 | ), 98 | onTap: showAddMedicineDialog, 99 | ), 100 | MySpaces.vSmallGapInBetween, 101 | AddedMedicineCard(), 102 | MySpaces.vGapInBetween, 103 | AddedMedicineCard(), 104 | MySpaces.vGapInBetween, 105 | AddedMedicineCard(), 106 | MySpaces.vSmallGapInBetween, 107 | FlatButton( 108 | onPressed: () { 109 | _onPressedAddPrescriptionDetails(); 110 | Navigator.pushNamed(context, HomeDoctor.id); 111 | }, 112 | shape: RoundedRectangleBorder( 113 | borderRadius: 114 | BorderRadius.circular(MyDimens.double_4)), 115 | color: MyColors.lighterPink, 116 | child: Padding( 117 | padding: EdgeInsets.symmetric( 118 | vertical: MyDimens.double_15, 119 | horizontal: MyDimens.double_20), 120 | child: Text(MyStrings.buttonLabel2, 121 | style: Theme.of(context) 122 | .textTheme 123 | .subtitle1 124 | .copyWith( 125 | color: MyColors.primaryColor, 126 | fontFamily: 'lexenddeca')), 127 | ), 128 | ), 129 | Padding( 130 | padding: EdgeInsets.all(MyDimens.double_200), 131 | ), 132 | ], 133 | )), 134 | ), 135 | ); 136 | }, 137 | ); 138 | } 139 | 140 | Widget _buildCupertinoTextField(int index) { 141 | return CupertinoTextField( 142 | padding: EdgeInsets.symmetric( 143 | horizontal: MyDimens.double_20, vertical: MyDimens.double_15), 144 | decoration: BoxDecoration( 145 | color: MyColors.inputFieldPink, 146 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 147 | style: Theme.of(context) 148 | .textTheme 149 | .subtitle1 150 | .copyWith(color: MyColors.lightestPink, fontFamily: 'lexenddeca'), 151 | maxLines: 1, 152 | cursorColor: MyColors.white, 153 | cursorWidth: 3, 154 | cursorRadius: Radius.circular(50), 155 | placeholder: textWidgetPlaceholdersPres[index], 156 | placeholderStyle: Theme.of(context).textTheme.headline6.copyWith( 157 | fontSize: 18, 158 | color: MyColors.inputFieldTextPink, 159 | fontFamily: 'lexenddeca'), 160 | onChanged: (String value) { 161 | prescriptionDetails[index] = value; 162 | }, 163 | ); 164 | } 165 | 166 | Future showAddMedicineDialog() { 167 | return showDialog( 168 | context: context, 169 | builder: (BuildContext context) => AddMedicineDialog()); 170 | } 171 | } 172 | 173 | class AddedMedicineCard extends StatelessWidget { 174 | @override 175 | Widget build(BuildContext context) { 176 | return Container( 177 | padding: EdgeInsets.symmetric( 178 | horizontal: MyDimens.double_20, vertical: MyDimens.double_15), 179 | width: MediaQuery.of(context).size.width * 0.80, 180 | decoration: BoxDecoration( 181 | borderRadius: BorderRadius.circular(MyDimens.double_4), 182 | color: MyColors.inputFieldPink, 183 | ), 184 | child: Column( 185 | mainAxisAlignment: MainAxisAlignment.center, 186 | crossAxisAlignment: CrossAxisAlignment.start, 187 | children: [ 188 | Text( 189 | MyStrings.sampleMedName, 190 | style: Theme.of(context) 191 | .textTheme 192 | .headline6 193 | .copyWith(color: MyColors.white, fontFamily: 'lexenddeca'), 194 | ), 195 | MySpaces.vSmallestGapInBetween, 196 | Text( 197 | MyStrings.sampleMedTime, 198 | style: Theme.of(context).textTheme.bodyText2.copyWith( 199 | color: MyColors.inputFieldTextPink, fontFamily: 'lexenddeca'), 200 | ), 201 | ], 202 | )); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /lib/pages/doctor-specific/samplePatientProfile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:soochit/global/myDimens.dart'; 3 | import 'package:soochit/global/mySpaces.dart'; 4 | import 'package:soochit/global/myColors.dart'; 5 | import 'package:soochit/global/myStrings.dart'; 6 | import 'package:soochit/pages/doctor-specific/prescription.dart'; 7 | import 'package:soochit/widgets/prescriptionHistoryCard.dart'; 8 | 9 | class SamplePatientProfile extends StatefulWidget { 10 | static String id = "samplePatientProfile"; 11 | 12 | List patientDet; 13 | SamplePatientProfile({Key key, @required this.patientDet}) : super(key: key); 14 | 15 | @override 16 | _SamplePatientProfileState createState() => 17 | _SamplePatientProfileState(patientDet: patientDet); 18 | } 19 | 20 | class _SamplePatientProfileState extends State { 21 | List patientDet; 22 | 23 | _SamplePatientProfileState({Key key, @required this.patientDet}); 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | backgroundColor: MyColors.white, 29 | body: SafeArea( 30 | child: Stack( 31 | children: [ 32 | SingleChildScrollView( 33 | child: Container( 34 | margin: EdgeInsets.all(MyDimens.double_30), 35 | child: Column( 36 | children: [ 37 | Column( 38 | crossAxisAlignment: CrossAxisAlignment.start, 39 | children: [ 40 | MySpaces.vMediumGapInBetween, 41 | Text( 42 | patientDet[1], 43 | style: Theme.of(context).textTheme.headline4.copyWith( 44 | color: MyColors.primaryColor, 45 | fontFamily: 'airbnb'), 46 | ), 47 | MySpaces.vSmallGapInBetween, 48 | Text( 49 | MyStrings.ageLabel + ":", 50 | style: Theme.of(context).textTheme.bodyText1.copyWith( 51 | color: MyColors.grey, fontFamily: 'lexenddeca'), 52 | ), 53 | Text( 54 | patientDet[3] + " " + MyStrings.yearsOldLabel, 55 | style: Theme.of(context).textTheme.headline5.copyWith( 56 | color: MyColors.black, fontFamily: 'lexenddeca'), 57 | ), 58 | MySpaces.vSmallGapInBetween, 59 | Text( 60 | MyStrings.phoneNumberLabel + ":", 61 | style: Theme.of(context).textTheme.bodyText1.copyWith( 62 | color: MyColors.grey, fontFamily: 'lexenddeca'), 63 | ), 64 | Text( 65 | patientDet[2], 66 | style: Theme.of(context).textTheme.headline5.copyWith( 67 | color: MyColors.black, fontFamily: 'lexenddeca'), 68 | ), 69 | MySpaces.vSmallGapInBetween, 70 | Container( 71 | width: double.infinity, 72 | height: MyDimens.double_1, 73 | color: MyColors.grey, 74 | ), 75 | MySpaces.vSmallGapInBetween, 76 | ], 77 | ), 78 | Column( 79 | children: [ 80 | PrescriptionHistoryCard(), 81 | MySpaces.vSmallGapInBetween, 82 | PrescriptionHistoryCard(), 83 | MySpaces.vSmallGapInBetween, 84 | PrescriptionHistoryCard(), 85 | MySpaces.vSmallGapInBetween, 86 | PrescriptionHistoryCard(), 87 | MySpaces.vSmallGapInBetween, 88 | PrescriptionHistoryCard(), 89 | MySpaces.vSmallGapInBetween, 90 | PrescriptionHistoryCard(), 91 | MySpaces.vSmallGapInBetween, 92 | PrescriptionHistoryCard(), 93 | ], 94 | ), 95 | ], 96 | )), 97 | ), 98 | Positioned( 99 | bottom: MyDimens.double_30, 100 | right: MyDimens.double_30, 101 | child: FloatingActionButton( 102 | onPressed: () { 103 | Navigator.of(context).push( 104 | MaterialPageRoute(builder: (_) => Prescription(patientDet: patientDet))); 105 | }, 106 | backgroundColor: MyColors.primaryColor, 107 | child: Icon(Icons.add, size: 40), 108 | ), 109 | ) 110 | ], 111 | )), 112 | ); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lib/pages/login.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Login extends StatefulWidget { 4 | static String id = "login"; 5 | @override 6 | _LoginState createState() => _LoginState(); 7 | } 8 | 9 | class _LoginState extends State { 10 | @override 11 | Widget build(BuildContext context) { 12 | return Container(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/pages/patient-specific/homePatient.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:soochit/global/myColors.dart'; 3 | import 'package:soochit/global/myDimens.dart'; 4 | import 'package:soochit/pages/authentication/signout-function.dart'; 5 | import 'package:soochit/pages/authentication/splashScreen.dart'; 6 | import 'package:soochit/pages/patient-specific/medicineDeadlines.dart'; 7 | import 'package:soochit/pages/patient-specific/prescriptionHistory.dart'; 8 | import 'package:soochit/widgets/addMedicineDialog.dart'; 9 | 10 | class HomePatient extends StatefulWidget { 11 | static String id = "homePatient"; 12 | @override 13 | _HomePatientState createState() => _HomePatientState(); 14 | } 15 | 16 | class _HomePatientState extends State { 17 | int pageIndex = 0; 18 | int firstIconColorInt = 0; 19 | int secondIconColorInt = 1; 20 | List _currentPage = [ 21 | MedicineDeadlines(), PrescriptionHistory() 22 | ]; 23 | List _iconColors = [ 24 | MyColors.white, MyColors.lightPink 25 | ]; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | void handleClick(String value) { 30 | switch (value) { 31 | case 'Logout': 32 | Auth.logout(); 33 | Navigator.pushNamed(context, SplashScreen.id); 34 | } 35 | } 36 | return Scaffold( 37 | body: _currentPage[pageIndex], 38 | appBar: AppBar( 39 | backgroundColor: MyColors.primaryColor, 40 | actions: [ 41 | Padding( 42 | padding: EdgeInsets.only(right: MyDimens.double_10), 43 | child: PopupMenuButton( 44 | onSelected: handleClick, 45 | itemBuilder: (BuildContext context) { 46 | return {'Logout'}.map((String choice) { 47 | return PopupMenuItem( 48 | value: choice, 49 | child: Text(choice), 50 | ); 51 | }).toList(); 52 | }, 53 | ), 54 | ) 55 | ], 56 | ), 57 | bottomNavigationBar: BottomAppBar( 58 | clipBehavior: Clip.antiAliasWithSaveLayer, 59 | shape: CircularNotchedRectangle(), 60 | child: Container( 61 | height: MyDimens.double_60, 62 | child: Padding( 63 | padding: EdgeInsets.symmetric(horizontal: MyDimens.double_60), 64 | child: Row( 65 | mainAxisSize: MainAxisSize.max, 66 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 67 | children: [ 68 | IconButton(icon: Icon(Icons.event_note, color: _iconColors[firstIconColorInt],), onPressed: () {setState(() { 69 | pageIndex = 0; 70 | firstIconColorInt = 0; 71 | secondIconColorInt = 1; 72 | });},), 73 | IconButton(icon: Icon(Icons.folder_open, color: _iconColors[secondIconColorInt]), onPressed: () {setState(() { 74 | pageIndex = 1; 75 | firstIconColorInt = 1; 76 | secondIconColorInt = 0; 77 | });},), 78 | ], 79 | ), 80 | ), 81 | color: MyColors.primaryColor, 82 | ), 83 | ), 84 | floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, 85 | floatingActionButton: FloatingActionButton(onPressed: () { 86 | showAddManualMedicineReminderDialog(); 87 | }, backgroundColor: MyColors.primaryColor, child: Icon(Icons.add, size: 40),), 88 | ); 89 | } 90 | Future showAddManualMedicineReminderDialog() { 91 | return showDialog( 92 | context: context, 93 | builder: (BuildContext context) => AddMedicineDialog()); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/pages/patient-specific/medicineDeadlines.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:firebase_auth/firebase_auth.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:provider/provider.dart'; 6 | import 'package:soochit/global/myColors.dart'; 7 | import 'package:soochit/global/myDimens.dart'; 8 | import 'package:soochit/global/mySpaces.dart'; 9 | import 'package:soochit/stores/login_store.dart'; 10 | import 'package:soochit/widgets/medicineDeadlineReminder.dart'; 11 | import 'package:cloud_firestore/cloud_firestore.dart'; 12 | import 'package:soochit/functions/notificationPlugin.dart'; 13 | import 'package:soochit/functions/notificationScreen.dart'; 14 | 15 | class MedicineDeadlines extends StatefulWidget { 16 | static String id = "medicineDeadlines"; 17 | FirebaseUser user; 18 | 19 | MedicineDeadlines({Key key, @required this.user}) : super(key: key); 20 | 21 | @override 22 | _MedicineDeadlinesState createState() => _MedicineDeadlinesState(user: user); 23 | } 24 | 25 | class _MedicineDeadlinesState extends State { 26 | FirebaseUser user; 27 | int count = 0; 28 | _MedicineDeadlinesState({Key key, @required this.user}); 29 | 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | notificationPlugin 35 | .setListenerForLowerVersions(onNotificationInLowerVersions); 36 | notificationPlugin.setOnNotificationClick(onNotificationClick); 37 | } 38 | 39 | @override 40 | Widget build(BuildContext context) { 41 | return Consumer(builder: (_, loginStore, __) { 42 | String uid = loginStore.firebaseUser.uid; 43 | return Scaffold( 44 | body: SafeArea( 45 | child: SingleChildScrollView( 46 | child: Container( 47 | margin: EdgeInsets.symmetric( 48 | vertical: MyDimens.double_10, horizontal: MyDimens.double_30), 49 | child: StreamBuilder( 50 | stream: Firestore.instance 51 | .collection('Medicine') 52 | .document(uid) 53 | .snapshots(), 54 | builder: (context, snapshot) { 55 | final DocumentSnapshot ds = snapshot.data; 56 | final Map map = ds.data; 57 | return Column( 58 | children: [ 59 | MySpaces.vMediumGapInBetween, 60 | StreamBuilder( 61 | stream: Firestore.instance 62 | .collection('Patient') 63 | .document(uid) 64 | .snapshots(), 65 | builder: (context, snapshot) { 66 | String currentUsername = snapshot.data['name']; 67 | return GestureDetector( 68 | onTap: () async{ 69 | await notificationPlugin.scheduleNotification(); 70 | }, 71 | child: Text( 72 | currentUsername + "'s Medical Deadlines", 73 | style: Theme.of(context) 74 | .textTheme 75 | .headline4 76 | .copyWith( 77 | color: MyColors.primaryColor, 78 | fontFamily: 'airbnb'), 79 | ), 80 | ); 81 | }), 82 | MySpaces.vLargeGapInBetween, 83 | Column( 84 | children: map.entries 85 | .map((MapEntry entry) => MedicineDeadlineReminder( 86 | medName: entry.value, time: entry.key)) 87 | .toList(), 88 | ) 89 | ], 90 | ); 91 | }), 92 | ), 93 | )), 94 | ); 95 | }); 96 | } 97 | 98 | onNotificationInLowerVersions(ReceivedNotification receivedNotification) { 99 | print('Notification Received ${receivedNotification.id}'); 100 | } 101 | 102 | onNotificationClick(String payload) { 103 | print('Payload $payload'); 104 | Navigator.push(context, MaterialPageRoute(builder: (coontext) { 105 | return NotificationScreen( 106 | payload: payload, 107 | ); 108 | })); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /lib/pages/patient-specific/patientRegistration.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:soochit/global/myDimens.dart'; 6 | import 'package:soochit/global/myColors.dart'; 7 | import 'package:soochit/global/mySpaces.dart'; 8 | import 'package:soochit/global/myStrings.dart'; 9 | import 'package:soochit/pages/patient-specific/homePatient.dart'; 10 | 11 | // Patient's details -> now in array 12 | // String name; 13 | // String hospitalName; 14 | // String hospitalAddress; 15 | // String qualifications; 16 | 17 | List patientDetails = ['', '', '', '']; 18 | List textWidgetPlaceholders = [ 19 | MyStrings.nameLabel, 20 | MyStrings.ageLabel, 21 | MyStrings.genderLabel, 22 | MyStrings.addressLabel, 23 | ]; 24 | 25 | class PatientRegistration extends StatefulWidget { 26 | @override 27 | static String id = 'patientRegistration'; 28 | FirebaseUser user; 29 | 30 | PatientRegistration({Key key, @required this.user}) : super(key: key); 31 | 32 | @override 33 | _PatientRegistrationState createState() => _PatientRegistrationState(user: user); 34 | } 35 | 36 | class _PatientRegistrationState extends State { 37 | FirebaseUser user; 38 | 39 | _PatientRegistrationState({Key key, @required this.user}); 40 | 41 | void _onPressedAddDocDetails() async{ 42 | var firebaseUser = await FirebaseAuth.instance.currentUser(); 43 | Firestore.instance.collection('Patient').document(firebaseUser.uid).setData( 44 | { 45 | 'phoneNumber':firebaseUser.phoneNumber, 46 | 'name':patientDetails[0], 47 | 'age': patientDetails[1], 48 | 'gender':patientDetails[2], 49 | 'address':patientDetails[3], 50 | }).then((_){ 51 | print('added patient details'); 52 | }); 53 | } 54 | 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return Material( 59 | color: MyColors.primaryColor, 60 | child: SingleChildScrollView( 61 | child: Container( 62 | color: MyColors.primaryColor, 63 | margin: EdgeInsets.only( 64 | left: MyDimens.double_40, right: MyDimens.double_40, top: MyDimens.double_120), 65 | child: Column( 66 | crossAxisAlignment: CrossAxisAlignment.end, 67 | children: [ 68 | Column( 69 | crossAxisAlignment: CrossAxisAlignment.start, 70 | children: [ 71 | Text(MyStrings.registerLabel, 72 | style: Theme.of(context) 73 | .textTheme 74 | .headline3 75 | .copyWith(color: MyColors.white, fontFamily: 'airbnb')), 76 | MySpaces.vSmallGapInBetween, 77 | _buildCupertinoTextField(0), 78 | MySpaces.vSmallGapInBetween, 79 | _buildCupertinoTextField(1), 80 | MySpaces.vSmallGapInBetween, 81 | _buildCupertinoTextField(2), 82 | MySpaces.vSmallGapInBetween, 83 | _buildCupertinoTextField(3), 84 | MySpaces.vMediumGapInBetween, 85 | ], 86 | ), 87 | FlatButton( 88 | onPressed: () { 89 | _onPressedAddDocDetails(); 90 | Navigator.pushNamed(context, HomePatient.id); 91 | }, 92 | shape: RoundedRectangleBorder( 93 | borderRadius: BorderRadius.circular(MyDimens.double_4)), 94 | color: MyColors.lighterPink, 95 | child: Padding( 96 | padding: EdgeInsets.symmetric( 97 | vertical: MyDimens.double_15, 98 | horizontal: MyDimens.double_20), 99 | child: Text(MyStrings.buttonLabel2, 100 | style: Theme.of(context).textTheme.subtitle1.copyWith( 101 | color: MyColors.primaryColor, 102 | fontFamily: 'lexenddeca')), 103 | ), 104 | ), 105 | Padding(padding: EdgeInsets.all(MyDimens.double_200),), 106 | ], 107 | ) 108 | ), 109 | ), 110 | ); 111 | } 112 | 113 | Widget _buildCupertinoTextField(int index) { 114 | return CupertinoTextField( 115 | padding: EdgeInsets.symmetric( 116 | horizontal: MyDimens.double_20, vertical: MyDimens.double_15), 117 | decoration: BoxDecoration( 118 | color: MyColors.inputFieldPink, 119 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 120 | style: Theme.of(context) 121 | .textTheme 122 | .subtitle1 123 | .copyWith(color: MyColors.lightestPink, fontFamily: 'lexenddeca'), 124 | maxLines: 1, 125 | cursorColor: MyColors.white, 126 | cursorWidth: 3, 127 | cursorRadius: Radius.circular(50), 128 | placeholder: textWidgetPlaceholders[index], 129 | placeholderStyle: Theme.of(context).textTheme.headline6.copyWith( 130 | fontSize: 18, 131 | color: MyColors.inputFieldTextPink, 132 | fontFamily: 'lexenddeca'), 133 | onChanged: (String value) { 134 | patientDetails[index] = value; 135 | }, 136 | ); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /lib/pages/patient-specific/prescriptionHistory.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:soochit/global/myColors.dart'; 3 | import 'package:soochit/global/myDimens.dart'; 4 | import 'package:soochit/global/mySpaces.dart'; 5 | import 'package:soochit/global/myStrings.dart'; 6 | import 'package:soochit/widgets/prescriptionHistoryCard.dart'; 7 | 8 | class PrescriptionHistory extends StatefulWidget { 9 | static String id = "prescriptionHistory"; 10 | @override 11 | _PrescriptionHistoryState createState() => _PrescriptionHistoryState(); 12 | } 13 | 14 | class _PrescriptionHistoryState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | body: SafeArea( 19 | child: SingleChildScrollView( 20 | child: Container( 21 | margin: EdgeInsets.symmetric(vertical: MyDimens.double_10, horizontal: MyDimens.double_30), 22 | child: Column( 23 | children: [ 24 | MySpaces.vMediumGapInBetween, 25 | Text( 26 | MyStrings.patientPrescriptionHistoryLabel, style: Theme.of(context).textTheme.headline4.copyWith(color: MyColors.primaryColor, fontFamily: 'airbnb'), 27 | ), 28 | MySpaces.vLargeGapInBetween, 29 | Column( 30 | children: [ 31 | PrescriptionHistoryCard(), 32 | MySpaces.vSmallGapInBetween, 33 | PrescriptionHistoryCard(), 34 | MySpaces.vSmallGapInBetween, 35 | PrescriptionHistoryCard(), 36 | MySpaces.vSmallGapInBetween, 37 | PrescriptionHistoryCard(), 38 | MySpaces.vSmallGapInBetween, 39 | PrescriptionHistoryCard(), 40 | MySpaces.vSmallGapInBetween, 41 | PrescriptionHistoryCard(), 42 | MySpaces.vSmallGapInBetween, 43 | PrescriptionHistoryCard(), 44 | MySpaces.vSmallGapInBetween, 45 | PrescriptionHistoryCard() 46 | ], 47 | ) 48 | ], 49 | ), 50 | ), 51 | ), 52 | ), 53 | ); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /lib/pages/welcome.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_auth/firebase_auth.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:soochit/global/myColors.dart'; 5 | import 'package:soochit/global/mySpaces.dart'; 6 | import 'package:soochit/global/myStrings.dart'; 7 | import 'package:soochit/global/myDimens.dart'; 8 | import 'package:soochit/pages/doctor-specific/doctorRegistration.dart'; 9 | import 'package:soochit/pages/patient-specific/patientRegistration.dart'; 10 | 11 | List userType = ['Doctor', 'Patient']; 12 | List backgroundColor = [MyColors.lightestPink, MyColors.lightestPink]; 13 | List textColor = [MyColors.black, MyColors.black]; 14 | String selectedRole; 15 | 16 | class Welcome extends StatefulWidget { 17 | static String id = "welcome"; 18 | FirebaseUser user; 19 | 20 | Welcome({Key key, @required this.user}) : super(key: key); 21 | @override 22 | _WelcomeState createState() => _WelcomeState(user: user); 23 | } 24 | 25 | class _WelcomeState extends State { 26 | FirebaseUser user; 27 | 28 | _WelcomeState({Key key, @required this.user}); 29 | @override 30 | Widget build(BuildContext context) { 31 | return Scaffold( 32 | body: Stack( 33 | children: [ 34 | Container( 35 | height: double.infinity, 36 | width: double.infinity, 37 | color: MyColors.primaryColor, 38 | child: Align( 39 | alignment: Alignment.topCenter, 40 | child: Padding( 41 | padding: EdgeInsets.symmetric(vertical: MyDimens.double_100), 42 | child: Column( 43 | children: [ 44 | Text( 45 | MyStrings.welcomeToLabel, 46 | style: Theme.of(context).textTheme.headline4.copyWith( 47 | color: MyColors.lighterPink, 48 | fontFamily: 'airbnb', 49 | fontSize: 30), 50 | ), 51 | Text(MyStrings.appName, 52 | style: Theme.of(context).textTheme.headline3.copyWith( 53 | color: MyColors.white, fontFamily: 'airbnb')), 54 | ], 55 | ), 56 | ), 57 | ), 58 | ), 59 | Positioned( 60 | bottom: MyDimens.double_negative_300, 61 | right: MyDimens.double_negative_200, 62 | child: Container( 63 | height: MyDimens.double_600, 64 | width: MyDimens.double_600, 65 | decoration: 66 | BoxDecoration(color: Colors.white, shape: BoxShape.circle), 67 | ), 68 | ), 69 | Positioned( 70 | bottom: MyDimens.double_100, 71 | left: MyDimens.double_10, 72 | right: MyDimens.double_10, 73 | child: Container( 74 | height: MyDimens.double_300, 75 | width: double.infinity, 76 | margin: EdgeInsets.symmetric(horizontal: MyDimens.double_20), 77 | child: Card( 78 | shape: RoundedRectangleBorder( 79 | borderRadius: BorderRadius.circular(MyDimens.double_10)), 80 | elevation: MyDimens.double_7, 81 | child: Padding( 82 | padding: const EdgeInsets.symmetric( 83 | horizontal: MyDimens.double_30), 84 | child: Column( 85 | children: [ 86 | Padding( 87 | padding: const EdgeInsets.symmetric( 88 | vertical: MyDimens.double_20), 89 | child: Align( 90 | child: Text(MyStrings.whoAreYouLabel, 91 | style: Theme.of(context) 92 | .textTheme 93 | .headline4 94 | .copyWith( 95 | color: MyColors.primaryColor, 96 | fontFamily: 'lexenddeca')), 97 | alignment: Alignment.centerLeft, 98 | )), 99 | Padding( 100 | padding: const EdgeInsets.symmetric( 101 | vertical: MyDimens.double_2point5), 102 | child: Row( 103 | children: [ 104 | Expanded( 105 | child: FlatButton( 106 | padding: EdgeInsets.symmetric( 107 | vertical: MyDimens.double_10, 108 | horizontal: MyDimens.double_20), 109 | onPressed: () { 110 | setState(() { 111 | if (backgroundColor[0] == 112 | MyColors.lightestPink) { 113 | backgroundColor[0] = 114 | MyColors.primaryColor; 115 | textColor[0] = MyColors.white; 116 | backgroundColor[1] = 117 | MyColors.lightestPink; 118 | textColor[1] = MyColors.black; 119 | selectedRole = userType[0]; 120 | } else { 121 | selectedRole = null; 122 | backgroundColor[0] = 123 | MyColors.lightestPink; 124 | textColor[0] = MyColors.black; 125 | } 126 | }); 127 | }, 128 | color: backgroundColor[0], 129 | shape: RoundedRectangleBorder( 130 | borderRadius: BorderRadius.circular( 131 | MyDimens.double_7)), 132 | child: Align( 133 | child: Text(MyStrings.doctorLabel, 134 | style: Theme.of(context) 135 | .textTheme 136 | .headline6 137 | .copyWith( 138 | color: textColor[0], 139 | fontFamily: 'lexenddeca')), 140 | alignment: Alignment.centerLeft, 141 | )), 142 | ), 143 | ], 144 | ), 145 | ), 146 | Padding( 147 | padding: const EdgeInsets.symmetric( 148 | vertical: MyDimens.double_2point5), 149 | child: Column( 150 | children: [ 151 | Row( 152 | children: [ 153 | Expanded( 154 | child: FlatButton( 155 | padding: EdgeInsets.symmetric( 156 | vertical: MyDimens.double_10, 157 | horizontal: MyDimens.double_20), 158 | onPressed: () { 159 | setState(() { 160 | if (backgroundColor[1] == 161 | MyColors.lightestPink) { 162 | backgroundColor[1] = 163 | MyColors.primaryColor; 164 | textColor[1] = MyColors.white; 165 | backgroundColor[0] = 166 | MyColors.lightestPink; 167 | textColor[0] = MyColors.black; 168 | selectedRole = userType[1]; 169 | } else { 170 | selectedRole = null; 171 | backgroundColor[1] = 172 | MyColors.lightestPink; 173 | textColor[1] = MyColors.black; 174 | } 175 | }); 176 | }, 177 | color: backgroundColor[1], 178 | shape: RoundedRectangleBorder( 179 | borderRadius: BorderRadius.circular( 180 | MyDimens.double_7)), 181 | child: Align( 182 | child: Text(MyStrings.patientLabel, 183 | style: Theme.of(context) 184 | .textTheme 185 | .headline6 186 | .copyWith( 187 | color: textColor[1], 188 | fontFamily: 189 | 'lexenddeca')), 190 | alignment: Alignment.centerLeft, 191 | )), 192 | ), 193 | ], 194 | ), 195 | MySpaces.vSmallGapInBetween, 196 | Visibility( 197 | visible: (selectedRole != null), 198 | child: InkWell( 199 | child: Align( 200 | child: Icon( 201 | CupertinoIcons.check_mark_circled_solid, 202 | size: MyDimens.double_40, 203 | color: MyColors.primaryColor, 204 | ), 205 | alignment: Alignment.centerRight, 206 | ), 207 | onTap: () { 208 | if(selectedRole==userType[0]) 209 | Navigator.of(context).push( 210 | MaterialPageRoute(builder: (_) => DoctorRegistration(user: user))); 211 | else 212 | Navigator.of(context).push( 213 | MaterialPageRoute(builder: (_) => PatientRegistration(user: user))); 214 | }, 215 | ), 216 | ) 217 | ], 218 | )), 219 | ], 220 | ), 221 | ), 222 | ), 223 | ), 224 | ) 225 | ], 226 | ), 227 | ); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /lib/stores/login_store.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:firebase_auth/firebase_auth.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:mobx/mobx.dart'; 5 | import 'package:soochit/global/myStrings.dart'; 6 | import 'package:soochit/pages/authentication/register.dart'; 7 | import 'package:soochit/pages/authentication/enterOTP.dart'; 8 | import 'package:soochit/pages/doctor-specific/homeDoctor.dart'; 9 | import 'package:soochit/pages/patient-specific/homePatient.dart'; 10 | import 'package:soochit/pages/welcome.dart'; 11 | import 'package:soochit/widgets/snackbar.dart'; 12 | 13 | part 'login_store.g.dart'; 14 | 15 | class LoginStore = LoginStoreBase with _$LoginStore; 16 | 17 | abstract class LoginStoreBase with Store { 18 | final FirebaseAuth _auth = FirebaseAuth.instance; 19 | String actualCode; 20 | 21 | @observable 22 | bool isLoginLoading = false; 23 | @observable 24 | bool isOtpLoading = false; 25 | 26 | @observable 27 | GlobalKey loginScaffoldKey = GlobalKey(); 28 | @observable 29 | GlobalKey otpScaffoldKey = GlobalKey(); 30 | 31 | @observable 32 | FirebaseUser firebaseUser; 33 | 34 | @action 35 | Future isAlreadyAuthenticated() async { 36 | firebaseUser = await _auth.currentUser(); 37 | if (firebaseUser != null) { 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } 43 | 44 | @action 45 | Future uidOfUser() async{ 46 | firebaseUser = await _auth.currentUser(); 47 | return firebaseUser.uid; 48 | } 49 | 50 | @action 51 | Future getCodeWithPhoneNumber( 52 | BuildContext context, String phoneNumber) async { 53 | isLoginLoading = true; 54 | 55 | await _auth.verifyPhoneNumber( 56 | phoneNumber: phoneNumber, 57 | timeout: Duration(seconds: 60), 58 | verificationCompleted: (AuthCredential auth) async { 59 | await _auth.signInWithCredential(auth).then((AuthResult value) { 60 | if (value != null && value.user != null) { 61 | print('Authentication successful'); 62 | onAuthenticationSuccessful(context, value); 63 | } else { 64 | loginScaffoldKey.currentState.showSnackBar( 65 | getSnackBar(context, MyStrings.invalidCodeOrAuth)); 66 | } 67 | }).catchError((error) { 68 | loginScaffoldKey.currentState.showSnackBar( 69 | getSnackBar(context, MyStrings.somethingGoneWrong)); 70 | }); 71 | }, 72 | verificationFailed: (AuthException authException) { 73 | print('Error message: ' + authException.message); 74 | loginScaffoldKey.currentState.showSnackBar( 75 | getSnackBar(context, MyStrings.invalidPhoneNumberFormat)); 76 | isLoginLoading = false; 77 | }, 78 | codeSent: (String verificationId, [int forceResendingToken]) async { 79 | actualCode = verificationId; 80 | isLoginLoading = false; 81 | await Navigator.of(context) 82 | .push(MaterialPageRoute(builder: (_) => EnterOTP())); 83 | }, 84 | codeAutoRetrievalTimeout: (String verificationId) { 85 | actualCode = verificationId; 86 | }); 87 | } 88 | 89 | @action 90 | Future validateOtpAndLogin(BuildContext context, String smsCode) async { 91 | isOtpLoading = true; 92 | final AuthCredential _authCredential = PhoneAuthProvider.getCredential( 93 | verificationId: actualCode, smsCode: smsCode); 94 | 95 | await _auth.signInWithCredential(_authCredential).catchError((error) { 96 | isOtpLoading = false; 97 | otpScaffoldKey.currentState 98 | .showSnackBar(getSnackBar(context, MyStrings.incorrectOTP)); 99 | }).then((AuthResult authResult) { 100 | if (authResult != null && authResult.user != null) { 101 | print('Authentication successful'); 102 | onAuthenticationSuccessful(context, authResult); 103 | } 104 | }); 105 | } 106 | 107 | Future onAuthenticationSuccessful( 108 | BuildContext context, AuthResult result) async { 109 | isLoginLoading = true; 110 | isOtpLoading = true; 111 | 112 | firebaseUser = result.user; 113 | 114 | var collectionDoc = Firestore.instance.collection('Doctor'); 115 | var collectionPat = Firestore.instance.collection('Patient'); 116 | var docDoc = await collectionDoc.document(firebaseUser.uid).get(); 117 | var docPat = await collectionPat.document(firebaseUser.uid).get(); 118 | if (docDoc.exists) 119 | Navigator.of(context).pushAndRemoveUntil( 120 | MaterialPageRoute(builder: (_) => HomeDoctor(user: firebaseUser)), 121 | (Route route) => false); 122 | else if (docPat.exists) 123 | Navigator.of(context).pushAndRemoveUntil( 124 | MaterialPageRoute(builder: (_) => HomePatient()), 125 | (Route route) => false); 126 | else 127 | Navigator.of(context).pushAndRemoveUntil( 128 | MaterialPageRoute(builder: (_) => Welcome(user: firebaseUser)), 129 | (Route route) => false); 130 | 131 | isLoginLoading = false; 132 | isOtpLoading = false; 133 | } 134 | 135 | @action 136 | Future signOut(BuildContext context) async { 137 | await _auth.signOut(); 138 | await Navigator.of(context).pushAndRemoveUntil( 139 | MaterialPageRoute(builder: (_) => Register()), 140 | (Route route) => false); 141 | firebaseUser = null; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /lib/stores/login_store.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'login_store.dart'; 4 | 5 | // ************************************************************************** 6 | // StoreGenerator 7 | // ************************************************************************** 8 | 9 | // ignore_for_file: non_constant_identifier_names, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic 10 | 11 | mixin _$LoginStore on LoginStoreBase, Store { 12 | final _$isLoginLoadingAtom = Atom(name: 'LoginStoreBase.isLoginLoading'); 13 | 14 | @override 15 | bool get isLoginLoading { 16 | _$isLoginLoadingAtom.context.enforceReadPolicy(_$isLoginLoadingAtom); 17 | _$isLoginLoadingAtom.reportObserved(); 18 | return super.isLoginLoading; 19 | } 20 | 21 | @override 22 | set isLoginLoading(bool value) { 23 | _$isLoginLoadingAtom.context.conditionallyRunInAction(() { 24 | super.isLoginLoading = value; 25 | _$isLoginLoadingAtom.reportChanged(); 26 | }, _$isLoginLoadingAtom, name: '${_$isLoginLoadingAtom.name}_set'); 27 | } 28 | 29 | final _$isOtpLoadingAtom = Atom(name: 'LoginStoreBase.isOtpLoading'); 30 | 31 | @override 32 | bool get isOtpLoading { 33 | _$isOtpLoadingAtom.context.enforceReadPolicy(_$isOtpLoadingAtom); 34 | _$isOtpLoadingAtom.reportObserved(); 35 | return super.isOtpLoading; 36 | } 37 | 38 | @override 39 | set isOtpLoading(bool value) { 40 | _$isOtpLoadingAtom.context.conditionallyRunInAction(() { 41 | super.isOtpLoading = value; 42 | _$isOtpLoadingAtom.reportChanged(); 43 | }, _$isOtpLoadingAtom, name: '${_$isOtpLoadingAtom.name}_set'); 44 | } 45 | 46 | final _$loginScaffoldKeyAtom = Atom(name: 'LoginStoreBase.loginScaffoldKey'); 47 | 48 | @override 49 | GlobalKey get loginScaffoldKey { 50 | _$loginScaffoldKeyAtom.context.enforceReadPolicy(_$loginScaffoldKeyAtom); 51 | _$loginScaffoldKeyAtom.reportObserved(); 52 | return super.loginScaffoldKey; 53 | } 54 | 55 | @override 56 | set loginScaffoldKey(GlobalKey value) { 57 | _$loginScaffoldKeyAtom.context.conditionallyRunInAction(() { 58 | super.loginScaffoldKey = value; 59 | _$loginScaffoldKeyAtom.reportChanged(); 60 | }, _$loginScaffoldKeyAtom, name: '${_$loginScaffoldKeyAtom.name}_set'); 61 | } 62 | 63 | final _$otpScaffoldKeyAtom = Atom(name: 'LoginStoreBase.otpScaffoldKey'); 64 | 65 | @override 66 | GlobalKey get otpScaffoldKey { 67 | _$otpScaffoldKeyAtom.context.enforceReadPolicy(_$otpScaffoldKeyAtom); 68 | _$otpScaffoldKeyAtom.reportObserved(); 69 | return super.otpScaffoldKey; 70 | } 71 | 72 | @override 73 | set otpScaffoldKey(GlobalKey value) { 74 | _$otpScaffoldKeyAtom.context.conditionallyRunInAction(() { 75 | super.otpScaffoldKey = value; 76 | _$otpScaffoldKeyAtom.reportChanged(); 77 | }, _$otpScaffoldKeyAtom, name: '${_$otpScaffoldKeyAtom.name}_set'); 78 | } 79 | 80 | final _$firebaseUserAtom = Atom(name: 'LoginStoreBase.firebaseUser'); 81 | 82 | @override 83 | FirebaseUser get firebaseUser { 84 | _$firebaseUserAtom.context.enforceReadPolicy(_$firebaseUserAtom); 85 | _$firebaseUserAtom.reportObserved(); 86 | return super.firebaseUser; 87 | } 88 | 89 | @override 90 | set firebaseUser(FirebaseUser value) { 91 | _$firebaseUserAtom.context.conditionallyRunInAction(() { 92 | super.firebaseUser = value; 93 | _$firebaseUserAtom.reportChanged(); 94 | }, _$firebaseUserAtom, name: '${_$firebaseUserAtom.name}_set'); 95 | } 96 | 97 | final _$isAlreadyAuthenticatedAsyncAction = 98 | AsyncAction('isAlreadyAuthenticated'); 99 | 100 | @override 101 | Future isAlreadyAuthenticated() { 102 | return _$isAlreadyAuthenticatedAsyncAction 103 | .run(() => super.isAlreadyAuthenticated()); 104 | } 105 | 106 | final _$getCodeWithPhoneNumberAsyncAction = 107 | AsyncAction('getCodeWithPhoneNumber'); 108 | 109 | @override 110 | Future getCodeWithPhoneNumber( 111 | BuildContext context, String phoneNumber) { 112 | return _$getCodeWithPhoneNumberAsyncAction 113 | .run(() => super.getCodeWithPhoneNumber(context, phoneNumber)); 114 | } 115 | 116 | final _$validateOtpAndLoginAsyncAction = AsyncAction('validateOtpAndLogin'); 117 | 118 | @override 119 | Future validateOtpAndLogin(BuildContext context, String smsCode) { 120 | return _$validateOtpAndLoginAsyncAction 121 | .run(() => super.validateOtpAndLogin(context, smsCode)); 122 | } 123 | 124 | final _$signOutAsyncAction = AsyncAction('signOut'); 125 | 126 | @override 127 | Future signOut(BuildContext context) { 128 | return _$signOutAsyncAction.run(() => super.signOut(context)); 129 | } 130 | 131 | @override 132 | String toString() { 133 | final string = 134 | 'isLoginLoading: ${isLoginLoading.toString()},isOtpLoading: ${isOtpLoading.toString()},loginScaffoldKey: ${loginScaffoldKey.toString()},otpScaffoldKey: ${otpScaffoldKey.toString()},firebaseUser: ${firebaseUser.toString()}'; 135 | return '{$string}'; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /lib/widgets/addMedicineDialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:soochit/global/myColors.dart'; 5 | import 'package:soochit/global/myDimens.dart'; 6 | import 'package:soochit/global/mySpaces.dart'; 7 | import 'package:soochit/global/myStrings.dart'; 8 | import 'package:firebase_auth/firebase_auth.dart'; 9 | import 'package:cloud_firestore/cloud_firestore.dart'; 10 | 11 | 12 | class AddMedicineDialog extends StatefulWidget { 13 | @override 14 | _AddMedicineDialogState createState() => _AddMedicineDialogState(); 15 | } 16 | 17 | class _AddMedicineDialogState extends State { 18 | 19 | TextEditingController medicineNameController = new TextEditingController(); 20 | TextEditingController timeController = new TextEditingController(); 21 | String time; 22 | String medicineName; 23 | List medicineList = []; 24 | 25 | void _onPressedAddMedicineDetails() async{ 26 | var firebaseUser = await FirebaseAuth.instance.currentUser(); // finds the current user 27 | // this takes up a firebase instance and makes a collection and a document (if not present already). 28 | // Further it overwrites all data inside that collection and document by the string map we have pu 29 | medicineList.add(medicineNameController.text); 30 | 31 | Firestore.instance.collection('Medicine').document(firebaseUser.uid).updateData( 32 | { 33 | timeController.text:FieldValue.arrayUnion(medicineList), 34 | // the string map to add to FireStore 35 | }).then((_){ 36 | print('added medicine details'); // print some message to console to see everything went good! 37 | }); 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return Dialog( 43 | shape: RoundedRectangleBorder( 44 | borderRadius: BorderRadius.circular(MyDimens.double_10), 45 | ), 46 | elevation: 0.0, 47 | backgroundColor: MyColors.primaryColor, 48 | child: Container( 49 | margin: EdgeInsets.all(20), 50 | color: MyColors.primaryColor, 51 | child: Wrap( 52 | children: [ 53 | Column( 54 | crossAxisAlignment: CrossAxisAlignment.start, 55 | mainAxisAlignment: MainAxisAlignment.center, 56 | children: [ 57 | Text( 58 | MyStrings.addAMedicineLabel, style: Theme.of(context).textTheme.headline5.copyWith(color: MyColors.white, fontFamily: 'lexenddeca'), 59 | ), 60 | MySpaces.vSmallGapInBetween, 61 | _CupertinoTextFieldPres(placeholderTextIndex: 0, textInputType: TextInputType.text, controller: medicineNameController,), 62 | MySpaces.vGapInBetween, 63 | _CupertinoTextFieldPres(placeholderTextIndex: 1, textInputType: TextInputType.text, controller: timeController,), 64 | MySpaces.vGapInBetween, 65 | Row( 66 | mainAxisAlignment: MainAxisAlignment.end, 67 | children: [ 68 | GestureDetector( 69 | onTap: (){ 70 | Navigator.of(context).pop(); 71 | }, 72 | child: Text(MyStrings.cancelLabel, style: Theme.of(context).textTheme.bodyText2.copyWith(color: MyColors.lightPink, fontSize: MyDimens.double_15, fontFamily: 'lexenddeca'),), 73 | ), 74 | MySpaces.hSmallGapInBetween, 75 | FlatButton( 76 | shape: RoundedRectangleBorder( 77 | borderRadius: BorderRadius.circular(MyDimens.double_4), 78 | ), 79 | onPressed: (){ 80 | // adds the medicine in database. 81 | _onPressedAddMedicineDetails(); 82 | Navigator.of(context).pop(); 83 | }, 84 | color: MyColors.white, 85 | child: Text( 86 | MyStrings.confirmLabel, style: Theme.of(context).textTheme.bodyText1.copyWith(color: MyColors.primaryColor, fontSize: MyDimens.double_15, fontFamily: 'lexendeca'), 87 | ), 88 | ) 89 | ], 90 | ), 91 | ], 92 | ), 93 | ], 94 | ) 95 | ) 96 | ); 97 | } 98 | } 99 | 100 | class _CupertinoTextFieldPres extends StatelessWidget { 101 | int placeholderTextIndex; 102 | TextInputType textInputType; 103 | TextEditingController controller; 104 | 105 | _CupertinoTextFieldPres({@required this.placeholderTextIndex, @required this.textInputType, this.controller}); 106 | List placeholderTextList = [ 107 | MyStrings.medicineNameLabel, 108 | MyStrings.timingsLabel, 109 | ]; 110 | 111 | @override 112 | Widget build(BuildContext context) { 113 | return CupertinoTextField( 114 | controller: controller, 115 | keyboardType: textInputType, 116 | padding: EdgeInsets.symmetric( 117 | horizontal: MyDimens.double_20, vertical: MyDimens.double_15), 118 | decoration: BoxDecoration( 119 | color: MyColors.inputFieldPink, 120 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 121 | style: Theme.of(context) 122 | .textTheme 123 | .subtitle1 124 | .copyWith(color: MyColors.lightestPink, fontFamily: 'lexenddeca'), 125 | maxLines: 1, 126 | cursorColor: MyColors.white, 127 | cursorWidth: 3, 128 | cursorRadius: Radius.circular(50), 129 | placeholder: placeholderTextList[placeholderTextIndex], 130 | placeholderStyle: Theme.of(context).textTheme.headline6.copyWith( 131 | fontSize: 18, 132 | color: MyColors.inputFieldTextPink, 133 | fontFamily: 'lexenddeca'), 134 | ); 135 | } 136 | } 137 | 138 | 139 | -------------------------------------------------------------------------------- /lib/widgets/addPatientDialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:soochit/global/myColors.dart'; 5 | import 'package:soochit/global/myDimens.dart'; 6 | import 'package:soochit/global/mySpaces.dart'; 7 | import 'package:soochit/global/myStrings.dart'; 8 | 9 | class AddPatientDialog extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | return Dialog( 13 | shape: RoundedRectangleBorder( 14 | borderRadius: BorderRadius.circular(MyDimens.double_10), 15 | ), 16 | elevation: 0.0, 17 | backgroundColor: MyColors.primaryColor, 18 | child: Container( 19 | margin: EdgeInsets.all(20), 20 | color: MyColors.primaryColor, 21 | child: Wrap( 22 | children: [ 23 | Column( 24 | crossAxisAlignment: CrossAxisAlignment.start, 25 | mainAxisAlignment: MainAxisAlignment.center, 26 | children: [ 27 | Text( 28 | MyStrings.addAPatientLabel, style: Theme.of(context).textTheme.headline5.copyWith(color: MyColors.white, fontFamily: 'lexenddeca'), 29 | ), 30 | MySpaces.vSmallGapInBetween, 31 | CupertinoTextField( 32 | keyboardType: TextInputType.phone, 33 | padding: EdgeInsets.symmetric( 34 | horizontal: MyDimens.double_20, vertical: MyDimens.double_15), 35 | decoration: BoxDecoration( 36 | color: MyColors.inputFieldPink, 37 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4))), 38 | style: Theme.of(context) 39 | .textTheme 40 | .subtitle1 41 | .copyWith(color: MyColors.lightestPink, fontFamily: 'lexenddeca'), 42 | maxLines: 1, 43 | cursorColor: MyColors.white, 44 | cursorWidth: 3, 45 | cursorRadius: Radius.circular(50), 46 | placeholder: MyStrings.phoneNumberLabel, 47 | placeholderStyle: Theme.of(context).textTheme.headline6.copyWith( 48 | fontSize: 18, 49 | color: MyColors.inputFieldTextPink, 50 | fontFamily: 'lexenddeca'), 51 | ), 52 | MySpaces.vGapInBetween, 53 | Row( 54 | mainAxisAlignment: MainAxisAlignment.end, 55 | children: [ 56 | GestureDetector( 57 | onTap: (){ 58 | Navigator.of(context).pop(); 59 | }, 60 | child: Text(MyStrings.cancelLabel, style: Theme.of(context).textTheme.bodyText2.copyWith(color: MyColors.lightPink, fontSize: MyDimens.double_15, fontFamily: 'lexenddeca'),), 61 | ), 62 | MySpaces.hSmallGapInBetween, 63 | FlatButton( 64 | shape: RoundedRectangleBorder( 65 | borderRadius: BorderRadius.circular(MyDimens.double_4), 66 | ), 67 | onPressed: (){ 68 | // TODO: add the user in doctor's database. 69 | Navigator.of(context).pop(); 70 | }, 71 | color: MyColors.white, 72 | child: Text( 73 | MyStrings.confirmLabel, style: Theme.of(context).textTheme.bodyText1.copyWith(color: MyColors.primaryColor, fontSize: MyDimens.double_15, fontFamily: 'lexendeca'), 74 | ), 75 | ) 76 | ], 77 | ), 78 | ], 79 | ), 80 | ], 81 | ) 82 | ) 83 | ); 84 | } 85 | } 86 | 87 | 88 | -------------------------------------------------------------------------------- /lib/widgets/loaderHud.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:soochit/global/myColors.dart'; 3 | import 'package:soochit/global/myDimens.dart'; 4 | 5 | class LoaderHUD extends StatelessWidget { 6 | final bool inAsyncCall; 7 | final double opacity; 8 | final Color color; 9 | final Widget progressIndicator = Container( 10 | width: MyDimens.double_200, 11 | height: MyDimens.double_100, 12 | decoration: BoxDecoration( 13 | borderRadius: BorderRadius.all(Radius.circular(MyDimens.double_4)), 14 | color: MyColors.primaryColor.withOpacity(0.6), 15 | ), 16 | child: const Center(child: CircularProgressIndicator()), 17 | ); 18 | final bool dismissible; 19 | final Widget child; 20 | 21 | LoaderHUD({ 22 | Key key, 23 | @required this.inAsyncCall, 24 | this.opacity = 0.3, 25 | this.color = MyColors.lightestPink, 26 | this.dismissible = false, 27 | @required this.child, 28 | }) : assert(child != null), 29 | assert(inAsyncCall != null), 30 | super(key: key); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | if (!inAsyncCall) return child; 35 | 36 | return Stack( 37 | children: [ 38 | child, 39 | Opacity( 40 | child: ModalBarrier(dismissible: dismissible, color: color), 41 | opacity: opacity, 42 | ), 43 | Center(child: progressIndicator), 44 | ], 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/widgets/medicineDeadlineReminder.dart: -------------------------------------------------------------------------------- 1 | import 'package:cloud_firestore/cloud_firestore.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:soochit/global/myStrings.dart'; 4 | import 'package:soochit/global/myDimens.dart'; 5 | import 'package:soochit/global/myColors.dart'; 6 | import 'package:soochit/global/mySpaces.dart'; 7 | 8 | class MedicineDeadlineReminder extends StatelessWidget { 9 | String time; 10 | List medName; 11 | MedicineDeadlineReminder({@required this.medName, @required this.time}); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Column( 16 | children: [ 17 | Container( 18 | height: MyDimens.double_35, 19 | width: MediaQuery.of(context).size.width * 0.80, 20 | decoration: BoxDecoration( 21 | borderRadius: BorderRadius.only( 22 | topLeft: Radius.circular(MyDimens.double_10), 23 | topRight: Radius.circular(MyDimens.double_10)), 24 | color: MyColors.primaryColor, 25 | ), 26 | child: Align( 27 | child: Text( 28 | time, 29 | style: Theme.of(context) 30 | .textTheme 31 | .subtitle1 32 | .copyWith(color: MyColors.white, fontFamily: 'lexenddeca'), 33 | ), 34 | alignment: Alignment.center, 35 | )), 36 | Container( 37 | padding: EdgeInsets.symmetric(horizontal: MyDimens.double_35, vertical: MyDimens.double_10), 38 | width: MediaQuery.of(context).size.width * 0.80, 39 | decoration: BoxDecoration( 40 | borderRadius: BorderRadius.only( 41 | bottomLeft: Radius.circular(MyDimens.double_10), 42 | bottomRight: Radius.circular(MyDimens.double_10)), 43 | color: MyColors.lightestPink, 44 | ), 45 | child: Wrap( 46 | children: [ 47 | Column( 48 | mainAxisAlignment: MainAxisAlignment.center, 49 | crossAxisAlignment: CrossAxisAlignment.start, 50 | children: [ 51 | for (var i=0; i SamplePatientProfile(patientDet: patientDet))); 14 | }, 15 | child: Column( 16 | children: [ 17 | Container( 18 | padding: EdgeInsets.symmetric(horizontal: MyDimens.double_30), 19 | height: MyDimens.double_70, 20 | width: MediaQuery.of(context).size.width * 0.90, 21 | decoration: BoxDecoration( 22 | borderRadius: BorderRadius.circular(MyDimens.double_7), 23 | color: MyColors.lightestPink, 24 | ), 25 | child: Row( 26 | mainAxisAlignment: MainAxisAlignment.center, 27 | children: [ 28 | new Container( 29 | width: 40.0, 30 | height: 40.0, 31 | decoration: new BoxDecoration( 32 | shape: BoxShape.circle, 33 | image: new DecorationImage( 34 | fit: BoxFit.fill, 35 | image: 36 | new NetworkImage("https://github.com/dotrachit.png"), 37 | ))), 38 | MySpaces.hSmallGapInBetween, 39 | Column( 40 | mainAxisAlignment: MainAxisAlignment.center, 41 | crossAxisAlignment: CrossAxisAlignment.start, 42 | children: [ 43 | Text( 44 | patientDet[1], 45 | style: Theme.of(context).textTheme.headline5.copyWith( 46 | color: MyColors.black, fontFamily: 'lexenddeca'), 47 | ), 48 | MySpaces.vSmallestGapInBetween, 49 | Text( 50 | patientDet[2] + 51 | ' • ' + 52 | MyStrings.recentAppointmentDate, 53 | style: Theme.of(context) 54 | .textTheme 55 | .bodyText2 56 | .copyWith(color: MyColors.grey, fontFamily: 'lexenddeca'), 57 | ), 58 | ], 59 | ) 60 | ], 61 | ), 62 | ), 63 | MySpaces.vSmallGapInBetween, 64 | ], 65 | ), 66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /lib/widgets/snackbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:soochit/global/myColors.dart'; 3 | 4 | Widget getSnackBar(BuildContext context, String text) { 5 | return SnackBar( 6 | behavior: SnackBarBehavior.floating, 7 | backgroundColor: MyColors.white, 8 | content: Text( 9 | text, 10 | style: Theme.of(context).textTheme.bodyText1.copyWith( 11 | color: MyColors.primaryColor, fontFamily: 'lexenddeca'), 12 | ), 13 | ); 14 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: soochit 2 | description: Not just another medicine reminder. 3 | 4 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.7.0 <3.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | numeric_keyboard: ^1.0.0 16 | cupertino_icons: ^0.1.3 17 | firebase_core: ^0.4.4+3 18 | firebase_auth: ^0.15.5+3 19 | mobx: ^1.1.1 20 | flutter_mobx: ^1.1.0 21 | provider: ^4.0.4 22 | cloud_firestore: ^0.13.6 23 | firebase_storage: ^3.0.6 24 | flutter_local_notifications: ^1.4.4+1 25 | rxdart: ^0.24.1 26 | path_provider: ^1.6.11 27 | http: ^0.12.1 28 | 29 | dev_dependencies: 30 | flutter_test: 31 | sdk: flutter 32 | build_runner: ^1.8.1 33 | mobx_codegen: ^1.0.3 34 | 35 | flutter: 36 | 37 | uses-material-design: true 38 | 39 | # assets: 40 | # - images/a_dot_burr.jpeg 41 | # - images/a_dot_ham.jpeg 42 | 43 | # An image asset can refer to one or more resolution-specific "variants", see 44 | # https://flutter.dev/assets-and-images/#resolution-aware. 45 | 46 | # For details regarding adding assets from package dependencies, see 47 | # https://flutter.dev/assets-and-images/#from-packages 48 | 49 | fonts: 50 | - family: airbnb 51 | fonts: 52 | - asset: assets/fonts/AirbnbCereal-Bold.ttf 53 | weight: 800 54 | 55 | - family: lexenddeca 56 | fonts: 57 | - asset: assets/fonts/LexendDeca-Regular.ttf 58 | 59 | assets: 60 | - assets/images/ -------------------------------------------------------------------------------- /screenshots.md: -------------------------------------------------------------------------------- 1 | |Welcome Screen|Add Medicine Screen|Confirm OTP Screen| 2 | |------|------|------| 3 | |||| 4 | 5 | |Previous Patients Screen|Add Patient Dialog|Medicine Deadlines Screen| 6 | |------|------|------| 7 | |||| 8 | 9 | |Prescription History Screen| 10 | |------| 11 | || 12 | -------------------------------------------------------------------------------- /setup-instructions.md: -------------------------------------------------------------------------------- 1 | # Setup instructions 2 | 3 | ## Prerequisites 4 | 5 | - [Android Studio](https://developer.android.com/studio) or any IDE to open Flutter project 6 | - JDK 7 | 8 | ## Installations 9 | 10 | 1. Install Flutter by following instructions from [flutter.dev](https://flutter.dev). To summarise: 11 | - Select the appropriate operating system 12 | - Download the flutter sdk to a preferred location on your local system. 13 | 2. Fork and clone the [soochit repository](https://github.com/MLH-Fellowship/soochit) repository to your local machine. 14 | 3. Make sure to install the **Flutter** and **Dart** plugins. 15 | - If Soochir is the first project that you will be viewing in Android Studio then: 16 | - Start Android Studio 17 | - Open Plugin Preferences 18 | - Browse repositories and search for flutter 19 | - Install and click yes to install Dart as well if prompted. 20 | - Flutter and dart can also be installed after opening a project. 21 | - Go to File menu -> Settings -> plugins 22 | - Search for the plugin. In this case it would be Flutter and Dart. Install them if not done yet and click Apply. 23 | 24 | ## Local Development Setup 25 | 26 | This section will help you set up the project locally on your system. 27 | 28 | 1. Open the project on your IDE. 29 | 2. Run `pub get` on project level terminal to install all the required dependencies. 30 | 3. Ensure that the Flutter SDK is provided the correct path. Open File menu -> Settings -> Languages & Frameworks -> Flutter 31 | 4. In order to run a flutter project, either a virtual device needs to be setup or a physical device can be used. Remember to `enable Debugging` in **Developer Options** in the physical device. 32 | 5. Connect your physical device or setup the virtual device before you run the application. Ensure that the device is visible on top menu. 33 | 34 | ## Firebase Configurations 35 | Follow the [official firebase documentation](https://firebase.google.com/docs/flutter/setup?platform=android) to connect firebase to the app locally. The following information, however, is required to set it up successfully. 36 | 37 | * Name the firebase project `Soochit`. 38 | * Before adding apps, go to Authentication under Develop, and click on the Set up sign-in method button. Enable `Phone` sign-in provider. 39 | * Android package name: `com.example.soochit` 40 | * Be sure to enter your SHA key so that authentication can work properly. 41 | 42 | Refer to the Flutter [online documentation](https://flutter.dev/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. 43 | 44 | Huge shoutout to [AnitaB's mentorship-flutter project](https://github.com/anitab-org/mentorship-flutter) for the detailed installation guide! 🚀 45 | -------------------------------------------------------------------------------- /soochit.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:soochit/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | --------------------------------------------------------------------------------