diff --git a/GoogleService-Info.plist b/GoogleService-Info.plist deleted file mode 100644 index 0c093a2a..00000000 --- a/GoogleService-Info.plist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - CLIENT_ID - 864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r.apps.googleusercontent.com - REVERSED_CLIENT_ID - com.googleusercontent.apps.864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r - API_KEY - AIzaSyA_6ayGCk4fly7o7eTVBrj9kuHBYHMAOfs - GCM_SENDER_ID - 864393916058 - PLIST_VERSION - 1 - BUNDLE_ID - com.cloud.diplomaticquarterapp - PROJECT_ID - diplomaticquarter-d2385 - STORAGE_BUCKET - diplomaticquarter-d2385.appspot.com - IS_ADS_ENABLED - - IS_ANALYTICS_ENABLED - - IS_APPINVITE_ENABLED - - IS_GCM_ENABLED - - IS_SIGNIN_ENABLED - - GOOGLE_APP_ID - 1:864393916058:ios:13f787bbfe6051f8b97923 - DATABASE_URL - https://diplomaticquarter-d2385.firebaseio.com - - \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 11e99a2a..336e8e53 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -39,7 +39,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.cloud.diplomaticquarterapp" +// applicationId "com.cloud.diplomaticquarterapp" + applicationId "com.ejada.hmg.uat" minSdkVersion 21 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() diff --git a/android/app/google-services.json b/android/app/google-services.json index a4655794..6d1d75a9 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -1,37 +1,39 @@ { "project_info": { - "project_number": "864393916058", - "firebase_url": "https://diplomaticquarter-d2385.firebaseio.com", - "project_id": "diplomaticquarter-d2385", - "storage_bucket": "diplomaticquarter-d2385.appspot.com" + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.appspot.com" }, "client": [ { "client_info": { - "mobilesdk_app_id": "1:864393916058:android:5b5a65cd6d8c18b4b97923", + "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", "android_client_info": { - "package_name": "com.cloud.diplomaticquarterapp" + "package_name": "com.ejada.hmg.uat" } }, "oauth_client": [ { - "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com", + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", "client_type": 3 } ], "api_key": [ { - "current_key": "AIzaSyBdV3mos1BPhUzNKCj2KANJtiO3o2zh9IM" + "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw" } ], "services": { + "analytics_service": { + "status": 1 + }, "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com", - "client_type": 3 - } - ] + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 } } } diff --git a/android/app/gradle/wrapper/gradle-wrapper.properties b/android/app/gradle/wrapper/gradle-wrapper.properties index 8fc3bbec..a2c20300 100644 --- a/android/app/gradle/wrapper/gradle-wrapper.properties +++ b/android/app/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +#distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1a3d4cfe..63f94294 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ In most cases you can leave this as-is, but you if you want to provide additional functionality it is fine to subclass or reimplement FlutterApplication and put your custom class here. --> + @@ -29,12 +30,16 @@ - + + + + + + android:label="Dr. Alhabib"> + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4b..348b5116 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b79..410b1b1e 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d43914..bb9943af 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d3..0b9d9359 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372ee..aaa9808d 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/build.gradle b/android/build.gradle index 32bda0b1..c0fc03b3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -9,16 +9,17 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:3.5.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.4' + classpath 'com.google.gms:google-services:4.3.8' } } allprojects { repositories { google() - jcenter() +// jcenter() + mavenCentral() } } diff --git a/android/google-services.json b/android/google-services.json index a4655794..dd4038cf 100644 --- a/android/google-services.json +++ b/android/google-services.json @@ -1,37 +1,39 @@ { "project_info": { - "project_number": "864393916058", - "firebase_url": "https://diplomaticquarter-d2385.firebaseio.com", - "project_id": "diplomaticquarter-d2385", - "storage_bucket": "diplomaticquarter-d2385.appspot.com" + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.appspot.com" }, "client": [ { "client_info": { - "mobilesdk_app_id": "1:864393916058:android:5b5a65cd6d8c18b4b97923", + "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", "android_client_info": { - "package_name": "com.cloud.diplomaticquarterapp" + "package_name": "com.ejada.hmg" } }, "oauth_client": [ { - "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com", + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", "client_type": 3 } ], "api_key": [ { - "current_key": "AIzaSyBdV3mos1BPhUzNKCj2KANJtiO3o2zh9IM" + "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw" } ], "services": { + "analytics_service": { + "status": 1 + }, "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "864393916058-tphjrn8j39ntevt32ekcvmll8aue7qql.apps.googleusercontent.com", - "client_type": 3 - } - ] + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 } } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 1f9de82f..6fdb0e44 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Sep 03 16:26:30 EEST 2020 +#Wed Jul 14 15:55:18 AST 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/assets/images/1.png b/assets/images/1.png new file mode 100644 index 00000000..c90aa190 Binary files /dev/null and b/assets/images/1.png differ diff --git a/assets/images/2.png b/assets/images/2.png new file mode 100644 index 00000000..48891b32 Binary files /dev/null and b/assets/images/2.png differ diff --git a/assets/images/3.png b/assets/images/3.png new file mode 100644 index 00000000..721f6e6c Binary files /dev/null and b/assets/images/3.png differ diff --git a/assets/images/4.png b/assets/images/4.png new file mode 100644 index 00000000..6d61b45f Binary files /dev/null and b/assets/images/4.png differ diff --git a/assets/images/5.png b/assets/images/5.png new file mode 100644 index 00000000..e45f432c Binary files /dev/null and b/assets/images/5.png differ diff --git a/assets/images/AlHabibMedicalService/health_calculator/bmi.png b/assets/images/AlHabibMedicalService/health_calculator/bmi.png new file mode 100644 index 00000000..6df6c9f9 Binary files /dev/null and b/assets/images/AlHabibMedicalService/health_calculator/bmi.png differ diff --git a/assets/images/AlHabibMedicalService/health_calculator/bmr.png b/assets/images/AlHabibMedicalService/health_calculator/bmr.png new file mode 100644 index 00000000..db31ed43 Binary files /dev/null and b/assets/images/AlHabibMedicalService/health_calculator/bmr.png differ diff --git a/assets/images/AlHabibMedicalService/health_calculator/body-fat.png b/assets/images/AlHabibMedicalService/health_calculator/body-fat.png new file mode 100644 index 00000000..97b05df3 Binary files /dev/null and b/assets/images/AlHabibMedicalService/health_calculator/body-fat.png differ diff --git a/assets/images/bc_parking.png b/assets/images/bc_parking.png new file mode 100644 index 00000000..64633516 Binary files /dev/null and b/assets/images/bc_parking.png differ diff --git a/assets/images/new-design/pending.svg b/assets/images/new-design/pending.svg new file mode 100644 index 00000000..2c26afbd --- /dev/null +++ b/assets/images/new-design/pending.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/new-design/verification_check.svg b/assets/images/new-design/verification_check.svg new file mode 100644 index 00000000..1b3cdcca --- /dev/null +++ b/assets/images/new-design/verification_check.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/new/hmg_logo.png b/assets/images/new/hmg_logo.png new file mode 100644 index 00000000..2555cfa9 Binary files /dev/null and b/assets/images/new/hmg_logo.png differ diff --git a/assets/images/nfc/ic_done.png b/assets/images/nfc/ic_done.png new file mode 100644 index 00000000..5b802855 Binary files /dev/null and b/assets/images/nfc/ic_done.png differ diff --git a/assets/images/nfc/ic_nfc.png b/assets/images/nfc/ic_nfc.png new file mode 100644 index 00000000..274e1b8c Binary files /dev/null and b/assets/images/nfc/ic_nfc.png differ diff --git a/assets/images/powerd-by.jpg b/assets/images/powerd-by.jpg index 93bdbb18..eda1688c 100644 Binary files a/assets/images/powerd-by.jpg and b/assets/images/powerd-by.jpg differ diff --git a/assets/images/powerd-by2.jpg b/assets/images/powerd-by2.jpg new file mode 100644 index 00000000..93bdbb18 Binary files /dev/null and b/assets/images/powerd-by2.jpg differ diff --git a/assets/payment_options/payment_options.png b/assets/payment_options/payment_options.png new file mode 100644 index 00000000..4bb83fec Binary files /dev/null and b/assets/payment_options/payment_options.png differ diff --git a/google-services.json b/google-services_DQ.json similarity index 100% rename from google-services.json rename to google-services_DQ.json diff --git a/google-services_HMG.json b/google-services_HMG.json new file mode 100644 index 00000000..dd4038cf --- /dev/null +++ b/google-services_HMG.json @@ -0,0 +1,42 @@ +{ + "project_info": { + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", + "android_client_info": { + "package_name": "com.ejada.hmg" + } + }, + "oauth_client": [ + { + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/hms-plugins/flutter-hms-location/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/hms-plugins/flutter-hms-location/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java new file mode 100644 index 00000000..975e9019 --- /dev/null +++ b/hms-plugins/flutter-hms-location/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -0,0 +1,25 @@ +package io.flutter.plugins; + +import io.flutter.plugin.common.PluginRegistry; +import com.huawei.hms.flutter.location.LocationPlugin; + +/** + * Generated file. Do not edit. + */ +public final class GeneratedPluginRegistrant { + public static void registerWith(PluginRegistry registry) { + if (alreadyRegisteredWith(registry)) { + return; + } + LocationPlugin.registerWith(registry.registrarFor("com.huawei.hms.flutter.location.LocationPlugin")); + } + + private static boolean alreadyRegisteredWith(PluginRegistry registry) { + final String key = GeneratedPluginRegistrant.class.getCanonicalName(); + if (registry.hasPlugin(key)) { + return true; + } + registry.registrarFor(key); + return false; + } +} diff --git a/hms-plugins/flutter-hms-location/android/local.properties b/hms-plugins/flutter-hms-location/android/local.properties new file mode 100644 index 00000000..c6cb6fc0 --- /dev/null +++ b/hms-plugins/flutter-hms-location/android/local.properties @@ -0,0 +1,2 @@ +sdk.dir=C:\\Users\\sultan.khan\\AppData\\Local\\Android\\Sdk +flutter.sdk=C:\\Program Files\\flutter \ No newline at end of file diff --git a/hms-plugins/flutter-hms-location/ios/Flutter/Generated.xcconfig b/hms-plugins/flutter-hms-location/ios/Flutter/Generated.xcconfig new file mode 100644 index 00000000..4527e66e --- /dev/null +++ b/hms-plugins/flutter-hms-location/ios/Flutter/Generated.xcconfig @@ -0,0 +1,14 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=C:\Program Files\flutter +FLUTTER_APPLICATION_PATH=C:\Projects\DQ\hms-plugins\flutter-hms-location +FLUTTER_TARGET=lib\main.dart +FLUTTER_BUILD_DIR=build +SYMROOT=${SOURCE_ROOT}/../build\ios +OTHER_LDFLAGS=$(inherited) -framework Flutter +FLUTTER_FRAMEWORK_DIR=C:\Program Files\flutter\bin\cache\artifacts\engine\ios +FLUTTER_BUILD_NAME=5.0.0 +FLUTTER_BUILD_NUMBER=301 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=false +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.packages diff --git a/hms-plugins/flutter-hms-location/ios/Flutter/flutter_export_environment.sh b/hms-plugins/flutter-hms-location/ios/Flutter/flutter_export_environment.sh new file mode 100644 index 00000000..87c35592 --- /dev/null +++ b/hms-plugins/flutter-hms-location/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=C:\Program Files\flutter" +export "FLUTTER_APPLICATION_PATH=C:\Projects\DQ\hms-plugins\flutter-hms-location" +export "FLUTTER_TARGET=lib\main.dart" +export "FLUTTER_BUILD_DIR=build" +export "SYMROOT=${SOURCE_ROOT}/../build\ios" +export "OTHER_LDFLAGS=$(inherited) -framework Flutter" +export "FLUTTER_FRAMEWORK_DIR=C:\Program Files\flutter\bin\cache\artifacts\engine\ios" +export "FLUTTER_BUILD_NAME=5.0.0" +export "FLUTTER_BUILD_NUMBER=301" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=false" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.packages" diff --git a/hms-plugins/flutter-hms-location/ios/Runner/GeneratedPluginRegistrant.h b/hms-plugins/flutter-hms-location/ios/Runner/GeneratedPluginRegistrant.h new file mode 100644 index 00000000..ed9a5c61 --- /dev/null +++ b/hms-plugins/flutter-hms-location/ios/Runner/GeneratedPluginRegistrant.h @@ -0,0 +1,17 @@ +// +// Generated file. Do not edit. +// + +#ifndef GeneratedPluginRegistrant_h +#define GeneratedPluginRegistrant_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GeneratedPluginRegistrant : NSObject ++ (void)registerWithRegistry:(NSObject*)registry; +@end + +NS_ASSUME_NONNULL_END +#endif /* GeneratedPluginRegistrant_h */ diff --git a/hms-plugins/flutter-hms-location/ios/Runner/GeneratedPluginRegistrant.m b/hms-plugins/flutter-hms-location/ios/Runner/GeneratedPluginRegistrant.m new file mode 100644 index 00000000..60dfa42b --- /dev/null +++ b/hms-plugins/flutter-hms-location/ios/Runner/GeneratedPluginRegistrant.m @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +#import "GeneratedPluginRegistrant.h" + +@implementation GeneratedPluginRegistrant + ++ (void)registerWithRegistry:(NSObject*)registry { +} + +@end diff --git a/ios/Podfile b/ios/Podfile index d68afba2..89424e2a 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -3,6 +3,7 @@ # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' +$FirebaseAnalyticsWithoutAdIdSupport = true project 'Runner', { 'Debug' => :debug, diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab..e83c3bf5 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1,128 @@ { - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" + "images":[ + { + "idiom":"iphone", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"iphone", + "size":"20x20", + "scale":"3x", + "filename":"Icon-App-20x20@3x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"3x", + "filename":"Icon-App-29x29@3x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"3x", + "filename":"Icon-App-40x40@3x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"2x", + "filename":"Icon-App-60x60@2x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"3x", + "filename":"Icon-App-60x60@3x.png" + }, + { + "idiom":"iphone", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"1x", + "filename":"Icon-App-20x20@1x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"1x", + "filename":"Icon-App-40x40@1x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"1x", + "filename":"Icon-App-76x76@1x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"83.5x83.5", + "scale":"2x", + "filename":"Icon-App-83.5x83.5@2x.png" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "scale" : "1x", + "filename" : "ItunesArtwork@2x.png" + } + ], + "info":{ + "version":1, + "author":"easyappicon" } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } } diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 28c6bf03..0e65243a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 2ccbfd96..2e4c7963 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index f091b6b0..59435c76 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cde1211..20855aad 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index d0ef06e7..11d35da4 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index dcdc2306..93523cbe 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 2ccbfd96..2e4c7963 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index c8f9ed8f..00bb8dbd 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index a6d6b860..3eaa1fb6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index a6d6b860..3eaa1fb6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 75b2d164..fd80aa41 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index c4df70d3..39c7958d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 6a84f41e..47a96a43 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index d0e1f585..8c4ca7b0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist index 0c093a2a..633037cb 100644 --- a/ios/Runner/GoogleService-Info.plist +++ b/ios/Runner/GoogleService-Info.plist @@ -3,21 +3,23 @@ CLIENT_ID - 864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r.apps.googleusercontent.com + 815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com REVERSED_CLIENT_ID - com.googleusercontent.apps.864393916058-ekeb4s8tgfo58dutv0l54399t7ivr06r + com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt + ANDROID_CLIENT_ID + 815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com API_KEY - AIzaSyA_6ayGCk4fly7o7eTVBrj9kuHBYHMAOfs + AIzaSyDiXnCO00li4V7Ioa2YZ_M4ECxRsu_P9tA GCM_SENDER_ID - 864393916058 + 815750722565 PLIST_VERSION 1 BUNDLE_ID - com.cloud.diplomaticquarterapp + com.HMG.HMG-Smartphone PROJECT_ID - diplomaticquarter-d2385 + api-project-815750722565 STORAGE_BUCKET - diplomaticquarter-d2385.appspot.com + api-project-815750722565.appspot.com IS_ADS_ENABLED IS_ANALYTICS_ENABLED @@ -29,8 +31,8 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - 1:864393916058:ios:13f787bbfe6051f8b97923 + 1:815750722565:ios:328ec247a81a2ca23c186c DATABASE_URL - https://diplomaticquarter-d2385.firebaseio.com + https://api-project-815750722565.firebaseio.com \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index ae084167..72bd4ac9 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -11,7 +11,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - diplomaticquarterapp + Dr. Alhabib CFBundlePackageType APPL CFBundleShortVersionString diff --git a/lib/analytics/analytic-events.dart b/lib/analytics/analytic-events.dart new file mode 100644 index 00000000..3e107d95 --- /dev/null +++ b/lib/analytics/analytic-events.dart @@ -0,0 +1,69 @@ +import 'package:diplomaticquarterapp/uitl/utils.dart'; + +class _Event{ + String name; + String description; + bool active; + _Event(dynamic map){ + name = map['name']; + description = map['description']; + active = map['active']; + } + + flutterName() => 'f: $name'; +} + +class AnalyticEvents{ + static _Event get(String key) { + var e = _Event(mapping[key]); + if(e == null){ + var label = labelFrom(className: key); // Convert Class Name in to Label (HomeCare -> Home Care) + e = _Event({"name": label, "active":true, "description":key}); + } + return e; + } + + static var mapping = const { + "HomeHealthCarePage" : { + "active" : true, + "name" : "Home Health Care Page", + "description" : "", + }, + "SplashScreen" : { + "active" : true, + "name" : "Splash Screen", + "description" : "", + }, + "LandingPage" : { + "active" : true, + "name" : "Landing Page", + "description" : "", + }, + "WelcomeLogin" : { + "active" : true, + "name" : "Welcome Login", + "description" : "", + }, + "LoginType" : { + "active" : true, + "name" : "Login Type", + "description" : "", + }, + "Login" : { + "active" : true, + "name" : "Login", + "description" : "", + }, + "ForgotPassword" : { + "active" : true, + "name" : "Forgot Password", + "description" : "", + }, + "" : { + "active" : true, + "name" : "", + "description" : "", + }, + }; +} + diff --git a/lib/analytics/google-analytics.dart b/lib/analytics/google-analytics.dart new file mode 100644 index 00000000..f4bf8b72 --- /dev/null +++ b/lib/analytics/google-analytics.dart @@ -0,0 +1,85 @@ +import 'package:diplomaticquarterapp/analytics/analytic-events.dart'; +import 'package:diplomaticquarterapp/routes.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:firebase_analytics/firebase_analytics.dart'; +import 'package:firebase_analytics/observer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class Singleton { + const Singleton(); //Constant constructor + + void hello() { print('Hello world'); } +} + +var analytics = FirebaseAnalytics(); + +class GAnalytics{ + const GAnalytics(); + static GAnalytics shared = const GAnalytics(); + NavObserver navObserver() => NavObserver(); +} +// adb shell setprop debug.firebase.analytics.app com.ejada.hmg -> Android +class NavObserver extends RouteObserver>{ + + _sendScreenView(PageRoute route) async{ + + + log(String className){ + var event = AnalyticEvents.get(className); + if(event.active){ + analytics.setCurrentScreen(screenName: event.flutterName(), screenClassOverride: className).catchError( (Object error) { + debugPrint('$FirebaseAnalyticsObserver: $error'); + }, + test: (Object error) { + return error is PlatformException; + }, + ); + } + } + + if(route.settings.name != null && route.settings.name.isNotEmpty && route.settings.name != "null"){ + var class_ = routes[route.settings.name](0); + if(class_ != null) + log(class_.toStringShort()); + + }else if(route is FadePage){ + var class_ = route.page; + if(class_ != null) + log(class_.toStringShort()); + + }else if(route is MaterialPageRoute){ + var class_ = route.builder(null); + if (class_ != null) + log(class_.toStringShort()); + + }else{ + print(""); + } + + } + + @override + void didPush(Route route, Route previousRoute) { + super.didPush(route, previousRoute); + if (route is PageRoute) { + _sendScreenView(route); + } + } + + @override + void didReplace({Route newRoute, Route oldRoute}) { + super.didReplace(newRoute: newRoute, oldRoute: oldRoute); + if (newRoute is PageRoute) { + _sendScreenView(newRoute); + } + } + + @override + void didPop(Route route, Route previousRoute) { + super.didPop(route, previousRoute); + // if (previousRoute is PageRoute && route is PageRoute) { + // _sendScreenView(previousRoute); + // } + } +} \ No newline at end of file diff --git a/lib/config/config.dart b/lib/config/config.dart index f87b7628..1a5278d4 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -14,15 +14,15 @@ const PACKAGES_SHOPPING_CART = '/api/shopping_cart_items'; const PACKAGES_ORDERS = '/api/orders'; const BASE_URL = 'https://uat.hmgwebservices.com/'; -//const BASE_URL = 'https://hmgwebservices.com/'; +// const BASE_URL = 'https://hmgwebservices.com/'; // Pharmacy UAT URLs const BASE_PHARMACY_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; const PHARMACY_BASE_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; // Pharmacy Production URLs -// const BASE_PHARMACY_URL = 'https://mdlaboratories.com/exacartapi/api/'; -// const PHARMACY_BASE_URL = 'https://mdlaboratories.com/exacartapi/api/'; +//const BASE_PHARMACY_URL = 'https://mdlaboratories.com/exacartapi/api/'; +//const PHARMACY_BASE_URL = 'https://mdlaboratories.com/exacartapi/api/'; const PING_SERVICE = 'Services/Weather.svc/REST/CheckConnectivity'; @@ -33,8 +33,7 @@ const GET_GEO_ZONES = 'Services/Patients.svc/REST/GeoF_GetAllPoints'; const LOG_GEO_ZONES = 'Services/Patients.svc/REST/GeoF_InsertPatientFileInfo'; // Delivery Driver -const DRIVER_LOCATION = - 'Services/Patients.svc/REST/PatientER_GetDriverLocation'; +const DRIVER_LOCATION = 'Services/Patients.svc/REST/PatientER_GetDriverLocation'; //weather const WEATHER_INDICATOR = 'Services/Weather.svc/REST/GetCityInfo'; @@ -42,51 +41,36 @@ const WEATHER_INDICATOR = 'Services/Weather.svc/REST/GetCityInfo'; const GET_PRIVILEGE = 'Services/Patients.svc/REST/Service_Privilege'; // Wifi Credentials -const WIFI_CREDENTIALS = - "Services/Patients.svc/Hmg_SMS_Get_By_ProjectID_And_PatientID"; +const WIFI_CREDENTIALS = "Services/Patients.svc/Hmg_SMS_Get_By_ProjectID_And_PatientID"; ///Doctor -const GET_MY_DOCTOR = - 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; +const GET_MY_DOCTOR = 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; const GET_DOCTOR_PROFILE = 'Services/Doctors.svc/REST/GetDocProfiles'; -const GET_DOCTOR_RATING_NOTES = - 'Services/Doctors.svc/REST/dr_GetNotesDoctorRating'; -const GET_DOCTOR_RATING_DETAILS = - 'Services/Doctors.svc/REST/dr_GetDoctorRatingDetails'; +const GET_DOCTOR_RATING_NOTES = 'Services/Doctors.svc/REST/dr_GetNotesDoctorRating'; +const GET_DOCTOR_RATING_DETAILS = 'Services/Doctors.svc/REST/dr_GetDoctorRatingDetails'; const GET_DOCTOR_RATING = 'Services/Doctors.svc/REST/dr_GetAvgDoctorRating'; ///Prescriptions const PRESCRIPTIONS = 'Services/Patients.svc/REST/GetPrescriptionApptList'; -const GET_PRESCRIPTIONS_ALL_ORDERS = - 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; -const GET_PRESCRIPTION_REPORT = - 'Services/Patients.svc/REST/INP_GetPrescriptionReport'; -const SEND_PRESCRIPTION_EMAIL = - 'Services/Notifications.svc/REST/SendPrescriptionEmail'; -const GET_PRESCRIPTION_REPORT_ENH = - 'Services/Patients.svc/REST/GetPrescriptionReport_enh'; +const GET_PRESCRIPTIONS_ALL_ORDERS = 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; +const GET_PRESCRIPTION_REPORT = 'Services/Patients.svc/REST/INP_GetPrescriptionReport'; +const SEND_PRESCRIPTION_EMAIL = 'Services/Notifications.svc/REST/SendPrescriptionEmail'; +const GET_PRESCRIPTION_REPORT_ENH = 'Services/Patients.svc/REST/GetPrescriptionReport_enh'; ///Lab Order const GET_Patient_LAB_ORDERS = 'Services/Patients.svc/REST/GetPatientLabOrders'; -const GET_Patient_LAB_SPECIAL_RESULT = - 'Services/Patients.svc/REST/GetPatientLabSpecialResults'; -const SEND_LAB_RESULT_EMAIL = - 'Services/Notifications.svc/REST/SendLabReportEmail'; -const GET_Patient_LAB_RESULT = - 'Services/Patients.svc/REST/GetPatientLabResults'; -const GET_Patient_LAB_ORDERS_RESULT = - 'Services/Patients.svc/REST/GetPatientLabOrdersResults'; +const GET_Patient_LAB_SPECIAL_RESULT = 'Services/Patients.svc/REST/GetPatientLabSpecialResults'; +const SEND_LAB_RESULT_EMAIL = 'Services/Notifications.svc/REST/SendLabReportEmail'; +const GET_Patient_LAB_RESULT = 'Services/Patients.svc/REST/GetPatientLabResults'; +const GET_Patient_LAB_ORDERS_RESULT = 'Services/Patients.svc/REST/GetPatientLabOrdersResults'; /// const GET_PATIENT_ORDERS = 'Services/Patients.svc/REST/GetPatientRadOrders'; -const GET_PATIENT_LAB_ORDERS_BY_APPOINTMENT = - 'Services/Patients.svc/REST/GetPatientLabResultsByAppointmentNo'; +const GET_PATIENT_LAB_ORDERS_BY_APPOINTMENT = 'Services/Patients.svc/REST/GetPatientLabResultsByAppointmentNo'; -const GET_PATIENT_ORDERS_DETAILS = - 'Services/Patients.svc/REST/Rad_UpdatePatientRadOrdersToRead'; +const GET_PATIENT_ORDERS_DETAILS = 'Services/Patients.svc/REST/Rad_UpdatePatientRadOrdersToRead'; const GET_RAD_IMAGE_URL = 'Services/Patients.svc/Rest/GetRadImageURL'; -const SEND_RAD_REPORT_EMAIL = - 'Services/Notifications.svc/REST/SendRadReportEmail'; +const SEND_RAD_REPORT_EMAIL = 'Services/Notifications.svc/REST/SendRadReportEmail'; ///Feedback const SEND_FEEDBACK = 'Services/COCWS.svc/REST/InsertCOCItemInSPList'; @@ -95,32 +79,27 @@ const GET_PATIENT_AppointmentHistory = 'Services' '/Doctors.svc/REST/PateintHasAppoimentHistory'; ///VITAL SIGN -const GET_PATIENT_VITAL_SIGN = - 'Services/Doctors.svc/REST/Doctor_GetPatientVitalSign'; +const GET_PATIENT_VITAL_SIGN = 'Services/Doctors.svc/REST/Doctor_GetPatientVitalSign'; ///Er Nearest -const GET_NEAREST_HOSPITAL = - 'Services/Patients.svc/REST/Patient_GetProjectAvgERWaitingTime'; +const GET_NEAREST_HOSPITAL = 'Services/Patients.svc/REST/Patient_GetProjectAvgERWaitingTime'; ///ED Online -const ER_GET_VISUAL_TRIAGE_QUESTIONS = - "services/Doctors.svc/REST/ER_GetVisualTriageQuestions"; -const ER_SAVE_TRIAGE_INFORMATION = - "services/Doctors.svc/REST/ER_SaveTriageInformation"; +const ER_GET_VISUAL_TRIAGE_QUESTIONS = "services/Doctors.svc/REST/ER_GetVisualTriageQuestions"; +const ER_SAVE_TRIAGE_INFORMATION = "services/Doctors.svc/REST/ER_SaveTriageInformation"; const ER_GetPatientPaymentInformationForERClinic = "services/Doctors.svc/REST/ER_GetPatientPaymentInformationForERClinic"; ///Er Nearest -const GET_AMBULANCE_REQUEST = - 'Services/Patients.svc/REST/PatientER_RRT_GetAllTransportationMethod'; -const GET_PATIENT_ALL_PRES_ORDERS = - 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; -const GET_PICK_UP_REQUEST_BY_PRES_ORDER_ID = - 'Services/Patients.svc/REST/PatientER_RRT_GetPickUpRequestByPresOrderID'; -const UPDATE_PRESS_ORDER = - 'Services/Patients.svc/REST/PatientER_UpdatePresOrder'; -const INSERT_ER_INERT_PRES_ORDER = - 'Services/Patients.svc/REST/PatientER_InsertPresOrder'; +const GET_AMBULANCE_REQUEST = 'Services/Patients.svc/REST/PatientER_RRT_GetAllTransportationMethod'; +const GET_PATIENT_ALL_PRES_ORDERS = 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; +const GET_PICK_UP_REQUEST_BY_PRES_ORDER_ID = 'Services/Patients.svc/REST/PatientER_RRT_GetPickUpRequestByPresOrderID'; +const UPDATE_PRESS_ORDER = 'Services/Patients.svc/REST/PatientER_UpdatePresOrder'; +const INSERT_ER_INERT_PRES_ORDER = 'Services/Patients.svc/REST/PatientER_InsertPresOrder'; + +/// ER RRT +const GET_ALL_RC_TRANSPORTATION = 'rc/api/Transportation/getalltransportation'; +const GET_ALL_RRT_QUESTIONS = 'Services/Patients.svc/REST/PatientER_RRT_GetAllQuestions'; ///FindUs const GET_FINDUS_REQUEST = 'Services/Lists.svc/REST/Get_HMG_Locations'; @@ -129,15 +108,13 @@ const GET_FINDUS_REQUEST = 'Services/Lists.svc/REST/Get_HMG_Locations'; const GET_LIVECHAT_REQUEST = 'Services/Patients.svc/REST/GetPatientICProjects'; ///babyInformation -const GET_BABYINFORMATION_REQUEST = - 'Services/Community.svc/REST/GetBabyByUserID'; +const GET_BABYINFORMATION_REQUEST = 'Services/Community.svc/REST/GetBabyByUserID'; ///Get Baby By User ID const GET_BABY_BY_USER_ID = 'Services/Community.svc/REST/GetBabyByUserID'; ///userInformation -const GET_USERINFORMATION_REQUEST = - 'Services/Community.svc/REST/GetUserInformation_New'; +const GET_USERINFORMATION_REQUEST = 'Services/Community.svc/REST/GetUserInformation_New'; ///Update email const UPDATE_PATENT_EMAIL = 'Services/Patients.svc/REST/UpdatePateintEmail'; @@ -159,29 +136,21 @@ const GET_TABLE_REQUEST = 'Services/Community.svc/REST/CreateVaccinationTable'; const GET_CITIES_REQUEST = 'Services/Lists.svc/REST/GetAllCities'; ///BloodDetails -const GET_BLOOD_REQUEST = - 'services/PatientVarification.svc/REST/BloodDonation_GetBloodGroupDetails'; +const GET_BLOOD_REQUEST = 'services/PatientVarification.svc/REST/BloodDonation_GetBloodGroupDetails'; -const SAVE_BLOOD_REQUEST = - 'Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType'; +const SAVE_BLOOD_REQUEST = 'Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType'; -const GET_BLOOD_AGREEMENT = - 'Services/PatientVarification.svc/REST/CheckUserAgreementForBloodDonation'; -const SAVE_BLOOD_AGREEMENT = - 'Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation'; +const GET_BLOOD_AGREEMENT = 'Services/PatientVarification.svc/REST/CheckUserAgreementForBloodDonation'; +const SAVE_BLOOD_AGREEMENT = 'Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation'; ///Reports const REPORTS = 'Services/Doctors.svc/REST/GetPatientMedicalReportStatusInfo'; -const INSERT_REQUEST_FOR_MEDICAL_REPORT = - 'Services/Doctors.svc/REST/InsertRequestForMedicalReport'; -const SEND_MEDICAL_REPORT_EMAIL = - 'Services/Notifications.svc/REST/SendMedicalReportEmail'; +const INSERT_REQUEST_FOR_MEDICAL_REPORT = 'Services/Doctors.svc/REST/InsertRequestForMedicalReport'; +const SEND_MEDICAL_REPORT_EMAIL = 'Services/Notifications.svc/REST/SendMedicalReportEmail'; ///Rate -const IS_LAST_APPOITMENT_RATED = - 'Services/Doctors.svc/REST/IsLastAppoitmentRated'; -const GET_APPOINTMENT_DETAILS_BY_NO = - 'Services/MobileNotifications.svc/REST/GetAppointmentDetailsByApptNo'; +const IS_LAST_APPOITMENT_RATED = 'Services/Doctors.svc/REST/IsLastAppoitmentRated'; +const GET_APPOINTMENT_DETAILS_BY_NO = 'Services/MobileNotifications.svc/REST/GetAppointmentDetailsByApptNo'; const GET_QR_PARKING = 'Services/SWP.svc/REST/GetQRParkingByID'; @@ -193,8 +162,7 @@ const GET_QR_PARKING = 'Services/SWP.svc/REST/GetQRParkingByID'; const GET_CLINICS_LIST_URL = "Services/lists.svc/REST/GetClinicCentralized"; //URL to get active appointment list -const GET_ACTIVE_APPOINTMENTS_LIST_URL = - "Services/Doctors.svc/Rest/Dr_GetAppointmentActiveNumber"; +const GET_ACTIVE_APPOINTMENTS_LIST_URL = "Services/Doctors.svc/Rest/Dr_GetAppointmentActiveNumber"; //URL to get projects list const GET_PROJECTS_LIST = 'Services/Lists.svc/REST/GetProject'; @@ -203,115 +171,87 @@ const GET_PROJECTS_LIST = 'Services/Lists.svc/REST/GetProject'; const GET_DOCTORS_LIST_URL = "Services/Doctors.svc/REST/SearchDoctorsByTime"; //URL to dental doctors list -const GET_DENTAL_DOCTORS_LIST_URL = - "Services/Doctors.svc/REST/Dental_DoctorChiefComplaintMapping"; +const GET_DENTAL_DOCTORS_LIST_URL = "Services/Doctors.svc/REST/Dental_DoctorChiefComplaintMapping"; //URL to get doctor free slots const GET_DOCTOR_FREE_SLOTS = "Services/Doctors.svc/REST/GetDoctorFreeSlots"; //URL to insert appointment -const INSERT_SPECIFIC_APPOINTMENT = - "Services/Doctors.svc/REST/InsertSpecificAppointment"; +const INSERT_SPECIFIC_APPOINTMENT = "Services/Doctors.svc/REST/InsertSpecificAppointment"; //URL to get patient share -const GET_PATIENT_SHARE = - "Services/Doctors.svc/REST/GetCheckinScreenAppointmentDetailsByAppointmentNO"; +const GET_PATIENT_SHARE = "Services/Doctors.svc/REST/GetCheckinScreenAppointmentDetailsByAppointmentNO"; //URL to get patient appointment history -const GET_PATIENT_APPOINTMENT_HISTORY = - "Services/Doctors.svc/REST/PateintHasAppoimentHistory"; +const GET_PATIENT_APPOINTMENT_HISTORY = "Services/Doctors.svc/REST/PateintHasAppoimentHistory"; -const SEND_REPORT_EYE_EMAIL = - "Services/Notifications.svc/REST/SendGlassesPrescriptionEmail"; +const SEND_REPORT_EYE_EMAIL = "Services/Notifications.svc/REST/SendGlassesPrescriptionEmail"; -const SEND_CONTACT_LENS_PRESCRIPTION_EMAIL = - "Services/Notifications.svc/REST/SendContactLensPrescriptionEmail"; +const SEND_CONTACT_LENS_PRESCRIPTION_EMAIL = "Services/Notifications.svc/REST/SendContactLensPrescriptionEmail"; //URL to get patient appointment curfew history -const GET_PATIENT_APPOINTMENT_CURFEW_HISTORY = - "Services/Doctors.svc/REST/AppoimentHistoryForCurfew"; +const GET_PATIENT_APPOINTMENT_CURFEW_HISTORY = "Services/Doctors.svc/REST/AppoimentHistoryForCurfew"; //URL to confirm appointment -const CONFIRM_APPOINTMENT = - "Services/MobileNotifications.svc/REST/ConfirmAppointment"; +const CONFIRM_APPOINTMENT = "Services/MobileNotifications.svc/REST/ConfirmAppointment"; -const INSERT_VIDA_REQUEST = - "Services/ER_VirtualCall.svc/REST/PatientER_VidaRequestInseart"; +const INSERT_VIDA_REQUEST = "Services/ER_VirtualCall.svc/REST/PatientER_VidaRequestInseart"; //URL to cancel appointment const CANCEL_APPOINTMENT = "Services/Doctors.svc/REST/CancelAppointment"; //URL get appointment QR -const GENERATE_QR_APPOINTMENT = - "Services/Doctors.svc/REST/GenerateQRAppointmentNo"; +const GENERATE_QR_APPOINTMENT = "Services/Doctors.svc/REST/GenerateQRAppointmentNo"; //URL send email appointment QR -const EMAIL_QR_APPOINTMENT = - "Services/Notifications.svc/REST/sendEmailForOnLineCheckin"; +const EMAIL_QR_APPOINTMENT = "Services/Notifications.svc/REST/sendEmailForOnLineCheckin"; //URL check payment status -const CHECK_PAYMENT_STATUS = - "Services/PayFort_Serv.svc/REST/GetRequestStatusByRequestID"; +const CHECK_PAYMENT_STATUS = "Services/PayFort_Serv.svc/REST/GetRequestStatusByRequestID"; //URL create advance payment const CREATE_ADVANCE_PAYMENT = "Services/Doctors.svc/REST/CreateAdvancePayment"; -const HIS_CREATE_ADVANCE_PAYMENT = - "Services/Patients.svc/REST/HIS_CreateAdvancePayment"; +const HIS_CREATE_ADVANCE_PAYMENT = "Services/Patients.svc/REST/HIS_CreateAdvancePayment"; -const ADD_ADVANCE_NUMBER_REQUEST = - 'Services/PayFort_Serv.svc/REST/AddAdvancedNumberRequest'; +const ADD_ADVANCE_NUMBER_REQUEST = 'Services/PayFort_Serv.svc/REST/AddAdvancedNumberRequest'; -const IS_ALLOW_ASK_DOCTOR = - 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; -const GET_CALL_REQUEST_TYPE = - 'Services/Doctors.svc/REST/GetCallRequestType_LOV'; -const ADD_VIDA_REQUEST = - 'Services/ER_VirtualCall.svc/REST/PatientER_VidaRequestInseart'; +const IS_ALLOW_ASK_DOCTOR = 'Services/Doctors.svc/REST/GetPatientDoctorAppointmentResult'; +const GET_CALL_REQUEST_TYPE = 'Services/Doctors.svc/REST/GetCallRequestType_LOV'; +const ADD_VIDA_REQUEST = 'Services/ER_VirtualCall.svc/REST/PatientER_VidaRequestInseart'; const SEND_CALL_REQUEST = 'Services/Doctors.svc/REST/InsertCallInfo'; -const GET_LIVECARE_CLINICS = - 'Services/ER_VirtualCall.svc/REST/PatientER_GetClinics'; +const GET_LIVECARE_CLINICS = 'Services/ER_VirtualCall.svc/REST/PatientER_GetClinics'; -const GET_LIVECARE_SCHEDULE_CLINICS = - 'Services/Doctors.svc/REST/PatientER_GetClinicsHaveSchedule'; +const GET_LIVECARE_SCHEDULE_CLINICS = 'Services/Doctors.svc/REST/PatientER_GetClinicsHaveSchedule'; -const GET_LIVECARE_SCHEDULE_CLINIC_DOCTOR_LIST = - 'Services/Doctors.svc/REST/PatientER_GetDoctorByClinicID'; +const GET_LIVECARE_SCHEDULE_CLINIC_DOCTOR_LIST = 'Services/Doctors.svc/REST/PatientER_GetDoctorByClinicID'; -const GET_LIVECARE_SCHEDULE_DOCTOR_TIME_SLOTS = - 'Services/Doctors.svc/REST/PatientER_GetDoctorFreeSlots'; +const GET_LIVECARE_SCHEDULE_DOCTOR_TIME_SLOTS = 'Services/Doctors.svc/REST/PatientER_GetDoctorFreeSlots'; -const INSERT_LIVECARE_SCHEDULE_APPOINTMENT = - 'Services/Doctors.svc/REST/InsertSpecificAppoitmentForSchedule'; +const INSERT_LIVECARE_SCHEDULE_APPOINTMENT = 'Services/Doctors.svc/REST/InsertSpecificAppoitmentForSchedule'; const GET_PATIENT_SHARE_LIVECARE = "Services/Doctors.svc/REST/GetCheckinScreenAppointmentDetailsByAppointmentNOForLiveCare"; -const GET_LIVECARE_CLINIC_TIMING = - 'Services/ER_VirtualCall.svc/REST/PatientER_GetClinicsServiceTimingsSchedule'; +const GET_LIVECARE_CLINIC_TIMING = 'Services/ER_VirtualCall.svc/REST/PatientER_GetClinicsServiceTimingsSchedule'; -const GET_ER_APPOINTMENT_FEES = - 'Services/DoctorApplication.svc/REST/GetERAppointmentFees'; +const GET_ER_APPOINTMENT_FEES = 'Services/DoctorApplication.svc/REST/GetERAppointmentFees'; const GET_ER_APPOINTMENT_TIME = 'Services/ER_VirtualCall.svc/REST/GetRestTime'; -const ADD_NEW_CALL_FOR_PATIENT_ER = - 'Services/DoctorApplication.svc/REST/NewCallForPatientER'; +const ADD_NEW_CALL_FOR_PATIENT_ER = 'Services/DoctorApplication.svc/REST/NewCallForPatientER'; -const GET_LIVECARE_HISTORY = - 'Services/ER_VirtualCall.svc/REST/GetPatientErVirtualHistory'; -const CANCEL_LIVECARE_REQUEST = - 'Services/ER_VirtualCall.svc/REST/DeleteErRequest'; -const SEND_LIVECARE_INVOICE_EMAIL = - 'Services/Notifications.svc/REST/SendInvoiceForLiveCare'; +const GET_LIVECARE_HISTORY = 'Services/ER_VirtualCall.svc/REST/GetPatientErVirtualHistory'; +const CANCEL_LIVECARE_REQUEST = 'Services/ER_VirtualCall.svc/REST/DeleteErRequest'; +const SEND_LIVECARE_INVOICE_EMAIL = 'Services/Notifications.svc/REST/SendInvoiceForLiveCare'; const GET_USER_TERMS = 'Services/Patients.svc/REST/GetUserTermsAndConditions'; -const UPDATE_HEALTH_TERMS = - 'services/Patients.svc/REST/UpdatePateintHealthSummaryReport'; +const UPDATE_HEALTH_TERMS = 'services/Patients.svc/REST/UpdatePateintHealthSummaryReport'; + +const GET_PATIENT_HEALTH_STATS = 'Services/Patients.svc/REST/Med_GetTransactionsSts'; -const GET_PATIENT_HEALTH_STATS = - 'Services/Patients.svc/REST/Med_GetTransactionsSts'; +const SEND_CHECK_IN_NFC_REQUEST = 'Services/Patients.svc/REST/Patient_CheckAppointmentValidation_ForNFC'; //URL to get medicine and pharmacies list const CHANNEL = 3; @@ -332,21 +272,16 @@ var DeviceTypeID = Platform.isIOS ? 1 : 2; const LANGUAGE_ID = 2; const GET_PHARMCY_ITEMS = "Services/Lists.svc/REST/GetPharmcyItems_Region"; const GET_PHARMACY_LIST = "Services/Patients.svc/REST/GetPharmcyList"; -const GET_PAtIENTS_INSURANCE = - "Services/Patients.svc/REST/Get_PatientInsuranceDetails"; -const GET_PAtIENTS_INSURANCE_UPDATED = - "Services/Patients.svc/REST/PatientER_GetPatientInsuranceCardUpdateHistory"; +const GET_PAtIENTS_INSURANCE = "Services/Patients.svc/REST/Get_PatientInsuranceDetails"; +const GET_PAtIENTS_INSURANCE_UPDATED = "Services/Patients.svc/REST/PatientER_GetPatientInsuranceCardUpdateHistory"; const INSURANCE_DETAILS = "Services/Patients.svc/REST/Get_InsuranceCheckList"; -const GET_PATIENT_INSURANCE_DETAILS = - "Services/Patients.svc/REST/PatientER_GetPatientInsuranceDetails"; -const UPLOAD_INSURANCE_CARD = - 'Services/Patients.svc/REST/PatientER_PatientInfoForInsuranceCardUpdate'; +const GET_PATIENT_INSURANCE_DETAILS = "Services/Patients.svc/REST/PatientER_GetPatientInsuranceDetails"; +const UPLOAD_INSURANCE_CARD = 'Services/Patients.svc/REST/PatientER_PatientInfoForInsuranceCardUpdate'; const GET_VACCINES = "Services/Patients.svc/REST/GetDoneVaccinesByPatientID"; const GET_VACCINES_EMAIL = "Services/Notifications.svc/REST/SendVaccinesEmail"; -const GET_PAtIENTS_INSURANCE_APPROVALS = - "Services/Patients.svc/REST/GetApprovalStatus"; +const GET_PAtIENTS_INSURANCE_APPROVALS = "Services/Patients.svc/REST/GetApprovalStatus"; const SEARCH_BOT = 'HabibiChatBotApi/BotInterface/GetVoiceCommandResponse'; const GET_VACCINATIONS_ITEMS = "/Services/ERP.svc/REST/GET_VACCINATIONS_ITEMS"; @@ -356,81 +291,57 @@ const GET_PATIENT_SICK_LEAVE = 'Services/Patients.svc/REST/GetPatientSickLeave'; const SendSickLeaveEmail = 'Services/Notifications.svc/REST/SendSickLeaveEmail'; -const GET_PATIENT_AdVANCE_BALANCE_AMOUNT = - 'Services/Patients.svc/REST/GetPatientAdvanceBalanceAmount'; -const GET_PATIENT_INFO_BY_ID = - 'Services/Doctors.svc/REST/GetPatientInfoByPatientID'; +const GET_PATIENT_AdVANCE_BALANCE_AMOUNT = 'Services/Patients.svc/REST/GetPatientAdvanceBalanceAmount'; +const GET_PATIENT_INFO_BY_ID = 'Services/Doctors.svc/REST/GetPatientInfoByPatientID'; const GET_PATIENT_INFO_BY_ID_AND_MOBILE_NUMBER = 'Services/Patients.svc/REST/AP_GetPatientInfoByPatientIDandMobileNumber'; -const SEND_ACTIVATION_CODE_FOR_ADVANCE_PAYMENT = - 'Services/Authentication.svc/REST/SendActivationCodeForAdvancePayment'; +const SEND_ACTIVATION_CODE_FOR_ADVANCE_PAYMENT = 'Services/Authentication.svc/REST/SendActivationCodeForAdvancePayment'; const CHECK_ACTIVATION_CODE_FOR_ADVANCE_PAYMENT = 'Services/Authentication.svc/REST/CheckActivationCodeForAdvancePayment'; -const GET_COVID_DRIVETHRU_PROJECT_LIST = - 'Services/Doctors.svc/REST/COVID19_ProjectDriveThroughTestingCenter'; +const GET_COVID_DRIVETHRU_PROJECT_LIST = 'Services/Doctors.svc/REST/COVID19_ProjectDriveThroughTestingCenter'; + +const GET_COVID_DRIVETHRU_PAYMENT_INFO = 'Services/Doctors.svc/REST/COVID19_GetPatientPaymentInormation'; -const GET_COVID_DRIVETHRU_PAYMENT_INFO = - 'Services/Doctors.svc/REST/COVID19_GetPatientPaymentInormation'; +const GET_COVID_DRIVETHRU_FREE_SLOTS = 'Services/Doctors.svc/REST/COVID19_GetFreeSlots'; -const GET_COVID_DRIVETHRU_FREE_SLOTS = - 'Services/Doctors.svc/REST/COVID19_GetFreeSlots'; +const GET_COVID_DRIVETHRU_PROCEDURES_LIST = + 'Services/Doctors.svc/REST/COVID19_GetTestProcedures'; ///Smartwatch Integration Services -const GET_PATIENT_LAST_RECORD = - 'Services/Patients.svc/REST/Med_GetPatientLastRecord'; +const GET_PATIENT_LAST_RECORD = 'Services/Patients.svc/REST/Med_GetPatientLastRecord'; ///My Trackers -const GET_DIABETIC_RESULT_AVERAGE = - 'Services/Patients.svc/REST/Patient_GetDiabeticResultAverage'; -const GET_DIABTEC_RESULT = - 'Services/Patients.svc/REST/Patient_GetDiabtecResults'; -const ADD_DIABTEC_RESULT = - 'Services/Patients.svc/REST/Patient_AddDiabtecResult'; - -const GET_BLOOD_PRESSURE_RESULT_AVERAGE = - 'Services/Patients.svc/REST/Patient_GetBloodPressureResultAverage'; -const GET_BLOOD_PRESSURE_RESULT = - 'Services/Patients.svc/REST/Patient_GetBloodPressureResult'; -const ADD_BLOOD_PRESSURE_RESULT = - 'Services/Patients.svc/REST/Patient_AddBloodPressureResult'; - -const GET_WEIGHT_PRESSURE_RESULT_AVERAGE = - 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResultAverage'; -const GET_WEIGHT_PRESSURE_RESULT = - 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResult'; -const ADD_WEIGHT_PRESSURE_RESULT = - 'Services/Patients.svc/REST/Patient_AddWeightMeasurementResult'; +const GET_DIABETIC_RESULT_AVERAGE = 'Services/Patients.svc/REST/Patient_GetDiabeticResultAverage'; +const GET_DIABTEC_RESULT = 'Services/Patients.svc/REST/Patient_GetDiabtecResults'; +const ADD_DIABTEC_RESULT = 'Services/Patients.svc/REST/Patient_AddDiabtecResult'; + +const GET_BLOOD_PRESSURE_RESULT_AVERAGE = 'Services/Patients.svc/REST/Patient_GetBloodPressureResultAverage'; +const GET_BLOOD_PRESSURE_RESULT = 'Services/Patients.svc/REST/Patient_GetBloodPressureResult'; +const ADD_BLOOD_PRESSURE_RESULT = 'Services/Patients.svc/REST/Patient_AddBloodPressureResult'; + +const GET_WEIGHT_PRESSURE_RESULT_AVERAGE = 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResultAverage'; +const GET_WEIGHT_PRESSURE_RESULT = 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResult'; +const ADD_WEIGHT_PRESSURE_RESULT = 'Services/Patients.svc/REST/Patient_AddWeightMeasurementResult'; const ADD_ACTIVE_PRESCRIPTIONS_REPORT_BY_PATIENT_ID = 'Services/Patients.svc/Rest/GetActivePrescriptionReportByPatientID'; -const GET_CALL_INFO_HOURS_RESULT = - 'Services/Doctors.svc/REST/GetCallInfoHoursResult'; -const GET_CALL_REQUEST_TYPE_LOV = - 'Services/Doctors.svc/REST/GetCallRequestType_LOV'; - -const UPDATE_DIABETIC_RESULT = - 'Services/Patients.svc/REST/Patient_UpdateDiabeticResult'; - -const SEND_AVERAGE_BLOOD_SUGAR_REPORT = - 'Services/Notifications.svc/REST/SendAverageBloodSugarReport'; -const DEACTIVATE_DIABETIC_STATUS = - 'services/Patients.svc/REST/Patient_DeactivateDiabeticStatus'; -const DEACTIVATE_BLOOD_PRESSURES_STATUS = - 'services/Patients.svc/REST/Patient_DeactivateBloodPressureStatus'; - -const UPDATE_BLOOD_PRESSURE_RESULT = - 'Services/Patients.svc/REST/Patient_UpdateBloodPressureResult'; -const SEND_AVERAGE_BLOOD_WEIGHT_REPORT = - 'Services/Notifications.svc/REST/SendAverageBodyWeightReport'; -const SEND_AVERAGE_BLOOD_PRESSURE_REPORT = - 'Services/Notifications.svc/REST/SendAverageBloodPressureReport'; - -const UPDATE_WEIGHT_PRESSURE_RESULT = - 'Services/Patients.svc/REST/Patient_UpdateWeightMeasurementResult'; -const DEACTIVATE_WEIGHT_PRESSURE_RESULT = - 'services/Patients.svc/REST/Patient_DeactivateWeightMeasurementStatus'; +const GET_CALL_INFO_HOURS_RESULT = 'Services/Doctors.svc/REST/GetCallInfoHoursResult'; +const GET_CALL_REQUEST_TYPE_LOV = 'Services/Doctors.svc/REST/GetCallRequestType_LOV'; + +const UPDATE_DIABETIC_RESULT = 'Services/Patients.svc/REST/Patient_UpdateDiabeticResult'; + +const SEND_AVERAGE_BLOOD_SUGAR_REPORT = 'Services/Notifications.svc/REST/SendAverageBloodSugarReport'; +const DEACTIVATE_DIABETIC_STATUS = 'services/Patients.svc/REST/Patient_DeactivateDiabeticStatus'; +const DEACTIVATE_BLOOD_PRESSURES_STATUS = 'services/Patients.svc/REST/Patient_DeactivateBloodPressureStatus'; + +const UPDATE_BLOOD_PRESSURE_RESULT = 'Services/Patients.svc/REST/Patient_UpdateBloodPressureResult'; +const SEND_AVERAGE_BLOOD_WEIGHT_REPORT = 'Services/Notifications.svc/REST/SendAverageBodyWeightReport'; +const SEND_AVERAGE_BLOOD_PRESSURE_REPORT = 'Services/Notifications.svc/REST/SendAverageBloodPressureReport'; + +const UPDATE_WEIGHT_PRESSURE_RESULT = 'Services/Patients.svc/REST/Patient_UpdateWeightMeasurementResult'; +const DEACTIVATE_WEIGHT_PRESSURE_RESULT = 'services/Patients.svc/REST/Patient_DeactivateWeightMeasurementStatus'; const GET_DOCTOR_RESPONSE = 'Services/Patients.svc/REST/GetDoctorResponse'; const UPDATE_READ_STATUS = 'Services/Patients.svc/REST/UpdateReadStatus'; const INSERT_CALL_INFO = 'Services/Doctors.svc/REST/InsertCallInfo'; @@ -438,39 +349,31 @@ const INSERT_CALL_INFO = 'Services/Doctors.svc/REST/InsertCallInfo'; const GET_PATIENT_ALLERGIES = 'Services/Patients.svc/REST/GetPatientAllergies'; // H2O -const H2O_GET_USER_PROGRESS = - "Services/H2ORemainder.svc/REST/H2O_GetUserProgress"; -const H2O_INSERT_USER_ACTIVITY = - "Services/H2ORemainder.svc/REST/H2O_InsertUserActivity"; -const H2O_GET_USER_DETAIL = - "Services/H2ORemainder.svc/REST/H2O_GetUserDetails_New"; -const H2O_UPDATE_USER_DETAIL = - "Services/H2ORemainder.svc/REST/H2O_UpdateUserDetails_New"; -const H2O_UNDO_USER_ACTIVITY = - "Services/H2ORemainder.svc/REST/H2o_UndoUserActivity"; +const H2O_GET_USER_PROGRESS = "Services/H2ORemainder.svc/REST/H2O_GetUserProgress"; +const H2O_INSERT_USER_ACTIVITY = "Services/H2ORemainder.svc/REST/H2O_InsertUserActivity"; +const H2O_GET_USER_DETAIL = "Services/H2ORemainder.svc/REST/H2O_GetUserDetails_New"; +const H2O_UPDATE_USER_DETAIL = "Services/H2ORemainder.svc/REST/H2O_UpdateUserDetails_New"; +const H2O_UNDO_USER_ACTIVITY = "Services/H2ORemainder.svc/REST/H2o_UndoUserActivity"; //E_Referral Services -const GET_ALL_RELATIONSHIP_TYPES = - "Services/Patients.svc/REST/GetAllRelationshipTypes"; -const SEND_ACTIVATION_CODE_FOR_E_REFERRAL = - 'Services/Authentication.svc/REST/SendActivationCodeForEReferral'; -const CHECK_ACTIVATION_CODE_FOR_E_REFERRAL = - 'Services/Authentication.svc/REST/CheckActivationCodeForEReferral'; +const GET_ALL_RELATIONSHIP_TYPES = "Services/Patients.svc/REST/GetAllRelationshipTypes"; +const SEND_ACTIVATION_CODE_FOR_E_REFERRAL = 'Services/Authentication.svc/REST/SendActivationCodeForEReferral'; +const CHECK_ACTIVATION_CODE_FOR_E_REFERRAL = 'Services/Authentication.svc/REST/CheckActivationCodeForEReferral'; const GET_ALL_CITIES = 'services/Lists.svc/rest/GetAllCities'; const CREATE_E_REFERRAL = "Services/Patients.svc/REST/CreateEReferral"; const GET_E_REFERRALS = "Services/Patients.svc/REST/GetEReferrals"; // Encillary Orders -const GET_ANCILLARY_ORDERS = - 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderList'; +const GET_ANCILLARY_ORDERS = 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderList'; -const GET_ANCILLARY_ORDERS_DETAILS = - 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderProcList'; +const GET_ANCILLARY_ORDERS_DETAILS = 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderProcList'; //Pharmacy wishlist // const GET_WISHLIST = "http://swd-pharapp-01:7200/api/shopping_cart_items/"; +const GET_DOCTOR_LIST_BY_TIME = "Services/Doctors.svc/REST/SearchDoctorsByTime"; + // pharmacy const PHARMACY_AUTORZIE_CUSTOMER = "AutorizeCustomer"; const PHARMACY_VERIFY_CUSTOMER = "VerifyCustomer"; @@ -496,50 +399,34 @@ const GET_SHIPPING_OPTIONS = "get_shipping_option/"; const DELETE_SHOPPING_CART = "delete_shopping_cart_items/"; const DELETE_SHOPPING_CART_ALL = "delete_shopping_cart_item_by_customer/"; const ORDER_SHOPPING_CART = "orders"; -const GET_LACUM_ACCOUNT_INFORMATION = - "Services/Patients.svc/REST/GetLakumAccountInformation"; -const GET_LACUM_GROUP_INFORMATION = - "Services/Patients.svc/REST/GetlakumInQueryInfoGrouping"; -const LACUM_ACCOUNT_ACTIVATE = - "Services/Patients.svc/REST/LakumAccountActivation"; -const LACUM_ACCOUNT_DEACTIVATE = - "Services/Patients.svc/REST/LakumAccountDeactivation"; -const CREATE_LAKUM_ACCOUNT = - "Services/Patients.svc/REST/PHR_CreateLakumAccount"; -const TRANSFER_YAHALA_LOYALITY_POINTS = - "Services/Patients.svc/REST/TransferYaHalaLoyaltyPoints"; -const LAKUM_GET_USER_TERMS_AND_CONDITIONS = - "Services/ERP.svc/REST/GetUserTermsAndConditionsForEPharmcy"; +const GET_LACUM_ACCOUNT_INFORMATION = "Services/Patients.svc/REST/GetLakumAccountInformation"; +const GET_LACUM_GROUP_INFORMATION = "Services/Patients.svc/REST/GetlakumInQueryInfoGrouping"; +const LACUM_ACCOUNT_ACTIVATE = "Services/Patients.svc/REST/LakumAccountActivation"; +const LACUM_ACCOUNT_DEACTIVATE = "Services/Patients.svc/REST/LakumAccountDeactivation"; +const CREATE_LAKUM_ACCOUNT = "Services/Patients.svc/REST/PHR_CreateLakumAccount"; +const TRANSFER_YAHALA_LOYALITY_POINTS = "Services/Patients.svc/REST/TransferYaHalaLoyaltyPoints"; +const LAKUM_GET_USER_TERMS_AND_CONDITIONS = "Services/ERP.svc/REST/GetUserTermsAndConditionsForEPharmcy"; const PRESCRIPTION = 'Services/Patients.svc/REST/GetPrescriptionApptList'; const GET_RECOMMENDED_PRODUCT = 'alsoProduct/'; const GET_MOST_VIEWED_PRODUCTS = "mostview?"; const GET_NEW_PRODUCTS = "newproducts?"; // Home Health Care -const HHC_GET_ALL_SERVICES = - "Services/Patients.svc/REST/PatientER_HHC_GetAllServices"; -const HHC_GET_ALL_CMC_SERVICES = - "Services/Patients.svc/REST/PatientER_CMC_GetAllServices"; -const PATIENT_ER_UPDATE_PRES_ORDER = - "Services/Patients.svc/REST/PatientER_UpdatePresOrder"; -const GET_ORDER_DETAIL_BY_ID = - "Services/Patients.svc/REST/PatientER_HHC_GetTransactionsForOrder"; -const GET_CMC_ORDER_DETAIL_BY_ID = - "Services/Patients.svc/REST/PatientER_CMC_GetTransactionsForOrder"; +const HHC_GET_ALL_SERVICES = "Services/Patients.svc/REST/PatientER_HHC_GetAllServices"; +const HHC_GET_ALL_CMC_SERVICES = "Services/Patients.svc/REST/PatientER_CMC_GetAllServices"; +const PATIENT_ER_UPDATE_PRES_ORDER = "Services/Patients.svc/REST/PatientER_UpdatePresOrder"; +const GET_ORDER_DETAIL_BY_ID = "Services/Patients.svc/REST/PatientER_HHC_GetTransactionsForOrder"; +const GET_CMC_ORDER_DETAIL_BY_ID = "Services/Patients.svc/REST/PatientER_CMC_GetTransactionsForOrder"; const GET_CHECK_UP_ITEMS = "Services/Patients.svc/REST/GetCheckUpItems"; const PUSH_NOTIFICATION_GET_ALL_NOTIFICATIONS = 'Services/MobileNotifications.svc/REST/PushNotification_GetAllNotifications'; const PUSH_NOTIFICATION_SET_MESSAGES_FROM_POOL_AS_READ = 'Services/MobileNotifications.svc/REST/PushNotification_SetMessagesFromPoolAsRead'; -const GET_PATIENT_ALL_PRES_ORD = - 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; -const PATIENT_ER_INSERT_PRES_ORDER = - 'Services/Patients.svc/REST/PatientER_InsertPresOrder'; +const GET_PATIENT_ALL_PRES_ORD = 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; +const PATIENT_ER_INSERT_PRES_ORDER = 'Services/Patients.svc/REST/PatientER_InsertPresOrder'; const PHARMACY_MAKE_REVIEW = 'epharmacy/api/insertreviews'; -const BLOOD_DONATION_REGISTER_BLOOD_TYPE = - 'Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType'; -const ADD_USER_AGREEMENT_FOR_BLOOD_DONATION = - 'Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation'; +const BLOOD_DONATION_REGISTER_BLOOD_TYPE = 'Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType'; +const ADD_USER_AGREEMENT_FOR_BLOOD_DONATION = 'Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation'; //Pharmacy wishlist const GET_WISHLIST = "shopping_cart_items/"; @@ -572,8 +459,7 @@ const GET_SUB_PRODUCTS = 'products?categoryid='; const GET_FINAL_PRODUCTS = 'products?fields=id,reviews,discount_ids,name,namen,localized_names,display_order,short_description,full_description,full_descriptionn,sku,order_minimum_quantity,order_maximum_quantity,price,old_price,images,is_rx,rx_message,rx_messagen,discount_name,discount_namen,approved_rating_sum,approved_total_reviews,allow_back_in_stock_subscriptions,stock_quantity,stock_availability,stock_availabilityn,discount_percentage&CategoryId='; const GET_CLINIC_CATEGORY = 'Services/Doctors.svc/REST/DP_GetClinicCategory'; -const GET_DISEASE_BY_CLINIC_ID = - 'Services/Doctors.svc/REST/DP_GetDiseasesByClinicID'; +const GET_DISEASE_BY_CLINIC_ID = 'Services/Doctors.svc/REST/DP_GetDiseasesByClinicID'; const SEARCH_DOCTOR_BY_TIME = 'Services/Doctors.svc/REST/SearchDoctorsByTime'; const TIMER_MIN = 10; @@ -589,6 +475,8 @@ const SCAN_QR_CODE = 'productbysku/'; const FILTERED_PRODUCTS = 'products?categoryids='; +const GET_DOCTOR_LIST_CALCULATION = "Services/Doctors.svc/REST/GetCallculationDoctors"; + class AppGlobal { static var context; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 8c044739..46a9ff4f 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -97,30 +97,29 @@ const Map localizedValues = { 'payment': {'en': 'Payment', 'ar': 'الدفع'}, 'cancel-nocaps': {'en': 'Cancel', 'ar': 'الغاء'}, 'set-reminder': {'en': 'Set Reminder', 'ar': 'تعيين تذكير'}, - + "national-id-number": {"en": "National ID Number", "ar": "رقم الهوية الوطنيةالاقامة"}, + "medical-file-number": {"en": "Medical File Number", "ar": "رقم الملف الطبي"}, 'login': {'en': 'Login', 'ar': 'تسجيل الدخول'}, 'loginregister': {'en': 'Login / Register', 'ar': 'تسجيل الدخول'}, 'poweredBy': {'en': 'Powered By', 'ar': 'مشغل بواسطة'}, "welcome": {"en": "Welcome", "ar": "مرحبا"}, "welcome-to": {"en": "Welcome to", "ar": "مرحبا بك في"}, - "dr-sulaiman-text": {"en": "Dr. Sulaiman Al Habib", "ar": "د. سليمان الحبيب"}, "patient-app": {"en": "Patient App", "ar": "تطبيق المريض"}, "welcome_text": {"en": "Dr. Sulaiman Al Habib Mobile Application", "ar": "الدكتور سليمان الحبيب لتطبيقات الهاتف المتحرك"}, + "dr-sulaiman-text": {"en": "Dr. Sulaiman Al Habib", "ar": "د. سليمان الحبيب"}, 'welcome_text2': {'en': 'Have you visited AlHabib Medical Group before? ', 'ar': 'هل قمت بزيارة مجموعة الحبيب الطبية من قبل؟'}, 'yes': {'en': 'Yes', 'ar': 'نعم'}, 'no': {'en': 'No', 'ar': 'لا'}, "logintyperadio": {"en": "Choose from below options to login to your medical file.", "ar": "اختر من الخيارات أدناه لتسجيل الدخول إلى ملفك الطبي."}, "registernow": {"en": "Register Now", "ar": "تسجيل الان"}, "nationalID": {"en": "Enter the Identification Number", "ar": "أدخل رقم الهوية الوطنية او الاقامة"}, - "national-id-number": {"en": "National ID Number", "ar": "رقم الهوية الوطنيةالاقامة"}, - "medical-file-number": {"en": "Medical File Number", "ar": "رقم الملف الطبي"}, "national-id": {"en": "National ID", "ar": "رقم الهوية"}, "fileNo": {"en": "File Number", "ar": "رقم الملف"}, "fileno": {"en": "File No", "ar": "رقم الملف"}, "forgotFileNo": {"en": "Forgot file Number?", "ar": "نسيت رقم الملف الطبي؟"}, "forgotFileNoTitle": {"en": "Forgot medical file", "ar": "نسيت رقم الملف"}, - "enter-national-id": {"en": "Please Enter Mobile Number and National ID Number", "ar": "الرجاء إدخال رقم الجوال ورقم الهوية"}, + "enter-national-id": {"en": "Please enter mobile number and identification number", "ar": "الرجاء إدخال رقم الجوال ورقم الهوية"}, "profile-info": {"en": "Please enter profile information", "ar": "الرجاء إدخال معلومات الملف الشخصي"}, "submit": {"en": "Submit", "ar": "ارسال"}, "forgot-desc": {"en": "Enter the mobile number to receive the Medical file Number via SMS", "ar": "أدخل رقم الجوال المسجل لاستلام رقم الملف عن طريق الرسائل النصية"}, @@ -133,10 +132,8 @@ const Map localizedValues = { "verify-with-faceid": {"en": "Face ID", "ar": "معرف الوجه"}, "verify-with-sms": {"en": "SMS", "ar": "الرسائل القصيرة"}, "verify-with-whatsapp": {"en": "Whatsapp", "ar": " الواتس اب"}, - "verify-through": {"en": "Verify Through", "ar": " تحقق من خلال"}, - "last-login": {"en": "Last Login Details:", "ar": "آخر تسجيل دخول"}, - "last-login-with": {"en": "Verification Type:", "ar": "نوع التحقق:"}, - "please-verify": {"en": "Please Verify", "ar": "ارجوك تحقق:"}, + "last-login": {"en": "LAST LOGIN AT:", "ar": "آخر تسجيل دخول"}, + "last-login-with": {"en": "VERIFICATION TYPE:", "ar": "نوع التحقق:"}, "verify-fingerprint": { "en": "To activate the fingerprint login service, please verify data by using one of the following options.", "ar": "لتفعيل خدمة الدخول بالبصمة، يرجى اختيار احدى القنوات التالية للتحقق من البيانات" @@ -184,7 +181,7 @@ const Map localizedValues = { 'askDocNotAllowed': {'en': 'This service will be available for last 15 days doctor Visit only', 'ar': 'هذه الخدمة متاحة للزيارات خلال اخر 15 يوم فقط'}, "more-verify": {"en": "More Verification Options", "ar": "المزيد من خيارات التحقق"}, "welcome-back": {"en": "Welcome back!", "ar": "مرحبا بعودتك!"}, - "account-info": {"en": "Would you like to login with current Username?", "ar": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟"}, + "account-info": {"en": "Would you like to login with current username?", "ar": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟"}, "another-acc": {"en": "Use Another Account", "ar": "استخدم حسابا آخر"}, "next": {"en": "Next", "ar": 'التالى'}, "first-name": {"en": "First Name", "ar": "الاسم الأول"}, @@ -281,6 +278,13 @@ const Map localizedValues = { "ar": " خدمة المواقف، تتيح هذه الخدمة للمستخدم معلومات عن موقف السيارة ليسهل عليه العودة لها لاحقاً ، 1- بالضغط على زر(قراءة الكود) تستطيع حفظ البيانات الخاصة بالموقف. 2-بالضغط على زر(عرض موقف سيارتي) يعرض لك موقع السيارة في خرائط قوقل. 3- لإعادة قراءة موقف آخرعن طريق الضغط على زر(مسح بيانات الموقف). " }, + "parkingDescription": { + "en": + "Parking service is for you to scan the car location so you can find it easy on you way out. click on (scan parking) button to save the parking location, then (show my park) button will appear to show you the way for the parking. if you want to rescan parking QR just click on (Clear My Data).", + "ar": + "خدمة المواقف، تتيح هذه الخدمة للمستخدم معلومات عن موقف السيارة ليسهل عليه العودة لها لاحقاً ، 1- بالضغط على زر(قراءة الكود) تستطيع حفظ البيانات الخاصة بالموقف. 2-بالضغط على زر(عرض موقف سيارتي) يعرض لك موقع السيارة في خرائط قوقل. 3- لإعادة قراءة موقف آخرعن طريق الضغط على زر(مسح بيانات الموقف)." + }, + "checkinOption": {"en": "Check-In Options", "ar": "تحقق في الخيارات"}, "readBarcode": {"en": "Read Barcode", "ar": "قراءة الكود"}, "showMyPark": {"en": "Show My Park", "ar": "عرض بارك"}, "clearMyData": {"en": "clear My Data", "ar": "امسح البيانات"}, @@ -746,7 +750,7 @@ const Map localizedValues = { "HealthTipsBasedOnCurrentWeather": {"en": "Health Tips Based On Current Weather", 'ar': ' نصائح صحية على أساس الطقس الحالي '}, "MoreDetails": {"en": "More details", "ar": " المزيد من التفاصيل "}, "SendCopy": {"en": "Send Copy", "ar": "ارسال نسخة"}, - "ResendOrder": {"en": "Resend order & deliver", "ar": "إعادة طلب و توصيل"}, + "ResendOrder": {"en": "Refill Order & Delivery", "ar": "إعادة طلب و توصيل"}, "Ports": {"en": "Ports", "ar": "المنافذ"}, "Way": {"en": "Way", "ar": "الطزيقة"}, "Average": {"en": "Average", "ar": "المعدل"}, @@ -780,6 +784,7 @@ const Map localizedValues = { "complain-without-appo": {"en": "Complaint without appointment", "ar": "شكوى بدون موعد"}, "question": {"en": "Question", "ar": "سؤال"}, "message-type": {"en": "Message Type", "ar": "نوع الرسالة"}, + "feedback-type": {"en": "Feedback Type", "ar": "نوع الرسالة"}, "compliment": {"en": "compliment", "ar": "ثناء"}, "suggestion": {"en": "Suggestion", "ar": "إقتراح"}, "your-feedback": {"en": "Your feedback was sent", "ar": "لقد تم ارسال اقراحك شكرا لك"}, @@ -791,6 +796,10 @@ const Map localizedValues = { "YouCanFind": {"en": "You Can Find ", "ar": "باستطاعتك العثور على "}, "ItemInSearch": {"en": " Item In Search", "ar": " عنصر في البحث "}, "blood-donation": {"en": "Blood Donation", "ar": "التبرع بالدم"}, + "blood-donation-info": { + "en": "Through this service, you can register your name as a blood donor where the blood bank in the Habib Medical Group will communicate you in case of need for blood type.", + "ar": "عن طريق هذه الخدمة تستطيع تسجيل اسمك كمتبرع بالدم حيث سيتم التواصل معك عن طريق بنك الدم في مجموعة الحبيب الطبية في حال الحاجة الى فصيلة الدم ." + }, "blood-instruction": {"en": "Enter the required information, In order to register for Blood Donation Service", "ar": "ادخل المعلومات المطلوبة للتسجيل بخدمة التبرع بالدم"}, "view-terms": {"en": "To view the terms and conditions", "ar": "عرض الشروط والأحكام"}, "wantConnectHmgNetwork": { @@ -842,6 +851,7 @@ const Map localizedValues = { }, "RRT-transport-heading": {"en": "Select Transportation Method", "ar": "حدد طريقة النقل"}, "RRT-direction-heading": {"en": "Select Direction", "ar": "حدد الاتجاه"}, + "RRT-way-heading": {"en": "Select Way", "ar": "حدد الطريق"}, "to-hospital": {"en": "To Hospital", "ar": "الى المستشفى"}, "from-hospital": {"en": "From Hospital", "ar": "من المستشفى"}, "one-direc": {"en": "One Way", "ar": "ذهاب"}, @@ -863,6 +873,20 @@ const Map localizedValues = { "stretcher": {"en": "Stretcher", "ar": "نقالة"}, "none": {"en": "None", "ar": "لا شيء"}, "RRT-Summary": {"en": "Summary", "ar": "ملخص الطلب"}, + "AmountBeforeTax": {"en": "Amount Before Tax:", "ar": "Amount Before Tax:"}, + "ApproximateServiceFee": {"en": "Approximate Service Fee", "ar": "Approximate Service Fee"}, + "TaxAmount": {"en": "Tax Amount:", "ar": "Tax Amount:"}, + "TotalAmountPayable": {"en": "Total Amount Payable:", "ar": "Total Amount Payable:"}, + "iAcceptTermsConditions": {"en": "I Accept the Terms And Conditions", "ar": "You can pay by the following options:"}, + "YouCanPayByTheFollowingOptions": {"en": "You can pay by the following options:", "ar": "I Accept the Terms And Conditions"}, + "RRTDDetails": { + "en": + "The RRT service provides medical services urgent and stable cases, not life-threatening situation or extremities and the service includes providing medical care from a copmplete medical team at home", + "ar": + "The RRT service provides medical services urgent and stable cases, not life-threatening situation or extremities and the service includes providing medical care from a copmplete medical team at home" + }, + "Rapid-Response-Team": {"en": "Rapid Response Team", "ar": "فريق الاستجابة السريع"}, + "rrtService": {"en": "RRT Service", "ar": "خدمة RRT"}, "bill-amount": {"en": "Bill Amount", "ar": "مبلغ الفاتورة"}, "transport-method": {"en": "Transportation Method", "ar": "طريقة النقل"}, "directions": {"en": "Directions", "ar": "الاتجاهات"}, @@ -1047,7 +1071,7 @@ const Map localizedValues = { "updated-email": {"en": "Updated email successfully", "ar": "تم تحديث البريد الالكتروني"}, "view-list-children": {"en": "View List of Children", "ar": "عرض قائمة الأطفال"}, - "covidTest": {"en": "COVID TEST", "ar": "فحص كورونا"}, + "covidTest": {"en": "COVID-19 TEST", "ar": "فحص كورونا"}, "driveThru": {"en": "Drive-Thru", "ar": "من السيارة"}, "trackDeliveryDriver": {"en": "Track Delivery Driver", "ar": "trackDeliveryDriver"}, @@ -1210,7 +1234,7 @@ const Map localizedValues = { "drinking": {"en": "Drinkning", "ar": "الشرب"}, "remaining": {"en": "Remaining", "ar": "المتبقي"}, "taken": {"en": "Taken", "ar": " مأخوذ"}, - "ml": {"en": "ml", "ar": "مل"}, + "ml": {"en": "ML", "ar": "مل"}, "l": {"en": "L", "ar": "لتر"}, "custom-label": {"en": "Enter amount", "ar": "أدخل كمية الماء"}, "custom-label-in-litres": {"en": "Enter amount in liters", "ar": "أدخل الكمية باللتر"}, @@ -1297,10 +1321,21 @@ const Map localizedValues = { "expectedArrivalTime": {"en": "Expected arrival time", "ar": "الوقت المتوقع للوصول"}, "add-address": {"en": "Add new address", "ar": "اضف عنوان جديد"}, "enter-file": {"en": "Please Enter Mobile Number and Medical File Number", "ar": "الرجاء إدخال رقم الجوال ورقم الملف الطبي"}, + "allow": {"en": "Allow", "ar": "السماح"}, + "reject": {"en": "Reject", "ar": "رفض"}, "referralRequesterInformation": {"en": "Referral requester information", "ar": "معلومات طالب الإحالة"}, "enterReferralRequesterName": {"en": "Enter Referral Requester Name*", "ar": "أدخل اسم مقدم طلب الإحالة *"}, "selectRelationship": {"en": "Select Relationship", "ar": "حدد العلاقة"}, "requesterRelationship": {"en": "Requester Relationship", "ar": "علاقة الطالب"}, "newReferral": {"en": "New Referral", "ar": "إحالة جديدة"}, - "searchForReferrals": {"en": "Search For Referrals", "ar": "ابحث عن الإحالات"} + "searchForReferrals": {"en": "Search For Referrals", "ar": "ابحث عن الإحالات"}, + "covid-select-procedure": {"en": "Please select the procedure:", "ar": "الرجاء تحديد الإجراء:"}, + "online-consultation": {"en": "Online Consultation", "ar": "استشارة مباشرة"}, + "expected-weiting": {"en": "Waiting time to start LiveCare consultation ", "ar": "وقت الانتظار المتوقع لبدء استشارة لايف كير"}, + "er-consult-fee": {"en": "Consultation Fee", "ar": "رسوم الاستشارة"}, + "insured-patient": {"en": "If you're Insurance patient, you have only have to pay the co-payment", "ar": "إذا كنت مريضًا في مجال التأمين ، فليس عليك سوى دفع المبلغ المشترك"}, + "i-accept-terms": {"en": "I Accept the Terms And Conditions", "ar": "أوافق على الشروط والأحكام"}, + "upcoming-pay-options": {"en": "You can pay by the following Options:", "ar": "يمكنك الدفع عن طريق الخيارات التالية:"}, + + "please-accept-terms": {"en": "Please accept terms & conditions to continue", "ar": "يرجى قبول الشروط والأحكام للمتابعة"}, }; diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index caada21f..703f5e3c 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -29,3 +29,5 @@ const BLOOD_TYPE = 'blood-type'; const NOTIFICATION_COUNT = 'notification-count'; const PHARMACY_SELECTED_ADDRESS = 'selected-address'; const PHARMACY_AUTORZIE_TOKEN = 'PHARMACY_AUTORZIE_TOKEN'; +const H2O_UNIT = 'H2O_UNIT'; +const H2O_REMINDER = 'H2O_REMINDER'; diff --git a/lib/core/model/AlHabibMedicalService/H2O/user_detail_model.dart b/lib/core/model/AlHabibMedicalService/H2O/user_detail_model.dart index bb100219..2f4ec9f0 100644 --- a/lib/core/model/AlHabibMedicalService/H2O/user_detail_model.dart +++ b/lib/core/model/AlHabibMedicalService/H2O/user_detail_model.dart @@ -49,6 +49,7 @@ class UserDetailModel { this.isNotificationON}); UserDetailModel.fromJson(Map json) { + if(json==null) return; userID = json['UserID']; patientID = json['PatientID']; patientType = json['PatientType']; diff --git a/lib/core/model/active_medications/ActivePrescriptionReport.dart b/lib/core/model/active_medications/ActivePrescriptionReport.dart index 866cb728..1917a6c8 100644 --- a/lib/core/model/active_medications/ActivePrescriptionReport.dart +++ b/lib/core/model/active_medications/ActivePrescriptionReport.dart @@ -23,7 +23,7 @@ class ActivePrescriptionReport { dynamic patientName; dynamic phoneOffice1; dynamic prescriptionQR; - int prescriptionTimes; + double prescriptionTimes; dynamic productImage; String productImageBase64; String productImageString; diff --git a/lib/core/model/health_calcolator/get_doctor_by_time_model.dart b/lib/core/model/health_calcolator/get_doctor_by_time_model.dart new file mode 100644 index 00000000..02c4a6ca --- /dev/null +++ b/lib/core/model/health_calcolator/get_doctor_by_time_model.dart @@ -0,0 +1,198 @@ +class DoctorListByTimeModel { + dynamic clinicID; + String clinicName; + String doctorTitle; + dynamic iD; + String name; + dynamic projectID; + String projectName; + dynamic actualDoctorRate; + dynamic clinicRoomNo; + dynamic date; + dynamic dayName; + double decimalDoctorRate; + dynamic doctorAvailability; + dynamic doctorID; + String doctorImageURL; + dynamic doctorProfile; + dynamic doctorProfileInfo; + dynamic doctorRate; + dynamic doctorStarsRate; + dynamic gender; + String genderDescription; + bool isAllowWaitList; + bool isAppointmentAllowed; + bool isDoctorAllowVedioCall; + bool isDoctorDummy; + bool isDoctorHasPrePostImages; + bool isLiveCare; + String latitude; + String longitude; + String nationalityFlagURL; + String nationalityID; + String nationalityName; + dynamic nearestFreeSlot; + dynamic noOfPatientsRate; + dynamic originalClinicID; + dynamic personRate; + dynamic projectDistanceInKiloMeters; + String qR; + dynamic qRString; + dynamic rateNumber; + dynamic serviceID; + String setupID; + List speciality; + dynamic workingHours; + + DoctorListByTimeModel( + {this.clinicID, + this.clinicName, + this.doctorTitle, + this.iD, + this.name, + this.projectID, + this.projectName, + this.actualDoctorRate, + this.clinicRoomNo, + this.date, + this.dayName, + this.decimalDoctorRate, + this.doctorAvailability, + this.doctorID, + this.doctorImageURL, + this.doctorProfile, + this.doctorProfileInfo, + this.doctorRate, + this.doctorStarsRate, + this.gender, + this.genderDescription, + this.isAllowWaitList, + this.isAppointmentAllowed, + this.isDoctorAllowVedioCall, + this.isDoctorDummy, + this.isDoctorHasPrePostImages, + this.isLiveCare, + this.latitude, + this.longitude, + this.nationalityFlagURL, + this.nationalityID, + this.nationalityName, + this.nearestFreeSlot, + this.noOfPatientsRate, + this.originalClinicID, + this.personRate, + this.projectDistanceInKiloMeters, + this.qR, + this.qRString, + this.rateNumber, + this.serviceID, + this.setupID, + this.speciality, + this.workingHours}); + + DoctorListByTimeModel.fromJson(Map json) { + clinicID = json['ClinicID']; + clinicName = json['ClinicName']; + doctorTitle = json['DoctorTitle']; + iD = json['ID']; + name = json['Name']; + projectID = json['ProjectID']; + projectName = json['ProjectName']; + actualDoctorRate = json['ActualDoctorRate']; + clinicRoomNo = json['ClinicRoomNo']; + date = json['Date']; + dayName = json['DayName']; + decimalDoctorRate = json['DecimalDoctorRate']; + doctorAvailability = json['DoctorAvailability']; + doctorID = json['DoctorID']; + doctorImageURL = json['DoctorImageURL']; + doctorProfile = json['DoctorProfile']; + doctorProfileInfo = json['DoctorProfileInfo']; + doctorRate = json['DoctorRate']; + doctorStarsRate = json['DoctorStarsRate']; + gender = json['Gender']; + genderDescription = json['GenderDescription']; + isAllowWaitList = json['IsAllowWaitList']; + isAppointmentAllowed = json['IsAppointmentAllowed']; + isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall']; + isDoctorDummy = json['IsDoctorDummy']; + isDoctorHasPrePostImages = json['IsDoctorHasPrePostImages']; + isLiveCare = json['IsLiveCare']; + latitude = json['Latitude']; + longitude = json['Longitude']; + nationalityFlagURL = json['NationalityFlagURL']; + nationalityID = json['NationalityID']; + nationalityName = json['NationalityName']; + nearestFreeSlot = json['NearestFreeSlot']; + noOfPatientsRate = json['NoOfPatientsRate']; + originalClinicID = json['OriginalClinicID']; + personRate = json['PersonRate']; + projectDistanceInKiloMeters = json['ProjectDistanceInKiloMeters']; + qR = json['QR']; + qRString = json['QRString']; + rateNumber = json['RateNumber']; + serviceID = json['ServiceID']; + setupID = json['SetupID']; + speciality = json['Speciality'].cast(); + workingHours = json['WorkingHours']; + } + + Map toJson() { + final Map data = new Map(); + data['ClinicID'] = this.clinicID; + data['ClinicName'] = this.clinicName; + data['DoctorTitle'] = this.doctorTitle; + data['ID'] = this.iD; + data['Name'] = this.name; + data['ProjectID'] = this.projectID; + data['ProjectName'] = this.projectName; + data['ActualDoctorRate'] = this.actualDoctorRate; + data['ClinicRoomNo'] = this.clinicRoomNo; + data['Date'] = this.date; + data['DayName'] = this.dayName; + data['DecimalDoctorRate'] = this.decimalDoctorRate; + data['DoctorAvailability'] = this.doctorAvailability; + data['DoctorID'] = this.doctorID; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorProfile'] = this.doctorProfile; + data['DoctorProfileInfo'] = this.doctorProfileInfo; + data['DoctorRate'] = this.doctorRate; + data['DoctorStarsRate'] = this.doctorStarsRate; + data['Gender'] = this.gender; + data['GenderDescription'] = this.genderDescription; + data['IsAllowWaitList'] = this.isAllowWaitList; + data['IsAppointmentAllowed'] = this.isAppointmentAllowed; + data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall; + data['IsDoctorDummy'] = this.isDoctorDummy; + data['IsDoctorHasPrePostImages'] = this.isDoctorHasPrePostImages; + data['IsLiveCare'] = this.isLiveCare; + data['Latitude'] = this.latitude; + data['Longitude'] = this.longitude; + data['NationalityFlagURL'] = this.nationalityFlagURL; + data['NationalityID'] = this.nationalityID; + data['NationalityName'] = this.nationalityName; + data['NearestFreeSlot'] = this.nearestFreeSlot; + data['NoOfPatientsRate'] = this.noOfPatientsRate; + data['OriginalClinicID'] = this.originalClinicID; + data['PersonRate'] = this.personRate; + data['ProjectDistanceInKiloMeters'] = this.projectDistanceInKiloMeters; + data['QR'] = this.qR; + data['QRString'] = this.qRString; + data['RateNumber'] = this.rateNumber; + data['ServiceID'] = this.serviceID; + data['SetupID'] = this.setupID; + data['Speciality'] = this.speciality; + data['WorkingHours'] = this.workingHours; + return data; + } +} + +class DoctorsListTime { + List doctorsByTimeList = List(); + String filterName = ""; + + DoctorsListTime({filterName, DoctorListByTimeModel doctor}) { + doctorsByTimeList.add(doctor); + this.filterName = filterName; + } +} diff --git a/lib/core/model/health_calcolator/get_doctor_by_time_request_model.dart b/lib/core/model/health_calcolator/get_doctor_by_time_request_model.dart new file mode 100644 index 00000000..cf9b2004 --- /dev/null +++ b/lib/core/model/health_calcolator/get_doctor_by_time_request_model.dart @@ -0,0 +1,80 @@ +class DoctorListByTimeRequestModel { + int clinicID; + bool isGetNearAppointment; + bool continueDentalPlan; + bool isSearchAppointmnetByClinicID; + int patientID; + int latitude; + int longitude; + bool license; + double versionID; + int channel; + int languageID; + String iPAdress; + String generalid; + int patientOutSA; + dynamic sessionID; + bool isDentalAllowedBackend; + int deviceTypeID; + + DoctorListByTimeRequestModel( + {this.clinicID, + this.isGetNearAppointment, + this.continueDentalPlan, + this.isSearchAppointmnetByClinicID, + this.patientID, + this.latitude, + this.longitude, + this.license, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID}); + + DoctorListByTimeRequestModel.fromJson(Map json) { + clinicID = json['ClinicID']; + isGetNearAppointment = json['IsGetNearAppointment']; + continueDentalPlan = json['ContinueDentalPlan']; + isSearchAppointmnetByClinicID = json['IsSearchAppointmnetByClinicID']; + patientID = json['PatientID']; + latitude = json['Latitude']; + longitude = json['Longitude']; + license = json['License']; + versionID = json['VersionID']; + channel = json['Channel']; + languageID = json['LanguageID']; + iPAdress = json['IPAdress']; + generalid = json['generalid']; + patientOutSA = json['PatientOutSA']; + sessionID = json['SessionID']; + isDentalAllowedBackend = json['isDentalAllowedBackend']; + deviceTypeID = json['DeviceTypeID']; + } + + Map toJson() { + final Map data = new Map(); + data['ClinicID'] = this.clinicID; + data['IsGetNearAppointment'] = this.isGetNearAppointment; + data['ContinueDentalPlan'] = this.continueDentalPlan; + data['IsSearchAppointmnetByClinicID'] = this.isSearchAppointmnetByClinicID; + data['PatientID'] = this.patientID; + data['Latitude'] = this.latitude; + data['Longitude'] = this.longitude; + data['License'] = this.license; + data['VersionID'] = this.versionID; + data['Channel'] = this.channel; + data['LanguageID'] = this.languageID; + data['IPAdress'] = this.iPAdress; + data['generalid'] = this.generalid; + data['PatientOutSA'] = this.patientOutSA; + data['SessionID'] = this.sessionID; + data['isDentalAllowedBackend'] = this.isDentalAllowedBackend; + data['DeviceTypeID'] = this.deviceTypeID; + return data; + } +} diff --git a/lib/core/model/health_calcolator/get_doctor_list_calcolation_model.dart b/lib/core/model/health_calcolator/get_doctor_list_calcolation_model.dart new file mode 100644 index 00000000..409cab60 --- /dev/null +++ b/lib/core/model/health_calcolator/get_doctor_list_calcolation_model.dart @@ -0,0 +1,64 @@ +class GetDoctorListModel { + int calcID; + int projectID; + int clinicID; + String clinicName; + int doctorID; + String doctorImageURL; + String doctorName; + String doctorTitle; + int gender; + String genderDescription; + String nationality; + String nationalityFlagURL; + String projectName; + + GetDoctorListModel( + {this.calcID, + this.projectID, + this.clinicID, + this.clinicName, + this.doctorID, + this.doctorImageURL, + this.doctorName, + this.doctorTitle, + this.gender, + this.genderDescription, + this.nationality, + this.nationalityFlagURL, + this.projectName}); + + GetDoctorListModel.fromJson(Map json) { + calcID = json['CalcID']; + projectID = json['ProjectID']; + clinicID = json['ClinicID']; + clinicName = json['ClinicName']; + doctorID = json['DoctorID']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + doctorTitle = json['DoctorTitle']; + gender = json['Gender']; + genderDescription = json['GenderDescription']; + nationality = json['Nationality']; + nationalityFlagURL = json['NationalityFlagURL']; + projectName = json['ProjectName']; + } + + Map toJson() { + final Map data = new Map(); + data['CalcID'] = this.calcID; + data['ProjectID'] = this.projectID; + data['ClinicID'] = this.clinicID; + data['ClinicName'] = this.clinicName; + data['DoctorID'] = this.doctorID; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorName'] = this.doctorName; + data['DoctorTitle'] = this.doctorTitle; + data['Gender'] = this.gender; + data['GenderDescription'] = this.genderDescription; + data['Nationality'] = this.nationality; + data['NationalityFlagURL'] = this.nationalityFlagURL; + data['ProjectName'] = this.projectName; + return data; + } +} diff --git a/lib/core/model/health_calcolator/get_doctor_list_calcolation_request_model.dart b/lib/core/model/health_calcolator/get_doctor_list_calcolation_request_model.dart new file mode 100644 index 00000000..80002341 --- /dev/null +++ b/lib/core/model/health_calcolator/get_doctor_list_calcolation_request_model.dart @@ -0,0 +1,52 @@ +class GetDoctorListRequestModel { + int calculationID; + double versionID; + int channel; + int languageID; + String iPAdress; + String generalid; + int patientOutSA; + String sessionID; + bool isDentalAllowedBackend; + int deviceTypeID; + + GetDoctorListRequestModel( + {this.calculationID, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID}); + + GetDoctorListRequestModel.fromJson(Map json) { + calculationID = json['CalculationID']; + versionID = json['VersionID']; + channel = json['Channel']; + languageID = json['LanguageID']; + iPAdress = json['IPAdress']; + generalid = json['generalid']; + patientOutSA = json['PatientOutSA']; + sessionID = json['SessionID']; + isDentalAllowedBackend = json['isDentalAllowedBackend']; + deviceTypeID = json['DeviceTypeID']; + } + + Map toJson() { + final Map data = new Map(); + data['CalculationID'] = this.calculationID; + data['VersionID'] = this.versionID; + data['Channel'] = this.channel; + data['LanguageID'] = this.languageID; + data['IPAdress'] = this.iPAdress; + data['generalid'] = this.generalid; + data['PatientOutSA'] = this.patientOutSA; + data['SessionID'] = this.sessionID; + data['isDentalAllowedBackend'] = this.isDentalAllowedBackend; + data['DeviceTypeID'] = this.deviceTypeID; + return data; + } +} diff --git a/lib/core/model/insurance/ReauestInsuranceApprovalModel.dart b/lib/core/model/insurance/ReauestInsuranceApprovalModel.dart index 5f41f878..26bf567a 100644 --- a/lib/core/model/insurance/ReauestInsuranceApprovalModel.dart +++ b/lib/core/model/insurance/ReauestInsuranceApprovalModel.dart @@ -1,4 +1,4 @@ -class ReauestInsuranceApprovalModel { +class RequestInsuranceApprovalModel { double versionID; int channel; int languageID; @@ -15,7 +15,7 @@ class ReauestInsuranceApprovalModel { int eXuldAPPNO; int projectID; - ReauestInsuranceApprovalModel( + RequestInsuranceApprovalModel( {this.versionID, this.channel, this.languageID, @@ -32,7 +32,7 @@ class ReauestInsuranceApprovalModel { this.eXuldAPPNO, this.projectID}); - ReauestInsuranceApprovalModel.fromJson(Map json) { + RequestInsuranceApprovalModel.fromJson(Map json) { versionID = json['VersionID']; channel = json['Channel']; languageID = json['LanguageID']; diff --git a/lib/core/model/insurance/insurance_approval.dart b/lib/core/model/insurance/insurance_approval.dart index 894fad46..27911267 100644 --- a/lib/core/model/insurance/insurance_approval.dart +++ b/lib/core/model/insurance/insurance_approval.dart @@ -1,140 +1,465 @@ -class InsuranceApprovalDetails { - String procedureName; - String status; - String isInvoicedDesc; - - InsuranceApprovalDetails({ - this.procedureName, - this.status, - this.isInvoicedDesc, - }); - - InsuranceApprovalDetails.fromJson(Map json) { - try { - isInvoicedDesc = json['IsInvoicedDesc']; - status = json['Status']; - procedureName = json['ProcedureName']; - } catch (e) { - print(e); - } - } -} - class InsuranceApprovalModel { - InsuranceApprovalDetails approvalDetails; - double versionID; - int channel; - int languageID; - String iPAdress; - String generalid; - int patientOutSA; - String sessionID; - bool isDentalAllowedBackend; - int deviceTypeID; - int patientID; - String tokenID; - int patientTypeID; - int patientType; - int eXuldAPPNO; + String setupID; int projectID; - String doctorName; - String clinicName; - String patientDescription; int approvalNo; - String approvalStatusDescption; - int unUsedCount; - - //String companyName; + String approvalDate; + int patientType; + int patientID; + int companyID; + int subCategoryID; + int doctorID; + int clinicID; + int approvalType; + String inpatientApprovalSubType; + String validFrom; + String vaildDays; + String validTo; + bool isApprovalOnGross; + bool isPackage; + int requestedAmount; + int actualApprovedAmount; + int aviliableAmount; + String companyApprovalNo; + int progNoteOrderNo; + String submitOn; + String receiptOn; + String remarks1; + String remarks2; + int status; + String feedbackStatusBy; + String feedbackStatus; + String feedbackStatusOn; + int authorizerID; String expiryDate; - String rceiptOn; int appointmentNo; + int admissionNo; + int admissionRequestNo; + int createdBy; + String createdOn; + int editedBy; + String editedOn; + String rowVer; + bool isAddlDiscApplied; + int inProgressReasonID; + String extendedBy; + String extendedOn; + int subPolicyNo; + int noOrderAuthorizerID; + bool isVerbalApproval; + String subStatus; + bool isNotificationSend; + String eApprovalStatus; + String eApprovalRemarks; + bool isEmailSentOnDelayApproval; + int eAuthorizationID; + InsuranceApprovalDetails apporvalDetails; + String approvalStatusDescption; + String clinicName; + String clinicNameN; + String companyName; + String doctorImageURL; + String doctorName; + String doctorNameN; + int doctorRate; + String doctorTitle; + int gender; + String genderDescription; + bool isActiveDoctorProfile; + bool isExecludeDoctor; + bool isInOutPatient; + String isInOutPatientDescription; + String isInOutPatientDescriptionN; + bool isLiveCareAppointment; + String projectName; + String projectNameN; + String qR; + List speciality; + String strApprovalDate; + String strExpiryDate; + String strSubmitDate; + int totaUnUsedCount; + int unUsedCount; InsuranceApprovalModel( - {this.versionID, - this.channel, - this.languageID, - this.iPAdress, - this.generalid, - this.patientOutSA, - this.sessionID, - this.isDentalAllowedBackend, - this.deviceTypeID, - this.patientID, - this.tokenID, - this.patientTypeID, - this.patientType, - this.eXuldAPPNO, + {this.setupID, this.projectID, - this.doctorName, - this.clinicName, - this.patientDescription, this.approvalNo, - this.approvalStatusDescption, - this.unUsedCount, - //this.companyName, + this.approvalDate, + this.patientType, + this.patientID, + this.companyID, + this.subCategoryID, + this.doctorID, + this.clinicID, + this.approvalType, + this.inpatientApprovalSubType, + this.validFrom, + this.vaildDays, + this.validTo, + this.isApprovalOnGross, + this.isPackage, + this.requestedAmount, + this.actualApprovedAmount, + this.aviliableAmount, + this.companyApprovalNo, + this.progNoteOrderNo, + this.submitOn, + this.receiptOn, + this.remarks1, + this.remarks2, + this.status, + this.feedbackStatusBy, + this.feedbackStatus, + this.feedbackStatusOn, + this.authorizerID, this.expiryDate, - this.rceiptOn, - this.approvalDetails, - this.appointmentNo}); - - InsuranceApprovalDetails x = InsuranceApprovalDetails(); + this.appointmentNo, + this.admissionNo, + this.admissionRequestNo, + this.createdBy, + this.createdOn, + this.editedBy, + this.editedOn, + this.rowVer, + this.isAddlDiscApplied, + this.inProgressReasonID, + this.extendedBy, + this.extendedOn, + this.subPolicyNo, + this.noOrderAuthorizerID, + this.isVerbalApproval, + this.subStatus, + this.isNotificationSend, + this.eApprovalStatus, + this.eApprovalRemarks, + this.isEmailSentOnDelayApproval, + this.eAuthorizationID, + this.apporvalDetails, + this.approvalStatusDescption, + this.clinicName, + this.clinicNameN, + this.companyName, + this.doctorImageURL, + this.doctorName, + this.doctorNameN, + this.doctorRate, + this.doctorTitle, + this.gender, + this.genderDescription, + this.isActiveDoctorProfile, + this.isExecludeDoctor, + this.isInOutPatient, + this.isInOutPatientDescription, + this.isInOutPatientDescriptionN, + this.isLiveCareAppointment, + this.projectName, + this.projectNameN, + this.qR, + this.speciality, + this.strApprovalDate, + this.strExpiryDate, + this.strSubmitDate, + this.totaUnUsedCount, + this.unUsedCount}); InsuranceApprovalModel.fromJson(Map json) { - try { - rceiptOn = json['ReceiptOn']; - expiryDate = json['ExpiryDate']; - //companyName = json['CompanyName']; - unUsedCount = json['TotaUnUsedCount']; - approvalStatusDescption = json['ApprovalStatusDescption']; - approvalNo = json['ApprovalNo']; - patientDescription = json['IsInOutPatientDescription']; - versionID = json['VersionID']; - channel = json['Channel']; - languageID = json['LanguageID']; - iPAdress = json['IPAdress']; - generalid = json['generalid']; - patientOutSA = json['PatientOutSA']; - sessionID = json['SessionID']; - isDentalAllowedBackend = json['isDentalAllowedBackend']; - deviceTypeID = json['DeviceTypeID']; - patientID = json['PatientID']; - tokenID = json['TokenID']; - patientTypeID = json['PatientTypeID']; - patientType = json['PatientType']; - eXuldAPPNO = json['EXuldAPPNO']; - projectID = json['ProjectID']; - doctorName = json['DoctorName']; - clinicName = json['ClinicName']; - approvalDetails = - InsuranceApprovalDetails.fromJson(json['ApporvalDetails'][0]); - appointmentNo = json['AppointmentNo']; - } catch (e) { - print(e); + setupID = json['SetupID']; + projectID = json['ProjectID']; + approvalNo = json['ApprovalNo']; + approvalDate = json['ApprovalDate']; + patientType = json['PatientType']; + patientID = json['PatientID']; + companyID = json['CompanyID']; + subCategoryID = json['SubCategoryID']; + doctorID = json['DoctorID']; + clinicID = json['ClinicID']; + approvalType = json['ApprovalType']; + inpatientApprovalSubType = json['InpatientApprovalSubType']; + validFrom = json['ValidFrom']; + vaildDays = json['VaildDays']; + validTo = json['ValidTo']; + isApprovalOnGross = json['IsApprovalOnGross']; + isPackage = json['IsPackage']; + requestedAmount = json['RequestedAmount']; + actualApprovedAmount = json['ActualApprovedAmount']; + aviliableAmount = json['AviliableAmount']; + companyApprovalNo = json['CompanyApprovalNo']; + progNoteOrderNo = json['ProgNoteOrderNo']; + submitOn = json['SubmitOn']; + receiptOn = json['ReceiptOn']; + remarks1 = json['Remarks1']; + remarks2 = json['Remarks2']; + status = json['Status']; + feedbackStatusBy = json['FeedbackStatusBy']; + feedbackStatus = json['FeedbackStatus']; + feedbackStatusOn = json['FeedbackStatusOn']; + authorizerID = json['AuthorizerID']; + expiryDate = json['ExpiryDate']; + appointmentNo = json['AppointmentNo']; + admissionNo = json['AdmissionNo']; + admissionRequestNo = json['AdmissionRequestNo']; + createdBy = json['CreatedBy']; + createdOn = json['CreatedOn']; + editedBy = json['EditedBy']; + editedOn = json['EditedOn']; + rowVer = json['RowVer']; + isAddlDiscApplied = json['IsAddlDiscApplied']; + inProgressReasonID = json['InProgressReasonID']; + extendedBy = json['ExtendedBy']; + extendedOn = json['ExtendedOn']; + subPolicyNo = json['SubPolicyNo']; + noOrderAuthorizerID = json['NoOrderAuthorizerID']; + isVerbalApproval = json['isVerbalApproval']; + subStatus = json['SubStatus']; + isNotificationSend = json['IsNotificationSend']; + eApprovalStatus = json['EApprovalStatus']; + eApprovalRemarks = json['EApprovalRemarks']; + isEmailSentOnDelayApproval = json['IsEmailSentOnDelayApproval']; + eAuthorizationID = json['EAuthorizationID']; + if (json['ApporvalDetails'] != null) { + apporvalDetails = InsuranceApprovalDetails.fromJson(json['ApporvalDetails'][0]); } + approvalStatusDescption = json['ApprovalStatusDescption']; + clinicName = json['ClinicName']; + clinicNameN = json['ClinicNameN']; + companyName = json['CompanyName']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + doctorRate = json['DoctorRate']; + doctorTitle = json['DoctorTitle']; + gender = json['Gender']; + genderDescription = json['GenderDescription']; + isActiveDoctorProfile = json['IsActiveDoctorProfile']; + isExecludeDoctor = json['IsExecludeDoctor']; + isInOutPatient = json['IsInOutPatient']; + isInOutPatientDescription = json['IsInOutPatientDescription']; + isInOutPatientDescriptionN = json['IsInOutPatientDescriptionN']; + isLiveCareAppointment = json['IsLiveCareAppointment']; + projectName = json['ProjectName']; + projectNameN = json['ProjectNameN']; + qR = json['QR']; + speciality = json['Speciality'].cast(); + strApprovalDate = json['StrApprovalDate']; + strExpiryDate = json['StrExpiryDate']; + strSubmitDate = json['StrSubmitDate']; + totaUnUsedCount = json['TotaUnUsedCount']; + unUsedCount = json['UnUsedCount']; } Map toJson() { final Map data = new Map(); - data['VersionID'] = this.versionID; - data['Channel'] = this.channel; - data['LanguageID'] = this.languageID; - data['IPAdress'] = this.iPAdress; - data['generalid'] = this.generalid; - data['PatientOutSA'] = this.patientOutSA; - data['SessionID'] = this.sessionID; - data['isDentalAllowedBackend'] = this.isDentalAllowedBackend; - data['DeviceTypeID'] = this.deviceTypeID; - data['PatientID'] = this.patientID; - data['TokenID'] = this.tokenID; - data['PatientTypeID'] = this.patientTypeID; + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['ApprovalNo'] = this.approvalNo; + data['ApprovalDate'] = this.approvalDate; data['PatientType'] = this.patientType; - if (appointmentNo == null) { - data['EXuldAPPNO'] = this.eXuldAPPNO; - data['ProjectID'] = this.projectID; - } - if (appointmentNo != null) { - data['AppointmentNo'] = this.appointmentNo; + data['PatientID'] = this.patientID; + data['CompanyID'] = this.companyID; + data['SubCategoryID'] = this.subCategoryID; + data['DoctorID'] = this.doctorID; + data['ClinicID'] = this.clinicID; + data['ApprovalType'] = this.approvalType; + data['InpatientApprovalSubType'] = this.inpatientApprovalSubType; + data['ValidFrom'] = this.validFrom; + data['VaildDays'] = this.vaildDays; + data['ValidTo'] = this.validTo; + data['IsApprovalOnGross'] = this.isApprovalOnGross; + data['IsPackage'] = this.isPackage; + data['RequestedAmount'] = this.requestedAmount; + data['ActualApprovedAmount'] = this.actualApprovedAmount; + data['AviliableAmount'] = this.aviliableAmount; + data['CompanyApprovalNo'] = this.companyApprovalNo; + data['ProgNoteOrderNo'] = this.progNoteOrderNo; + data['SubmitOn'] = this.submitOn; + data['ReceiptOn'] = this.receiptOn; + data['Remarks1'] = this.remarks1; + data['Remarks2'] = this.remarks2; + data['Status'] = this.status; + data['FeedbackStatusBy'] = this.feedbackStatusBy; + data['FeedbackStatus'] = this.feedbackStatus; + data['FeedbackStatusOn'] = this.feedbackStatusOn; + data['AuthorizerID'] = this.authorizerID; + data['ExpiryDate'] = this.expiryDate; + data['AppointmentNo'] = this.appointmentNo; + data['AdmissionNo'] = this.admissionNo; + data['AdmissionRequestNo'] = this.admissionRequestNo; + data['CreatedBy'] = this.createdBy; + data['CreatedOn'] = this.createdOn; + data['EditedBy'] = this.editedBy; + data['EditedOn'] = this.editedOn; + data['RowVer'] = this.rowVer; + data['IsAddlDiscApplied'] = this.isAddlDiscApplied; + data['InProgressReasonID'] = this.inProgressReasonID; + data['ExtendedBy'] = this.extendedBy; + data['ExtendedOn'] = this.extendedOn; + data['SubPolicyNo'] = this.subPolicyNo; + data['NoOrderAuthorizerID'] = this.noOrderAuthorizerID; + data['isVerbalApproval'] = this.isVerbalApproval; + data['SubStatus'] = this.subStatus; + data['IsNotificationSend'] = this.isNotificationSend; + data['EApprovalStatus'] = this.eApprovalStatus; + data['EApprovalRemarks'] = this.eApprovalRemarks; + data['IsEmailSentOnDelayApproval'] = this.isEmailSentOnDelayApproval; + data['EAuthorizationID'] = this.eAuthorizationID; + if (this.apporvalDetails != null) { + data['ApporvalDetails'] = this.apporvalDetails.toJson; } + data['ApprovalStatusDescption'] = this.approvalStatusDescption; + data['ClinicName'] = this.clinicName; + data['ClinicNameN'] = this.clinicNameN; + data['CompanyName'] = this.companyName; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorName'] = this.doctorName; + data['DoctorNameN'] = this.doctorNameN; + data['DoctorRate'] = this.doctorRate; + data['DoctorTitle'] = this.doctorTitle; + data['Gender'] = this.gender; + data['GenderDescription'] = this.genderDescription; + data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile; + data['IsExecludeDoctor'] = this.isExecludeDoctor; + data['IsInOutPatient'] = this.isInOutPatient; + data['IsInOutPatientDescription'] = this.isInOutPatientDescription; + data['IsInOutPatientDescriptionN'] = this.isInOutPatientDescriptionN; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; + data['ProjectName'] = this.projectName; + data['ProjectNameN'] = this.projectNameN; + data['QR'] = this.qR; + data['Speciality'] = this.speciality; + data['StrApprovalDate'] = this.strApprovalDate; + data['StrExpiryDate'] = this.strExpiryDate; + data['StrSubmitDate'] = this.strSubmitDate; + data['TotaUnUsedCount'] = this.totaUnUsedCount; + data['UnUsedCount'] = this.unUsedCount; + return data; + } +} + +class InsuranceApprovalDetails { + int setupID; + int projectID; + int approvalNo; + int lineItemNo; + int orderType; + int procedureID; + int toothNo; + int price; + int approvedAmount; + String unapprovedPatientShare; + int waivedAmount; + String discountType; + int discountValue; + String shareType; + String patientShareTypeValue; + String companyShareTypeValue; + String patientShare; + String companyShare; + int deductableAmount; + String disapprovedRemarks; + int progNoteOrderNo; + int progNoteLineItemNo; + String invoiceTransactionType; + int invoiceNo; + String procedureName; + String procedureNameN; + String status; + bool isInvoiced; + String isInvoicedDesc; + + InsuranceApprovalDetails( + {this.setupID, + this.projectID, + this.approvalNo, + this.lineItemNo, + this.orderType, + this.procedureID, + this.toothNo, + this.price, + this.approvedAmount, + this.unapprovedPatientShare, + this.waivedAmount, + this.discountType, + this.discountValue, + this.shareType, + this.patientShareTypeValue, + this.companyShareTypeValue, + this.patientShare, + this.companyShare, + this.deductableAmount, + this.disapprovedRemarks, + this.progNoteOrderNo, + this.progNoteLineItemNo, + this.invoiceTransactionType, + this.invoiceNo, + this.procedureName, + this.procedureNameN, + this.status, + this.isInvoiced, + this.isInvoicedDesc}); + + InsuranceApprovalDetails.fromJson(Map json) { + setupID = json['SetupID']; + projectID = json['ProjectID']; + approvalNo = json['ApprovalNo']; + lineItemNo = json['LineItemNo']; + orderType = json['OrderType']; + procedureID = json['ProcedureID']; + toothNo = json['ToothNo']; + price = json['Price']; + approvedAmount = json['ApprovedAmount']; + unapprovedPatientShare = json['UnapprovedPatientShare']; + waivedAmount = json['WaivedAmount']; + discountType = json['DiscountType']; + discountValue = json['DiscountValue']; + shareType = json['ShareType']; + patientShareTypeValue = json['PatientShareTypeValue']; + companyShareTypeValue = json['CompanyShareTypeValue']; + patientShare = json['PatientShare']; + companyShare = json['CompanyShare']; + deductableAmount = json['DeductableAmount']; + disapprovedRemarks = json['DisapprovedRemarks']; + progNoteOrderNo = json['ProgNoteOrderNo']; + progNoteLineItemNo = json['ProgNoteLineItemNo']; + invoiceTransactionType = json['InvoiceTransactionType']; + invoiceNo = json['InvoiceNo']; + procedureName = json['ProcedureName']; + procedureNameN = json['ProcedureNameN']; + status = json['Status']; + isInvoiced = json['IsInvoiced']; + isInvoicedDesc = json['IsInvoicedDesc']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['ApprovalNo'] = this.approvalNo; + data['LineItemNo'] = this.lineItemNo; + data['OrderType'] = this.orderType; + data['ProcedureID'] = this.procedureID; + data['ToothNo'] = this.toothNo; + data['Price'] = this.price; + data['ApprovedAmount'] = this.approvedAmount; + data['UnapprovedPatientShare'] = this.unapprovedPatientShare; + data['WaivedAmount'] = this.waivedAmount; + data['DiscountType'] = this.discountType; + data['DiscountValue'] = this.discountValue; + data['ShareType'] = this.shareType; + data['PatientShareTypeValue'] = this.patientShareTypeValue; + data['CompanyShareTypeValue'] = this.companyShareTypeValue; + data['PatientShare'] = this.patientShare; + data['CompanyShare'] = this.companyShare; + data['DeductableAmount'] = this.deductableAmount; + data['DisapprovedRemarks'] = this.disapprovedRemarks; + data['ProgNoteOrderNo'] = this.progNoteOrderNo; + data['ProgNoteLineItemNo'] = this.progNoteLineItemNo; + data['InvoiceTransactionType'] = this.invoiceTransactionType; + data['InvoiceNo'] = this.invoiceNo; + data['ProcedureName'] = this.procedureName; + data['ProcedureNameN'] = this.procedureNameN; + data['Status'] = this.status; + data['IsInvoiced'] = this.isInvoiced; + data['IsInvoicedDesc'] = this.isInvoicedDesc; return data; } } diff --git a/lib/core/model/prescriptions/prescription_report.dart b/lib/core/model/prescriptions/prescription_report.dart index 8c18df62..5545b25b 100644 --- a/lib/core/model/prescriptions/prescription_report.dart +++ b/lib/core/model/prescriptions/prescription_report.dart @@ -134,7 +134,7 @@ class PrescriptionReport { frequencyID = json['frequencyID']; routeID = json['routeID']; name = json['name']; - itemDescriptionN = json['itemDescriptionN']; + itemDescriptionN = json['ItemDescriptionN']; routeN = json['routeN']; frequencyN = json['frequencyN']; } diff --git a/lib/core/model/prescriptions/prescription_report_enh.dart b/lib/core/model/prescriptions/prescription_report_enh.dart index 203eaaff..01a34c47 100644 --- a/lib/core/model/prescriptions/prescription_report_enh.dart +++ b/lib/core/model/prescriptions/prescription_report_enh.dart @@ -15,6 +15,7 @@ class PrescriptionReportEnh { String imageThumbUrl; String isCovered; String itemDescription; + String itemDescriptionN; int itemID; String orderDate; int patientID; @@ -35,38 +36,39 @@ class PrescriptionReportEnh { PrescriptionReportEnh( {this.address, - this.appointmentNo, - this.clinic, - this.companyName, - this.days, - this.doctorName, - this.doseDailyQuantity, - this.frequency, - this.frequencyNumber, - this.image, - this.imageExtension, - this.imageSRCUrl, - this.imageString, - this.imageThumbUrl, - this.isCovered, - this.itemDescription, - this.itemID, - this.orderDate, - this.patientID, - this.patientName, - this.phoneOffice1, - this.prescriptionQR, - this.prescriptionTimes, - this.productImage, - this.productImageBase64, - this.productImageString, - this.projectID, - this.projectName, - this.remarks, - this.route, - this.sKU, - this.scaleOffset, - this.startDate}); + this.appointmentNo, + this.clinic, + this.companyName, + this.days, + this.doctorName, + this.doseDailyQuantity, + this.frequency, + this.frequencyNumber, + this.image, + this.imageExtension, + this.imageSRCUrl, + this.imageString, + this.imageThumbUrl, + this.isCovered, + this.itemDescription, + this.itemDescriptionN, + this.itemID, + this.orderDate, + this.patientID, + this.patientName, + this.phoneOffice1, + this.prescriptionQR, + this.prescriptionTimes, + this.productImage, + this.productImageBase64, + this.productImageString, + this.projectID, + this.projectName, + this.remarks, + this.route, + this.sKU, + this.scaleOffset, + this.startDate}); PrescriptionReportEnh.fromJson(Map json) { address = json['Address']; @@ -85,6 +87,7 @@ class PrescriptionReportEnh { imageThumbUrl = json['ImageThumbUrl']; isCovered = json['IsCovered']; itemDescription = json['ItemDescription']; + itemDescriptionN = json['ItemDescriptionN']; itemID = json['ItemID']; orderDate = json['OrderDate']; patientID = json['PatientID']; @@ -122,6 +125,7 @@ class PrescriptionReportEnh { data['ImageThumbUrl'] = this.imageThumbUrl; data['IsCovered'] = this.isCovered; data['ItemDescription'] = this.itemDescription; + data['ItemDescriptionN'] = this.itemDescriptionN; data['ItemID'] = this.itemID; data['OrderDate'] = this.orderDate; data['PatientID'] = this.patientID; diff --git a/lib/core/model/prescriptions/prescription_report_inp.dart b/lib/core/model/prescriptions/prescription_report_inp.dart new file mode 100644 index 00000000..b802337b --- /dev/null +++ b/lib/core/model/prescriptions/prescription_report_inp.dart @@ -0,0 +1,124 @@ +class PrescriptionReportINP { + int patientID; + String patientName; + String patientAge; + String patientGender; + String address; + String phoneOffice; + String itemDescription; + int doseTimingID; + int frequencyID; + int routeID; + String clinic; + String doctorName; + String route; + String frequency; + String remarks; + String name; + int days; + String startDate; + String orderDate; + int doseDailyQuantity; + int itemID; + Null productImage; + String sKU; + String itemDescriptionN; + String routeN; + String frequencyN; + String imageSRCUrl; + String imageThumbUrl; + + PrescriptionReportINP( + {this.patientID, + this.patientName, + this.patientAge, + this.patientGender, + this.address, + this.phoneOffice, + this.itemDescription, + this.doseTimingID, + this.frequencyID, + this.routeID, + this.clinic, + this.doctorName, + this.route, + this.frequency, + this.remarks, + this.name, + this.days, + this.startDate, + this.orderDate, + this.doseDailyQuantity, + this.itemID, + this.productImage, + this.sKU, + this.itemDescriptionN, + this.routeN, + this.frequencyN, + this.imageSRCUrl, + this.imageThumbUrl}); + + PrescriptionReportINP.fromJson(Map json) { + patientID = json['PatientID']; + patientName = json['PatientName']; + patientAge = json['PatientAge']; + patientGender = json['PatientGender']; + address = json['Address']; + phoneOffice = json['PhoneOffice']; + itemDescription = json['ItemDescription']; + doseTimingID = json['DoseTimingID']; + frequencyID = json['FrequencyID']; + routeID = json['RouteID']; + clinic = json['Clinic']; + doctorName = json['DoctorName']; + route = json['Route']; + frequency = json['Frequency']; + remarks = json['Remarks']; + name = json['Name']; + days = json['Days']; + startDate = json['StartDate']; + orderDate = json['OrderDate']; + doseDailyQuantity = json['DoseDailyQuantity']; + itemID = json['ItemID']; + productImage = json['ProductImage']; + sKU = json['SKU']; + itemDescriptionN = json['ItemDescriptionN']; + routeN = json['RouteN']; + frequencyN = json['FrequencyN']; + imageSRCUrl = json['ImageSRCUrl']; + imageThumbUrl = json['ImageThumbUrl']; + } + + Map toJson() { + final Map data = new Map(); + data['PatientID'] = this.patientID; + data['PatientName'] = this.patientName; + data['PatientAge'] = this.patientAge; + data['PatientGender'] = this.patientGender; + data['Address'] = this.address; + data['PhoneOffice'] = this.phoneOffice; + data['ItemDescription'] = this.itemDescription; + data['DoseTimingID'] = this.doseTimingID; + data['FrequencyID'] = this.frequencyID; + data['RouteID'] = this.routeID; + data['Clinic'] = this.clinic; + data['DoctorName'] = this.doctorName; + data['Route'] = this.route; + data['Frequency'] = this.frequency; + data['Remarks'] = this.remarks; + data['Name'] = this.name; + data['Days'] = this.days; + data['StartDate'] = this.startDate; + data['OrderDate'] = this.orderDate; + data['DoseDailyQuantity'] = this.doseDailyQuantity; + data['ItemID'] = this.itemID; + data['ProductImage'] = this.productImage; + data['SKU'] = this.sKU; + data['ItemDescriptionN'] = this.itemDescriptionN; + data['RouteN'] = this.routeN; + data['FrequencyN'] = this.frequencyN; + data['ImageSRCUrl'] = this.imageSRCUrl; + data['ImageThumbUrl'] = this.imageThumbUrl; + return data; + } +} diff --git a/lib/core/model/prescriptions/request_send_prescription_email.dart b/lib/core/model/prescriptions/request_send_prescription_email.dart index 2d1f3aa3..ecd0f36d 100644 --- a/lib/core/model/prescriptions/request_send_prescription_email.dart +++ b/lib/core/model/prescriptions/request_send_prescription_email.dart @@ -23,6 +23,7 @@ class RequestSendPrescriptionEmail { String setupID; String clinicName; String doctorName; + int doctorID; int projectID; List listPrescriptions; @@ -49,7 +50,8 @@ class RequestSendPrescriptionEmail { this.setupID, this.clinicName, this.doctorName, - this.projectID}); + this.projectID, + this.doctorID}); RequestSendPrescriptionEmail.fromJson(Map json) { appointmentDate = json['AppointmentDate']; @@ -75,6 +77,7 @@ class RequestSendPrescriptionEmail { clinicName = json['ClinicName']; doctorName = json['DoctorName']; projectID = json['ProjectID']; + doctorID = json['DoctorID']; } Map toJson() { @@ -106,7 +109,7 @@ class RequestSendPrescriptionEmail { data['ClinicName'] = this.clinicName; data['DoctorName'] = this.doctorName; data['ProjectID'] = this.projectID; - + data['DoctorID'] = this.doctorID; return data; } } diff --git a/lib/core/service/AlHabibMedicalService/health-calculator/bariatrics-service.dart b/lib/core/service/AlHabibMedicalService/health-calculator/bariatrics-service.dart index b59eadac..4b38ef65 100644 --- a/lib/core/service/AlHabibMedicalService/health-calculator/bariatrics-service.dart +++ b/lib/core/service/AlHabibMedicalService/health-calculator/bariatrics-service.dart @@ -2,24 +2,29 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/ClinicCategory.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/DiseasesByClinic.dart'; +import 'package:diplomaticquarterapp/core/model/health_calcolator/get_doctor_by_time_model.dart'; +import 'package:diplomaticquarterapp/core/model/health_calcolator/get_doctor_by_time_request_model.dart'; +import 'package:diplomaticquarterapp/core/model/health_calcolator/get_doctor_list_calcolation_model.dart'; +import 'package:diplomaticquarterapp/core/model/health_calcolator/get_doctor_list_calcolation_request_model.dart'; import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:flutter/cupertino.dart'; class BariatricsService extends BaseService { List clinicCategoryList = []; List diseasesList = []; + List doctorList = []; + List doctorListByTime = []; Future getClinicCategory() async { hasError = false; Map body = Map(); - var languageID = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); body['ClinicID'] = 108; // hint: it is static depend on IONIC project body['isDentalAllowedBackend'] = false; body['LanguageID'] = languageID == 'ar' ? 1 : 2; - await baseAppClient.post(GET_CLINIC_CATEGORY, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_CLINIC_CATEGORY, onSuccess: (dynamic response, int statusCode) { clinicCategoryList.clear(); if (response['ClinicCategoryList'] != null) response['ClinicCategoryList'].forEach((city) { @@ -36,8 +41,7 @@ class BariatricsService extends BaseService { Map body = Map(); body['ClinicID'] = 108; // hint: it is static depend on IONIC project - await baseAppClient.post(GET_DISEASE_BY_CLINIC_ID, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_DISEASE_BY_CLINIC_ID, onSuccess: (dynamic response, int statusCode) { diseasesList.clear(); if (response['DiseasesByClinicList'] != null) response['DiseasesByClinicList'].forEach((city) { @@ -51,8 +55,7 @@ class BariatricsService extends BaseService { Future searchDoctorsByTime(DiseasesByClinic disease) async { hasError = false; - var languageID = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); Map body = Map(); body['ClinicID'] = 108; // hint: it is static depend on IONIC project @@ -66,8 +69,38 @@ class BariatricsService extends BaseService { body['Longitude'] = 0; body['isDentalAllowedBackend'] = false; - await baseAppClient.post(SEARCH_DOCTOR_BY_TIME, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(SEARCH_DOCTOR_BY_TIME, onSuccess: (dynamic response, int statusCode) {}, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); + } + + Future getDoctorList({@required DiseasesByClinic disease}) async { + hasError = false; + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + + Map body = Map(); + body['ClinicID'] = 108; // hint: it is static depend on IONIC project + body['ContinueDentalPlan'] = false; + body['IsGetNearAppointment'] = false; + body['IsSearchAppointmnetByClinicID'] = true; + body['LanguageID'] = languageID == 'ar' ? 1 : 2; + body['Latitude'] = 0; + body['License'] = true; + body['Longitude'] = 0; + body['PatientID'] = 0; + body['isDentalAllowedBackend'] = false; + + if(disease != null) + body['DiseaseID'] = disease.diseasesID; + + await baseAppClient.post(GET_DOCTOR_LIST_BY_TIME, onSuccess: (dynamic response, int statusCode) { + doctorListByTime.clear(); + if (response['DoctorList'] != null) + response['DoctorList'].forEach((city) { + doctorListByTime.add(DoctorListByTimeModel.fromJson(city)); + }); }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index f12ef3da..43c39fec 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -29,8 +29,7 @@ AppSharedPreferences sharedPref = new AppSharedPreferences(); /// onFailure: (String error, int statusCode) {}, /// body: Map(); /// -AuthenticatedUserObject authenticatedUserObject = - locator(); +AuthenticatedUserObject authenticatedUserObject = locator(); VitalSignService _vitalSignService = locator(); class BaseAppClient { @@ -50,14 +49,10 @@ class BaseAppClient { //Map profile = await sharedPref.getObj(DOCTOR_PROFILE); var pharmacyToken = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN); var user = await sharedPref.getObject(USER_PROFILE); - Map headers = { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }; + Map headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}; if (!isExternal) { String token = await sharedPref.getString(TOKEN); - var languageID = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); if (body.containsKey('SetupID')) { body['SetupID'] = body.containsKey('SetupID') ? body['SetupID'] != null @@ -68,23 +63,17 @@ class BaseAppClient { body['VersionID'] = VERSION_ID; body['Channel'] = CHANNEL; - body['LanguageID'] = languageID == 'ar' ? 1 : 2; + body['LanguageID'] = (languageID == 'ar' ? 1 : 2); body['IPAdress'] = IP_ADDRESS; body['generalid'] = GENERAL_ID; - body['PatientOutSA'] = body.containsKey('PatientOutSA') - ? body['PatientOutSA'] != null - ? body['PatientOutSA'] - : PATIENT_OUT_SA - : PATIENT_OUT_SA; if (body.containsKey('isDentalAllowedBackend')) { - body['isDentalAllowedBackend'] = - body.containsKey('isDentalAllowedBackend') - ? body['isDentalAllowedBackend'] != null - ? body['isDentalAllowedBackend'] - : IS_DENTAL_ALLOWED_BACKEND - : IS_DENTAL_ALLOWED_BACKEND; + body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') + ? body['isDentalAllowedBackend'] != null + ? body['isDentalAllowedBackend'] + : IS_DENTAL_ALLOWED_BACKEND + : IS_DENTAL_ALLOWED_BACKEND; } body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2; @@ -107,19 +96,20 @@ class BaseAppClient { : PATIENT_TYPE_ID; if (user != null) { body['TokenID'] = token; - body['PatientID'] = body['PatientID'] != null - ? body['PatientID'] - : user['PatientID']; + body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID']; body['PatientOutSA'] = user['OutSA']; + body['PatientOutSA'] = body.containsKey('PatientOutSA') + ? body['PatientOutSA'] != null + ? body['PatientOutSA'] + : PATIENT_OUT_SA + : PATIENT_OUT_SA; body['SessionID'] = SESSION_ID; //getSe + headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': pharmacyToken, - 'Mobilenumber': user != null - ? Utils.getPhoneNumberWithoutZero( - user['MobileNumber'].toString()) - : "", + 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "", 'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', 'Username': user['PatientID'].toString(), }; @@ -131,8 +121,7 @@ class BaseAppClient { print("Body : ${json.encode(body)}"); if (await Utils.checkConnection()) { - final response = await http.post(url.trim(), - body: json.encode(body), headers: headers); + final response = await http.post(url.trim(), body: json.encode(body), headers: headers); final int statusCode = response.statusCode; print("statusCode :$statusCode"); if (statusCode < 200 || statusCode >= 400 || json == null) { @@ -144,8 +133,7 @@ class BaseAppClient { onSuccess(parsed, statusCode); } else { if (parsed['ErrorType'] == 4) { - navigateToAppUpdate( - AppGlobal.context, parsed['ErrorEndUserMessage']); + navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']); } if (isAllowAny) { onSuccess(parsed, statusCode); @@ -160,34 +148,24 @@ class BaseAppClient { if (parsed != null) { onSuccess(parsed, statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); logout(); } } - } else if (parsed['MessageStatus'] == 1 || - parsed['SMSLoginRequired'] == true) { + } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { onSuccess(parsed, statusCode); - } else if (parsed['MessageStatus'] == 2 && - parsed['IsAuthenticated']) { + } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) { if (parsed['SameClinicApptList'] != null) { onSuccess(parsed, statusCode); } else { - if (parsed['message'] == null && - parsed['ErrorEndUserMessage'] == null) { + if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { if (parsed['ErrorSearchMsg'] == null) { - onFailure("Server Error found with no available message", - statusCode); + onFailure("Server Error found with no available message", statusCode); } else { onFailure(parsed['ErrorSearchMsg'], statusCode); } } else { - onFailure( - parsed['message'] ?? - parsed['ErrorEndUserMessage'] ?? - parsed['ErrorMessage'], - statusCode); + onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } } else if (!parsed['IsAuthenticated']) { @@ -201,9 +179,7 @@ class BaseAppClient { if (parsed['message'] != null) { onFailure(parsed['message'] ?? parsed['message'], statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } } @@ -240,16 +216,13 @@ class BaseAppClient { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': token ?? '', - 'Mobilenumber': user != null - ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) - : "", + 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "", 'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', 'Username': user != null ? user['PatientID'].toString() : "", }; if (!isExternal) { String token = await sharedPref.getString(TOKEN); - var languageID = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); if (body.containsKey('SetupID')) { body['SetupID'] = body.containsKey('SetupID') ? body['SetupID'] != null @@ -271,12 +244,11 @@ class BaseAppClient { : PATIENT_OUT_SA; if (body.containsKey('isDentalAllowedBackend')) { - body['isDentalAllowedBackend'] = - body.containsKey('isDentalAllowedBackend') - ? body['isDentalAllowedBackend'] != null - ? body['isDentalAllowedBackend'] - : IS_DENTAL_ALLOWED_BACKEND - : IS_DENTAL_ALLOWED_BACKEND; + body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') + ? body['isDentalAllowedBackend'] != null + ? body['isDentalAllowedBackend'] + : IS_DENTAL_ALLOWED_BACKEND + : IS_DENTAL_ALLOWED_BACKEND; } body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2; @@ -299,9 +271,7 @@ class BaseAppClient { : PATIENT_TYPE_ID; if (user != null) { body['TokenID'] = token; - body['PatientID'] = body['PatientID'] != null - ? body['PatientID'] - : user['PatientID']; + body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID']; body['PatientOutSA'] = user['OutSA']; body['SessionID'] = SESSION_ID; //getSe headers = { @@ -320,8 +290,7 @@ class BaseAppClient { print("Body : ${json.encode(body)}"); if (await Utils.checkConnection()) { - final response = await http.post(url.trim(), - body: json.encode(body), headers: headers); + final response = await http.post(url.trim(), body: json.encode(body), headers: headers); final int statusCode = response.statusCode; print("statusCode :$statusCode"); if (statusCode < 200 || statusCode >= 400 || json == null) { @@ -333,8 +302,7 @@ class BaseAppClient { onSuccess(parsed, statusCode); } else { if (parsed['ErrorType'] == 4) { - navigateToAppUpdate( - AppGlobal.context, parsed['ErrorEndUserMessage']); + navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']); } if (isAllowAny) { onSuccess(parsed, statusCode); @@ -349,34 +317,24 @@ class BaseAppClient { if (parsed != null) { onSuccess(parsed, statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); logout(); } } - } else if (parsed['MessageStatus'] == 1 || - parsed['SMSLoginRequired'] == true) { + } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { onSuccess(parsed, statusCode); - } else if (parsed['MessageStatus'] == 2 && - parsed['IsAuthenticated']) { + } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) { if (parsed['SameClinicApptList'] != null) { onSuccess(parsed, statusCode); } else { - if (parsed['message'] == null && - parsed['ErrorEndUserMessage'] == null) { + if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { if (parsed['ErrorSearchMsg'] == null) { - onFailure("Server Error found with no available message", - statusCode); + onFailure("Server Error found with no available message", statusCode); } else { onFailure(parsed['ErrorSearchMsg'], statusCode); } } else { - onFailure( - parsed['message'] ?? - parsed['ErrorEndUserMessage'] ?? - parsed['ErrorMessage'], - statusCode); + onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } } else if (!parsed['IsAuthenticated']) { @@ -390,9 +348,7 @@ class BaseAppClient { if (parsed['message'] != null) { onFailure(parsed['message'] ?? parsed['message'], statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } } @@ -408,8 +364,7 @@ class BaseAppClient { } Future navigateToAppUpdate(context, String text) async { - Navigator.pushReplacement( - context, FadePage(page: AppUpdatePage(appUpdateText: text))); + Navigator.pushReplacement(context, FadePage(page: AppUpdatePage(appUpdateText: text))); } get(String endPoint, @@ -433,10 +388,7 @@ class BaseAppClient { if (await Utils.checkConnection()) { final response = await http.get( url.trim(), - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, ); final int statusCode = response.statusCode; print("statusCode :$statusCode"); @@ -480,9 +432,7 @@ class BaseAppClient { 'Content-Type': 'text/html; charset=utf-8', 'Accept': 'application/json', 'Authorization': token ?? '', - 'Mobilenumber': user != null - ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) - : "", + 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "", 'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', 'Username': user != null ? user['PatientID'].toString() : "", }); @@ -491,8 +441,7 @@ class BaseAppClient { if (statusCode < 200 || statusCode >= 400 || json == null) { if (statusCode == 401) { - AppToast.showErrorToast( - message: TranslationBase.of(AppGlobal.context).pharmacyRelogin); + AppToast.showErrorToast(message: TranslationBase.of(AppGlobal.context).pharmacyRelogin); Navigator.of(AppGlobal.context).pushNamed(HOME); } else { onFailure('Error While Fetching data', statusCode); @@ -520,10 +469,7 @@ class BaseAppClient { final response = await http.post( url.trim(), body: json.encode(body), - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, ); final int statusCode = response.statusCode; @@ -556,10 +502,7 @@ class BaseAppClient { if (await Utils.checkConnection()) { final response = await http.get( url.trim(), - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, ); final int statusCode = response.statusCode; @@ -586,10 +529,7 @@ class BaseAppClient { final response = await http.put( url.trim(), body: json.encode(body), - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, ); final int statusCode = response.statusCode; @@ -622,10 +562,7 @@ class BaseAppClient { if (await Utils.checkConnection()) { final response = await http.delete( url.trim(), - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, ); final int statusCode = response.statusCode; @@ -645,10 +582,8 @@ class BaseAppClient { await sharedPref.remove(LOGIN_TOKEN_ID); await sharedPref.remove(PHARMACY_CUSTOMER_ID); await authenticatedUserObject.getUser(); - Provider.of(AppGlobal.context, listen: false).isLogin = - false; - var model = - Provider.of(AppGlobal.context, listen: false); + Provider.of(AppGlobal.context, listen: false).isLogin = false; + var model = Provider.of(AppGlobal.context, listen: false); _vitalSignService.weightKg = ""; _vitalSignService.heightCm = ""; model.setState(0, false); @@ -662,8 +597,7 @@ class BaseAppClient { static defaultHttpParameters() async { String token = await sharedPref.getString(TOKEN); - var languageID = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); var user = await sharedPref.getObject(USER_PROFILE); var params = {}; if (user != null) { @@ -699,8 +633,7 @@ class BaseAppClient { try { if (isExternal) { String token = await sharedPref.getString(TOKEN); - var languageID = - await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); var user = await sharedPref.getObject(USER_PROFILE); if (body.containsKey('SetupID')) { body['SetupID'] = body.containsKey('SetupID') @@ -723,12 +656,11 @@ class BaseAppClient { : PATIENT_OUT_SA; if (body.containsKey('isDentalAllowedBackend')) { - body['isDentalAllowedBackend'] = - body.containsKey('isDentalAllowedBackend') - ? body['isDentalAllowedBackend'] != null - ? body['isDentalAllowedBackend'] - : IS_DENTAL_ALLOWED_BACKEND - : IS_DENTAL_ALLOWED_BACKEND; + body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') + ? body['isDentalAllowedBackend'] != null + ? body['isDentalAllowedBackend'] + : IS_DENTAL_ALLOWED_BACKEND + : IS_DENTAL_ALLOWED_BACKEND; } body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2; @@ -751,9 +683,7 @@ class BaseAppClient { : PATIENT_TYPE_ID; if (user != null) { body['TokenID'] = token; - body['PatientID'] = body['PatientID'] != null - ? body['PatientID'] - : user['PatientID']; + body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID']; body['PatientOutSA'] = user['OutSA']; body['SessionID'] = SESSION_ID; //getSessionId(token); } @@ -765,17 +695,14 @@ class BaseAppClient { var ss = json.encode(body); if (await Utils.checkConnection()) { - final response = - await http.post(url.trim(), body: json.encode(body), headers: { + final response = await http.post(url.trim(), body: json.encode(body), headers: { // 'Content-Type': 'application/json', // 'Accept': 'application/json', // 'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': token ?? '', - 'Mobilenumber': user != null - ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) - : "", + 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "", 'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', 'Username': user != null ? user['PatientID'].toString() : "", }); @@ -790,8 +717,7 @@ class BaseAppClient { onSuccess(parsed, statusCode); } else { if (parsed['ErrorType'] == 4) { - navigateToAppUpdate( - AppGlobal.context, parsed['ErrorEndUserMessage']); + navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']); } if (isAllowAny) { onSuccess(parsed, statusCode); @@ -806,31 +732,21 @@ class BaseAppClient { if (parsed != null) { onSuccess(parsed, statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); logout(); } } - } else if (parsed['MessageStatus'] == 1 || - parsed['SMSLoginRequired'] == true) { + } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { onSuccess(parsed, statusCode); - } else if (parsed['MessageStatus'] == 2 && - parsed['IsAuthenticated']) { - if (parsed['message'] == null && - parsed['ErrorEndUserMessage'] == null) { + } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) { + if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { if (parsed['ErrorSearchMsg'] == null) { - onFailure("Server Error found with no available message", - statusCode); + onFailure("Server Error found with no available message", statusCode); } else { onFailure(parsed['ErrorSearchMsg'], statusCode); } } else { - onFailure( - parsed['message'] ?? - parsed['ErrorEndUserMessage'] ?? - parsed['ErrorMessage'], - statusCode); + onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } else if (!parsed['IsAuthenticated']) { await logout(); @@ -843,9 +759,7 @@ class BaseAppClient { if (parsed['message'] != null) { onFailure(parsed['message'] ?? parsed['message'], statusCode); } else { - onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode); + onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } } diff --git a/lib/core/service/feedback/feedback_service.dart b/lib/core/service/feedback/feedback_service.dart index 9df5b0a6..9355daf0 100644 --- a/lib/core/service/feedback/feedback_service.dart +++ b/lib/core/service/feedback/feedback_service.dart @@ -6,6 +6,7 @@ import 'package:diplomaticquarterapp/core/model/feedback/request_insert_coc_item import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:diplomaticquarterapp/pages/feedback/appointment_history.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; class FeedbackService extends BaseService { List cOCItemList = List(); @@ -26,7 +27,7 @@ class FeedbackService extends BaseService { _requestInsertCOCItem.details = details; _requestInsertCOCItem.cOCTypeName = cOCTypeName; _requestInsertCOCItem.formTypeID = cOCTypeName; - _requestInsertCOCItem.mobileNo = user.mobileNumber; + _requestInsertCOCItem.mobileNo = "966" + Utils.getPhoneNumberWithoutZero(user.mobileNumber); _requestInsertCOCItem.isUserLoggedIn = true; _requestInsertCOCItem.projectID = user.projectID; _requestInsertCOCItem.patientName = user.firstName + " " + user.lastName; @@ -64,7 +65,7 @@ class FeedbackService extends BaseService { hasError = false; Map body = new Map(); body['IdentificationNo'] = user.patientIdentificationNo; - body['MobileNo'] = user.mobileNumber; + body['MobileNo'] = "966" + Utils.getPhoneNumberWithoutZero(user.mobileNumber); body['Searching_type'] = '1'; await baseAppClient.post(GET_STATUS_FOR_COCO, diff --git a/lib/core/service/insurance_service.dart b/lib/core/service/insurance_service.dart index 0b626342..6eb1f415 100644 --- a/lib/core/service/insurance_service.dart +++ b/lib/core/service/insurance_service.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/insurance/Insurance_card_details.dart'; +import 'package:diplomaticquarterapp/core/model/insurance/ReauestInsuranceApprovalModel.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_approval.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_card.dart'; import 'package:diplomaticquarterapp/core/model/insurance/insurance_card_update_model.dart'; @@ -25,8 +26,7 @@ class InsuranceCardService extends BaseService { List insuranceCardDetailsList = List(); bool isHaveInsuranceCard = false; - GetAllSharedRecordsByStatusResponse getAllSharedRecordsByStatusResponse = - GetAllSharedRecordsByStatusResponse(); + GetAllSharedRecordsByStatusResponse getAllSharedRecordsByStatusResponse = GetAllSharedRecordsByStatusResponse(); clearInsuranceCard() { _cardList.clear(); @@ -36,19 +36,12 @@ class InsuranceCardService extends BaseService { _cardUpdated.clear(); } - - InsuranceApprovalModel _insuranceApprovalModel = InsuranceApprovalModel( - isDentalAllowedBackend: false, - patientTypeID: 1, - patientType: 1, - eXuldAPPNO: 0, - projectID: 0); + RequestInsuranceApprovalModel _requestInsuranceApprovalModel = RequestInsuranceApprovalModel(isDentalAllowedBackend: false, patientTypeID: 1, patientType: 1, eXuldAPPNO: 0, projectID: 0); Future getInsurance() async { hasError = false; _cardList.clear(); - await baseAppClient.post(GET_PAtIENTS_INSURANCE, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_PAtIENTS_INSURANCE, onSuccess: (dynamic response, int statusCode) { response['List_PatientInsuranceCard'].forEach((item) { _cardList.add(InsuranceCardModel.fromJson(item)); }); @@ -60,10 +53,9 @@ class InsuranceCardService extends BaseService { Future getInsuranceUpdate() async { hasError = false; - _cardList.clear(); - await baseAppClient.post(GET_PAtIENTS_INSURANCE_UPDATED, - onSuccess: (dynamic response, int statusCode) { - _cardUpdated.clear(); + _cardList.clear(); + await baseAppClient.post(GET_PAtIENTS_INSURANCE_UPDATED, onSuccess: (dynamic response, int statusCode) { + _cardUpdated.clear(); response['List_PatientInsuranceCardHistory'].forEach((item) { _cardUpdated.add(InsuranceUpdateModel.fromJson(item)); }); @@ -77,17 +69,16 @@ class InsuranceCardService extends BaseService { hasError = false; // _cardList.clear(); if (appointmentNo != null) { - _insuranceApprovalModel.appointmentNo = appointmentNo; - _insuranceApprovalModel.eXuldAPPNO = null; - _insuranceApprovalModel.projectID = null; + // _requestInsuranceApprovalModel.appointmentNo = appointmentNo; + _requestInsuranceApprovalModel.eXuldAPPNO = null; + _requestInsuranceApprovalModel.projectID = null; } else { - _insuranceApprovalModel.appointmentNo = null; - _insuranceApprovalModel.eXuldAPPNO = 0; - _insuranceApprovalModel.projectID = 0; + // _requestInsuranceApprovalModel.appointmentNo = null; + _requestInsuranceApprovalModel.eXuldAPPNO = 0; + _requestInsuranceApprovalModel.projectID = 0; } - await baseAppClient.post(GET_PAtIENTS_INSURANCE_APPROVALS, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_PAtIENTS_INSURANCE_APPROVALS, onSuccess: (dynamic response, int statusCode) { print(response['HIS_Approval_List'].length); _insuranceApproval.clear(); _insuranceApproval.length = 0; @@ -97,14 +88,13 @@ class InsuranceCardService extends BaseService { }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; - }, body: _insuranceApprovalModel.toJson()); + }, body: _requestInsuranceApprovalModel.toJson()); } Future getFamilyFiles() async { var myFamily = await sharedPref.getObject(FAMILY_FILE); if (myFamily != null) { - getAllSharedRecordsByStatusResponse = - GetAllSharedRecordsByStatusResponse.fromJson(myFamily); + getAllSharedRecordsByStatusResponse = GetAllSharedRecordsByStatusResponse.fromJson(myFamily); } else { getSharedRecordByStatus(); } @@ -115,68 +105,75 @@ class InsuranceCardService extends BaseService { dynamic localRes; var request = GetAllSharedRecordsByStatusReq(); request.status = 0; - await baseAppClient.post(GET_SHARED_RECORD_BY_STATUS, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_SHARED_RECORD_BY_STATUS, onSuccess: (dynamic response, int statusCode) { localRes = response; }, onFailure: (String error, int statusCode) { AppToast.showErrorToast(message: error); throw error; }, body: request.toJson()); sharedPref.setObject(FAMILY_FILE, localRes); - getAllSharedRecordsByStatusResponse = - GetAllSharedRecordsByStatusResponse.fromJson(localRes); + getAllSharedRecordsByStatusResponse = GetAllSharedRecordsByStatusResponse.fromJson(localRes); } catch (error) { print(error); throw error; } } - Future getInsuranceDetails(data) async{ + + Future getInsuranceDetails(data) async { dynamic localRes; - await baseAppClient.post(INSURANCE_DETAILS, - onSuccess: (dynamic response, int statusCode) { - localRes = response['List_InsuranceCheckList']; - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body:{'CompanyID': data.companyID,'SubCategoryID':data.subCategoryID },); + await baseAppClient.post( + INSURANCE_DETAILS, + onSuccess: (dynamic response, int statusCode) { + localRes = response['List_InsuranceCheckList']; + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + body: {'CompanyID': data.companyID, 'SubCategoryID': data.subCategoryID}, + ); return Future.value(localRes); } - Future getPatientInsuranceDetails({String setupID, int projectID, String patientIdentificationID,int patientID}) async{ + Future getPatientInsuranceDetails({String setupID, int projectID, String patientIdentificationID, int patientID}) async { error = ""; hasError = false; insuranceCardDetails = null; isHaveInsuranceCard = false; - await baseAppClient.post(GET_PATIENT_INSURANCE_DETAILS, - onSuccess: (dynamic response, int statusCode) { - insuranceCardDetailsList.clear(); - isHaveInsuranceCard = true; - response['List_PatientInsuranceDetails'].forEach((item) { - insuranceCardDetailsList.add(InsuranceCardDetailsModel.fromJson(item)); - }); - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body:{'SetupID': setupID,'ProjectID':projectID,'PatientIdentificationID':patientIdentificationID ,'isDentalAllowedBackend':false,'PatientID':patientID},); - + await baseAppClient.post( + GET_PATIENT_INSURANCE_DETAILS, + onSuccess: (dynamic response, int statusCode) { + insuranceCardDetailsList.clear(); + isHaveInsuranceCard = true; + response['List_PatientInsuranceDetails'].forEach((item) { + insuranceCardDetailsList.add(InsuranceCardDetailsModel.fromJson(item)); + }); + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + body: {'SetupID': setupID, 'ProjectID': projectID, 'PatientIdentificationID': patientIdentificationID, 'isDentalAllowedBackend': false, 'PatientID': patientID}, + ); } - Future uploadInsuranceCard({ String patientIdentificationID,int patientID,String image=""}) async{ + Future uploadInsuranceCard({String patientIdentificationID, int patientID, String image = ""}) async { error = ""; - Map body = Map(); - body['PatientID']=patientID; - body['PatientType']=user.patientType; - body['MobileNo']=user.mobileNumber; - body['PatientIdentificationID']=patientIdentificationID; - body['InsuranceCardImage']= image; - - await baseAppClient.post(UPLOAD_INSURANCE_CARD, - onSuccess: (dynamic response, int statusCode) { - - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body:body,); - + Map body = Map(); + body['PatientID'] = patientID; + body['PatientType'] = user.patientType; + body['MobileNo'] = user.mobileNumber; + body['PatientIdentificationID'] = patientIdentificationID; + body['InsuranceCardImage'] = image; + + await baseAppClient.post( + UPLOAD_INSURANCE_CARD, + onSuccess: (dynamic response, int statusCode) {}, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, + body: body, + ); } } diff --git a/lib/core/service/medical/BloodPressureService.dart b/lib/core/service/medical/BloodPressureService.dart index 82130750..7a849808 100644 --- a/lib/core/service/medical/BloodPressureService.dart +++ b/lib/core/service/medical/BloodPressureService.dart @@ -73,7 +73,7 @@ class BloodPressureService extends BaseService { super.error = ""; Map body = Map(); body['isDentalAllowedBackend'] = false; - body['to'] = user.emailAddress; + body['To'] = user.emailAddress; await baseAppClient.post(SEND_AVERAGE_BLOOD_PRESSURE_REPORT, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { diff --git a/lib/core/service/medical/BloodSugarService.dart b/lib/core/service/medical/BloodSugarService.dart index e8e2fabf..4de444ea 100644 --- a/lib/core/service/medical/BloodSugarService.dart +++ b/lib/core/service/medical/BloodSugarService.dart @@ -114,7 +114,7 @@ class BloodSugarService extends BaseService { super.error = ""; Map body = Map(); body['isDentalAllowedBackend'] = false; - body['to'] = user.emailAddress; + body['To'] = user.emailAddress; await baseAppClient.post(SEND_AVERAGE_BLOOD_SUGAR_REPORT, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { diff --git a/lib/core/service/medical/WeightPressureService.dart b/lib/core/service/medical/WeightPressureService.dart index b48c4795..6d150c28 100644 --- a/lib/core/service/medical/WeightPressureService.dart +++ b/lib/core/service/medical/WeightPressureService.dart @@ -7,12 +7,9 @@ import 'package:diplomaticquarterapp/core/service/base_service.dart'; class WeightService extends BaseService { ///Average - List - monthWeightMeasurementResultAverage = List(); - List weekWeightMeasurementResultAverage = - List(); - List yearWeightMeasurementResultAverage = - List(); + List monthWeightMeasurementResultAverage = List(); + List weekWeightMeasurementResultAverage = List(); + List yearWeightMeasurementResultAverage = List(); ///Result List monthWeightMeasurementResult = List(); @@ -23,24 +20,20 @@ class WeightService extends BaseService { hasError = false; Map body = Map(); body['isDentalAllowedBackend'] = false; - await baseAppClient.post(GET_WEIGHT_PRESSURE_RESULT_AVERAGE, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_WEIGHT_PRESSURE_RESULT_AVERAGE, onSuccess: (dynamic response, int statusCode) { monthWeightMeasurementResultAverage.clear(); weekWeightMeasurementResultAverage.clear(); yearWeightMeasurementResultAverage.clear(); response['List_MonthWeightMeasurementResultAverage'].forEach((item) { - monthWeightMeasurementResultAverage - .add(MonthWeightMeasurementResultAverage.fromJson(item)); + monthWeightMeasurementResultAverage.add(MonthWeightMeasurementResultAverage.fromJson(item)); }); response['List_WeekWeightMeasurementResultAverage'].forEach((item) { - weekWeightMeasurementResultAverage - .add(WeekWeightMeasurementResultAverage.fromJson(item)); + weekWeightMeasurementResultAverage.add(WeekWeightMeasurementResultAverage.fromJson(item)); }); response['List_YearWeightMeasurementResultAverage'].forEach((item) { - yearWeightMeasurementResultAverage - .add(YearWeightMeasurementResultAverage.fromJson(item)); + yearWeightMeasurementResultAverage.add(YearWeightMeasurementResultAverage.fromJson(item)); }); }, onFailure: (String error, int statusCode) { hasError = true; @@ -50,8 +43,7 @@ class WeightService extends BaseService { Future getWeightMeasurementResult() async { hasError = false; - await baseAppClient.post(GET_WEIGHT_PRESSURE_RESULT, - onSuccess: (dynamic response, int statusCode) { + await baseAppClient.post(GET_WEIGHT_PRESSURE_RESULT, onSuccess: (dynamic response, int statusCode) { monthWeightMeasurementResult.clear(); weekWeightMeasurementResult.clear(); yearWeightMeasurementResult.clear(); @@ -61,8 +53,7 @@ class WeightService extends BaseService { }); response['List_MonthWeightMeasurementResult'].forEach((item) { - monthWeightMeasurementResult - .add(WeightMeasurementResult.fromJson(item)); + monthWeightMeasurementResult.add(WeightMeasurementResult.fromJson(item)); }); response['List_YearWeightMeasurementResult'].forEach((item) { @@ -74,8 +65,7 @@ class WeightService extends BaseService { }, body: Map()); } - addWeightResult( - {String weightDate, String weightMeasured, int weightUnit}) async { + addWeightResult({String weightDate, String weightMeasured, int weightUnit}) async { hasError = false; super.error = ""; @@ -85,15 +75,14 @@ class WeightService extends BaseService { body['weightUnit'] = weightUnit; body['isDentalAllowedBackend'] = false; - await baseAppClient.post(ADD_WEIGHT_PRESSURE_RESULT, - onSuccess: (response, statusCode) async {}, + await baseAppClient.post(ADD_WEIGHT_PRESSURE_RESULT, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: body); } - updateWeightResult({int lineItemNo, int weightUnit,String weightMeasured,String weightDate}) async { + updateWeightResult({int lineItemNo, int weightUnit, String weightMeasured, String weightDate}) async { hasError = false; super.error = ""; Map body = Map(); @@ -103,36 +92,36 @@ class WeightService extends BaseService { body['WeightDate'] = weightDate; body['isDentalAllowedBackend'] = false; - await baseAppClient.post(UPDATE_WEIGHT_PRESSURE_RESULT, - onSuccess: (response, statusCode) async {}, + await baseAppClient.post(UPDATE_WEIGHT_PRESSURE_RESULT, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: body); } + Future sendReportByEmail() async { hasError = false; super.error = ""; Map body = Map(); body['isDentalAllowedBackend'] = false; body['to'] = user.emailAddress; - await baseAppClient.post(SEND_AVERAGE_BLOOD_WEIGHT_REPORT, - onSuccess: (response, statusCode) async {}, + await baseAppClient.post(SEND_AVERAGE_BLOOD_WEIGHT_REPORT, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: body); + hasError = true; + super.error = error; + }, body: body); } - deleteWeightResult({int lineItemNo, }) async { + deleteWeightResult({ + int lineItemNo, + }) async { hasError = false; super.error = ""; Map body = Map(); body['LineItemNo'] = lineItemNo; body['isDentalAllowedBackend'] = false; - await baseAppClient.post(DEACTIVATE_WEIGHT_PRESSURE_RESULT, - onSuccess: (response, statusCode) async {}, + await baseAppClient.post(DEACTIVATE_WEIGHT_PRESSURE_RESULT, onSuccess: (response, statusCode) async {}, onFailure: (String error, int statusCode) { hasError = true; super.error = error; diff --git a/lib/core/service/medical/prescriptions_service.dart b/lib/core/service/medical/prescriptions_service.dart index e9741a7f..af34f2ba 100644 --- a/lib/core/service/medical/prescriptions_service.dart +++ b/lib/core/service/medical/prescriptions_service.dart @@ -2,6 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/Prescriptions.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/perscription_pharmacy.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report.dart'; +import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_inp.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_enh.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescriptions_order.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/request_get_list_pharmacy_for_prescriptions.dart'; @@ -15,7 +16,7 @@ import 'package:flutter/cupertino.dart'; class PrescriptionsService extends BaseService { List prescriptionsList = List(); - + List prescriptionReportListINP = List(); List prescriptionsOrderList = List(); Future getPrescriptions() async { @@ -56,32 +57,40 @@ class PrescriptionsService extends BaseService { appointmentNo: 0, isDentalAllowedBackend: false); List prescriptionReportList = List(); - Future getPrescriptionReport( - {Prescriptions prescriptions}) async { + Future getPrescriptionReport({Prescriptions prescriptions}) async { hasError = false; - _requestPrescriptionReport.dischargeNo = prescriptions.dischargeNo; + if (prescriptions.isInOutPatient == false) { + _requestPrescriptionReport.dischargeNo = prescriptions.dischargeNo; + } else { + _requestPrescriptionReport.dischargeNo = 0; + } _requestPrescriptionReport.projectID = prescriptions.projectID; _requestPrescriptionReport.clinicID = prescriptions.clinicID; _requestPrescriptionReport.setupID = prescriptions.setupID; _requestPrescriptionReport.episodeID = prescriptions.episodeID; _requestPrescriptionReport.appointmentNo = prescriptions.appointmentNo; - await baseAppClient.post(prescriptions.isInOutPatient? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT, + await baseAppClient.post( + prescriptions.isInOutPatient + ? GET_PRESCRIPTION_REPORT_ENH + : GET_PRESCRIPTION_REPORT, onSuccess: (dynamic response, int statusCode) { prescriptionReportList.clear(); prescriptionReportEnhList.clear(); - if(prescriptions.isInOutPatient){ + if (prescriptions.isInOutPatient) { response['ListPRM'].forEach((prescriptions) { - prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions)); - prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions)); + prescriptionReportList + .add(PrescriptionReport.fromJson(prescriptions)); + prescriptionReportEnhList + .add(PrescriptionReportEnh.fromJson(prescriptions)); }); - }else{ + } else { + prescriptionReportListINP.clear(); response['INP_GetPrescriptionReport_List'].forEach((prescriptions) { - prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions)); + prescriptionReportListINP + .add(PrescriptionReportINP.fromJson(prescriptions)); }); } - - }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; @@ -90,35 +99,42 @@ class PrescriptionsService extends BaseService { RequestSendPrescriptionEmail _requestSendPrescriptionEmail = RequestSendPrescriptionEmail( - isDentalAllowedBackend: false,); + isDentalAllowedBackend: false, + ); Future sendPrescriptionEmail(String appointmentDate, int patientID, - String clinicName, String doctorName, int projectID) async { + String clinicName, String doctorName, int doctorID, int projectID) async { _requestSendPrescriptionEmail.listPrescriptions = prescriptionReportList; _requestSendPrescriptionEmail.appointmentDate = appointmentDate; _requestSendPrescriptionEmail.patientID = patientID; _requestSendPrescriptionEmail.clinicName = clinicName; _requestSendPrescriptionEmail.doctorName = doctorName; _requestSendPrescriptionEmail.projectID = projectID; - _requestSendPrescriptionEmail.to = user.emailAddress; - _requestSendPrescriptionEmail.dateofBirth = user.dateofBirth; - _requestSendPrescriptionEmail.patientIditificationNum = user.patientIdentificationNo; - _requestSendPrescriptionEmail.patientMobileNumber = user.mobileNumber; - _requestSendPrescriptionEmail.patientName = user.firstName +" "+ user.lastName; - _requestSendPrescriptionEmail.setupID = user.setupID; + _requestSendPrescriptionEmail.to = user.emailAddress; + _requestSendPrescriptionEmail.dateofBirth = user.dateofBirth; + _requestSendPrescriptionEmail.patientIditificationNum = + user.patientIdentificationNo; + _requestSendPrescriptionEmail.patientMobileNumber = user.mobileNumber; + _requestSendPrescriptionEmail.doctorID = doctorID; + _requestSendPrescriptionEmail.patientName = + user.firstName + " " + user.lastName; + _requestSendPrescriptionEmail.setupID = user.setupID; + _requestSendPrescriptionEmail.to = user.emailAddress; hasError = false; - await baseAppClient.post(SEND_PRESCRIPTION_EMAIL, onSuccess: (response, statusCode) {}, + await baseAppClient + .post(SEND_PRESCRIPTION_EMAIL, onSuccess: (response, statusCode) {}, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: _requestSendPrescriptionEmail.toJson()); } - RequestGetListPharmacyForPrescriptions requestGetListPharmacyForPrescriptions = RequestGetListPharmacyForPrescriptions( + RequestGetListPharmacyForPrescriptions + requestGetListPharmacyForPrescriptions = + RequestGetListPharmacyForPrescriptions( latitude: 0, longitude: 0, isDentalAllowedBackend: false, - ); List pharmacyPrescriptionsList = List(); @@ -139,18 +155,19 @@ class PrescriptionsService extends BaseService { } RequestPrescriptionReportEnh _requestPrescriptionReportEnh = - RequestPrescriptionReportEnh(isDentalAllowedBackend: false,); + RequestPrescriptionReportEnh( + isDentalAllowedBackend: false, + ); List prescriptionReportEnhList = List(); - Future getPrescriptionReportEnh({PrescriptionsOrder prescriptionsOrder}) async { - + Future getPrescriptionReportEnh( + {PrescriptionsOrder prescriptionsOrder}) async { ///This logic copy from the old app from class [order-history.component.ts] in line 45 bool isInPatient = false; prescriptionsList.forEach((element) { if (prescriptionsOrder.appointmentNo == "0") { if (element.dischargeNo == int.parse(prescriptionsOrder.dischargeID)) { - _requestPrescriptionReportEnh.appointmentNo = element.appointmentNo; _requestPrescriptionReportEnh.clinicID = element.clinicID; _requestPrescriptionReportEnh.projectID = element.projectID; @@ -160,46 +177,45 @@ class PrescriptionsService extends BaseService { isInPatient = element.isInOutPatient; } } else { - if (int.parse(prescriptionsOrder.appointmentNo) == element.appointmentNo) { + if (int.parse(prescriptionsOrder.appointmentNo) == + element.appointmentNo) { _requestPrescriptionReportEnh.appointmentNo = element.appointmentNo; _requestPrescriptionReportEnh.clinicID = element.clinicID; _requestPrescriptionReportEnh.projectID = element.projectID; _requestPrescriptionReportEnh.episodeID = element.episodeID; _requestPrescriptionReportEnh.setupID = element.setupID; _requestPrescriptionReportEnh.dischargeNo = element.dischargeNo; - isInPatient = element.isInOutPatient;///call inpGetPrescriptionReport + isInPatient = element.isInOutPatient; + + ///call inpGetPrescriptionReport } } }); hasError = false; - await baseAppClient.post(isInPatient? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT, + await baseAppClient.post( + isInPatient ? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT, onSuccess: (dynamic response, int statusCode) { prescriptionReportEnhList.clear(); - if(isInPatient){ + if (isInPatient) { response['ListPRM'].forEach((prescriptions) { - prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions)); + prescriptionReportEnhList + .add(PrescriptionReportEnh.fromJson(prescriptions)); }); - }else{ + } else { response['INP_GetPrescriptionReport_List'].forEach((prescriptions) { - - PrescriptionReportEnh reportEnh = PrescriptionReportEnh.fromJson(prescriptions); - reportEnh.itemDescription = prescriptions['ItemDescriptionN']; + PrescriptionReportEnh reportEnh = + PrescriptionReportEnh.fromJson(prescriptions); + reportEnh.itemDescription = prescriptions['ItemDescriptionN']; prescriptionReportEnhList.add(reportEnh); - }); - } - - }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: _requestPrescriptionReportEnh.toJson()); - - } Future updatePressOrder({@required int presOrderID}) async { @@ -211,12 +227,10 @@ class PrescriptionsService extends BaseService { body['PresOrderStatus'] = 4; body['isDentalAllowedBackend'] = false; await baseAppClient.post(UPDATE_PRESS_ORDER, - onSuccess: (dynamic response, int statusCode) { - - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: body); + onSuccess: (dynamic response, int statusCode) {}, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); } - } diff --git a/lib/core/viewModels/AlHabibMedicalService/H2O_view_model.dart b/lib/core/viewModels/AlHabibMedicalService/H2O_view_model.dart index a89ec799..9d163a27 100644 --- a/lib/core/viewModels/AlHabibMedicalService/H2O_view_model.dart +++ b/lib/core/viewModels/AlHabibMedicalService/H2O_view_model.dart @@ -9,6 +9,7 @@ import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; import 'package:charts_flutter/flutter.dart' as charts; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import '../../../locator.dart'; +import 'dart:math' as math; class H2OViewModel extends BaseViewModel { H2OService _h2OService = locator(); @@ -91,11 +92,21 @@ class H2OViewModel extends BaseViewModel { _h2OService.userProgressForWeekDataList.forEach((UserProgressForWeekDataModel data) { globalData.add(new ChartSeries(data.dayName, data.percentageConsumed)); }); + Iterable minMaxList = globalData.map((e) => e.x).toList(); + int maxValue = minMaxList.isEmpty ? 0 : minMaxList.reduce(math.max); + int minValue = minMaxList.isEmpty ? 0 : minMaxList.reduce(math.min); + + if (maxValue == 0 && minValue == 0) { + maxValue = 1; + minValue = -1; + } return [ new charts.Series( id: 'Global Revenue', domainFn: (ChartSeries sales, _) => sales.y, measureFn: (ChartSeries sales, _) => sales.x, + measureLowerBoundFn: (ChartSeries sales, _) => minValue, + measureUpperBoundFn: (ChartSeries sales, _) => maxValue, data: globalData, ), ]; diff --git a/lib/core/viewModels/AlHabibMedicalService/health-calculator/Bariatrics-viewmodel.dart b/lib/core/viewModels/AlHabibMedicalService/health-calculator/Bariatrics-viewmodel.dart index 5853cc8f..53b39025 100644 --- a/lib/core/viewModels/AlHabibMedicalService/health-calculator/Bariatrics-viewmodel.dart +++ b/lib/core/viewModels/AlHabibMedicalService/health-calculator/Bariatrics-viewmodel.dart @@ -2,8 +2,11 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/ClinicCategory.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/DiseasesByClinic.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/ClinicCategory.dart'; +import 'package:diplomaticquarterapp/core/model/health_calcolator/get_doctor_by_time_model.dart'; +import 'package:diplomaticquarterapp/core/model/health_calcolator/get_doctor_list_calcolation_model.dart'; import 'package:diplomaticquarterapp/core/service/AlHabibMedicalService/health-calculator/bariatrics-service.dart'; import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:flutter/cupertino.dart'; import '../../../../locator.dart'; @@ -13,6 +16,9 @@ class BariatricsViewModel extends BaseViewModel { List get clinicCategoryList => _service.clinicCategoryList; List get diseasesList => _service.diseasesList; + List get doctorList => _service.doctorList; + List get doctorListByTime => _service.doctorListByTime; + List doctorLists = List(); void getClinicCategory() async { setState(ViewState.Busy); @@ -46,4 +52,27 @@ class BariatricsViewModel extends BaseViewModel { setState(ViewState.Idle); } } + + void getDoctorList({@required DiseasesByClinic disease}) async { + setState(ViewState.Busy); + await _service.getDoctorList(disease:disease); + if (_service.hasError) { + error = _service.error; + setState(ViewState.Error); + } else { + { + _service.doctorListByTime.forEach((element) { + List patientLabOrdersClinic = + doctorLists.where((elementClinic) => elementClinic.filterName == element.projectName).toList(); + + if (patientLabOrdersClinic.length != 0) { + doctorLists[doctorLists.indexOf(patientLabOrdersClinic[0])].doctorsByTimeList.add(element); + } else { + doctorLists.add(DoctorsListTime(filterName: element.projectName, doctor: element)); + } + }); + setState(ViewState.Idle); + } + } + } } diff --git a/lib/core/viewModels/er/rrt-view-model.dart b/lib/core/viewModels/er/rrt-view-model.dart new file mode 100644 index 00000000..a0ce7d07 --- /dev/null +++ b/lib/core/viewModels/er/rrt-view-model.dart @@ -0,0 +1,48 @@ + +import 'package:diplomaticquarterapp/core/service/base_service.dart'; + +import '../base_view_model.dart'; + + +class RRTService extends BaseService{ + +} + + +class RRTViewModel extends BaseViewModel{ + var _service = RRTService(); + + Future createRequest(){ + + return null; + } + + + Future getAllRequest(){ + + return null; + } + + + Future getRequestDetails(){ + + return null; + } + + + Future getAllQuestions(){ + + return null; + } + + + Future getCancelReasons(){ + + return null; + } + + Future cancelRequest(){ + + return null; + } +} \ No newline at end of file diff --git a/lib/core/viewModels/medical/blood_pressure_view_model.dart b/lib/core/viewModels/medical/blood_pressure_view_model.dart index ae3abbcb..16a43a6f 100644 --- a/lib/core/viewModels/medical/blood_pressure_view_model.dart +++ b/lib/core/viewModels/medical/blood_pressure_view_model.dart @@ -9,14 +9,11 @@ import '../../../core/viewModels/base_view_model.dart'; class BloodPressureViewMode extends BaseViewModel { BloodPressureService bloodPressureService = locator(); - List get monthDiabtecPatientResult => - bloodPressureService.monthDiabtecPatientResult; + List get monthDiabtecPatientResult => bloodPressureService.monthDiabtecPatientResult; - List get weekDiabtecPatientResult => - bloodPressureService.weekDiabtecPatientResult; + List get weekDiabtecPatientResult => bloodPressureService.weekDiabtecPatientResult; - List get yearDiabtecPatientResult => - bloodPressureService.yearDiabtecPatientResult; + List get yearDiabtecPatientResult => bloodPressureService.yearDiabtecPatientResult; List weightWeekTimeSeriesDataTop = []; List weightWeekTimeSeriesDataLow = []; @@ -37,35 +34,36 @@ class BloodPressureViewMode extends BaseViewModel { } else { clearDate(); bloodPressureService.weekDiabtectResultAverageList.forEach((element) { - weightWeekTimeSeriesDataTop.add(TimeSeriesSales2( - element.bloodPressureDate, - element.dailyDiastolicPressureAverageResult.toDouble())); - weightWeekTimeSeriesDataLow.add(TimeSeriesSales2( - element.bloodPressureDate, - element.dailySystolicePressureAverageResult.toDouble())); + weightWeekTimeSeriesDataTop + .add(TimeSeriesSales2(element.bloodPressureDate, element.dailyDiastolicPressureAverageResult.toDouble())); + weightWeekTimeSeriesDataLow + .add(TimeSeriesSales2(element.bloodPressureDate, element.dailySystolicePressureAverageResult.toDouble())); for (int index = 0; index < bloodPressureService.monthDiabtectResultAverageList.length; index++) { - - weighMonthTimeSeriesDataTop.add(TimeSeriesSales3(index, bloodPressureService.monthDiabtectResultAverageList[index].weekDiastolicPressureAverageResult.toDouble())); - - weighMonthTimeSeriesDataLow.add(TimeSeriesSales3(index, bloodPressureService.monthDiabtectResultAverageList[index].weekSystolicePressureAverageResult.toDouble())); + weighMonthTimeSeriesDataTop.add(TimeSeriesSales3( + index, + bloodPressureService.monthDiabtectResultAverageList[index].weekDiastolicPressureAverageResult + .toDouble())); + + weighMonthTimeSeriesDataLow.add(TimeSeriesSales3( + index, + bloodPressureService.monthDiabtectResultAverageList[index].weekSystolicePressureAverageResult + .toDouble())); } bloodPressureService.yearDiabtecResultAverageList.forEach((element) { - weightYearTimeSeriesDataTop.add(TimeSeriesSales2(element.date, - element.monthSystolicePressureAverageResult.toDouble())); + weightYearTimeSeriesDataTop + .add(TimeSeriesSales2(element.date, element.monthSystolicePressureAverageResult.toDouble())); - weightYearTimeSeriesDataLow.add(TimeSeriesSales2(element.date, - element.monthDiastolicPressureAverageResult.toDouble())); + weightYearTimeSeriesDataLow + .add(TimeSeriesSales2(element.date, element.monthDiastolicPressureAverageResult.toDouble())); }); - }); setState(ViewState.Idle); } } - - void clearDate(){ + void clearDate() { weightWeekTimeSeriesDataTop.clear(); weightWeekTimeSeriesDataLow.clear(); weighMonthTimeSeriesDataTop.clear(); @@ -86,24 +84,25 @@ class BloodPressureViewMode extends BaseViewModel { } } - Future addORUpdateDiabtecResult( + Future addORUpdateDiabtecResult( {String bloodPressureDate, String diastolicPressure, String systolicePressure, - int measuredArm,bool isUpdate = false}) async { + int measuredArm, + bool isUpdate = false}) async { setState(ViewState.BusyLocal); - if(!isUpdate) - await bloodPressureService.addDiabtecResult( - bloodPressureDate: bloodPressureDate, - diastolicPressure: diastolicPressure, - systolicePressure: systolicePressure, - measuredArm: measuredArm); + if (!isUpdate) + await bloodPressureService.addDiabtecResult( + bloodPressureDate: bloodPressureDate, + diastolicPressure: diastolicPressure, + systolicePressure: systolicePressure, + measuredArm: measuredArm); else await bloodPressureService.updateDiabtecResult( - bloodPressureDate: bloodPressureDate, - diastolicPressure: diastolicPressure, - systolicePressure: systolicePressure, - measuredArm: measuredArm); + bloodPressureDate: bloodPressureDate, + diastolicPressure: diastolicPressure, + systolicePressure: systolicePressure, + measuredArm: measuredArm); if (bloodPressureService.hasError) { error = bloodPressureService.error; setState(ViewState.ErrorLocal); @@ -113,7 +112,6 @@ class BloodPressureViewMode extends BaseViewModel { } } - Future deactivateDiabeticStatus({int lineItemNo}) async { setState(ViewState.BusyLocal); diff --git a/lib/core/viewModels/medical/blood_sugar_view_model.dart b/lib/core/viewModels/medical/blood_sugar_view_model.dart index 8a513992..28292311 100644 --- a/lib/core/viewModels/medical/blood_sugar_view_model.dart +++ b/lib/core/viewModels/medical/blood_sugar_view_model.dart @@ -39,6 +39,9 @@ class BloodSugarViewMode extends BaseViewModel { element.dailyAverageResult.toDouble(), )); }); + if (bloodWeekTimeSeriesData.isEmpty) { + bloodWeekTimeSeriesData.add(TimeSeriesSales2(DateTime.now(), 0)); + } for (int index = 0; index < bloodSugarService.monthDiabtectResultAverageList.length; diff --git a/lib/core/viewModels/medical/labs_view_model.dart b/lib/core/viewModels/medical/labs_view_model.dart index 9e3f09e5..f75abe88 100644 --- a/lib/core/viewModels/medical/labs_view_model.dart +++ b/lib/core/viewModels/medical/labs_view_model.dart @@ -16,14 +16,11 @@ class LabsViewModel extends BaseViewModel { List get labOrdersResultsList => _labsService.labOrdersResultsList; - List _patientLabOrdersListClinic = List(); List _patientLabOrdersListHospital = List(); List get patientLabOrdersList => - filterType == FilterType.Clinic - ? _patientLabOrdersListClinic - : _patientLabOrdersListHospital; + filterType == FilterType.Clinic ? _patientLabOrdersListClinic : _patientLabOrdersListHospital; void getLabs() async { if (authenticatedUserObject.isLogin) { @@ -34,41 +31,33 @@ class LabsViewModel extends BaseViewModel { setState(ViewState.Error); } else { _labsService.patientLabOrdersList.forEach((element) { - List patientLabOrdersClinic = - _patientLabOrdersListClinic - .where((elementClinic) => - elementClinic.filterName == element.clinicDescription) - .toList(); + List patientLabOrdersClinic = _patientLabOrdersListClinic + .where((elementClinic) => elementClinic.filterName == element.clinicDescription) + .toList(); if (patientLabOrdersClinic.length != 0) { - _patientLabOrdersListClinic[_patientLabOrdersListClinic - .indexOf(patientLabOrdersClinic[0])] + _patientLabOrdersListClinic[_patientLabOrdersListClinic.indexOf(patientLabOrdersClinic[0])] .patientLabOrdersList .add(element); } else { - _patientLabOrdersListClinic.add(PatientLabOrdersList( - filterName: element.clinicDescription, - patientDoctorAppointment: element)); + _patientLabOrdersListClinic + .add(PatientLabOrdersList(filterName: element.clinicDescription, patientDoctorAppointment: element)); } // doctor list sort via project - List patientLabOrdersHospital = - _patientLabOrdersListHospital - .where( - (elementClinic) => - elementClinic.filterName == element.projectName, - ) - .toList(); + List patientLabOrdersHospital = _patientLabOrdersListHospital + .where( + (elementClinic) => elementClinic.filterName == element.projectName, + ) + .toList(); if (patientLabOrdersHospital.length != 0) { - _patientLabOrdersListHospital[_patientLabOrdersListHospital - .indexOf(patientLabOrdersHospital[0])] + _patientLabOrdersListHospital[_patientLabOrdersListHospital.indexOf(patientLabOrdersHospital[0])] .patientLabOrdersList .add(element); } else { - _patientLabOrdersListHospital.add(PatientLabOrdersList( - filterName: element.projectName, - patientDoctorAppointment: element)); + _patientLabOrdersListHospital + .add(PatientLabOrdersList(filterName: element.projectName, patientDoctorAppointment: element)); } }); @@ -82,24 +71,16 @@ class LabsViewModel extends BaseViewModel { notifyListeners(); } - List get patientLabSpecialResult => - _labsService.patientLabSpecialResult; + List get patientLabSpecialResult => _labsService.patientLabSpecialResult; List get labResultList => _labsService.labResultList; List labResultLists = List(); - getLaboratoryResult( - {String projectID, - int clinicID, - String invoiceNo, - String orderNo}) async { + getLaboratoryResult({String projectID, int clinicID, String invoiceNo, String orderNo}) async { setState(ViewState.Busy); await _labsService.getLaboratoryResult( - invoiceNo: invoiceNo, - orderNo: orderNo, - projectID: projectID, - clinicID: clinicID); + invoiceNo: invoiceNo, orderNo: orderNo, projectID: projectID, clinicID: clinicID); if (_labsService.hasError) { error = _labsService.error; setState(ViewState.Error); @@ -116,14 +97,16 @@ class LabsViewModel extends BaseViewModel { setState(ViewState.Error); } else { _labsService.labResultList.forEach((element) { - List patientLabOrdersClinic = labResultLists.where((elementClinic) => elementClinic.filterName == element.testCode).toList(); + List patientLabOrdersClinic = + labResultLists.where((elementClinic) => elementClinic.filterName == element.testCode).toList(); if (patientLabOrdersClinic.length != 0) { - - var value= labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])].patientLabResultList - .where((e) => e.sampleCollectedOn== element.sampleCollectedOn && e.resultValue ==element.resultValue ).toList(); - if(value.isEmpty) - labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])].patientLabResultList.add(element); + var value = labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])] + .patientLabResultList + .where((e) => e.sampleCollectedOn == element.sampleCollectedOn && e.resultValue == element.resultValue) + .toList(); + if (value.isEmpty) + labResultLists[labResultLists.indexOf(patientLabOrdersClinic[0])].patientLabResultList.add(element); } else { labResultLists.add(LabResultList(filterName: element.testCode, lab: element)); } @@ -132,32 +115,33 @@ class LabsViewModel extends BaseViewModel { } } - - getPatientLabOrdersResults({PatientLabOrders patientLabOrder,String procedure}) async { + getPatientLabOrdersResults({PatientLabOrders patientLabOrder, String procedure}) async { setState(ViewState.Busy); - await _labsService.getPatientLabOrdersResults(patientLabOrder: patientLabOrder,procedure: procedure); + await _labsService.getPatientLabOrdersResults(patientLabOrder: patientLabOrder, procedure: procedure); if (_labsService.hasError) { error = _labsService.error; setState(ViewState.Error); } else { - bool isShouldClear = false; - if(_labsService.labOrdersResultsList.length==1) - { - labOrdersResultsList.forEach((element) { - if(element.resultValue.contains('/') ||element.resultValue.contains('*' )|| element.resultValue.isEmpty ) - isShouldClear = true; - });} - if(isShouldClear) - _labsService.labOrdersResultsList.clear(); + /// commented out based on PAP-304 + // bool isShouldClear = false; + // if (_labsService.labOrdersResultsList.length == 1) { + // labOrdersResultsList.forEach((element) { + // if (element.resultValue.contains('/') || element.resultValue.contains('*') || element.resultValue.isEmpty) + // isShouldClear = true; + // }); + // } + // if (isShouldClear) + // + // _labsService.labOrdersResultsList.clear(); setState(ViewState.Idle); } } - sendLabReportEmail({PatientLabOrders patientLabOrder,String mes}) async { + sendLabReportEmail({PatientLabOrders patientLabOrder, String mes}) async { await _labsService.sendLabReportEmail(patientLabOrder: patientLabOrder); if (_labsService.hasError) { error = _labsService.error; - }else + } else AppToast.showSuccessToast(message: mes); } } diff --git a/lib/core/viewModels/medical/prescriptions_view_model.dart b/lib/core/viewModels/medical/prescriptions_view_model.dart index 2c32a081..3ad9df99 100644 --- a/lib/core/viewModels/medical/prescriptions_view_model.dart +++ b/lib/core/viewModels/medical/prescriptions_view_model.dart @@ -4,7 +4,7 @@ import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_repor import 'package:diplomaticquarterapp/core/model/prescriptions/prescriptions_order.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:flutter/cupertino.dart'; - +import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_inp.dart'; import '../../../core/enum/filter_type.dart'; import '../../../core/enum/viewstate.dart'; import '../../../core/model/prescriptions/Prescriptions.dart'; @@ -19,17 +19,20 @@ class PrescriptionsViewModel extends BaseViewModel { List _prescriptionsOrderListClinic = List(); List _prescriptionsOrderListHospital = List(); - List get prescriptionReportList => _prescriptionsService.prescriptionReportList; + List get prescriptionReportListINP => + _prescriptionsService.prescriptionReportListINP; + List get prescriptionsList => _prescriptionsService.prescriptionsList; - List get prescriptionsHistory => _prescriptionsService.prescriptionsOrderList; - - List get pharmacyPrescriptionsList => _prescriptionsService.pharmacyPrescriptionsList ; + List get prescriptionsHistory => + _prescriptionsService.prescriptionsOrderList; + List get pharmacyPrescriptionsList => + _prescriptionsService.pharmacyPrescriptionsList; List get prescriptionsOrderList => filterType == FilterType.Clinic @@ -105,7 +108,8 @@ class PrescriptionsViewModel extends BaseViewModel { getPrescriptionReport({Prescriptions prescriptions}) async { setState(ViewState.Busy); - await _prescriptionsService.getPrescriptionReport(prescriptions: prescriptions); + await _prescriptionsService.getPrescriptionReport( + prescriptions: prescriptions); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.ErrorLocal); @@ -119,11 +123,12 @@ class PrescriptionsViewModel extends BaseViewModel { int patientID, String clinicName, String doctorName, - String mes, + int doctorID, + String mes, int projectID}) async { setState(ViewState.BusyLocal); - await _prescriptionsService.sendPrescriptionEmail( - appointmentDate, patientID, clinicName, doctorName, projectID); + await _prescriptionsService.sendPrescriptionEmail(appointmentDate, + patientID, clinicName, doctorName, doctorID, projectID); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.ErrorLocal); @@ -145,12 +150,13 @@ class PrescriptionsViewModel extends BaseViewModel { } } - - List get prescriptionReportEnhList => _prescriptionsService.prescriptionReportEnhList; + List get prescriptionReportEnhList => + _prescriptionsService.prescriptionReportEnhList; getPrescriptionReportEnh({PrescriptionsOrder prescriptionsOrder}) async { setState(ViewState.Busy); - await _prescriptionsService.getPrescriptionReportEnh(prescriptionsOrder: prescriptionsOrder); + await _prescriptionsService.getPrescriptionReportEnh( + prescriptionsOrder: prescriptionsOrder); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.Error); @@ -159,16 +165,14 @@ class PrescriptionsViewModel extends BaseViewModel { } } - - Future updatePressOrder({@required int presOrderID}) async { + Future updatePressOrder({@required int presOrderID}) async { setState(ViewState.Busy); await _prescriptionsService.updatePressOrder(presOrderID: presOrderID); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.Error); } else { - await getPrescriptions(); + await getPrescriptions(); } } - } diff --git a/lib/core/viewModels/medical/reports_monthly_view_model.dart b/lib/core/viewModels/medical/reports_monthly_view_model.dart index adb7223e..15ac9219 100644 --- a/lib/core/viewModels/medical/reports_monthly_view_model.dart +++ b/lib/core/viewModels/medical/reports_monthly_view_model.dart @@ -14,6 +14,10 @@ class ReportsMonthlyViewModel extends BaseViewModel { ReportsService _reportsService = locator(); String get userAgreementContent => _reportsService.userAgreementContent; + bool get receiveHealthSummaryReport => _reportsService?.user?.receiveHealthSummaryReport ?? false; + set receiveHealthSummaryReport(bool val) { + _reportsService?.user?.receiveHealthSummaryReport = val; + } getUserTermsAndConditions() async { setState(ViewState.Busy); @@ -26,14 +30,9 @@ class ReportsMonthlyViewModel extends BaseViewModel { } } - updatePatientHealthSummaryReport( - {String message, - bool isSummary, - bool isUpdateEmail = false, - String email}) async { + updatePatientHealthSummaryReport({String message, bool isSummary, bool isUpdateEmail = false, String email}) async { setState(ViewState.BusyLocal); - await _reportsService.updatePatientHealthSummaryReport( - isSummary: isSummary); + await _reportsService.updatePatientHealthSummaryReport(isSummary: isSummary); if (_reportsService.hasError) { error = _reportsService.error; AppToast.showErrorToast(message: error); diff --git a/lib/core/viewModels/medical/weight_pressure_view_model.dart b/lib/core/viewModels/medical/weight_pressure_view_model.dart index 42db0a58..4a01bd3b 100644 --- a/lib/core/viewModels/medical/weight_pressure_view_model.dart +++ b/lib/core/viewModels/medical/weight_pressure_view_model.dart @@ -16,14 +16,11 @@ import '../../../core/viewModels/base_view_model.dart'; class WeightPressureViewModel extends BaseViewModel { WeightService weightService = locator(); - List get monthWeightMeasurementResult => - weightService.monthWeightMeasurementResult; + List get monthWeightMeasurementResult => weightService.monthWeightMeasurementResult; - List get weekWeightMeasurementResult => - weightService.weekWeightMeasurementResult; + List get weekWeightMeasurementResult => weightService.weekWeightMeasurementResult; - List get yearWeightMeasurementResult => - weightService.yearWeightMeasurementResult; + List get yearWeightMeasurementResult => weightService.yearWeightMeasurementResult; List weightWeekTimeSeriesData = []; List weighMonthTimeSeriesData = []; @@ -35,7 +32,7 @@ class WeightPressureViewModel extends BaseViewModel { await weightService.getWeightMeasurementResult(); if (weightService.hasError) { error = weightService.error; - setState(ViewState.Error); + setState(ViewState.ErrorLocal); } else { weightService.weekWeightMeasurementResultAverage.forEach((element) { weightWeekTimeSeriesData.add(TimeSeriesSales2( @@ -44,14 +41,10 @@ class WeightPressureViewModel extends BaseViewModel { )); }); - for (int index = 0; - index < weightService.monthWeightMeasurementResultAverage.length; - index++) { + for (int index = 0; index < weightService.monthWeightMeasurementResultAverage.length; index++) { weighMonthTimeSeriesData.add(TimeSeriesSales3( index, - weightService - .monthWeightMeasurementResultAverage[index].weekAverageResult - .toDouble(), + weightService.monthWeightMeasurementResultAverage[index].weekAverageResult.toDouble(), )); } @@ -66,8 +59,7 @@ class WeightPressureViewModel extends BaseViewModel { } } - addWeightResult( - {String weightDate, String weightMeasured, int weightUnit}) async { + addWeightResult({String weightDate, String weightMeasured, int weightUnit}) async { setState(ViewState.BusyLocal); await weightService.addWeightResult( weightDate: weightDate, @@ -82,6 +74,7 @@ class WeightPressureViewModel extends BaseViewModel { setState(ViewState.Idle); } } + Future sendReportByEmail() async { setState(ViewState.BusyLocal); @@ -94,14 +87,10 @@ class WeightPressureViewModel extends BaseViewModel { } } - updateWeightResult({int lineItemNo, int weightUnit, String weightMeasured,String weightDate}) async { + updateWeightResult({int lineItemNo, int weightUnit, String weightMeasured, String weightDate}) async { setState(ViewState.BusyLocal); await weightService.updateWeightResult( - lineItemNo: lineItemNo, - weightMeasured: weightMeasured, - weightUnit: weightUnit, - weightDate: weightDate - ); + lineItemNo: lineItemNo, weightMeasured: weightMeasured, weightUnit: weightUnit, weightDate: weightDate); if (weightService.hasError) { error = weightService.error; setState(ViewState.Error); @@ -111,7 +100,9 @@ class WeightPressureViewModel extends BaseViewModel { } } - deleteWeightResult({int lineItemNo, }) async { + deleteWeightResult({ + int lineItemNo, + }) async { setState(ViewState.BusyLocal); await weightService.deleteWeightResult( lineItemNo: lineItemNo, diff --git a/lib/core/viewModels/vaccine_view_model.dart b/lib/core/viewModels/vaccine_view_model.dart index 9f8dfecf..37b57da4 100644 --- a/lib/core/viewModels/vaccine_view_model.dart +++ b/lib/core/viewModels/vaccine_view_model.dart @@ -22,7 +22,7 @@ class VaccineViewModel extends BaseViewModel { await _vaccineService.getMyVaccine(); if (_vaccineService.hasError) { error = _vaccineService.error; - setState(ViewState.ErrorLocal); + setState(ViewState.Error); } else setState(ViewState.Idle); } diff --git a/lib/locator.dart b/lib/locator.dart index 1acaf1af..bc8996b5 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -125,6 +125,7 @@ import 'core/viewModels/pharmacyModule/product_detail_view_model.dart'; import 'core/viewModels/pharmacyModule/review_view_model.dart'; import 'core/viewModels/pharmacyModule/wishlist_view_model.dart'; import 'core/viewModels/qr_view_model.dart'; +import 'core/viewModels/er/rrt-view-model.dart'; import 'core/viewModels/vaccine_view_model.dart'; import 'core/service/vaccine_service.dart'; import 'core/viewModels/weather/weather_view_model.dart'; @@ -250,6 +251,7 @@ void setupLocator() { locator.registerFactory(() => QrViewModel()); locator.registerFactory(() => ReportsMonthlyViewModel()); locator.registerFactory(() => NearHospitalViewModel()); + locator.registerFactory(() => RRTViewModel()); locator.registerFactory(() => AmRequestViewModel()); locator.registerFactory(() => PatientSickLeaveViewMode()); locator.registerFactory(() => MyBalanceViewModel()); @@ -304,6 +306,7 @@ void setupLocator() { locator.registerFactory(() => OfferCategoriesViewModel()); // Categories View Model locator.registerFactory(() => PackagesViewModel()); // Products View Model + //pharmacy // locator.registerFactory(() => PharmacyCategoriseViewModel()); // locator.registerFactory(() => OffersCategoriseViewModel()); diff --git a/lib/main.dart b/lib/main.dart index 45fa4c6d..defe0995 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,30 +1,30 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/theme/theme_notifier.dart'; import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/services/robo_search/search_provider.dart'; import 'package:diplomaticquarterapp/theme/theme_value.dart'; -import 'package:diplomaticquarterapp/uitl/HMG_Geofence.dart'; import 'package:diplomaticquarterapp/uitl/LocalNotification.dart'; import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; -import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:firebase_analytics/firebase_analytics.dart'; +import 'package:firebase_analytics/observer.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; - -import 'Constants.dart'; -import 'config/shared_pref_kay.dart'; import 'config/size_config.dart'; -import 'core/model/geofencing/requests/GeoZonesRequestModel.dart'; -import 'core/service/geofencing/GeofencingServices.dart'; import 'core/viewModels/project_view_model.dart'; import 'locator.dart'; import 'pages/pharmacies/compare-list.dart'; +import 'package:firebase_core/firebase_core.dart'; + void main() async { + WidgetsFlutterBinding.ensureInitialized(); + FirebaseApp defaultApp = await Firebase.initializeApp(); + setupLocator(); runApp(MyApp()); } @@ -35,6 +35,7 @@ class MyApp extends StatefulWidget { } class _MyApp extends State { + @override void initState() { // ProjectViewModel projectProvider; @@ -51,6 +52,8 @@ class _MyApp extends State { LocalNotification.getInstance() .showNow(title: "Payload", subtitle: payload, payload: payload); }); + + SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, @@ -85,6 +88,9 @@ class _MyApp extends State { ], child: Consumer( builder: (context, projectProvider, child) => MaterialApp( + navigatorObservers: [ + GAnalytics.shared.navObserver() + ], showSemanticsDebugger: false, title: 'Diplomatic Quarter App', locale: projectProvider.appLocal, diff --git a/lib/models/Authentication/authenticated_user.dart b/lib/models/Authentication/authenticated_user.dart index 4c7974a3..eacba6a5 100644 --- a/lib/models/Authentication/authenticated_user.dart +++ b/lib/models/Authentication/authenticated_user.dart @@ -61,71 +61,72 @@ class AuthenticatedUser { dynamic tempAddress; dynamic zipCode; dynamic isFamily; + dynamic cRSVerificationStatus; // dynamic patientPayType; // dynamic patientType; // dynamic status; - AuthenticatedUser({ - this.setupID, - this.patientType, - this.patientID, - this.firstName, - this.middleName, - this.lastName, - this.firstNameN, - this.middleNameN, - this.lastNameN, - this.relationshipID, - this.gender, - this.dateofBirth, - this.dateofBirthN, - this.nationalityID, - this.phoneResi, - this.phoneOffice, - this.mobileNumber, - this.faxNumber, - this.emailAddress, - this.bloodGroup, - this.rHFactor, - this.isEmailAlertRequired, - this.isSMSAlertRequired, - this.preferredLanguage, - this.isPrivilegedMember, - this.memberID, - this.expiryDate, - this.isHmgEmployee, - this.employeeID, - this.emergencyContactName, - this.emergencyContactNo, - this.patientPayType, - this.dHCCPatientRefID, - this.isPatientDummy, - this.status, - this.isStatusCleared, - this.patientIdentificationType, - this.patientIdentificationNo, - this.projectID, - this.infoSourceID, - this.address, - this.age, - this.ageDesc, - this.areaID, - this.createdBy, - this.genderDescription, - this.iR, - this.iSOCityID, - this.iSOCountryID, - this.listPrivilege, - this.marital, - this.outSA, - this.pOBox, - this.receiveHealthSummaryReport, - this.sourceType, - this.strDateofBirth, - this.tempAddress, - this.zipCode, - this.isFamily - }); + AuthenticatedUser( + {this.setupID, + this.patientType, + this.patientID, + this.firstName, + this.middleName, + this.lastName, + this.firstNameN, + this.middleNameN, + this.lastNameN, + this.relationshipID, + this.gender, + this.dateofBirth, + this.dateofBirthN, + this.nationalityID, + this.phoneResi, + this.phoneOffice, + this.mobileNumber, + this.faxNumber, + this.emailAddress, + this.bloodGroup, + this.rHFactor, + this.isEmailAlertRequired, + this.isSMSAlertRequired, + this.preferredLanguage, + this.isPrivilegedMember, + this.memberID, + this.expiryDate, + this.isHmgEmployee, + this.employeeID, + this.emergencyContactName, + this.emergencyContactNo, + this.patientPayType, + this.dHCCPatientRefID, + this.isPatientDummy, + this.status, + this.isStatusCleared, + this.patientIdentificationType, + this.patientIdentificationNo, + this.projectID, + this.infoSourceID, + this.address, + this.age, + this.ageDesc, + this.areaID, + this.createdBy, + this.genderDescription, + this.iR, + this.iSOCityID, + this.iSOCountryID, + this.listPrivilege, + this.marital, + this.outSA, + this.pOBox, + this.receiveHealthSummaryReport, + this.sourceType, + this.strDateofBirth, + this.tempAddress, + this.zipCode, + this.isFamily, + this.cRSVerificationStatus}); AuthenticatedUser.fromJson(Map json) { setupID = json['SetupID']; @@ -193,6 +194,7 @@ class AuthenticatedUser { tempAddress = json['TempAddress']; zipCode = json['ZipCode']; isFamily = json['IsFamily']; + cRSVerificationStatus = json['CRSVerificationStatus']; } Map toJson() { @@ -259,6 +261,7 @@ class AuthenticatedUser { data['TempAddress'] = this.tempAddress; data['ZipCode'] = this.zipCode; data['IsFamily'] = this.isFamily; + data['CRSVerificationStatus'] = this.cRSVerificationStatus; return data; } } diff --git a/lib/models/CovidDriveThru/CovidTestProceduresResponse.dart b/lib/models/CovidDriveThru/CovidTestProceduresResponse.dart new file mode 100644 index 00000000..c104a1fc --- /dev/null +++ b/lib/models/CovidDriveThru/CovidTestProceduresResponse.dart @@ -0,0 +1,32 @@ +class CovidTestProceduresResponse { + String procedureID; + String procedureName; + String procedureNameN; + int projectID; + String setupID; + + CovidTestProceduresResponse( + {this.procedureID, + this.procedureName, + this.procedureNameN, + this.projectID, + this.setupID}); + + CovidTestProceduresResponse.fromJson(Map json) { + procedureID = json['ProcedureID']; + procedureName = json['ProcedureName']; + procedureNameN = json['ProcedureNameN']; + projectID = json['ProjectID']; + setupID = json['SetupID']; + } + + Map toJson() { + final Map data = new Map(); + data['ProcedureID'] = this.procedureID; + data['ProcedureName'] = this.procedureName; + data['ProcedureNameN'] = this.procedureNameN; + data['ProjectID'] = this.projectID; + data['SetupID'] = this.setupID; + return data; + } +} diff --git a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart index b6cddf18..5a3271f2 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart @@ -292,7 +292,9 @@ class MobileNumberTextFiled extends StatelessWidget { padding: EdgeInsets.all(5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white), - child: Row(children: [ + child: Row( + textDirection: TextDirection.ltr, + children: [ Expanded( flex: 1, child: Icon( diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart index 7a9cd016..4d472a61 100644 --- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart +++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page.dart @@ -17,6 +17,7 @@ import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; import 'package:diplomaticquarterapp/pages/ErService/ErOptions.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/livecare/livecare_home.dart'; import 'package:diplomaticquarterapp/pages/paymentService/payment_service.dart'; import 'package:diplomaticquarterapp/pages/symptom-checker/info.dart'; @@ -263,13 +264,12 @@ class _AllHabibMedicalServiceState extends State { title: TranslationBase.of(context).childVaccine, ), ServicesContainer( - onTap: () => Navigator.push( - context, - FadePage( - page: ToDo(isShowAppBar: true), - ), - ), - imageLocation: 'assets/images/new-design/upcoming_icon_bottom_bar.png', + onTap: (){ + Navigator.pop(context); + LandingPage.shared.switchToDoFromHMGServices(); + }, + imageLocation: + 'assets/images/new-design/upcoming_icon_bottom_bar.png', title: TranslationBase.of(context).todoList, ), if (projectViewModel.havePrivilege(42)) diff --git a/lib/pages/AlHabibMedicalService/h2o/h20_setting.dart b/lib/pages/AlHabibMedicalService/h2o/h20_setting.dart index 4295558a..b8be6539 100644 --- a/lib/pages/AlHabibMedicalService/h2o/h20_setting.dart +++ b/lib/pages/AlHabibMedicalService/h2o/h20_setting.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/H2O/user_detail_model.dart'; import 'package:diplomaticquarterapp/core/service/AlHabibMedicalService/H2O_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; @@ -13,6 +14,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'package:manage_calendar_events/manage_calendar_events.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'Dialog/setting_page_radio_button_list_dialog.dart'; @@ -31,7 +34,7 @@ class _H2oSettingState extends State { TextEditingController _nameController = TextEditingController(); TextEditingController _heightController = TextEditingController(); TextEditingController _weightController = TextEditingController(); - bool _isUnitML = false; + bool _isUnitML = true; bool _isGenderMale = false; bool _isHeightCM = false; bool _isWeightKG = false; @@ -51,16 +54,25 @@ class _H2oSettingState extends State { void initState() { super.initState(); _userDetailModel = widget.userDetailModel; - _heightValue = _userDetailModel.height; - _weightValue = _userDetailModel.weight; + _heightValue = _userDetailModel?.height ?? 100; + _weightValue = _userDetailModel?.weight ?? 50; _heightController.text = _heightValue.toStringAsFixed(0); _weightController.text = _weightValue.toStringAsFixed(0); _nameController.text = _userDetailModel.firstName; - _isWeightKG = _userDetailModel.isWeightInKG; - _isHeightCM = _userDetailModel.isHeightInCM; - _isGenderMale = _userDetailModel.gender == "M" ? true : false; + _isWeightKG = _userDetailModel?.isWeightInKG ?? true; + _isHeightCM = _userDetailModel?.isHeightInCM ?? true; + _isGenderMale = (_userDetailModel?.gender ?? "M") == "M" ? true : false; _dobDate = DateUtil.convertStringToDate(_userDetailModel.dOB); _selectedActiveLevel = _userDetailModel.activityID ?? 1; + readPrefs(); + } + + SharedPreferences prefs; + void readPrefs() async { + prefs = await SharedPreferences.getInstance(); + _isUnitML = (prefs.getString(H2O_UNIT) ?? "ml") == "ml" ? true : false; + _selectedRemindedTime = prefs.getInt(H2O_REMINDER) ?? 0; + setState(() {}); } @override @@ -68,19 +80,9 @@ class _H2oSettingState extends State { // TODO: implement didChangeDependencies super.didChangeDependencies(); - _activityLevelListEng = [ - TranslationBase.of(context).notActive, - TranslationBase.of(context).lightActive, - TranslationBase.of(context).modActive, - TranslationBase.of(context).active - ]; + _activityLevelListEng = [TranslationBase.of(context).notActive, TranslationBase.of(context).lightActive, TranslationBase.of(context).modActive, TranslationBase.of(context).active]; - _remindedTimeListEng = [ - "1 ${TranslationBase.of(context).time}", - "2 ${TranslationBase.of(context).times}", - "3 ${TranslationBase.of(context).times}", - "4 ${TranslationBase.of(context).times}" - ]; + _remindedTimeListEng = ["1 ${TranslationBase.of(context).time}", "2 ${TranslationBase.of(context).times}", "3 ${TranslationBase.of(context).times}", "4 ${TranslationBase.of(context).times}"]; } @override @@ -339,8 +341,7 @@ class _H2oSettingState extends State { ]); } - Widget _commonSlidersRow( - _controller, double _minValue, double _maxValue, double _valueOrg, Function(String) onTextValueChange, Function(double) onValueChange) { + Widget _commonSlidersRow(_controller, double _minValue, double _maxValue, double _valueOrg, Function(String) onTextValueChange, Function(double) onValueChange) { return Container( margin: EdgeInsets.only(top: 6), padding: EdgeInsets.all(6), @@ -451,13 +452,35 @@ class _H2oSettingState extends State { _userDetailModel.dOB = tempDate; _userDetailModel.activityID = _selectedActiveLevel; GifLoaderDialogUtils.showMyDialog(context); - await widget.viewModel.updateUserDetail(_userDetailModel, (tag) { + await widget.viewModel.updateUserDetail(_userDetailModel, (tag) async { if (tag) { AppToast.showSuccessToast(message: TranslationBase.of(context).success); + await prefs.setString(H2O_UNIT, _isUnitML ? "ml" : "l"); + int _tempRemindTime = prefs.getInt(H2O_REMINDER) ?? _selectedRemindedTime; + if (_tempRemindTime != _selectedRemindedTime) { + await prefs.setInt(H2O_REMINDER, _selectedRemindedTime); + _addReminderToCalender(_selectedRemindedTime); + } } GifLoaderDialogUtils.hideDialog(context); }); Navigator.pop(context); } + + final CalendarPlugin _myPlugin = CalendarPlugin(); + void _addReminderToCalender(int _selectedRemindedTime) async { + bool _calendarPermission = await _myPlugin.hasPermissions(); + if (_calendarPermission) { + } else { + await _myPlugin.requestPermissions(); + } + _myPlugin.hasPermissions().then((value) { + if (!value) { + _myPlugin.requestPermissions(); + } else { + _myPlugin.getCalendars().then((value) => {print(value.length)}); + } + }); + } } diff --git a/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart b/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart index b4d39682..b847190f 100644 --- a/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart +++ b/lib/pages/AlHabibMedicalService/h2o/h2o_page.dart @@ -1,12 +1,18 @@ import 'dart:ui'; +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/h20_setting.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/month_page.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/today_page.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/week_page.dart'; +import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; +import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/medical/medical_profile_page.dart'; +import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/bottom_navigation/bottom_nav_bar.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; @@ -18,14 +24,16 @@ class H2OPage extends StatefulWidget { _H2OPageState createState() => _H2OPageState(); } -class _H2OPageState extends State - with SingleTickerProviderStateMixin { +class _H2OPageState extends State with SingleTickerProviderStateMixin { TabController _tabController; @override void initState() { super.initState(); - _tabController = TabController(length: 3, vsync: this,); + _tabController = TabController( + length: 3, + vsync: this, + ); } @override @@ -43,6 +51,7 @@ class _H2OPageState extends State appBarTitle: TranslationBase.of(context).waterTracker, showHomeAppBarIcon: false, baseViewModel: model, + isHelp: true, appBarIcons: [ IconButton( icon: Image.asset("assets/images/new-design/setting_gear_icon.png"), @@ -129,6 +138,39 @@ class _H2OPageState extends State ) ], ), + bottomNavigationBar: BottomNavBar( + changeIndex: (index) { + if (index == 0) { + IS_VOICE_COMMAND_CLOSED = false; + } else if (index == 1) { + Navigator.push( + context, + FadePage( + page: AppScaffold( + appBarTitle: TranslationBase.of(context).medicalProfile, + isShowAppBar: true, + showHomeAppBarIcon: false, + appBarIcons: [ + IconButton( + icon: Image.asset("assets/images/new-design/setting_gear_icon.png"), + color: Colors.white, + onPressed: () => Navigator.of(context).pushNamed( + SETTINGS, + ), + ), + ], + body: MedicalProfilePage()))); + } else if (index == 2) { + Navigator.of(context).pushNamedAndRemoveUntil(HOME, (Route route) => false); + } else if (index == 3) { + Navigator.of(context).pushNamed(MY_FAMILIY); + } else if (index == 4) { + Navigator.push(context, FadePage(page: ToDo(isShowAppBar: false))); + } + }, + showHomeIcon: true, + index: 0, + ), ), ), ); diff --git a/lib/pages/AlHabibMedicalService/h2o/month_page.dart b/lib/pages/AlHabibMedicalService/h2o/month_page.dart index e0118495..8867fb77 100644 --- a/lib/pages/AlHabibMedicalService/h2o/month_page.dart +++ b/lib/pages/AlHabibMedicalService/h2o/month_page.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/charts/app_bar_chart.dart'; @@ -8,15 +9,17 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_circular_progress_Indeicator.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MonthPage extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getUserProgressForMonthData(), builder: (_, model, widget) => AppScaffold( isShowAppBar: false, - appBarTitle: TranslationBase.of(context).h2o, + appBarTitle: TranslationBase.of(context).h2o, baseViewModel: model, body: Padding( padding: EdgeInsets.all(8.0), @@ -46,7 +49,7 @@ class MonthPage extends StatelessWidget { ], ), // SizedBox(height: 8), - AppBarChart(seriesList: model.userProgressForMonthDataSeries), + AppBarChart(seriesList: model.userProgressForMonthDataSeries, isArabic: projectViewModel.isArabic), ], ), ), diff --git a/lib/pages/AlHabibMedicalService/h2o/today_page.dart b/lib/pages/AlHabibMedicalService/h2o/today_page.dart index 33383287..03d11f50 100644 --- a/lib/pages/AlHabibMedicalService/h2o/today_page.dart +++ b/lib/pages/AlHabibMedicalService/h2o/today_page.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/widgets/h20_floating_action_button.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; @@ -7,8 +8,14 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class TodayPage extends StatelessWidget { + Future readPrefs() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return (prefs.getString(H2O_UNIT) ?? "ml") == "ml" ? true : false; + } + @override Widget build(BuildContext context) { return BaseView( @@ -34,55 +41,75 @@ class TodayPage extends StatelessWidget { : (model.userProgressData.percentageConsumed / 100) >= 1 ? 1 : (model.userProgressData.percentageConsumed / 100), - //, center: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // SizedBox( - // height: 40, - // ), - Text( - TranslationBase.of(context).consumed, - style: TextStyle(fontSize: 16.0), - ), - SizedBox( - height: 4, - ), - Text( - model.userProgressData == null - ? "0.0" - : model.userProgressData.quantityConsumed.toString() + TranslationBase.of(context).ml, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0, color: HexColor("#60BCF9")), - ), - SizedBox( - height: 4, - ), - SizedBox( - height: 5, - width: 50, - child: Container(), - ), - SizedBox( - height: 4, - ), - Text( - TranslationBase.of(context).remaining, - style: TextStyle(fontSize: 16.0), - ), - SizedBox( - height: 4, - ), - Text( - model.userProgressData == null - ? "0.0" - : (model.userProgressData.quantityLimit - model.userProgressData.quantityConsumed) < 0 - ? "0 ${TranslationBase.of(context).ml}" - : (model.userProgressData.quantityLimit - model.userProgressData.quantityConsumed).toString() + - ' ${TranslationBase.of(context).ml}', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0), - ), - ], + child: FutureBuilder( + future: readPrefs(), + builder: (context, data) { + var isUnitML = true; + String unit; + if (data.connectionState == ConnectionState.done) { + isUnitML = data.data; + } + if (isUnitML) { + unit = TranslationBase.of(context).ml; + } else { + unit = TranslationBase.of(context).l; + } + unit = unit.toLowerCase(); + var totalH2O = model?.userProgressData?.quantityLimit ?? 0.0; + var consumedH2O = model?.userProgressData?.quantityConsumed ?? 0.0; + if (!isUnitML) { + totalH2O = totalH2O / 1000; + consumedH2O = consumedH2O / 1000; + } + var remainingH2O = totalH2O - consumedH2O; + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // SizedBox( + // height: 40, + // ), + Text( + TranslationBase.of(context).consumed, + style: TextStyle(fontSize: 16.0), + ), + SizedBox( + height: 4, + ), + Text( + model.userProgressData == null ? "0.0" : "$consumedH2O $unit", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0, color: HexColor("#60BCF9")), + ), + SizedBox( + height: 4, + ), + SizedBox( + height: 5, + width: 50, + child: Container(), + ), + SizedBox( + height: 4, + ), + Text( + TranslationBase.of(context).remaining, + style: TextStyle(fontSize: 16.0), + ), + SizedBox( + height: 4, + ), + Text( + model.userProgressData == null + ? "0.0" + : (remainingH2O) < 0 + ? "0 $unit" + : '$remainingH2O $unit', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0), + ), + ], + ); + }, ), ), circularStrokeCap: CircularStrokeCap.butt, diff --git a/lib/pages/AlHabibMedicalService/h2o/week_page.dart b/lib/pages/AlHabibMedicalService/h2o/week_page.dart index 34e365e6..6f4423b2 100644 --- a/lib/pages/AlHabibMedicalService/h2o/week_page.dart +++ b/lib/pages/AlHabibMedicalService/h2o/week_page.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/charts/app_bar_chart.dart'; @@ -8,10 +9,12 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_circular_progress_Indeicator.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class WeekPage extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getUserProgressForWeekData(), builder: (_, model, widget) => AppScaffold( @@ -46,7 +49,7 @@ class WeekPage extends StatelessWidget { ], ), // SizedBox(height: 8), - AppBarChart(seriesList: model.userProgressForWeekDataSeries), + AppBarChart(seriesList: model.userProgressForWeekDataSeries,isArabic: projectViewModel.isArabic), ], ), ), diff --git a/lib/pages/AlHabibMedicalService/h2o/widgets/h20_buttom_navigation_bar.dart b/lib/pages/AlHabibMedicalService/h2o/widgets/h20_buttom_navigation_bar.dart new file mode 100644 index 00000000..1948e1c8 --- /dev/null +++ b/lib/pages/AlHabibMedicalService/h2o/widgets/h20_buttom_navigation_bar.dart @@ -0,0 +1,58 @@ +import 'package:diplomaticquarterapp/pages/landing/home_page.dart'; +import 'package:diplomaticquarterapp/widgets/bottom_navigation/bottom_nav_bar.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/floatingActionButton.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/pages/medical/medical_profile_page.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/BookingOptions.dart'; +import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; +import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; + +class H20BottomNavigationBar extends StatelessWidget { + H20BottomNavigationBar({Key key}) : super(key: key); + + PageController pageController = PageController(keepPage: true); + int currentTab = 0; + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + body: PageView( + physics: NeverScrollableScrollPhysics(), + controller: pageController, + children: [ + HomePage( + goToMyProfile: () { + _changeCurrentTab(1); + }, + ), + MedicalProfilePage(), + BookingOptions(), + MyFamily(isAppbarVisible: false), + ToDo(isShowAppBar: false), + ], // Please do not remove the BookingOptions from this array + ), + bottomNavigationBar: BottomNavBar( + changeIndex: _changeCurrentTab, + index: currentTab, + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButton: FloatingButton( + elevation: true, + onTap: () { + _changeCurrentTab(2); + }), + ); + } + + _changeCurrentTab(int tab) { + // setState(() { + currentTab = tab; + if (tab != 0) + pageController.jumpToPage(tab); + else { + pageController.jumpToPage(tab); + } + // }); + } +} diff --git a/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bariatrics-screen.dart b/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bariatrics-screen.dart index d9665aa4..c71a0c87 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bariatrics-screen.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bariatrics-screen.dart @@ -3,12 +3,14 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/DiseasesByClinic.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/health-calculator/Bariatrics-viewmodel.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/borderedButton.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -33,122 +35,99 @@ class _BariatricsPageState extends State { return BaseView( onModelReady: (model) => model.getClinicCategory(), - builder: (_, model, w) => - AppScaffold( - isShowAppBar: true, - appBarTitle: "${TranslationBase - .of(context) - .bariatrics}", - baseViewModel: model, - body: Column( - children: [ - Container( - margin: EdgeInsets.all(8.0), - child: Center( - child: Texts(TranslationBase - .of(context) - .bariatricsHeaderMsg), - ), - ), - Expanded( - child: Container( - margin: EdgeInsets.symmetric( - horizontal: 16.0, vertical: 8.0), - child: Row( - children: [ - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - ...model.diseasesList - .map((item) => - RadioListTile( + builder: (_, model, w) => AppScaffold( + isShowDecPage: false, + isShowAppBar: true, + appBarTitle: "${TranslationBase.of(context).bariatrics}", + baseViewModel: model, + body: Column( + children: [ + Container( + margin: EdgeInsets.all(8.0), + child: Center( + child: Texts(TranslationBase.of(context).bariatricsHeaderMsg), + ), + ), + Expanded( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + child: Row( + children: [ + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + ...model.diseasesList + .map((item) => RadioListTile( title: Texts("${item.diseases}"), activeColor: Colors.blue.shade700, value: item.diseasesID, - groupValue: _selectedDisease != null - ? _selectedDisease.diseasesID - : -1, - selected: _selectedDisease != null ? item - .diseasesID == - _selectedDisease.diseasesID : false, + groupValue: _selectedDisease != null ? _selectedDisease.diseasesID : -1, + selected: _selectedDisease != null + ? item.diseasesID == _selectedDisease.diseasesID + : false, onChanged: (val) { setState(() { _selectedDisease = item; }); }, )) - .toList() - ], - ), - ), + .toList() + ], ), - Image.asset( - _getImageName(widget.gender, widget.obeseResult, - projectProvider.isArabic), - fit: BoxFit.cover, - ), - ], + ), ), - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16), - child: BorderedButton( - TranslationBase - .of(context) - .continues, - fontSize: SizeConfig.textMultiplier * 2.1, - textColor: Colors.white, - vPadding: 8, - hPadding: 8, - backgroundColor: Theme - .of(context) - .primaryColor, - radius: 8, - fontWeight: FontWeight.bold, - handler: () async { - await model.searchDoctorsByTime(_selectedDisease); - if(model.state == ViewState.ErrorLocal){ - AppToast.showErrorToast(message: model.error); - } - // Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => BariatricsPage()), - // ); - }, - ), - ), - Container( - margin: EdgeInsets.only(bottom: 16.0, left: 16, right: 16), - child: BorderedButton( - TranslationBase - .of(context) - .skip, - fontSize: SizeConfig.textMultiplier * 2.1, - textColor: Colors.blue, - vPadding: 8, - hPadding: 8, - backgroundColor: Color(0x00000000), - radius: 8, - hasBorder: true, - borderColor: Color(0x00000000), - fontWeight: FontWeight.bold, - handler: () async { - await model.searchDoctorsByTime(_selectedDisease); - if(model.state == ViewState.ErrorLocal){ - AppToast.showErrorToast(message: model.error); - } - // Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => BariatricsPage()), - // ); - }, - ), + Image.asset( + _getImageName(widget.gender, widget.obeseResult, projectProvider.isArabic), + fit: BoxFit.cover, + ), + ], ), - ], + ), + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: BorderedButton( + TranslationBase.of(context).continues, + fontSize: SizeConfig.textMultiplier * 2.1, + textColor: Colors.white, + vPadding: 8, + hPadding: 8, + backgroundColor: Theme.of(context).primaryColor, + radius: 8, + fontWeight: FontWeight.bold, + handler: () async { + Navigator.push( + context, + FadePage(page: DoctorList(diseaseByClinic: _selectedDisease,)), + ); + }, + ), + ), + Container( + margin: EdgeInsets.only(bottom: 16.0, left: 16, right: 16), + child: BorderedButton( + TranslationBase.of(context).skip, + fontSize: SizeConfig.textMultiplier * 2.1, + textColor: Colors.blue, + vPadding: 8, + hPadding: 8, + backgroundColor: Color(0x00000000), + radius: 8, + hasBorder: true, + borderColor: Color(0x00000000), + fontWeight: FontWeight.bold, + handler: () async { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, + ), ), - ), + ], + ), + ), ); } diff --git a/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bmi_calculator.dart b/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bmi_calculator.dart index 2282472b..ec7074c2 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bmi_calculator.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/bmi_calculator.dart @@ -6,8 +6,10 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'dart:math'; +import '../health_calc_desc.dart'; import 'result_page.dart'; const activeCardColor = Color(0xff70777A); @@ -121,6 +123,23 @@ class _BMICalculatorState extends State { return AppScaffold( isShowAppBar: true, isShowDecPage: false, + showHomeAppBarIcon: false, + appBarIcons: [ + IconButton( + icon: Icon(Icons.info_outline), + color: Colors.white, + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => HealthDescPage( + "${TranslationBase.of(context).bmi} ${TranslationBase.of(context).calcHealth}", + TranslationBase.of(context).bmiCalcDesc, + "assets/images/AlHabibMedicalService/health_calculator/bmi.png")), + ); + }, + ) + ], appBarTitle: "${TranslationBase.of(context).bmi} ${TranslationBase.of(context).calcHealth}", body: SingleChildScrollView( diff --git a/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/result_page.dart index a541b3ce..9b0ee417 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/bmi_calculator/result_page.dart @@ -50,9 +50,9 @@ class ResultPage extends StatelessWidget { @override Widget build(BuildContext context) { return AppScaffold( + isShowDecPage: false, isShowAppBar: true, - appBarTitle: - "${TranslationBase.of(context).bmi} ${TranslationBase.of(context).calcHealth}", + appBarTitle: "${TranslationBase.of(context).bmi} ${TranslationBase.of(context).calcHealth}", body: Column( children: [ Expanded( @@ -112,11 +112,10 @@ class ResultPage extends StatelessWidget { backgroundColor: Theme.of(context).primaryColor, radius: 8, fontWeight: FontWeight.bold, - handler: (){ + handler: () { Navigator.push( context, - FadePage( - page: BariatricsPage(1, 1, finalResult)), + FadePage(page: BariatricsPage(1, 1, finalResult)), ); }, ), diff --git a/lib/pages/AlHabibMedicalService/health_calculator/bmr_calculator/bmr_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/bmr_calculator/bmr_result_page.dart index a3fdb5f7..6e7d6279 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/bmr_calculator/bmr_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/bmr_calculator/bmr_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; @@ -12,6 +14,7 @@ class BmrResultPage extends StatelessWidget { Widget build(BuildContext context) { return AppScaffold( isShowAppBar: true, + isShowDecPage: false, appBarTitle: 'BMR Calculator', body: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, @@ -55,8 +58,13 @@ class BmrResultPage extends StatelessWidget { Container( width: 350, child: Button( - label: 'See List Of Doctors', - ), + label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }), ), ], ), diff --git a/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat.dart b/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat.dart index 1530d0ee..0ce34e42 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat.dart @@ -148,18 +148,10 @@ class _BodyFatState extends State { void calculateBodyFat() { if (isMale == true) { - bodyFat = 495 / - (1.0324 - - 0.19077 * (log(waist - neck) / ln10) + - 0.15456 * (log(heightCm) / ln10)) - - 450; + bodyFat = 495 / (1.0324 - 0.19077 * (log(waist - neck) / ln10) + 0.15456 * (log(heightCm) / ln10)) - 450; fat = (bodyFat * 10) / 10.round(); } else if (isMale == false) { - bodyFat = 495 / - (1.29579 - - 0.35004 * (log(waist + hip - neck) / ln10) + - 0.22100 * (log(heightCm) / ln10)) - - 450; + bodyFat = 495 / (1.29579 - 0.35004 * (log(waist + hip - neck) / ln10) + 0.22100 * (log(heightCm) / ln10)) - 450; fat = (bodyFat * 10) / 10.round(); } if (fat <= 0) { @@ -180,11 +172,9 @@ class _BodyFatState extends State { } else if (bodyFat > 31 && bodyFat <= 60) { textResult = 'The category falls under obese'; } else if (bodyFat > 60) { - textResult = - 'Please check the value you have entered, since the body fat percentage has crosed the limits.'; + textResult = 'Please check the value you have entered, since the body fat percentage has crosed the limits.'; } else if (bodyFat <= 9) { - textResult = - 'Please check the value you have entered, since the body fat percentage cannot be this low.'; + textResult = 'Please check the value you have entered, since the body fat percentage cannot be this low.'; } } else { if (bodyFat > 5 && fat <= 13) { @@ -196,11 +186,9 @@ class _BodyFatState extends State { } else if (bodyFat > 24 && bodyFat <= 45) { textResult = 'The category falls under obese'; } else if (bodyFat > 45) { - textResult = - 'Please check the value you have entered, since the body fat percentage has crosed the limits.'; + textResult = 'Please check the value you have entered, since the body fat percentage has crosed the limits.'; } else if (bodyFat <= 5) { - textResult = - 'Please check the value you have entered, since the body fat percentage cannot be this low.'; + textResult = 'Please check the value you have entered, since the body fat percentage cannot be this low.'; } } } @@ -229,8 +217,7 @@ class _BodyFatState extends State { children: [ Padding( padding: EdgeInsets.all(10.0), - child: - Texts('Estimates the total body fat based on\n the size'), + child: Texts('Estimates the total body fat based on\n the size'), ), Divider( thickness: 2.0, @@ -308,14 +295,12 @@ class _BodyFatState extends State { child: Row( children: [ Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, horizontal: 8.0), + padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), child: Center( child: Container( width: 60.0, foregroundDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5.0), border: Border.all( color: Colors.blueGrey, width: 2.0, @@ -331,10 +316,8 @@ class _BodyFatState extends State { Container( height: 38.0, child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( decoration: BoxDecoration( @@ -351,8 +334,7 @@ class _BodyFatState extends State { ), onTap: () { setState(() { - if (heightCm < 250) - heightCm++; + if (heightCm < 250) heightCm++; }); }, ), @@ -364,8 +346,7 @@ class _BodyFatState extends State { ), onTap: () { setState(() { - if (heightCm > 0) - heightCm--; + if (heightCm > 0) heightCm--; }); }, ), @@ -420,16 +401,14 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], color: cmCard, borderRadius: BorderRadius.circular(3.0), ), child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 0.0, horizontal: 18.0), + padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 18.0), child: Center(child: Texts('CM')), ), ), @@ -452,14 +431,12 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], ), child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Center(child: Texts('Ft')), ), ), @@ -484,14 +461,12 @@ class _BodyFatState extends State { child: Row( children: [ Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, horizontal: 8.0), + padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), child: Center( child: Container( width: 60.0, foregroundDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5.0), border: Border.all( color: Colors.blueGrey, width: 2.0, @@ -507,10 +482,8 @@ class _BodyFatState extends State { Container( height: 38.0, child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( decoration: BoxDecoration( @@ -594,16 +567,14 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], color: neckCmCard, borderRadius: BorderRadius.circular(3.0), ), child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 0.0, horizontal: 18.0), + padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 18.0), child: Center(child: Texts('CM')), ), ), @@ -626,14 +597,12 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], ), child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Center(child: Texts('Ft')), ), ), @@ -658,14 +627,12 @@ class _BodyFatState extends State { child: Row( children: [ Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, horizontal: 8.0), + padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), child: Center( child: Container( width: 60.0, foregroundDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5.0), border: Border.all( color: Colors.blueGrey, width: 2.0, @@ -681,10 +648,8 @@ class _BodyFatState extends State { Container( height: 38.0, child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( decoration: BoxDecoration( @@ -701,8 +666,7 @@ class _BodyFatState extends State { ), onTap: () { setState(() { - if (waist < 200) - waist++; + if (waist < 200) waist++; }); }, ), @@ -769,16 +733,14 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], color: waistCmCard, borderRadius: BorderRadius.circular(3.0), ), child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 0.0, horizontal: 18.0), + padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 18.0), child: Center(child: Texts('CM')), ), ), @@ -801,14 +763,12 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], ), child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Center(child: Texts('Ft')), ), ), @@ -833,14 +793,12 @@ class _BodyFatState extends State { child: Row( children: [ Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, horizontal: 8.0), + padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), child: Center( child: Container( width: 60.0, foregroundDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5.0), border: Border.all( color: Colors.blueGrey, width: 2.0, @@ -856,10 +814,8 @@ class _BodyFatState extends State { Container( height: 38.0, child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Container( decoration: BoxDecoration( @@ -943,16 +899,14 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], color: hipCmCard, borderRadius: BorderRadius.circular(3.0), ), child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 0.0, horizontal: 18.0), + padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 18.0), child: Center(child: Texts('CM')), ), ), @@ -975,14 +929,12 @@ class _BodyFatState extends State { color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 7, - offset: Offset( - 0, 3), // changes position of shadow + offset: Offset(0, 3), // changes position of shadow ), ], ), child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Center(child: Texts('Ft')), ), ), @@ -995,7 +947,7 @@ class _BodyFatState extends State { ], ), Container( - height: 100.0, + height: MediaQuery.of(context).size.height * 0.084, width: 350.0, child: SecondaryButton( label: 'CALCULATE', diff --git a/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat_result_page.dart index c8c5476e..f41f9598 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/body_fat/body_fat_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; @@ -68,6 +70,12 @@ class FatResult extends StatelessWidget { width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/health_calculator/calorie_calculator/calorie_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/calorie_calculator/calorie_result_page.dart index 110b2afc..ed3dd8f8 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/calorie_calculator/calorie_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/calorie_calculator/calorie_result_page.dart @@ -1,7 +1,9 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:percent_indicator/circular_percent_indicator.dart'; @@ -45,13 +47,18 @@ class CalorieResultPage extends StatelessWidget { ), ), Container( - child: - Texts('Daily intake is ${calorie.toStringAsFixed(1)} calories'), + child: Texts('Daily intake is ${calorie.toStringAsFixed(1)} calories'), ), Container( width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs_result_page.dart index f8d0815a..474b8613 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'dart:math'; @@ -156,6 +158,12 @@ class CarbsResult extends StatelessWidget { width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due.dart b/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due.dart index d19c6017..db5a585c 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due.dart @@ -70,9 +70,7 @@ class _DeliveryDueState extends State { onConfirm: (date) { print('confirm $date'); setState(() { - bloodSugarDate == date - ? null - : bloodSugarDate = DateTime.now(); + bloodSugarDate = date; dateFrom = date.add(Duration(days: 10)); dateTo = date.add(Duration(days: 20)); @@ -90,9 +88,7 @@ class _DeliveryDueState extends State { padding: EdgeInsets.all(12), width: double.infinity, height: 65, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: Colors.white), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -124,14 +120,14 @@ class _DeliveryDueState extends State { context, FadePage( page: DeliveryDueResult( - conceivedDate: conceivedDate, - dateFrom: dateFrom, - dateTo: dateTo, - deliveryDue: deliveryDue, - firstTrimester: firstTrimester, - secondTrimester: secondTrimester, - thirdTrimester: thirdTrimester, - )), + conceivedDate: conceivedDate, + dateFrom: dateFrom, + dateTo: dateTo, + deliveryDue: deliveryDue, + firstTrimester: firstTrimester, + secondTrimester: secondTrimester, + thirdTrimester: thirdTrimester, + )), ); } }); diff --git a/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due_result_page.dart index fc53b044..e03e5fce 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/delivery_due/delivery_due_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -43,17 +45,13 @@ class DeliveryDueResult extends StatelessWidget { fontWeight: FontWeight.w400, ), Texts(DateFormat.yMMMEd().format(dateFrom), - fontWeight: FontWeight.w800, - fontSize: 21.0, - color: Color(0xffC5272D)), + fontWeight: FontWeight.w800, fontSize: 21.0, color: Color(0xffC5272D)), Texts( 'To:', fontWeight: FontWeight.w400, ), Texts(DateFormat.yMMMEd().format(dateTo), - fontWeight: FontWeight.w800, - fontSize: 21.0, - color: Color(0xffC5272D)), + fontWeight: FontWeight.w800, fontSize: 21.0, color: Color(0xffC5272D)), Texts( 'You have conceived on:', fontWeight: FontWeight.w400, @@ -94,6 +92,12 @@ class DeliveryDueResult extends StatelessWidget { width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/health_calculator/doctor_list.dart b/lib/pages/AlHabibMedicalService/health_calculator/doctor_list.dart new file mode 100644 index 00000000..ba906ca4 --- /dev/null +++ b/lib/pages/AlHabibMedicalService/health_calculator/doctor_list.dart @@ -0,0 +1,116 @@ +import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/HealthCalculator/DiseasesByClinic.dart'; +import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/health-calculator/Bariatrics-viewmodel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:rating_bar/rating_bar.dart'; + +class DoctorList extends StatelessWidget { + DiseasesByClinic diseaseByClinic; + DoctorList({Key key, this.diseaseByClinic}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BaseView( + allowAny: true, + onModelReady: (model) => model.getDoctorList(disease: diseaseByClinic), + builder: (BuildContext context, BariatricsViewModel model, Widget child) => AppScaffold( + isShowDecPage: false, + isShowAppBar: true, + baseViewModel: model, + appBarTitle: "Doctors List", + description: TranslationBase.of(context).infoApprovals, + infoList: TranslationBase.of(context).infoApprovalPoints, + body: ListView.builder( + itemCount: model.doctorLists.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), + child: Container( + //height: MediaQuery.of(context).size.height * 0.09, + decoration: BoxDecoration(color: Colors.white), + + child: ExpansionTile( + title: Padding( + padding: EdgeInsets.all(21.0), + child: Texts(model.doctorLists[index].filterName), + ), + children: model.doctorLists[index].doctorsByTimeList + .map((doctor) => Card( + margin: EdgeInsets.fromLTRB(10.0, 16.0, 10.0, 8.0), + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Container( + decoration: BoxDecoration(), + padding: EdgeInsets.all(7.0), + width: MediaQuery.of(context).size.width, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 1, + child: ClipRRect( + borderRadius: BorderRadius.circular(100.0), + child: Image.network(doctor.doctorImageURL, + fit: BoxFit.fill, height: 60.0, width: 60.0), + ), + ), + Expanded( + flex: 4, + child: Container( + width: MediaQuery.of(context).size.width * 0.55, + margin: EdgeInsets.fromLTRB(20.0, 10.0, 10.0, 0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (doctor.doctorTitle != null) + Text(doctor.doctorTitle + " " + doctor.name, style: TextStyle(fontSize: 14.0, color: Colors.grey[700], letterSpacing: 1.0)), + Container( + margin: EdgeInsets.only(top: 3.0), + child: Text(doctor.clinicName != null ? doctor.clinicName : "", style: TextStyle(fontSize: 12.0, color: Colors.grey[600], letterSpacing: 1.0)), + ), + Container( + margin: EdgeInsets.only(top: 3.0), + child: Text(doctor.projectName, style: TextStyle(fontSize: 12.0, color: Colors.grey[600], letterSpacing: 1.0)), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + RatingBar.readOnly( + initialRating: doctor.actualDoctorRate.toDouble(), + size: 20.0, + filledColor: Colors.yellow[700], + emptyColor: Colors.grey[500], + isHalfAllowed: true, + halfFilledIcon: Icons.star_half, + filledIcon: Icons.star, + emptyIcon: Icons.star, + ), + Container( + child: Image.network(doctor.nationalityFlagURL, + width: 25.0, height: 25.0), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + )) + .toList(), + ), + ), + ); + }), + )); + } +} diff --git a/lib/pages/AlHabibMedicalService/health_calculator/health_calc_desc.dart b/lib/pages/AlHabibMedicalService/health_calculator/health_calc_desc.dart new file mode 100644 index 00000000..19f8e986 --- /dev/null +++ b/lib/pages/AlHabibMedicalService/health_calculator/health_calc_desc.dart @@ -0,0 +1,40 @@ +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; + +class HealthDescPage extends StatelessWidget { + final String title; + final String desc; + final String icon; + + HealthDescPage(this.title, this.desc, this.icon); + + @override + Widget build(BuildContext context) { + return AppScaffold( + isShowAppBar: true, + isShowDecPage: false, + appBarTitle: title, + body: Container( + margin: EdgeInsets.all(8.0), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Image.asset( + icon, + fit: BoxFit.cover, + height: 80, + ), + ), + Expanded( + child: Text( + desc, + style: TextStyle(fontSize: 18.0), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/AlHabibMedicalService/health_calculator/ideal_body/ideal_body_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/ideal_body/ideal_body_result_page.dart index 605e499a..24fc768f 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/ideal_body/ideal_body_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/ideal_body/ideal_body_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'dart:math'; @@ -11,12 +13,7 @@ class IdealBodyResult extends StatelessWidget { final double overWeightBy; final String textResult; - IdealBodyResult( - {this.idealBodyWeight, - this.minRange, - this.mixRange, - this.overWeightBy, - this.textResult}); + IdealBodyResult({this.idealBodyWeight, this.minRange, this.mixRange, this.overWeightBy, this.textResult}); @override Widget build(BuildContext context) { return AppScaffold( @@ -82,8 +79,7 @@ class IdealBodyResult extends StatelessWidget { : overWeightBy > 10 && overWeightBy < 17 ? Column( children: [ - Texts( - 'This means that the weight is a little bit more than ideal weight by'), + Texts('This means that the weight is a little bit more than ideal weight by'), Texts(overWeightBy.toStringAsFixed(1)), Texts( 'May wish to consult with the doctor for medical help. Click to view our list of Doctors'), @@ -161,6 +157,12 @@ class IdealBodyResult extends StatelessWidget { width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart index 6669bf75..6ced14b2 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -9,8 +11,7 @@ class OvulationResult extends StatelessWidget { var dateTo; var conceivedDate; var deliveryDue; - OvulationResult( - {this.dateFrom, this.dateTo, this.deliveryDue, this.conceivedDate}); + OvulationResult({this.dateFrom, this.dateTo, this.deliveryDue, this.conceivedDate}); //var newFormat = DateFormat("yy-MM-dd"); @override @@ -84,6 +85,12 @@ class OvulationResult extends StatelessWidget { width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/health_converter/blood_sugar.dart b/lib/pages/AlHabibMedicalService/health_converter/blood_sugar.dart index cf230466..e429418d 100644 --- a/lib/pages/AlHabibMedicalService/health_converter/blood_sugar.dart +++ b/lib/pages/AlHabibMedicalService/health_converter/blood_sugar.dart @@ -42,6 +42,7 @@ class _BloodSugarState extends State { } void calculateBloodSugar() { + if (textController.text.isEmpty) return; if (cardMGColor == activeCardColor) { inputValue = double.parse(textController.text); inputValue = inputValue / 15; @@ -60,10 +61,18 @@ class _BloodSugarState extends State { double inputValue = 0; String unit; + @override + void initState() { + updateColor(1); + unit = 'mmol/l'; + super.initState(); + } + @override Widget build(BuildContext context) { return AppScaffold( isShowAppBar: true, + isShowDecPage: false, appBarTitle: TranslationBase.of(context).bloodSugarConversion, body: Padding( padding: const EdgeInsets.all(16.0), @@ -112,9 +121,11 @@ class _BloodSugarState extends State { onTap: () { setState(() { updateColor(1); - inputValue = - double.parse(textController.text); - inputValue = inputValue / 15; + if (textController.text.isNotEmpty) { + inputValue = + double.parse(textController.text); + inputValue = inputValue / 15; + } unit = 'mmol/l'; }); }, @@ -145,9 +156,11 @@ class _BloodSugarState extends State { onTap: () { setState(() { updateColor(2); - inputValue = - double.parse(textController.text); - inputValue = inputValue * 18; + if (textController.text.isNotEmpty) { + inputValue = + double.parse(textController.text); + inputValue = inputValue / 18; + } unit = 'mg/dlt'; }); }, @@ -170,7 +183,7 @@ class _BloodSugarState extends State { child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0), - child: Texts('MG/DLt TO\n MMOL/L'), + child: Texts('\nMMOL/L TO MG/DLt '), ), ), ), diff --git a/lib/pages/AlHabibMedicalService/my_web_view.dart b/lib/pages/AlHabibMedicalService/my_web_view.dart index 59163c15..c4841a24 100644 --- a/lib/pages/AlHabibMedicalService/my_web_view.dart +++ b/lib/pages/AlHabibMedicalService/my_web_view.dart @@ -8,8 +8,7 @@ class MyWebView extends StatelessWidget { final String title; final String selectedUrl; - final Completer _controller = - Completer(); + final Completer _controller = Completer(); MyWebView({ @required this.title, @@ -21,17 +20,12 @@ class MyWebView extends StatelessWidget { return AppScaffold( isShowAppBar: true, appBarTitle: title, - - body: - WebView( + body: WebView( initialUrl: selectedUrl, javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller.complete(webViewController); }, - ) - - - ); + )); } -} \ No newline at end of file +} diff --git a/lib/pages/AlHabibMedicalService/parking_page.dart b/lib/pages/AlHabibMedicalService/parking_page.dart index 82c390ea..19f06a56 100644 --- a/lib/pages/AlHabibMedicalService/parking_page.dart +++ b/lib/pages/AlHabibMedicalService/parking_page.dart @@ -8,7 +8,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:maps_launcher/maps_launcher.dart'; - +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import '../../d_q_icons_icons.dart'; class ParkingPage extends StatelessWidget { @@ -19,6 +19,13 @@ class ParkingPage extends StatelessWidget { builder: (_, model, widget) => AppScaffold( isShowAppBar: true, appBarTitle: TranslationBase.of(context).parking, + description: TranslationBase.of(context).parkingDescription, + imagesInfo: [ + ImagesInfo( + imageAr: 'assets/images/bc_parking.png', + imageEn: 'assets/images/bc_parking.png', + isAsset: true) + ], body: SingleChildScrollView( padding: EdgeInsets.all(12), child: !model.isSavePark diff --git a/lib/pages/AlHabibMedicalService/​ health_calculators.dart b/lib/pages/AlHabibMedicalService/​ health_calculators.dart index dbd8939c..fab4eb6d 100644 --- a/lib/pages/AlHabibMedicalService/​ health_calculators.dart +++ b/lib/pages/AlHabibMedicalService/​ health_calculators.dart @@ -9,7 +9,6 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; - import 'health_calculator/bmi_calculator/bmi_calculator.dart'; import 'health_calculator/bmr_calculator/bmr_calculator.dart'; import 'health_calculator/calorie_calculator/calorie_calculator.dart'; @@ -21,8 +20,7 @@ class HealthCalculators extends StatefulWidget { _HealthCalculatorsState createState() => _HealthCalculatorsState(); } -class _HealthCalculatorsState extends State - with SingleTickerProviderStateMixin { +class _HealthCalculatorsState extends State with SingleTickerProviderStateMixin { TabController _tabController; void initState() { super.initState(); @@ -67,22 +65,19 @@ class _HealthCalculatorsState extends State indicatorWeight: 4.0, indicatorColor: Colors.red, labelColor: Theme.of(context).buttonColor, - labelPadding: - EdgeInsets.symmetric(horizontal: 13.0, vertical: 2.0), + labelPadding: EdgeInsets.symmetric(horizontal: 13.0, vertical: 2.0), unselectedLabelColor: Colors.grey, tabs: [ Container( width: MediaQuery.of(context).size.width * 0.35, child: Center( - child: Texts( - TranslationBase.of(context).generalHealth), + child: Texts(TranslationBase.of(context).generalHealth), ), ), Container( width: MediaQuery.of(context).size.width * 0.35, child: Center( - child: - Texts(TranslationBase.of(context).womanHealth), + child: Texts(TranslationBase.of(context).womanHealth), ), ), ], @@ -121,8 +116,7 @@ class _HealthCalculatorsState extends State child: MedicalProfileItem( title: TranslationBase.of(context).bmi, imagePath: 'bmi_health_calculator.png', - subTitle: - TranslationBase.of(context).calcHealth, + subTitle: TranslationBase.of(context).calcHealth, ), ), ), @@ -140,8 +134,7 @@ class _HealthCalculatorsState extends State child: MedicalProfileItem( title: TranslationBase.of(context).calories, imagePath: 'calories-calculator.png', - subTitle: - TranslationBase.of(context).calcHealth, + subTitle: TranslationBase.of(context).calcHealth, ), ), ), @@ -163,8 +156,7 @@ class _HealthCalculatorsState extends State child: MedicalProfileItem( title: TranslationBase.of(context).bmr, imagePath: 'BMR_calculator.png', - subTitle: - TranslationBase.of(context).calcHealth, + subTitle: TranslationBase.of(context).calcHealth, ), ), ), @@ -220,11 +212,9 @@ class _HealthCalculatorsState extends State ); }, child: MedicalProfileItem( - title: - TranslationBase.of(context).carbohydrate, + title: TranslationBase.of(context).carbohydrate, imagePath: 'carb_protein.png', - subTitle: - TranslationBase.of(context).proteinFat, + subTitle: TranslationBase.of(context).proteinFat, ), ), ), diff --git a/lib/pages/Blood/blood_donation.dart b/lib/pages/Blood/blood_donation.dart index adff790c..ce6ab8ee 100644 --- a/lib/pages/Blood/blood_donation.dart +++ b/lib/pages/Blood/blood_donation.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/model/blooddonation/blood_groub_details.dart'; import 'package:diplomaticquarterapp/core/model/blooddonation/get_all_cities.dart'; @@ -60,7 +61,7 @@ class _BloodDonationPageState extends State { AppSharedPreferences sharedPref = AppSharedPreferences(); AuthenticatedUser authUser; var checkedValue = false; - + List imagesInfo = List(); @override void initState() { super.initState(); @@ -69,6 +70,13 @@ class _BloodDonationPageState extends State { @override Widget build(BuildContext context) { + imagesInfo.add( + ImagesInfo( + imageEn: + 'https://hmgwebservices.com/Images/MobileApp/images-info-home/blood/en/0.png', + imageAr: + 'https://hmgwebservices.com/Images/MobileApp/images-info-home/blood/ar/0.png'), + ); ProjectViewModel projectProvider = Provider.of(context); return BaseView( @@ -76,6 +84,8 @@ class _BloodDonationPageState extends State { builder: (_, model, w) => AppScaffold( isShowAppBar: true, baseViewModel: model, + imagesInfo: imagesInfo, + description: TranslationBase.of(context).bloodDonationInfo, appBarTitle: TranslationBase.of(context).bloodD, body: SingleChildScrollView( physics: ScrollPhysics(), diff --git a/lib/pages/BookAppointment/QRCode.dart b/lib/pages/BookAppointment/QRCode.dart index 00fb2fc8..ff7224be 100644 --- a/lib/pages/BookAppointment/QRCode.dart +++ b/lib/pages/BookAppointment/QRCode.dart @@ -13,8 +13,10 @@ import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/nfc/nfc_reader_sheet.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; +import 'package:nfc_in_flutter/nfc_in_flutter.dart'; class QRCode extends StatefulWidget { PatientShareResponse patientShareResponse; @@ -30,17 +32,27 @@ class QRCode extends StatefulWidget { class _QRCodeState extends State { Uint8List _bytes; + bool _supportsNFC = false; + BuildContext _context; @override void initState() { // TODO: implement initState + _bytes = base64.decode(widget.appoQR.split(',').last); widget.authUser = new AuthenticatedUser(); + NFC.isNDEFSupported.then((supported) { + setState(() { + print("nfc supprted"); + _supportsNFC = true; + }); + }); super.initState(); } @override Widget build(BuildContext context) { + _context = context; return AppScaffold( appBarTitle: TranslationBase.of(context).attendRegisterCode, isShowAppBar: true, @@ -51,9 +63,56 @@ class _QRCodeState extends State { mainAxisSize: MainAxisSize.max, children: [ Container( - margin: EdgeInsets.only(top: 30.0), - alignment: Alignment.center, - child: Image.memory(_bytes, scale: 0.5), + width: double.infinity, + height: MediaQuery.of(context).size.width / 3, + child: Row( + children: [ + _supportsNFC + ? Expanded( + flex: 1, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.only(top: 30.0), + alignment: Alignment.center, + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + border: Border.all(color: Colors.black), + borderRadius: BorderRadius.circular(10), + ), + child: Image.asset( + "assets/images/nfc/ic_nfc.png"), + ), + onTap: () { + showNfcReader(context, + onNcfScan: (String nfcId) { + Future.delayed( + const Duration(milliseconds: 100), + () { + sendNfcCheckInRequest(nfcId); + }); + }); + }, + ), + ], + ), + ) + : Container(), + Expanded( + flex: 1, + child: Container( + margin: EdgeInsets.only(top: 30.0), + alignment: Alignment.center, + child: Image.memory( + _bytes, + ), + ), + ), + ], + ), ), Container( margin: EdgeInsets.only(top: 20.0, left: 20.0, right: 20.0), @@ -70,18 +129,20 @@ class _QRCodeState extends State { EdgeInsets.only(top: 10.0, left: 40.0, bottom: 10.0), child: Image.asset( "assets/images/new-design/device_icon.png", - width: 120.0, - height: 120.0), + width: MediaQuery.of(context).size.width / 3.4, + height: MediaQuery.of(context).size.width / 3.4), ), - Container( - width: MediaQuery.of(context).size.width * 0.5, - margin: EdgeInsets.only( - top: 15.0, bottom: 10.0, left: 20.0, right: 20.0), - child: Text(TranslationBase.of(context).scanQRHospital, - style: TextStyle( - color: Colors.red[700], - fontSize: 20.0, - fontWeight: FontWeight.bold)), + Expanded( + child: Container( + width: double.infinity, + margin: EdgeInsets.only( + top: 15.0, bottom: 10.0, left: 20.0, right: 20.0), + child: Text(TranslationBase.of(context).scanQRHospital, + style: TextStyle( + color: Colors.red[700], + fontSize: 18.0, + fontWeight: FontWeight.bold)), + ), ), ], ), @@ -300,4 +361,51 @@ class _QRCodeState extends State { } return docSpeciality; } + + sendNfcCheckInRequest(String nfcId) { + GifLoaderDialogUtils.showMyDialog(context); + + DoctorsListService service = new DoctorsListService(); + + service + .sendCheckinNfcRequest(widget.patientShareResponse.appointmentNo, nfcId, + widget.patientShareResponse.projectID, context) + .then((res) { + print(res); + + GifLoaderDialogUtils.hideDialog(context); + _showMyDialog(res["SuccessMsg"], this.context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + _showMyDialog(err, this.context); + }); + } + + Future _showMyDialog(String message, BuildContext context) async { + return showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Alert'), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(message), + ], + ), + ), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } } diff --git a/lib/pages/BookAppointment/components/SearchByDoctor.dart b/lib/pages/BookAppointment/components/SearchByDoctor.dart index a1ecb7a0..5b4f6dc3 100644 --- a/lib/pages/BookAppointment/components/SearchByDoctor.dart +++ b/lib/pages/BookAppointment/components/SearchByDoctor.dart @@ -93,6 +93,7 @@ class _SearchByDoctorState extends State { service .getDoctorsListByName(doctorNameController.text, context) .then((res) { + GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { setState(() { if (res['DoctorList'].length != 0) { @@ -129,9 +130,12 @@ class _SearchByDoctorState extends State { navigateToSearchResults( context, doctorsList, _patientDoctorAppointmentListHospital); } else { + GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: res['ErrorEndUserMessage']); } }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); print(err); }); } diff --git a/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart b/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart index 04a7178f..c12dd877 100644 --- a/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart +++ b/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart import 'package:diplomaticquarterapp/models/Appointments/FreeSlot.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/Appointments/timeSlot.dart'; +import 'package:diplomaticquarterapp/models/CovidDriveThru/CovidTestProceduresResponse.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-payment-alert.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/services/covid-drivethru/covid-drivethru.dart'; @@ -27,6 +28,7 @@ class CovidTimeSlots extends StatefulWidget { static DateTime selectedAppoDateTime; static String selectedDate; static String selectedTime; + CovidTestProceduresResponse selectedProcedure; int selectedClinicID; int selectedDoctorID; @@ -35,7 +37,7 @@ class CovidTimeSlots extends StatefulWidget { PatientShareResponse patientShareResponse; - CovidTimeSlots({@required this.projectID}); + CovidTimeSlots({@required this.projectID, @required this.selectedProcedure}); @override _CovidTimeSlotsState createState() => _CovidTimeSlotsState(); @@ -94,10 +96,12 @@ class _CovidTimeSlotsState extends State super.dispose(); } - void _onDaySelected(DateTime day, List events, ProjectViewModel projectViewModel) { + void _onDaySelected( + DateTime day, List events, ProjectViewModel projectViewModel) { final DateFormat formatter = DateFormat('yyyy-MM-dd'); setState(() { - this.selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, projectViewModel.isArabic ? "ar" : "en"); + this.selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted( + day, projectViewModel.isArabic ? "ar" : "en"); openTimeSlotsPickerForDate(day, docFreeSlots); CovidTimeSlots.selectedDate = formatter.format(day); print(CovidTimeSlots.selectedDate); @@ -260,7 +264,8 @@ class _CovidTimeSlotsState extends State onPressed: () { bookCovidTestAppointment(); }, - child: Text(TranslationBase.of(context).bookNow, style: TextStyle(fontSize: 18.0)), + child: Text(TranslationBase.of(context).bookNow, + style: TextStyle(fontSize: 18.0)), ), ), ), @@ -355,11 +360,7 @@ class _CovidTimeSlotsState extends State }, ), onDaySelected: (date, event, _) { - _onDaySelected( - date, - event, - projectViewModel - ); + _onDaySelected(date, event, projectViewModel); _animationController.forward(from: 0.0); }, onVisibleDaysChanged: _onVisibleDaysChanged, @@ -494,7 +495,8 @@ class _CovidTimeSlotsState extends State docObject.projectID, CovidTimeSlots.selectedTime, CovidTimeSlots.selectedDate, - context) + context, + widget.selectedProcedure.procedureID) .then((res) { if (res['MessageStatus'] == 1) { AppToast.showSuccessToast(message: "Appointment Booked Successfully"); diff --git a/lib/pages/Covid-DriveThru/covid-drivethru-location.dart b/lib/pages/Covid-DriveThru/covid-drivethru-location.dart index a8cb5048..9bccd300 100644 --- a/lib/pages/Covid-DriveThru/covid-drivethru-location.dart +++ b/lib/pages/Covid-DriveThru/covid-drivethru-location.dart @@ -1,5 +1,7 @@ +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/CovidDriveThru/CovidPaymentInfoResponse.dart'; +import 'package:diplomaticquarterapp/models/CovidDriveThru/CovidTestProceduresResponse.dart'; import 'package:diplomaticquarterapp/models/CovidDriveThru/DriveThroughTestingCenterModel.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-payment-details.dart'; import 'package:diplomaticquarterapp/routes.dart'; @@ -21,6 +23,7 @@ class CovidDrivethruLocation extends StatefulWidget { class _CovidDrivethruLocationState extends State { String projectDropdownValue; List projectsList = []; + List proceduresList = []; bool isLocationSelected = false; String projectLat = ""; String projectLong = ""; @@ -29,23 +32,36 @@ class _CovidDrivethruLocationState extends State { ProjectViewModel projectViewModel; + List imagesInfo = List(); + @override void initState() { - WidgetsBinding.instance - .addPostFrameCallback((_) => getProjectsList(context)); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (projectViewModel.isLogin) { + getProjectsList(context); + getTestProcedures(context); + } + }); super.initState(); } @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); + imagesInfo.add(ImagesInfo( + imageEn: 'https://hmgwebservices.com/Images/MobileApp/covid/en/0.png', + imageAr: 'https://hmgwebservices.com/Images/MobileApp/covid/ar/0.png')); return AppScaffold( appBarTitle: TranslationBase.of(context).covidTest, isShowAppBar: true, + isShowDecPage: true, + description: TranslationBase.of(context).covidInfo, + imagesInfo: imagesInfo, body: SingleChildScrollView( child: Container( margin: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0.0), child: Column( + mainAxisSize: MainAxisSize.max, children: [ Container( alignment: projectViewModel.isArabic @@ -136,94 +152,98 @@ class _CovidDrivethruLocationState extends State { this.projectLong + "&key=AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8"), ) - : Container(), - ], - ), - ), - ), - bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.15, - width: double.infinity, - child: Column( - children: [ - Container( - margin: EdgeInsets.only(top: 10.0), - child: ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.91, - height: 45.0, - child: RaisedButton( - color: new Color(0xFFc5272d), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: Colors.red[300], - onPressed: () { - getDirections(); - }, - child: Text(TranslationBase.of(context).getDirections, - style: TextStyle(fontSize: 18.0)), - ), - ), - ), - Container( - margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0), - child: Flex( - direction: Axis.horizontal, - children: [ - Expanded( - flex: 1, - child: Container( - margin: EdgeInsets.fromLTRB(10.0, 0.0, 5.0, 0.0), + : SizedBox( + height: MediaQuery.of(context).size.height * 0.35, + ), + Container( + height: MediaQuery.of(context).size.height * 0.15, + width: double.infinity, + child: Column( + children: [ + Container( + margin: EdgeInsets.only(top: 10.0), child: ButtonTheme( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), - minWidth: MediaQuery.of(context).size.width * 0.7, + minWidth: MediaQuery.of(context).size.width * 0.91, height: 45.0, child: RaisedButton( - color: new Color(0xFF60686b), + color: new Color(0xFFc5272d), textColor: Colors.white, disabledTextColor: Colors.white, - disabledColor: Colors.grey[500], + disabledColor: Colors.red[300], onPressed: () { - back(); + getDirections(); }, - child: Text(TranslationBase.of(context).back, + child: Text(TranslationBase.of(context).getDirections, style: TextStyle(fontSize: 18.0)), ), ), ), - ), - Expanded( - flex: 1, - child: Container( - margin: EdgeInsets.fromLTRB(10.0, 0.0, 5.0, 0.0), - child: ButtonTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - minWidth: MediaQuery.of(context).size.width * 0.7, - height: 45.0, - child: RaisedButton( - color: new Color(0xFF60686b), - textColor: Colors.white, - disabledTextColor: Colors.white, - disabledColor: Colors.grey[500], - onPressed: () { - next(); - }, - child: Text(TranslationBase.of(context).next, - style: TextStyle(fontSize: 18.0)), - ), + Container( + margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0), + child: Flex( + direction: Axis.horizontal, + children: [ + Expanded( + flex: 1, + child: Container( + margin: EdgeInsets.fromLTRB(10.0, 0.0, 5.0, 0.0), + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: + MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF60686b), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: Colors.grey[500], + onPressed: () { + back(); + }, + child: Text(TranslationBase.of(context).back, + style: TextStyle(fontSize: 18.0)), + ), + ), + ), + ), + Expanded( + flex: 1, + child: Container( + margin: EdgeInsets.fromLTRB(10.0, 0.0, 5.0, 0.0), + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + minWidth: + MediaQuery.of(context).size.width * 0.7, + height: 45.0, + child: RaisedButton( + color: new Color(0xFF60686b), + textColor: Colors.white, + disabledTextColor: Colors.white, + disabledColor: Colors.grey[500], + onPressed: () { + next(); + }, + child: Text(TranslationBase.of(context).next, + style: TextStyle(fontSize: 18.0)), + ), + ), + ), + ), + ], ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ); @@ -268,43 +288,63 @@ class _CovidDrivethruLocationState extends State { getPaymentInfo(BuildContext context, String projectID) { CovidDriveThruService service = new CovidDriveThruService(); - CovidPaymentInfoResponse covidPaymentInfoResponse = new CovidPaymentInfoResponse(); - GifLoaderDialogUtils.showMyDialog(context); - service - .getCovidPaymentInformation(context, int.parse(projectID)) + .getCovidPaymentInformation( + context, int.parse(projectID), proceduresList[0].procedureID) .then((res) { - GifLoaderDialogUtils.hideDialog(context); - if (res['MessageStatus'] == 1) { - setState(() { - covidPaymentInfoResponse = CovidPaymentInfoResponse.fromJson( - res['COVID19_PatientShare']); - print(covidPaymentInfoResponse.procedureNameField); - }); - Navigator.push( - context, - FadePage( - page: CovidPaymentDetails( - covidPaymentInfoResponse: covidPaymentInfoResponse, - projectID: int.parse(projectID), - ))); - } else {} - }) - .catchError((err) { - print(err); + GifLoaderDialogUtils.hideDialog(context); + if (res['MessageStatus'] == 1) { + setState(() { + covidPaymentInfoResponse = + CovidPaymentInfoResponse.fromJson(res['COVID19_PatientShare']); + }); + Navigator.push( + context, + FadePage( + page: CovidPaymentDetails( + covidPaymentInfoResponse: covidPaymentInfoResponse, + projectID: int.parse(projectID), + proceduresList: proceduresList, + ))); + } else {} + }).catchError((err) { + print(err); + }); + } + + getTestProcedures(BuildContext context) { + CovidDriveThruService service = new CovidDriveThruService(); + GifLoaderDialogUtils.showMyDialog(context); + + CovidTestProceduresResponse covidTestProceduresResponse = + new CovidTestProceduresResponse(); + + service.getCovidTestProceduresList(context).then((res) { + if (res['MessageStatus'] == 1) { + print(res); + setState(() { + res['COVID19_TestProceduresList'].forEach((v) { + proceduresList.add(new CovidTestProceduresResponse.fromJson(v)); + }); }); + print(proceduresList.length); + print(proceduresList[0].procedureName); + GifLoaderDialogUtils.hideDialog(context); + } else {} + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); } getProjectsList(BuildContext context) { CovidDriveThruService service = new CovidDriveThruService(); GifLoaderDialogUtils.showMyDialog(context); service.getCovidProjectsList(context).then((res) { - print(res); if (res['MessageStatus'] == 1) { - print(res); setState(() { res['List_COVID19_ProjectDriveThroughTestingCenter'].forEach((v) { projectsList.add(new DriveThroughTestingCenterModel.fromJson(v)); diff --git a/lib/pages/Covid-DriveThru/covid-payment-details.dart b/lib/pages/Covid-DriveThru/covid-payment-details.dart index e6c87d0a..488dd3bf 100644 --- a/lib/pages/Covid-DriveThru/covid-payment-details.dart +++ b/lib/pages/Covid-DriveThru/covid-payment-details.dart @@ -1,5 +1,8 @@ import 'package:diplomaticquarterapp/models/CovidDriveThru/CovidPaymentInfoResponse.dart'; +import 'package:diplomaticquarterapp/models/CovidDriveThru/CovidTestProceduresResponse.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/Covid-TimeSlots.dart'; +import 'package:diplomaticquarterapp/services/covid-drivethru/covid-drivethru.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -10,9 +13,13 @@ import 'package:flutter_svg/flutter_svg.dart'; class CovidPaymentDetails extends StatefulWidget { CovidPaymentInfoResponse covidPaymentInfoResponse; int projectID; + List proceduresList; + CovidTestProceduresResponse selectedProcedure; CovidPaymentDetails( - {@required this.covidPaymentInfoResponse, @required this.projectID}); + {@required this.covidPaymentInfoResponse, + @required this.projectID, + @required this.proceduresList}); @override _CovidPaymentDetailsState createState() => _CovidPaymentDetailsState(); @@ -21,6 +28,13 @@ class CovidPaymentDetails extends StatefulWidget { class _CovidPaymentDetailsState extends State { bool isAgree = false; + @override + void initState() { + print(widget.proceduresList[0].procedureName); + widget.selectedProcedure = widget.proceduresList[0]; + super.initState(); + } + @override Widget build(BuildContext context) { return AppScaffold( @@ -28,7 +42,7 @@ class _CovidPaymentDetailsState extends State { isShowAppBar: true, body: SingleChildScrollView( child: Container( - margin: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0.0), + margin: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 100.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -82,13 +96,75 @@ class _CovidPaymentDetailsState extends State { borderRadius: BorderRadius.circular(10.0), color: Colors.white), margin: EdgeInsets.fromLTRB(0.0, 30.0, 0.0, 5.0), - padding: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 20.0), + padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 20.0), child: Column( children: [ Container( alignment: Alignment.center, margin: - EdgeInsets.only(left: 0.0, right: 20.0, top: 30.0), + EdgeInsets.only(left: 0.0, right: 20.0, top: 10.0), + child: Text( + TranslationBase.of(context).covidSelectProcedure, + style: TextStyle( + color: Colors.black, + fontSize: 20.0, + fontWeight: FontWeight.bold)), + ), + ...List.generate( + widget.proceduresList.length, + (index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 1, + ), + Row( + children: [ + Expanded( + flex: 1, + child: InkWell( + onTap: () { + setState(() { + widget.selectedProcedure = + widget.proceduresList[index]; + }); + }, + child: ListTile( + title: Text( + widget.proceduresList[index] + .procedureName, + style: TextStyle(fontSize: 14.0)), + leading: Radio( + value: widget.proceduresList[index], + groupValue: widget.selectedProcedure, + activeColor: Colors.red[800], + toggleable: true, + onChanged: (value) { + setState(() { + widget.selectedProcedure = value; + print(widget + .selectedProcedure.procedureName); + getPaymentInfo( + context, + widget.projectID.toString(), + widget.selectedProcedure + .procedureID); + }); + }, + ), + ), + ), + ) + ], + ), + ], + ), + ), + Divider(), + Container( + alignment: Alignment.center, + margin: + EdgeInsets.only(left: 0.0, right: 20.0, top: 10.0), child: Text(TranslationBase.of(context).testFee, style: TextStyle( color: Colors.black, @@ -144,7 +220,7 @@ class _CovidPaymentDetailsState extends State { isAgree = !isAgree; }); }, - activeColor: Colors.blue, + activeColor: Color(0xffB8382C), ), Texts(TranslationBase.of(context) .iAgreeToTheTermsAndConditions), @@ -238,6 +314,7 @@ class _CovidPaymentDetailsState extends State { FadePage( page: CovidTimeSlots( projectID: widget.projectID, + selectedProcedure: widget.selectedProcedure, ))); } @@ -245,6 +322,34 @@ class _CovidPaymentDetailsState extends State { Navigator.pop(context); } + getPaymentInfo( + BuildContext context, String projectID, String selectedProcedureID) { + CovidDriveThruService service = new CovidDriveThruService(); + GifLoaderDialogUtils.showMyDialog(context); + service + .getCovidPaymentInformation( + context, int.parse(projectID), selectedProcedureID) + .then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (res['MessageStatus'] == 1) { + setState(() { + widget.covidPaymentInfoResponse = + CovidPaymentInfoResponse.fromJson(res['COVID19_PatientShare']); + }); + // Navigator.push( + // context, + // FadePage( + // page: CovidPaymentDetails( + // covidPaymentInfoResponse: covidPaymentInfoResponse, + // projectID: int.parse(projectID), + // proceduresList: proceduresList, + // ))); + } else {} + }).catchError((err) { + print(err); + }); + } + _getNormalText(text) { return Container( margin: EdgeInsets.only(top: 20.0, right: 10.0), diff --git a/lib/pages/DrawerPages/family/add-family_type.dart b/lib/pages/DrawerPages/family/add-family_type.dart index 96e055b3..e4a82cb4 100644 --- a/lib/pages/DrawerPages/family/add-family_type.dart +++ b/lib/pages/DrawerPages/family/add-family_type.dart @@ -75,7 +75,7 @@ class AddFamilyMemberType extends StatelessWidget { ), AppText( TranslationBase.of(context) - .nationalID, + .idNo, fontSize: SizeConfig .textMultiplier * 2, diff --git a/lib/pages/DrawerPages/family/my-family.dart b/lib/pages/DrawerPages/family/my-family.dart index baac5c63..e4e582bb 100644 --- a/lib/pages/DrawerPages/family/my-family.dart +++ b/lib/pages/DrawerPages/family/my-family.dart @@ -351,9 +351,21 @@ class _MyFamily extends State with TickerProviderStateMixin { Padding( padding: EdgeInsets.only(left: 10, right: 10), child: Row(children: [ - Expanded(flex: 3, child: AppText('Name')), - Expanded(flex: 1, child: AppText('Allow')), - Expanded(flex: 1, child: AppText('Reject')), + Expanded( + flex: 3, + child: AppText( + TranslationBase.of(context) + .name)), + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context) + .allow)), + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context) + .reject)), ])), Column( children: familyFileProvider.allSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList.map((result) { @@ -487,8 +499,16 @@ class _MyFamily extends State with TickerProviderStateMixin { Padding( padding: EdgeInsets.only(left: 10, right: 10), child: Row(children: [ - Expanded(flex: 3, child: AppText('Name')), - Expanded(flex: 1, child: AppText('Delete')), + Expanded( + flex: 3, + child: AppText( + TranslationBase.of(context) + .name)), + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context) + .delete)), ])), Column( children: familyFileProvider.allSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList.map((result) { diff --git a/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart b/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart index 63d915d1..6f3281dc 100644 --- a/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart +++ b/lib/pages/ErService/AmbulanceRequestIndexPages/SelectTransportationMethod.dart @@ -206,7 +206,7 @@ class _SelectTransportationMethodState SizedBox( height: 8, ), - Texts(TranslationBase.of(context).directionHeading), + Texts(TranslationBase.of(context).wayHeading), SizedBox( height: 5, ), diff --git a/lib/pages/ErService/ErOptions.dart b/lib/pages/ErService/ErOptions.dart index e0ff3ed4..632d9f86 100644 --- a/lib/pages/ErService/ErOptions.dart +++ b/lib/pages/ErService/ErOptions.dart @@ -1,8 +1,13 @@ +import 'dart:convert'; + +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/ErService/rapid-response-team/rrt-main-screen.dart'; import 'package:diplomaticquarterapp/uitl/location_util.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import '../../uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/pages/ErService/widgets/card_common.dart'; @@ -23,6 +28,7 @@ class ErOptions extends StatefulWidget { class _ErOptionsState extends State { LocationUtils locationUtils; + ProjectViewModel projectViewModel; @override void initState() { @@ -35,9 +41,13 @@ class _ErOptionsState extends State { } @override Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + final rrtLocked = !projectViewModel.havePrivilege(68); + return AppScaffold( isShowAppBar: widget.isAppbar, appBarTitle: TranslationBase.of(context).bookAppo, + isShowDecPage: false, body: Container( margin: EdgeInsets.fromLTRB(10.0, 20.0, 10.0, 10.0), child: Column( @@ -45,6 +55,7 @@ class _ErOptionsState extends State { children: [ Container( + height: 170, margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), child: Row( mainAxisSize: MainAxisSize.max, @@ -82,6 +93,7 @@ class _ErOptionsState extends State { ), Container( margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), + height: 170, child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, @@ -94,14 +106,24 @@ class _ErOptionsState extends State { onTap: (){ Navigator.push( context, - FadePage( - page: DdServicesPage())); + FadePage(page: DdServicesPage()) + ); }, ), ), Expanded( - child: Container(), + child: CardCommonEr( + locked: rrtLocked, + image: 'assets/images/new-design/AM.PNG', + text: TranslationBase.of(context).rrtService, + subText: TranslationBase.of(context).RapidResponseTeam, + onTap:(){ + Navigator.push( + context, + FadePage( + page: RRTMainScreen())); + }), ) ], ), diff --git a/lib/pages/ErService/NearestEr.dart b/lib/pages/ErService/NearestEr.dart index eaf0d4ef..cbafacce 100644 --- a/lib/pages/ErService/NearestEr.dart +++ b/lib/pages/ErService/NearestEr.dart @@ -31,6 +31,7 @@ class NearestEr extends StatelessWidget { : (model) => model.getProjectAvgERWaitingTimeOrders(), builder: (_, mode, widget) => AppScaffold( isShowAppBar: true, + isShowDecPage: false, appBarTitle: TranslationBase.of(context).NearestEr, baseViewModel: mode, body: mode.ProjectAvgERWaitingTimeModeList.length > 0 diff --git a/lib/pages/ErService/rapid-response-team/rrt-logs-page.dart b/lib/pages/ErService/rapid-response-team/rrt-logs-page.dart new file mode 100644 index 00000000..acfe13d8 --- /dev/null +++ b/lib/pages/ErService/rapid-response-team/rrt-logs-page.dart @@ -0,0 +1,94 @@ +import 'package:diplomaticquarterapp/core/viewModels/er/rrt-view-model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + + +class RRTLogPage extends StatefulWidget{ + + @override + State createState() => RRTLogPageState(); + +} +class RRTLogPageState extends State{ + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (viewModel){ + + }, + builder: (ctx, vm, widget){ + return ListView.builder( + itemCount: 10, + itemBuilder: (ctx, idx) => RRTLogListItem() + ); + } + ); + } + +} + + + +// ------------------------ +// List Item Widget +// ------------------------ + + +final _item_content_seperator = Container(height: 0.25, padding: EdgeInsets.all(10), color: Colors.grey.withOpacity(0.5)); + +class RRTLogListItem extends StatelessWidget{ + BuildContext _context; + @override + Widget build(BuildContext context) { + _context = context; + + return Container( + padding: EdgeInsets.all(15), margin: EdgeInsets.symmetric(horizontal: 15, vertical: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15), + boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.25), spreadRadius: 1, blurRadius: 3)] + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _contentItem(label: "Request ID", value: "2318"), + _item_content_seperator, + _contentItem(label: "Status", value: "2318"), + _item_content_seperator, + _contentItem(label: "Pickup Date", value: "2318"), + _item_content_seperator, + _contentItem(label: "Location", value: "2318"), + _item_content_seperator, + SizedBox(height: 10), + FractionallySizedBox(child: cancelButton()) + ], + ), + ); + } + + Widget _contentItem({@required String label, String value}){ + return Container( + padding: EdgeInsets.symmetric(vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: TextStyle(color: Theme.of(_context).appBarTheme.color, fontSize: 9, letterSpacing: 1),), + SizedBox(height: 5,), + Text(value, style: TextStyle(color: Theme.of(_context).appBarTheme.color,fontWeight: FontWeight.bold, fontSize: 14),), + ], + ), + ); + } + + Widget cancelButton() => MaterialButton( + height: 45, + color: Color(0xFFc5272d), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10) ), + onPressed: () { }, + child: Text("CANCEL", style: TextStyle(color: Colors.white, fontSize: 13),), + + ); +} + diff --git a/lib/pages/ErService/rapid-response-team/rrt-main-screen.dart b/lib/pages/ErService/rapid-response-team/rrt-main-screen.dart new file mode 100644 index 00000000..fe1c6a9d --- /dev/null +++ b/lib/pages/ErService/rapid-response-team/rrt-main-screen.dart @@ -0,0 +1,77 @@ + +import 'package:diplomaticquarterapp/pages/ErService/rapid-response-team/rrt-logs-page.dart'; +import 'package:diplomaticquarterapp/pages/ErService/rapid-response-team/rrt-request-page.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class RRTMainScreen extends StatefulWidget{ + @override + State createState() => RRTMainScreenState(); +} + +class RRTMainScreenState extends State with SingleTickerProviderStateMixin{ + + int currentIndex = 0; + TabController tabController; + PageController pageController = PageController(initialPage: 0, keepPage: true); + + @override + void initState() { + super.initState(); + tabController = TabController(length: 2, vsync: this); + } + + @override + Widget build(BuildContext context) { + + return AppScaffold( + appBarTitle: 'Rapid Response Team', + isShowAppBar: true, + body: Column( + children: [ + tabBar(), + Expanded( + child: contentPager() + ) + ], + ), + ); + } + + Widget tabBar() => Container( + margin: EdgeInsets.all(15), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(10)), + child: TabBar( + onTap: onPageChanged, + indicatorWeight: 3, + indicatorColor: Color(0xFFc5272d), + isScrollable: false, + controller: tabController, + indicatorSize: TabBarIndicatorSize.label, + tabs: [ + Tab( + child: Text("Rapid Response Team", style: TextStyle(color: Theme.of(context).appBarTheme.color),), + ), + Tab( + child: Text("Order Log", style: TextStyle(color: Theme.of(context).appBarTheme.color),), + ), + ] + ), + ); + + Widget contentPager() => PageView( + onPageChanged: onPageChanged, + controller: pageController, + children: [ + RRTRequestPage(), + RRTLogPage(), + ], + ); + + void onPageChanged(int index) { + pageController.animateToPage(index, duration: Duration(milliseconds: 200), curve: Curves.easeInOut); + tabController.animateTo(index); + } +} diff --git a/lib/pages/ErService/rapid-response-team/rrt-pickup-address-page.dart b/lib/pages/ErService/rapid-response-team/rrt-pickup-address-page.dart new file mode 100644 index 00000000..91e9cbd2 --- /dev/null +++ b/lib/pages/ErService/rapid-response-team/rrt-pickup-address-page.dart @@ -0,0 +1,92 @@ +import 'dart:async'; + +import 'package:diplomaticquarterapp/core/viewModels/er/rrt-view-model.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +class RRTRequestPickupAddressPage extends StatefulWidget{ + + @override + State createState() => RRTRequestPickupAddressPageState(); + +} +class RRTRequestPickupAddressPageState extends State{ + bool acceptTerms = false; + Completer mapController = Completer(); + + static final CameraPosition mapCamera = CameraPosition( + target: LatLng(37.42796133580664, -122.085749655962), + zoom: 14.4746, + ); + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (viewModel){ + + }, + builder: (ctx, vm, widget) => AppScaffold( + appBarTitle: TranslationBase.of(context).pickupLocation, + isShowAppBar: true, + body: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + selectAddress(), + Expanded( + child: GoogleMap( + mapType: MapType.normal, + initialCameraPosition: mapCamera, + onCameraIdle: (){ + + }, + onMapCreated: (controller){ + mapController.complete(controller); + }, + ) + ), + continueButton() + ], + ) + ) + ); + } + + Widget selectAddress(){ + return Container( + margin: EdgeInsets.all(15), + child: Expanded( + child: MaterialButton( + height: 50, + color: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10) ), + onPressed: () { }, + child: Row( + children: [ + Text(TranslationBase.of(context).selectAddress, style: TextStyle(color: Colors.white, fontSize: 13, letterSpacing: 1),), + Spacer(), + Icon(Icons.keyboard_arrow_down, size: 15, color: Colors.grey,) + ], + ), + ), + ), + ); + } + + Widget continueButton(){ + return Padding( + padding: const EdgeInsets.all(15), + child: MaterialButton( + height: 50, + color: Theme.of(context).appBarTheme.color, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10) ), + onPressed: () { }, + child: Text(TranslationBase.of(context).continues, style: TextStyle(color: Colors.white, fontSize: 15, letterSpacing: 1),), + ), + ); + } + +} \ No newline at end of file diff --git a/lib/pages/ErService/rapid-response-team/rrt-request-page.dart b/lib/pages/ErService/rapid-response-team/rrt-request-page.dart new file mode 100644 index 00000000..9fb0a2f5 --- /dev/null +++ b/lib/pages/ErService/rapid-response-team/rrt-request-page.dart @@ -0,0 +1,176 @@ +import 'package:diplomaticquarterapp/core/viewModels/er/rrt-view-model.dart'; +import 'package:diplomaticquarterapp/pages/ErService/rapid-response-team/rrt-pickup-address-page.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class RRTRequestPage extends StatefulWidget{ + + @override + State createState() => RRTRequestPageState(); + +} +class RRTRequestPageState extends State{ + bool acceptTerms = false; + + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (viewModel){ + + }, + builder: (ctx, vm, widget) => Column( + children: [ + Expanded( + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15), + children: [ + serviceDescription(context), + SizedBox(height: 20), + priceTable(context), + + acceptPolicy(), + + Container(height: 0.5, color: Theme.of(context).appBarTheme.color),// Seperator + + Container( + padding: EdgeInsets.only(top: 20, bottom: 5), + alignment: Alignment.center, + child: Text(TranslationBase.of(context).YouCanPayByTheFollowingOptions, style: TextStyle(fontSize: 13, color: Theme.of(context).appBarTheme.color, fontWeight: FontWeight.w500), maxLines: 2) + ), + + paymentOptions(), + ], + ), + ), + + actionButtons() + ], + ) + ); + } + + Widget serviceDescription(BuildContext context) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + TranslationBase.of(context).RRTDDetails, + textAlign: TextAlign.justify, + style: TextStyle(color: Theme.of(context).appBarTheme.color, fontSize: 15, height: 1.5, fontWeight: FontWeight.w300), + ), + ); + + Widget priceTable(BuildContext context){ + var radius = Radius.circular(8); + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + height: 30, + decoration: BoxDecoration(color: Theme.of(context).appBarTheme.color, borderRadius: BorderRadius.only(topLeft: radius, topRight: radius)), + child: Center(child: Text(TranslationBase.of(context).ApproximateServiceFee, style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500, letterSpacing: 1))), + ), + + pricingRow(label: TranslationBase.of(context).AmountBeforeTax, value: '500 SAR'), + Container(height: 0.5, color: Theme.of(context).appBarTheme.color), + + pricingRow(label: TranslationBase.of(context).TaxAmount, value: '50 SAR'), + Container(height: 0.5, color: Theme.of(context).appBarTheme.color), + + pricingRow(label: TranslationBase.of(context).TotalAmountPayable, value: '550 SAR', labelBold: true), + Container(height: 0.5, color: Theme.of(context).appBarTheme.color), + ], + ); + } + + Widget pricingRow({@required String label, @required String value, bool labelBold = false, bool valueBold = false}){ + return + Container( + height: 40, margin: EdgeInsets.symmetric(horizontal: 10), + child: Row( + children: [ + Text(label, style: TextStyle(fontSize: 13, color: Theme.of(context).appBarTheme.color, fontWeight: labelBold ? FontWeight.bold : FontWeight.normal)), + Spacer(), + Container(height: 40, color: Theme.of(context).appBarTheme.color, width: 0.5,), + Container( + alignment: Alignment.center, + width: MediaQuery.of(context).size.width * 0.25, + child: Text(value, style: TextStyle(fontSize: 13, color: Theme.of(context).appBarTheme.color, fontWeight: valueBold ? FontWeight.bold : FontWeight.normal)) + ), + ], + ), + ); + } + + + Widget acceptPolicy(){ + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Row( + children: [ + Checkbox(value: acceptTerms, onChanged: (v){ + setState(() => acceptTerms = v); + }), + SizedBox(width: 10), + Expanded( + child: Text(TranslationBase.of(context).iAcceptTermsConditions, style: TextStyle(fontSize: 13, color: Theme.of(context).appBarTheme.color), maxLines: 2) + ), + Container( + alignment: Alignment.center, + width: MediaQuery.of(context).size.width * 0.25, + child: TextButton( + child: Text(TranslationBase.of(context).clickHere, style: TextStyle(fontSize: 12, color: Colors.blue, fontWeight: FontWeight.w400)), + onPressed: (){ + + } + ), + ) + ], + ), + ); + } + + Widget paymentOptions()=> Container( + height: 30, + alignment: Alignment.center, + child: Image.asset("assets/payment_options/payment_options.png", fit: BoxFit.fill,) + ); + + Widget actionButtons(){ + return Container( + margin: EdgeInsets.all(15), + child: Row( + children: [ + Expanded( + child: MaterialButton( + height: 50, + color: Theme.of(context).appBarTheme.color, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10) ), + onPressed: () { }, + child: Text(TranslationBase.of(context).cancel, style: TextStyle(color: Colors.white, fontSize: 13, letterSpacing: 1),), + + ), + ), + SizedBox(width: 20,), + Expanded( + child: MaterialButton( + height: 50, + color: Theme.of(context).appBarTheme.color, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10) ), + child: Text(TranslationBase.of(context).ok, style: TextStyle(color: Colors.white, fontSize: 13, letterSpacing: 1),), + onPressed: () { + Navigator.push( + context, + FadePage( + page: RRTRequestPickupAddressPage())); + }, + ), + ) + ], + ), + ); + } + +} \ No newline at end of file diff --git a/lib/pages/ErService/widgets/card_common.dart b/lib/pages/ErService/widgets/card_common.dart index 6b396dc9..cd0dfaa9 100644 --- a/lib/pages/ErService/widgets/card_common.dart +++ b/lib/pages/ErService/widgets/card_common.dart @@ -10,51 +10,72 @@ class CardCommonEr extends StatelessWidget { final image; final text; final subText; + final bool locked; final Function onTap; const CardCommonEr( - {@required this.image, - @required this.text, - @required this.subText, - @required this.onTap}); + { + this.locked = false, + @required this.image, + @required this.text, + @required this.subText, + @required this.onTap, + }); @override Widget build(BuildContext context) { return GestureDetector( - onTap: () => onTap(), - child: Container( - margin: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0), - decoration: BoxDecoration(boxShadow: [ - BoxShadow(color: Colors.grey[400], blurRadius: 2.0, spreadRadius: 0.0) - ], borderRadius: BorderRadius.circular(10), color: Colors.white), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + onTap: locked ? null : onTap, + child: Opacity( + opacity: locked ? 0.25 : 1.0, + child: Stack( + children: [ Container( - margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0), - child: Text(this.text, - overflow: TextOverflow.clip, - style: TextStyle( - color: new Color(0xFFc5272d), - letterSpacing: 1.0, - fontSize: 20.0)), + margin: EdgeInsets.fromLTRB(9.0, 9.0, 9.0, 9.0), + decoration: BoxDecoration(boxShadow: [ + BoxShadow(color: Colors.grey[400], blurRadius: 2.0, spreadRadius: 0.0) + ], borderRadius: BorderRadius.circular(10), color: Colors.white), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0), + child: Text(this.text, + overflow: TextOverflow.clip, + style: TextStyle( + color: new Color(0xFFc5272d), + letterSpacing: 1.0, + fontSize: 20.0)), + ), + Container( + margin: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0), + child: Text(this.subText, + overflow: TextOverflow.clip, + style: TextStyle( + color: Colors.black, letterSpacing: 1.0, fontSize: 15.0)), + ), + Spacer(), + Container( + alignment: Alignment.bottomRight, + margin: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 8.0), + child: Image.asset(this.image, width: 60.0, height: 60.0), + ), + ], ), - Container( - margin: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0), - child: Text(this.subText, - overflow: TextOverflow.clip, - style: TextStyle( - color: Colors.black, letterSpacing: 1.0, fontSize: 15.0)), - ), - Container( - alignment: Alignment.bottomRight, - margin: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 8.0), - child: Image.asset(this.image, width: 60.0, height: 60.0), - ), - ], + ), + if(locked) + Align( + alignment: Alignment.center, + child: lock() + ) + ] , ), ), ); } + Widget lock(){ + return Container(child: Icon(Icons.lock_rounded, size: 80),); + } + } diff --git a/lib/pages/MyAppointments/widgets/AppointmentCardView.dart b/lib/pages/MyAppointments/widgets/AppointmentCardView.dart index 51e18ff4..31a7cb2d 100644 --- a/lib/pages/MyAppointments/widgets/AppointmentCardView.dart +++ b/lib/pages/MyAppointments/widgets/AppointmentCardView.dart @@ -195,7 +195,7 @@ class _ApointmentCardState extends State { widgetBuilder: (_, CurrentRemainingTime time) { return time != null ? Text( - '${time.days}:${time.hours}:${time.min}:${time.sec} ' + + '${time.days != null ? time.days : "0"}:${time.hours != null ? time.hours : "0"}:${time.min}:${time.sec} ' + TranslationBase.of(context) .upcomingTimeLeft, style: TextStyle( diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index 266a0a70..298b121c 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -93,9 +93,16 @@ class _ToDoState extends State { padding: EdgeInsets.all(0.0), itemCount: widget.appoList.length, itemBuilder: (context, index) { + print("ttt "+getNextActionImage(widget + .appoList[index] + .nextAction)); + print("ttt "+widget + .appoList[index] + .nextAction.toString()); return Container( margin: EdgeInsets.all(10.0), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( child: Card( @@ -367,44 +374,32 @@ class _ToDoState extends State { color: Color(0xff20bc44), ), height: 30.0, - margin: projectViewModel.isArabic - ? EdgeInsets.fromLTRB(160.0, 0.0, 30.0, 0.0) - : EdgeInsets.fromLTRB(20.0, 0.0, 160.0, 0.0), + padding: EdgeInsets.only(right:15), + margin: EdgeInsets.symmetric(horizontal:20), transform: Matrix4.translationValues(0.0, -8.0, 0.0), child: Row( + mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [ widget.appoList[index].isLiveCareAppointment - ? Container( - margin: EdgeInsets.fromLTRB( - 5.0, 0.0, 5.0, 0.0), - child: Image.asset( - "assets/images/new-design/video.png"), - ) - : Container( - margin: EdgeInsets.fromLTRB( - 5.0, 0.0, 5.0, 0.0), - child: Image.asset( - "assets/images/new-design/walkin.png"), - ), + ? Image.asset( + "assets/images/new-design/video.png") + : Image.asset( + "assets/images/new-design/walkin.png"), widget.appoList[index].isLiveCareAppointment - ? Container( - child: Text( - TranslationBase.of(context).videoAppo, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 11.0)), - ) - : Container( - child: Text( - TranslationBase.of(context) - .walkinAppo, - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 11.0)), - ) + ? Text( + TranslationBase.of(context).videoAppo, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 11.0)) + : Text( + TranslationBase.of(context) + .walkinAppo, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 11.0)) ], ), ), @@ -460,6 +455,10 @@ class _ToDoState extends State { return "assets/images/new-design/waiting_for_doctor.png"; break; + case 90: + return "assets/images/new-design/check-in.png"; + break; + default: return ""; } @@ -481,6 +480,9 @@ class _ToDoState extends State { break; case 60: break; + case 90: + getAppoQR(context, appo); + break; } } @@ -517,6 +519,10 @@ class _ToDoState extends State { return TranslationBase.of(context).waitingForDoctor; break; + case 90: + return TranslationBase.of(context).checkinOptions; + break; + default: return ""; } diff --git a/lib/pages/feedback/send_feedback_page.dart b/lib/pages/feedback/send_feedback_page.dart index fca9624c..a8e553be 100644 --- a/lib/pages/feedback/send_feedback_page.dart +++ b/lib/pages/feedback/send_feedback_page.dart @@ -19,6 +19,7 @@ import 'package:diplomaticquarterapp/widgets/others/floating_button_search.dart' import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:speech_to_text/speech_recognition_error.dart'; import 'dart:convert'; import 'dart:io'; @@ -326,9 +327,9 @@ class _SendFeedbackPageState extends State { fontSize: 13.5, hintColor: Colors.black, fontWeight: FontWeight.w600, - onChanged: (v){setState(() { - - });}, + onChanged: (v) { + setState(() {}); + }, validator: (value) { if (value.isEmpty) return TranslationBase.of(context).emptySubject; @@ -349,11 +350,13 @@ class _SendFeedbackPageState extends State { controller: messageController, suffixIcon: Icons.mic, onSuffixTap: () { + requestPermissions(); + openSpeechReco(); }, - onChanged: (v){setState(() { - - });}, + onChanged: (v) { + setState(() {}); + }, validator: (value) { if (value.isEmpty) return TranslationBase.of(context).emptyMessage; @@ -437,7 +440,7 @@ class _SendFeedbackPageState extends State { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.12, + height: 80, width: double.infinity, padding: EdgeInsets.all(15.0), child: Center( @@ -447,39 +450,37 @@ class _SendFeedbackPageState extends State { label: TranslationBase.of(context).send, textColor: Colors.white, disabled: (titleController.text.toString().isEmpty || - messageController.text.toString().isEmpty ), + messageController.text.toString().isEmpty), onTap: () { final form = formKey.currentState; if (form.validate()) { - - GifLoaderDialogUtils.showMyDialog(context); - model - .sendCOCItem( - title: titleController.text, - attachment: images.length > 0 ? images[0] : "", - details: messageController.text, - cOCTypeName: getCOCName(), - appointHistory: messageType == - MessageType.ComplaintOnAnAppointment - ? appointHistory - : null) - .then((value) { - if (value) { - setState(() { - titleController.text = ""; - messageController.text = ""; - images = []; - }); - setMessageType(MessageType.NON); - GifLoaderDialogUtils.hideDialog(context); - AppToast.showSuccessToast( - message: TranslationBase.of(context).yourFeedback); - } else { - AppToast.showErrorToast(message: model.error); - GifLoaderDialogUtils.hideDialog(context); - } - }); - + GifLoaderDialogUtils.showMyDialog(context); + model + .sendCOCItem( + title: titleController.text, + attachment: images.length > 0 ? images[0] : "", + details: messageController.text, + cOCTypeName: getCOCName(), + appointHistory: messageType == + MessageType.ComplaintOnAnAppointment + ? appointHistory + : null) + .then((value) { + if (value) { + setState(() { + titleController.text = ""; + messageController.text = ""; + images = []; + }); + setMessageType(MessageType.NON); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showSuccessToast( + message: TranslationBase.of(context).yourFeedback); + } else { + AppToast.showErrorToast(message: model.error); + GifLoaderDialogUtils.hideDialog(context); + } + }); } }, ), @@ -544,7 +545,7 @@ class _SendFeedbackPageState extends State { if (available) { speech.listen( onResult: resultListener, - // listenMode: ListenMode.confirmation, + listenMode: stt.ListenMode.confirmation, localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA', ); } else { @@ -552,12 +553,23 @@ class _SendFeedbackPageState extends State { } } - void errorListener(SpeechRecognitionError error) {} + void errorListener(SpeechRecognitionError error) { + event.setValue({"searchText": 'null'}); + //SpeechToText.closeAlertDialog(context); + print(error); + } void statusListener(String status) { reconizedWord = status == 'listening' ? 'Lisening...' : 'Sorry....'; } + void requestPermissions() async { + Map statuses = await [ + Permission.microphone, + ].request(); + print(statuses); + } + void resultListener(result) { reconizedWord = result.recognizedWords; event.setValue({"searchText": reconizedWord}); @@ -565,10 +577,18 @@ class _SendFeedbackPageState extends State { if (result.finalResult == true) { setState(() { RoboSearch.closeAlertDialog(context); - messageController.text = reconizedWord; + speech.stop(); + messageController.text = reconizedWord + '\n'; }); } } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize( + onError: errorListener, onStatus: statusListener); + print(hasSpeech); + if (!mounted) return; + } } class FeedbackTypeDialog extends StatefulWidget { @@ -588,7 +608,6 @@ class FeedbackTypeDialogState extends State { setMessageDialogType(MessageType messageType) { setState(() { - messageTypeDialog = messageType; }); } diff --git a/lib/pages/feedback/status_feedback_page.dart b/lib/pages/feedback/status_feedback_page.dart index e37f3138..5b297e89 100644 --- a/lib/pages/feedback/status_feedback_page.dart +++ b/lib/pages/feedback/status_feedback_page.dart @@ -93,16 +93,24 @@ class _StatusFeedbackPageState extends State { child: Center( child: Column( children: [ - SizedBox(height: MediaQuery.of(context).size.height*0.4,), - Image.asset('assets/images/comments.png',width: 80,height: 80,), - SizedBox(height: 15,), + SizedBox( + height: MediaQuery.of(context).size.height * 0.4, + ), + Image.asset( + 'assets/images/comments.png', + width: 80, + height: 80, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).noSearchResult), ], ), ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.12, + height: 80, width: double.infinity, padding: EdgeInsets.all(15.0), child: Center( @@ -112,8 +120,7 @@ class _StatusFeedbackPageState extends State { label: TranslationBase.of(context).search, textColor: Colors.white, disabled: true, - onTap: () { - }, + onTap: () {}, ), ), ), diff --git a/lib/pages/insurance/insurance_approval_screen.dart b/lib/pages/insurance/insurance_approval_screen.dart index d81e704e..7283abf8 100644 --- a/lib/pages/insurance/insurance_approval_screen.dart +++ b/lib/pages/insurance/insurance_approval_screen.dart @@ -24,23 +24,13 @@ class _InsuranceApprovalState extends State { @override Widget build(BuildContext context) { - imagesInfo.add(ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/en/0.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/ar/0.png')); - imagesInfo.add(ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/en/1.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/ar/1.png')); + imagesInfo + .add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/en/0.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/ar/0.png')); + imagesInfo + .add(ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/en/1.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/apporvals/ar/1.png')); return BaseView( - onModelReady: widget.appointmentNo != null - ? (model) => - model.getInsuranceApproval(appointmentNo: widget.appointmentNo) - : (model) => model.getInsuranceApproval(), - builder: (BuildContext context, InsuranceViewModel model, Widget child) => - AppScaffold( + onModelReady: widget.appointmentNo != null ? (model) => model.getInsuranceApproval(appointmentNo: widget.appointmentNo) : (model) => model.getInsuranceApproval(), + builder: (BuildContext context, InsuranceViewModel model, Widget child) => AppScaffold( isShowAppBar: true, baseViewModel: model, appBarTitle: TranslationBase.of(context).approvals, @@ -65,153 +55,121 @@ class _InsuranceApprovalState extends State { children: [ Texts( TranslationBase.of(context).totalApproval, - color: Color(0xff60688B), - fontSize: 19.0, - fontWeight: FontWeight.w600, + color: Color(0xff60688B), + fontSize: 19.0, + fontWeight: FontWeight.w600, ), if (model.insuranceApproval.length > 0) Container( width: 60, height: 40, - decoration: BoxDecoration( - color: Theme.of(context).primaryColor, - borderRadius: BorderRadius.circular(19.0)), + decoration: BoxDecoration(color: Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(19.0)), child: Center( child: Texts( - model.insuranceApproval[0].unUsedCount - .toString(), - color: Colors.white, fontSize: 17.0, + model.insuranceApproval[0].unUsedCount.toString(), + color: Colors.white, + fontSize: 17.0, ), )) ], )), - ...List.generate( - model.insuranceApproval.length, - (index) => RoundedContainer( - backgroundColor: Colors.white, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ExpansionTile( - title: Container( - //height: 120.0, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - model.insuranceApproval[index].patientDescription == "In Patient" - ? Container( - decoration: BoxDecoration( - color: Theme.of(context).primaryColor, - borderRadius: - BorderRadius.circular( - 16.0)), - width: 115.0, - padding: - EdgeInsets.only(left: 11.5), - child: Center( - child: Texts( - TranslationBase.of(context).inPatient, - color: Colors.white, - ), - ), - ) - : Container( - decoration: BoxDecoration( - color: Color(0xff505A5D), - borderRadius: - BorderRadius.circular( - 16.0)), - width: 115.0, - padding: - EdgeInsets.only(left: 11.5), - child: Center( - child: Texts( - TranslationBase.of(context).outpatient, - color: Colors.white, - ), - ), - ), - Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0), - child: Texts( - model.insuranceApproval[index] - .clinicName, - fontSize: 20.0, - color: Color(0xff60686B), - fontWeight: FontWeight.w600, - ), + ...List.generate(model.insuranceApproval.length, (index) { + print(model.insuranceApproval[index].isLiveCareAppointment); + return RoundedContainer( + backgroundColor: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ExpansionTile( + title: Container( + //height: 120.0, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + model.insuranceApproval[index].isLiveCareAppointment + ? sideBadge(TranslationBase.of(context).liveCare, 0xffA9A089) + : model.insuranceApproval[index].isInOutPatient + ? sideBadge(TranslationBase.of(context).outpatient, 0xff505a5d) + : sideBadge(TranslationBase.of(context).inPatient, 0xffb8372c), + Padding( + padding: EdgeInsets.symmetric(vertical: 10.0), + child: Texts( + model.insuranceApproval[index].clinicName, + fontSize: 20.0, + color: Color(0xff60686B), + fontWeight: FontWeight.w600, + ), + ), + Texts( + model.insuranceApproval[index].doctorName, + fontSize: 17.0, + ), + ], + ), + ), + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Texts( + TranslationBase.of(context).approvalNo, + fontSize: 18.0, ), Texts( - model.insuranceApproval[index] - .doctorName, - fontSize: 17.0, + model.insuranceApproval[index].approvalNo.toString(), + fontSize: 18.0, + fontWeight: FontWeight.w600, ), ], ), - ), - children: [ - Padding( - padding: EdgeInsets.symmetric( - vertical: 12.0, horizontal: 12.0), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - children: [ - Texts( - TranslationBase.of(context).approvalNo, - fontSize: 18.0, - ), - Texts(model.insuranceApproval[index].approvalNo.toString(), - fontSize: 18.0, - fontWeight: FontWeight.w600,), - ], - ), - Divider( - color: Colors.black, - height: 25.0, - thickness: 1.0, - ), - Row( - children: [ - Texts( - TranslationBase.of(context).procedureStatus , - fontSize: 17.5, - ), - SizedBox(width: 12,), - Texts( - model.insuranceApproval[index].approvalStatusDescption, - fontWeight: FontWeight.w600, - fontSize: 17.5, - ), - ], - ), - Divider( - color: Colors.black, - height: 25.0, - thickness: 1.0, - ), - Row( - children: [ - Texts( - TranslationBase.of(context).unusedCount, - fontSize: 17.5, - ), - Texts( - model.insuranceApproval[index].unUsedCount.toString(), - fontSize: 17.5, - fontWeight: FontWeight.w600, - ), - ], - ), - Divider( - color: Colors.black, - height: 25.0, - thickness: 1.0, - ), + Divider( + color: Colors.black, + height: 25.0, + thickness: 1.0, + ), + Row( + children: [ + Texts( + TranslationBase.of(context).procedureStatus, + fontSize: 17.5, + ), + SizedBox( + width: 12, + ), + Texts( + model.insuranceApproval[index].approvalStatusDescption, + fontWeight: FontWeight.w600, + fontSize: 17.5, + ), + ], + ), + Divider( + color: Colors.black, + height: 25.0, + thickness: 1.0, + ), + Row( + children: [ + Texts( + TranslationBase.of(context).unusedCount, + fontSize: 17.5, + ), + Texts( + model.insuranceApproval[index].unUsedCount.toString(), + fontSize: 17.5, + fontWeight: FontWeight.w600, + ), + ], + ), + Divider( + color: Colors.black, + height: 25.0, + thickness: 1.0, + ), // Text( // 'Company Name: ' + // model.insuranceApproval[index] @@ -224,190 +182,131 @@ class _InsuranceApprovalState extends State { // fontSize: 17.5, // fontWeight: FontWeight.w600), // ), - Texts( - TranslationBase.of(context).companyName, - fontWeight: FontWeight.w600, - fontSize: 17.5, - ), - - Divider( - color: Colors.black, - height: 25.0, - thickness: 1.0, - ), - Row( - children: [ - Texts( - TranslationBase.of(context).receiptOn , - fontSize: 17.5, - fontWeight: FontWeight.w600, - - ), - Texts( - convertDateFormat(model.insuranceApproval[index].rceiptOn), - fontSize: 17.5, - fontWeight: FontWeight.w600, + Texts( + TranslationBase.of(context).companyName, + fontWeight: FontWeight.w600, + fontSize: 17.5, + ), - ), - ], + Divider( + color: Colors.black, + height: 25.0, + thickness: 1.0, + ), + Row( + children: [ + Texts( + TranslationBase.of(context).receiptOn, + fontSize: 17.5, + fontWeight: FontWeight.w600, + ), + Texts( + convertDateFormat(model.insuranceApproval[index].receiptOn), + fontSize: 17.5, + fontWeight: FontWeight.w600, + ), + ], + ), + Divider( + color: Colors.black, + height: 25.0, + thickness: 1.0, + ), + Row( + children: [ + Texts( + TranslationBase.of(context).expiryDate, + fontSize: 17.5, + fontWeight: FontWeight.w600, + ), + Texts( + convertDateFormat(model.insuranceApproval[index].expiryDate), + fontSize: 17.5, + fontWeight: FontWeight.w600, + ), + ], + ), + Divider( + color: Colors.black, + height: 55.0, + thickness: 1.2, + ), + IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: Column( + children: [ + Text(TranslationBase.of(context).procedureName), + Padding( + padding: EdgeInsets.only(top: SizeConfig.heightMultiplier * 3.0), + child: Text( + model.insuranceApproval[index].apporvalDetails?.procedureName ?? '', + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15.5), + ), + ), + ], + ), ), - Divider( + VerticalDivider( + width: 10.0, + thickness: 1.2, color: Colors.black, - height: 25.0, - thickness: 1.0, ), - Row( - children: [ - Texts( - TranslationBase.of(context).expiryDate, - fontSize: 17.5, - fontWeight: FontWeight.w600, - - ), - Texts( - convertDateFormat(model.insuranceApproval[index].expiryDate), - fontSize: 17.5, - fontWeight: FontWeight.w600, - - ), - ], + Expanded( + flex: 1, + child: Column( + children: [ + Text(TranslationBase.of(context).procedureStatus), + Padding( + padding: EdgeInsets.only(top: SizeConfig.heightMultiplier * 3.0), + child: Text( + model.insuranceApproval[index].apporvalDetails?.status ?? '', + style: TextStyle(fontSize: 17.5, fontWeight: FontWeight.w600), + ), + ), + ], + ), ), - Divider( - color: Colors.black, - height: 55.0, + VerticalDivider( + width: 2.3, thickness: 1.2, + color: Colors.black, ), - IntrinsicHeight( - child: Row( - crossAxisAlignment: - CrossAxisAlignment.center, + Expanded( + flex: 1, + child: Column( children: [ - Expanded( - flex: 1, - child: Column( - children: [ - Text(TranslationBase.of( - context) - .procedureName), - Padding( - padding: EdgeInsets.only( - top: SizeConfig - .heightMultiplier * - 3.0), - child: Text( - model - .insuranceApproval[ - index] - .approvalDetails == - null - ? '' - : model - .insuranceApproval[ - index] - .approvalDetails - .procedureName, - style: TextStyle( - fontWeight: - FontWeight.w600, - fontSize: 15.5), - ), - ), - ], - ), - ), - VerticalDivider( - width: 10.0, - thickness: 1.2, - color: Colors.black, - ), - Expanded( - flex: 1, - child: Column( - children: [ - Text(TranslationBase.of( - context) - .procedureStatus), - Padding( - padding: EdgeInsets.only( - top: SizeConfig - .heightMultiplier * - 3.0), - child: Text( - model - .insuranceApproval[ - index] - .approvalDetails == - null - ? '' - : model - .insuranceApproval[ - index] - .approvalDetails - .status, - style: TextStyle( - fontSize: 17.5, - fontWeight: - FontWeight - .w600), - ), - ), - ], - ), - ), - VerticalDivider( - width: 2.3, - thickness: 1.2, - color: Colors.black, - ), - Expanded( - flex: 1, - child: Column( - children: [ - Text(TranslationBase.of( - context) - .usageStatus), - Padding( - padding: EdgeInsets.only( - top: SizeConfig - .heightMultiplier * - 3.0), - child: Text( - model - .insuranceApproval[ - index] - .approvalDetails == - null - ? '' - : model - .insuranceApproval[ - index] - .approvalDetails - .isInvoicedDesc, - style: TextStyle( - fontWeight: - FontWeight.w600, - fontSize: 17.5), - ), - ), - ], + Text(TranslationBase.of(context).usageStatus), + Padding( + padding: EdgeInsets.only(top: SizeConfig.heightMultiplier * 3.0), + child: Text( + model.insuranceApproval[index].apporvalDetails?.isInvoicedDesc ?? '', + style: TextStyle(fontWeight: FontWeight.w600, fontSize: 17.5), ), ), ], ), ), - Divider( - color: Colors.black, - height: 25.0, - thickness: 1.0, - ), ], ), ), + Divider( + color: Colors.black, + height: 25.0, + thickness: 1.0, + ), ], ), - ], - ), - )), + ), + ], + ), + ], + ), + ); + }), ], ), ), @@ -416,6 +315,22 @@ class _InsuranceApprovalState extends State { ); } + Widget sideBadge(String title, int color) { + return Container( + decoration: BoxDecoration( + color: Color(color), + borderRadius: BorderRadius.circular(16.0), + ), + width: 115.0, + padding: EdgeInsets.only(top: 1, bottom: 1), + alignment: Alignment.center, + child: Texts( + title, + color: Colors.white, + ), + ); + } + convertDateFormat(String Date) { const start = "/Date("; const end = "+0300)"; @@ -423,13 +338,8 @@ class _InsuranceApprovalState extends State { final startIndex = Date.indexOf(start); final endIndex = Date.indexOf(end, startIndex + start.length); - var date = new DateTime.fromMillisecondsSinceEpoch( - int.parse(Date.substring(startIndex + start.length, endIndex))); - String newDate = date.year.toString() + - "-" + - date.month.toString().padLeft(2, '0') + - "-" + - date.day.toString().padLeft(2, '0'); + var date = new DateTime.fromMillisecondsSinceEpoch(int.parse(Date.substring(startIndex + start.length, endIndex))); + String newDate = date.year.toString() + "-" + date.month.toString().padLeft(2, '0') + "-" + date.day.toString().padLeft(2, '0'); return newDate.toString(); } diff --git a/lib/pages/insurance/insurance_card_screen.dart b/lib/pages/insurance/insurance_card_screen.dart index da66c572..cf58e815 100644 --- a/lib/pages/insurance/insurance_card_screen.dart +++ b/lib/pages/insurance/insurance_card_screen.dart @@ -6,7 +6,7 @@ import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_details.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; -import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -33,26 +33,41 @@ class _InsuranceCardState extends State { @override Widget build(BuildContext context) { imagesInfo.add(ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/en/0.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/ar/0.png')); + imageEn: 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/en/0.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/imges-info/insurance-card/ar/0.png')); return BaseView( onModelReady: (model) => model.getInsurance(), - builder: (BuildContext context, InsuranceViewModel model, Widget child) => - AppScaffold( + builder: (BuildContext context, InsuranceViewModel model, Widget child) => AppScaffold( isShowAppBar: true, baseViewModel: model, + showHomeAppBarIcon: false, appBarTitle: TranslationBase.of(context).insuranceCards, description: TranslationBase.of(context).infoInsuranceCards, infoList: TranslationBase.of(context).infoInsuranceCardsPoints, imagesInfo: imagesInfo, + appBarIcons: [ + IconButton( + padding: EdgeInsets.zero, + icon: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + margin: EdgeInsets.only(right: 8), + padding: EdgeInsets.only(right: 4, left: 4), + child: Image.asset( + 'assets/images/medical/insurance_update_icon_.png', + height: SizeConfig.heightMultiplier * 5, + width: SizeConfig.heightMultiplier * 5, + ), + ), + onPressed: () { + Navigator.push(context, FadePage(page: InsuranceUpdate())); + }, + ), + ], body: Container( - margin: EdgeInsets.only( - left: SizeConfig.screenWidth * 0.004, - right: SizeConfig.screenWidth * 0.004, - top: SizeConfig.screenWidth * 0.04), + margin: EdgeInsets.only(left: SizeConfig.screenWidth * 0.004, right: SizeConfig.screenWidth * 0.004, top: SizeConfig.screenWidth * 0.04), child: ListView.builder( itemCount: model.insurance == null ? 0 : model.insurance.length, itemBuilder: (BuildContext context, int index) { @@ -82,23 +97,16 @@ class _InsuranceCardState extends State { Container( padding: EdgeInsets.all(14), width: double.infinity, - decoration: BoxDecoration( - shape: BoxShape.rectangle, - border: Border.all( - color: Colors.grey, width: 0.2), - borderRadius: - BorderRadius.all(Radius.circular(2)), - boxShadow: [ - BoxShadow( - color: Colors.white70, - ), - ]), + decoration: BoxDecoration(shape: BoxShape.rectangle, border: Border.all(color: Colors.grey, width: 0.2), borderRadius: BorderRadius.all(Radius.circular(2)), boxShadow: [ + BoxShadow( + color: Colors.white70, + ), + ]), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Texts( - TranslationBase.of(context).companyName + - model.insurance[index].companyName, + TranslationBase.of(context).companyName + model.insurance[index].companyName, fontSize: 20.0, fontWeight: FontWeight.w700, ), @@ -108,93 +116,46 @@ class _InsuranceCardState extends State { thickness: 0.5, ), Column( - crossAxisAlignment: - CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Texts( - TranslationBase.of(context) - .category, - fontSize: 18.5), - Texts( - model.insurance[index] - .subCategoryDesc, - fontSize: 18.5) - ], + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Texts(TranslationBase.of(context).category, fontSize: 18.5), Texts(model.insurance[index].subCategoryDesc, fontSize: 18.5)], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Texts( - TranslationBase.of(context) - .expirationDate, - fontSize: 18.5), + Texts(TranslationBase.of(context).expirationDate, fontSize: 18.5), Texts( convertDateFormat( - model.insurance[index] - .cardValidTo, + model.insurance[index].cardValidTo, ), fontSize: 18.5), ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Texts( - TranslationBase.of(context) - .status + - ": ", - fontSize: 18.5), - model.insurance[index].isActive == - true - ? Texts( - TranslationBase.of(context) - .activeInsurence, - color: Colors.green, - fontWeight: FontWeight.w900, - fontSize: 17.9) - : Texts( - TranslationBase.of(context) - .notActive, - color: Colors.red, - fontWeight: FontWeight.w900, - fontSize: 17.9) + Texts(TranslationBase.of(context).status + ": ", fontSize: 18.5), + model.insurance[index].isActive == true + ? Texts(TranslationBase.of(context).activeInsurence, color: Colors.green, fontWeight: FontWeight.w900, fontSize: 17.9) + : Texts(TranslationBase.of(context).notActive, color: Colors.red, fontWeight: FontWeight.w900, fontSize: 17.9) ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Texts( - TranslationBase.of(context) - .patientCard, - fontSize: 18.5), - Texts( - model.insurance[index] - .patientCardID, - fontSize: 18.5) - ], + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Texts(TranslationBase.of(context).patientCard, fontSize: 18.5), Texts(model.insurance[index].patientCardID, fontSize: 18.5)], ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Texts( - TranslationBase.of(context) - .policyNumber, - fontSize: 18.5, - ), - Texts( - model.insurance[index] - .insurancePolicyNumber, - fontSize: 18.5, - ) - ]), + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Texts( + TranslationBase.of(context).policyNumber, + fontSize: 18.5, + ), + Texts( + model.insurance[index].insurancePolicyNumber, + fontSize: 18.5, + ) + ]), ], ), SizedBox( @@ -204,11 +165,8 @@ class _InsuranceCardState extends State { Container( color: Colors.transparent, child: SecondaryButton( - onTap: () => { - getDetails(model.insurance[index]) - }, - label: TranslationBase.of(context) - .seeDetails, + onTap: () => {getDetails(model.insurance[index])}, + label: TranslationBase.of(context).seeDetails, textColor: Colors.white, ), width: double.infinity, @@ -235,23 +193,16 @@ class _InsuranceCardState extends State { final startIndex = exDate.indexOf(start); final endIndex = exDate.indexOf(end, startIndex + start.length); - var date = new DateTime.fromMillisecondsSinceEpoch( - int.parse(exDate.substring(startIndex + start.length, endIndex))); - String newDate = date.year.toString() + - "-" + - date.month.toString().padLeft(2, '0') + - "-" + - date.day.toString().padLeft(2, '0'); + var date = new DateTime.fromMillisecondsSinceEpoch(int.parse(exDate.substring(startIndex + start.length, endIndex))); + String newDate = date.year.toString() + "-" + date.month.toString().padLeft(2, '0') + "-" + date.day.toString().padLeft(2, '0'); return newDate.toString(); } getDetails(data) { GifLoaderDialogUtils.showMyDialog(context); - _insuranceCardService.getInsuranceDetails(data).then((value) => { - GifLoaderDialogUtils.hideDialog(context), - Navigator.push(context, - FadePage(page: InsuranceCardDetails(data: value[0]['CheckList']))) - }); + _insuranceCardService + .getInsuranceDetails(data) + .then((value) => {GifLoaderDialogUtils.hideDialog(context), Navigator.push(context, FadePage(page: InsuranceCardDetails(data: value[0]['CheckList'])))}); } } diff --git a/lib/pages/landing/home_page.dart b/lib/pages/landing/home_page.dart index d5229161..3f25217c 100644 --- a/lib/pages/landing/home_page.dart +++ b/lib/pages/landing/home_page.dart @@ -1,3 +1,5 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/dashboard_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; @@ -19,6 +21,7 @@ import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:feather_icons_flutter/feather_icons_flutter.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -43,7 +46,10 @@ class _HomePageState extends State { Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return BaseView( - onModelReady: (model) => model.getPatientRadOrders(), + onModelReady: (model) => () async { + model.getPatientRadOrders(); + var user = await sharedPref.getObject(USER_PROFILE); + }, builder: (_, model, wi) => AppScaffold( isShowDecPage: false, isHelp: true, @@ -61,7 +67,8 @@ class _HomePageState extends State { width: double.infinity, height: 210, decoration: BoxDecoration( - image: DecorationImage(image: ExactAssetImage('assets/images/dashboard_top_bg.png'), fit: BoxFit.cover), + image: DecorationImage( + image: ExactAssetImage('assets/images/dashboard_top_bg.png'), fit: BoxFit.cover), ), child: Stack( children: [ @@ -100,7 +107,10 @@ class _HomePageState extends State { margin: EdgeInsets.only( top: 15.0, ), - child: SvgPicture.asset('assets/images/new-design/covid-19-car.svg', width: 45.0, height: 45.0), + child: SvgPicture.asset( + 'assets/images/new-design/covid-19-car.svg', + width: 45.0, + height: 45.0), ), Container( margin: EdgeInsets.only(top: 5.0), @@ -157,9 +167,13 @@ class _HomePageState extends State { height: 125, padding: EdgeInsets.all(15), margin: EdgeInsets.all(5), - decoration: BoxDecoration(color: Colors.white.withOpacity(0.3), borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.3), + borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( - projectViewModel.isArabic ? 'assets/images/new-design/livecare_arabic_logo.svg' : 'assets/images/new-design/liveCare_white_logo.svg', + projectViewModel.isArabic + ? 'assets/images/new-design/livecare_arabic_logo.svg' + : 'assets/images/new-design/liveCare_white_logo.svg', ), ), ), @@ -176,8 +190,10 @@ class _HomePageState extends State { ), Positioned( top: 155, - left: MediaQuery.of(context).size.width * (MediaQuery.of(context).orientation == Orientation.landscape ? 0.02 : 0.03), - right: MediaQuery.of(context).size.width * (MediaQuery.of(context).orientation == Orientation.landscape ? 0.02 : 0.03), + left: MediaQuery.of(context).size.width * + (MediaQuery.of(context).orientation == Orientation.landscape ? 0.02 : 0.03), + right: MediaQuery.of(context).size.width * + (MediaQuery.of(context).orientation == Orientation.landscape ? 0.02 : 0.03), child: (!model.isLogin) ? Container( width: double.infinity, @@ -187,7 +203,8 @@ class _HomePageState extends State { shape: BoxShape.rectangle, border: Border.all(color: Colors.transparent, width: 0.5), borderRadius: BorderRadius.all(Radius.circular(9)), - image: DecorationImage(image: ExactAssetImage('assets/images/bg_graphic.png'), fit: BoxFit.cover)), + image: DecorationImage( + image: ExactAssetImage('assets/images/bg_graphic.png'), fit: BoxFit.cover)), child: Container( margin: EdgeInsets.all(5), child: Column( @@ -208,7 +225,8 @@ class _HomePageState extends State { fontSize: 16, ), Align( - alignment: projectViewModel.isArabic ? Alignment.bottomLeft : Alignment.bottomRight, + alignment: + projectViewModel.isArabic ? Alignment.bottomLeft : Alignment.bottomRight, child: InkWell( onTap: () { widget.goToMyProfile(); @@ -246,7 +264,8 @@ class _HomePageState extends State { shape: BoxShape.rectangle, border: Border.all(color: Colors.transparent, width: 0.5), borderRadius: BorderRadius.all(Radius.circular(9)), - image: DecorationImage(image: ExactAssetImage('assets/images/bg_graphic.png'), fit: BoxFit.cover), + image: DecorationImage( + image: ExactAssetImage('assets/images/bg_graphic.png'), fit: BoxFit.cover), ), child: Container( margin: EdgeInsets.all(5), @@ -262,20 +281,48 @@ class _HomePageState extends State { SizedBox( height: 8, ), - Row( - children: [ - Texts( - model.user.firstName + " " + model.user.lastName, - color: Colors.grey[100], - bold: true, - fontSize: 15, - ), - Container( - margin: EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0), - child: SvgPicture.asset("assets/images/new-design/verification_check.svg"), - ), - ], - ), + model.user.cRSVerificationStatus == 2 + ? Row( + children: [ + Texts( + model.user.firstName + " " + model.user.lastName, + color: Colors.grey[100], + bold: true, + fontSize: 15, + ), + Container( + margin: EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0), + child: SvgPicture.asset( + "assets/images/new-design/verification_check.svg"), + ), + ], + ) + : model.user.cRSVerificationStatus == 3 + ? Row( + children: [ + Texts( + model.user.firstName + " " + model.user.lastName, + color: Colors.grey[100], + bold: true, + fontSize: 15, + ), + Container( + margin: EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0), + child: SvgPicture.asset( + "assets/images/new-design/pending.svg"), + ), + ], + ) + : Row( + children: [ + Texts( + model.user.firstName + " " + model.user.lastName, + color: Colors.grey[100], + bold: true, + fontSize: 15, + ), + ], + ), Texts( '${model.user.patientID}', color: Colors.white, @@ -332,7 +379,7 @@ class _HomePageState extends State { height: 40, ), Texts( - "${model.heightCm}", + "${model.heightCm} ${TranslationBase.of(context).cm}", color: Colors.white, fontSize: 17, ) @@ -350,7 +397,8 @@ class _HomePageState extends State { width: 25, height: 40, ), - Texts('${model.weightKg}', color: Colors.white, fontSize: 17) + Texts('${model.weightKg} ${TranslationBase.of(context).kg}', + color: Colors.white, fontSize: 17) ], ), ), @@ -359,17 +407,13 @@ class _HomePageState extends State { ), Expanded( child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Image.asset( 'assets/images/blood_icon.png', width: 35, height: 40, ), - Texts( - '${model.booldType}', - color: Colors.white, - ) + Texts('${model.booldType}', color: Colors.white, fontSize: 17) ], ), ), @@ -411,7 +455,9 @@ class _HomePageState extends State { ), ), ), - if (projectViewModel.havePrivilege(64) || projectViewModel.havePrivilege(65) || projectViewModel.havePrivilege(67)) + if (projectViewModel.havePrivilege(64) || + projectViewModel.havePrivilege(65) || + projectViewModel.havePrivilege(67)) Container( margin: EdgeInsets.only(left: 15, right: 15), child: Row( @@ -419,37 +465,48 @@ class _HomePageState extends State { children: [ if (projectViewModel.havePrivilege(64)) DashboardItem( - onTap: () { - Navigator.push( - context, - FadePage( - page: HomeHealthCarePage(), - ), - ); - }, + onTap: (model.user != null && model.user.outSA == 1) + ? () {} + : () { + Navigator.push( + context, + FadePage( + page: HomeHealthCarePage(), + ), + ); + }, child: Center( child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/home_health_care_icon.png', - width: 50, - height: 50, - ), - SizedBox( - height: 10, - ), - Texts( - TranslationBase.of(context).homeHealthCare, - textAlign: TextAlign.center, - color: Colors.white, - fontWeight: FontWeight.w700, - fontSize: SizeConfig.textMultiplier * 1.55, - ) - ], - ), - ), + padding: const EdgeInsets.all(15.0), + child: (model.user != null && model.user.outSA == 1) + ? Container( + width: double.infinity, + height: double.infinity, + color: Colors.grey.withOpacity(0.7), + child: Icon( + Icons.lock_outline, + size: 40, + ), + ) + : Column( + children: [ + Image.asset( + 'assets/images/home_health_care_icon.png', + width: 50, + height: 50, + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context).homeHealthCare, + textAlign: TextAlign.center, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.textMultiplier * 1.55, + ) + ], + )), ), height: MediaQuery.of(context).size.width * 0.4, imageName: 'home_healthcare_service_bg.png', @@ -457,29 +514,46 @@ class _HomePageState extends State { ), if (projectViewModel.havePrivilege(65)) DashboardItem( - onTap: () => getPharmacyToken(model), + onTap: () => + (model.user != null && model.user.outSA == 1) ? () {} : getPharmacyToken(model), child: Center( child: Padding( padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/pharmacy_logo.png', - width: 40, - height: 40, - ), - SizedBox( - height: 20, - ), - Texts( - TranslationBase.of(context).onlinePharmacy, - textAlign: TextAlign.center, - color: Colors.white, - fontWeight: FontWeight.w700, - fontSize: SizeConfig.textMultiplier * 1.55, - ) - ], - ), + child: (model.user != null && model.user.outSA == 1) + ? Container( + width: double.infinity, + height: double.infinity, + color: Colors.grey.withOpacity(0.7), + child: Icon( + Icons.lock_outline, + size: 40, + ), + ) + : Column( + children: [ + // if (projectViewModel.user != null && model.isLogin && model.user.outSA == 1) + // Image.asset( + // 'assets/images/lock_icon.png', + // width: 50, + // height: 50, + // ), + Image.asset( + 'assets/images/pharmacy_logo.png', + width: 40, + height: 40, + ), + SizedBox( + height: 20, + ), + Texts( + TranslationBase.of(context).onlinePharmacy, + textAlign: TextAlign.center, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.textMultiplier * 1.55, + ) + ], + ), ), ), height: MediaQuery.of(context).size.width * 0.4, @@ -487,37 +561,48 @@ class _HomePageState extends State { ), if (projectViewModel.havePrivilege(67)) DashboardItem( - onTap: () { - Navigator.push( - context, - FadePage( - page: CMCPage(), - ), - ); - }, + onTap: (model.user != null && model.user.outSA == 1) + ? () {} + : () { + Navigator.push( + context, + FadePage( + page: CMCPage(), + ), + ); + }, child: Center( child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - children: [ - Image.asset( - 'assets/images/comprehensive_medical_checkup_logo.png', - width: 50, - height: 50, - ), - SizedBox( - height: 10, - ), - Texts( - TranslationBase.of(context).cmcHeading, - textAlign: TextAlign.center, - color: Colors.white, - fontWeight: FontWeight.w700, - fontSize: SizeConfig.textMultiplier * 1.55, - ) - ], - ), - ), + padding: const EdgeInsets.all(15.0), + child: (model.user != null && model.user.outSA == 1) + ? Container( + width: double.infinity, + height: double.infinity, + color: Colors.grey.withOpacity(0.7), + child: Icon( + Icons.lock_outline, + size: 40, + ), + ) + : Column( + children: [ + Image.asset( + 'assets/images/comprehensive_medical_checkup_logo.png', + width: 50, + height: 50, + ), + SizedBox( + height: 10, + ), + Texts( + TranslationBase.of(context).cmcHeading, + textAlign: TextAlign.center, + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.textMultiplier * 1.55, + ) + ], + )), ), height: MediaQuery.of(context).size.width * 0.4, color: HexColor("#747C80"), @@ -766,7 +851,17 @@ class _HomePageState extends State { } class DashboardItem extends StatelessWidget { - const DashboardItem({this.hasBorder = false, this.imageName, @required this.child, this.onTap, Key key, this.width, this.height, this.color, this.opacity = 0.4, this.hasColorFilter = true}) + const DashboardItem( + {this.hasBorder = false, + this.imageName, + @required this.child, + this.onTap, + Key key, + this.width, + this.height, + this.color, + this.opacity = 0.4, + this.hasColorFilter = true}) : super(key: key); final bool hasBorder; final String imageName; @@ -796,12 +891,15 @@ class DashboardItem extends StatelessWidget { : HexColor('#050705').withOpacity(opacity) : Colors.white, borderRadius: BorderRadius.circular(6.0), - border: hasBorder ? Border.all(width: 1.0, color: const Color(0xffcccccc)) : Border.all(width: 0.0, color: Colors.transparent), + border: hasBorder + ? Border.all(width: 1.0, color: const Color(0xffcccccc)) + : Border.all(width: 0.0, color: Colors.transparent), image: imageName != null ? DecorationImage( image: ExactAssetImage('assets/images/$imageName'), fit: BoxFit.cover, - colorFilter: hasColorFilter ? new ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstIn) : null, + colorFilter: + hasColorFilter ? new ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstIn) : null, ) : null, ), diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index ba5c9e1d..0d307779 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/core/model/geofencing/requests/GeoZonesRequestModel.dart'; @@ -18,7 +19,6 @@ import 'package:diplomaticquarterapp/pages/medical/medical_profile_page.dart'; import 'package:diplomaticquarterapp/pages/medical/medical_profile_page_new.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart' as family; - import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/uitl/CalendarUtils.dart'; import 'package:diplomaticquarterapp/uitl/HMGNetworkConnectivity.dart'; @@ -33,10 +33,12 @@ import 'package:diplomaticquarterapp/widgets/buttons/floatingActionButton.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/drawer/app_drawer_widget.dart'; +import 'package:firebase_analytics/observer.dart'; import 'package:diplomaticquarterapp/widgets/others/not_auh_page.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; @@ -46,12 +48,22 @@ import '../../routes.dart'; import 'home_page.dart'; class LandingPage extends StatefulWidget { + static LandingPage shared; + _LandingPageState state; + LandingPage() { + LandingPage.shared = this; + } + static bool isOpenCallPage = false; static IncomingCallData incomingCallData = new IncomingCallData(); @override - _LandingPageState createState() => _LandingPageState(); + _LandingPageState createState() => state = _LandingPageState(); + + switchToDoFromHMGServices() { + state.changeCurrentTab(4); + } } class _LandingPageState extends State with WidgetsBindingObserver { @@ -63,11 +75,14 @@ class _LandingPageState extends State with WidgetsBindingObserver { var notificationCount = ''; var themeNotifier; + bool _showBottomNavigationBar = true; + ///inject the user data AuthenticatedUserObject authenticatedUserObject = locator(); final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); final authService = new AuthProvider(); + var event = RobotProvider(); var familyFileProvider = family.FamilyFilesProvider(); @@ -82,33 +97,66 @@ class _LandingPageState extends State with WidgetsBindingObserver { bool isPageNavigated = false; LocationUtils locationUtils; - _changeCurrentTab(int tab) { - if (tab == 3) { - // if (!projectViewModel.isLogin) { - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (cxt) => NotAutPage( - // title: TranslationBase.of(context).myFamilyFiles, - // description: TranslationBase.of(context).familyInfo, - // infoList: [], - // imagesInfo: [], - // icon: "assets/images/new/bottom_nav/family_files.svg", - // ), - // ), - // ); - // return Container(); - // } - // return; + changeCurrentTab(int tab) { + print(tab); + if (!projectViewModel.isLogin) { + if (tab == 3) { + List imagesInfo = []; + imagesInfo.add( + ImagesInfo( + imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/0.png', + imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/0.png'), + ); + + imagesInfo.add( + ImagesInfo( + imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/1.png', + imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/1.png'), + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (cxt) => NotAutPage( + title: TranslationBase.of(context).myFamilyFiles, + description: TranslationBase.of(context).familyInfo, + infoList: [], + imagesInfo: imagesInfo, + icon: "assets/images/new/bottom_nav/family_files.svg", + ), + ), + ); + return; + } + if (tab == 4) { + List imagesInfo = []; + imagesInfo.add( + ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/en/0.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/ar/0.png')); + + Navigator.push( + context, + MaterialPageRoute( + builder: (cxt) => NotAutPage( + title: TranslationBase.of(context).todoList, + description: TranslationBase.of(context).infoTodo, + infoList: [], + imagesInfo: imagesInfo, + icon: "assets/images/new/bottom_nav/todo.svg", + ), + ), + ); + return; + } } setState(() { - currentTab = tab; - if (tab != 0) + if (currentTab > 0 && tab == 2) + pageController.jumpToPage(0); + else if (tab != 0) pageController.jumpToPage(tab); else { IS_VOICE_COMMAND_CLOSED = false; pageController.jumpToPage(tab); } + currentTab = tab; }); } @@ -197,6 +245,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { }); requestPermissions(); + // }); // // //_firebase Background message handler @@ -369,7 +418,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { checkValue(projectProvider) { if (projectProvider.searchValue != null) { - _changeCurrentTab(2); + changeCurrentTab(2); } } @@ -401,6 +450,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { } else { GifLoaderDialogUtils.showMyDialog(context); authService.selectDeviceImei(DEVICE_TOKEN).then((SelectDeviceIMEIRES value) { + this.getNotificationCount(DEVICE_TOKEN); GifLoaderDialogUtils.hideDialog(context); if (value != null) { setUserValues(value); @@ -529,7 +579,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { children: [ HomePage2( goToMyProfile: () { - _changeCurrentTab(1); + changeCurrentTab(1); }, onLoginClick: () { login(); @@ -542,7 +592,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { ], // Please do not remove the BookingOptions from this array ), bottomNavigationBar: BottomNavBar( - changeIndex: _changeCurrentTab, + changeIndex: changeCurrentTab, index: currentTab, ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, @@ -550,7 +600,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { ? FloatingButton( elevation: true, onTap: () { - _changeCurrentTab(2); + changeCurrentTab(2); }) : null); } diff --git a/lib/pages/livecare/widgets/LiveCarePaymentDialog.dart b/lib/pages/livecare/widgets/LiveCarePaymentDialog.dart index e2dab5b0..c06c9464 100644 --- a/lib/pages/livecare/widgets/LiveCarePaymentDialog.dart +++ b/lib/pages/livecare/widgets/LiveCarePaymentDialog.dart @@ -9,7 +9,9 @@ class LiveCarePaymentDialog extends StatefulWidget { String clinicName; LiveCarePaymentDialog( - {@required this.getERAppointmentFeesList, @required this.waitingTime, @required this.clinicName}); + {@required this.getERAppointmentFeesList, + @required this.waitingTime, + @required this.clinicName}); @override _LiveCarePaymentDialogState createState() => _LiveCarePaymentDialogState(); @@ -32,14 +34,15 @@ class _LiveCarePaymentDialogState extends State { height: MediaQuery.of(context).size.height * 0.691, margin: EdgeInsets.all(20.0), width: 450.0, - child: Column( + child: SingleChildScrollView( + child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ Container( alignment: Alignment.center, margin: EdgeInsets.only(bottom: 10.0), - child: Text("Online Consultation", + child: Text(TranslationBase.of(context).onlineConsultation, textAlign: TextAlign.center, style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold)), @@ -52,7 +55,7 @@ class _LiveCarePaymentDialogState extends State { direction: Axis.horizontal, children: [ Expanded( - child: Text("Waiting time to start LiveCare consultation", + child: Text(TranslationBase.of(context).expectedWaiting, textAlign: TextAlign.end, style: TextStyle(fontSize: 13.0)), ), @@ -92,7 +95,7 @@ class _LiveCarePaymentDialogState extends State { alignment: Alignment.center, margin: EdgeInsets.only(top: 5.0), padding: EdgeInsets.all(5.0), - child: Text("Consultation fee", + child: Text(TranslationBase.of(context).erConsultFee, textAlign: TextAlign.center, style: TextStyle( fontSize: 14.0, @@ -155,8 +158,7 @@ class _LiveCarePaymentDialogState extends State { Container( margin: EdgeInsets.only(left: 10.0), width: MediaQuery.of(context).size.width * 0.55, - child: Text( - "If you're Insurance patient, you have only have to pay the co-payment", + child: Text(TranslationBase.of(context).insuredPatient, style: TextStyle(fontSize: 13.0)), ), ], @@ -175,7 +177,7 @@ class _LiveCarePaymentDialogState extends State { ), Container( child: new Text( - 'I Accept the Terms And Conditions', + TranslationBase.of(context).iAcceptTerms, style: new TextStyle(fontSize: 14.0), ), ), @@ -198,7 +200,7 @@ class _LiveCarePaymentDialogState extends State { alignment: Alignment.center, margin: EdgeInsets.only(top: 10.0), child: new Text( - 'You can pay by the following Options:', + TranslationBase.of(context).upComingPayOption, textAlign: TextAlign.center, style: new TextStyle(fontSize: 14.0), ), @@ -236,8 +238,10 @@ class _LiveCarePaymentDialogState extends State { Expanded( child: InkWell( onTap: () { - if(_selected == 0) { - AppToast.showErrorToast(message: "Please accept terms & conditions to continue"); + if (_selected == 0) { + AppToast.showErrorToast( + message: TranslationBase.of(context) + .pleaseAcceptTerms); } else { Navigator.pop(context, true); } @@ -255,7 +259,7 @@ class _LiveCarePaymentDialogState extends State { ), ), ], - ), + )), ), ), ); diff --git a/lib/pages/livecare/widgets/clinic_list.dart b/lib/pages/livecare/widgets/clinic_list.dart index 103066d5..ae7f1dca 100644 --- a/lib/pages/livecare/widgets/clinic_list.dart +++ b/lib/pages/livecare/widgets/clinic_list.dart @@ -535,7 +535,8 @@ class _clinic_listState extends State { isDataLoaded ? Container( height: MediaQuery.of(context).size.height * 0.7, - child: Column( + child: SingleChildScrollView( + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( @@ -575,7 +576,7 @@ class _clinic_listState extends State { height: 10.0, ), ], - ), + )), ) : Container(), isDataLoaded @@ -584,7 +585,7 @@ class _clinic_listState extends State { child: Container( width: MediaQuery.of(context).size.width, height: 50.0, - margin: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), + margin: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 20.0), child: ButtonTheme( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart index 677f08a5..540c9a43 100644 --- a/lib/pages/login/confirm-login.dart +++ b/lib/pages/login/confirm-login.dart @@ -629,6 +629,7 @@ class _ConfirmLogin extends State { // sharedPref.setString( // BLOOD_TYPE, result['PatientBloodType']), authenticatedUserObject.user = result.list, + sharedPref.setObject(MAIN_USER, result.list), sharedPref.setObject(USER_PROFILE, result.list), loginTokenID = result.logInTokenID, diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart index 117a3d1f..4025fe21 100644 --- a/lib/pages/login/login.dart +++ b/lib/pages/login/login.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; @@ -42,6 +43,7 @@ class Login extends StatefulWidget { class _Login extends State { final util = Utils(); final nationalIDorFile = TextEditingController(); + final mobileNumberController = TextEditingController(); final int loginType = LoginType.loginType; String mobileNo; String countryCode = '966'; @@ -63,6 +65,11 @@ class _Login extends State { void initState() { // getDeviceToken(); super.initState(); + + if (BASE_URL.contains("uat.")) { + nationalIDorFile.text = "1231755"; + mobileNumberController.text = mobileNo = "537503378"; + } } getDeviceToken() async { @@ -115,15 +122,17 @@ class _Login extends State { height: 43, width: double.infinity, child: FlatButton( - onPressed: () { - this.startLogin(); - }, + onPressed: isButtonDisabled + ? null + : () { + this.startLogin(); + }, child: Text( TranslationBase.of(context).login, style: TextStyle(fontSize: 16, fontFamily: "Poppins", fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.48), ), - // color: Color(0xffD02127), - color: isButtonDisabled == true ? Color(0xff575757) : Color(0xffD02127), + disabledColor: Color(0xff575757), + color: Color(0xffD02127), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), ), @@ -156,7 +165,9 @@ class _Login extends State { child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Directionality(textDirection: TextDirection.ltr, child: MobileNo(onNumberChange: (value) => {mobileNo = value, validateForm()}, onCountryChange: (value) => countryCode = value)), + Directionality( + textDirection: TextDirection.ltr, + child: MobileNo(controller: mobileNumberController, onNumberChange: (value) => {mobileNo = value, validateForm()}, onCountryChange: (value) => countryCode = value)), Directionality( textDirection: TextDirection.ltr, child: Container( @@ -396,6 +407,8 @@ class _Login extends State { appointmentRateViewModel.isLogin = true; projectViewModel.isLogin = true; authenticatedUserObject.user = result.list; + // authenticatedUserObject.user.cRSVerificationStatus = + // result['CRSVerificationStatus']; projectViewModel.user = authenticatedUserObject.user; await familyFileProvider.getSharedRecordByStatus(); diff --git a/lib/pages/login/register-info.dart b/lib/pages/login/register-info.dart index 467068cc..d28fea86 100644 --- a/lib/pages/login/register-info.dart +++ b/lib/pages/login/register-info.dart @@ -278,44 +278,46 @@ class _RegisterInfo extends State { registerNow() { dynamic request = getTempUserRequest(); GifLoaderDialogUtils.showMyDialog(context); - this.authService.registerUser(request).then((result) => { - GifLoaderDialogUtils.hideDialog(context), - // userData = result.list; - //AuthenticatedUser.fromJson(result['List'][0]), - if(result is String){ - new ConfirmDialog( - context: context, - confirmMessage: result, - okText: TranslationBase.of(context).ok, - cancelText: TranslationBase.of(context).cancel_nocaps, - okFunction: () => { - ConfirmDialog.closeAlertDialog(context) - }, - cancelFunction: () => {ConfirmDialog.closeAlertDialog(context)}) - .showAlertDialog(context) - - }else - { - result.list.isFamily = false, - sharedPref.setObject(USER_PROFILE, result.list), - this.sharedPref.setObject(MAIN_USER, result.list), - sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), - sharedPref.setString(TOKEN, result.authenticationTokenID), - Navigator.of(context).pushNamed(HOME) - } - }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); + this + .authService + .registerUser(request) + .then((result) => { + GifLoaderDialogUtils.hideDialog(context), + // userData = result.list; + //AuthenticatedUser.fromJson(result['List'][0]), + if (result is String) + { + new ConfirmDialog( + context: context, + confirmMessage: result, + okText: TranslationBase.of(context).ok, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () => + {ConfirmDialog.closeAlertDialog(context)}, + cancelFunction: () => { + ConfirmDialog.closeAlertDialog(context) + }).showAlertDialog(context) + } + else + { + result.list.isFamily = false, + sharedPref.setObject(USER_PROFILE, result.list), + this.sharedPref.setObject(MAIN_USER, result.list), + sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), + sharedPref.setString(TOKEN, result.authenticationTokenID), + Navigator.of(context).pushNamed(HOME) + } + }) + .catchError((err) { + GifLoaderDialogUtils.hideDialog(context); ConfirmDialog dialog = new ConfirmDialog( context: context, confirmMessage: err, okText: TranslationBase.of(context).confirm, cancelText: TranslationBase.of(context).cancel_nocaps, - okFunction: () => { - ConfirmDialog.closeAlertDialog(context) - }, + okFunction: () => {ConfirmDialog.closeAlertDialog(context)}, cancelFunction: () => {ConfirmDialog.closeAlertDialog(context)}); dialog.showAlertDialog(context); - }); } @@ -347,17 +349,18 @@ class _RegisterInfo extends State { "PatientIdentificationNo": registerInfo.idNumber, "MobileNumber": registerd_data.patientMobileNumber, "PatientOutSA": registerd_data.zipCode == '966' ? 0 : 1, - "FirstNameN":registerInfo.firstNameAr =='-' ?"": registerInfo.firstNameAr, - "FirstName": registerInfo.firstNameEn =='-' ?"":registerInfo.firstNameEn, - "MiddleNameN":registerInfo.secondNameAr =='-' ? "" : registerInfo.secondNameAr, - "MiddleName":registerInfo.secondNameEn == '-' ? "": registerInfo.secondNameEn, - "LastNameN": registerInfo.lastNameAr =='-'? "" : registerInfo.lastNameAr, - "LastName": registerInfo.lastNameEn =='-' ? "": registerInfo.lastNameEn, + "FirstNameN": registerInfo.firstNameAr, + "FirstName": registerInfo.firstNameEn, + "MiddleNameN": registerInfo.secondNameAr, + "MiddleName": registerInfo.secondNameEn, + "LastNameN": registerInfo.lastNameAr, + "LastName": registerInfo.lastNameEn, "StrDateofBirth": registerInfo.dateOfBirth, "DateofBirth": DateUtil.convertISODateToJsonDate( registerInfo.dateOfBirth.replaceAll('/', '-')), "Gender": registerInfo.gender == 'M' ? 1 : 2, - "NationalityID": registerInfo.nationality, + "NationalityID": registerInfo.nationalityCode, + "eHealthIDField": registerInfo.healthId, "DateofBirthN": date, "EmailAddress": email, "SourceType": location, diff --git a/lib/pages/login/register.dart b/lib/pages/login/register.dart index c6a3b872..1591d1d5 100644 --- a/lib/pages/login/register.dart +++ b/lib/pages/login/register.dart @@ -21,6 +21,7 @@ import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; class Register extends StatefulWidget { @override @@ -294,12 +295,12 @@ class _Register extends State { // DOB: this.dateOption === '1' ? this.dateOfBirth : moment(this.dateOfBirth).format('DD/MM/YYYY'), // IsHijri: Number(this.dateOption) // } + + final DateFormat dateFormat = DateFormat('dd/MM/yyyy'); GifLoaderDialogUtils.showMyDialog(context); var request = CheckUserStatusRequest(); request.patientIdentificationID = nationalIDorFile.text; - request.dOB = isHijri == 1 - ? dob - : "${selectedDate.toLocal()}".split(' ')[0].replaceAll('-', '/'); + request.dOB = isHijri == 1 ? dob : dateFormat.format(selectedDate); request.isHijri = isHijri; request.patientOutSA = countryCode == '966' ? 0 : 1; this.authService.checkUserStatus(request).then((result) => { @@ -311,7 +312,12 @@ class _Register extends State { Navigator.of(context).push(FadePage(page: ConfirmLogin())), } else - {AppToast.showErrorToast(message: result)} + { + AppToast.showErrorToast( + message: result + ? result + : TranslationBase.of(context).somethingWentWrong) + } }); } diff --git a/lib/pages/medical/active_medications/ActiveMedicationsPage.dart b/lib/pages/medical/active_medications/ActiveMedicationsPage.dart index 5bc9618d..a6fc5fef 100644 --- a/lib/pages/medical/active_medications/ActiveMedicationsPage.dart +++ b/lib/pages/medical/active_medications/ActiveMedicationsPage.dart @@ -49,7 +49,8 @@ class ActiveMedicationsPage extends StatelessWidget { height: 5, ), Texts( - TranslationBase.of(context).expDate+' :' + + TranslationBase.of(context).expDate + + ' :' + DateUtil.getDayMonthYearDateFormatted(model .activePrescriptionReport[index].orderDate), ), @@ -57,21 +58,24 @@ class ActiveMedicationsPage extends StatelessWidget { height: 5, ), Texts( - TranslationBase.of(context).route+ ' :' + + TranslationBase.of(context).route + + ' :' + model.activePrescriptionReport[index].route, ), SizedBox( height: 5, ), Texts( - TranslationBase.of(context).frequency+ ' :' + + TranslationBase.of(context).frequency + + ' :' + model.activePrescriptionReport[index].frequency, ), SizedBox( height: 5, ), Texts( - TranslationBase.of(context).dailyQuantity + ' :${model.activePrescriptionReport[index].doseDailyQuantity}', + TranslationBase.of(context).dailyQuantity + + ' :${model.activePrescriptionReport[index].doseDailyQuantity}', ), ], ), @@ -86,16 +90,20 @@ class ActiveMedicationsPage extends StatelessWidget { color: Colors.red, size: 28, ), - SizedBox(height: 25,), + SizedBox( + height: 25, + ), InkWell( - onTap: (){ + onTap: () { Navigator.push( context, FadePage( page: ReminderPage( - frequency: model.activePrescriptionReport[index] + frequency: model + .activePrescriptionReport[index] .frequencyNumber, - days: model.activePrescriptionReport[index].days, + days: model + .activePrescriptionReport[index].days, itemDescription: model .activePrescriptionReport[index] .itemDescription, diff --git a/lib/pages/medical/ask_doctor/request_type.dart b/lib/pages/medical/ask_doctor/request_type.dart index 55e04a73..eaf2913d 100644 --- a/lib/pages/medical/ask_doctor/request_type.dart +++ b/lib/pages/medical/ask_doctor/request_type.dart @@ -104,7 +104,8 @@ class _RequestTypePageState extends State { ), bottomSheet: Container( width: double.maxFinite, - height: MediaQuery.of(context).size.height * 0.1, + // height: MediaQuery.of(context).size.height * 0.1, + height: 80.0, child: Padding( padding: const EdgeInsets.all(12.0), child: SecondaryButton( diff --git a/lib/pages/medical/balance/my_balance_page.dart b/lib/pages/medical/balance/my_balance_page.dart index 7639bb2f..f097bda5 100644 --- a/lib/pages/medical/balance/my_balance_page.dart +++ b/lib/pages/medical/balance/my_balance_page.dart @@ -8,7 +8,6 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:hexcolor/hexcolor.dart'; import 'advance_payment_page.dart'; @@ -105,12 +104,12 @@ class MyBalancePage extends StatelessWidget { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.12, + // height: MediaQuery.of(context).size.height * 0.12, + height: 70.0, color: Colors.white, width: double.infinity, padding: EdgeInsets.all(12), child: SecondaryButton( - // color: Colors.grey[900], textColor: Colors.white, label: TranslationBase.of(context).createAdvancedPayment, onTap: () { diff --git a/lib/pages/medical/balance/new_text_Field.dart b/lib/pages/medical/balance/new_text_Field.dart index 3e20dc00..ec3eaf3b 100644 --- a/lib/pages/medical/balance/new_text_Field.dart +++ b/lib/pages/medical/balance/new_text_Field.dart @@ -42,39 +42,39 @@ final _mobileFormatter = NumberTextInputFormatter(); class NewTextFields extends StatefulWidget { NewTextFields( {Key key, - this.type, - this.hintText, - this.suffixIcon, - this.autoFocus, - this.onChanged, - this.initialValue, - this.minLines, - this.maxLines, - this.inputFormatters, - this.padding, - this.focus = false, - this.maxLengthEnforced = true, - this.suffixIconColor, - this.inputAction, - this.onSubmit, - this.keepPadding = true, - this.textCapitalization = TextCapitalization.none, - this.controller, - this.keyboardType, - this.validator, - this.borderOnlyError = false, - this.onSaved, - this.onSuffixTap, - this.readOnly: false, - this.maxLength, - this.prefixIcon, - this.bare = false, - this.onTap, - this.fontSize = 16.0, - this.fontWeight = FontWeight.w700, - this.autoValidate = false, - this.hintColor, - this.isEnabled = true,this.counterText=""}) + this.type, + this.hintText, + this.suffixIcon, + this.autoFocus, + this.onChanged, + this.initialValue, + this.minLines, + this.maxLines, + this.inputFormatters, + this.padding, + this.focus = false, + this.maxLengthEnforced = true, + this.suffixIconColor, + this.inputAction, + this.onSubmit, + this.keepPadding = true, + this.textCapitalization = TextCapitalization.none, + this.controller, + this.keyboardType, + this.validator, + this.borderOnlyError = false, + this.onSaved, + this.onSuffixTap, + this.readOnly: false, + this.maxLength, + this.prefixIcon, + this.bare = false, + this.onTap, + this.fontSize = 16.0, + this.fontWeight = FontWeight.w700, + this.autoValidate = false, + this.hintColor, + this.isEnabled = true,this.counterText=""}) : super(key: key); final String hintText; @@ -171,10 +171,10 @@ class _NewTextFieldsState extends State { textCapitalization: widget.textCapitalization, onFieldSubmitted: widget.inputAction == TextInputAction.next ? (widget.onSubmit != null - ? widget.onSubmit - : (val) { - _focusNode.nextFocus(); - }) + ? widget.onSubmit + : (val) { + _focusNode.nextFocus(); + }) : widget.onSubmit, textInputAction: widget.inputAction, minLines: widget.minLines ?? 1, @@ -194,15 +194,15 @@ class _NewTextFieldsState extends State { fontSize: widget.fontSize, fontWeight: widget.fontWeight), inputFormatters: widget.keyboardType == TextInputType.phone ? [ - WhitelistingTextInputFormatter.digitsOnly, - _mobileFormatter, - ] + WhitelistingTextInputFormatter.digitsOnly, + _mobileFormatter, + ] : widget.inputFormatters, decoration: InputDecoration( labelText: widget.hintText, counterText: widget.counterText, labelStyle: - TextStyle(color: Theme.of(context).textTheme.bodyText1.color), + TextStyle(color: Theme.of(context).textTheme.bodyText1.color), errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).errorColor.withOpacity(0.5), diff --git a/lib/pages/medical/my_trackers/Weight/AddWeightPage.dart b/lib/pages/medical/my_trackers/Weight/AddWeightPage.dart index 62f4e878..9c588f73 100644 --- a/lib/pages/medical/my_trackers/Weight/AddWeightPage.dart +++ b/lib/pages/medical/my_trackers/Weight/AddWeightPage.dart @@ -27,13 +27,13 @@ class AddWeightPage extends StatefulWidget { AddWeightPage( {Key key, - this.model, - this.isUpdate = false, - this.dayWeightDate, - this.lineItemNo, - this.weightValue, - this.measureTimeSelectedType, - this.weightUnit}) + this.model, + this.isUpdate = false, + this.dayWeightDate, + this.lineItemNo, + this.weightValue, + this.measureTimeSelectedType, + this.weightUnit}) : super(key: key); @override @@ -79,39 +79,39 @@ class _AddWeightPageState extends State { ? TranslationBase.of(context).update : TranslationBase.of(context).add, appBarIcons: widget.isUpdate - ? [ - IconButton( - icon: Icon(Icons.delete), - color: Colors.white, - onPressed: () { - ConfirmDialog dialog = new ConfirmDialog( - context: context, - confirmMessage: 'Remove this measure', - okText: TranslationBase.of(context).ok, - cancelText: TranslationBase.of(context).cancel, - okFunction: () async { - ConfirmDialog.closeAlertDialog(context); + ? [ + IconButton( + icon: Icon(Icons.delete), + color: Colors.white, + onPressed: () { + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: 'Remove this measure', + okText: TranslationBase.of(context).ok, + cancelText: TranslationBase.of(context).cancel, + okFunction: () async { + ConfirmDialog.closeAlertDialog(context); - GifLoaderDialogUtils.showMyDialog(context); - widget.model - .deleteWeightResult(lineItemNo: widget.lineItemNo) - .then((value) { - GifLoaderDialogUtils.hideDialog(context); - if (widget.model.state == ViewState.ErrorLocal) - AppToast.showErrorToast( - message: widget.model.error); - else - Navigator.pop(context); - }).catchError((e) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: widget.model.error); - }); - }, - cancelFunction: () => {}); - dialog.showAlertDialog(context); - }, - ) - ] + GifLoaderDialogUtils.showMyDialog(context); + widget.model + .deleteWeightResult(lineItemNo: widget.lineItemNo) + .then((value) { + GifLoaderDialogUtils.hideDialog(context); + if (widget.model.state == ViewState.ErrorLocal) + AppToast.showErrorToast( + message: widget.model.error); + else + Navigator.pop(context); + }).catchError((e) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: widget.model.error); + }); + }, + cancelFunction: () => {}); + dialog.showAlertDialog(context); + }, + ) + ] : null, body: SingleChildScrollView( physics: BouncingScrollPhysics(), @@ -246,12 +246,12 @@ class _AddWeightPageState extends State { GifLoaderDialogUtils.showMyDialog(context); widget.model .updateWeightResult( - weightDate: - '${dayWeightDate.year}-${dayWeightDate.month}-${dayWeightDate.day} ${timeWeightDate.hour}:${timeWeightDate.minute}:00', - weightMeasured: - _weightValueController.text.toString(), - weightUnit: weightUnit, - lineItemNo: widget.lineItemNo) + weightDate: + '${dayWeightDate.year}-${dayWeightDate.month}-${dayWeightDate.day} ${timeWeightDate.hour}:${timeWeightDate.minute}:00', + weightMeasured: + _weightValueController.text.toString(), + weightUnit: weightUnit, + lineItemNo: widget.lineItemNo) .then((value) { GifLoaderDialogUtils.hideDialog(context); if (widget.model.state == ViewState.Error) @@ -263,7 +263,7 @@ class _AddWeightPageState extends State { widget.model .addWeightResult( weightDate: - '${dayWeightDate.year}-${dayWeightDate.month}-${dayWeightDate.day} ${timeWeightDate.hour}:${timeWeightDate.minute}:00', + '${dayWeightDate.year}-${dayWeightDate.month}-${dayWeightDate.day} ${timeWeightDate.hour}:${timeWeightDate.minute}:00', weightMeasured: _weightValueController.text.toString(), weightUnit: weightUnit, ) diff --git a/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart b/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart index c90b29a7..41592110 100644 --- a/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart +++ b/lib/pages/medical/my_trackers/Weight/WeightHomePage.dart @@ -20,8 +20,7 @@ class WeightHomePage extends StatefulWidget { _WeightHomePageState createState() => _WeightHomePageState(); } -class _WeightHomePageState extends State - with SingleTickerProviderStateMixin { +class _WeightHomePageState extends State with SingleTickerProviderStateMixin { TabController _tabController; @override @@ -42,33 +41,38 @@ class _WeightHomePageState extends State onModelReady: (model) => model.getWeight(), builder: (_, model, w) => AppScaffold( isShowAppBar: true, + isShowDecPage: false, appBarTitle: TranslationBase.of(context).weight, - appBarIcons: [IconButton( - icon: Icon(Icons.email), - color: Colors.white, - onPressed: () { - showDialog( - context: context, - child: ConfirmSendEmailDialog( - email: model.user.emailAddress, - onTapSendEmail: () async{ - GifLoaderDialogUtils.showMyDialog(context); - model.sendReportByEmail().then((value) { - GifLoaderDialogUtils.hideDialog(context); - if(model.state == ViewState.ErrorLocal){ + appBarIcons: [ + IconButton( + icon: Icon(Icons.email), + color: Colors.white, + onPressed: () { + showDialog( + context: context, + child: ConfirmSendEmailDialog( + email: model.user.emailAddress, + onTapSendEmail: () async { + GifLoaderDialogUtils.showMyDialog(context); + model.sendReportByEmail().then((value) { + GifLoaderDialogUtils.hideDialog(context); + if (model.state == ViewState.ErrorLocal) { + AppToast.showErrorToast(message: model.error); + } else { + AppToast.showSuccessToast( + message: TranslationBase.of(context).emailSentSuccessfully, + ); + } + }).catchError((e) { + GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: model.error); - }else{ - AppToast.showSuccessToast(message:TranslationBase.of(context).emailSentSuccessfully, ); - } - }).catchError((e){ - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: model.error); - }); - }, - ), - ); - }, - ),], + }); + }, + ), + ); + }, + ), + ], baseViewModel: model, body: Scaffold( extendBodyBehindAppBar: true, @@ -89,7 +93,7 @@ class _WeightHomePageState extends State model: model, ), WeightYearPage( - model: model, + model: model, ) ], ), @@ -98,7 +102,12 @@ class _WeightHomePageState extends State ), floatingActionButton: InkWell( onTap: () { - Navigator.push(context, FadePage(page: AddWeightPage(model: model,))); + Navigator.push( + context, + FadePage( + page: AddWeightPage( + model: model, + ))); }, child: Container( width: 55, diff --git a/lib/pages/medical/my_trackers/Weight/WeightMonthlyPage.dart b/lib/pages/medical/my_trackers/Weight/WeightMonthlyPage.dart index 6f64bacb..e3aa9755 100644 --- a/lib/pages/medical/my_trackers/Weight/WeightMonthlyPage.dart +++ b/lib/pages/medical/my_trackers/Weight/WeightMonthlyPage.dart @@ -28,46 +28,61 @@ class WeightMonthlyPage extends StatelessWidget { Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: model.weighMonthTimeSeriesData.isEmpty?Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),):ListView( - children: [ - Container( - width: double.maxFinite, - color: Colors.white, - child: MonthLineChartCurved( - horizontalInterval: 1.0, - title: TranslationBase.of(context).weight, - timeSeries: model.weighMonthTimeSeriesData, - indexes: model.weighMonthTimeSeriesData.length ~/ 5.5, - )), - SizedBox( - height: 12, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Texts(TranslationBase.of(context).details), - ), - Container( - padding: EdgeInsets.all(10), - color: Colors.transparent, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Table( - border: TableBorder.symmetric( - inside: BorderSide(width: 2.0, color: Colors.grey[300]), + isShowDecPage: false, + body: model.weighMonthTimeSeriesData.isEmpty + ? Container( + child: Center( + child: Container( + child: Center( + child: MonthLineChartCurved( + horizontalInterval: 1.0, + title: TranslationBase.of(context).weight, + timeSeries: model.weighMonthTimeSeriesData, + indexes: model.weighMonthTimeSeriesData.length ~/ 5.5 ?? 0, + ), ), - children: fullData(context, projectViewModel, model), ), + ), + ) + : ListView( + children: [ + Container( + width: double.maxFinite, + color: Colors.white, + child: MonthLineChartCurved( + horizontalInterval: 1.0, + title: TranslationBase.of(context).weight, + timeSeries: model.weighMonthTimeSeriesData, + indexes: model.weighMonthTimeSeriesData.length ~/ 5.5, + )), + SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Texts(TranslationBase.of(context).details), + ), + Container( + padding: EdgeInsets.all(10), + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(context, projectViewModel, model), + ), + ], + ), + ) ], ), - ) - ], - ), ); } - List fullData(BuildContext context, - ProjectViewModel projectViewModel, WeightPressureViewModel model) { + List fullData(BuildContext context, ProjectViewModel projectViewModel, WeightPressureViewModel model) { List tableRow = []; tableRow.add( TableRow( @@ -76,12 +91,8 @@ class WeightMonthlyPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), - topRight: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), + topLeft: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), + topRight: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), ), ), child: Center( @@ -109,12 +120,8 @@ class WeightMonthlyPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), - topRight: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), + topLeft: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), + topRight: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), ), ), child: Center( diff --git a/lib/pages/medical/my_trackers/Weight/WeightWeeklyPage.dart b/lib/pages/medical/my_trackers/Weight/WeightWeeklyPage.dart index 866c2b5b..d0c92da1 100644 --- a/lib/pages/medical/my_trackers/Weight/WeightWeeklyPage.dart +++ b/lib/pages/medical/my_trackers/Weight/WeightWeeklyPage.dart @@ -1,5 +1,3 @@ -import 'package:diplomaticquarterapp/core/model/my_trakers/chartData/WeekChartDate.dart'; -import 'package:diplomaticquarterapp/core/model/my_trakers/weight/WeightMeasurementResult.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/weight_pressure_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/LineChartCurved.dart'; @@ -26,47 +24,62 @@ class WeightWeeklyPage extends StatelessWidget { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: model.weightWeekTimeSeriesData.isEmpty?Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),):ListView( - children: [ - Container( - margin: EdgeInsets.only(top: 12, left: 8, right: 8), - color: Colors.white, - child: LineChartCurved( - horizontalInterval: 1.0, - title: TranslationBase.of(context).weight, - timeSeries: model.weightWeekTimeSeriesData, - indexes: model.weightWeekTimeSeriesData.length ~/ 5.5, - ), - ), - SizedBox( - height: 12, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Texts(TranslationBase.of(context).details), - ), - Container( - padding: EdgeInsets.all(10), - color: Colors.transparent, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Table( - border: TableBorder.symmetric( - inside: BorderSide(width: 2.0, color: Colors.grey[300]), + isShowDecPage: false, + body: model.weightWeekTimeSeriesData.isEmpty + ? Container( + child: Center( + child: Container( + child: Center( + child: LineChartCurved( + horizontalInterval: 1.0, + title: TranslationBase.of(context).weight, + timeSeries: model.weightWeekTimeSeriesData, + indexes: model.weightWeekTimeSeriesData.length ~/ 5.5 ?? 0, + ), ), - children: fullData(context, projectViewModel, model), ), + ), + ) + : ListView( + children: [ + Container( + margin: EdgeInsets.only(top: 12, left: 8, right: 8), + color: Colors.white, + child: LineChartCurved( + horizontalInterval: 1.0, + title: TranslationBase.of(context).weight, + timeSeries: model.weightWeekTimeSeriesData, + indexes: model.weightWeekTimeSeriesData.length ~/ 5.5 ?? 0, + ), + ), + SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Texts(TranslationBase.of(context).details), + ), + Container( + padding: EdgeInsets.all(10), + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(context, projectViewModel, model), + ), + ], + ), + ) ], ), - ) - ], - ), ); } - List fullData(BuildContext context, - ProjectViewModel projectViewModel, WeightPressureViewModel model) { + List fullData(BuildContext context, ProjectViewModel projectViewModel, WeightPressureViewModel model) { List tableRow = []; tableRow.add( TableRow( @@ -75,12 +88,8 @@ class WeightWeeklyPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), - topRight: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), + topLeft: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), + topRight: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), ), ), child: Center( @@ -120,12 +129,8 @@ class WeightWeeklyPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), - topRight: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), + topLeft: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), + topRight: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), ), ), child: Center( diff --git a/lib/pages/medical/my_trackers/Weight/WeightYeaPage.dart b/lib/pages/medical/my_trackers/Weight/WeightYeaPage.dart index 7fa03819..f8fc4dc4 100644 --- a/lib/pages/medical/my_trackers/Weight/WeightYeaPage.dart +++ b/lib/pages/medical/my_trackers/Weight/WeightYeaPage.dart @@ -18,55 +18,70 @@ import 'package:provider/provider.dart'; class WeightYearPage extends StatelessWidget { final WeightPressureViewModel model; - - const WeightYearPage({Key key, this.model, }) - : super(key: key); + const WeightYearPage({ + Key key, + this.model, + }) : super(key: key); @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: model.weightYearTimeSeriesData.isEmpty ? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),) : ListView( - children: [ - Container( - width: double.maxFinite, - color: Colors.white, - child: LineChartCurved( - horizontalInterval: 2.0, - title: TranslationBase.of(context).weight, - timeSeries: model.weightYearTimeSeriesData, - indexes: model.weightYearTimeSeriesData.length ~/ 5.5, - ) - ), - SizedBox( - height: 12, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Texts(TranslationBase.of(context).details), - ), - Container( - padding: EdgeInsets.all(10), - color: Colors.transparent, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Table( - border: TableBorder.symmetric( - inside: BorderSide(width: 2.0, color: Colors.grey[300]), + isShowDecPage: false, + body: model.weightYearTimeSeriesData.isEmpty + ? Container( + child: Center( + child: Container( + child: Center( + child: LineChartCurved( + horizontalInterval: 1.0, + title: TranslationBase.of(context).weight, + timeSeries: model.weightYearTimeSeriesData, + indexes: model.weightWeekTimeSeriesData.length ~/ 5.5 ?? 0, + ), ), - children: fullData(context, projectViewModel, model), ), + ), + ) + : ListView( + children: [ + Container( + width: double.maxFinite, + color: Colors.white, + child: LineChartCurved( + horizontalInterval: 2.0, + title: TranslationBase.of(context).weight, + timeSeries: model.weightYearTimeSeriesData, + indexes: model.weightYearTimeSeriesData.length ~/ 5.5 ?? "", + )), + SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Texts(TranslationBase.of(context).details), + ), + Container( + padding: EdgeInsets.all(10), + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(context, projectViewModel, model), + ), + ], + ), + ) ], ), - ) - ], - ), ); } - List fullData(BuildContext context, - ProjectViewModel projectViewModel, WeightPressureViewModel model) { + List fullData(BuildContext context, ProjectViewModel projectViewModel, WeightPressureViewModel model) { List tableRow = []; tableRow.add( TableRow( @@ -75,12 +90,8 @@ class WeightYearPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), - topRight: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), + topLeft: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), + topRight: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), ), ), child: Center( @@ -108,12 +119,8 @@ class WeightYearPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), - topRight: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), + topLeft: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), + topRight: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), ), ), child: Center( @@ -128,7 +135,7 @@ class WeightYearPage extends StatelessWidget { ), ); model.yearWeightMeasurementResult.forEach( - (diabtec) { + (diabtec) { tableRow.add( TableRow( children: [ diff --git a/lib/pages/medical/my_trackers/blood_pressure/AddBloodPressurePage.dart b/lib/pages/medical/my_trackers/blood_pressure/AddBloodPressurePage.dart index ade2c366..98058bcf 100644 --- a/lib/pages/medical/my_trackers/blood_pressure/AddBloodPressurePage.dart +++ b/lib/pages/medical/my_trackers/blood_pressure/AddBloodPressurePage.dart @@ -42,15 +42,14 @@ class AddBloodPressurePage extends StatefulWidget { class _AddBloodPressurePageState extends State { TextEditingController _bloodSystolicValueController = TextEditingController(); - TextEditingController _bloodDiastolicValueController = - TextEditingController(); + TextEditingController _bloodDiastolicValueController = TextEditingController(); DateTime bloodSugarDate = DateTime.now(); DateTime timeSugarDate = DateTime.now(); int measuredArm = 1; bool isButtonDisabled = false; final List measureTimeEnList = [ - 'Left', - 'Right', + 'Left arm ', + 'Right arm', ]; final List measureTimeArList = [ 'الذراع الأيسر', @@ -81,9 +80,7 @@ class _AddBloodPressurePageState extends State { return AppScaffold( isShowAppBar: true, - appBarTitle: widget.isUpdate - ? TranslationBase.of(context).update - : TranslationBase.of(context).add, + appBarTitle: widget.isUpdate ? TranslationBase.of(context).update : TranslationBase.of(context).add, appBarIcons: widget.isUpdate ? [ IconButton( @@ -99,14 +96,10 @@ class _AddBloodPressurePageState extends State { ConfirmDialog.closeAlertDialog(context); GifLoaderDialogUtils.showMyDialog(context); - widget.model - .deactivateDiabeticStatus( - lineItemNo: widget.lineItemNo) - .then((value) { + widget.model.deactivateDiabeticStatus(lineItemNo: widget.lineItemNo).then((value) { GifLoaderDialogUtils.hideDialog(context); if (widget.model.state == ViewState.ErrorLocal) - AppToast.showErrorToast( - message: widget.model.error); + AppToast.showErrorToast(message: widget.model.error); else Navigator.pop(context); }).catchError((e) { @@ -151,17 +144,13 @@ class _AddBloodPressurePageState extends State { ), InkWell( onTap: () { - confirmSelectMeasureTimeDialog(projectViewModel.isArabic - ? measureTimeEnList - : measureTimeArList); + confirmSelectMeasureTimeDialog(!projectViewModel.isArabic ? measureTimeArList : measureTimeEnList); }, child: Container( padding: EdgeInsets.all(12), width: double.infinity, height: 65, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: Colors.white), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -188,17 +177,13 @@ class _AddBloodPressurePageState extends State { bloodSugarDate = date; }, ); - }, - currentTime: bloodSugarDate, - locale: projectViewModel.localeType); + }, currentTime: bloodSugarDate, locale: projectViewModel.localeType); }, child: Container( padding: EdgeInsets.all(12), width: double.infinity, height: 65, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: Colors.white), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -213,30 +198,22 @@ class _AddBloodPressurePageState extends State { ), InkWell( onTap: () { - DatePicker.showTimePicker(context, showTitleActions: true, - onConfirm: (date) { + DatePicker.showTimePicker(context, showTitleActions: true, onConfirm: (date) { setState( () { timeSugarDate = date; }, ); - }, - currentTime: timeSugarDate, - locale: projectViewModel.localeType); + }, currentTime: timeSugarDate, locale: projectViewModel.localeType); }, child: Container( padding: EdgeInsets.all(12), width: double.infinity, height: 65, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: Colors.white), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Texts(TranslationBase.of(context).time), - Texts(getTime()) - ], + children: [Texts(TranslationBase.of(context).time), Texts(getTime())], ), ), ), @@ -254,12 +231,9 @@ class _AddBloodPressurePageState extends State { loading: widget.model.state == ViewState.BusyLocal, label: TranslationBase.of(context).save.toUpperCase(), textColor: Colors.white, - color: isButtonDisabled - ? Colors.grey[900] - : Colors.grey, + color: isButtonDisabled ? Colors.grey[900] : Colors.grey, onTap: () async { - if (_bloodSystolicValueController.text.isNotEmpty && - _bloodDiastolicValueController.text.isNotEmpty) { + if (_bloodSystolicValueController.text.isNotEmpty && _bloodDiastolicValueController.text.isNotEmpty) { GifLoaderDialogUtils.showMyDialog(context); widget.model @@ -267,10 +241,8 @@ class _AddBloodPressurePageState extends State { isUpdate: widget.isUpdate, bloodPressureDate: '${bloodSugarDate.year}-${bloodSugarDate.month}-${bloodSugarDate.day} ${timeSugarDate.hour}:${timeSugarDate.minute}:00', - diastolicPressure: - _bloodDiastolicValueController.text.toString(), - systolicePressure: - _bloodSystolicValueController.text.toString(), + diastolicPressure: _bloodDiastolicValueController.text.toString(), + systolicePressure: _bloodSystolicValueController.text.toString(), measuredArm: measuredArm, ) .then((value) { @@ -318,7 +290,7 @@ class _AddBloodPressurePageState extends State { } void validateForm() { - print("_bloodSystolicValueController "+_bloodSystolicValueController.text.length.toString()); + print("_bloodSystolicValueController " + _bloodSystolicValueController.text.length.toString()); if (measureTimeSelectedType != 'Left Arm' && _bloodSystolicValueController.text.length > 0 && _bloodDiastolicValueController.text.length > 0) { @@ -348,5 +320,4 @@ class _AddBloodPressurePageState extends State { // }); // } } - } diff --git a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureMonthly.dart b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureMonthly.dart index 04853689..6d4f02d8 100644 --- a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureMonthly.dart +++ b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureMonthly.dart @@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; @@ -21,7 +22,7 @@ class BloodPressureMonthlyPage extends StatelessWidget { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: model.weighMonthTimeSeriesDataTop.isEmpty? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),):ListView( + body: ListView( children: [ Container( margin: EdgeInsets.only(top: 12, left: 8, right: 8), @@ -29,8 +30,8 @@ class BloodPressureMonthlyPage extends StatelessWidget { child: MonthCurvedChartBloodPressure( horizontalInterval: 20.0, title: TranslationBase.of(context).bloodPressure, - timeSeries1: model.weighMonthTimeSeriesDataTop, - timeSeries2: model.weighMonthTimeSeriesDataLow, + timeSeries1: model.weighMonthTimeSeriesDataTop.isEmpty?[TimeSeriesSales3(0,0.0)]:model.weighMonthTimeSeriesDataTop, + timeSeries2: model.weighMonthTimeSeriesDataLow.isEmpty?[TimeSeriesSales3(0,0.0)]:model.weighMonthTimeSeriesDataLow, indexes: model.weightWeekTimeSeriesDataLow.length ~/ 5.5, ), ), @@ -47,7 +48,7 @@ class BloodPressureMonthlyPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Table( + model.weighMonthTimeSeriesDataTop.isEmpty? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),):Table( border: TableBorder.symmetric( inside: BorderSide(width: 2.0, color: Colors.grey[300]), ), diff --git a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureYeaPage.dart b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureYeaPage.dart index b5b01f06..68172354 100644 --- a/lib/pages/medical/my_trackers/blood_pressure/BloodPressureYeaPage.dart +++ b/lib/pages/medical/my_trackers/blood_pressure/BloodPressureYeaPage.dart @@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/CurvedChartBloodPressure.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; @@ -18,7 +19,7 @@ class BloodPressureYearPage extends StatelessWidget { Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: model.weightYearTimeSeriesDataTop.isEmpty? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),):ListView( + body:ListView( children: [ Container( margin: EdgeInsets.only(top: 12, left: 8, right: 8), @@ -26,8 +27,8 @@ class BloodPressureYearPage extends StatelessWidget { child: CurvedChartBloodPressure( horizontalInterval: 3.0,// model.weightWeekTimeSeriesDataLow.length==1 ?1 :20.0, title: TranslationBase.of(context).bloodPressure, - timeSeries1: model.weightYearTimeSeriesDataTop, - timeSeries2: model.weightYearTimeSeriesDataLow, + timeSeries1: model.weightYearTimeSeriesDataTop.isEmpty?[TimeSeriesSales2(DateTime.now(),0.0)]:model.weightYearTimeSeriesDataTop, + timeSeries2: model.weightYearTimeSeriesDataLow.isEmpty?[TimeSeriesSales2(DateTime.now(),0.0)]:model.weightYearTimeSeriesDataLow, indexes: model.weightWeekTimeSeriesDataLow.length ~/ 5.5, ), ), @@ -44,7 +45,7 @@ class BloodPressureYearPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Table( + model.weightYearTimeSeriesDataTop.isEmpty? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),):Table( border: TableBorder.symmetric( inside: BorderSide(width: 2.0, color: Colors.grey[300]), ), diff --git a/lib/pages/medical/my_trackers/blood_pressure/bloodPressureWeeklyPage.dart b/lib/pages/medical/my_trackers/blood_pressure/bloodPressureWeeklyPage.dart index e4ff7332..1929d836 100644 --- a/lib/pages/medical/my_trackers/blood_pressure/bloodPressureWeeklyPage.dart +++ b/lib/pages/medical/my_trackers/blood_pressure/bloodPressureWeeklyPage.dart @@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/CurvedChartBloodPressure.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; @@ -21,7 +22,7 @@ class BloodPressureWeeklyPage extends StatelessWidget { Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: model.weightWeekTimeSeriesDataTop.isEmpty? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),): ListView( + body: ListView( children: [ Container( margin: EdgeInsets.only(top: 12, left: 8, right: 8), @@ -29,8 +30,8 @@ class BloodPressureWeeklyPage extends StatelessWidget { child: CurvedChartBloodPressure( horizontalInterval:3.0, title: TranslationBase.of(context).bloodPressure, - timeSeries1: model.weightWeekTimeSeriesDataTop, - timeSeries2: model.weightWeekTimeSeriesDataLow, + timeSeries1: model.weightWeekTimeSeriesDataTop.isEmpty?[TimeSeriesSales2(DateTime.now(),0.0)]:model.weightWeekTimeSeriesDataTop, + timeSeries2: model.weightWeekTimeSeriesDataLow.isEmpty?[TimeSeriesSales2(DateTime.now(),0.0)]:model.weightWeekTimeSeriesDataLow, indexes: model.weightWeekTimeSeriesDataLow.length ~/ 5.5, ), ), @@ -47,7 +48,7 @@ class BloodPressureWeeklyPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Table( + model.weightWeekTimeSeriesDataTop.isEmpty? Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),): Table( border: TableBorder.symmetric( inside: BorderSide(width: 2.0, color: Colors.grey[300]), ), diff --git a/lib/pages/medical/my_trackers/blood_suger/AddBloodSugarPage.dart b/lib/pages/medical/my_trackers/blood_suger/AddBloodSugarPage.dart index 2ed34c0f..6d4755dc 100644 --- a/lib/pages/medical/my_trackers/blood_suger/AddBloodSugarPage.dart +++ b/lib/pages/medical/my_trackers/blood_suger/AddBloodSugarPage.dart @@ -27,13 +27,13 @@ class AddBloodSugarPage extends StatefulWidget { AddBloodSugarPage( {Key key, - this.bloodSugarDate, - this.measureUnitSelectedType, - this.isUpdate = false, - this.measuredTime, - this.bloodSugarValue, - this.lineItemNo, - this.bloodSugarViewMode}) + this.bloodSugarDate, + this.measureUnitSelectedType, + this.isUpdate = false, + this.measuredTime, + this.bloodSugarValue, + this.lineItemNo, + this.bloodSugarViewMode}) : super(key: key); @override @@ -99,42 +99,42 @@ class _AddBloodSugarPageState extends State { ? TranslationBase.of(context).update : TranslationBase.of(context).add, appBarIcons: widget.isUpdate - ? [ - IconButton( - icon: Icon(Icons.delete), - color: Colors.white, - onPressed: () { - ConfirmDialog dialog = new ConfirmDialog( - context: context, - confirmMessage: 'Remove this measure', - okText: TranslationBase.of(context).ok, - cancelText: TranslationBase.of(context).cancel, - okFunction: () async { - ConfirmDialog.closeAlertDialog(context); + ? [ + IconButton( + icon: Icon(Icons.delete), + color: Colors.white, + onPressed: () { + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: 'Remove this measure', + okText: TranslationBase.of(context).ok, + cancelText: TranslationBase.of(context).cancel, + okFunction: () async { + ConfirmDialog.closeAlertDialog(context); - GifLoaderDialogUtils.showMyDialog(context); - widget.bloodSugarViewMode - .deactivateDiabeticStatus( - lineItemNo: widget.lineItemNo) - .then((value) { - GifLoaderDialogUtils.hideDialog(context); - if (widget.bloodSugarViewMode.state == - ViewState.ErrorLocal) - AppToast.showErrorToast( - message: widget.bloodSugarViewMode.error); - else - Navigator.pop(context); - }).catchError((e) { - GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast( - message: widget.bloodSugarViewMode.error); - }); - }, - cancelFunction: () => {}); - dialog.showAlertDialog(context); - }, - ) - ] + GifLoaderDialogUtils.showMyDialog(context); + widget.bloodSugarViewMode + .deactivateDiabeticStatus( + lineItemNo: widget.lineItemNo) + .then((value) { + GifLoaderDialogUtils.hideDialog(context); + if (widget.bloodSugarViewMode.state == + ViewState.ErrorLocal) + AppToast.showErrorToast( + message: widget.bloodSugarViewMode.error); + else + Navigator.pop(context); + }).catchError((e) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast( + message: widget.bloodSugarViewMode.error); + }); + }, + cancelFunction: () => {}); + dialog.showAlertDialog(context); + }, + ) + ] : null, body: SingleChildScrollView( physics: BouncingScrollPhysics(), @@ -186,10 +186,10 @@ class _AddBloodSugarPageState extends State { showTitleActions: true, minTime: DateTime(DateTime.now().year - 1, 1, 1), maxTime: DateTime.now(), onConfirm: (date) { - setState(() { - bloodSugarDate = date; - }); - }, + setState(() { + bloodSugarDate = date; + }); + }, currentTime: bloodSugarDate, locale: projectViewModel.localeType); }, @@ -216,10 +216,10 @@ class _AddBloodSugarPageState extends State { onTap: () { DatePicker.showTimePicker(context, showTitleActions: true, onConfirm: (date) { - setState(() { - timeSugarDate = date; - }); - }, + setState(() { + timeSugarDate = date; + }); + }, currentTime: timeSugarDate, locale: projectViewModel.localeType); }, @@ -282,20 +282,20 @@ class _AddBloodSugarPageState extends State { label: TranslationBase.of(context).save.toUpperCase(), textColor: Colors.white, color: isButtonDisabled ? Colors.grey[900] : Colors.grey, - onTap: () { + onTap: () async { if (_bloodSugarValueController.text.isNotEmpty) { if (widget.isUpdate) { GifLoaderDialogUtils.showMyDialog(context); - widget.bloodSugarViewMode + await widget.bloodSugarViewMode .updateDiabtecResult( - month: bloodSugarDate, - hour: timeSugarDate, - diabtecUnit: measureUnitSelectedType, - measuredTime: measuredTime, - lineItemNo: widget.lineItemNo, - bloodSugerResult: - _bloodSugarValueController.text.toString()) - .then((value) { + month: bloodSugarDate, + hour: timeSugarDate, + diabtecUnit: measureUnitSelectedType, + measuredTime: measuredTime, + lineItemNo: widget.lineItemNo, + bloodSugerResult: + _bloodSugarValueController.text.toString()); + GifLoaderDialogUtils.hideDialog(context); if (widget.bloodSugarViewMode.state == ViewState.ErrorLocal) @@ -303,25 +303,28 @@ class _AddBloodSugarPageState extends State { message: widget.bloodSugarViewMode.error); else Navigator.pop(context); - }); - } else - widget.bloodSugarViewMode + + } else { + GifLoaderDialogUtils.showMyDialog(context); + await widget.bloodSugarViewMode .addDiabtecResult( diabtecUnit: measureUnitSelectedType, measuredTime: measuredTime, bloodSugerResult: - _bloodSugarValueController.text.toString(), + _bloodSugarValueController.text.toString(), bloodSugerDateChart: - '${bloodSugarDate.year}-${bloodSugarDate.month}-${bloodSugarDate.day} ${timeSugarDate.hour}:${timeSugarDate.minute}:00', - ) - .then((value) { + '${bloodSugarDate.year}-${bloodSugarDate.month}-${bloodSugarDate.day} ${timeSugarDate.hour}:${timeSugarDate.minute}:00', + ); + GifLoaderDialogUtils.hideDialog(context); if (widget.bloodSugarViewMode.state == ViewState.Error) AppToast.showErrorToast( message: widget.bloodSugarViewMode.error); else Navigator.pop(context); - }); + + } + } }), ), diff --git a/lib/pages/medical/my_trackers/blood_suger/BloodMonthly.dart b/lib/pages/medical/my_trackers/blood_suger/BloodMonthly.dart index 1294c5dd..a0f37c83 100644 --- a/lib/pages/medical/my_trackers/blood_suger/BloodMonthly.dart +++ b/lib/pages/medical/my_trackers/blood_suger/BloodMonthly.dart @@ -1,6 +1,7 @@ import 'package:diplomaticquarterapp/core/model/my_trakers/blood_sugar/DiabtecPatientResult.dart'; import 'package:diplomaticquarterapp/core/model/my_trakers/chartData/WeekChartDate.dart'; import 'package:diplomaticquarterapp/core/model/my_trakers/chartData/YearMonthlyChartDate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/medical/blood_sugar_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/LineChartCurved.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/MonthLineChartCurved.dart'; @@ -17,25 +18,32 @@ import 'package:provider/provider.dart'; class BloodMonthlyPage extends StatelessWidget { final List diabtecPatientResult; - final List timeSeriesData ; + final List timeSeriesData; + final BloodSugarViewMode bloodSugarViewMode; - const BloodMonthlyPage({Key key, this.diabtecPatientResult, this.timeSeriesData}) + + const BloodMonthlyPage( + {Key key, this.diabtecPatientResult, this.timeSeriesData, this.bloodSugarViewMode}) : super(key: key); + @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: timeSeriesData.isEmpty?Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),): ListView( + baseViewModel: bloodSugarViewMode, + body: ListView( children: [ Container( + margin: EdgeInsets.only(top: 12, left: 8, right: 8), width: double.maxFinite, color: Colors.white, child: MonthLineChartCurved( - title: 'Sugar', - timeSeries: timeSeriesData, + title: '${TranslationBase.of(context).bloodSugar}', + timeSeries: timeSeriesData.isEmpty + ? [TimeSeriesSales3(0, 0.0)] + : timeSeriesData, indexes: timeSeriesData.length ~/ 5.5, - ) - ), + )), SizedBox( height: 12, ), @@ -49,12 +57,20 @@ class BloodMonthlyPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Table( - border: TableBorder.symmetric( - inside: BorderSide(width: 2.0, color: Colors.grey[300]), - ), - children: fullData(context,projectViewModel), - ), + timeSeriesData.isEmpty + ? Container( + child: Center( + child: Texts( + TranslationBase.of(context).noDataAvailable), + ), + ) + : Table( + border: TableBorder.symmetric( + inside: + BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(context, projectViewModel), + ), ], ), ) @@ -63,7 +79,8 @@ class BloodMonthlyPage extends StatelessWidget { ); } - List fullData(BuildContext context,ProjectViewModel projectViewModel) { + List fullData( + BuildContext context, ProjectViewModel projectViewModel) { List tableRow = []; tableRow.add( TableRow( @@ -73,8 +90,12 @@ class BloodMonthlyPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), - topRight: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0), + topLeft: projectViewModel.isArabic + ? Radius.circular(0.0) + : Radius.circular(10.0), + topRight: projectViewModel.isArabic + ? Radius.circular(10.0) + : Radius.circular(0.0), ), ), child: Center( @@ -120,8 +141,12 @@ class BloodMonthlyPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0), - topRight: projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topLeft: projectViewModel.isArabic + ? Radius.circular(10.0) + : Radius.circular(0.0), + topRight: projectViewModel.isArabic + ? Radius.circular(0.0) + : Radius.circular(10.0), ), ), child: Center( @@ -133,7 +158,6 @@ class BloodMonthlyPage extends StatelessWidget { ), height: 40), ), - ], ), ); @@ -149,7 +173,7 @@ class BloodMonthlyPage extends StatelessWidget { color: Colors.white, child: Center( child: Texts( - '${projectViewModel.isArabic ? DateUtil.getMonthDayYearDateFormattedAr(diabtec.dateChart):DateUtil.getMonthDayYearDateFormatted(diabtec.dateChart)} ', + '${projectViewModel.isArabic ? DateUtil.getMonthDayYearDateFormattedAr(diabtec.dateChart) : DateUtil.getMonthDayYearDateFormatted(diabtec.dateChart)} ', textAlign: TextAlign.center, fontSize: 12, ), diff --git a/lib/pages/medical/my_trackers/blood_suger/BloodYeaPage.dart b/lib/pages/medical/my_trackers/blood_suger/BloodYeaPage.dart index 842d55f1..a11b3b14 100644 --- a/lib/pages/medical/my_trackers/blood_suger/BloodYeaPage.dart +++ b/lib/pages/medical/my_trackers/blood_suger/BloodYeaPage.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/model/my_trakers/blood_sugar/DiabtecPatientResult.dart'; import 'package:diplomaticquarterapp/core/model/my_trakers/chartData/WeekChartDate.dart'; +import 'package:diplomaticquarterapp/core/viewModels/medical/blood_sugar_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/medical/my_trackers/widget/LineChartCurved.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; @@ -16,29 +17,25 @@ import 'package:provider/provider.dart'; class BloodYearPage extends StatelessWidget { final List diabtecPatientResult; final List timeSeriesData; + final BloodSugarViewMode bloodSugarViewMode; - const BloodYearPage({Key key, this.diabtecPatientResult, this.timeSeriesData}) - : super(key: key); + const BloodYearPage({Key key, this.diabtecPatientResult, this.timeSeriesData, this.bloodSugarViewMode}) : super(key: key); @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body: timeSeriesData.isEmpty - ? Container( - child: Center( - child: Texts(TranslationBase.of(context).noDataAvailable), - ), - ) - : ListView( + baseViewModel: bloodSugarViewMode, + body: ListView( children: [ Container( + margin: EdgeInsets.only(top: 12, left: 8, right: 8), width: double.maxFinite, color: Colors.white, child: LineChartCurved( - title: 'Sugar', - timeSeries: timeSeriesData, - indexes: timeSeriesData.length ~/ 5.5, + title: '${TranslationBase.of(context).bloodSugar}', + timeSeries: timeSeriesData.isEmpty?[TimeSeriesSales2(DateTime.now(),0.0)]:timeSeriesData, + indexes: timeSeriesData.length ~/ 5.5 ?? 0, )), SizedBox( height: 12, @@ -53,10 +50,15 @@ class BloodYearPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Table( + timeSeriesData.isEmpty + ? Container( + child: Center( + child: Texts(TranslationBase.of(context).noDataAvailable), + ), + ) + :Table( border: TableBorder.symmetric( - inside: - BorderSide(width: 2.0, color: Colors.grey[300]), + inside: BorderSide(width: 2.0, color: Colors.grey[300]), ), children: fullData(context, projectViewModel), ), @@ -68,8 +70,7 @@ class BloodYearPage extends StatelessWidget { ); } - List fullData( - BuildContext context, ProjectViewModel projectViewModel) { + List fullData(BuildContext context, ProjectViewModel projectViewModel) { List tableRow = []; tableRow.add( TableRow( @@ -79,12 +80,8 @@ class BloodYearPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), - topRight: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), + topLeft: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), + topRight: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), ), ), child: Center( @@ -130,12 +127,8 @@ class BloodYearPage extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.only( - topLeft: projectViewModel.isArabic - ? Radius.circular(10.0) - : Radius.circular(0.0), - topRight: projectViewModel.isArabic - ? Radius.circular(0.0) - : Radius.circular(10.0), + topLeft: projectViewModel.isArabic ? Radius.circular(10.0) : Radius.circular(0.0), + topRight: projectViewModel.isArabic ? Radius.circular(0.0) : Radius.circular(10.0), ), ), child: Center( diff --git a/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart b/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart index 7abbcceb..29989e53 100644 --- a/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart +++ b/lib/pages/medical/my_trackers/blood_suger/blood_sugar_home_page.dart @@ -75,7 +75,7 @@ class _BloodSugarHomePageState extends State ),], isShowAppBar: true, appBarTitle: TranslationBase.of(context).bloodSugar, - baseViewModel: model, + // baseViewModel: model, body: Scaffold( extendBodyBehindAppBar: true, appBar: TabBarWidget(tabController: _tabController,), @@ -93,11 +93,12 @@ class _BloodSugarHomePageState extends State ), BloodMonthlyPage( timeSeriesData: model.monthTimeSeriesData, - diabtecPatientResult: model.monthDiabtecPatientResult, + diabtecPatientResult: model.monthDiabtecPatientResult, bloodSugarViewMode: model, ), BloodYearPage( timeSeriesData: model.yearTimeSeriesData, diabtecPatientResult: model.yearDiabtecPatientResult, + bloodSugarViewMode: model, ) ], ), diff --git a/lib/pages/medical/my_trackers/blood_suger/blood_sugar_weekly_page.dart b/lib/pages/medical/my_trackers/blood_suger/blood_sugar_weekly_page.dart index 60f3293d..6e1ff71b 100644 --- a/lib/pages/medical/my_trackers/blood_suger/blood_sugar_weekly_page.dart +++ b/lib/pages/medical/my_trackers/blood_suger/blood_sugar_weekly_page.dart @@ -31,42 +31,48 @@ class BloodSugarWeeklyPage extends StatelessWidget { Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); return AppScaffold( - body:timeSeriesData.isEmpty?Container(child: Center(child: Texts(TranslationBase.of(context).noDataAvailable),),): ListView( - children: [ - Container( - margin: EdgeInsets.only(top: 12, left: 8, right: 8), - color: Colors.white, - child: LineChartCurved( - title: 'Sugar', - timeSeries: timeSeriesData, - indexes: timeSeriesData.length ~/ 5.5, - ), - ), - SizedBox( - height: 12, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Texts(TranslationBase.of(context).details), - ), - Container( - padding: EdgeInsets.all(10), - color: Colors.transparent, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Table( - border: TableBorder.symmetric( - inside: BorderSide(width: 2.0, color: Colors.grey[300]), + baseViewModel: bloodSugarViewMode, + body: ListView( + children: [ + Container( + margin: EdgeInsets.only(top: 12, left: 8, right: 8), + color: Colors.white, + child: LineChartCurved( + title: '${TranslationBase.of(context).bloodSugar}', + timeSeries: timeSeriesData.isEmpty?[TimeSeriesSales2(DateTime.now(),0.0)]:timeSeriesData, + indexes: timeSeriesData.length ~/ 5.5, ), - children: - fullData(context, projectViewModel, bloodSugarViewMode), ), + SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Texts(TranslationBase.of(context).details), + ), + Container( + padding: EdgeInsets.all(10), + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + timeSeriesData.isEmpty + ? Container( + child: Center( + child: Texts(TranslationBase.of(context).noDataAvailable), + ), + ) + :Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(context, projectViewModel, bloodSugarViewMode), + ), + ], + ), + ) ], ), - ) - ], - ), ); } diff --git a/lib/pages/medical/my_trackers/my_trackers.dart b/lib/pages/medical/my_trackers/my_trackers.dart index 5e5c4527..c133c67a 100644 --- a/lib/pages/medical/my_trackers/my_trackers.dart +++ b/lib/pages/medical/my_trackers/my_trackers.dart @@ -15,6 +15,7 @@ class MyTrackers extends StatelessWidget { return AppScaffold( appBarTitle: TranslationBase.of(context).myTracker, isShowAppBar: true, + isShowDecPage: false, body: SingleChildScrollView( child: Container( padding: EdgeInsets.all(12), @@ -27,22 +28,24 @@ class MyTrackers extends StatelessWidget { children: [ Expanded( child: InkWell( - onTap: ()=> Navigator.push(context, FadePage(page: BloodSugarHomePage())), + onTap: () => Navigator.push(context, FadePage(page: BloodSugarHomePage())), child: Container( margin: EdgeInsets.all(5), - width: MediaQuery.of(context).size.width*0.35, - height:MediaQuery.of(context).size.width*0.35 , + width: MediaQuery.of(context).size.width * 0.35, + height: MediaQuery.of(context).size.width * 0.35, decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(8), - color: Colors.white - ), + shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(8), color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/tracker/blood-suger.png',width: 60.0,), - SizedBox(height: 15,), + Image.asset( + 'assets/tracker/blood-suger.png', + width: 60.0, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).bloodSugar), ], ), @@ -51,22 +54,24 @@ class MyTrackers extends StatelessWidget { ), Expanded( child: InkWell( - onTap: ()=> Navigator.push(context, FadePage(page: BloodPressureHomePage())), + onTap: () => Navigator.push(context, FadePage(page: BloodPressureHomePage())), child: Container( margin: EdgeInsets.all(5), - width: MediaQuery.of(context).size.width*0.35, - height:MediaQuery.of(context).size.width*0.35 , + width: MediaQuery.of(context).size.width * 0.35, + height: MediaQuery.of(context).size.width * 0.35, decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(8), - color: Colors.white - ), + shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(8), color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/tracker/blood-pressure.png',width: 60.0,), - SizedBox(height: 15,), + Image.asset( + 'assets/tracker/blood-pressure.png', + width: 60.0, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).bloodPressure), ], ), @@ -80,22 +85,24 @@ class MyTrackers extends StatelessWidget { children: [ Expanded( child: InkWell( - onTap: ()=> Navigator.push(context, FadePage(page: WeightHomePage())), + onTap: () => Navigator.push(context, FadePage(page: WeightHomePage())), child: Container( margin: EdgeInsets.all(5), - width: MediaQuery.of(context).size.width*0.35, - height:MediaQuery.of(context).size.width*0.35 , + width: MediaQuery.of(context).size.width * 0.35, + height: MediaQuery.of(context).size.width * 0.35, decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(8), - color: Colors.white - ), + shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(8), color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/tracker/weight.png',width: 60.0,), - SizedBox(height: 15,), + Image.asset( + 'assets/tracker/weight.png', + width: 60.0, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).weight), ], ), diff --git a/lib/pages/medical/my_trackers/widget/CurvedChartBloodPressure.dart b/lib/pages/medical/my_trackers/widget/CurvedChartBloodPressure.dart index ac2349bc..7248b7e0 100644 --- a/lib/pages/medical/my_trackers/widget/CurvedChartBloodPressure.dart +++ b/lib/pages/medical/my_trackers/widget/CurvedChartBloodPressure.dart @@ -158,19 +158,13 @@ class CurvedChartBloodPressure extends StatelessWidget { ), leftTitles: SideTitles( showTitles: true, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, + getTextStyles: (value) => const TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (value.toInt() == 0) - return '${value.toInt()}'; - else if (value.toInt() % horizontalInterval == 0) - return '${value.toInt()}'; - else - return ''; - }, margin: 12, ), ), diff --git a/lib/pages/medical/my_trackers/widget/LineChartCurved.dart b/lib/pages/medical/my_trackers/widget/LineChartCurved.dart index eeff06dd..2597f17c 100644 --- a/lib/pages/medical/my_trackers/widget/LineChartCurved.dart +++ b/lib/pages/medical/my_trackers/widget/LineChartCurved.dart @@ -10,11 +10,7 @@ class LineChartCurved extends StatelessWidget { final int indexes; final double horizontalInterval; - LineChartCurved( - {this.title, - this.timeSeries, - this.indexes, - this.horizontalInterval = 20.0}); + LineChartCurved({this.title, this.timeSeries, this.indexes, this.horizontalInterval = 20.0}); List xAxixs = List(); List yAxixs = List(); @@ -24,7 +20,7 @@ class LineChartCurved extends StatelessWidget { getXaxix(); getYaxix(); return AspectRatio( - aspectRatio: 1.1, + aspectRatio: 1.0, child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(18)), @@ -40,8 +36,7 @@ class LineChartCurved extends StatelessWidget { ), Text( title, - style: TextStyle( - color: Colors.black, fontSize: 15, letterSpacing: 2), + style: TextStyle(color: Colors.black, fontSize: 15, letterSpacing: 2), textAlign: TextAlign.center, ), SizedBox( @@ -49,8 +44,7 @@ class LineChartCurved extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.only( - right: 18.0, left: 16.0, top: 15, bottom: 15), + padding: const EdgeInsets.only(right: 18.0, left: 16.0, top: 15, bottom: 15), child: LineChart( sampleData1(context), swapAnimationDuration: const Duration(milliseconds: 250), @@ -86,7 +80,6 @@ class LineChartCurved extends StatelessWidget { } } } - LineChartData sampleData1(context) { return LineChartData( lineTouchData: LineTouchData( @@ -97,10 +90,7 @@ class LineChartCurved extends StatelessWidget { handleBuiltInTouches: true, ), gridData: FlGridData( - horizontalInterval: horizontalInterval, - show: true, - drawVerticalLine: true, - drawHorizontalLine: true), + horizontalInterval: horizontalInterval, show: true, drawVerticalLine: true, drawHorizontalLine: true), titlesData: FlTitlesData( bottomTitles: SideTitles( showTitles: true, @@ -131,19 +121,13 @@ class LineChartCurved extends StatelessWidget { ), leftTitles: SideTitles( showTitles: true, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, getTextStyles: (value) => const TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (value.toInt() == 0) - return '${value.toInt()}'; - else if (value.toInt() % horizontalInterval == 0) - return '${value.toInt()}'; - else - return ''; - }, + margin: 12, ), ), @@ -168,7 +152,7 @@ class LineChartCurved extends StatelessWidget { minX: 0, maxX: (timeSeries.length - 1).toDouble(), maxY: getMaxY() + 0.3, - minY: getMinY(), + minY: 0,//getMinY(), lineBarsData: getData(context), ); } @@ -184,7 +168,7 @@ class LineChartCurved extends StatelessWidget { } double getMinY() { - double min = timeSeries[0].sales; + double min = timeSeries.isEmpty ? 0 : timeSeries.first.sales; timeSeries.forEach((element) { double resultValueDouble = element.sales; if (resultValueDouble < min) min = resultValueDouble; @@ -196,6 +180,9 @@ class LineChartCurved extends StatelessWidget { List getData(context) { List spots = List(); + if (timeSeries.length == 0) { + spots.add(FlSpot(0, 0)); + } for (int index = 0; index < timeSeries.length; index++) { spots.add(FlSpot(index.toDouble(), timeSeries[index].sales)); } diff --git a/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart b/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart index 135d0a95..ee7e00af 100644 --- a/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart +++ b/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart @@ -21,7 +21,7 @@ class MonthCurvedChartBloodPressure extends StatelessWidget { Widget build(BuildContext context) { getXaxix(); return AspectRatio( - aspectRatio: 1.1, + aspectRatio: 1.0, child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(18)), @@ -137,19 +137,21 @@ class MonthCurvedChartBloodPressure extends StatelessWidget { ), leftTitles: SideTitles( showTitles: true, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, + getTextStyles: (value) => const TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (value.toInt() == 0) - return '${value.toInt()}'; - else if (value.toInt() % horizontalInterval == 0) - return '${value.toInt()}'; - else - return ''; - }, + // getTitles: (value) { + // // if (value.toInt() == 0) + // // return '${value.toInt()}'; + // // else if (value.toInt() % horizontalInterval == 0) + // // return '${value.toInt()}'; + // // else + // return '${value.toInt()}'; + // }, margin: 12, ), ), diff --git a/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart b/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart index 607f3ab0..5ef71f5b 100644 --- a/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart +++ b/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart @@ -10,11 +10,7 @@ class MonthLineChartCurved extends StatelessWidget { final int indexes; final double horizontalInterval; - MonthLineChartCurved( - {this.title, - this.timeSeries, - this.indexes, - this.horizontalInterval = 15.0}); + MonthLineChartCurved({this.title, this.timeSeries, this.indexes, this.horizontalInterval = 15.0}); List xAxixs = List(); List yAxixs = List(); @@ -40,8 +36,7 @@ class MonthLineChartCurved extends StatelessWidget { ), Text( title, - style: TextStyle( - color: Colors.black, fontSize: 15, letterSpacing: 2), + style: TextStyle(color: Colors.black, fontSize: 15, letterSpacing: 2), textAlign: TextAlign.center, ), SizedBox( @@ -49,8 +44,7 @@ class MonthLineChartCurved extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.only( - right: 18.0, left: 16.0, top: 15, bottom: 15), + padding: const EdgeInsets.only(right: 18.0, left: 16.0, top: 15, bottom: 15), child: LineChart( sampleData1(context), swapAnimationDuration: const Duration(milliseconds: 250), @@ -97,10 +91,7 @@ class MonthLineChartCurved extends StatelessWidget { handleBuiltInTouches: true, ), gridData: FlGridData( - horizontalInterval: horizontalInterval, - show: true, - drawVerticalLine: true, - drawHorizontalLine: true), + horizontalInterval: horizontalInterval, show: true, drawVerticalLine: true, drawHorizontalLine: true), titlesData: FlTitlesData( bottomTitles: SideTitles( showTitles: true, @@ -120,14 +111,16 @@ class MonthLineChartCurved extends StatelessWidget { fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (value.toInt() == 0) - return '${value.toInt()}'; - else if (value.toInt() % horizontalInterval == 0) - return '${value.toInt()}'; - else - return ''; - }, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, + + // getTitles: (value) { + // if (value.toInt() == 0) + // return '${value.toInt()}'; + // else if (value.toInt() % horizontalInterval == 0) + // return '${value.toInt()}'; + // else + // return ''; + // }, margin: 12, ), ), @@ -180,6 +173,9 @@ class MonthLineChartCurved extends StatelessWidget { List getData(context) { List spots = List(); + if (timeSeries.length == 0) { + spots.add(FlSpot(0, 0)); + } for (int index = 0; index < timeSeries.length; index++) { spots.add(FlSpot(index.toDouble(), timeSeries[index].sales)); } diff --git a/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart b/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart index 96227fba..8224e61d 100644 --- a/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart +++ b/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart @@ -10,92 +10,94 @@ import 'package:maps_launcher/maps_launcher.dart'; import 'package:url_launcher/url_launcher.dart'; class PharmacyForPrescriptionsPage extends StatelessWidget { - final PrescriptionReport prescriptionReport; + final itemID; - PharmacyForPrescriptionsPage({Key key, this.prescriptionReport}); + PharmacyForPrescriptionsPage({Key key, this.itemID}); @override Widget build(BuildContext context) { - return BaseView( - onModelReady: (model) => model.getListPharmacyForPrescriptions(itemId: prescriptionReport.itemID), - builder: (_, model, widget) => AppScaffold( - isShowAppBar: true, - appBarTitle: TranslationBase.of(context).availability, - baseViewModel: model, - body: ListView.builder( - itemBuilder: (context, index) => Container( - width: double.infinity, - margin: EdgeInsets.only(top: 10, left: 10, right: 10), - padding: EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(10.0), - ), - border: Border.all(color: Colors.grey[200], width: 0.5), + return BaseView( + onModelReady: (model) => + model.getListPharmacyForPrescriptions(itemId: itemID), + builder: (_, model, widget) => AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).availability, + baseViewModel: model, + body: ListView.builder( + itemBuilder: (context, index) => Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10, left: 10, right: 10), + padding: EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10.0), ), - child: Row( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5)), - child: Image.network( - model.pharmacyPrescriptionsList[index].projectImageURL, - fit: BoxFit.cover, - width: 60, - height: 70, - ), + border: Border.all(color: Colors.grey[200], width: 0.5), + ), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5)), + child: Image.network( + model.pharmacyPrescriptionsList[index].projectImageURL, + fit: BoxFit.cover, + width: 60, + height: 70, ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts(model.pharmacyPrescriptionsList[index] - .locationDescription), - SizedBox( - height: 5, - ), - Texts(model.pharmacyPrescriptionsList[index].cityName), - ], - ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts(model.pharmacyPrescriptionsList[index] + .locationDescription), + SizedBox( + height: 5, + ), + Texts(model.pharmacyPrescriptionsList[index].cityName), + ], ), ), - InkWell( - onTap: () { - MapsLauncher.launchCoordinates( - double.parse( - model.pharmacyPrescriptionsList[index].latitude), - double.parse( - model.pharmacyPrescriptionsList[index].longitude)); - }, + ), + InkWell( + onTap: () { + MapsLauncher.launchCoordinates( + double.parse( + model.pharmacyPrescriptionsList[index].latitude), + double.parse( + model.pharmacyPrescriptionsList[index].longitude)); + }, + child: Icon( + Icons.pin_drop, + size: 18, + color: Colors.red[900], + ), + ), + SizedBox( + width: 15, + ), + InkWell( + onTap: Feedback.wrapForTap(() { + launch( + "tel://${model.pharmacyPrescriptionsList[index].phoneNumber}"); + }, context), + child: Container( child: Icon( - Icons.pin_drop, + Icons.call, size: 18, color: Colors.red[900], ), ), - SizedBox( - width: 15, - ), - InkWell( - onTap: Feedback.wrapForTap((){ - launch("tel://${model.pharmacyPrescriptionsList[index].phoneNumber}"); - },context), - child: Container( - child: Icon( - Icons.call, - size: 18, - color: Colors.red[900], - ), - ), - ) - ], - ), + ) + ], ), - itemCount: model.pharmacyPrescriptionsList.length, ), + itemCount: model.pharmacyPrescriptionsList.length, ), - ); + ), + ); } } diff --git a/lib/pages/medical/prescriptions/prescription_details_inp.dart b/lib/pages/medical/prescriptions/prescription_details_inp.dart new file mode 100644 index 00000000..91f4a4c6 --- /dev/null +++ b/lib/pages/medical/prescriptions/prescription_details_inp.dart @@ -0,0 +1,310 @@ +import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report.dart'; +import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_inp.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/MyAppointments/widgets/reminder_dialog.dart'; +import 'package:diplomaticquarterapp/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class PrescriptionDetailsPageINP extends StatelessWidget { + final PrescriptionReportINP prescriptionReport; + + PrescriptionDetailsPageINP({Key key, this.prescriptionReport}); + + @override + Widget build(BuildContext context) { + return AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).prescriptions, + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10, left: 10, right: 10), + padding: EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10.0), + ), + border: Border.all(color: Colors.grey[200], width: 0.5), + ), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5)), + child: Image.network( + prescriptionReport.imageSRCUrl, + fit: BoxFit.cover, + width: 60, + height: 70, + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Texts( + prescriptionReport.itemDescription.isNotEmpty + ? prescriptionReport.itemDescription + : prescriptionReport.itemDescriptionN ?? ''), + ), + ), + ) + ], + ), + ), + Container( + margin: EdgeInsets.all(8), + child: Row( + children: [ + Expanded( + child: InkWell( + onTap: () => Navigator.push( + context, + FadePage( + page: PharmacyForPrescriptionsPage( + itemID: prescriptionReport.itemID), + ), + ), + child: Center( + child: Column( + children: [ + Container( + width: 50, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.rectangle), + child: Column( + children: [ + Icon( + Icons.pin_drop, + color: Colors.red[800], + size: 55, + ), + ], + ), + ), + SizedBox( + height: 5, + ), + Texts(TranslationBase.of(context).availability) + ], + ), + )), + ), + _addReminderButton(context) + ], + ), + ), + Container( + color: Colors.white, + margin: EdgeInsets.only(top: 10, left: 10, right: 10), + child: Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 0.5), + outside: BorderSide(width: 0.5)), + children: [ + TableRow( + children: [ + Container( + color: Colors.white, + height: 40, + width: double.infinity, + child: Center( + child: Texts( + TranslationBase.of(context).route, + fontSize: 14, + ))), + Container( + color: Colors.white, + height: 40, + width: double.infinity, + child: Center( + child: Texts( + TranslationBase.of(context).frequency, + fontSize: 14, + ))), + Container( + color: Colors.white, + height: 40, + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 4), + child: Center( + child: Texts( + "${TranslationBase.of(context).dailyDoses}", + fontSize: 14, + ))), + Container( + color: Colors.white, + height: 40, + width: double.infinity, + child: Center( + child: Texts( + TranslationBase.of(context).duration, + fontSize: 14, + ))), + ], + ), + TableRow( + children: [ + Container( + color: Colors.white, + height: 50, + width: double.infinity, + child: Center( + child: Text(prescriptionReport.routeN ?? ''))), + Container( + color: Colors.white, + height: 50, + width: double.infinity, + child: Center( + child: + Text(prescriptionReport.frequencyN ?? ''))), + Container( + color: Colors.white, + height: 50, + width: double.infinity, + child: Center( + child: Text( + '${prescriptionReport.doseDailyQuantity}'))), + Container( + color: Colors.white, + height: 50, + width: double.infinity, + child: + Center(child: Text('${prescriptionReport.days}'))) + ], + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 10, left: 10, right: 10), + width: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(5), + child: Center( + child: Column( + children: [ + Texts(TranslationBase.of(context).notes), + SizedBox( + height: 5, + ), + Divider( + height: 0.5, + color: Colors.grey[300], + ), + SizedBox( + height: 5, + ), + Texts(prescriptionReport.remarks ?? ''), + ], + ), + ), + ) + ], + ), + ), + ); + } + + Widget _addReminderButton(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + + return GestureDetector( + onTap: () { + DateTime startDate = DateTime.now(); + DateTime endDate = DateTime(startDate.year, startDate.month, + startDate.day + prescriptionReport.days); + + print(prescriptionReport); + showGeneralDialog( + barrierColor: Colors.black.withOpacity(0.5), + transitionBuilder: (context, a1, a2, widget) { + final curvedValue = + Curves.easeInOutBack.transform(a1.value) - 1.0; + return Transform( + transform: + Matrix4.translationValues(0.0, curvedValue * 200, 0.0), + child: Opacity( + opacity: a1.value, + child: ReminderDialog( + eventId: prescriptionReport.itemID.toString(), + title: "Prescription Reminder", + description: + "${prescriptionReport.itemDescriptionN} ${prescriptionReport.frequencyN} ${prescriptionReport.routeN} ", + startDate: + "/Date(${startDate.millisecondsSinceEpoch}+0300)/", + endDate: "/Date(${endDate.millisecondsSinceEpoch}+0300)/", + location: prescriptionReport.remarks, + ), + ), + ); + }, + transitionDuration: Duration(milliseconds: 500), + barrierDismissible: true, + barrierLabel: '', + context: context, + pageBuilder: (context, animation1, animation2) {}); + }, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + // height: 100.0, + margin: EdgeInsets.all(7.0), + padding: EdgeInsets.only(bottom: 4.0), + decoration: BoxDecoration(boxShadow: [ + BoxShadow( + color: Colors.grey[400], blurRadius: 2.0, spreadRadius: 0.0) + ], borderRadius: BorderRadius.circular(10), color: Colors.white), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Container( + margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 0.0), + child: Text("add", + overflow: TextOverflow.clip, + style: TextStyle( + color: new Color(0xffB8382C), + letterSpacing: 1.0, + fontSize: 18.0)), + ), + Container( + margin: EdgeInsets.fromLTRB(5.0, 0.0, 5.0, 0.0), + child: Text("reminder", + overflow: TextOverflow.clip, + style: TextStyle( + color: Colors.black, + letterSpacing: 1.0, + fontSize: 15.0)), + ), + Container( + alignment: projectViewModel.isArabic + ? Alignment.bottomLeft + : Alignment.bottomRight, + margin: projectViewModel.isArabic + ? EdgeInsets.fromLTRB(10.0, 7.0, 0.0, 8.0) + : EdgeInsets.fromLTRB(0.0, 7.0, 10.0, 8.0), + child: Image.asset( + "assets/images/new-design/reminder_icon.png", + width: 45.0, + height: 45.0), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/medical/prescriptions/prescription_details_page.dart b/lib/pages/medical/prescriptions/prescription_details_page.dart index 72e830cf..218d7ac6 100644 --- a/lib/pages/medical/prescriptions/prescription_details_page.dart +++ b/lib/pages/medical/prescriptions/prescription_details_page.dart @@ -53,7 +53,7 @@ class PrescriptionDetailsPage extends StatelessWidget { child: Texts( prescriptionReport.itemDescription.isNotEmpty ? prescriptionReport.itemDescription - : prescriptionReport.itemDescriptionN), + : prescriptionReport.itemDescriptionN ?? ''), ), ), ) @@ -70,7 +70,7 @@ class PrescriptionDetailsPage extends StatelessWidget { context, FadePage( page: PharmacyForPrescriptionsPage( - prescriptionReport: prescriptionReport), + itemID: prescriptionReport.itemID), ), ), child: Center( @@ -118,14 +118,19 @@ class PrescriptionDetailsPage extends StatelessWidget { height: 40, width: double.infinity, child: Center( - child: Texts(TranslationBase.of(context).route, fontSize: 14,))), + child: Texts( + TranslationBase.of(context).route, + fontSize: 14, + ))), Container( color: Colors.white, height: 40, width: double.infinity, child: Center( - child: - Texts(TranslationBase.of(context).frequency, fontSize: 14,))), + child: Texts( + TranslationBase.of(context).frequency, + fontSize: 14, + ))), Container( color: Colors.white, height: 40, @@ -133,14 +138,18 @@ class PrescriptionDetailsPage extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 4), child: Center( child: Texts( - "${TranslationBase.of(context).dailyDoses}", fontSize: 14,))), + "${TranslationBase.of(context).dailyDoses}", + fontSize: 14, + ))), Container( color: Colors.white, height: 40, width: double.infinity, child: Center( - child: - Texts(TranslationBase.of(context).duration, fontSize: 14,))), + child: Texts( + TranslationBase.of(context).duration, + fontSize: 14, + ))), ], ), TableRow( @@ -149,8 +158,8 @@ class PrescriptionDetailsPage extends StatelessWidget { color: Colors.white, height: 50, width: double.infinity, - child: - Center(child: Text(prescriptionReport.routeN))), + child: Center( + child: Text(prescriptionReport.routeN ?? ''))), Container( color: Colors.white, height: 50, diff --git a/lib/pages/medical/prescriptions/prescription_items_page.dart b/lib/pages/medical/prescriptions/prescription_items_page.dart index c6581493..e47b8ea7 100644 --- a/lib/pages/medical/prescriptions/prescription_items_page.dart +++ b/lib/pages/medical/prescriptions/prescription_items_page.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_repor import 'package:diplomaticquarterapp/core/viewModels/medical/prescriptions_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescription_details_inp.dart'; import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescription_details_page.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; @@ -24,7 +25,7 @@ class PrescriptionItemsPage extends StatelessWidget { //TODO @override Widget build(BuildContext context) { - ProjectViewModel projectViewModel = Provider.of(context); + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getPrescriptionReport(prescriptions: prescriptions), @@ -38,14 +39,14 @@ class PrescriptionItemsPage extends StatelessWidget { children: [ if (!prescriptions.isInOutPatient) ...List.generate( - model.prescriptionReportList.length, + model.prescriptionReportListINP.length, (index) => InkWell( onTap: () => Navigator.push( context, FadePage( - page: PrescriptionDetailsPage( + page: PrescriptionDetailsPageINP( prescriptionReport: - model.prescriptionReportList[index], + model.prescriptionReportListINP[index], ), ), ), @@ -68,7 +69,7 @@ class PrescriptionItemsPage extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(5)), child: Image.network( - model.prescriptionReportList[index] + model.prescriptionReportListINP[index] .imageSRCUrl, fit: BoxFit.cover, width: 60, @@ -83,13 +84,17 @@ class PrescriptionItemsPage extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: Center( child: Texts(model - .prescriptionReportList[index] + .prescriptionReportListINP[index] .itemDescription .isNotEmpty - ? model.prescriptionReportList[index] + ? model + .prescriptionReportListINP[index] .itemDescription - : model.prescriptionReportList[index] - .itemDescriptionN)), + : model + .prescriptionReportListINP[ + index] + .itemDescriptionN ?? + '')), )), Icon( Icons.arrow_forward_ios, @@ -163,7 +168,12 @@ class PrescriptionItemsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Texts(model.prescriptionReportEnhList[index] - .itemDescription), + .itemDescription.isNotEmpty + ? model.prescriptionReportEnhList[index] + .itemDescription + : model.prescriptionReportEnhList[index] + .itemDescriptionN ?? + ''), ], ), ), @@ -188,36 +198,37 @@ class PrescriptionItemsPage extends StatelessWidget { child: Column( children: [ Divider(), - if(projectViewModel.havePrivilege(13)) - Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - label: TranslationBase.of(context).sendCopy, - onTap: () { - showConfirmMessage(context,model); - }, - loading: model.state == ViewState.BusyLocal, - ), - ), + if (projectViewModel.havePrivilege(13)) Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - label: TranslationBase.of(context).resendOrder, - backgroundColor: Colors.green[800], - onTap: (){ - - Navigator.push( - context, - FadePage( - page: PrescriptionDeliveryAddressPage( - prescriptions: prescriptions, - prescriptionReportList: model.prescriptionReportList, - prescriptionReportEnhList: model.prescriptionReportEnhList, - ), + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + label: TranslationBase.of(context).sendCopy, + onTap: () { + showConfirmMessage(context, model); + }, + loading: model.state == ViewState.BusyLocal, + ), + ), + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + label: TranslationBase.of(context).resendOrder, + backgroundColor: Colors.green[800], + onTap: () { + Navigator.push( + context, + FadePage( + page: PrescriptionDeliveryAddressPage( + prescriptions: prescriptions, + prescriptionReportList: + model.prescriptionReportList, + prescriptionReportEnhList: + model.prescriptionReportEnhList, ), - ); - }, - )) + ), + ); + }, + )) ], ), ), @@ -236,6 +247,7 @@ class PrescriptionItemsPage extends StatelessWidget { patientID: prescriptions.patientID, clinicName: prescriptions.companyName, doctorName: prescriptions.doctorName, + doctorID: prescriptions.doctorID, mes: TranslationBase.of(context).sendSuc, projectID: prescriptions.projectID); }, diff --git a/lib/pages/medical/reports/monthly_reports.dart b/lib/pages/medical/reports/monthly_reports.dart index 4484bd5f..80f6ac76 100644 --- a/lib/pages/medical/reports/monthly_reports.dart +++ b/lib/pages/medical/reports/monthly_reports.dart @@ -19,15 +19,24 @@ class MonthlyReportsPage extends StatefulWidget { } class _MonthlyReportsPageState extends State { - bool isAgree = false; - bool isSummary = false; - String email = ""; + bool isAgree; + bool isSummary; + String email; final formKey = GlobalKey(); @override Widget build(BuildContext context) { - return BaseView( - builder: (_, model, w) => AppScaffold( + return BaseView(builder: (_, model, w) { + if (isSummary == null) { + isSummary = model.receiveHealthSummaryReport; + } + if (isAgree == null) { + isAgree = model.receiveHealthSummaryReport; + } + if (email == null) { + email = model?.user?.emailAddress ?? ""; + } + return AppScaffold( isShowAppBar: true, appBarTitle: TranslationBase.of(context).monthlyReports, body: SingleChildScrollView( @@ -41,15 +50,10 @@ class _MonthlyReportsPageState extends State { Container( padding: EdgeInsets.all(9), height: 55, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(8)), - shape: BoxShape.rectangle, - border: Border.all(color: Colors.grey)), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(8)), shape: BoxShape.rectangle, border: Border.all(color: Colors.grey)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Texts( TranslationBase.of(context).patientHealthSummaryReport, bold: true, @@ -62,12 +66,12 @@ class _MonthlyReportsPageState extends State { setState(() { isSummary = !isSummary; }); - if(!isSummary) { + if (!isSummary) { GifLoaderDialogUtils.showMyDialog(context); - await model.updatePatientHealthSummaryReport( - message: TranslationBase - .of(context) - .updateSuccessfully, isSummary: isSummary); + await model.updatePatientHealthSummaryReport(message: TranslationBase.of(context).updateSuccessfully, isSummary: isSummary); + model.receiveHealthSummaryReport = isSummary; + isAgree = isSummary; + model.user.emailAddress = ""; GifLoaderDialogUtils.hideDialog(context); } }, @@ -80,11 +84,11 @@ class _MonthlyReportsPageState extends State { ), Container( margin: EdgeInsets.all(8), - child: TextFields( + child: TextFields( fillColor: Colors.red, hintText: 'email@email.com', fontSize: 20, - initialValue: model.user.emailAddress, + initialValue: email, fontWeight: FontWeight.w600, onChanged: (text) { email = text; @@ -111,8 +115,7 @@ class _MonthlyReportsPageState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( - child: Texts(TranslationBase.of(context) - .toViewTheTermsAndConditions), + child: Texts(TranslationBase.of(context).toViewTheTermsAndConditions), ), InkWell( onTap: () { @@ -156,19 +159,15 @@ class _MonthlyReportsPageState extends State { child: SecondaryButton( textColor: Colors.white, label: TranslationBase.of(context).save, - disabled: (!isAgree || !isSummary ), + disabled: (!isAgree || !isSummary), onTap: () async { final form = formKey.currentState; if (form.validate()) { GifLoaderDialogUtils.showMyDialog(context); await model.updatePatientHealthSummaryReport( - message: TranslationBase - .of(context) - .updateSuccessfully, - isSummary: isSummary, - isUpdateEmail: true, - email: email.isNotEmpty ? email : model.user - .emailAddress); + message: TranslationBase.of(context).updateSuccessfully, isSummary: isSummary, isUpdateEmail: true, email: email.isNotEmpty ? email : model.user.emailAddress); + model.receiveHealthSummaryReport = isSummary; + model.user.emailAddress = email.isNotEmpty ? email : model.user.emailAddress; GifLoaderDialogUtils.hideDialog(context); } }, @@ -177,8 +176,7 @@ class _MonthlyReportsPageState extends State { Padding( padding: const EdgeInsets.all(5.0), child: Texts( - TranslationBase.of(context) - .instructionAgree, + TranslationBase.of(context).instructionAgree, fontWeight: FontWeight.normal, ), ), @@ -191,7 +189,7 @@ class _MonthlyReportsPageState extends State { ), ), ), - ), - ); + ); + }); } } diff --git a/lib/pages/medical/reports/report_list_widget.dart b/lib/pages/medical/reports/report_list_widget.dart index 72d0422b..922fb239 100644 --- a/lib/pages/medical/reports/report_list_widget.dart +++ b/lib/pages/medical/reports/report_list_widget.dart @@ -61,15 +61,13 @@ class ReportListWidget extends StatelessWidget { ), Texts(reportList[index].projectName), Texts(reportList[index].clinicDescription), - Texts(TranslationBase.of(context).invoiceNo + - ': ${reportList[index].invoiceNo}'), + Texts(TranslationBase.of(context).invoiceNo + ': ${reportList[index].invoiceNo}'), SizedBox(height: 12), ], ), reportList[index].status == 2 ? Container( - margin: - EdgeInsets.only(left: 15.0, right: 15.0), + margin: EdgeInsets.only(left: 15.0, right: 15.0), child: InkWell( onTap: () { showConfirmMessage(reportList[index]); @@ -78,7 +76,7 @@ class ReportListWidget extends StatelessWidget { child: Icon( Icons.email, color: Theme.of(context).primaryColor, - size: 35.0, + size: 30.0, ), ), ) @@ -123,8 +121,7 @@ class ReportListWidget extends StatelessWidget { report.setupId) .then((value) { GifLoaderDialogUtils.hideDialog(AppGlobal.context); - AppToast.showSuccessToast( - message: TranslationBase.of(AppGlobal.context).emailSentSuccessfully); + AppToast.showSuccessToast(message: TranslationBase.of(AppGlobal.context).emailSentSuccessfully); }).catchError((err) { GifLoaderDialogUtils.hideDialog(AppGlobal.context); print(err); diff --git a/lib/pages/medical/vital_sign/LineChartCurved.dart b/lib/pages/medical/vital_sign/LineChartCurved.dart index fe112767..e62a300a 100644 --- a/lib/pages/medical/vital_sign/LineChartCurved.dart +++ b/lib/pages/medical/vital_sign/LineChartCurved.dart @@ -27,7 +27,7 @@ class LineChartCurved extends StatelessWidget { getYaxix(); calculateMaxAndMin(); return AspectRatio( - aspectRatio: 1.1, + aspectRatio: 1.0, child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(18)), @@ -80,14 +80,6 @@ class LineChartCurved extends StatelessWidget { } getYaxix() { - // int indexess= (timeSeries.length*0.30).toInt(); - // for (int index = 0; index < timeSeries.length; index++) { - // int mIndex = indexess * index; - // if (mIndex < timeSeries.length) { - // yAxixs.add(timeSeries[mIndex].sales); - // } - // } - for (int index = 0; index < timeSeries.length; index++) { int mIndex = indexes * index; if (mIndex < timeSeries.length) { @@ -142,21 +134,8 @@ class LineChartCurved extends StatelessWidget { fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (timeSeries.length < 15) { - return '${value.toInt()}'; - } else { - if (value == minY) - return '${value.toInt()}'; - if (value == getMaxY()) - return '${value.toInt()}'; - //if (yAxixs.contains(value)) { - return '${value.toInt()}'; + interval:getMaxY() - getMinY() <=500?getMaxY() - getMinY() <=50?10:50:getMaxY() - getMinY() <=1000?100:getMaxY() - getMinY()>=10000?5000:200, - return ''; - } - return '${value.toInt()}'; - }, margin: 12, ), ), @@ -181,7 +160,7 @@ class LineChartCurved extends StatelessWidget { minX: minX, maxX: maxX, maxY: maxY, - minY: minY, + minY: 0, lineBarsData: getData(context), ); } diff --git a/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart b/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart index 2d95f08c..e656d60e 100644 --- a/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart +++ b/lib/pages/medical/vital_sign/LineChartCurvedBloodPressure.dart @@ -151,9 +151,8 @@ class LineChartCurvedBloodPressure extends StatelessWidget { fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - return '${value.toInt()}'; - }, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, + margin: 12, ), ), diff --git a/lib/pages/rateAppointment/rate_appointment_clinic.dart b/lib/pages/rateAppointment/rate_appointment_clinic.dart index bf0f4b4e..7fe38f1b 100644 --- a/lib/pages/rateAppointment/rate_appointment_clinic.dart +++ b/lib/pages/rateAppointment/rate_appointment_clinic.dart @@ -94,6 +94,11 @@ class _RateAppointmentClinicState extends State { height: 8, ), LargeAvatar( + url: + 'https://hmgwebservices.com/Images/Hospitals/' + + model.appointmentDetails.projectID + .toString() + + '.jpg', name: model.appointmentDetails.clinicName, width: 110, height: 110, @@ -146,19 +151,17 @@ class _RateAppointmentClinicState extends State { child: Container( key: ValueKey(rating), child: IconButton( - iconSize: 45.0, + //iconSize: 45.0, onPressed: () { setState(() { rating = index + 1; }); }, - color: rating >= (index + 1) - ? Color.fromRGBO(255, 186, 0, 1.0) - : Colors.grey[400], + iconSize: rating == (index + 1) ? 60 : 40, // Theme.of(context).hintColor, - icon: Icon(rating >= (index + 1) - ? EvaIcons.star - : EvaIcons.star)), + icon: Image.asset('assets/images/' + + (index + 1).toString() + + '.png')), ), ), ) @@ -208,8 +211,8 @@ class _RateAppointmentClinicState extends State { } }, label: TranslationBase.of(context).submit, - disabled: (model.state == ViewState.Busy || rating==0), - // loading: model.state == ViewState.BusyLocal, + disabled: (model.state == ViewState.Busy || rating == 0), + // loading: model.state == ViewState.BusyLocal, textColor: Theme.of(context).backgroundColor), ), SizedBox( @@ -225,7 +228,7 @@ class _RateAppointmentClinicState extends State { ); }, child: Texts( - TranslationBase.of(context).later, + TranslationBase.of(context).later, decoration: TextDecoration.underline, color: HexColor('#151DFE'), fontSize: 18, diff --git a/lib/pages/settings/general_setting.dart b/lib/pages/settings/general_setting.dart index fa9fdf28..bd07bfa0 100644 --- a/lib/pages/settings/general_setting.dart +++ b/lib/pages/settings/general_setting.dart @@ -9,6 +9,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:provider/provider.dart'; import 'package:screen/screen.dart'; @@ -27,10 +28,11 @@ class _GeneralSettings extends State bool location = false; var sharedPref = new AppSharedPreferences(); var permission = new PermissionService(); + LocationPermission locationPermission; var mediaQueryData; @override void initState() { - getValues(); + this.getValues(); super.initState(); } @@ -80,7 +82,6 @@ class _GeneralSettings extends State setState(() { accsibility = value; }); - //setAccisibility(value); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, @@ -199,6 +200,7 @@ class _GeneralSettings extends State setState(() { camera = value; }); + this.permission.openSettings(); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, @@ -215,9 +217,12 @@ class _GeneralSettings extends State Switch( value: location, onChanged: (value) { - setState(() { - location = value; - }); + if (value == true) { + Navigator.pop(context); + this.setLocationPermission(); + } else { + Geolocator.openLocationSettings(); + } }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, @@ -227,6 +232,23 @@ class _GeneralSettings extends State ])); } + setLocationPermission() async { + locationPermission = await Geolocator.checkPermission(); + if (locationPermission == LocationPermission.denied) { + locationPermission = await Geolocator.requestPermission(); + if (locationPermission != LocationPermission.denied) { + setState(() { + location = true; + }); + } else { + this.location = false; + } + } else { + Geolocator.openLocationSettings(); + this.location = true; + } + } + setTheme(value) async { switch (value) { case 0: @@ -277,9 +299,15 @@ class _GeneralSettings extends State vibration = permission.isVibrationEnabled() == null ? false : permission.isVibrationEnabled(); - accsibility = mediaQueryData.accessibleNavigation; - setTheme(blindValue); + // accsibility = mediaQueryData.accessibleNavigation; + //setTheme(blindValue); } + var camera = await this.permission.isCameraEnabled(); + var location = await this.permission.isLocationEnabled(); + setState(() { + this.camera = camera; + this.location = location; + }); } getTheme(value) async { diff --git a/lib/pages/settings/profile_setting.dart b/lib/pages/settings/profile_setting.dart index 833cdf2b..d877514c 100644 --- a/lib/pages/settings/profile_setting.dart +++ b/lib/pages/settings/profile_setting.dart @@ -44,7 +44,7 @@ class _ProfileSettings extends State child: model.user != null ? ListView(scrollDirection: Axis.vertical, children: [ Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.all(15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -74,7 +74,7 @@ class _ProfileSettings extends State padding: EdgeInsets.all(10), ), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Row( @@ -93,7 +93,7 @@ class _ProfileSettings extends State ], )), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Row( @@ -116,7 +116,7 @@ class _ProfileSettings extends State padding: EdgeInsets.all(10), ), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Row( @@ -136,7 +136,7 @@ class _ProfileSettings extends State ], )), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Row( @@ -160,7 +160,7 @@ class _ProfileSettings extends State padding: EdgeInsets.all(10), ), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Column( @@ -175,7 +175,7 @@ class _ProfileSettings extends State ], )), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Column( @@ -190,7 +190,7 @@ class _ProfileSettings extends State ], )), Container( - color: Theme.of(context).primaryColor, + color: Theme.of(context).textTheme.headline2.color, padding: EdgeInsets.only( top: 0, left: 10, right: 10, bottom: 0), child: Column( diff --git a/lib/pages/vaccine/my_vaccines_screen.dart b/lib/pages/vaccine/my_vaccines_screen.dart index fb723a1f..27ce8399 100644 --- a/lib/pages/vaccine/my_vaccines_screen.dart +++ b/lib/pages/vaccine/my_vaccines_screen.dart @@ -30,173 +30,190 @@ class _MyVaccinesState extends State { onModelReady: (model) => model.getVaccine(), builder: (BuildContext context, VaccineViewModel model, Widget child) => AppScaffold( - isShowAppBar: true, - appBarTitle: TranslationBase.of(context).myVaccines, - baseViewModel: model, - body: Container( - margin: EdgeInsets.only( - left: SizeConfig.screenWidth * 0.004, - right: SizeConfig.screenWidth * 0.004, - top: SizeConfig.screenWidth * 0.04, - ), - child: Column( - children: [ - RoundedContainer( - backgroundColor: Colors.white, - child: ExpansionTile( - title: Container( - height: 65.0, - child: Text('2018'), - ), - children: [ - Container( - child: ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: model.vaccineList == null - ? 0 - : model.vaccineList.length, - itemBuilder: (BuildContext context, int index) { - return Column( - children: [ - RoundedContainer( - child: Column( - children: [ - Row( + isShowAppBar: true, + baseViewModel: model, + appBarTitle: TranslationBase.of(context).myVaccines, + body: Container( + margin: EdgeInsets.only( + left: SizeConfig.screenWidth * 0.004, + right: SizeConfig.screenWidth * 0.004, + top: SizeConfig.screenWidth * 0.04, + ), + child: Column( + children: [ + RoundedContainer( + backgroundColor: Colors.white, + child: ExpansionTile( + title: Container( + height: 65.0, + child: Text('2018'), + ), + children: [ + Container( + child: ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: model.vaccineList == null + ? 0 + : model.vaccineList.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + RoundedContainer( + child: Column( children: [ - Expanded( - child: Column( - children: [ - Padding( - padding: EdgeInsets.symmetric( - horizontal: 20.0, - vertical: 20.0), - child: Image.network( - model.vaccineList[index] - .doctorImageURL, - height: SizeConfig + Row( + children: [ + Expanded( + child: Column( + children: [ + Padding( + padding: EdgeInsets + .symmetric( + horizontal: + 20.0, + vertical: 20.0), + child: Image.network( + model + .vaccineList[ + index] + .doctorImageURL, + height: SizeConfig .imageSizeMultiplier * - 23, - width: SizeConfig + 23, + width: SizeConfig .imageSizeMultiplier * - 20, - fit: BoxFit.fill, - ), + 20, + fit: BoxFit.fill, + ), + ), + ], ), - ], - ), - flex: 2, - ), - Expanded( - child: Container( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - model.vaccineList[index] + flex: 2, + ), + Expanded( + child: Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + model + .vaccineList[ + index] .doctorTitle + - model.vaccineList[index] - .doctorName, - style: TextStyle( - fontWeight: + model + .vaccineList[ + index] + .doctorName, + style: TextStyle( + fontWeight: FontWeight.w900, - fontSize: 16.6, - ), - ), - SizedBox(height: 7.0), - Text( - model.vaccineList[index] - .projectName, - style: TextStyle( - fontSize: 17.0, - letterSpacing: 0.5, - ), - ), - SizedBox(height: 7.0), - Text( - model.vaccineList[index] - .vaccineName, - style: TextStyle( - fontSize: 17.0, - ), - ), - SizedBox(height: 7.0), - Text( - 'Date Taken ' + - convertDateFormat(model - .vaccineList[index] - .invoiceDate), - style: TextStyle( - fontSize: 17.0), + fontSize: 16.6, + ), + ), + SizedBox(height: 7.0), + Text( + model + .vaccineList[ + index] + .projectName, + style: TextStyle( + fontSize: 17.0, + letterSpacing: 0.5, + ), + ), + SizedBox(height: 7.0), + Text( + model + .vaccineList[ + index] + .vaccineName, + style: TextStyle( + fontSize: 17.0, + ), + ), + SizedBox(height: 7.0), + Text( + 'Date Taken ' + + convertDateFormat(model + .vaccineList[ + index] + .invoiceDate), + style: TextStyle( + fontSize: 17.0), + ), + ], ), - ], + ), + flex: 5, ), - ), - flex: 5, + ], ), ], ), - ], - ), - ), - ], - ); - }), - ) - ], - ), - ), - // SpaceBetweenTexts(space: 165.0), - ], - ), - ), - bottomSheet: Container( - color: Theme.of(context).scaffoldBackgroundColor, - padding: EdgeInsets.all(12), - height: MediaQuery.of(context).size.height * 0.25, - width: double.infinity, - child: Column( - children: [ - Divider( - height: 2, - thickness: 1, - ), - SizedBox( - height: 6, - ), - Container( - width: double.infinity, - // height: 80.0, - child: Button( - disabled: true, - label: TranslationBase.of(context).checkVaccineAvailability, - backgroundColor: Color(0xff9EA3A4), - onTap: () => Navigator.push( - context, FadePage(page: MyVaccinesItemPage())), - ), + ), + ], + ); + }), + ) + ], + ), + ), + // SpaceBetweenTexts(space: 165.0), + ], ), - if (projectViewModel.havePrivilege(27)) - Container( - width: double.infinity, - // height: 80.0, - child: SecondaryButton( - label: TranslationBase.of(context).sendEmail, - color: Color(0xffF62426), - textColor: Colors.white, - disabled: model.vaccineList.length == 0, - loading: model.state == ViewState.BusyLocal, - onTap: () async { - model.sendEmail( - message: TranslationBase.of(context) - .emailSentSuccessfully); - }, + ), + bottomSheet: model.state == ViewState.Busy?Container(height: 0,): model.vaccineList.length > 0 + ? Container( + color: Theme.of(context).scaffoldBackgroundColor, + padding: EdgeInsets.all(12), + height: MediaQuery.of(context).size.height * 0.25, + width: double.infinity, + child: Column( + children: [ + Divider( + height: 2, + thickness: 1, + ), + SizedBox( + height: 6, ), - ), - ], + Container( + width: double.infinity, + // height: 80.0, + child: Button( + disabled: true, + label: TranslationBase.of(context) + .checkVaccineAvailability, + backgroundColor: Color(0xff9EA3A4), + onTap: () => Navigator.push( + context, FadePage(page: MyVaccinesItemPage())), + ), + ), + if (projectViewModel.havePrivilege(27)) + Container( + width: double.infinity, + // height: 80.0, + child: SecondaryButton( + label: TranslationBase.of(context).sendEmail, + color: Color(0xffF62426), + textColor: Colors.white, + disabled: model.vaccineList.length == 0, + loading: model.state == ViewState.BusyLocal, + onTap: () async { + model.sendEmail( + message: TranslationBase.of(context) + .emailSentSuccessfully); + }, + ), + ), + ], + ), + ) + : Container(height: 0,), ), - ), - ), ); } diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index a7d9f826..8296f3bd 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -321,7 +321,7 @@ class DoctorsListService extends BaseService { } Future insertAppointment(int docID, int clinicID, int projectID, - String selectedTime, String selectedDate, BuildContext context) async { + String selectedTime, String selectedDate, BuildContext context, [String procedureID]) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { @@ -341,6 +341,7 @@ class DoctorsListService extends BaseService { "StartTime": selectedTime, "SelectedTime": selectedTime, "EndTime": selectedTime, + "ProcedureID": procedureID, "InitialSlotDuration": 0, "StrAppointmentDate": selectedDate, "IsVirtual": false, @@ -1447,4 +1448,24 @@ class DoctorsListService extends BaseService { }, body: request); return Future.value(localRes); } + + Future sendCheckinNfcRequest( + int appointmentNo, String nfcCode,int projectId, BuildContext context) async { + Map request; + + Request req = appGlobal.getPublicRequest(); + request = { + "AppointmentNo":appointmentNo, + "NFC_Code": nfcCode, + "ProjectID": projectId, + }; + dynamic localRes; + await baseAppClient.post(SEND_CHECK_IN_NFC_REQUEST, + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } } diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart index 43fdc456..3ad128d4 100644 --- a/lib/services/authentication/auth_provider.dart +++ b/lib/services/authentication/auth_provider.dart @@ -117,8 +117,8 @@ class AuthProvider with ChangeNotifier { var imei = await sharedPref.getString(PUSH_TOKEN); // if (!request.) { newRequest.iMEI = imei; //imei!=null ? imei : ''; - newRequest.firstName = request.firstName + " " + request.lastName; - newRequest.firstNameN = request.firstNameN + " " + request.lastNameN; + newRequest.firstName = request.firstName??"" + " " + request.lastName??""; + newRequest.firstNameN = request.firstNameN??"" + " " + request.lastNameN??""; newRequest.lastNameN = request.lastNameN ?? ""; newRequest.outSA = request.outSA == 1 ? true : false; newRequest.biometricEnabled = false; diff --git a/lib/services/clinic_services/get_clinic_service.dart b/lib/services/clinic_services/get_clinic_service.dart index 99345030..2b2d933f 100644 --- a/lib/services/clinic_services/get_clinic_service.dart +++ b/lib/services/clinic_services/get_clinic_service.dart @@ -35,8 +35,7 @@ class ClinicListService extends BaseService { dynamic localRes; - await baseAppClient.post(GET_CLINICS_LIST_URL, - onSuccess: (response, statusCode) async { + await baseAppClient.post(GET_CLINICS_LIST_URL, onSuccess: (response, statusCode) async { localRes = response; }, onFailure: (String error, int statusCode) { throw error; @@ -54,7 +53,7 @@ class ClinicListService extends BaseService { "VersionID": req.VersionID, "Channel": req.Channel, "generalid": 'Cs2020@2016\$2958', - "PatientOutSA": 0, + "PatientOutSA": user.outSA, "TokenID": "", "IsActiveAppointment": true, "DeviceTypeID": req.DeviceTypeID, @@ -65,12 +64,11 @@ class ClinicListService extends BaseService { dynamic localRes; - await baseAppClient.post(GET_ACTIVE_APPOINTMENTS_LIST_URL, - onSuccess: (response, statusCode) async { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: request); + await baseAppClient.post(GET_ACTIVE_APPOINTMENTS_LIST_URL, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); return Future.value(localRes); } @@ -92,8 +90,7 @@ class ClinicListService extends BaseService { dynamic localRes; - await baseAppClient.post(GET_PROJECTS_LIST, - onSuccess: (response, statusCode) async { + await baseAppClient.post(GET_PROJECTS_LIST, onSuccess: (response, statusCode) async { localRes = response; }, onFailure: (String error, int statusCode) { throw error; @@ -101,15 +98,12 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future getChiefComplaintsList( - int clinicID, int projectID, BuildContext context, - {doctorId}) async { + Future getChiefComplaintsList(int clinicID, int projectID, BuildContext context, {doctorId}) async { //Utils.showProgressDialog(context); Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { - var data = AuthenticatedUser.fromJson( - await this.sharedPref.getObject(USER_PROFILE)); + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); authUser = data; } @@ -137,8 +131,7 @@ class ClinicListService extends BaseService { dynamic localRes; - await baseAppClient.post(GET_DOCTORS_LIST_URL, - onSuccess: (response, statusCode) async { + await baseAppClient.post(GET_DOCTORS_LIST_URL, onSuccess: (response, statusCode) async { localRes = response; }, onFailure: (String error, int statusCode) { throw error; @@ -146,19 +139,15 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future getChiefComplaintDoctorList( - int chiefComplaintID, int projectID, BuildContext context, - {doctorId}) async { + Future getChiefComplaintDoctorList(int chiefComplaintID, int projectID, BuildContext context, {doctorId}) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { - var data = AuthenticatedUser.fromJson( - await this.sharedPref.getObject(USER_PROFILE)); + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); authUser = data; } - if (await this.sharedPref.getDouble(USER_LAT) != null && - await this.sharedPref.getDouble(USER_LONG) != null) { + if (await this.sharedPref.getDouble(USER_LAT) != null && await this.sharedPref.getDouble(USER_LONG) != null) { lat = await this.sharedPref.getDouble(USER_LAT); long = await this.sharedPref.getDouble(USER_LONG); } @@ -179,13 +168,12 @@ class ClinicListService extends BaseService { "Latitude": lat.toString(), "Longitude": long.toString(), "DeviceTypeID": req.DeviceTypeID, - "IsPublicRequest" : true + "IsPublicRequest": true }; dynamic localRes; - await baseAppClient.post(GET_DENTAL_DOCTORS_LIST_URL, - onSuccess: (response, statusCode) async { + await baseAppClient.post(GET_DENTAL_DOCTORS_LIST_URL, onSuccess: (response, statusCode) async { localRes = response; }, onFailure: (String error, int statusCode) { throw error; diff --git a/lib/services/covid-drivethru/covid-drivethru.dart b/lib/services/covid-drivethru/covid-drivethru.dart index 3943a8b3..35e8fb2f 100644 --- a/lib/services/covid-drivethru/covid-drivethru.dart +++ b/lib/services/covid-drivethru/covid-drivethru.dart @@ -50,7 +50,43 @@ class CovidDriveThruService extends BaseService { return Future.value(localRes); } - Future getCovidPaymentInformation(BuildContext context, int projectID) async { + Future getCovidTestProceduresList(BuildContext context) async { + Map request; + + if (await this.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson( + await this.sharedPref.getObject(USER_PROFILE)); + authUser = data; + } + + var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + Request req = appGlobal.getPublicRequest(); + request = { + "LanguageID": languageID == 'ar' ? 1 : 2, + "IPAdress": "10.20.10.20", + "VersionID": req.VersionID, + "Channel": req.Channel, + "generalid": 'Cs2020@2016\$2958', + "PatientOutSA": authUser.outSA, + "TokenID": "", + "DeviceTypeID": req.DeviceTypeID, + "SessionID": "YckwoXhUmWBsnHKEKig", + "PatientID": authUser.patientID != null ? authUser.patientID : 0, + "License": true + }; + + dynamic localRes; + + await baseAppClient.post(GET_COVID_DRIVETHRU_PROCEDURES_LIST, + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + + Future getCovidPaymentInformation(BuildContext context, int projectID, String procedureID) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { @@ -65,6 +101,7 @@ class CovidDriveThruService extends BaseService { "LanguageID": languageID == 'ar' ? 1 : 2, "IPAdress": "10.20.10.20", "ProjectID": projectID, + "ProcedureId": procedureID, "VersionID": req.VersionID, "Channel": req.Channel, "generalid": 'Cs2020@2016\$2958', diff --git a/lib/services/family_files/family_files_provider.dart b/lib/services/family_files/family_files_provider.dart index 7a2dec81..8238a35b 100644 --- a/lib/services/family_files/family_files_provider.dart +++ b/lib/services/family_files/family_files_provider.dart @@ -259,7 +259,7 @@ class FamilyFilesProvider with ChangeNotifier { var currentUser = AuthenticatedUser.fromJson(await sharedPref.getObject(MAIN_USER)); //const request = new SwitchUserRequest(); - request['LogInTokenID'] = ''; + // request['LogInTokenID'] = ''; request['PatientOutSA'] = currentUser.outSA; //? 1 : 0; request['PatientMobileNumber'] = currentUser.mobileNumber; //['MobileNumber']; @@ -276,7 +276,7 @@ class FamilyFilesProvider with ChangeNotifier { AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); //const request = new SwitchUserRequest(); - request['LogInTokenID'] = ''; + // request['LogInTokenID'] = ''; request['PatientOutSA'] = currentUser.outSA; //? 1 : 0; request['PatientMobileNumber'] = switchUser.mobileNumber; //['MobileNumber']; diff --git a/lib/services/permission/permission_service.dart b/lib/services/permission/permission_service.dart index ea408ce2..d88ec599 100644 --- a/lib/services/permission/permission_service.dart +++ b/lib/services/permission/permission_service.dart @@ -10,9 +10,12 @@ import 'package:flutter/services.dart'; import 'package:localstorage/localstorage.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:vibration/vibration.dart'; +import 'package:geolocator/geolocator.dart' as geo; +// import 'package:open_settings/open_settings.dart'; + class PermissionService extends BaseService { final LocalStorage storage = new LocalStorage("permission"); - + geo.LocationPermission locationPermission; AppGlobal appGlobal = new AppGlobal(); setVibrationPermission(flag) async { @@ -20,23 +23,24 @@ class PermissionService extends BaseService { } isVibrationEnabled() { - return (storage.getItem('isVibration') ==null) || (storage.getItem('isVibration')) ==false ? false :true; + return (storage.getItem('isVibration') == null) || + (storage.getItem('isVibration')) == false + ? false + : true; } - vibrate(callback, context) async{ - if (callback == null) - return null; - if(isVibrationEnabled() ==true){ - if (await Vibration.hasVibrator()) { - Vibration.vibrate(duration: 100); - callback(); + vibrate(callback, context) async { + if (callback == null) return null; + if (isVibrationEnabled() == true) { + if (await Vibration.hasVibrator()) { + Vibration.vibrate(duration: 100); + callback(); } - }else{ + } else { callback(); } } - setTheme(flag) async { storage.setItem('isTheme', flag); } @@ -44,23 +48,36 @@ class PermissionService extends BaseService { isThemeEnabled() { return storage.getItem('isTheme'); } - cameraPermission() async{ - Map statuses = await [ - Permission.camera, - ].request(); - } - isCameraEnabled() async{ - print(await Permission.camera.status); - return await Permission.camera.status == PermissionStatus.granted ? true : false; + + cameraPermission() async { + Map statuses = await [ + Permission.camera, + ].request(); + } + + isCameraEnabled() async { + return await Permission.camera.isGranted; } - setCameraLocationPermission(context) async{ + + setCameraLocationPermission(context) async { Navigator.pop(context); openAppSettings(); } - isLocationEnabled() async{ - return await Permission.location.status == PermissionStatus.granted ? true : false; + + isLocationEnabled() async { + var permission = await geo.Geolocator.checkPermission(); + if (permission == geo.LocationPermission.denied) { + return false; + } else { + return true; + } } - openSettings() async{ + + openSettings() async { openAppSettings(); } + + openAccessbility() { + // OpenSettings.openAppSetting(); + } } diff --git a/lib/services/pharmacy_services/pharmacyAddress_service.dart b/lib/services/pharmacy_services/pharmacyAddress_service.dart index 592359ca..2909f18d 100644 --- a/lib/services/pharmacy_services/pharmacyAddress_service.dart +++ b/lib/services/pharmacy_services/pharmacyAddress_service.dart @@ -89,7 +89,7 @@ class PharmacyAddressService extends BaseService { Map body = Map(); body["customer"] = customerObject; - await baseAppClient.post("$url", onSuccess: (response, statusCode) async { + await baseAppClient.postPharmacy("$url", onSuccess: (response, statusCode) async { addresses.clear(); response['customers'][0]['addresses'].forEach((item) { addresses.add(Addresses.fromJson(item)); diff --git a/lib/splashPage.dart b/lib/splashPage.dart index df474862..5f4c667c 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -3,10 +3,12 @@ import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:firebase_analytics/observer.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; - +import 'package:flutter/services.dart'; +import 'analytics/google-analytics.dart'; import 'config/shared_pref_kay.dart'; import 'config/size_config.dart'; import 'core/service/AuthenticatedUserObject.dart'; diff --git a/lib/uitl/date_uitl.dart b/lib/uitl/date_uitl.dart index b3657143..e569fc56 100644 --- a/lib/uitl/date_uitl.dart +++ b/lib/uitl/date_uitl.dart @@ -66,9 +66,12 @@ class DateUtil { /// [dateString] String we want to convert static String checkDate(DateTime checkedTime) { DateTime currentTime = DateTime.now(); - if ((currentTime.year == checkedTime.year) && (currentTime.month == checkedTime.month) && (currentTime.day == checkedTime.day)) { + if ((currentTime.year == checkedTime.year) && + (currentTime.month == checkedTime.month) && + (currentTime.day == checkedTime.day)) { return "Today"; - } else if ((currentTime.year == checkedTime.year) && (currentTime.month == checkedTime.month)) { + } else if ((currentTime.year == checkedTime.year) && + (currentTime.month == checkedTime.month)) { if ((currentTime.day - checkedTime.day) == 1) { return "YESTERDAY"; } else if ((currentTime.day - checkedTime.day) == -1) { @@ -86,7 +89,13 @@ class DateUtil { static String getDateFormatted(String date) { DateTime dateObj = DateUtil.convertStringToDate(date); - return DateUtil.getWeekDay(dateObj.weekday) + ", " + dateObj.day.toString() + " " + DateUtil.getMonth(dateObj.month) + " " + dateObj.year.toString(); + return DateUtil.getWeekDay(dateObj.weekday) + + ", " + + dateObj.day.toString() + + " " + + DateUtil.getMonth(dateObj.month) + + " " + + dateObj.year.toString(); } /// get month by @@ -232,6 +241,25 @@ class DateUtil { } } + static getWeekDayEnglish(int weekDay) { + switch (weekDay) { + case 1: + return "Monday"; + case 2: + return "Tuesday"; + case 3: + return "Wednesday"; + case 4: + return "Thursday"; + case 5: + return "Friday"; + case 6: + return "Saturday "; + case 7: + return "Sunday"; + } + } + /// get data formatted like Apr 26,2020 /// [dateTime] convert DateTime to data formatted static String getMonthDayYearDateFormatted(DateTime dateTime) { @@ -240,7 +268,6 @@ class DateUtil { else return ""; } - /// get data formatted like Apr 26,2020 /// [dateTime] convert DateTime to data formatted Arabic static String getMonthDayYearDateFormattedAr(DateTime dateTime) { @@ -252,38 +279,65 @@ class DateUtil { /// get data formatted like Thursday, Apr 26,2020 /// [dateTime] convert DateTime to date formatted - static String getWeekDayMonthDayYearDateFormatted(DateTime dateTime, String lang) { + static String getWeekDayMonthDayYearDateFormatted( + DateTime dateTime, String lang) { + // print(dateTime); + // print(dateTime.weekday); + // print(dateTime.weekday.getDayOfWeekEnumValue.value); if (dateTime != null) return lang == 'en' - ? getDay(dateTime.weekday.getDayOfWeekEnumValue) + ", " + getMonth(dateTime.month) + " " + dateTime.day.toString() + " " + dateTime.year.toString() - : getWeekDayArabic(dateTime.weekday) + ", " + dateTime.day.toString() + " " + getMonthArabic(dateTime.month) + " " + dateTime.year.toString(); + ? getWeekDayEnglish(dateTime.weekday) + + ", " + + getMonth(dateTime.month) + + " " + + dateTime.day.toString() + + " " + + dateTime.year.toString() + : getWeekDayArabic(dateTime.weekday) + + ", " + + dateTime.day.toString() + + " " + + getMonthArabic(dateTime.month) + + " " + + dateTime.year.toString(); else return ""; } - static String getMonthDayYearLangDateFormatted(DateTime dateTime, String lang) { + static String getMonthDayYearLangDateFormatted( + DateTime dateTime, String lang) { if (dateTime != null) return lang == 'en' - ? getMonth(dateTime.month) + " " + dateTime.day.toString() + " " + dateTime.year.toString() - : dateTime.day.toString() + " " + getMonthArabic(dateTime.month) + " " + dateTime.year.toString(); + ? getMonth(dateTime.month) + + " " + + dateTime.day.toString() + + " " + + dateTime.year.toString() + : dateTime.day.toString() + + " " + + getMonthArabic(dateTime.month) + + " " + + dateTime.year.toString(); else return ""; } /// get data formatted like 26/4/2020 - static String getDayMonthYearLangDateFormatted(DateTime dateTime, String lang) { + static String getDayMonthYearLangDateFormatted( + DateTime dateTime, String lang) { if (dateTime != null) return lang == 'en' - ? dateTime.day.toString() + " " + getMonth(dateTime.month) + " " + dateTime.year.toString() - : dateTime.day.toString() + " " + getMonthArabic(dateTime.month) + " " + dateTime.year.toString(); - else - return ""; - } + ? dateTime.day.toString() + + " " + + getMonth(dateTime.month) + - /// get data formatted like Augast/2020 - static String getMonthYearLangDateFormatted(DateTime dateTime, String lang) { - if (dateTime != null) - return lang == 'en' ? getMonth(dateTime.month) + " " + dateTime.year.toString() : getMonthArabic(dateTime.month) + " " + dateTime.year.toString(); + " " + + dateTime.year.toString() + : dateTime.day.toString() + + " " + + getMonthArabic(dateTime.month) + + " " + + dateTime.year.toString(); else return ""; } @@ -292,7 +346,11 @@ class DateUtil { /// [dateTime] convert DateTime to data formatted static String getDayMonthYearDateFormatted(DateTime dateTime) { if (dateTime != null) - return dateTime.day.toString() + "/" + dateTime.month.toString() + "/" + dateTime.year.toString(); + return dateTime.day.toString() + + "/" + + dateTime.month.toString() + + "/" + + dateTime.year.toString(); else return ""; } @@ -301,7 +359,15 @@ class DateUtil { /// [dateTime] convert DateTime to data formatted static String getDayMonthYearHourMinuteDateFormatted(DateTime dateTime) { if (dateTime != null) - return dateTime.day.toString() + "/" + dateTime.month.toString() + "/" + dateTime.year.toString() + " " + dateTime.hour.toString() + ":" + dateTime.minute.toString(); + return dateTime.day.toString() + + "/" + + dateTime.month.toString() + + "/" + + dateTime.year.toString() + + " " + + dateTime.hour.toString() + + ":" + + dateTime.minute.toString(); else return ""; } @@ -325,12 +391,18 @@ class DateUtil { return ""; } - static String getFormattedDate(DateTime dateTime, String formattedString) { - return DateFormat(formattedString).format(dateTime); + static String getFormattedDate(DateTime dateTime, String formattedString){ + return DateFormat(formattedString) + .format(dateTime); } static convertISODateToJsonDate(String isoDate) { - return "/Date(" + DateFormat('mm-dd-yyy').parse(isoDate).millisecondsSinceEpoch.toString() + ")/"; + return "/Date(" + + DateFormat('mm-dd-yyy') + .parse(isoDate) + .millisecondsSinceEpoch + .toString() + + ")/"; } static String getDay(DayOfWeek dayOfWeek) { diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index cb7705dc..3992cba0 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -133,23 +133,18 @@ class TranslationBase { String get no => localizedValues['no'][locale.languageCode]; String get logintypeRadio => localizedValues['logintyperadio'][locale.languageCode]; - String get registerInfoFamily => localizedValues['register-info-family'][locale.languageCode]; String get registerNow => localizedValues['registernow'][locale.languageCode]; String get nationalID => localizedValues['nationalID'][locale.languageCode]; - String get medicalFileNumber => localizedValues['medical-file-number'][locale.languageCode]; - String get nationalIdNumber => localizedValues['national-id-number'][locale.languageCode]; String get idNo => localizedValues['national-id'][locale.languageCode]; String get fileNo => localizedValues['fileNo'][locale.languageCode]; - String get fileno => localizedValues['fileno'][locale.languageCode]; - String get forgotPassword => localizedValues['forgotFileNo'][locale.languageCode]; String get forgotFileNoTitle => localizedValues['forgotFileNoTitle'][locale.languageCode]; @@ -209,7 +204,6 @@ class TranslationBase { String get upcomingConfirm => localizedValues['upcoming-confirm'][locale.languageCode]; String get upcomingPaymentPending => localizedValues['upcoming-payment-pending'][locale.languageCode]; - String get upcomingConfirmMore => localizedValues['book-success-confirm-more-24-1-2'][locale.languageCode]; String get upcomingPaymentNow => localizedValues['upcoming-payment-now'][locale.languageCode]; @@ -256,10 +250,6 @@ class TranslationBase { String get refferal => localizedValues['refferal'][locale.languageCode]; - String get appointments => localizedValues['appointments'][locale.languageCode]; - - String get all2 => localizedValues['all2'][locale.languageCode]; - String get healthCare => localizedValues['healthCare'][locale.languageCode]; String get emergency => localizedValues['emergency'][locale.languageCode]; @@ -283,7 +273,6 @@ class TranslationBase { String get pharmaciesList => localizedValues['pharmaciesList'][locale.languageCode]; String get description => localizedValues['description'][locale.languageCode]; - String get howToUse => localizedValues['howToUse'][locale.languageCode]; String get price => localizedValues['price'][locale.languageCode]; @@ -303,23 +292,14 @@ class TranslationBase { String get appsetting => localizedValues['app-settings'][locale.languageCode]; String get rateApp => localizedValues['rate-app'][locale.languageCode]; - String get setReminder => localizedValues['set-reminder'][locale.languageCode]; - String get before => localizedValues['before'][locale.languageCode]; - String get minute => localizedValues['minute'][locale.languageCode]; - String get hour => localizedValues['hour'][locale.languageCode]; - String get reminderSuccess => localizedValues['reminderSuccess'][locale.languageCode]; - String get patientShareToDo => localizedValues['patientShareToDo'][locale.languageCode]; - String get patientTaxToDo => localizedValues['patientTaxToDo'][locale.languageCode]; - String get patientShareTotalToDo => localizedValues['patientShareTotalToDo'][locale.languageCode]; - String get paymentMethod => localizedValues['paymentMethod'][locale.languageCode]; String get moreVerification => localizedValues['more-verify'][locale.languageCode]; @@ -333,19 +313,12 @@ class TranslationBase { String get next => localizedValues['next'][locale.languageCode]; String get noNeedToWaitInLine => localizedValues['noNeedToWaitInLine'][locale.languageCode]; - String get useQRAppoAttend => localizedValues['useQRAppoAttend'][locale.languageCode]; - String get passQRAppoAttend => localizedValues['passQRAppoAttend'][locale.languageCode]; - String get sitWaitingQR => localizedValues['sitWaitingQR'][locale.languageCode]; - String get attendRegisterCode => localizedValues['attendRegisterCode'][locale.languageCode]; - String get scanQRHospital => localizedValues['scanQRHospital'][locale.languageCode]; - String get sendEmail => localizedValues['sendEmail'][locale.languageCode]; - String get close => localizedValues['close'][locale.languageCode]; String get booked => localizedValues['booked'][locale.languageCode]; @@ -739,11 +712,8 @@ class TranslationBase { String get depositorName => localizedValues['DepositorName'][locale.languageCode]; String get mobileNumber => localizedValues['MobileNumber'][locale.languageCode]; - String get phoneNumber => localizedValues['phone-number'][locale.languageCode]; - String get country => localizedValues['country'][locale.languageCode]; - String get ok => localizedValues['Ok'][locale.languageCode]; String get waterConsumedInWeek => localizedValues['WaterConsumedInWeek'][locale.languageCode]; @@ -807,19 +777,12 @@ class TranslationBase { String get scheduleTime => localizedValues['ScheduleTime'][locale.languageCode]; String get askDoctor => localizedValues['AskDoctor'][locale.languageCode]; - String get doctorResponses => localizedValues['DoctorResponses'][locale.languageCode]; - String get newDes => localizedValues['New'][locale.languageCode]; - String get all => localizedValues['All'][locale.languageCode]; - String get questionHere => localizedValues['QuestionHere'][locale.languageCode]; - String get viewDoctorResponses => localizedValues['ViewDoctorResponses'][locale.languageCode]; - String get serviceInformationButton => localizedValues['ServiceInformationButton'][locale.languageCode]; - String get serviceInformationTitle => localizedValues['ServiceInformationTitle'][locale.languageCode]; String get infoLab => localizedValues['info-lab'][locale.languageCode]; @@ -829,144 +792,85 @@ class TranslationBase { String get orders => localizedValues['orders'][locale.languageCode]; String get lakum => localizedValues['lakum'][locale.languageCode]; - String get wishlist => localizedValues['wishlist'][locale.languageCode]; - String get reviews => localizedValues['reviews'][locale.languageCode]; - String get myPrescriptions => localizedValues['myPrescriptions'][locale.languageCode]; - String get medicationRefill => localizedValues['medicationRefill'][locale.languageCode]; - String get pillReminder => localizedValues['pillReminder'][locale.languageCode]; - String get shippingAddresses => localizedValues['shippingAddresses'][locale.languageCode]; - String get reachUs => localizedValues['reachUs'][locale.languageCode]; - String get ourLocations => localizedValues['ourLocations'][locale.languageCode]; - String get edit => localizedValues['edit'][locale.languageCode]; - String get delete => localizedValues['delete'][locale.languageCode]; - String get addAddress => localizedValues['addAddress'][locale.languageCode]; - String get addNewAddress => localizedValues['addNewAddress'][locale.languageCode]; - String get order => localizedValues['order'][locale.languageCode]; - String get delivered => localizedValues['delivered'][locale.languageCode]; - String get processing => localizedValues['processing'][locale.languageCode]; - String get pending => localizedValues['pending'][locale.languageCode]; - String get cancelled => localizedValues['cancelled'][locale.languageCode]; - String get writeReview => localizedValues['writeReview'][locale.languageCode]; - String get shareReview => localizedValues['shareReview'][locale.languageCode]; - String get backMyAccount => localizedValues['backMyAccount'][locale.languageCode]; - String get reviewSuccessful => localizedValues['reviewSuccessful'][locale.languageCode]; - String get reviewShared => localizedValues['reviewShared'][locale.languageCode]; - String get reviewComment => localizedValues['reviewComment'][locale.languageCode]; - String get shippedMethod => localizedValues['shippedMethod'][locale.languageCode]; - String get orderDetail => localizedValues['orderDetail'][locale.languageCode]; + String get deliveryDriverTrack => + localizedValues['DeliveryDriverTrack'][locale.languageCode]; + String get deliveryLocation => + localizedValues['DeliveryLocation'][locale.languageCode]; String get deliveryDriverTrack => localizedValues['DeliveryDriverTrack'][locale.languageCode]; String get deliveryLocation => localizedValues['DeliveryLocation'][locale.languageCode]; String get driver => localizedValues['Driver'][locale.languageCode]; - String get subtotal => localizedValues['subtotal'][locale.languageCode]; - String get shipping => localizedValues['shipping'][locale.languageCode]; - String get shipBy => localizedValues['shipBy'][locale.languageCode]; - String get lakumPoints => localizedValues['lakumPoints'][locale.languageCode]; - String get use => localizedValues['use'][locale.languageCode]; - String get proceedPay => localizedValues['proceedPay'][locale.languageCode]; - String get vat => localizedValues['vat'][locale.languageCode]; - String get inclusiveVat => localizedValues['inclusiveVat'][locale.languageCode]; - String get items => localizedValues['items'][locale.languageCode]; - String get checkOut => localizedValues['checkOut'][locale.languageCode]; - String get total => localizedValues['total'][locale.languageCode]; - String get sar => localizedValues['sar'][locale.languageCode]; - String get payOnline => localizedValues['payOnline'][locale.languageCode]; - String get cancelOrder => localizedValues['cancelOrder'][locale.languageCode]; - String get confirmAddress => localizedValues['confirmAddress'][locale.languageCode]; - String get confirmLocation => localizedValues['confirmLocation'][locale.languageCode]; - String get confirmDeleteMsg => localizedValues['confirmDeleteMsg'][locale.languageCode]; - String get confirmDelete => localizedValues['confirmDelete'][locale.languageCode]; - String get confirmCancellation => localizedValues['confirmCancellation'][locale.languageCode]; - String get serviceInformation => localizedValues['ServiceInformation'][locale.languageCode]; - String get homeHealthCare => localizedValues['HomeHealthCare'][locale.languageCode]; - String get HHCNotAuthMsg => localizedValues['HHCNotAuthMsg'][locale.languageCode]; - String get homeHealthCareText => localizedValues['HomeHealthCareText'][locale.languageCode]; - String get loginRegister => localizedValues['LoginRegister'][locale.languageCode]; - String get orderLog => localizedValues['OrderLog'][locale.languageCode]; // String get infoLab => localizedValues['info-lab'][locale.languageCode]; // String get infoRadiology => String get orderNumber => localizedValues['orderNumber'][locale.languageCode]; - String get orderDate => localizedValues['orderDate'][locale.languageCode]; - String get itemsNo => localizedValues['itemsNo'][locale.languageCode]; - String get noOrder => localizedValues['noOrder'][locale.languageCode]; - String get noResult => localizedValues['noResult'][locale.languageCode]; String get offersAndPromotions => localizedValues['offersAndPromotions'][locale.languageCode]; - String get review => localizedValues['review'][locale.languageCode]; - String get deliveredOrder => localizedValues['deliveredOrder'][locale.languageCode]; - String get pendingOrder => localizedValues['pendingOrder'][locale.languageCode]; - String get processingOrder => localizedValues['processingOrder'][locale.languageCode]; - String get cancelledOrder => localizedValues['cancelledOrder'][locale.languageCode]; - String get compare => localizedValues['compare'][locale.languageCode]; - String get medicationsRefill => localizedValues['medicationsRefill'][locale.languageCode]; - String get myPrescription => localizedValues['myPrescription'][locale.languageCode]; - String get quantity => localizedValues['quantity'][locale.languageCode]; String get conditionsHMG => localizedValues['conditionsHMG'][locale.languageCode]; @@ -1989,6 +1893,24 @@ class TranslationBase { String get requesterRelationship => localizedValues["requesterRelationship"][locale.languageCode]; String get newReferral => localizedValues["newReferral"][locale.languageCode]; + String get searchForReferrals => + localizedValues["searchForReferrals"][locale.languageCode]; + String get covidSelectProcedure => + localizedValues["covid-select-procedure"][locale.languageCode]; + String get onlineConsultation => + localizedValues["online-consultation"][locale.languageCode]; + String get expectedWaiting => + localizedValues["expected-weiting"][locale.languageCode]; + String get erConsultFee => + localizedValues["er-consult-fee"][locale.languageCode]; + String get insuredPatient => + localizedValues["insured-patient"][locale.languageCode]; + String get iAcceptTerms => + localizedValues["i-accept-terms"][locale.languageCode]; + String get upComingPayOption => + localizedValues["upcoming-pay-options"][locale.languageCode]; + String get pleaseAcceptTerms => + localizedValues["please-accept-terms"][locale.languageCode]; String get searchForReferrals => localizedValues["searchForReferrals"][locale.languageCode]; } diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index d3e703aa..0f1422d2 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -141,7 +141,7 @@ class Utils { } String loginIDPattern(loginType) { - var length = loginType == 1 ? 10 : 7; + var length = loginType == 1 ? 10 : 6; return "([0-9]{" + length.toString() + "})"; } @@ -593,7 +593,8 @@ class Utils { )); medical.add(InkWell( - onTap: () => projectViewModel.havePrivilege(48) ? Navigator.push(context, FadePage(page: ActiveMedicationsPage())) : null, + onTap: () => + projectViewModel.havePrivilege(48) ? Navigator.push(context, FadePage(page: ActiveMedicationsPage())) : null, child: MedicalProfileItem( title: TranslationBase.of(context).myMedical, imagePath: 'active_medications.png', @@ -603,7 +604,24 @@ class Utils { )); medical.add(InkWell( - onTap: () => projectViewModel.havePrivilege(14) ? Navigator.push(context, FadePage(page: EyeMeasurementsPage())) : null, + onTap: () => projectViewModel.havePrivilege(6) + ? Navigator.push( + context, + FadePage( + page: DoctorHomePage(), + ), + ) + : null, + child: MedicalProfileItem( + title: TranslationBase.of(context).myDoctor, + imagePath: 'doctor_icon.png', + subTitle: TranslationBase.of(context).myDoctorSubtitle, + isEnable: projectViewModel.havePrivilege(6)), + )); + + medical.add(InkWell( + onTap: () => + projectViewModel.havePrivilege(14) ? Navigator.push(context, FadePage(page: EyeMeasurementsPage())) : null, child: MedicalProfileItem( title: TranslationBase.of(context).eye, imagePath: 'eye_measurement_icon.png', @@ -634,7 +652,8 @@ class Utils { )); medical.add(InkWell( - onTap: () => projectViewModel.havePrivilege(18) ? Navigator.push(context, FadePage(page: InsuranceApproval())) : null, + onTap: () => + projectViewModel.havePrivilege(18) ? Navigator.push(context, FadePage(page: InsuranceApproval())) : null, child: MedicalProfileItem( title: TranslationBase.of(context).insuranceApproval, imagePath: 'insurance_approvals_icon.png', @@ -664,7 +683,8 @@ class Utils { )); medical.add(InkWell( - onTap: () => projectViewModel.havePrivilege(20) ? Navigator.push(context, FadePage(page: HomeReportPage())) : null, + onTap: () => + projectViewModel.havePrivilege(20) ? Navigator.push(context, FadePage(page: HomeReportPage())) : null, child: MedicalProfileItem( title: TranslationBase.of(context).medical, imagePath: 'medical_reports_icon.png', @@ -674,7 +694,8 @@ class Utils { )); medical.add(InkWell( - onTap: () => projectViewModel.havePrivilege(19) ? Navigator.push(context, FadePage(page: MonthlyReportsPage())) : null, + onTap: () => + projectViewModel.havePrivilege(19) ? Navigator.push(context, FadePage(page: MonthlyReportsPage())) : null, child: MedicalProfileItem( title: TranslationBase.of(context).monthly, imagePath: 'monthly_reports_icon.png', @@ -684,7 +705,8 @@ class Utils { )); medical.add(InkWell( - onTap: () => projectViewModel.havePrivilege(16) ? Navigator.push(context, FadePage(page: PatientSickLeavePage())) : null, + onTap: () => + projectViewModel.havePrivilege(16) ? Navigator.push(context, FadePage(page: PatientSickLeavePage())) : null, child: MedicalProfileItem( title: TranslationBase.of(context).sick, imagePath: 'sick_leaves_icons.png', @@ -703,6 +725,7 @@ class Utils { ), )); + // TODO mosa check it medical.add(MedicalProfileItem( title: TranslationBase.of(context).patientCall, imagePath: 'medical_history_icon.png', @@ -808,6 +831,7 @@ Widget applyShadow({Color color = Colors.grey, double shadowOpacity = 0.5, doubl ); } + Future userData() async { var userData = AuthenticatedUser.fromJson(await AppSharedPreferences().getObject(MAIN_USER)); return userData; @@ -831,6 +855,25 @@ openAppStore({String androidPackageName, String iOSAppID}) async { launch("https://itunes.apple.com/kr/app/apple-store/$iOSAppID)"); } } + +String labelFrom({@required String className}){ + RegExp exp = RegExp(r'(?<=[a-z])[A-Z]'); + + String result = className.replaceAllMapped(exp, (m) { + var str = m.group(0); + if(str != null){ + return ('_' + str); + } + return ""; + }); + + if(result.isEmpty) + return className; + + result = result.replaceAll("_", " "); + return result; +} + /* userBoard.asMap().map((i, element) => MapEntry(i, Stack( GestureDetector(onTap: () { diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index f33e9dd5..76819533 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -21,7 +21,8 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; class BottomNavBar extends StatefulWidget { final ValueChanged changeIndex; final int index; - BottomNavBar({Key key, this.changeIndex, this.index}) : super(key: key); + final bool showHomeIcon; + BottomNavBar({Key key, this.changeIndex, this.index, this.showHomeIcon = false}) : super(key: key); @override _BottomNavBarState createState() => _BottomNavBarState(); @@ -33,7 +34,7 @@ class _BottomNavBarState extends State { var event = RobotProvider(); _changeIndex(int index) async { widget.changeIndex(index); - if (_index == 0) { + if (index == 0) { event.setValue({'isRobotVisible': 'true'}); } } @@ -72,27 +73,46 @@ class _BottomNavBarState extends State { ), if (widget.index == 0) Expanded( - child: SizedBox( - height: 50, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox(height: 22), - ], - ), - ), + child: (widget.showHomeIcon) + ? SizedBox( + child: BottomNavigationItem( + icon: Icons.home_outlined, + activeIcon: Icons.home_outlined, + changeIndex: _changeIndex, + index: widget.index, + currentIndex: 2, + name: TranslationBase.of(context).home, + ), + ) + : SizedBox( + height: 50, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 22), + ], + ), + ), ), if (widget.index != 0 && projectViewModel.havePrivilege(34)) BottomNavigationItem( - icon: EvaIcons.calendar, - activeIcon: EvaIcons.calendar, + icon: Icons.home_outlined, + activeIcon: Icons.home_outlined, changeIndex: _changeIndex, - index: _index, - currentIndex: 2, - name: TranslationBase.of(context).bookAppo, + index: widget.index, + currentIndex: 0, + name: TranslationBase.of(context).home, ), - if (widget.index == 0 && projectViewModel.havePrivilege(34)) + // BottomNavigationItem( + // icon: EvaIcons.calendar, + // activeIcon: EvaIcons.calendar, + // changeIndex: _changeIndex, + // index: _index, + // currentIndex: 2, + // name: TranslationBase.of(context).bookAppo, + // ), + if (/*widget.index == 0 && */projectViewModel.havePrivilege(34)) BottomNavigationItem( icon: EvaIcons.calendar, activeIcon: EvaIcons.calendar, diff --git a/lib/widgets/buttons/secondary_button.dart b/lib/widgets/buttons/secondary_button.dart index b5a4655a..8c4ba851 100644 --- a/lib/widgets/buttons/secondary_button.dart +++ b/lib/widgets/buttons/secondary_button.dart @@ -241,7 +241,7 @@ class _SecondaryButtonState extends State widget.label, style: TextStyle( color: widget.textColor, - fontSize: widget.small ? 12.0 : 15.0, + fontSize: widget.small ? 12.0 : 14.0, // fontWeight: FontWeight.w800, fontFamily: projectViewModel.isArabic ? 'Cairo' diff --git a/lib/widgets/charts/app_bar_chart.dart b/lib/widgets/charts/app_bar_chart.dart index 439d5ae9..818de33f 100644 --- a/lib/widgets/charts/app_bar_chart.dart +++ b/lib/widgets/charts/app_bar_chart.dart @@ -4,10 +4,12 @@ import 'package:charts_flutter/flutter.dart' as charts; class AppBarChart extends StatelessWidget { const AppBarChart({ Key key, + @required this.isArabic, @required this.seriesList, }) : super(key: key); final List seriesList; + final bool isArabic; @override Widget build(BuildContext context) { @@ -19,7 +21,7 @@ class AppBarChart extends StatelessWidget { // animate: animate, domainAxis: charts.OrdinalAxisSpec( renderSpec: charts.GridlineRendererSpec( - labelAnchor: charts.TickLabelAnchor.after, + labelAnchor: isArabic ? charts.TickLabelAnchor.before : charts.TickLabelAnchor.after, labelRotation: -30, labelOffsetFromAxisPx: 30, labelOffsetFromTickPx: 15, diff --git a/lib/widgets/data_display/medical/LabResult/laboratory_result_widget.dart b/lib/widgets/data_display/medical/LabResult/laboratory_result_widget.dart index 09306441..7b49559c 100644 --- a/lib/widgets/data_display/medical/LabResult/laboratory_result_widget.dart +++ b/lib/widgets/data_display/medical/LabResult/laboratory_result_widget.dart @@ -103,7 +103,7 @@ class _LaboratoryResultWidgetState extends State { color: Colors.white, ), Texts( - TranslationBase.of(context).sendCopy, + TranslationBase.of(context).sendEmail, color: Colors.white, ) ], diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index cc500955..848f0071 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -309,7 +309,7 @@ class _AppDrawerState extends State { padding: EdgeInsets.only(left: 5, right: 5), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ AppText(result.patientName, color: result.responseID == user.patientID ? Color(0xFF40ACC9) : Colors.black), - AppText(TranslationBase.of(context).fileno + ": " + result.patientID.toString(), color: result.responseID == user.patientID ? Color(0xFF40ACC9) : Colors.black), + AppText(TranslationBase.of(context).fileno + ": " + result.responseID.toString(), color: result.responseID == user.patientID ? Color(0xFF40ACC9) : Colors.black), ]))), ], ))) @@ -564,6 +564,7 @@ class _AppDrawerState extends State { if (mainUser["PatientID"] != result.list.patientID) { result.list.isFamily = true; } + // result.list.cRSVerificationStatus = result['CRSVerificationStatus']; this.sharedPref.setString(APP_LANGUAGE, currentLang); this.sharedPref.setObject(MAIN_USER, mainUser); diff --git a/lib/widgets/in_app_browser/InAppBrowser.dart b/lib/widgets/in_app_browser/InAppBrowser.dart index 63509b7c..946876a7 100644 --- a/lib/widgets/in_app_browser/InAppBrowser.dart +++ b/lib/widgets/in_app_browser/InAppBrowser.dart @@ -21,17 +21,17 @@ var _InAppBrowserOptions = InAppBrowserClassOptions( class MyInAppBrowser extends InAppBrowser { _PAYMENT_TYPE paymentType; - // static String SERVICE_URL = - // 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT - static String SERVICE_URL = - 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE + 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT - // static String PREAUTH_SERVICE_URL = - // 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort PreAuth Payment Gateway URL UAT + // static String SERVICE_URL = + // 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE static String PREAUTH_SERVICE_URL = - 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort PreAuth Payment Gateway URL Live Store + 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort PreAuth Payment Gateway URL UAT + + // static String PREAUTH_SERVICE_URL = + // 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort PreAuth Payment Gateway URL Live Store // static String PRESCRIPTION_PAYMENT_WITH_ORDERID = // 'https://uat.hmgwebservices.com/epharmacy/checkout/OpcCompleteRedirectionPaymentClientbyOrder?orderID='; diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart new file mode 100644 index 00000000..067c0c9a --- /dev/null +++ b/lib/widgets/nfc/nfc_reader_sheet.dart @@ -0,0 +1,196 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:nfc_in_flutter/nfc_in_flutter.dart'; + +void showNfcReader(BuildContext context, {Function onNcfScan}) { + showModalBottomSheet( + context: context, + enableDrag: false, + isDismissible: false, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(12), topRight: Radius.circular(12)), + ), + backgroundColor: Colors.white, + builder: (context) { + return NfcLayout( + onNcfScan: onNcfScan, + ); + }); +} + +class NfcLayout extends StatefulWidget { + Function onNcfScan; + + NfcLayout({this.onNcfScan}); + + @override + _NfcLayoutState createState() => _NfcLayoutState(); +} + +class _NfcLayoutState extends State { + StreamSubscription _stream; + bool _reading = false; + Widget mainWidget; + String nfcId; + + @override + void initState() { + super.initState(); + + setState(() { + // _reading = true; + // Start reading using NFC.readNDEF() + _stream = NFC + .readNDEF( + once: false, + throwOnUserCancel: false, + readerMode: NFCDispatchReaderMode()) + .listen((NDEFMessage message) { + setState(() { + _reading = true; + mainWidget = doneNfc(); + }); + Future.delayed(const Duration(milliseconds: 500), () { + _stream?.cancel(); + widget.onNcfScan(nfcId); + Navigator.pop(context); + }); + print("read NDEF id: ${message.id}"); + // widget.onNcfScan(message.id); + nfcId = message.id; + }, onError: (e) { + // Check error handling guide below + }); + }); + } + + @override + Widget build(BuildContext context) { + (mainWidget == null && !_reading) + ? mainWidget = scanNfc() + : mainWidget = doneNfc(); + return AnimatedSwitcher( + duration: Duration(milliseconds: 500), child: mainWidget); + } + + Widget scanNfc() { + return Container( + key: ValueKey(1), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 30, + ), + Text( + "Ready To Scan", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox( + height: 30, + ), + Image.asset( + "assets/images/nfc/ic_nfc.png", + height: MediaQuery.of(context).size.width / 3, + ), + SizedBox( + height: 30, + ), + Text( + "Approach an NFC Tag", + style: TextStyle( + fontSize: 18, + ), + ), + SizedBox( + height: 30, + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width / 1.2, + height: 45.0, + buttonColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + child: RaisedButton( + onPressed: () { + _stream?.cancel(); + Navigator.pop(context); + }, + child: Text("CANCEL"), + ), + ), + SizedBox( + height: 30, + ), + ], + ), + ); + } + + Widget doneNfc() { + return Container( + key: ValueKey(2), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 30, + ), + Text( + "Successfully Scanned", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox( + height: 30, + ), + Image.asset( + "assets/images/nfc/ic_done.png", + height: MediaQuery.of(context).size.width / 3, + ), + SizedBox( + height: 30, + ), + Text( + "Approach an NFC Tag", + style: TextStyle( + fontSize: 18, + ), + ), + SizedBox( + height: 30, + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width / 1.2, + height: 45.0, + buttonColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + child: RaisedButton( + // onPressed: () { + // _stream?.cancel(); + // widget.onNcfScan(nfcId); + // Navigator.pop(context); + // }, + onPressed: null, + + child: Text("DONE"), + ), + ), + SizedBox( + height: 30, + ), + ], + ), + ); + } +} diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index a7f36b3f..6066ed5e 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -129,6 +129,7 @@ class AppScaffold extends StatelessWidget { ) : buildBodyWidget(context), ), + floatingActionButton: floatingActionButton, ); } @@ -271,6 +272,15 @@ class _RobotIcon extends State { }); } } + if (p['isRobotVisible'] == 'false') { + if (this.mounted) { + setState(() { + if (IS_VOICE_COMMAND_CLOSED == true) { + this.isAnimation = false; + } + }); + } + } }); super.initState(); diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index f881fb29..195b479b 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -206,6 +206,7 @@ class _FloatingSearchButton extends State with TickerProvi if (this.mounted) { controller.reverse(); IS_VOICE_COMMAND_CLOSED = true; + event.setValue({'isRobotVisible': 'false'}); } }); }, diff --git a/lib/widgets/others/not_auh_page.dart b/lib/widgets/others/not_auh_page.dart index d247c9f5..9bef623b 100644 --- a/lib/widgets/others/not_auh_page.dart +++ b/lib/widgets/others/not_auh_page.dart @@ -71,6 +71,34 @@ class _NotAutPageState extends State { widget.description, style: TextStyle(fontSize: 14, fontFamily: "Poppins", fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.56, height: 21 / 14), ), + SizedBox( + height: 14, + ), + if (!projectViewModel.isInternetConnection) + Center( + child: SizedBox( + height: MediaQuery.of(context).size.height * 0.55, + width: MediaQuery.of(context).size.width * 0.50, + child: Image.asset(projectViewModel.isArabic ? 'assets/images/Wifi-AR.png' : 'assets/images/wifi-EN.png'), + ), + ), + if (projectViewModel.isInternetConnection && widget.imagesInfo != null) + CarouselSlider( + items: widget.imagesInfo.map((image) { + return Builder( + builder: (BuildContext context) { + return SizedBox( + width: MediaQuery.of(context).size.width * 0.50, + child: image.isAsset ? Image.asset(projectViewModel.isArabic ? image.imageAr : image.imageEn) : Image.network(projectViewModel.isArabic ? image.imageAr : image.imageEn)); + }, + ); + }).toList(), + options: CarouselOptions( + height: MediaQuery.of(context).size.height * 0.55, + autoPlay: widget.imagesInfo.length > 1, + viewportFraction: 1.0, + ), + ), ], ), ), diff --git a/lib/widgets/typewriter/typewiter.dart b/lib/widgets/typewriter/typewiter.dart index a86cc9f0..5354df38 100644 --- a/lib/widgets/typewriter/typewiter.dart +++ b/lib/widgets/typewriter/typewiter.dart @@ -1,3 +1,5 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:flutter/material.dart'; @@ -14,6 +16,7 @@ class _TyperState extends State Animation _characterCount; AnimationController _controller; int _stringIndex; + var event = RobotProvider(); @override void initState() { _controller = new AnimationController( diff --git a/pubspec.yaml b/pubspec.yaml index 68ee1b26..776e48c7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: # Localizations flutter_localizations: sdk: flutter - intl: ^0.16.1 + intl: ^0.16.0 # web view webview_flutter: ^0.3.24 # http client @@ -52,6 +52,7 @@ dependencies: shared_preferences: ^0.5.8 flutter_flexible_toast: ^0.1.4 firebase_messaging: ^7.0.3 + firebase_analytics: ^6.3.0 cloud_firestore: ^0.14.3 android_intent: ^0.3.7+7 # Progress bar @@ -162,7 +163,7 @@ dependencies: # recase: ^3.0.0 wakelock: ^0.1.4 after_layout: ^1.0.7 - twilio_programmable_video: ^0.5.0+3 + twilio_programmable_video: ^0.6.2 cached_network_image: ^2.4.1 flutter_tts: path: flutter_tts-voice_enhancement @@ -171,12 +172,13 @@ dependencies: wifi: ^0.1.5 vibration: ^1.7.3 + nfc_in_flutter: ^2.0.5 speech_to_text: path: speech_to_text badges: ^1.1.4 - +# open_settings: ^2.0.1 # Dep by Zohaib shimmer: ^1.1.2 carousel_slider: ^2.3.1 @@ -218,10 +220,14 @@ flutter: - assets/images/svg/ - assets/tracker/ - assets/images/AlHabibMedicalService/ + - assets/images/AlHabibMedicalService/health_calculator/ - assets/images/pharmacy_module/ - assets/images/gif/ - assets/images/pharmacy_module/payment/ - assets/images/pharmacy_module/lakum/ + - assets/images/nfc/ + - assets/payment_options/ + - assets/images/new/ - assets/images/new/bottom_nav/ - assets/images/new/services/ diff --git a/speech_to_text/android/build.gradle b/speech_to_text/android/build.gradle index 6b23b300..cc06ea57 100644 --- a/speech_to_text/android/build.gradle +++ b/speech_to_text/android/build.gradle @@ -31,7 +31,7 @@ android { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { - minSdkVersion 21 + minSdkVersion 18 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } lintOptions { diff --git a/speech_to_text/android/gradle/local.properties b/speech_to_text/android/gradle/local.properties index 71a0a2e4..b85628e7 100644 --- a/speech_to_text/android/gradle/local.properties +++ b/speech_to_text/android/gradle/local.properties @@ -1,3 +1,2 @@ sdk.dir=/Users/stephen.owens/Library/Android/sdk -flutter.sdk=/Users/stephen.owens/Documents/dev/flutter/sdk/flutter -org.gradle.jvmargs=-Xmx1536m -Duser.country=US -Duser.language=en \ No newline at end of file +flutter.sdk=/Users/stephen.owens/Documents/dev/flutter/sdk/flutter \ No newline at end of file diff --git a/speech_to_text/example/android/app/build.gradle b/speech_to_text/example/android/app/build.gradle index 8b616f29..104069d3 100644 --- a/speech_to_text/example/android/app/build.gradle +++ b/speech_to_text/example/android/app/build.gradle @@ -39,7 +39,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.csdcorp.speech_to_text_example" - minSdkVersion 21 + minSdkVersion 18 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/speech_to_text_/.github/workflows/master.yml b/speech_to_text_/.github/workflows/master.yml new file mode 100644 index 00000000..4d4cff1c --- /dev/null +++ b/speech_to_text_/.github/workflows/master.yml @@ -0,0 +1,19 @@ +name: build + +on: + push: + branches: + - master + +jobs: + test: + name: Test on Ubuntu + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: subosito/flutter-action@v1.3.2 + with: + flutter-version: '1.17.1' + channel: 'stable' + - run: flutter pub get + - run: flutter test diff --git a/speech_to_text_/.gitignore b/speech_to_text_/.gitignore new file mode 100644 index 00000000..8969cbcd --- /dev/null +++ b/speech_to_text_/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ + +build/ +coverage/ +example/.flutter-plugins-dependencies +**/ios/Flutter/flutter_export_environment.sh +android/.idea/ diff --git a/speech_to_text_/.metadata b/speech_to_text_/.metadata new file mode 100644 index 00000000..1940d996 --- /dev/null +++ b/speech_to_text_/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f + channel: stable + +project_type: plugin diff --git a/speech_to_text_/CHANGELOG.md b/speech_to_text_/CHANGELOG.md new file mode 100644 index 00000000..477e110c --- /dev/null +++ b/speech_to_text_/CHANGELOG.md @@ -0,0 +1,166 @@ +# Changelog + +## 2.3.0 + +### New + * new parameter `onDevice` on the `listen` method enforces on device recognition for sensitive content + * onSoundLevelChange now supported on iOS + * added compile troubleshooting help to README.md + * `SpeechToTextProvider` is an alternate and simpler way to interact with the `SpeechToText` plugin. + * new `provider_example.dart` example for usage of `SpeechToTextProvider`. +### Fix + * on iOS handles some conflicts with other applications better to keep speech working after calls for example + + +## 2.2.0 + +### New + * improved error handling and logging in the iOS implementation + * added general guides for iOS to the README + * moved stress testing out of the main example + * iOS now defaults to using the speaker rather than the receiver for start /stop sounds when no headphones +### Fix + * iOS now properly deactivates the audio session when no longer listening + * start and stop sounds on iOS should be more reliable when available + +## 2.1.0 +### Breaking + * `listenFor` now calls `stop` rather than `cancel` as this seems like more useful behaviour + +### Fix + * Android no longer stops or cancels the speech recognizer if it has already been shutdown by a + timeout or other platform behaviour. + * Android no longer tries to restart the listener when it is already active + * Now properly notifies errors that happen after listening stops due to platform callback rather than + client request. See https://github.com/csdcorp/speech_to_text/issues/51 + +## 2.0.1 +### Fix + * Resolves an issue with the Android implementation not handling permission requests properly on apps + that didn't use the 1.12.x plugin APIs for registration. The permission dialog would not appear and + permission was denied. + + +## 2.0.0 + +### Breaking + + * Upgraded to New Swift 1.12 plugin structure, may work with older Flutter version but not guaranteed + +### New + + * the plugin now requests both speech and microphone permission on initialize on iOS + * added `debugLogging` parameter to the `initialize` method to control native logging + +### Fix + + * The Android implementation now blocks duplicate results notifications. It appears that at least on some + Android versions the final results notification onResults is notified twice when Android automatically + terminates the session due to a pause time. The de-duplication looks for successive notifications + with < 100 ms between them and blocks the second. If you miss any onResult notifications please post + an issue. + +## 1.1.0 + +### New + + * error_timeout has been separated into error_network_timeout and error_speech_timeout + +## 1.0.0 + +### New + * hasPermission to check for the current permission without bringing up the system dialog + * `listen` has a new optional `cancelOnError` parameter to support automatically canceling + a listening session on a permanent error. + * `listen` has a new optional `partialResults` parameter that controls whether the callback + receives partial or only final results. + +## 0.8.0 + +### New + + * speech recognizer now exposes multiple possible transcriptions for each recognized speech + * alternates list on SpeechRecognitionResult exposes alternate transcriptions of voice + * confidence on SpeechRecognitionResult gives an estimate of confidence in the transcription + * isConfident on SpeechRecognitionResult supports testing confidence + * hasConfidenceRating on SpeechRecognitionResult indicates if confidence was provided from the device + * new SpeechRecognitionWords class gives details on per transcription words and confidence + +### Fix + + * speechRecognizer availabilityDidChange was crashing if invoked due to an invalid parameter type + * Added iOS platform 10 to example Podfile to resolve compilation warnings + +## 0.7.2 + +### Breaking + + * Upgrade Swift to version 5 to match Flutter. Projects using this plugin must now switch to 5. + +## 0.7.1 + +### Fix + + * Upgrade Kotlin to 1.3.5 to match the Flutter 1.12 version + * Upgrade Gradle build to 3.5.0 to match the Flutter 1.12 version + * Android version of the plugin was repeating the system default locale in the `locales` list + +## 0.7.0 + +### New + + * locales method returns the list of available languages for speech + * new optional localeId parameter on listen method supports choosing the comprehension language separately from the current system locale. + +### Breaking + + * `cancel` and `stop` are now async + +## 0.6.3 + +### Fix + + * request permission fix on Android to ensure it doesn't conflict with other requests + +## 0.6.2 + +### Fix + + * channel invoke wasn't being done on the main thread in iOS + +## 0.6.1 + +### Fix + + * listening sound was failing due to timing, now uses play and record mode on iOS. + + ## 0.6.0 +### Breaking + + * The filenames for the optional sounds for iOS have changed. + +### New + + * Added an optional listenFor parameter to set a max duration to listen for speech and then automatically cancel. + +### Fix + + * Was failing to play sounds because of record mode. Now plays sounds before going into record mode and after coming out. + * Status listener was being ignored, now properly notifies on status changes. + +## 0.5.1 + * Fixes a problem where the recognizer left the AVAudioSession in record mode which meant that subsequent sounds couldn't be played. + +## 0.5.0 +Initial draft with limited functionality, supports: + * initializing speech recognition + * asking the user for permission if required + * listening for recognized speech + * canceling the current recognition session + * stopping the current recognition session +* Android and iOS 10+ support + +Missing: + * some error handling + * testing across multiple OS versions + * and more, to be discovered... diff --git a/speech_to_text_/LICENSE b/speech_to_text_/LICENSE new file mode 100644 index 00000000..7c3991c8 --- /dev/null +++ b/speech_to_text_/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Corner Software Development Corp. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/speech_to_text_/README.md b/speech_to_text_/README.md new file mode 100644 index 00000000..af726f0e --- /dev/null +++ b/speech_to_text_/README.md @@ -0,0 +1,150 @@ +# speech_to_text + +[![pub package](https://img.shields.io/badge/pub-v2.3.0-blue)](https://pub.dartlang.org/packages/speech_to_text) [![build status](https://github.com/csdcorp/speech_to_text/workflows/build/badge.svg)](https://github.com/csdcorp/speech_to_text/actions?query=workflow%3Abuild) + +A library that exposes device specific speech recognition capability. + +This plugin contains a set of classes that make it easy to use the speech recognition +capabilities of the mobile device in Flutter. It supports both Android and iOS. The +target use cases for this library are commands and short phrases, not continuous spoken +conversion or always on listening. + +## Recent Updates + +The 2.3.0 version adds `SpeechToTextProvider` as a simpler way to interact with the plugin. Checkout +the new `provider_example.dart` for intended usage. + +The 2.2.0 version improves audio session handling and start / stop sound playback on iOS. + +*Note*: Feedback from any test devices is welcome. + +## Using + +To recognize text from the microphone import the package and call the plugin, like so: + +```dart +import 'package:speech_to_text/speech_to_text.dart' as stt; + + stt.SpeechToText speech = stt.SpeechToText(); + bool available = await speech.initialize( onStatus: statusListener, onError: errorListener ); + if ( available ) { + speech.listen( onResult: resultListener ); + } + else { + print("The user has denied the use of speech recognition."); + } + // some time later... + speech.stop() +``` + +### Initialize once +The `initialize` method only needs to be called once per application session. After that `listen`, +`start`, `stop`, and `cancel` can be used to interact with the plugin. Subsequent calls to `initialize` +are ignored which is safe but does mean that the `onStatus` and `onError` callbacks cannot be reset after +the first call to `initialize`. For that reason there should be only one instance of the plugin per +application. The `SpeechToTextProvider` is one way to create a single instance and easily reuse it in +multiple widgets. + +## Permissions + +Applications using this plugin require user permissions. +### iOS + +Add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: + +* `NSSpeechRecognitionUsageDescription` - describe why your app uses speech recognition. This is called _Privacy - Speech Recognition Usage Description_ in the visual editor. +* `NSMicrophoneUsageDescription` - describe why your app needs access to the microphone. This is called _Privacy - Microphone Usage Description_ in the visual editor. + +### Android + +Add the record audio permission to your _AndroidManifest.xml_ file, located in `/android/app/src/main/AndroidManifest.xml`. + +* `android.permission.RECORD_AUDIO` - this permission is required for microphone access. +* `android.permission.INTERNET` - this permission is required because speech recognition may use remote services. + +## Adding Sounds for iOS (optional) + +Android automatically plays system sounds when speech listening starts or stops but iOS does not. This plugin supports playing sounds to indicate listening status on iOS if sound files are available as assets in the application. To enable sounds in an application using this plugin add the sound files to the project and reference them in the assets section of the application `pubspec.yaml`. The location and filenames of the sound files must exactly match what +is shown below or they will not be found. The example application for the plugin shows the usage. *Note* These files should be very short as they delay +the start / end of the speech recognizer until the sound playback is complete. +```yaml + assets: + - assets/sounds/speech_to_text_listening.m4r + - assets/sounds/speech_to_text_cancel.m4r + - assets/sounds/speech_to_text_stop.m4r +``` +* `speech_to_text_listening.m4r` - played when the listen method is called. +* `speech_to_text_cancel.m4r` - played when the cancel method is called. +* `speech_to_text_stop.m4r` - played when the stop method is called. + +## Troubleshooting + +### SDK version error trying to compile for Android +``` +Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [:speech_to_text] +``` +The speech_to_text plugin requires at least Android SDK 21 because some of the speech functions in Android +were only introduced in that version. To fix this error you need to change the `build.gradle` entry to reflect +this version. Here's what the relevant part of that file looked like as of this writing: +``` + defaultConfig { + applicationId "com.example.app" + minSdkVersion 21 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } +``` + +### Incorrect Swift version trying to compile for iOS +``` +/Users/markvandergon/flutter/.pub-cache/hosted/pub.dartlang.org/speech_to_text-1.1.0/ios/Classes/SwiftSpeechToTextPlugin.swift:224:44: error: value of type 'SwiftSpeechToTextPlugin' has no member 'AVAudioSession' + rememberedAudioCategory = self.AVAudioSession.Category + ~~~~ ^~~~~~~~~~~~~~ + /Users/markvandergon/flutter/.pub-cache/hosted/pub.dartlang.org/speech_to_text-1.1.0/ios/Classes/SwiftSpeechToTextPlugin.swift:227:63: error: type 'Int' has no member 'notifyOthersOnDeactivation' + try self.audioSession.setActive(true, withFlags: .notifyOthersOnDeactivation) +``` +This happens when the Swift language version is not set correctly. See this thread for help https://github.com/csdcorp/speech_to_text/issues/45. + +### Swift not supported trying to compile for iOS +``` +`speech_to_text` does not specify a Swift version and none of the targets (`Runner`) integrating it have the `SWIFT_VERSION` attribute set. +``` +This usually happens for older projects that only support Objective-C. See this thread for help https://github.com/csdcorp/speech_to_text/issues/88. + +### Not working on a particular Android device +The symptom for this issue is that the `initialize` method will always fail. If you turn on debug logging +using the `debugLogging: true` flag on the `initialize` method you'll see `'Speech recognition unavailable'` +in the Android log. There's a lengthy issue discussion here https://github.com/csdcorp/speech_to_text/issues/36 +about this. The issue seems to be that the recognizer is not always automatically enabled on the device. Two +key things helped resolve the issue in this case at least. + +#### First +1. Go to Google Play +2. Search for 'Google' +3. You should find this app: https://play.google.com/store/apps/details?id=com.google.android.googlequicksearchbox +If 'Disabled' enable it + +This is the SO post that helped: https://stackoverflow.com/questions/28769320/how-to-check-wether-speech-recognition-is-available-or-not + +#### Second +Ensure the app has the required permissions. The symptom for this that you get a permanent error notification + 'error_audio_error` when starting a listen session. Here's a Stack Overflow post that addresses that + https://stackoverflow.com/questions/46376193/android-speechrecognizer-audio-recording-error + Here's the important excerpt: + >You should go to system setting, Apps, Google app, then enable its permission of microphone. + +### iOS recognition guidelines +Apple has quite a good guide on the user experience for using speech, the original is here +https://developer.apple.com/documentation/speech/sfspeechrecognizer This is the section that I think is particularly relevant: + +>#### Create a Great User Experience for Speech Recognition +>Here are some tips to consider when adding speech recognition support to your app. + +>**Be prepared to handle failures caused by speech recognition limits.** Because speech recognition is a network-based service, limits are enforced so that the service can remain freely available to all apps. Individual devices may be limited in the number of recognitions that can be performed per day, and each app may be throttled globally based on the number of requests it makes per day. If a recognition request fails quickly (within a second or two of starting), check to see if the recognition service became unavailable. If it is, you may want to ask users to try again later. + +>**Plan for a one-minute limit on audio duration.** Speech recognition places a relatively high burden on battery life and network usage. To minimize this burden, the framework stops speech recognition tasks that last longer than one minute. This limit is similar to the one for keyboard-related dictation. +Remind the user when your app is recording. For example, display a visual indicator and play sounds at the beginning and end of speech recognition to help users understand that they're being actively recorded. You can also display speech as it is being recognized so that users understand what your app is doing and see any mistakes made during the recognition process. + +>**Do not perform speech recognition on private or sensitive information.** Some speech is not appropriate for recognition. Don't send passwords, health or financial data, and other sensitive speech for recognition. diff --git a/speech_to_text_/android/.classpath b/speech_to_text_/android/.classpath new file mode 100644 index 00000000..eb19361b --- /dev/null +++ b/speech_to_text_/android/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/speech_to_text_/android/.gitignore b/speech_to_text_/android/.gitignore new file mode 100644 index 00000000..c6cbe562 --- /dev/null +++ b/speech_to_text_/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/speech_to_text_/android/.project b/speech_to_text_/android/.project new file mode 100644 index 00000000..3050653c --- /dev/null +++ b/speech_to_text_/android/.project @@ -0,0 +1,23 @@ + + + speech_to_text + Project android_____ created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs b/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..7a23d112 --- /dev/null +++ b/speech_to_text_/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(5.6.1)) +connection.project.dir= +eclipse.preferences.version=1 +gradle.user.home= +java.home= +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/speech_to_text_/android/build.gradle b/speech_to_text_/android/build.gradle new file mode 100644 index 00000000..6b23b300 --- /dev/null +++ b/speech_to_text_/android/build.gradle @@ -0,0 +1,44 @@ +group 'com.csdcorp.speech_to_text' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + defaultConfig { + minSdkVersion 21 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/speech_to_text_/android/gradle/gradle.properties b/speech_to_text_/android/gradle/gradle.properties new file mode 100644 index 00000000..94adc3a3 --- /dev/null +++ b/speech_to_text_/android/gradle/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/speech_to_text_/android/gradle/local.properties b/speech_to_text_/android/gradle/local.properties new file mode 100644 index 00000000..71a0a2e4 --- /dev/null +++ b/speech_to_text_/android/gradle/local.properties @@ -0,0 +1,3 @@ +sdk.dir=/Users/stephen.owens/Library/Android/sdk +flutter.sdk=/Users/stephen.owens/Documents/dev/flutter/sdk/flutter +org.gradle.jvmargs=-Xmx1536m -Duser.country=US -Duser.language=en \ No newline at end of file diff --git a/speech_to_text_/android/gradle/settings.gradle b/speech_to_text_/android/gradle/settings.gradle new file mode 100644 index 00000000..cdfc1c4b --- /dev/null +++ b/speech_to_text_/android/gradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'speech_to_text' diff --git a/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties b/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..674bdda0 --- /dev/null +++ b/speech_to_text_/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/speech_to_text_/android/src/main/AndroidManifest.xml b/speech_to_text_/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..61a73f32 --- /dev/null +++ b/speech_to_text_/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt b/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt new file mode 100644 index 00000000..7954add3 --- /dev/null +++ b/speech_to_text_/android/src/main/kotlin/com/csdcorp/speech_to_text/SpeechToTextPlugin.kt @@ -0,0 +1,595 @@ +package com.csdcorp.speech_to_text + +import androidx.annotation.NonNull; +import io.flutter.embedding.engine.plugins.FlutterPlugin +import android.Manifest +import android.annotation.TargetApi +import android.app.Activity +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import android.os.Bundle +import android.speech.RecognitionListener +import android.speech.SpeechRecognizer.createSpeechRecognizer +import android.speech.RecognizerIntent +import android.speech.SpeechRecognizer +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result +import io.flutter.plugin.common.PluginRegistry +import io.flutter.plugin.common.PluginRegistry.Registrar +import org.json.JSONObject +import android.content.Context +import android.content.BroadcastReceiver +import android.os.Handler +import android.os.Looper +import android.util.Log +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding +import io.flutter.plugin.common.BinaryMessenger +import org.json.JSONArray +import java.util.* + + +enum class SpeechToTextErrors { + multipleRequests, + unimplemented, + noLanguageIntent, + recognizerNotAvailable, + missingOrInvalidArg, + unknown +} + +enum class SpeechToTextCallbackMethods { + textRecognition, + notifyStatus, + notifyError, + soundLevelChange, +} + +enum class SpeechToTextStatus { + listening, + notListening, + unavailable, + available, +} + +enum class ListenMode { + deviceDefault, + dictation, + search, + confirmation, +} + +const val pluginChannelName = "plugin.csdcorp.com/speech_to_text" + +@TargetApi(8) +/** SpeechToTextPlugin */ +public class SpeechToTextPlugin : + MethodCallHandler, RecognitionListener, + PluginRegistry.RequestPermissionsResultListener, FlutterPlugin, + ActivityAware { + private var pluginContext: Context? = null + private var channel: MethodChannel? = null + private val minSdkForSpeechSupport = 21 + private val speechToTextPermissionCode = 28521 + private val missingConfidence: Double = -1.0 + private val logTag = "SpeechToTextPlugin" + private var currentActivity: Activity? = null + private var activeResult: Result? = null + private var initializedSuccessfully: Boolean = false + private var permissionToRecordAudio: Boolean = false + private var listening = false + private var debugLogging: Boolean = false + private var speechRecognizer: SpeechRecognizer? = null + private var recognizerIntent: Intent? = null + private var previousRecognizerLang: String? = null + private var previousPartialResults: Boolean = true + private var previousListenMode: ListenMode = ListenMode.deviceDefault + private var lastFinalTime: Long = 0 + private val handler: Handler = Handler(Looper.getMainLooper()) + private val defaultLanguageTag: String = Locale.getDefault().toLanguageTag() + + override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + + onAttachedToEngine(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); + } + + // This static function is optional and equivalent to onAttachedToEngine. It supports the old + // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting + // plugin registration via this function while apps migrate to use the new Android APIs + // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. + // + // It is encouraged to share logic between onAttachedToEngine and registerWith to keep + // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called + // depending on the user's project. onAttachedToEngine or registerWith must both be defined + // in the same class. + companion object { + @JvmStatic + fun registerWith(registrar: Registrar) { + val speechPlugin = SpeechToTextPlugin() + speechPlugin.currentActivity = registrar.activity() + registrar.addRequestPermissionsResultListener(speechPlugin) + speechPlugin.onAttachedToEngine(registrar.context(), registrar.messenger()) + } + } + + private fun onAttachedToEngine(applicationContext: Context, messenger: BinaryMessenger) { + this.pluginContext = applicationContext; + channel = MethodChannel(messenger, pluginChannelName) + channel?.setMethodCallHandler(this) + } + + override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + this.pluginContext = null; + channel?.setMethodCallHandler(null) + channel = null + } + + override fun onDetachedFromActivity() { + currentActivity = null + } + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + currentActivity = binding.activity + binding.addRequestPermissionsResultListener(this) + } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + currentActivity = binding.activity + binding.addRequestPermissionsResultListener(this) + } + + override fun onDetachedFromActivityForConfigChanges() { + currentActivity = null + } + + override fun onMethodCall(@NonNull call: MethodCall, @NonNull rawrResult: Result) { + val result = ChannelResultWrapper(rawrResult) + try { + when (call.method) { + "has_permission" -> hasPermission(result) + "initialize" -> { + var dlog = call.argument("debugLogging") + if (null != dlog) { + debugLogging = dlog + } + initialize(result) + } + "listen" -> { + var localeId = call.argument("localeId") + if (null == localeId) { + localeId = defaultLanguageTag + } + var partialResults = call.argument("partialResults") + if (null == partialResults) { + partialResults = true + } + val listenModeIndex = call.argument("listenMode") + if ( null == listenModeIndex ) { + result.error(SpeechToTextErrors.missingOrInvalidArg.name, + "listenMode is required", null) + return + } + startListening(result, localeId, partialResults, listenModeIndex ) + } + "stop" -> stopListening(result) + "cancel" -> cancelListening(result) + "locales" -> locales(result) + else -> result.notImplemented() + } + } catch (exc: Exception) { + Log.e(logTag, "Unexpected exception", exc) + result.error(SpeechToTextErrors.unknown.name, + "Unexpected exception", exc.localizedMessage) + } + } + + private fun hasPermission(result: Result) { + if (sdkVersionTooLow(result)) { + return + } + debugLog("Start has_permission") + val localContext = pluginContext + if (localContext != null) { + val hasPerm = ContextCompat.checkSelfPermission(localContext, + Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED + result.success(hasPerm) + } + } + + private fun initialize(result: Result) { + if (sdkVersionTooLow(result)) { + return + } + debugLog("Start initialize") + if (null != activeResult) { + result.error(SpeechToTextErrors.multipleRequests.name, + "Only one initialize at a time", null) + return + } + activeResult = result + val localContext = pluginContext + initializeIfPermitted(pluginContext) + } + + private fun sdkVersionTooLow(result: Result): Boolean { + if (Build.VERSION.SDK_INT < minSdkForSpeechSupport) { + result.success(false) + return true; + } + return false; + } + + private fun isNotInitialized(result: Result): Boolean { + if (!initializedSuccessfully || null == pluginContext) { + result.success(false) + } + return !initializedSuccessfully + } + + private fun isListening(): Boolean { + return listening + } + + private fun isNotListening(): Boolean { + return !listening + } + + private fun startListening(result: Result, languageTag: String, partialResults: Boolean, + listenModeIndex: Int) { + if (sdkVersionTooLow(result) || isNotInitialized(result) || isListening()) { + return + } + debugLog("Start listening") + var listenMode = ListenMode.deviceDefault + if ( listenModeIndex == ListenMode.dictation.ordinal) { + listenMode = ListenMode.dictation + } + setupRecognizerIntent(languageTag, partialResults, listenMode) + handler.post { + run { + speechRecognizer?.startListening(recognizerIntent) + } + } + notifyListening(isRecording = true) + result.success(true) + debugLog("Start listening done") + } + + private fun stopListening(result: Result) { + if (sdkVersionTooLow(result) || isNotInitialized(result) || isNotListening()) { + return + } + debugLog("Stop listening") + handler.post { + run { + speechRecognizer?.stopListening() + } + } + notifyListening(isRecording = false) + result.success(true) + debugLog("Stop listening done") + } + + private fun cancelListening(result: Result) { + if (sdkVersionTooLow(result) || isNotInitialized(result) || isNotListening()) { + return + } + debugLog("Cancel listening") + handler.post { + run { + speechRecognizer?.cancel() + } + } + notifyListening(isRecording = false) + result.success(true) + debugLog("Cancel listening done") + } + + private fun locales(result: Result) { + if (sdkVersionTooLow(result) || isNotInitialized(result)) { + return + } + var detailsIntent = RecognizerIntent.getVoiceDetailsIntent(pluginContext) + if (null == detailsIntent) { + detailsIntent = Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS) + } + if (null == detailsIntent) { + result.error(SpeechToTextErrors.noLanguageIntent.name, + "Could not get voice details", null) + return + } + pluginContext?.sendOrderedBroadcast( + detailsIntent, null, LanguageDetailsChecker(result), + null, Activity.RESULT_OK, null, null) + } + + private fun notifyListening(isRecording: Boolean) { + debugLog("Notify listening") + listening = isRecording + val status = when (isRecording) { + true -> SpeechToTextStatus.listening.name + false -> SpeechToTextStatus.notListening.name + } + channel?.invokeMethod(SpeechToTextCallbackMethods.notifyStatus.name, status) + debugLog("Notify listening done") + } + + private fun updateResults(speechBundle: Bundle?, isFinal: Boolean) { + if (isDuplicateFinal( isFinal )) { + debugLog("Discarding duplicate final") + return + } + val userSaid = speechBundle?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) + if (null != userSaid && userSaid.isNotEmpty()) { + val speechResult = JSONObject() + speechResult.put("finalResult", isFinal) + val confidence = speechBundle?.getFloatArray(SpeechRecognizer.CONFIDENCE_SCORES) + val alternates = JSONArray() + for (resultIndex in 0..userSaid.size - 1) { + val speechWords = JSONObject() + speechWords.put("recognizedWords", userSaid[resultIndex]) + if (null != confidence && confidence.size >= userSaid.size) { + speechWords.put("confidence", confidence[resultIndex]) + } else { + speechWords.put("confidence", missingConfidence) + } + alternates.put(speechWords) + } + speechResult.put("alternates", alternates) + val jsonResult = speechResult.toString() + debugLog("Calling results callback") + channel?.invokeMethod(SpeechToTextCallbackMethods.textRecognition.name, + jsonResult) + } + } + + private fun isDuplicateFinal( isFinal: Boolean ) : Boolean { + if ( !isFinal ) { + return false + } + val delta = System.currentTimeMillis() - lastFinalTime + lastFinalTime = System.currentTimeMillis() + return delta >= 0 && delta < 100 + } + + private fun initializeIfPermitted(context: Context?) { + val localContext = context + if (null == localContext) { + completeInitialize() + return + } + permissionToRecordAudio = ContextCompat.checkSelfPermission(localContext, + Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED + debugLog("Checked permission") + if (!permissionToRecordAudio) { + val localActivity = currentActivity + if (null != localActivity) { + debugLog("Requesting permission") + ActivityCompat.requestPermissions(localActivity, + arrayOf(Manifest.permission.RECORD_AUDIO), speechToTextPermissionCode) + } else { + debugLog("no permission, no activity, completing") + completeInitialize() + } + } else { + debugLog("has permission, completing") + completeInitialize() + } + debugLog("leaving initializeIfPermitted") + } + + private fun completeInitialize() { + + debugLog("completeInitialize") + if (permissionToRecordAudio) { + debugLog("Testing recognition availability") + if (!SpeechRecognizer.isRecognitionAvailable(pluginContext)) { + Log.e(logTag, "Speech recognition not available on this device") + activeResult?.error(SpeechToTextErrors.recognizerNotAvailable.name, + "Speech recognition not available on this device", "") + activeResult = null + return + } + + debugLog("Creating recognizer") + speechRecognizer = createSpeechRecognizer(pluginContext).apply { + debugLog("Setting listener") + setRecognitionListener(this@SpeechToTextPlugin) + } + if (null == speechRecognizer) { + Log.e(logTag, "Speech recognizer null") + activeResult?.error( + SpeechToTextErrors.recognizerNotAvailable.name, + "Speech recognizer null", "") + activeResult = null + } + + debugLog("before setup intent") + setupRecognizerIntent(defaultLanguageTag, true, ListenMode.deviceDefault) + debugLog("after setup intent") + } + + initializedSuccessfully = permissionToRecordAudio + debugLog("sending result") + activeResult?.success(permissionToRecordAudio) + debugLog("leaving complete") + activeResult = null + } + + private fun setupRecognizerIntent(languageTag: String, partialResults: Boolean, listenMode: ListenMode) { + debugLog("setupRecognizerIntent") + if (previousRecognizerLang == null || + previousRecognizerLang != languageTag || + partialResults != previousPartialResults || previousListenMode != listenMode ) { + previousRecognizerLang = languageTag; + previousPartialResults = partialResults + previousListenMode = listenMode + handler.post { + run { + recognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { + debugLog("In RecognizerIntent apply") + putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM) + debugLog("put model") + val localContext = pluginContext + if (null != localContext) { + putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, + localContext.applicationInfo.packageName) + } + debugLog("put package") + putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, partialResults) + debugLog("put partial") + if (languageTag != Locale.getDefault().toLanguageTag()) { + putExtra(RecognizerIntent.EXTRA_LANGUAGE, languageTag); + debugLog("put languageTag") + } + } + } + } + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array?, + grantResults: IntArray?): Boolean { + when (requestCode) { + speechToTextPermissionCode -> { + if (null != grantResults) { + permissionToRecordAudio = grantResults.isNotEmpty() && + grantResults.get(0) == PackageManager.PERMISSION_GRANTED + } + completeInitialize() + return true + } + } + return false + } + + + override fun onPartialResults(results: Bundle?) = updateResults(results, false) + override fun onResults(results: Bundle?) = updateResults(results, true) + override fun onEndOfSpeech() = notifyListening(isRecording = false) + + override fun onError(errorCode: Int) { + val errorMsg = when (errorCode) { + SpeechRecognizer.ERROR_AUDIO -> "error_audio_error" + SpeechRecognizer.ERROR_CLIENT -> "error_client" + SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "error_permission" + SpeechRecognizer.ERROR_NETWORK -> "error_network" + SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "error_network_timeout" + SpeechRecognizer.ERROR_NO_MATCH -> "error_no_match" + SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "error_busy" + SpeechRecognizer.ERROR_SERVER -> "error_server" + SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "error_speech_timeout" + else -> "error_unknown" + } + sendError(errorMsg) + } + + private fun debugLog( msg: String ) { + if ( debugLogging ) { + Log.d( logTag, msg ) + } + } + + private fun sendError(errorMsg: String) { + val speechError = JSONObject() + speechError.put("errorMsg", errorMsg) + speechError.put("permanent", true) + handler.post { + run { + channel?.invokeMethod(SpeechToTextCallbackMethods.notifyError.name, speechError.toString()) + } + } + } + + override fun onRmsChanged(rmsdB: Float) { + handler.post { + run { + channel?.invokeMethod(SpeechToTextCallbackMethods.soundLevelChange.name, rmsdB) + } + } + } + + override fun onReadyForSpeech(p0: Bundle?) {} + override fun onBufferReceived(p0: ByteArray?) {} + override fun onEvent(p0: Int, p1: Bundle?) {} + override fun onBeginningOfSpeech() {} +} + +// See https://stackoverflow.com/questions/10538791/how-to-set-the-language-in-speech-recognition-on-android/10548680#10548680 +class LanguageDetailsChecker(flutterResult: Result) : BroadcastReceiver() { + private val result: Result = flutterResult + private var supportedLanguages: List? = null + + private var languagePreference: String? = null + + override fun onReceive(context: Context, intent: Intent) { + val results = getResultExtras(true) + if (results.containsKey(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE)) { + languagePreference = results.getString(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE) + } + if (results.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) { + supportedLanguages = results.getStringArrayList( + RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES) + createResponse(supportedLanguages) + } + } + + private fun createResponse(supportedLanguages: List?) { + val currentLocale = Locale.getDefault() + val localeNames = ArrayList() + localeNames.add(buildIdNameForLocale(currentLocale)) + if (null != supportedLanguages) { + for (lang in supportedLanguages) { + if (currentLocale.toLanguageTag() == lang) { + continue + } + val locale = Locale.forLanguageTag(lang) + localeNames.add(buildIdNameForLocale(locale)) + } + } + result.success(localeNames) + + } + + private fun buildIdNameForLocale(locale: Locale): String { + val name = locale.displayName.replace(':', ' ') + return "${locale.language}_${locale.country}:$name" + } +} + +private class ChannelResultWrapper(result: Result) : Result { + // Caller handler + val handler: Handler = Handler(Looper.getMainLooper()) + val result: Result = result + + // make sure to respond in the caller thread + override fun success(results: Any?) { + + handler.post { + run { + result.success(results); + } + } + } + + override fun error(errorCode: String?, errorMessage: String?, data: Any?) { + handler.post { + run { + result.error(errorCode, errorMessage, data); + } + } + } + + override fun notImplemented() { + handler.post { + run { + result.notImplemented(); + } + } + } +} diff --git a/speech_to_text_/example/.gitignore b/speech_to_text_/example/.gitignore new file mode 100644 index 00000000..2ddde2a5 --- /dev/null +++ b/speech_to_text_/example/.gitignore @@ -0,0 +1,73 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/speech_to_text_/example/.metadata b/speech_to_text_/example/.metadata new file mode 100644 index 00000000..aeb01ee2 --- /dev/null +++ b/speech_to_text_/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f + channel: stable + +project_type: app diff --git a/speech_to_text_/example/README.md b/speech_to_text_/example/README.md new file mode 100644 index 00000000..92252821 --- /dev/null +++ b/speech_to_text_/example/README.md @@ -0,0 +1,155 @@ +# speech_to_text_example + +Demonstrates how to use the speech_to_text plugin. This example requires +that the plugin has been installed. It initializes speech recognition, +listens for words and prints them. + + +## Source + +```dart +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + bool _hasSpeech = false; + String lastWords = ""; + String lastError = ""; + String lastStatus = ""; + final SpeechToText speech = SpeechToText(); + + @override + void initState() { + super.initState(); + initSpeechState(); + } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize(onError: errorListener, onStatus: statusListener ); + + if (!mounted) return; + setState(() { + _hasSpeech = hasSpeech; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Speech to Text Example'), + ), + body: _hasSpeech + ? Column(children: [ + Expanded( + child: Center( + child: Text('Speech recognition available'), + ), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FlatButton( + child: Text('Start'), + onPressed: startListening, + ), + FlatButton( + child: Text('Stop'), + onPressed: stopListening, + ), + FlatButton( + child: Text('Cancel'), + onPressed:cancelListening, + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Center( + child: Text('Recognized Words'), + ), + Center( + child: Text(lastWords), + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Center( + child: Text('Error'), + ), + Center( + child: Text(lastError), + ), + ], + ), + ), + Expanded( + child: Center( + child: speech.isListening ? Text("I'm listening...") : Text( 'Not listening' ), + ), + ), + ]) + : Center( child: Text('Speech recognition unavailable', style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold))), + ), + ); + } + + void startListening() { + lastWords = ""; + lastError = ""; + speech.listen(onResult: resultListener ); + setState(() { + + }); + } + + void stopListening() { + speech.stop( ); + setState(() { + + }); + } + + void cancelListening() { + speech.cancel( ); + setState(() { + + }); + } + + void resultListener(SpeechRecognitionResult result) { + setState(() { + lastWords = "${result.recognizedWords} - ${result.finalResult}"; + }); + } + + void errorListener(SpeechRecognitionError error ) { + setState(() { + lastError = "${error.errorMsg} - ${error.permanent}"; + }); + } + void statusListener(String status ) { + setState(() { + lastStatus = "$status"; + }); + } +} +``` \ No newline at end of file diff --git a/speech_to_text_/example/android/.project b/speech_to_text_/example/android/.project new file mode 100644 index 00000000..d7d48141 --- /dev/null +++ b/speech_to_text_/example/android/.project @@ -0,0 +1,17 @@ + + + android___ + Project android___ created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs b/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..e8895216 --- /dev/null +++ b/speech_to_text_/example/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/speech_to_text_/example/android/app/build.gradle b/speech_to_text_/example/android/app/build.gradle new file mode 100644 index 00000000..8b616f29 --- /dev/null +++ b/speech_to_text_/example/android/app/build.gradle @@ -0,0 +1,67 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.csdcorp.speech_to_text_example" + minSdkVersion 21 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml b/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..36edf838 --- /dev/null +++ b/speech_to_text_/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/speech_to_text_/example/android/app/src/main/AndroidManifest.xml b/speech_to_text_/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..b0912061 --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt b/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt new file mode 100644 index 00000000..f44e470e --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/kotlin/com/csdcorp/speech_to_text_example/MainActivity.kt @@ -0,0 +1,12 @@ +package com.csdcorp.speech_to_text_example + +import androidx.annotation.NonNull; +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + GeneratedPluginRegistrant.registerWith(flutterEngine); + } +} diff --git a/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml b/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..db77bb4b Binary files /dev/null and b/speech_to_text_/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..17987b79 Binary files /dev/null and b/speech_to_text_/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..09d43914 Binary files /dev/null and b/speech_to_text_/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..d5f1c8d3 Binary files /dev/null and b/speech_to_text_/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..4d6372ee Binary files /dev/null and b/speech_to_text_/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/speech_to_text_/example/android/app/src/main/res/values/styles.xml b/speech_to_text_/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..00fa4417 --- /dev/null +++ b/speech_to_text_/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml b/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..36edf838 --- /dev/null +++ b/speech_to_text_/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/speech_to_text_/example/android/build.gradle b/speech_to_text_/example/android/build.gradle new file mode 100644 index 00000000..13546311 --- /dev/null +++ b/speech_to_text_/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/speech_to_text_/example/android/gradle.properties b/speech_to_text_/example/android/gradle.properties new file mode 100644 index 00000000..a6738207 --- /dev/null +++ b/speech_to_text_/example/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties b/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..052e7951 --- /dev/null +++ b/speech_to_text_/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Mar 16 08:57:32 EDT 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/speech_to_text_/example/android/settings.gradle b/speech_to_text_/example/android/settings.gradle new file mode 100644 index 00000000..5a2f14fb --- /dev/null +++ b/speech_to_text_/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r b/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r new file mode 100644 index 00000000..ccb3afe3 Binary files /dev/null and b/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r differ diff --git a/speech_to_text_/example/assets/sounds/speech_to_text_listening.m4r b/speech_to_text_/example/assets/sounds/speech_to_text_listening.m4r new file mode 100644 index 00000000..3131d60f Binary files /dev/null and b/speech_to_text_/example/assets/sounds/speech_to_text_listening.m4r differ diff --git a/speech_to_text_/example/assets/sounds/speech_to_text_stop.m4r b/speech_to_text_/example/assets/sounds/speech_to_text_stop.m4r new file mode 100644 index 00000000..8817f01b Binary files /dev/null and b/speech_to_text_/example/assets/sounds/speech_to_text_stop.m4r differ diff --git a/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist b/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..6b4c0f78 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/speech_to_text_/example/ios/Flutter/Debug.xcconfig b/speech_to_text_/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..e8efba11 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/speech_to_text_/example/ios/Flutter/Flutter.podspec b/speech_to_text_/example/ios/Flutter/Flutter.podspec new file mode 100644 index 00000000..5ca30416 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/speech_to_text_/example/ios/Flutter/Release.xcconfig b/speech_to_text_/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..399e9340 --- /dev/null +++ b/speech_to_text_/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/speech_to_text_/example/ios/Podfile b/speech_to_text_/example/ios/Podfile new file mode 100644 index 00000000..ab7d5b46 --- /dev/null +++ b/speech_to_text_/example/ios/Podfile @@ -0,0 +1,90 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '10.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/speech_to_text_/example/ios/Podfile.lock b/speech_to_text_/example/ios/Podfile.lock new file mode 100644 index 00000000..60c8b57d --- /dev/null +++ b/speech_to_text_/example/ios/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - Flutter (1.0.0) + - speech_to_text (0.0.1): + - Flutter + - Try + - Try (2.1.1) + +DEPENDENCIES: + - Flutter (from `Flutter`) + - speech_to_text (from `.symlinks/plugins/speech_to_text/ios`) + +SPEC REPOS: + trunk: + - Try + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + speech_to_text: + :path: ".symlinks/plugins/speech_to_text/ios" + +SPEC CHECKSUMS: + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe + Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 + +PODFILE CHECKSUM: 0ba44ad07df4ab62269dc769727cf0f12b1e453d + +COCOAPODS: 1.9.3 diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj b/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c40af650 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,578 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + C446300A034BF27D9F1ACEF9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 59AFE6BB0B596A0E0811BDFF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 6280E2A777726D2043BF80B7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C3909A4B7EC98A20255210E3 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C446300A034BF27D9F1ACEF9 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7937AF765430D66F28F7FEEF /* Frameworks */ = { + isa = PBXGroup; + children = ( + E76E9615C6B4FABD88067D55 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + A68CCF1640763A551D35BD31 /* Pods */, + 7937AF765430D66F28F7FEEF /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + A68CCF1640763A551D35BD31 /* Pods */ = { + isa = PBXGroup; + children = ( + 59AFE6BB0B596A0E0811BDFF /* Pods-Runner.debug.xcconfig */, + 6280E2A777726D2043BF80B7 /* Pods-Runner.release.xcconfig */, + C3909A4B7EC98A20255210E3 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 949FCB95217187F2C022D6A9 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 8B0988F04B6AE44AA0304FEF /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 3X949YE9K2; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 8B0988F04B6AE44AA0304FEF /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 949FCB95217187F2C022D6A9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3X949YE9K2; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3X949YE9K2; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 3X949YE9K2; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.csdcorp.speechToTextExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..a28140cf --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/speech_to_text_/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/speech_to_text_/example/ios/Runner/AppDelegate.swift b/speech_to_text_/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/speech_to_text_/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..dc9ada47 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..28c6bf03 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..2ccbfd96 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..f091b6b0 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..4cde1211 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..d0ef06e7 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..dcdc2306 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 00000000..2ccbfd96 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..c8f9ed8f Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..a6d6b860 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..a6d6b860 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..75b2d164 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..c4df70d3 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..6a84f41e Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..d0e1f585 Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard b/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/speech_to_text_/example/ios/Runner/Info.plist b/speech_to_text_/example/ios/Runner/Info.plist new file mode 100644 index 00000000..a69c0fce --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + NSMicrophoneUsageDescription + This example listens for speech on the device microphone on your request. + NSSpeechRecognitionUsageDescription + This example recognizes words as you speak them and displays them. + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + speech_to_text_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h b/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..7335fdf9 --- /dev/null +++ b/speech_to_text_/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/speech_to_text_/example/lib/main.dart b/speech_to_text_/example/lib/main.dart new file mode 100644 index 00000000..0115b828 --- /dev/null +++ b/speech_to_text_/example/lib/main.dart @@ -0,0 +1,275 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + bool _hasSpeech = false; + double level = 0.0; + double minSoundLevel = 50000; + double maxSoundLevel = -50000; + String lastWords = ""; + String lastError = ""; + String lastStatus = ""; + String _currentLocaleId = ""; + List _localeNames = []; + final SpeechToText speech = SpeechToText(); + + @override + void initState() { + requestPermissions(); + super.initState(); + } + + Future initSpeechState() async { + bool hasSpeech = await speech.initialize( + onError: errorListener, onStatus: statusListener); + if (hasSpeech) { + _localeNames = await speech.locales(); + + var systemLocale = await speech.systemLocale(); + _currentLocaleId = systemLocale.localeId; + } + + if (!mounted) return; + + setState(() { + _hasSpeech = hasSpeech; + }); + } + + void requestPermissions() async{ + Map statuses = await [ + Permission.microphone, + ].request(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Speech to Text CloudSolution'), + ), + body: Column(children: [ + Center( + child: Text( + 'Speech recognition available', + style: TextStyle(fontSize: 22.0), + ), + ), + Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Initialize'), + onPressed: _hasSpeech ? null : initSpeechState, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + child: Text('Start'), + onPressed: !_hasSpeech || speech.isListening + ? null + : startListening, + ), + FlatButton( + child: Text('Stop'), + onPressed: speech.isListening ? stopListening : null, + ), + FlatButton( + child: Text('Cancel'), + onPressed: speech.isListening ? cancelListening : null, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + DropdownButton( + onChanged: (selectedVal) => _switchLang(selectedVal), + value: _currentLocaleId, + items: _localeNames + .map( + (localeName) => DropdownMenuItem( + value: localeName.localeId, + child: Text(localeName.name), + ), + ) + .toList(), + ), + ], + ) + ], + ), + ), + Expanded( + flex: 4, + child: Column( + children: [ + Center( + child: Text( + 'Recognized Words', + style: TextStyle(fontSize: 22.0), + ), + ), + Expanded( + child: Stack( + children: [ + Container( + color: Theme.of(context).selectedRowColor, + child: Center( + child: Text( + lastWords, + textAlign: TextAlign.center, + ), + ), + ), + Positioned.fill( + bottom: 10, + child: Align( + alignment: Alignment.bottomCenter, + child: Container( + width: 40, + height: 40, + alignment: Alignment.center, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + blurRadius: .26, + spreadRadius: level * 1.5, + color: Colors.black.withOpacity(.05)) + ], + color: Colors.white, + borderRadius: + BorderRadius.all(Radius.circular(50)), + ), + child: IconButton(icon: Icon(Icons.mic)), + ), + ), + ), + ], + ), + ), + ], + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Center( + child: Text( + 'Error Status', + style: TextStyle(fontSize: 22.0), + ), + ), + Center( + child: Text(lastError), + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 20), + color: Theme.of(context).backgroundColor, + child: Center( + child: speech.isListening + ? Text( + "I'm listening...", + style: TextStyle(fontWeight: FontWeight.bold), + ) + : Text( + 'Not listening', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + ]), + ), + ); + } + + void startListening() { + lastWords = ""; + lastError = ""; + speech.listen( + onResult: resultListener, + listenFor: Duration(seconds: 10), + localeId: _currentLocaleId, + onSoundLevelChange: soundLevelListener, + cancelOnError: true, + partialResults: true, + onDevice: true, + listenMode: ListenMode.confirmation); + setState(() {}); + } + + void stopListening() { + speech.stop(); + setState(() { + level = 0.0; + }); + } + + void cancelListening() { + speech.cancel(); + setState(() { + level = 0.0; + }); + } + + void resultListener(SpeechRecognitionResult result) { + setState(() { + lastWords = "${result.recognizedWords} - ${result.finalResult}"; + }); + } + + void soundLevelListener(double level) { + minSoundLevel = min(minSoundLevel, level); + maxSoundLevel = max(maxSoundLevel, level); + // print("sound level $level: $minSoundLevel - $maxSoundLevel "); + setState(() { + this.level = level; + }); + } + + void errorListener(SpeechRecognitionError error) { + // print("Received error status: $error, listening: ${speech.isListening}"); + setState(() { + lastError = "${error.errorMsg} - ${error.permanent}"; + }); + } + + void statusListener(String status) { + // print( + // "Received listener status: $status, listening: ${speech.isListening}"); + setState(() { + lastStatus = "$status"; + }); + } + + _switchLang(selectedVal) { + setState(() { + _currentLocaleId = selectedVal; + }); + print(selectedVal); + } +} diff --git a/speech_to_text_/example/pubspec.yaml b/speech_to_text_/example/pubspec.yaml new file mode 100644 index 00000000..d2bfcff7 --- /dev/null +++ b/speech_to_text_/example/pubspec.yaml @@ -0,0 +1,33 @@ +name: speech_to_text_example +description: Demonstrates how to use the speech_to_text plugin. +version: 1.1.0 +publish_to: 'none' + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + cupertino_icons: ^0.1.2 + permission_handler: ^5.0.1+1 + + provider: + +dev_dependencies: + flutter_test: + sdk: flutter + + speech_to_text: + path: ../ + +# The following section is specific to Flutter. +flutter: + + uses-material-design: true + + assets: + - assets/sounds/speech_to_text_listening.m4r + - assets/sounds/speech_to_text_cancel.m4r + - assets/sounds/speech_to_text_stop.m4r diff --git a/speech_to_text_/example/test/widget_test.dart b/speech_to_text_/example/test/widget_test.dart new file mode 100644 index 00000000..639a52fb --- /dev/null +++ b/speech_to_text_/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../lib/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/speech_to_text_/ios/.gitignore b/speech_to_text_/ios/.gitignore new file mode 100644 index 00000000..aa479fd3 --- /dev/null +++ b/speech_to_text_/ios/.gitignore @@ -0,0 +1,37 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/speech_to_text_/ios/Assets/.gitkeep b/speech_to_text_/ios/Assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/speech_to_text_/ios/Classes/SpeechToTextPlugin.h b/speech_to_text_/ios/Classes/SpeechToTextPlugin.h new file mode 100644 index 00000000..1785eb8f --- /dev/null +++ b/speech_to_text_/ios/Classes/SpeechToTextPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface SpeechToTextPlugin : NSObject +@end diff --git a/speech_to_text_/ios/Classes/SpeechToTextPlugin.m b/speech_to_text_/ios/Classes/SpeechToTextPlugin.m new file mode 100644 index 00000000..20d0327d --- /dev/null +++ b/speech_to_text_/ios/Classes/SpeechToTextPlugin.m @@ -0,0 +1,8 @@ +#import "SpeechToTextPlugin.h" +#import + +@implementation SpeechToTextPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftSpeechToTextPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift b/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift new file mode 100644 index 00000000..68687967 --- /dev/null +++ b/speech_to_text_/ios/Classes/SwiftSpeechToTextPlugin.swift @@ -0,0 +1,580 @@ +import Flutter +import UIKit +import Speech +import os.log +import Try + +public enum SwiftSpeechToTextMethods: String { + case has_permission + case initialize + case listen + case stop + case cancel + case locales + case unknown // just for testing +} + +public enum SwiftSpeechToTextCallbackMethods: String { + case textRecognition + case notifyStatus + case notifyError + case soundLevelChange +} + +public enum SpeechToTextStatus: String { + case listening + case notListening + case unavailable + case available +} + +public enum SpeechToTextErrors: String { + case onDeviceError + case noRecognizerError + case listenFailedError + case missingOrInvalidArg +} + +public enum ListenMode: Int { + case deviceDefault = 0 + case dictation = 1 + case search = 2 + case confirmation = 3 +} + +struct SpeechRecognitionWords : Codable { + let recognizedWords: String + let confidence: Decimal +} + +struct SpeechRecognitionResult : Codable { + let alternates: [SpeechRecognitionWords] + let finalResult: Bool +} + +struct SpeechRecognitionError : Codable { + let errorMsg: String + let permanent: Bool +} + +enum SpeechToTextError: Error { + case runtimeError(String) +} + + +@available(iOS 10.0, *) +public class SwiftSpeechToTextPlugin: NSObject, FlutterPlugin { + private var channel: FlutterMethodChannel + private var registrar: FlutterPluginRegistrar + private var recognizer: SFSpeechRecognizer? + private var currentRequest: SFSpeechAudioBufferRecognitionRequest? + private var currentTask: SFSpeechRecognitionTask? + private var listeningSound: AVAudioPlayer? + private var successSound: AVAudioPlayer? + private var cancelSound: AVAudioPlayer? + private var rememberedAudioCategory: AVAudioSession.Category? + private var previousLocale: Locale? + private var onPlayEnd: (() -> Void)? + private var returnPartialResults: Bool = true + private var failedListen: Bool = false + private var listening = false + private let audioSession = AVAudioSession.sharedInstance() + private let audioEngine = AVAudioEngine() + private let jsonEncoder = JSONEncoder() + private let busForNodeTap = 0 + private let speechBufferSize: AVAudioFrameCount = 1024 + private static var subsystem = Bundle.main.bundleIdentifier! + private let pluginLog = OSLog(subsystem: "com.csdcorp.speechToText", category: "plugin") + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "plugin.csdcorp.com/speech_to_text", binaryMessenger: registrar.messenger()) + let instance = SwiftSpeechToTextPlugin( channel, registrar: registrar ) + registrar.addMethodCallDelegate(instance, channel: channel ) + } + + init( _ channel: FlutterMethodChannel, registrar: FlutterPluginRegistrar ) { + self.channel = channel + self.registrar = registrar + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case SwiftSpeechToTextMethods.has_permission.rawValue: + hasPermission( result ) + case SwiftSpeechToTextMethods.initialize.rawValue: + initialize( result ) + case SwiftSpeechToTextMethods.listen.rawValue: + guard let argsArr = call.arguments as? Dictionary, + let partialResults = argsArr["partialResults"] as? Bool, let onDevice = argsArr["onDevice"] as? Bool, let listenModeIndex = argsArr["listenMode"] as? Int + else { + DispatchQueue.main.async { + result(FlutterError( code: SpeechToTextErrors.missingOrInvalidArg.rawValue, + message:"Missing arg partialResults, onDevice, and listenMode are required", + details: nil )) + } + return + } + var localeStr: String? = nil + if let localeParam = argsArr["localeId"] as? String { + localeStr = localeParam + } + guard let listenMode = ListenMode(rawValue: listenModeIndex) else { + DispatchQueue.main.async { + result(FlutterError( code: SpeechToTextErrors.missingOrInvalidArg.rawValue, + message:"invalid value for listenMode, must be 0-2, was \(listenModeIndex)", + details: nil )) + } + return + } + + listenForSpeech( result, localeStr: localeStr, partialResults: partialResults, onDevice: onDevice, listenMode: listenMode ) + case SwiftSpeechToTextMethods.stop.rawValue: + stopSpeech( result ) + case SwiftSpeechToTextMethods.cancel.rawValue: + cancelSpeech( result ) + case SwiftSpeechToTextMethods.locales.rawValue: + locales( result ) + default: + os_log("Unrecognized method: %{PUBLIC}@", log: pluginLog, type: .error, call.method) + DispatchQueue.main.async { + result( FlutterMethodNotImplemented) + } + } + } + + private func hasPermission( _ result: @escaping FlutterResult) { + let has = SFSpeechRecognizer.authorizationStatus() == SFSpeechRecognizerAuthorizationStatus.authorized && + AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted + DispatchQueue.main.async { + result( has ) + } + } + + private func initialize( _ result: @escaping FlutterResult) { + var success = false + let status = SFSpeechRecognizer.authorizationStatus() + switch status { + case SFSpeechRecognizerAuthorizationStatus.notDetermined: + SFSpeechRecognizer.requestAuthorization({(status)->Void in + success = status == SFSpeechRecognizerAuthorizationStatus.authorized + if ( success ) { + AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in + if granted { + self.setupSpeechRecognition(result) + } else{ + self.sendBoolResult( false, result ); + os_log("User denied permission", log: self.pluginLog, type: .info) + } + }) + } + else { + self.sendBoolResult( false, result ); + } + }); + case SFSpeechRecognizerAuthorizationStatus.denied: + os_log("Permission permanently denied", log: self.pluginLog, type: .info) + sendBoolResult( false, result ); + case SFSpeechRecognizerAuthorizationStatus.restricted: + os_log("Device restriction prevented initialize", log: self.pluginLog, type: .info) + sendBoolResult( false, result ); + default: + os_log("Has permissions continuing with setup", log: self.pluginLog, type: .debug) + setupSpeechRecognition(result) + } + } + + fileprivate func sendBoolResult( _ value: Bool, _ result: @escaping FlutterResult) { + DispatchQueue.main.async { + result( value ) + } + } + + fileprivate func setupListeningSound() { + listeningSound = loadSound("assets/sounds/speech_to_text_listening.m4r") + successSound = loadSound("assets/sounds/speech_to_text_stop.m4r") + cancelSound = loadSound("assets/sounds/speech_to_text_cancel.m4r") + } + + fileprivate func loadSound( _ assetPath: String ) -> AVAudioPlayer? { + var player: AVAudioPlayer? = nil + let soundKey = registrar.lookupKey(forAsset: assetPath ) + guard !soundKey.isEmpty else { + return player + } + if let soundPath = Bundle.main.path(forResource: soundKey, ofType:nil) { + let soundUrl = URL(fileURLWithPath: soundPath ) + do { + player = try AVAudioPlayer(contentsOf: soundUrl ) + player?.delegate = self + } catch { + // no audio + } + } + return player + } + + private func setupSpeechRecognition( _ result: @escaping FlutterResult) { + setupRecognizerForLocale( locale: Locale.current ) + guard recognizer != nil else { + sendBoolResult( false, result ); + return + } + recognizer?.delegate = self + setupListeningSound() + + sendBoolResult( true, result ); + } + + private func setupRecognizerForLocale( locale: Locale ) { + if ( previousLocale == locale ) { + return + } + previousLocale = locale + recognizer = SFSpeechRecognizer( locale: locale ) + } + + private func getLocale( _ localeStr: String? ) -> Locale { + guard let aLocaleStr = localeStr else { + return Locale.current + } + let locale = Locale(identifier: aLocaleStr) + return locale + } + + private func stopSpeech( _ result: @escaping FlutterResult) { + if ( !listening ) { + sendBoolResult( false, result ); + return + } + stopAllPlayers() + if let sound = successSound { + onPlayEnd = {() -> Void in + self.currentTask?.finish() + self.stopCurrentListen( ) + self.sendBoolResult( true, result ) + return + } + sound.play() + } + else { + stopCurrentListen( ) + sendBoolResult( true, result ); + } + } + + private func cancelSpeech( _ result: @escaping FlutterResult) { + if ( !listening ) { + sendBoolResult( false, result ); + return + } + stopAllPlayers() + if let sound = cancelSound { + onPlayEnd = {() -> Void in + self.currentTask?.cancel() + self.stopCurrentListen( ) + self.sendBoolResult( true, result ) + return + } + sound.play() + } + else { + self.currentTask?.cancel() + stopCurrentListen( ) + sendBoolResult( true, result ); + } + } + + private func stopAllPlayers() { + cancelSound?.stop() + successSound?.stop() + listeningSound?.stop() + } + + private func stopCurrentListen( ) { + stopAllPlayers() + currentRequest?.endAudio() + + do { + try trap { + self.audioEngine.stop() + } + } + catch { + os_log("Error stopping engine: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + } + do { + try trap { + let inputNode = self.audioEngine.inputNode + inputNode.removeTap(onBus: self.busForNodeTap); + } + } + catch { + os_log("Error removing trap: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + } + do { + if let rememberedAudioCategory = rememberedAudioCategory { + try self.audioSession.setCategory(rememberedAudioCategory) + } + } + catch { + os_log("Error stopping listen: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + } + do { + try self.audioSession.setActive(false, options: .notifyOthersOnDeactivation) + } + catch { + os_log("Error deactivation: %{PUBLIC}@", log: pluginLog, type: .info, error.localizedDescription) + } + currentRequest = nil + currentTask = nil + onPlayEnd = nil + listening = false + } + + private func listenForSpeech( _ result: @escaping FlutterResult, localeStr: String?, partialResults: Bool, onDevice: Bool, listenMode: ListenMode ) { + if ( nil != currentTask || listening ) { + sendBoolResult( false, result ); + return + } + do { + // let inErrorTest = true + failedListen = false + returnPartialResults = partialResults + setupRecognizerForLocale(locale: getLocale(localeStr)) + guard let localRecognizer = recognizer else { + result(FlutterError( code: SpeechToTextErrors.noRecognizerError.rawValue, + message:"Failed to create speech recognizer", + details: nil )) + return + } + if ( onDevice ) { + if #available(iOS 13.0, *), !localRecognizer.supportsOnDeviceRecognition { + result(FlutterError( code: SpeechToTextErrors.onDeviceError.rawValue, + message:"on device recognition is not supported on this device", + details: nil )) + } + } + rememberedAudioCategory = self.audioSession.category + try self.audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker) + // try self.audioSession.setMode(AVAudioSession.Mode.measurement) + try self.audioSession.setMode(AVAudioSession.Mode.default) + try self.audioSession.setActive(true, options: .notifyOthersOnDeactivation) + if let sound = listeningSound { + self.onPlayEnd = {()->Void in + if ( !self.failedListen ) { + self.listening = true + self.invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.listening.rawValue ) + + } + } + sound.play() + } + self.audioEngine.reset(); + let inputNode = self.audioEngine.inputNode + if(inputNode.inputFormat(forBus: 0).channelCount == 0){ + throw SpeechToTextError.runtimeError("Not enough available inputs.") + } + self.currentRequest = SFSpeechAudioBufferRecognitionRequest() + guard let currentRequest = self.currentRequest else { + sendBoolResult( false, result ); + return + } + currentRequest.shouldReportPartialResults = true + if #available(iOS 13.0, *), onDevice { + currentRequest.requiresOnDeviceRecognition = true + } + switch listenMode { + case ListenMode.dictation: + currentRequest.taskHint = SFSpeechRecognitionTaskHint.dictation + break + case ListenMode.search: + currentRequest.taskHint = SFSpeechRecognitionTaskHint.search + break + case ListenMode.confirmation: + currentRequest.taskHint = SFSpeechRecognitionTaskHint.confirmation + break + default: + break + } + self.currentTask = self.recognizer?.recognitionTask(with: currentRequest, delegate: self ) + let recordingFormat = inputNode.outputFormat(forBus: self.busForNodeTap) + try trap { + inputNode.installTap(onBus: self.busForNodeTap, bufferSize: self.speechBufferSize, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in + currentRequest.append(buffer) + self.updateSoundLevel( buffer: buffer ) + } + } + // if ( inErrorTest ){ + // throw SpeechToTextError.runtimeError("for testing only") + // } + self.audioEngine.prepare() + try self.audioEngine.start() + if nil == listeningSound { + listening = true + self.invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.listening.rawValue ) + } + sendBoolResult( true, result ); + } + catch { + failedListen = true + os_log("Error starting listen: %{PUBLIC}@", log: pluginLog, type: .error, error.localizedDescription) + stopCurrentListen() + sendBoolResult( false, result ); + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) + let speechError = SpeechRecognitionError(errorMsg: "error_listen_failed", permanent: true ) + do { + let errorResult = try jsonEncoder.encode(speechError) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyError, arguments: String( data:errorResult, encoding: .utf8) ) + } catch { + os_log("Could not encode JSON", log: pluginLog, type: .error) + } + } + } + + private func updateSoundLevel( buffer: AVAudioPCMBuffer) { + guard + let channelData = buffer.floatChannelData + else { + return + } + + let channelDataValue = channelData.pointee + let channelDataValueArray = stride(from: 0, + to: Int(buffer.frameLength), + by: buffer.stride).map{ channelDataValue[$0] } + let frameLength = Float(buffer.frameLength) + let rms = sqrt(channelDataValueArray.map{ $0 * $0 }.reduce(0, +) / frameLength ) + let avgPower = 20 * log10(rms) + self.invokeFlutter( SwiftSpeechToTextCallbackMethods.soundLevelChange, arguments: avgPower ) + } + + /// Build a list of localId:name with the current locale first + private func locales( _ result: @escaping FlutterResult ) { + var localeNames = [String](); + let locales = SFSpeechRecognizer.supportedLocales(); + let currentLocale = Locale.current + if let idName = buildIdNameForLocale(forIdentifier: currentLocale.identifier ) { + localeNames.append(idName) + } + for locale in locales { + if ( locale.identifier == currentLocale.identifier) { + continue + } + if let idName = buildIdNameForLocale(forIdentifier: locale.identifier ) { + localeNames.append(idName) + } + } + DispatchQueue.main.async { + result(localeNames) + } + } + + private func buildIdNameForLocale( forIdentifier: String ) -> String? { + var idName: String? + if let name = Locale.current.localizedString(forIdentifier: forIdentifier ) { + let sanitizedName = name.replacingOccurrences(of: ":", with: " ") + idName = "\(forIdentifier):\(sanitizedName)" + } + return idName + } + + private func handleResult( _ transcriptions: [SFTranscription], isFinal: Bool ) { + if ( !isFinal && !returnPartialResults ) { + return + } + var speechWords: [SpeechRecognitionWords] = [] + for transcription in transcriptions { + let words: SpeechRecognitionWords = SpeechRecognitionWords(recognizedWords: transcription.formattedString, confidence: confidenceIn( transcription)) + speechWords.append( words ) + } + let speechInfo = SpeechRecognitionResult(alternates: speechWords, finalResult: isFinal ) + do { + let speechMsg = try jsonEncoder.encode(speechInfo) + if let speechStr = String( data:speechMsg, encoding: .utf8) { + os_log("Encoded JSON result: %{PUBLIC}@", log: pluginLog, type: .debug, speechStr ) + invokeFlutter( SwiftSpeechToTextCallbackMethods.textRecognition, arguments: speechStr ) + } + } catch { + os_log("Could not encode JSON", log: pluginLog, type: .error) + } + } + + private func confidenceIn( _ transcription: SFTranscription ) -> Decimal { + guard ( transcription.segments.count > 0 ) else { + return 0; + } + var totalConfidence: Float = 0.0; + for segment in transcription.segments { + totalConfidence += segment.confidence + } + let avgConfidence: Float = totalConfidence / Float(transcription.segments.count ) + let confidence: Float = (avgConfidence * 1000).rounded() / 1000 + return Decimal( string: String( describing: confidence ) )! + } + + private func invokeFlutter( _ method: SwiftSpeechToTextCallbackMethods, arguments: Any? ) { + DispatchQueue.main.async { + self.channel.invokeMethod( method.rawValue, arguments: arguments ) + } + } + +} + +@available(iOS 10.0, *) +extension SwiftSpeechToTextPlugin : SFSpeechRecognizerDelegate { + public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { + let availability = available ? SpeechToTextStatus.available.rawValue : SpeechToTextStatus.unavailable.rawValue + os_log("Availability changed: %{PUBLIC}@", log: pluginLog, type: .debug, availability) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: availability ) + } +} + +@available(iOS 10.0, *) +extension SwiftSpeechToTextPlugin : SFSpeechRecognitionTaskDelegate { + public func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask) { + // Do nothing for now + } + + public func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask) { + reportError(source: "FinishedReadingAudio", error: task.error) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) + } + + public func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask) { + reportError(source: "TaskWasCancelled", error: task.error) + invokeFlutter( SwiftSpeechToTextCallbackMethods.notifyStatus, arguments: SpeechToTextStatus.notListening.rawValue ) + } + + public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool) { + reportError(source: "FinishSuccessfully", error: task.error) + stopCurrentListen( ) + } + + public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription) { + reportError(source: "HypothesizeTranscription", error: task.error) + handleResult( [transcription], isFinal: false ) + } + + public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult) { + reportError(source: "FinishRecognition", error: task.error) + let isFinal = recognitionResult.isFinal + handleResult( recognitionResult.transcriptions, isFinal: isFinal ) + } + + private func reportError( source: String, error: Error?) { + if ( nil != error) { + os_log("%{PUBLIC}@ with error: %{PUBLIC}@", log: pluginLog, type: .debug, source, error.debugDescription) + } + } +} + +@available(iOS 10.0, *) +extension SwiftSpeechToTextPlugin : AVAudioPlayerDelegate { + + public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, + successfully flag: Bool) { + if let playEnd = self.onPlayEnd { + playEnd() + } + } +} diff --git a/speech_to_text_/ios/speech_to_text.podspec b/speech_to_text_/ios/speech_to_text.podspec new file mode 100644 index 00000000..1db79aa0 --- /dev/null +++ b/speech_to_text_/ios/speech_to_text.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'speech_to_text' + s.version = '0.0.1' + s.summary = 'A new flutter plugin project.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.dependency 'Try' + + s.ios.deployment_target = '8.0' +end + diff --git a/speech_to_text_/lib/speech_recognition_error.dart b/speech_to_text_/lib/speech_recognition_error.dart new file mode 100644 index 00000000..2ab6cd4d --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_error.dart @@ -0,0 +1,44 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'speech_recognition_error.g.dart'; + +/// A single error returned from the underlying speech services. +/// +/// Errors are either transient or permanent. Permanent errors +/// block speech recognition from continuing and must be +/// addressed before recogntion will work. Transient errors +/// cause individual recognition sessions to fail but subsequent +/// attempts may well succeed. +@JsonSerializable() +class SpeechRecognitionError { + /// Use this to differentiate the various error conditions. + /// + /// Not meant for display to the user. + final String errorMsg; + + /// True means that recognition cannot continue until + /// the error is resolved. + final bool permanent; + + SpeechRecognitionError(this.errorMsg, this.permanent); + + factory SpeechRecognitionError.fromJson(Map json) => + _$SpeechRecognitionErrorFromJson(json); + Map toJson() => _$SpeechRecognitionErrorToJson(this); + + @override + String toString() { + return "SpeechRecognitionError msg: $errorMsg, permanent: $permanent"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionError && + errorMsg == other.errorMsg && + permanent == other.permanent; + } + + @override + int get hashCode => errorMsg.hashCode; +} diff --git a/speech_to_text_/lib/speech_recognition_error.g.dart b/speech_to_text_/lib/speech_recognition_error.g.dart new file mode 100644 index 00000000..65299f6d --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_error.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'speech_recognition_error.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SpeechRecognitionError _$SpeechRecognitionErrorFromJson( + Map json) { + return SpeechRecognitionError( + json['errorMsg'] as String, + json['permanent'] as bool, + ); +} + +Map _$SpeechRecognitionErrorToJson( + SpeechRecognitionError instance) => + { + 'errorMsg': instance.errorMsg, + 'permanent': instance.permanent, + }; diff --git a/speech_to_text_/lib/speech_recognition_event.dart b/speech_to_text_/lib/speech_recognition_event.dart new file mode 100644 index 00000000..71729365 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_event.dart @@ -0,0 +1,30 @@ +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +enum SpeechRecognitionEventType { + finalRecognitionEvent, + partialRecognitionEvent, + errorEvent, + statusChangeEvent, + soundLevelChangeEvent, +} + +/// A single event in a stream of speech recognition events. +/// +/// Use [eventType] to determine what type of event it is and depending on that +/// use the other properties to get information about it. +class SpeechRecognitionEvent { + final SpeechRecognitionEventType eventType; + final SpeechRecognitionError _error; + final SpeechRecognitionResult _result; + final bool _listening; + final double _level; + + SpeechRecognitionEvent( + this.eventType, this._result, this._error, this._listening, this._level); + + bool get isListening => _listening; + double get level => _level; + SpeechRecognitionResult get recognitionResult => _result; + SpeechRecognitionError get error => _error; +} diff --git a/speech_to_text_/lib/speech_recognition_result.dart b/speech_to_text_/lib/speech_recognition_result.dart new file mode 100644 index 00000000..38509f65 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_result.dart @@ -0,0 +1,140 @@ +import 'dart:collection'; + +import 'package:json_annotation/json_annotation.dart'; + +part 'speech_recognition_result.g.dart'; + +/// A sequence of recognized words from the speech recognition +/// service. +/// +/// Depending on the platform behaviour the words may come in all +/// at once at the end or as partial results as each word is +/// recognized. Use the [finalResult] flag to determine if the +/// result is considered final by the platform. +@JsonSerializable(explicitToJson: true) +class SpeechRecognitionResult { + List _alternates; + + /// Returns a list of possible transcriptions of the speech. + /// + /// The first value is always the same as the [recognizedWords] + /// value. Use the confidence for each alternate transcription + /// to determine how likely it is. Note that not all platforms + /// do a good job with confidence, there are convenience methods + /// on [SpeechRecogntionWords] to work with possibly missing + /// confidence values. + List get alternates => + UnmodifiableListView(_alternates); + + /// The sequence of words that is the best transcription of + /// what was said. + /// + /// This is the same as the first value of [alternates]. + String get recognizedWords => + _alternates.isNotEmpty ? _alternates.first.recognizedWords : ""; + + /// False means the words are an interim result, true means + /// they are the final recognition. + final bool finalResult; + + /// The confidence that the [recognizedWords] are correct. + /// + /// Confidence is expressed as a value between 0 and 1. -1 + /// means that the confidence value was not available. + double get confidence => + _alternates.isNotEmpty ? _alternates.first.confidence : 0; + + /// true if there is confidence in this recognition, false otherwise. + /// + /// There are two separate ways for there to be confidence, the first + /// is if the confidence is missing, which is indicated by a value of + /// -1. The second is if the confidence is greater than or equal + /// [threshold]. If [threshold] is not provided it defaults to 0.8. + bool isConfident( + {double threshold = SpeechRecognitionWords.confidenceThreshold}) => + _alternates.isNotEmpty + ? _alternates.first.isConfident(threshold: threshold) + : false; + + /// true if [confidence] is not the [missingConfidence] value, false + /// otherwise. + bool get hasConfidenceRating => + _alternates.isNotEmpty ? _alternates.first.hasConfidenceRating : false; + + SpeechRecognitionResult(this._alternates, this.finalResult); + + @override + String toString() { + return "SpeechRecognitionResult words: $_alternates, final: $finalResult"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionResult && + recognizedWords == other.recognizedWords && + finalResult == other.finalResult; + } + + @override + int get hashCode => recognizedWords.hashCode; + + factory SpeechRecognitionResult.fromJson(Map json) => + _$SpeechRecognitionResultFromJson(json); + Map toJson() => _$SpeechRecognitionResultToJson(this); +} + +/// A set of words recognized in a [SpeechRecognitionResult]. +/// +/// Each result will have one or more [SpeechRecognitionWords] +/// with a varying degree of confidence about each set of words. +@JsonSerializable() +class SpeechRecognitionWords { + /// The sequence of words recognized + final String recognizedWords; + + /// The confidence that the [recognizedWords] are correct. + /// + /// Confidence is expressed as a value between 0 and 1. 0 + /// means that the confidence value was not available. Use + /// [isConfident] which will ignore 0 values automatically. + final double confidence; + + static const double confidenceThreshold = 0.8; + static const double missingConfidence = -1; + + const SpeechRecognitionWords(this.recognizedWords, this.confidence); + + /// true if there is confidence in this recognition, false otherwise. + /// + /// There are two separate ways for there to be confidence, the first + /// is if the confidence is missing, which is indicated by a value of + /// -1. The second is if the confidence is greater than or equal + /// [threshold]. If [threshold] is not provided it defaults to 0.8. + bool isConfident({double threshold = confidenceThreshold}) => + confidence == missingConfidence || confidence >= threshold; + + /// true if [confidence] is not the [missingConfidence] value, false + /// otherwise. + bool get hasConfidenceRating => confidence != missingConfidence; + + @override + String toString() { + return "SpeechRecognitionWords words: $recognizedWords, confidence: $confidence"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionWords && + recognizedWords == other.recognizedWords && + confidence == other.confidence; + } + + @override + int get hashCode => recognizedWords.hashCode; + + factory SpeechRecognitionWords.fromJson(Map json) => + _$SpeechRecognitionWordsFromJson(json); + Map toJson() => _$SpeechRecognitionWordsToJson(this); +} diff --git a/speech_to_text_/lib/speech_recognition_result.g.dart b/speech_to_text_/lib/speech_recognition_result.g.dart new file mode 100644 index 00000000..023e5485 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_result.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'speech_recognition_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SpeechRecognitionResult _$SpeechRecognitionResultFromJson( + Map json) { + return SpeechRecognitionResult( + (json['alternates'] as List) + ?.map((e) => e == null + ? null + : SpeechRecognitionWords.fromJson(e as Map)) + ?.toList(), + json['finalResult'] as bool, + ); +} + +Map _$SpeechRecognitionResultToJson( + SpeechRecognitionResult instance) => + { + 'alternates': instance.alternates?.map((e) => e?.toJson())?.toList(), + 'finalResult': instance.finalResult, + }; + +SpeechRecognitionWords _$SpeechRecognitionWordsFromJson( + Map json) { + return SpeechRecognitionWords( + json['recognizedWords'] as String, + (json['confidence'] as num)?.toDouble(), + ); +} + +Map _$SpeechRecognitionWordsToJson( + SpeechRecognitionWords instance) => + { + 'recognizedWords': instance.recognizedWords, + 'confidence': instance.confidence, + }; diff --git a/speech_to_text_/lib/speech_to_text.dart b/speech_to_text_/lib/speech_to_text.dart new file mode 100644 index 00000000..343706e6 --- /dev/null +++ b/speech_to_text_/lib/speech_to_text.dart @@ -0,0 +1,511 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:math'; + +import 'package:clock/clock.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +enum ListenMode { + deviceDefault, + dictation, + search, + confirmation, +} + +/// Notified as words are recognized with the current set of recognized words. +/// +/// See the [onResult] argument on the [listen] method for use. +typedef SpeechResultListener = void Function(SpeechRecognitionResult result); + +/// Notified if errors occur during recognition or intialization. +/// +/// Possible errors per the Android docs are described here: +/// https://developer.android.com/reference/android/speech/SpeechRecognizer +/// "error_audio_error" +/// "error_client" +/// "error_permission" +/// "error_network" +/// "error_network_timeout" +/// "error_no_match" +/// "error_busy" +/// "error_server" +/// "error_speech_timeout" +/// See the [onError] argument on the [initialize] method for use. +typedef SpeechErrorListener = void Function( + SpeechRecognitionError errorNotification); + +/// Notified when recognition status changes. +/// +/// See the [onStatus] argument on the [initialize] method for use. +typedef SpeechStatusListener = void Function(String status); + +/// Notified when the sound level changes during a listen method. +/// +/// [level] is a measure of the decibels of the current sound on +/// the recognition input. See the [onSoundLevelChange] argument on +/// the [listen] method for use. +typedef SpeechSoundLevelChange = Function(double level); + +/// An interface to device specific speech recognition services. +/// +/// The general flow of a speech recognition session is as follows: +/// ```Dart +/// SpeechToText speech = SpeechToText(); +/// bool isReady = await speech.initialize(); +/// if ( isReady ) { +/// await speech.listen( resultListener: resultListener ); +/// } +/// ... +/// // At some point later +/// speech.stop(); +/// ``` +class SpeechToText { + static const String listenMethod = 'listen'; + static const String textRecognitionMethod = 'textRecognition'; + static const String notifyErrorMethod = 'notifyError'; + static const String notifyStatusMethod = 'notifyStatus'; + static const String soundLevelChangeMethod = "soundLevelChange"; + static const String notListeningStatus = "notListening"; + static const String listeningStatus = "listening"; + + static const MethodChannel speechChannel = + const MethodChannel('plugin.csdcorp.com/speech_to_text'); + static final SpeechToText _instance = + SpeechToText.withMethodChannel(speechChannel); + bool _initWorked = false; + bool _recognized = false; + bool _listening = false; + bool _cancelOnError = false; + bool _partialResults = false; + int _listenStartedAt = 0; + int _lastSpeechEventAt = 0; + Duration _pauseFor; + Duration _listenFor; + + /// True if not listening or the user called cancel / stop, false + /// if cancel/stop were invoked by timeout or error condition. + bool _userEnded = false; + String _lastRecognized = ""; + String _lastStatus = ""; + double _lastSoundLevel = 0; + Timer _listenTimer; + LocaleName _systemLocale; + SpeechRecognitionError _lastError; + SpeechResultListener _resultListener; + SpeechErrorListener errorListener; + SpeechStatusListener statusListener; + SpeechSoundLevelChange _soundLevelChange; + + final MethodChannel channel; + factory SpeechToText() => _instance; + + @visibleForTesting + SpeechToText.withMethodChannel(this.channel); + + /// True if words have been recognized during the current [listen] call. + /// + /// Goes false as soon as [cancel] is called. + bool get hasRecognized => _recognized; + + /// The last set of recognized words received. + /// + /// This is maintained across [cancel] calls but cleared on the next + /// [listen]. + String get lastRecognizedWords => _lastRecognized; + + /// The last status update received, see [initialize] to register + /// an optional listener to be notified when this changes. + String get lastStatus => _lastStatus; + + /// The last sound level received during a listen event. + /// + /// The sound level is a measure of how loud the current + /// input is during listening. Use the [onSoundLevelChange] + /// argument in the [listen] method to get notified of + /// changes. + double get lastSoundLevel => _lastSoundLevel; + + /// True if [initialize] succeeded + bool get isAvailable => _initWorked; + + /// True if [listen] succeeded and [stop] or [cancel] has not been called. + /// + /// Also goes false when listening times out if listenFor was set. + bool get isListening => _listening; + bool get isNotListening => !isListening; + + /// The last error received or null if none, see [initialize] to + /// register an optional listener to be notified of errors. + SpeechRecognitionError get lastError => _lastError; + + /// True if an error has been received, see [lastError] for details + bool get hasError => null != lastError; + + /// Returns true if the user has already granted permission to access the + /// microphone, does not prompt the user. + /// + /// This method can be called before [initialize] to check if permission + /// has already been granted. If this returns false then the [initialize] + /// call will prompt the user for permission if it is allowed to do so. + /// Note that applications cannot ask for permission again if the user has + /// denied them permission in the past. + Future get hasPermission async { + bool hasPermission = await channel.invokeMethod('has_permission'); + return hasPermission; + } + + /// Initialize speech recognition services, returns true if + /// successful, false if failed. + /// + /// This method must be called before any other speech functions. + /// If this method returns false no further [SpeechToText] methods + /// should be used. Should only be called once if successful but does protect + /// itself if called repeatedly. False usually means that the user has denied + /// permission to use speech. The usual option in that case is to give them + /// instructions on how to open system settings and grant permission. + /// + /// [onError] is an optional listener for errors like + /// timeout, or failure of the device speech recognition. + /// [onStatus] is an optional listener for status changes from + /// listening to not listening. + /// [debugLogging] controls whether there is detailed logging from the underlying + /// plugins. It is off by default, usually only useful for troubleshooting issues + /// with a paritcular OS version or device, fairly verbose + Future initialize( + {SpeechErrorListener onError, + SpeechStatusListener onStatus, + debugLogging = false}) async { + if (_initWorked) { + return Future.value(_initWorked); + } + errorListener = onError; + statusListener = onStatus; + channel.setMethodCallHandler(_handleCallbacks); + _initWorked = await channel + .invokeMethod('initialize', {"debugLogging": debugLogging}); + return _initWorked; + } + + /// Stops the current listen for speech if active, does nothing if not. + /// + /// Stopping a listen session will cause a final result to be sent. Each + /// listen session should be ended with either [stop] or [cancel], for + /// example in the dispose method of a Widget. [cancel] is automatically + /// invoked by a permanent error if [cancelOnError] is set to true in the + /// [listen] call. + /// + /// *Note:* Cannot be used until a successful [initialize] call. Should + /// only be used after a successful [listen] call. + Future stop() async { + _userEnded = true; + return _stop(); + } + + Future _stop() async { + if (!_initWorked) { + return; + } + _shutdownListener(); + await channel.invokeMethod('stop'); + } + + /// Cancels the current listen for speech if active, does nothing if not. + /// + /// Canceling means that there will be no final result returned from the + /// recognizer. Each listen session should be ended with either [stop] or + /// [cancel], for example in the dispose method of a Widget. [cancel] is + /// automatically invoked by a permanent error if [cancelOnError] is set + /// to true in the [listen] call. + /// + /// *Note* Cannot be used until a successful [initialize] call. Should only + /// be used after a successful [listen] call. + Future cancel() async { + _userEnded = true; + return _cancel(); + } + + Future _cancel() async { + if (!_initWorked) { + return; + } + _shutdownListener(); + await channel.invokeMethod('cancel'); + } + + /// Starts a listening session for speech and converts it to text, + /// invoking the provided [onResult] method as words are recognized. + /// + /// Cannot be used until a successful [initialize] call. There is a + /// time limit on listening imposed by both Android and iOS. The time + /// depends on the device, network, etc. Android is usually quite short, + /// especially if there is no active speech event detected, on the order + /// of ten seconds or so. + /// + /// When listening is done always invoke either [cancel] or [stop] to + /// end the session, even if it times out. [cancelOnError] provides an + /// automatic way to ensure this happens. + /// + /// [onResult] is an optional listener that is notified when words + /// are recognized. + /// + /// [listenFor] sets the maximum duration that it will listen for, after + /// that it automatically stops the listen for you. + /// + /// [pauseFor] sets the maximum duration of a pause in speech with no words + /// detected, after that it automatically stops the listen for you. + /// + /// [localeId] is an optional locale that can be used to listen in a language + /// other than the current system default. See [locales] to find the list of + /// supported languages for listening. + /// + /// [onSoundLevelChange] is an optional listener that is notified when the + /// sound level of the input changes. Use this to update the UI in response to + /// more or less input. The values currently differ between Ancroid and iOS, + /// haven't yet been able to determine from the Android documentation what the + /// value means. On iOS the value returned is in decibels. + /// + /// [cancelOnError] if true then listening is automatically canceled on a + /// permanent error. This defaults to false. When false cancel should be + /// called from the error handler. + /// + /// [partialResults] if true the listen reports results as they are recognized, + /// when false only final results are reported. Defaults to true. + /// + /// [onDevice] if true the listen attempts to recognize locally with speech never + /// leaving the device. If it cannot do this the listen attempt will fail. This is + /// usually only needed for sensitive content where privacy or security is a concern. + Future listen( + {SpeechResultListener onResult, + Duration listenFor, + Duration pauseFor, + String localeId, + SpeechSoundLevelChange onSoundLevelChange, + cancelOnError = false, + partialResults = true, + onDevice = false, + ListenMode listenMode = ListenMode.confirmation}) async { + if (!_initWorked) { + throw SpeechToTextNotInitializedException(); + } + _userEnded = false; + _cancelOnError = cancelOnError; + _recognized = false; + _resultListener = onResult; + _soundLevelChange = onSoundLevelChange; + _partialResults = partialResults; + Map listenParams = { + "partialResults": partialResults || null != pauseFor, + "onDevice": onDevice, + "listenMode": listenMode.index, + }; + if (null != localeId) { + listenParams["localeId"] = localeId; + } + try { + bool started = await channel.invokeMethod(listenMethod, listenParams); + if (started) { + _listenStartedAt = clock.now().millisecondsSinceEpoch; + _setupListenAndPause(pauseFor, listenFor); + } + } on PlatformException catch (e) { + throw ListenFailedException(e.details); + } + } + + void _setupListenAndPause(Duration pauseFor, Duration listenFor) { + _pauseFor = null; + _listenFor = null; + if (null == pauseFor && null == listenFor) { + return; + } + var minDuration; + if (null == pauseFor) { + _listenFor = Duration(milliseconds: listenFor.inMilliseconds); + minDuration = listenFor; + } else if (null == listenFor) { + _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); + minDuration = pauseFor; + } else { + _listenFor = Duration(milliseconds: listenFor.inMilliseconds); + _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); + var minMillis = min(listenFor.inMilliseconds - _elapsedListenMillis, + pauseFor.inMilliseconds); + minDuration = Duration(milliseconds: minMillis); + } + _listenTimer = Timer(minDuration, _stopOnPauseOrListen); + } + + int get _elapsedListenMillis => + clock.now().millisecondsSinceEpoch - _listenStartedAt; + int get _elapsedSinceSpeechEvent => + clock.now().millisecondsSinceEpoch - _lastSpeechEventAt; + + void _stopOnPauseOrListen() { + if (null != _listenFor && + _elapsedListenMillis >= _listenFor.inMilliseconds) { + _stop(); + } else if (null != _pauseFor && + _elapsedSinceSpeechEvent >= _pauseFor.inMilliseconds) { + _stop(); + } else { + _setupListenAndPause(_pauseFor, _listenFor); + } + } + + /// returns the list of speech locales available on the device. + /// + /// This method is useful to find the identifier to use + /// for the [listen] method, it is the [localeId] member of the + /// [LocaleName]. + /// + /// Each [LocaleName] in the returned list has the + /// identifier for the locale as well as a name for + /// display. The name is localized for the system locale on + /// the device. + Future> locales() async { + if (!_initWorked) { + throw SpeechToTextNotInitializedException(); + } + final List locales = await channel.invokeMethod('locales'); + List filteredLocales = locales + .map((locale) { + var components = locale.split(":"); + if (components.length != 2) { + return null; + } + return LocaleName(components[0], components[1]); + }) + .where((item) => item != null) + .toList(); + if (filteredLocales.isNotEmpty) { + _systemLocale = filteredLocales.first; + } else { + _systemLocale = null; + } + filteredLocales.sort((ln1, ln2) => ln1.name.compareTo(ln2.name)); + return filteredLocales; + } + + /// returns the locale that will be used if no localeId is passed + /// to the [listen] method. + Future systemLocale() async { + if (null == _systemLocale) { + await locales(); + } + return Future.value(_systemLocale); + } + + Future _handleCallbacks(MethodCall call) async { + // print("SpeechToText call: ${call.method} ${call.arguments}"); + switch (call.method) { + case textRecognitionMethod: + if (call.arguments is String) { + _onTextRecognition(call.arguments); + } + break; + case notifyErrorMethod: + if (call.arguments is String) { + await _onNotifyError(call.arguments); + } + break; + case notifyStatusMethod: + if (call.arguments is String) { + _onNotifyStatus(call.arguments); + } + break; + case soundLevelChangeMethod: + if (call.arguments is double) { + _onSoundLevelChange(call.arguments); + } + break; + default: + } + } + + void _onTextRecognition(String resultJson) { + _lastSpeechEventAt = clock.now().millisecondsSinceEpoch; + Map resultMap = jsonDecode(resultJson); + SpeechRecognitionResult speechResult = + SpeechRecognitionResult.fromJson(resultMap); + if (!_partialResults && !speechResult.finalResult) { + return; + } + _recognized = true; + // print("Recognized text $resultJson"); + + _lastRecognized = speechResult.recognizedWords; + if (null != _resultListener) { + _resultListener(speechResult); + } + } + + Future _onNotifyError(String errorJson) async { + if (isNotListening && _userEnded) { + return; + } + Map errorMap = jsonDecode(errorJson); + SpeechRecognitionError speechError = + SpeechRecognitionError.fromJson(errorMap); + _lastError = speechError; + if (null != errorListener) { + errorListener(speechError); + } + if (_cancelOnError && speechError.permanent) { + await _cancel(); + } + } + + void _onNotifyStatus(String status) { + _lastStatus = status; + _listening = status == listeningStatus; + // print(status); + if (null != statusListener) { + statusListener(status); + } + } + + void _onSoundLevelChange(double level) { + if (isNotListening) { + return; + } + _lastSoundLevel = level; + if (null != _soundLevelChange) { + _soundLevelChange(level); + } + } + + _shutdownListener() { + _listening = false; + _recognized = false; + _listenTimer?.cancel(); + _listenTimer = null; + } + + @visibleForTesting + Future processMethodCall(MethodCall call) async { + return await _handleCallbacks(call); + } +} + +/// A single locale with a [name], localized to the current system locale, +/// and a [localeId] which can be used in the [listen] method to choose a +/// locale for speech recognition. +class LocaleName { + final String localeId; + final String name; + LocaleName(this.localeId, this.name); +} + +/// Thrown when a method is called that requires successful +/// initialization first. +class SpeechToTextNotInitializedException implements Exception {} + +/// Thrown when listen fails to properly start a speech listening session +/// on the device +class ListenFailedException implements Exception { + final String details; + ListenFailedException(this.details); +} diff --git a/speech_to_text_/lib/speech_to_text_provider.dart b/speech_to_text_/lib/speech_to_text_provider.dart new file mode 100644 index 00000000..91adf3b4 --- /dev/null +++ b/speech_to_text_/lib/speech_to_text_provider.dart @@ -0,0 +1,201 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_event.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +/// Simplifies interaction with [SpeechToText] by handling all the callbacks and notifying +/// listeners as events happen. +/// +/// Here's an example of using the [SpeechToTextProvider] +/// ``` +/// var speechProvider = SpeechToTextProvider( SpeechToText()); +/// var available = await speechProvider.initialize(); +/// StreamSubscription _subscription; +/// _subscription = speechProvider.recognitionController.stream.listen((recognitionEvent) { +/// if (recognitionEvent.eventType == SpeechRecognitionEventType.finalRecognitionEvent ) { +/// print("I heard: ${recognitionEvent.recognitionResult.recognizedWords}"); +/// } +/// }); +/// speechProvider.addListener(() { +/// var words = speechProvider.lastWords; +/// }); +class SpeechToTextProvider extends ChangeNotifier { + final StreamController _recognitionController = + StreamController.broadcast(); + final SpeechToText _speechToText; + SpeechRecognitionResult _lastResult; + double _lastLevel = 0; + List _locales = []; + LocaleName _systemLocale; + + /// Only construct one instance in an application. + /// + /// Do not call `initialize` on the [SpeechToText] that is passed as a parameter, instead + /// call the [initialize] method on this class. + SpeechToTextProvider(this._speechToText); + + Stream get stream => _recognitionController.stream; + + /// Returns the last result received, may be null. + SpeechRecognitionResult get lastResult => _lastResult; + + /// Returns the last error received, may be null. + SpeechRecognitionError get lastError => _speechToText.lastError; + + /// Returns the last sound level received. + /// + /// Note this is only available when the `soundLevel` is set to true on + /// a call to [listen], will be 0 at all other times. + double get lastLevel => _lastLevel; + + /// Initializes the provider and the contained [SpeechToText] instance. + /// + /// Returns true if [SpeechToText] was initialized successful and can now + /// be used, false otherwse. + Future initialize() async { + if (isAvailable) { + return isAvailable; + } + bool availableBefore = _speechToText.isAvailable; + bool available = + await _speechToText.initialize(onStatus: _onStatus, onError: _onError); + if (available) { + _locales = []; + _locales.addAll(await _speechToText.locales()); + _systemLocale = await _speechToText.systemLocale(); + } + if (availableBefore != available) { + notifyListeners(); + } + return available; + } + + /// Returns true if the provider has been initialized and can be used to recognize speech. + bool get isAvailable => _speechToText.isAvailable; + + /// Returns true if the provider cannot be used to recognize speech, either because it has not + /// yet been initialized or because initialization failed. + bool get isNotAvailable => !_speechToText.isAvailable; + + /// Returns true if [SpeechToText] is listening for new speech. + bool get isListening => _speechToText.isListening; + + /// Returns true if [SpeechToText] is not listening for new speech. + bool get isNotListening => _speechToText.isNotListening; + + /// Returns true if [SpeechToText] has a previous error. + bool get hasError => _speechToText.hasError; + + /// Returns true if [lastResult] has a last result. + bool get hasResults => null != _lastResult; + + /// Returns the list of locales that are available on the device for speech recognition. + List get locales => _locales; + + /// Returns the locale that is currently set as active on the device. + LocaleName get systemLocale => _systemLocale; + + /// Start listening for new events, set [partialResults] to true to receive interim + /// recognition results. + /// + /// [soundLevel] set to true to be notified on changes to the input sound level + /// on the microphone. + /// + /// [listenFor] sets the maximum duration that it will listen for, after + /// that it automatically stops the listen for you. + /// + /// [pauseFor] sets the maximum duration of a pause in speech with no words + /// detected, after that it automatically stops the listen for you. + /// + /// Call this only after a successful [initialize] call + void listen( + {bool partialResults = false, + bool soundLevel = false, + Duration listenFor, + Duration pauseFor}) { + _lastLevel = 0; + _lastResult = null; + if (soundLevel) { + _speechToText.listen( + partialResults: partialResults, + listenFor: listenFor, + pauseFor: pauseFor, + cancelOnError: true, + onResult: _onListenResult, + // onSoundLevelChange: _onSoundLevelChange); + ); + } else { + _speechToText.listen( + partialResults: partialResults, + listenFor: listenFor, + pauseFor: pauseFor, + cancelOnError: true, + onResult: _onListenResult); + } + } + + /// Stops a current active listening session. + /// + /// Call this after calling [listen] to stop the recognizer from listening further + /// and return the current result as final. + void stop() { + _speechToText.stop(); + notifyListeners(); + } + + /// Cancel a current active listening session. + /// + /// Call this after calling [listen] to stop the recognizer from listening further + /// and ignore any results recognized so far. + void cancel() { + _speechToText.cancel(); + notifyListeners(); + } + + void _onError(SpeechRecognitionError errorNotification) { + _recognitionController.add(SpeechRecognitionEvent( + SpeechRecognitionEventType.errorEvent, + null, + errorNotification, + isListening, + null)); + notifyListeners(); + } + + void _onStatus(String status) { + _recognitionController.add(SpeechRecognitionEvent( + SpeechRecognitionEventType.statusChangeEvent, + null, + null, + isListening, + null)); + notifyListeners(); + } + + void _onListenResult(SpeechRecognitionResult result) { + _lastResult = result; + _recognitionController.add(SpeechRecognitionEvent( + result.finalResult + ? SpeechRecognitionEventType.finalRecognitionEvent + : SpeechRecognitionEventType.partialRecognitionEvent, + result, + null, + isListening, + null)); + notifyListeners(); + } + + // void _onSoundLevelChange(double level) { + // _lastLevel = level; + // _recognitionController.add(SpeechRecognitionEvent( + // SpeechRecognitionEventType.soundLevelChangeEvent, + // null, + // null, + // null, + // level)); + // notifyListeners(); + // } +} diff --git a/speech_to_text_/pubspec.yaml b/speech_to_text_/pubspec.yaml new file mode 100644 index 00000000..34b3da29 --- /dev/null +++ b/speech_to_text_/pubspec.yaml @@ -0,0 +1,31 @@ +name: speech_to_text +description: A Flutter plugin that exposes device specific speech to text recognition capability. + + + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.10.0" + +dependencies: + flutter: + sdk: flutter + json_annotation: ^3.0.0 + clock: ^1.0.1 + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^1.0.0 + json_serializable: ^3.0.0 + fake_async: ^1.0.1 + +flutter: + plugin: + platforms: + android: + package: com.csdcorp.speech_to_text + pluginClass: SpeechToTextPlugin + ios: + pluginClass: SpeechToTextPlugin + diff --git a/speech_to_text_/test/speech_recognition_error_test.dart b/speech_to_text_/test/speech_recognition_error_test.dart new file mode 100644 index 00000000..202ae4cd --- /dev/null +++ b/speech_to_text_/test/speech_recognition_error_test.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; + +void main() { + const String msg1 = "msg1"; + + setUp(() {}); + + group('properties', () { + test('equals true for same object', () { + SpeechRecognitionError error = SpeechRecognitionError(msg1, false); + expect(error, error); + }); + test('equals true for different object same values', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); + expect(error1, error2); + }); + test('equals false for different object', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); + expect(error1, isNot(error2)); + }); + test('hash same for same object', () { + SpeechRecognitionError error = SpeechRecognitionError(msg1, false); + expect(error.hashCode, error.hashCode); + }); + test('hash same for different object same values', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); + expect(error1.hashCode, error2.hashCode); + }); + test('hash different for different object', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); + expect(error1.hashCode, isNot(error2.hashCode)); + }); + test('toString as expected', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + expect(error1.toString(), + "SpeechRecognitionError msg: $msg1, permanent: false"); + }); + }); + group('json', () { + test('loads properly', () { + var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); + SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); + expect(error.errorMsg, msg1); + expect(error.permanent, isTrue); + json = jsonDecode('{"errorMsg":"$msg1","permanent":false}'); + error = SpeechRecognitionError.fromJson(json); + expect(error.permanent, isFalse); + }); + test('roundtrips properly', () { + var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); + SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); + var roundtripJson = error.toJson(); + SpeechRecognitionError roundtripError = + SpeechRecognitionError.fromJson(roundtripJson); + expect(error, roundtripError); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognition_event_test.dart b/speech_to_text_/test/speech_recognition_event_test.dart new file mode 100644 index 00000000..ceaaab8a --- /dev/null +++ b/speech_to_text_/test/speech_recognition_event_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_event.dart'; + +import 'test_speech_channel_handler.dart'; + +void main() { + group('properties', () { + test('status listening matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.statusChangeEvent, null, null, true, null); + expect(event.eventType, SpeechRecognitionEventType.statusChangeEvent); + expect(event.isListening, isTrue); + }); + test('result matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.finalRecognitionEvent, + TestSpeechChannelHandler.firstRecognizedResult, + null, + null, + null); + expect(event.eventType, SpeechRecognitionEventType.finalRecognitionEvent); + expect(event.recognitionResult, + TestSpeechChannelHandler.firstRecognizedResult); + }); + test('error matches', () { + var event = SpeechRecognitionEvent(SpeechRecognitionEventType.errorEvent, + null, TestSpeechChannelHandler.firstError, null, null); + expect(event.eventType, SpeechRecognitionEventType.errorEvent); + expect(event.error, TestSpeechChannelHandler.firstError); + }); + test('sound level matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.soundLevelChangeEvent, + null, + null, + null, + TestSpeechChannelHandler.level1); + expect(event.eventType, SpeechRecognitionEventType.soundLevelChangeEvent); + expect(event.level, TestSpeechChannelHandler.level1); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognition_result_test.dart b/speech_to_text_/test/speech_recognition_result_test.dart new file mode 100644 index 00000000..1516779a --- /dev/null +++ b/speech_to_text_/test/speech_recognition_result_test.dart @@ -0,0 +1,134 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +void main() { + final String firstRecognizedWords = 'hello'; + final String secondRecognizedWords = 'hello there'; + final double firstConfidence = 0.85; + final double secondConfidence = 0.62; + final String firstRecognizedJson = + '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; + final String secondRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; + final SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + final SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + + setUp(() {}); + + group('recognizedWords', () { + test('empty if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.recognizedWords, isEmpty); + }); + test('matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.recognizedWords, firstRecognizedWords); + }); + }); + group('alternates', () { + test('empty if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.alternates, isEmpty); + }); + test('expected contents', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.alternates, contains(firstWords)); + expect(result.alternates, contains(secondWords)); + }); + test('in order', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.alternates.first, firstWords); + }); + }); + group('confidence', () { + test('0 if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.confidence, 0); + }); + test('isConfident false if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.isConfident(), isFalse); + }); + test('isConfident matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.isConfident(), firstWords.isConfident()); + }); + test('hasConfidenceRating false if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.hasConfidenceRating, isFalse); + }); + test('hasConfidenceRating matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.hasConfidenceRating, firstWords.hasConfidenceRating); + }); + }); + group('json', () { + test('loads correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); + expect(result.recognizedWords, firstRecognizedWords); + expect(result.confidence, firstConfidence); + }); + test('roundtrips correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); + var roundTripJson = result.toJson(); + SpeechRecognitionResult roundtripResult = + SpeechRecognitionResult.fromJson(roundTripJson); + expect(result, roundtripResult); + }); + }); + group('overrides', () { + test('toString works with no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect( + result.toString(), "SpeechRecognitionResult words: [], final: true"); + }); + test('toString works with alternates', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result.toString(), + "SpeechRecognitionResult words: [SpeechRecognitionWords words: hello, confidence: 0.85], final: true"); + }); + test('hash same for same object', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result.hashCode, result.hashCode); + }); + test('hash differs for different objects', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result2 = + SpeechRecognitionResult([secondWords], true); + expect(result1.hashCode, isNot(result2.hashCode)); + }); + test('equals same for same object', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result, result); + }); + test('equals same for different object same values', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result1a = + SpeechRecognitionResult([firstWords], true); + expect(result1, result1a); + }); + test('equals differs for different objects', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result2 = + SpeechRecognitionResult([secondWords], true); + expect(result1, isNot(result2)); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognitions_words_test.dart b/speech_to_text_/test/speech_recognitions_words_test.dart new file mode 100644 index 00000000..36a9ef0e --- /dev/null +++ b/speech_to_text_/test/speech_recognitions_words_test.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +void main() { + final String firstRecognizedWords = 'hello'; + final String secondRecognizedWords = 'hello there'; + final double firstConfidence = 0.85; + final double secondConfidence = 0.62; + final String firstRecognizedJson = + '{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}'; + final SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + final SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + + setUp(() {}); + + group('properties', () { + test('words', () { + expect(firstWords.recognizedWords, firstRecognizedWords); + expect(secondWords.recognizedWords, secondRecognizedWords); + }); + test('confidence', () { + expect(firstWords.confidence, firstConfidence); + expect(secondWords.confidence, secondConfidence); + expect(firstWords.hasConfidenceRating, isTrue); + }); + test('equals true for same object', () { + expect(firstWords, firstWords); + }); + test('equals true for different object with same values', () { + SpeechRecognitionWords firstWordsA = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + expect(firstWords, firstWordsA); + }); + test('equals false for different results', () { + expect(firstWords, isNot(secondWords)); + }); + test('hash same for same object', () { + expect(firstWords.hashCode, firstWords.hashCode); + }); + test('hash same for different object with same values', () { + SpeechRecognitionWords firstWordsA = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + expect(firstWords.hashCode, firstWordsA.hashCode); + }); + test('hash different for different results', () { + expect(firstWords.hashCode, isNot(secondWords.hashCode)); + }); + }); + group('isConfident', () { + test('true when >= 0.8', () { + expect(firstWords.isConfident(), isTrue); + }); + test('false when < 0.8', () { + expect(secondWords.isConfident(), isFalse); + }); + test('respects threshold', () { + expect(secondWords.isConfident(threshold: 0.5), isTrue); + }); + test('true when missing', () { + SpeechRecognitionWords words = SpeechRecognitionWords( + firstRecognizedWords, SpeechRecognitionWords.missingConfidence); + expect(words.isConfident(), isTrue); + expect(words.hasConfidenceRating, isFalse); + }); + }); + group('json', () { + test('loads correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); + expect(words.recognizedWords, firstRecognizedWords); + expect(words.confidence, firstConfidence); + }); + test('roundtrips correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); + var roundTripJson = words.toJson(); + SpeechRecognitionWords roundtripWords = + SpeechRecognitionWords.fromJson(roundTripJson); + expect(words, roundtripWords); + }); + }); +} diff --git a/speech_to_text_/test/speech_to_text_provider_test.dart b/speech_to_text_/test/speech_to_text_provider_test.dart new file mode 100644 index 00000000..25366b6f --- /dev/null +++ b/speech_to_text_/test/speech_to_text_provider_test.dart @@ -0,0 +1,196 @@ +import 'package:fake_async/fake_async.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_to_text_provider.dart'; + +import 'test_speech_channel_handler.dart'; +import 'test_speech_listener.dart'; + +void main() { + SpeechToTextProvider provider; + SpeechToText speechToText; + TestSpeechChannelHandler speechHandler; + TestSpeechListener speechListener; + + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + speechToText = SpeechToText.withMethodChannel(SpeechToText.speechChannel); + speechHandler = TestSpeechChannelHandler(speechToText); + speechToText.channel + .setMockMethodCallHandler(speechHandler.methodCallHandler); + provider = SpeechToTextProvider(speechToText); + speechListener = TestSpeechListener(provider); + provider.addListener(speechListener.onNotify); + }); + + tearDown(() { + speechToText.channel.setMockMethodCallHandler(null); + }); + + group('delegates', () { + test('isListening matches delegate defaults', () { + expect(provider.isListening, speechToText.isListening); + expect(provider.isNotListening, speechToText.isNotListening); + }); + test('isAvailable matches delegate defaults', () { + expect(provider.isAvailable, speechToText.isAvailable); + expect(provider.isNotAvailable, !speechToText.isAvailable); + }); + test('isAvailable matches delegate after init', () async { + expect(await provider.initialize(), isTrue); + expect(provider.isAvailable, speechToText.isAvailable); + expect(provider.isNotAvailable, !speechToText.isAvailable); + }); + test('hasError matches delegate after error', () async { + expect(await provider.initialize(), isTrue); + expect(provider.hasError, speechToText.hasError); + }); + }); + group('listening', () { + test('notifies on initialize', () async { + fakeAsync((fa) { + provider.initialize(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isAvailable, isTrue); + }); + }); + test('notifies on listening', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isTrue); + expect(provider.hasResults, isFalse); + }); + }); + test('notifies on final words', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + speechListener.reset(); + speechHandler.notifyFinalWords(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(provider.hasResults, isTrue); + var result = speechListener.recognitionResult; + expect(result.recognizedWords, + TestSpeechChannelHandler.secondRecognizedWords); + expect(result.finalResult, isTrue); + }); + }); + test('hasResult false after listening before new results', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + speechHandler.notifyFinalWords(); + provider.stop(); + setupForListen(provider, fa, speechListener); + fa.flushMicrotasks(); + expect(provider.hasResults, isFalse); + }); + }); + test('notifies on partial words', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, partialResults: true); + speechListener.reset(); + speechHandler.notifyPartialWords(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(provider.hasResults, isTrue); + var result = speechListener.recognitionResult; + expect(result.recognizedWords, + TestSpeechChannelHandler.firstRecognizedWords); + expect(result.finalResult, isFalse); + }); + }); + }); + group('soundLevel', () { + test('notifies when requested', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, + partialResults: true, soundLevel: true); + speechListener.reset(); + speechHandler.notifySoundLevel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.soundLevel, TestSpeechChannelHandler.level2); + }); + }); + test('no notification by default', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, + partialResults: true, soundLevel: false); + speechListener.reset(); + speechHandler.notifySoundLevel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isFalse); + expect(speechListener.soundLevel, 0); + }); + }); + }); + group('stop/cancel', () { + test('notifies on stop', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + provider.stop(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isFalse); + }); + }); + test('notifies on cancel', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + provider.cancel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isFalse); + }); + }); + }); + group('error handling', () { + test('hasError matches delegate default', () async { + expect(await provider.initialize(), isTrue); + expect(provider.hasError, speechToText.hasError); + }); + test('notifies on error', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + speechHandler.notifyPermanentError(); + expect(speechListener.notified, isTrue); + expect(speechListener.hasError, isTrue); + }); + }); + }); + group('locale', () { + test('locales empty before init', () async { + expect(provider.systemLocale, isNull); + expect(provider.locales, isEmpty); + }); + test('set from SpeechToText after init', () async { + fakeAsync((fa) { + speechHandler.setupLocales(); + provider.initialize(); + fa.flushMicrotasks(); + expect( + provider.systemLocale.localeId, TestSpeechChannelHandler.localeId1); + expect(provider.locales, hasLength(speechHandler.locales.length)); + }); + }); + }); +} + +void setupForListen(SpeechToTextProvider provider, FakeAsync fa, + TestSpeechListener speechListener, + {bool partialResults = false, bool soundLevel = false}) { + provider.initialize(); + fa.flushMicrotasks(); + speechListener.reset(); + provider.listen(partialResults: partialResults, soundLevel: soundLevel); + fa.flushMicrotasks(); +} diff --git a/speech_to_text_/test/speech_to_text_test.dart b/speech_to_text_/test/speech_to_text_test.dart new file mode 100644 index 00000000..7b4701ff --- /dev/null +++ b/speech_to_text_/test/speech_to_text_test.dart @@ -0,0 +1,425 @@ +import 'package:fake_async/fake_async.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +import 'test_speech_channel_handler.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + TestSpeechListener listener; + TestSpeechChannelHandler speechHandler; + SpeechToText speech; + + setUp(() { + listener = TestSpeechListener(); + speech = SpeechToText.withMethodChannel(SpeechToText.speechChannel); + speechHandler = TestSpeechChannelHandler(speech); + speech.channel.setMockMethodCallHandler(speechHandler.methodCallHandler); + }); + + tearDown(() { + speech.channel.setMockMethodCallHandler(null); + }); + + group('hasPermission', () { + test('true if platform reports true', () async { + expect(await speech.hasPermission, true); + }); + test('false if platform reports false', () async { + speechHandler.hasPermissionResult = false; + expect(await speech.hasPermission, false); + }); + }); + group('init', () { + test('succeeds on platform success', () async { + expect(await speech.initialize(), true); + expect(speechHandler.initInvoked, true); + expect(speech.isAvailable, true); + }); + test('only invokes once', () async { + expect(await speech.initialize(), true); + speechHandler.initInvoked = false; + expect(await speech.initialize(), true); + expect(speechHandler.initInvoked, false); + }); + test('fails on platform failure', () async { + speechHandler.initResult = false; + expect(await speech.initialize(), false); + expect(speech.isAvailable, false); + }); + }); + + group('listen', () { + test('fails with exception if not initialized', () async { + try { + await speech.listen(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('fails with exception if init fails', () async { + try { + speechHandler.initResult = false; + await speech.initialize(); + await speech.listen(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('invokes listen after successful init', () async { + await speech.initialize(); + await speech.listen(); + expect(speechHandler.listenLocale, isNull); + expect(speechHandler.listenInvoked, true); + }); + test('converts platformException to listenFailed', () async { + await speech.initialize(); + speechHandler.listenException = true; + try { + await speech.listen(); + fail("Should have thrown"); + } on ListenFailedException catch (e) { + expect(e.details, TestSpeechChannelHandler.listenExceptionDetails); + } catch (wrongE) { + fail("Should have been ListenFailedException"); + } + }); + test('stops listen after listenFor duration', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(listenFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 2)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after listenFor duration even with speech event', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(listenFor: Duration(seconds: 1)); + speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after pauseFor duration with no speech', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(pauseFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 2)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after pauseFor with longer listenFor duration', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen( + pauseFor: Duration(seconds: 1), listenFor: Duration(seconds: 5)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after listenFor with longer pauseFor duration', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen( + listenFor: Duration(seconds: 1), pauseFor: Duration(seconds: 5)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('keeps listening after pauseFor with speech event', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(pauseFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + fa.elapse(Duration(seconds: 1)); + speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + fa.flushMicrotasks(); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isTrue); + }); + }); + test('uses localeId if provided', () async { + await speech.initialize(); + await speech.listen(localeId: TestSpeechChannelHandler.localeId1); + expect(speechHandler.listenInvoked, true); + expect(speechHandler.listenLocale, TestSpeechChannelHandler.localeId1); + }); + test('calls speech listener', () async { + await speech.initialize(); + await speech.listen(onResult: listener.onSpeechResult); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + expect(listener.speechResults, 1); + expect( + listener.results, [TestSpeechChannelHandler.firstRecognizedResult]); + expect(speech.lastRecognizedWords, + TestSpeechChannelHandler.firstRecognizedWords); + }); + test('calls speech listener with multiple', () async { + await speech.initialize(); + await speech.listen(onResult: listener.onSpeechResult); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.secondRecognizedJson)); + expect(listener.speechResults, 2); + expect(listener.results, [ + TestSpeechChannelHandler.firstRecognizedResult, + TestSpeechChannelHandler.secondRecognizedResult + ]); + expect(speech.lastRecognizedWords, + TestSpeechChannelHandler.secondRecognizedWords); + }); + }); + + group('status callback', () { + test('invoked on listen', () async { + await speech.initialize( + onError: listener.onSpeechError, onStatus: listener.onSpeechStatus); + await speech.processMethodCall(MethodCall( + SpeechToText.notifyStatusMethod, SpeechToText.listeningStatus)); + expect(listener.speechStatus, 1); + expect(listener.statuses.contains(SpeechToText.listeningStatus), true); + }); + }); + + group('soundLevel callback', () { + test('invoked on listen', () async { + await speech.initialize(); + await speech.listen(onSoundLevelChange: listener.onSoundLevel); + await speech.processMethodCall(MethodCall( + SpeechToText.soundLevelChangeMethod, + TestSpeechChannelHandler.level1)); + expect(listener.soundLevel, 1); + expect(listener.soundLevels, contains(TestSpeechChannelHandler.level1)); + }); + test('sets lastLevel', () async { + await speech.initialize(); + await speech.listen(onSoundLevelChange: listener.onSoundLevel); + await speech.processMethodCall(MethodCall( + SpeechToText.soundLevelChangeMethod, + TestSpeechChannelHandler.level1)); + expect(speech.lastSoundLevel, TestSpeechChannelHandler.level1); + }); + }); + + group('cancel', () { + test('does nothing if not initialized', () async { + speech.cancel(); + expect(speechHandler.cancelInvoked, false); + }); + test('cancels an active listen', () async { + await speech.initialize(); + await speech.listen(); + await speech.cancel(); + expect(speechHandler.cancelInvoked, true); + expect(speech.isListening, isFalse); + }); + }); + group('stop', () { + test('does nothing if not initialized', () async { + speech.stop(); + expect(speechHandler.cancelInvoked, false); + }); + test('stops an active listen', () async { + await speech.initialize(); + speech.listen(); + speech.stop(); + expect(speechHandler.stopInvoked, true); + }); + }); + group('error', () { + test('notifies handler with transient', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.transientErrorJson)); + expect(listener.speechErrors, 1); + expect(listener.errors.first.permanent, isFalse); + }); + test('notifies handler with permanent', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(listener.speechErrors, 1); + expect(listener.errors.first.permanent, isTrue); + }); + test('continues listening on transient', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.transientErrorJson)); + expect(speech.isListening, isTrue); + }); + test('continues listening on permanent if cancel not explicitly requested', + () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isTrue); + }); + test('stops listening on permanent if cancel explicitly requested', + () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(cancelOnError: true); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + }); + test('Error not sent after cancel', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.cancel(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + expect(listener.speechErrors, 0); + }); + test('Error still sent after implicit cancel', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(cancelOnError: true); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + expect(listener.speechErrors, 2); + }); + }); + group('locales', () { + test('fails with exception if not initialized', () async { + try { + await speech.locales(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('system locale null if not initialized', () async { + LocaleName current; + try { + current = await speech.systemLocale(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + expect(current, isNull); + } + }); + test('handles an empty list', () async { + await speech.initialize(onError: listener.onSpeechError); + List localeNames = await speech.locales(); + expect(speechHandler.localesInvoked, isTrue); + expect(localeNames, isEmpty); + }); + test('returns expected locales', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + speechHandler.locales.add(TestSpeechChannelHandler.locale2); + List localeNames = await speech.locales(); + expect(localeNames, hasLength(speechHandler.locales.length)); + expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); + expect(localeNames[0].name, TestSpeechChannelHandler.name1); + expect(localeNames[1].localeId, TestSpeechChannelHandler.localeId2); + expect(localeNames[1].name, TestSpeechChannelHandler.name2); + }); + test('skips incorrect locales', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add("InvalidJunk"); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + List localeNames = await speech.locales(); + expect(localeNames, hasLength(1)); + expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); + expect(localeNames[0].name, TestSpeechChannelHandler.name1); + }); + test('system locale matches first returned locale', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + speechHandler.locales.add(TestSpeechChannelHandler.locale2); + LocaleName current = await speech.systemLocale(); + expect(current.localeId, TestSpeechChannelHandler.localeId1); + }); + }); + group('status', () { + test('recognized false at start', () async { + expect(speech.hasRecognized, isFalse); + }); + test('listening false at start', () async { + expect(speech.isListening, isFalse); + }); + }); + test('available false at start', () async { + expect(speech.isAvailable, isFalse); + }); + test('hasError false at start', () async { + expect(speech.hasError, isFalse); + }); + test('lastError null at start', () async { + expect(speech.lastError, isNull); + }); + test('status empty at start', () async { + expect(speech.lastStatus, isEmpty); + }); +} + +class TestSpeechListener { + int speechResults = 0; + List results = []; + int speechErrors = 0; + List errors = []; + int speechStatus = 0; + List statuses = []; + int soundLevel = 0; + List soundLevels = []; + + void onSpeechResult(SpeechRecognitionResult result) { + ++speechResults; + results.add(result); + } + + void onSpeechError(SpeechRecognitionError errorResult) { + ++speechErrors; + errors.add(errorResult); + } + + void onSpeechStatus(String status) { + ++speechStatus; + statuses.add(status); + } + + void onSoundLevel(double level) { + ++soundLevel; + soundLevels.add(level); + } +} diff --git a/speech_to_text_/test/test_speech_channel_handler.dart b/speech_to_text_/test/test_speech_channel_handler.dart new file mode 100644 index 00000000..a55f0670 --- /dev/null +++ b/speech_to_text_/test/test_speech_channel_handler.dart @@ -0,0 +1,134 @@ +import 'package:flutter/services.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +/// Holds a set of responses and acts as a mock for the platform specific +/// implementations allowing test cases to determine what the result of +/// a call should be. +class TestSpeechChannelHandler { + final SpeechToText _speech; + + bool listenException = false; + + static const String listenExceptionCode = "listenFailedError"; + static const String listenExceptionMessage = "Failed"; + static const String listenExceptionDetails = "Device Listen Failure"; + + TestSpeechChannelHandler(this._speech); + + bool initResult = true; + bool initInvoked = false; + bool listenInvoked = false; + bool cancelInvoked = false; + bool stopInvoked = false; + bool localesInvoked = false; + bool hasPermissionResult = true; + String listeningStatusResponse = SpeechToText.listeningStatus; + String listenLocale; + List locales = []; + static const String localeId1 = "en_US"; + static const String localeId2 = "fr_CA"; + static const String name1 = "English US"; + static const String name2 = "French Canada"; + static const String locale1 = "$localeId1:$name1"; + static const String locale2 = "$localeId2:$name2"; + static const String firstRecognizedWords = 'hello'; + static const String secondRecognizedWords = 'hello there'; + static const double firstConfidence = 0.85; + static const double secondConfidence = 0.62; + static const String firstRecognizedJson = + '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; + static const String secondRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; + static const String finalRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":true}'; + static const SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + static const SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + static final SpeechRecognitionResult firstRecognizedResult = + SpeechRecognitionResult([firstWords], false); + static final SpeechRecognitionResult secondRecognizedResult = + SpeechRecognitionResult([secondWords], false); + static final SpeechRecognitionResult finalRecognizedResult = + SpeechRecognitionResult([secondWords], true); + static const String transientErrorJson = + '{"errorMsg":"network","permanent":false}'; + static const String permanentErrorJson = + '{"errorMsg":"network","permanent":true}'; + static final SpeechRecognitionError firstError = + SpeechRecognitionError("network", true); + static const double level1 = 0.5; + static const double level2 = 10; + + Future methodCallHandler(MethodCall methodCall) async { + switch (methodCall.method) { + case "has_permission": + return hasPermissionResult; + break; + case "initialize": + initInvoked = true; + return initResult; + break; + case "cancel": + cancelInvoked = true; + return true; + break; + case "stop": + stopInvoked = true; + return true; + break; + case SpeechToText.listenMethod: + listenInvoked = true; + if (listenException) { + throw PlatformException( + code: listenExceptionCode, + message: listenExceptionMessage, + details: listenExceptionDetails); + } + listenLocale = methodCall.arguments["localeId"]; + await _speech.processMethodCall(MethodCall( + SpeechToText.notifyStatusMethod, listeningStatusResponse)); + return initResult; + break; + case "locales": + localesInvoked = true; + return locales; + break; + default: + } + return initResult; + } + + void notifyFinalWords() { + _speech.processMethodCall( + MethodCall(SpeechToText.textRecognitionMethod, finalRecognizedJson)); + } + + void notifyPartialWords() { + _speech.processMethodCall( + MethodCall(SpeechToText.textRecognitionMethod, firstRecognizedJson)); + } + + void notifyPermanentError() { + _speech.processMethodCall( + MethodCall(SpeechToText.notifyErrorMethod, permanentErrorJson)); + } + + void notifyTransientError() { + _speech.processMethodCall( + MethodCall(SpeechToText.notifyErrorMethod, transientErrorJson)); + } + + void notifySoundLevel() { + _speech.processMethodCall( + MethodCall(SpeechToText.soundLevelChangeMethod, level2)); + } + + void setupLocales() { + locales.clear(); + locales.add(locale1); + locales.add(locale2); + } +} diff --git a/speech_to_text_/test/test_speech_listener.dart b/speech_to_text_/test/test_speech_listener.dart new file mode 100644 index 00000000..1efcd81c --- /dev/null +++ b/speech_to_text_/test/test_speech_listener.dart @@ -0,0 +1,36 @@ +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text_provider.dart'; + +/// Holds the results of notification by the [SpeechToTextProvider] +class TestSpeechListener { + final SpeechToTextProvider _speechProvider; + + bool isListening = false; + bool isFinal = false; + bool isAvailable = false; + bool notified = false; + bool hasError = false; + SpeechRecognitionResult recognitionResult; + SpeechRecognitionError lastError; + double soundLevel; + + TestSpeechListener(this._speechProvider); + + void reset() { + isListening = false; + isFinal = false; + isAvailable = false; + notified = false; + } + + void onNotify() { + notified = true; + isAvailable = _speechProvider.isAvailable; + isListening = _speechProvider.isListening; + recognitionResult = _speechProvider.lastResult; + hasError = _speechProvider.hasError; + lastError = _speechProvider.lastError; + soundLevel = _speechProvider.lastLevel; + } +}