diff --git a/android/app/build.gradle b/android/app/build.gradle index 807f7fad..300075a5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -23,6 +23,7 @@ if (flutterVersionName == null) { apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { @@ -60,4 +61,5 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "com.google.firebase:firebase-messaging:20.1.0" } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 00000000..f86832ad --- /dev/null +++ b/android/app/google-services.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.cloud.diplomaticquarterapp" + } + }, + "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/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b88d5204..fa31e719 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -33,15 +33,22 @@ android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" /> + + + + + + + diff --git a/android/build.gradle b/android/build.gradle index 3100ad2d..70b3637d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.2' } } diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/assets/images/habib-logo.png b/assets/images/habib-logo.png new file mode 100644 index 00000000..bcb6a42b Binary files /dev/null and b/assets/images/habib-logo.png differ diff --git a/assets/images/id_card_icon.png b/assets/images/id_card_icon.png new file mode 100644 index 00000000..96650604 Binary files /dev/null and b/assets/images/id_card_icon.png differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 00000000..0d9e4a56 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/images/my_file_white_icon.png b/assets/images/my_file_white_icon.png new file mode 100644 index 00000000..6bd9b935 Binary files /dev/null and b/assets/images/my_file_white_icon.png differ diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee8..e8efba11 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee8..399e9340 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 00000000..9712eaff --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,87 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '9.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 + +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/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 00000000..23df2dbe --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,292 @@ +PODS: + - barcode_scan (0.0.1): + - Flutter + - MTBBarcodeScanner + - SwiftProtobuf + - connectivity (0.0.1): + - Flutter + - Reachability + - connectivity_for_web (0.1.0): + - Flutter + - connectivity_macos (0.0.1): + - Flutter + - device_info (0.0.1): + - Flutter + - Firebase/Core (6.23.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.4.2) + - Firebase/CoreOnly (6.23.0): + - FirebaseCore (= 6.6.7) + - Firebase/Messaging (6.23.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 4.3.1) + - firebase_messaging (0.0.1): + - Firebase/Core + - Firebase/Messaging + - Flutter + - FirebaseAnalytics (6.4.2): + - FirebaseCore (~> 6.6) + - FirebaseInstallations (~> 1.2) + - GoogleAppMeasurement (= 6.4.2) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - FirebaseAnalyticsInterop (1.5.0) + - FirebaseCore (6.6.7): + - FirebaseCoreDiagnostics (~> 1.2) + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.2.4): + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleDataTransportCCTSupport (~> 3.0) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 0.3.901) + - FirebaseCoreDiagnosticsInterop (1.2.0) + - FirebaseInstallations (1.2.0): + - FirebaseCore (~> 6.6) + - GoogleUtilities/Environment (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.6) + - PromisesObjC (~> 1.2) + - FirebaseInstanceID (4.3.4): + - FirebaseCore (~> 6.6) + - FirebaseInstallations (~> 1.0) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/UserDefaults (~> 6.5) + - FirebaseMessaging (4.3.1): + - FirebaseAnalyticsInterop (~> 1.5) + - FirebaseCore (~> 6.6) + - FirebaseInstanceID (~> 4.3) + - GoogleUtilities/AppDelegateSwizzler (~> 6.5) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Reachability (~> 6.5) + - GoogleUtilities/UserDefaults (~> 6.5) + - Protobuf (>= 3.9.2, ~> 3.9) + - Flutter (1.0.0) + - flutter_flexible_toast (0.0.1): + - Flutter + - flutter_local_notifications (0.0.1): + - Flutter + - flutter_plugin_android_lifecycle (0.0.1): + - Flutter + - GoogleAppMeasurement (6.4.2): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - GoogleDataTransport (6.0.0) + - GoogleDataTransportCCTSupport (3.0.0): + - GoogleDataTransport (~> 6.0) + - nanopb (~> 0.3.901) + - GoogleUtilities/AppDelegateSwizzler (6.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.6.0): + - PromisesObjC (~> 1.2) + - GoogleUtilities/Logger (6.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.6.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.6.0)" + - GoogleUtilities/Reachability (6.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.6.0): + - GoogleUtilities/Logger + - hexcolor (0.0.1): + - Flutter + - image_cropper (0.0.2): + - Flutter + - TOCropViewController (~> 2.5.2) + - image_picker (0.0.1): + - Flutter + - local_auth (0.0.1): + - Flutter + - MTBBarcodeScanner (5.0.11) + - nanopb (0.3.9011): + - nanopb/decode (= 0.3.9011) + - nanopb/encode (= 0.3.9011) + - nanopb/decode (0.3.9011) + - nanopb/encode (0.3.9011) + - path_provider_linux (0.0.1): + - Flutter + - "permission_handler (5.0.1+1)": + - Flutter + - PromisesObjC (1.2.8) + - Protobuf (3.11.4) + - Reachability (3.2) + - shared_preferences (0.0.1): + - Flutter + - shared_preferences_linux (0.0.1): + - Flutter + - shared_preferences_macos (0.0.1): + - Flutter + - shared_preferences_web (0.0.1): + - Flutter + - SwiftProtobuf (1.10.2) + - TOCropViewController (2.5.4) + - url_launcher (0.0.1): + - Flutter + - url_launcher_linux (0.0.1): + - Flutter + - url_launcher_macos (0.0.1): + - Flutter + - url_launcher_web (0.0.1): + - Flutter + +DEPENDENCIES: + - barcode_scan (from `.symlinks/plugins/barcode_scan/ios`) + - connectivity (from `.symlinks/plugins/connectivity/ios`) + - connectivity_for_web (from `.symlinks/plugins/connectivity_for_web/ios`) + - connectivity_macos (from `.symlinks/plugins/connectivity_macos/ios`) + - device_info (from `.symlinks/plugins/device_info/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_flexible_toast (from `.symlinks/plugins/flutter_flexible_toast/ios`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`) + - hexcolor (from `.symlinks/plugins/hexcolor/ios`) + - image_cropper (from `.symlinks/plugins/image_cropper/ios`) + - image_picker (from `.symlinks/plugins/image_picker/ios`) + - local_auth (from `.symlinks/plugins/local_auth/ios`) + - path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`) + - permission_handler (from `.symlinks/plugins/permission_handler/ios`) + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - shared_preferences_linux (from `.symlinks/plugins/shared_preferences_linux/ios`) + - shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`) + - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + - url_launcher_linux (from `.symlinks/plugins/url_launcher_linux/ios`) + - url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`) + - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`) + +SPEC REPOS: + trunk: + - Firebase + - FirebaseAnalytics + - FirebaseAnalyticsInterop + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseCoreDiagnosticsInterop + - FirebaseInstallations + - FirebaseInstanceID + - FirebaseMessaging + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleUtilities + - MTBBarcodeScanner + - nanopb + - PromisesObjC + - Protobuf + - Reachability + - SwiftProtobuf + - TOCropViewController + +EXTERNAL SOURCES: + barcode_scan: + :path: ".symlinks/plugins/barcode_scan/ios" + connectivity: + :path: ".symlinks/plugins/connectivity/ios" + connectivity_for_web: + :path: ".symlinks/plugins/connectivity_for_web/ios" + connectivity_macos: + :path: ".symlinks/plugins/connectivity_macos/ios" + device_info: + :path: ".symlinks/plugins/device_info/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_flexible_toast: + :path: ".symlinks/plugins/flutter_flexible_toast/ios" + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + flutter_plugin_android_lifecycle: + :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" + hexcolor: + :path: ".symlinks/plugins/hexcolor/ios" + image_cropper: + :path: ".symlinks/plugins/image_cropper/ios" + image_picker: + :path: ".symlinks/plugins/image_picker/ios" + local_auth: + :path: ".symlinks/plugins/local_auth/ios" + path_provider_linux: + :path: ".symlinks/plugins/path_provider_linux/ios" + permission_handler: + :path: ".symlinks/plugins/permission_handler/ios" + shared_preferences: + :path: ".symlinks/plugins/shared_preferences/ios" + shared_preferences_linux: + :path: ".symlinks/plugins/shared_preferences_linux/ios" + shared_preferences_macos: + :path: ".symlinks/plugins/shared_preferences_macos/ios" + shared_preferences_web: + :path: ".symlinks/plugins/shared_preferences_web/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + url_launcher_linux: + :path: ".symlinks/plugins/url_launcher_linux/ios" + url_launcher_macos: + :path: ".symlinks/plugins/url_launcher_macos/ios" + url_launcher_web: + :path: ".symlinks/plugins/url_launcher_web/ios" + +SPEC CHECKSUMS: + barcode_scan: a5c27959edfafaa0c771905bad0b29d6d39e4479 + connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 + connectivity_for_web: 2b8584556930d4bd490d82b836bcf45067ce345b + connectivity_macos: e2e9731b6b22dda39eb1b128f6969d574460e191 + device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 + Firebase: 585ae467b3edda6a5444e788fda6888f024d8d6f + firebase_messaging: 21344b3b3a7d9d325d63a70e3750c0c798fe1e03 + FirebaseAnalytics: 558f7a03d19de451093032c806f39d5f9dff096e + FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae + FirebaseCore: a2788a0d5f6c1dff17b8f79b4a73654a8d4bfdbd + FirebaseCoreDiagnostics: b59c024493a409f8aecba02c99928d0d8431d159 + FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 + FirebaseInstallations: 2119fb3e46b0a88bfdbf12562f855ee3252462fa + FirebaseInstanceID: cef67c4967c7cecb56ea65d8acbb4834825c587b + FirebaseMessaging: 828e66eb357a893e3cebd9ee0f6bc1941447cc94 + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_flexible_toast: 0547e740cae0c33bb7c51bcd931233f4584e1143 + flutter_local_notifications: 9e4738ce2471c5af910d961a6b7eadcf57c50186 + flutter_plugin_android_lifecycle: dc0b544e129eebb77a6bfb1239d4d1c673a60a35 + GoogleAppMeasurement: 2253e99c1f22638cf234c059144660c338ad76c3 + GoogleDataTransport: 061fe7d9b476710e3cd8ea51e8e07d8b67c2b420 + GoogleDataTransportCCTSupport: 0f39025e8cf51f168711bd3fb773938d7e62ddb5 + GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1 + hexcolor: fdfb9c4258ad96e949c2dbcdf790a62194b8aa89 + image_cropper: 3c16d7651730ffe85897f5a1c4e2547e6b54989a + image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09 + local_auth: 25938960984c3a7f6e3253e3f8d962fdd16852bd + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4 + permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6 + PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 + Protobuf: 176220c526ad8bd09ab1fb40a978eac3fef665f7 + Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 + shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d + shared_preferences_linux: afefbfe8d921e207f01ede8b60373d9e3b566b78 + shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087 + shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9 + SwiftProtobuf: bec1ae7d686ff73dd09d79866154f4970b891410 + TOCropViewController: 2a1ae1242600b1f2d996fd91a5268b2309a33b5c + url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef + url_launcher_linux: ac237cb7a8058736e4aae38bdbcc748a4b394cc0 + url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313 + url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c + +PODFILE CHECKSUM: 2609452b760cd11039b14039a86564367a3d8ab9 + +COCOAPODS: 1.9.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index b1c7ff05..785bfcb8 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* 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 */; }; + 5A016D0DD1095D385566337C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC606583E610E227F8186476 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -29,6 +30,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 09DDD2020D673759BD0E86B8 /* 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 = ""; }; 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 = ""; }; @@ -42,6 +44,9 @@ 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 = ""; }; + A8949DBAE70E5B302D91F1DB /* 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 = ""; }; + AC606583E610E227F8186476 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2D9C922B5D0172FE487333D /* 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -49,12 +54,32 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5A016D0DD1095D385566337C /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0A1F078D9C068A8B18DE1EDB /* Pods */ = { + isa = PBXGroup; + children = ( + A8949DBAE70E5B302D91F1DB /* Pods-Runner.debug.xcconfig */, + E2D9C922B5D0172FE487333D /* Pods-Runner.release.xcconfig */, + 09DDD2020D673759BD0E86B8 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 44EDA189DE1BB86E3A41BD4A /* Frameworks */ = { + isa = PBXGroup; + children = ( + AC606583E610E227F8186476 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +97,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 0A1F078D9C068A8B18DE1EDB /* Pods */, + 44EDA189DE1BB86E3A41BD4A /* Frameworks */, ); sourceTree = ""; }; @@ -113,12 +140,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + B4860726BBF5BF6213BBC91C /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 72E9699567A7106FD141B9B3 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -191,6 +220,64 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 72E9699567A7106FD141B9B3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", + "${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework", + "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", + "${BUILT_PRODUCTS_DIR}/Protobuf/protobuf.framework", + "${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework", + "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", + "${BUILT_PRODUCTS_DIR}/TOCropViewController/TOCropViewController.framework", + "${BUILT_PRODUCTS_DIR}/barcode_scan/barcode_scan.framework", + "${BUILT_PRODUCTS_DIR}/connectivity/connectivity.framework", + "${BUILT_PRODUCTS_DIR}/device_info/device_info.framework", + "${BUILT_PRODUCTS_DIR}/flutter_flexible_toast/flutter_flexible_toast.framework", + "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework", + "${BUILT_PRODUCTS_DIR}/flutter_plugin_android_lifecycle/flutter_plugin_android_lifecycle.framework", + "${BUILT_PRODUCTS_DIR}/hexcolor/hexcolor.framework", + "${BUILT_PRODUCTS_DIR}/image_cropper/image_cropper.framework", + "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", + "${BUILT_PRODUCTS_DIR}/local_auth/local_auth.framework", + "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/protobuf.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TOCropViewController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_flexible_toast.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_plugin_android_lifecycle.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hexcolor.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_cropper.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -205,6 +292,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + B4860726BBF5BF6213BBC91C /* [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; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16..21a3cc14 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/lib/config/config.dart b/lib/config/config.dart index cd53d564..d0de877a 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -1,10 +1,12 @@ -import 'dart:io'; -import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'dart:io'; const MAX_SMALL_SCREEN = 660; +//const BASE_URL = 'https://hmgwebservices.com/Services'; + +const GET_PROJECT = '/Lists.svc/REST/GetProject'; const BASE_URL = 'https://hmgwebservices.com/'; // Production Environment //const BASE_URL = 'https://uat.hmgwebservices.com/'; // UAT Environment @@ -21,6 +23,15 @@ const GET_DOCTOR_PROFILE = "Services/Doctors.svc/REST/GetDocProfiles"; //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"; + +//URL to get patient share +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"; + class AppGlobal { static var context; @@ -34,6 +45,7 @@ class AppGlobal { request.generalid = 'Cs2020@2016\$2958'; request.PatientOutSA = 0; request.SessionID = null; + request.TokenID = "@dm!n"; request.isDentalAllowedBackend = false; request.DeviceTypeID = Platform.isIOS ? 1 : 2; @@ -41,3 +53,8 @@ class AppGlobal { } } + +const CHANNEL = 3; +const GENERAL_ID = 'Cs2020@2016\$2958'; +const IP_ADDRESS = '10.20.10.20'; +const VERSION_ID = 5.5; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 87fe4cf9..39b887d2 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -45,4 +45,41 @@ const Map> localizedValues = { 'time': {'en': 'Time', 'ar': 'الوقت'}, + 'login': {'en': 'Login', 'ar': 'تسجيل الدخول'}, + 'loginregister': {'en': 'Login / Register', 'ar': 'دخولتسجيل'}, + 'welcome': {'en': 'Welcome', 'ar': 'أهلا بك'}, + 'welcome_text': { + 'en': 'Dr. Sulaiman Al Habib Mobile Application ', + '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": "National ID", "ar": "رقم الهوية"}, + "fileNo": {"en": "File Number", "ar": "رقم الملف"}, + "forgotFileNo": {"en": "Forgot file Number?", "ar": "نسيت رقم الملف الطبي؟"}, + "enter-national-id": { + "en": "Please enter mobile number and national ID / Iqama", + "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": "أدخل رقم الجوال المسجل لاستلام رقم الملف عن طريق الرسائل النصية" + }, + "dob": {"en": "Birth Date:", "ar": "تاريخ الميلاد"}, + "hijri-date": {"en": "Hijri Date", "ar": "التاريخ الهجري"}, + "gregorian-date": {"en": "Gregorian Date", "ar": "التاريخ الميلادي"}, }; diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index 8c03fcce..1e75a802 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -1,3 +1,7 @@ const TOKEN = 'token'; const APP_LANGUAGE = 'language'; - +const USER_PROFILE = 'user-profile'; +const PUSH_TOKEN = 'push-token'; +const REGISTER_DATA_FOR_REGISTER = 'register-data-for-register'; +const LOGIN_TOKEN_ID = 'register-data-for-register'; +const REGISTER_DATA_FOR_LOGIIN = 'register-data-for-login'; diff --git a/lib/core/enum/viewstate.dart b/lib/core/enum/viewstate.dart new file mode 100644 index 00000000..09b5d34b --- /dev/null +++ b/lib/core/enum/viewstate.dart @@ -0,0 +1 @@ +enum ViewState { Idle, Busy, Error } diff --git a/lib/core/model/auth/check_paitent_authentication_req.dart b/lib/core/model/auth/check_paitent_authentication_req.dart new file mode 100644 index 00000000..2846c1fc --- /dev/null +++ b/lib/core/model/auth/check_paitent_authentication_req.dart @@ -0,0 +1,76 @@ +class CheckPatientAuthenticationReq { + int patientMobileNumber; + String zipCode; + bool isRegister; + String tokenID; + int searchType; + String patientIdentificationID; + int patientID; + double versionID; + int channel; + int languageID; + String iPAdress; + String generalid; + int patientOutSA; + Null sessionID; + bool isDentalAllowedBackend; + int deviceTypeID; + + CheckPatientAuthenticationReq( + {this.patientMobileNumber, + this.zipCode, + this.isRegister, + this.tokenID, + this.searchType, + this.patientIdentificationID, + this.patientID, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID}); + + CheckPatientAuthenticationReq.fromJson(Map json) { + patientMobileNumber = json['PatientMobileNumber']; + zipCode = json['ZipCode']; + isRegister = json['isRegister']; + tokenID = json['TokenID']; + searchType = json['SearchType']; + patientIdentificationID = json['PatientIdentificationID']; + patientID = json['PatientID']; + 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['PatientMobileNumber'] = this.patientMobileNumber; + data['ZipCode'] = this.zipCode; + data['isRegister'] = this.isRegister; + data['TokenID'] = this.tokenID; + data['SearchType'] = this.searchType; + data['PatientIdentificationID'] = this.patientIdentificationID; + data['PatientID'] = this.patientID; + 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/auth/select_device_imei_res.dart b/lib/core/model/auth/select_device_imei_res.dart new file mode 100644 index 00000000..14444279 --- /dev/null +++ b/lib/core/model/auth/select_device_imei_res.dart @@ -0,0 +1,68 @@ +class SelectDeviceIMEIRES { + bool biometricEnabled; + String createdOn; + String editedOn; + int iD; + String iMEI; + String identificationNo; + int logInType; + String mobile; + String name; + String nameN; + bool outSA; + int patientID; + int patientType; + int preferredLanguage; + + SelectDeviceIMEIRES( + {this.biometricEnabled, + this.createdOn, + this.editedOn, + this.iD, + this.iMEI, + this.identificationNo, + this.logInType, + this.mobile, + this.name, + this.nameN, + this.outSA, + this.patientID, + this.patientType, + this.preferredLanguage}); + + SelectDeviceIMEIRES.fromJson(Map json) { + biometricEnabled = json['BiometricEnabled']; + createdOn = json['CreatedOn']; + editedOn = json['EditedOn']; + iD = json['ID']; + iMEI = json['IMEI']; + identificationNo = json['IdentificationNo']; + logInType = json['LogInType']; + mobile = json['Mobile']; + name = json['Name']; + nameN = json['NameN']; + outSA = json['OutSA']; + patientID = json['PatientID']; + patientType = json['PatientType']; + preferredLanguage = json['PreferredLanguage']; + } + + Map toJson() { + final Map data = new Map(); + data['BiometricEnabled'] = this.biometricEnabled; + data['CreatedOn'] = this.createdOn; + data['EditedOn'] = this.editedOn; + data['ID'] = this.iD; + data['IMEI'] = this.iMEI; + data['IdentificationNo'] = this.identificationNo; + data['LogInType'] = this.logInType; + data['Mobile'] = this.mobile; + data['Name'] = this.name; + data['NameN'] = this.nameN; + data['OutSA'] = this.outSA; + data['PatientID'] = this.patientID; + data['PatientType'] = this.patientType; + data['PreferredLanguage'] = this.preferredLanguage; + return data; + } +} diff --git a/lib/core/model/hospitals/hospitals_model.dart b/lib/core/model/hospitals/hospitals_model.dart new file mode 100644 index 00000000..a0628c60 --- /dev/null +++ b/lib/core/model/hospitals/hospitals_model.dart @@ -0,0 +1,76 @@ +class HospitalsModel { + String desciption; + Null desciptionN; + int iD; + String legalName; + String legalNameN; + String name; + Null nameN; + String phoneNumber; + String setupID; + int distanceInKilometers; + bool isActive; + String latitude; + String longitude; + int mainProjectID; + Null projectOutSA; + bool usingInDoctorApp; + + HospitalsModel( + {this.desciption, + this.desciptionN, + this.iD, + this.legalName, + this.legalNameN, + this.name, + this.nameN, + this.phoneNumber, + this.setupID, + this.distanceInKilometers, + this.isActive, + this.latitude, + this.longitude, + this.mainProjectID, + this.projectOutSA, + this.usingInDoctorApp}); + + HospitalsModel.fromJson(Map json) { + desciption = json['Desciption']; + desciptionN = json['DesciptionN']; + iD = json['ID']; + legalName = json['LegalName']; + legalNameN = json['LegalNameN']; + name = json['Name']; + nameN = json['NameN']; + phoneNumber = json['PhoneNumber']; + setupID = json['SetupID']; + distanceInKilometers = json['DistanceInKilometers']; + isActive = json['IsActive']; + latitude = json['Latitude']; + longitude = json['Longitude']; + mainProjectID = json['MainProjectID']; + projectOutSA = json['ProjectOutSA']; + usingInDoctorApp = json['UsingInDoctorApp']; + } + + Map toJson() { + final Map data = new Map(); + data['Desciption'] = this.desciption; + data['DesciptionN'] = this.desciptionN; + data['ID'] = this.iD; + data['LegalName'] = this.legalName; + data['LegalNameN'] = this.legalNameN; + data['Name'] = this.name; + data['NameN'] = this.nameN; + data['PhoneNumber'] = this.phoneNumber; + data['SetupID'] = this.setupID; + data['DistanceInKilometers'] = this.distanceInKilometers; + data['IsActive'] = this.isActive; + data['Latitude'] = this.latitude; + data['Longitude'] = this.longitude; + data['MainProjectID'] = this.mainProjectID; + data['ProjectOutSA'] = this.projectOutSA; + data['UsingInDoctorApp'] = this.usingInDoctorApp; + return data; + } +} diff --git a/lib/core/model/hospitals/request_get_hospitals_model.dart b/lib/core/model/hospitals/request_get_hospitals_model.dart new file mode 100644 index 00000000..be163654 --- /dev/null +++ b/lib/core/model/hospitals/request_get_hospitals_model.dart @@ -0,0 +1,56 @@ +class RequestGetHospitalsModel { + int latitude; + int longitude; + double versionID; + int channel; + int languageID; + String iPAdress; + String generalid; + int patientOutSA; + String sessionID; + bool isDentalAllowedBackend; + int deviceTypeID; + + RequestGetHospitalsModel( + {this.latitude, + this.longitude, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID}); + + RequestGetHospitalsModel.fromJson(Map json) { + latitude = json['Latitude']; + longitude = json['Longitude']; + 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['Latitude'] = this.latitude; + data['Longitude'] = this.longitude; + 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/service/base_service.dart b/lib/core/service/base_service.dart new file mode 100644 index 00000000..828420c7 --- /dev/null +++ b/lib/core/service/base_service.dart @@ -0,0 +1,9 @@ + +import 'client/base_app_client.dart'; + +class BaseService{ + String error; + bool hasError = false; + BaseAppClient baseAppClient = BaseAppClient(); + +} \ No newline at end of file diff --git a/lib/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart similarity index 99% rename from lib/client/base_app_client.dart rename to lib/core/service/client/base_app_client.dart index ec905586..57686824 100644 --- a/lib/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -1,4 +1,5 @@ import 'dart:convert'; + import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; @@ -13,7 +14,7 @@ AppSharedPreferences sharedPref = new AppSharedPreferences(); /// body: null); class BaseAppClient { - static post( + post( String endPoint, { Map body, Function(dynamic response, int statusCode) onSuccess, @@ -21,7 +22,6 @@ class BaseAppClient { }) async { String url = BASE_URL + endPoint; try { - //Map profile = await sharedPref.getObj(DOCTOR_PROFILE); // String token = await sharedPref.getString(TOKEN); diff --git a/lib/core/service/hospital_service.dart b/lib/core/service/hospital_service.dart new file mode 100644 index 00000000..c131d94f --- /dev/null +++ b/lib/core/service/hospital_service.dart @@ -0,0 +1,36 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; +import 'package:diplomaticquarterapp/core/model/hospitals/request_get_hospitals_model.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; + +class HospitalService extends BaseService { + List _hospitals = List(); + + List get hospitals => _hospitals; + + RequestGetHospitalsModel _requestGetHospitalsModel = RequestGetHospitalsModel( + latitude: 0, + longitude: 0, + versionID: 5.2, + channel: 3, + languageID: 2, + iPAdress: '10.20.10.20', + generalid: 'Cs2020@2016\$2958', + patientOutSA: 0, + sessionID: 'JUWuiMBCEGkAAxQpakQ', + isDentalAllowedBackend: false, + deviceTypeID: 2); + + Future getHospitals() async { + await baseAppClient.post(GET_PROJECT, + onSuccess: (dynamic response, int statusCode) { + _hospitals.clear(); + response['ListProject'].forEach((hospital) { + _hospitals.add(HospitalsModel.fromJson(hospital)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: _requestGetHospitalsModel.toJson()); + } +} diff --git a/lib/core/viewModels/base_view_model.dart b/lib/core/viewModels/base_view_model.dart new file mode 100644 index 00000000..497a96b6 --- /dev/null +++ b/lib/core/viewModels/base_view_model.dart @@ -0,0 +1,16 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:flutter/material.dart'; + +class BaseViewModel extends ChangeNotifier { + ViewState _state = ViewState.Idle; + bool isInternetConnection = true; + + ViewState get state => _state; + + String error = ""; + + void setState(ViewState viewState) { + _state = viewState; + notifyListeners(); + } +} diff --git a/lib/core/viewModels/hospital_view_model.dart b/lib/core/viewModels/hospital_view_model.dart new file mode 100644 index 00000000..66ad4b01 --- /dev/null +++ b/lib/core/viewModels/hospital_view_model.dart @@ -0,0 +1,22 @@ +import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; +import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; +import 'package:diplomaticquarterapp/core/service/hospital_service.dart'; + +import '../../locator.dart'; +import 'base_view_model.dart'; + +class HospitalViewModel extends BaseViewModel { + HospitalService _hospitalService = locator(); + + List get hospitals => _hospitalService.hospitals; + + Future getHospitals() async { + setState(ViewState.Busy); + await _hospitalService.getHospitals(); + if (_hospitalService.hasError) { + error = _hospitalService.error; + setState(ViewState.Error); + } else + setState(ViewState.Idle); + } +} diff --git a/lib/providers/project_provider.dart b/lib/core/viewModels/project_view_model.dart similarity index 96% rename from lib/providers/project_provider.dart rename to lib/core/viewModels/project_view_model.dart index da48ffb9..e91ea4f2 100644 --- a/lib/providers/project_provider.dart +++ b/lib/core/viewModels/project_view_model.dart @@ -5,7 +5,7 @@ import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:flutter/cupertino.dart'; -class ProjectProvider with ChangeNotifier { +class ProjectViewModel with ChangeNotifier { AppSharedPreferences sharedPref = AppSharedPreferences(); Locale _appLocale; String currentLanguage = 'ar'; @@ -20,7 +20,7 @@ class ProjectProvider with ChangeNotifier { bool get isArabic => _isArabic; StreamSubscription subscription; - ProjectProvider() { + ProjectViewModel() { loadSharedPrefLanguage(); subscription = Connectivity() diff --git a/lib/locator.dart b/lib/locator.dart new file mode 100644 index 00000000..3d44f4ce --- /dev/null +++ b/lib/locator.dart @@ -0,0 +1,15 @@ +import 'package:get_it/get_it.dart'; + +import 'core/service/hospital_service.dart'; +import 'core/viewModels/hospital_view_model.dart'; + +GetIt locator = GetIt.instance; + +///di +void setupLocator() { + /// Services + locator.registerLazySingleton(() => HospitalService()); + + /// View Model + locator.registerFactory(() => HospitalViewModel()); +} diff --git a/lib/main.dart b/lib/main.dart index dff61ac6..06cf9652 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,14 +1,15 @@ -import 'package:diplomaticquarterapp/pages/home_page.dart'; -import 'package:diplomaticquarterapp/pages/landing_page.dart'; -import 'package:diplomaticquarterapp/providers/project_provider.dart'; +import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:provider/provider.dart'; - import 'config/size_config.dart'; +import 'core/viewModels/project_view_model.dart'; +import 'locator.dart'; +import 'pages/landing/landing_page.dart'; void main() { + setupLocator(); runApp(MyApp()); } @@ -22,11 +23,11 @@ class MyApp extends StatelessWidget { SizeConfig().init(constraints, orientation); return MultiProvider( providers: [ - ChangeNotifierProvider( - create: (context) => ProjectProvider(), + ChangeNotifierProvider( + create: (context) => ProjectViewModel(), ), ], - child: Consumer( + child: Consumer( builder: (context, projectProvider, child) => MaterialApp( showSemanticsDebugger: false, title: 'Diplomatic Quarter App', @@ -61,11 +62,9 @@ class MyApp extends StatelessWidget { splashColor: Colors.transparent, primaryColor: Colors.grey, cursorColor: Color.fromRGBO(78, 62, 253, 1.0), - iconTheme:IconThemeData( - - ) , + iconTheme: IconThemeData(), appBarTheme: AppBarTheme( - color: Color.fromRGBO(247, 248, 251, 1), + color: Colors.grey, brightness: Brightness.light, elevation: 0.0, actionsIconTheme: IconThemeData( @@ -73,10 +72,8 @@ class MyApp extends StatelessWidget { ), ), ), - initialRoute: '/', - routes: { - '/': (context) => LandingPage() - }, + initialRoute: HOME, + routes: routes, debugShowCheckedModeBanner: false, ), ), diff --git a/lib/models/Appointments/AppoimentAllHistoryResultList.dart b/lib/models/Appointments/AppoimentAllHistoryResultList.dart new file mode 100644 index 00000000..b4f62d1d --- /dev/null +++ b/lib/models/Appointments/AppoimentAllHistoryResultList.dart @@ -0,0 +1,274 @@ +class AppoitmentAllHistoryResultList { + String setupID; + int projectID; + int appointmentNo; + String appointmentDate; + Null appointmentDateN; + int appointmentType; + String bookDate; + int patientType; + int patientID; + int clinicID; + int doctorID; + String endDate; + String startTime; + String endTime; + int status; + int visitType; + int visitFor; + int patientStatusType; + int companyID; + int bookedBy; + String bookedOn; + Null confirmedBy; + Null confirmedOn; + Null arrivalChangedBy; + Null arrivedOn; + Null editedBy; + Null editedOn; + Null doctorName; + Null doctorNameN; + String statusDesc; + Null statusDescN; + bool vitalStatus; + Null vitalSignAppointmentNo; + int episodeID; + int actualDoctorRate; + String clinicName; + bool complainExists; + String doctorImageURL; + String doctorNameObj; + int doctorRate; + List doctorSpeciality; + String doctorTitle; + int gender; + String genderDescription; + bool iSAllowOnlineCheckedIN; + bool isActiveDoctor; + bool isActiveDoctorProfile; + bool isDoctorAllowVedioCall; + bool isExecludeDoctor; + int isFollowup; + bool isLiveCareAppointment; + bool isMedicalReportRequested; + bool isOnlineCheckedIN; + String latitude; + Null listHISGetContactLensPerscription; + Null listHISGetGlassPerscription; + String longitude; + int nextAction; + int noOfPatientsRate; + int originalClinicID; + int originalProjectID; + String projectName; + String qR; + int remaniningHoursTocanPay; + bool sMSButtonVisable; + + AppoitmentAllHistoryResultList( + {this.setupID, + this.projectID, + this.appointmentNo, + this.appointmentDate, + this.appointmentDateN, + this.appointmentType, + this.bookDate, + this.patientType, + this.patientID, + this.clinicID, + this.doctorID, + this.endDate, + this.startTime, + this.endTime, + this.status, + this.visitType, + this.visitFor, + this.patientStatusType, + this.companyID, + this.bookedBy, + this.bookedOn, + this.confirmedBy, + this.confirmedOn, + this.arrivalChangedBy, + this.arrivedOn, + this.editedBy, + this.editedOn, + this.doctorName, + this.doctorNameN, + this.statusDesc, + this.statusDescN, + this.vitalStatus, + this.vitalSignAppointmentNo, + this.episodeID, + this.actualDoctorRate, + this.clinicName, + this.complainExists, + this.doctorImageURL, + this.doctorNameObj, + this.doctorRate, + this.doctorSpeciality, + this.doctorTitle, + this.gender, + this.genderDescription, + this.iSAllowOnlineCheckedIN, + this.isActiveDoctor, + this.isActiveDoctorProfile, + this.isDoctorAllowVedioCall, + this.isExecludeDoctor, + this.isFollowup, + this.isLiveCareAppointment, + this.isMedicalReportRequested, + this.isOnlineCheckedIN, + this.latitude, + this.listHISGetContactLensPerscription, + this.listHISGetGlassPerscription, + this.longitude, + this.nextAction, + this.noOfPatientsRate, + this.originalClinicID, + this.originalProjectID, + this.projectName, + this.qR, + this.remaniningHoursTocanPay, + this.sMSButtonVisable}); + + AppoitmentAllHistoryResultList.fromJson(Map json) { + setupID = json['SetupID']; + projectID = json['ProjectID']; + appointmentNo = json['AppointmentNo']; + appointmentDate = json['AppointmentDate']; + appointmentDateN = json['AppointmentDateN']; + appointmentType = json['AppointmentType']; + bookDate = json['BookDate']; + patientType = json['PatientType']; + patientID = json['PatientID']; + clinicID = json['ClinicID']; + doctorID = json['DoctorID']; + endDate = json['EndDate']; + startTime = json['StartTime']; + endTime = json['EndTime']; + status = json['Status']; + visitType = json['VisitType']; + visitFor = json['VisitFor']; + patientStatusType = json['PatientStatusType']; + companyID = json['CompanyID']; + bookedBy = json['BookedBy']; + bookedOn = json['BookedOn']; + confirmedBy = json['ConfirmedBy']; + confirmedOn = json['ConfirmedOn']; + arrivalChangedBy = json['ArrivalChangedBy']; + arrivedOn = json['ArrivedOn']; + editedBy = json['EditedBy']; + editedOn = json['EditedOn']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + statusDesc = json['StatusDesc']; + statusDescN = json['StatusDescN']; + vitalStatus = json['VitalStatus']; + vitalSignAppointmentNo = json['VitalSignAppointmentNo']; + episodeID = json['EpisodeID']; + actualDoctorRate = json['ActualDoctorRate']; + clinicName = json['ClinicName']; + complainExists = json['ComplainExists']; + doctorImageURL = json['DoctorImageURL']; + doctorNameObj = json['DoctorNameObj']; + doctorRate = json['DoctorRate']; + doctorSpeciality = json['DoctorSpeciality'].cast(); + doctorTitle = json['DoctorTitle']; + gender = json['Gender']; + genderDescription = json['GenderDescription']; + iSAllowOnlineCheckedIN = json['ISAllowOnlineCheckedIN']; + isActiveDoctor = json['IsActiveDoctor']; + isActiveDoctorProfile = json['IsActiveDoctorProfile']; + isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall']; + isExecludeDoctor = json['IsExecludeDoctor']; + isFollowup = json['IsFollowup']; + isLiveCareAppointment = json['IsLiveCareAppointment']; + isMedicalReportRequested = json['IsMedicalReportRequested']; + isOnlineCheckedIN = json['IsOnlineCheckedIN']; + latitude = json['Latitude']; + listHISGetContactLensPerscription = + json['List_HIS_GetContactLensPerscription']; + listHISGetGlassPerscription = json['List_HIS_GetGlassPerscription']; + longitude = json['Longitude']; + nextAction = json['NextAction']; + noOfPatientsRate = json['NoOfPatientsRate']; + originalClinicID = json['OriginalClinicID']; + originalProjectID = json['OriginalProjectID']; + projectName = json['ProjectName']; + qR = json['QR']; + remaniningHoursTocanPay = json['RemaniningHoursTocanPay']; + sMSButtonVisable = json['SMSButtonVisable']; + } + + Map toJson() { + final Map data = new Map(); + data['SetupID'] = this.setupID; + data['ProjectID'] = this.projectID; + data['AppointmentNo'] = this.appointmentNo; + data['AppointmentDate'] = this.appointmentDate; + data['AppointmentDateN'] = this.appointmentDateN; + data['AppointmentType'] = this.appointmentType; + data['BookDate'] = this.bookDate; + data['PatientType'] = this.patientType; + data['PatientID'] = this.patientID; + data['ClinicID'] = this.clinicID; + data['DoctorID'] = this.doctorID; + data['EndDate'] = this.endDate; + data['StartTime'] = this.startTime; + data['EndTime'] = this.endTime; + data['Status'] = this.status; + data['VisitType'] = this.visitType; + data['VisitFor'] = this.visitFor; + data['PatientStatusType'] = this.patientStatusType; + data['CompanyID'] = this.companyID; + data['BookedBy'] = this.bookedBy; + data['BookedOn'] = this.bookedOn; + data['ConfirmedBy'] = this.confirmedBy; + data['ConfirmedOn'] = this.confirmedOn; + data['ArrivalChangedBy'] = this.arrivalChangedBy; + data['ArrivedOn'] = this.arrivedOn; + data['EditedBy'] = this.editedBy; + data['EditedOn'] = this.editedOn; + data['DoctorName'] = this.doctorName; + data['DoctorNameN'] = this.doctorNameN; + data['StatusDesc'] = this.statusDesc; + data['StatusDescN'] = this.statusDescN; + data['VitalStatus'] = this.vitalStatus; + data['VitalSignAppointmentNo'] = this.vitalSignAppointmentNo; + data['EpisodeID'] = this.episodeID; + data['ActualDoctorRate'] = this.actualDoctorRate; + data['ClinicName'] = this.clinicName; + data['ComplainExists'] = this.complainExists; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorNameObj'] = this.doctorNameObj; + data['DoctorRate'] = this.doctorRate; + data['DoctorSpeciality'] = this.doctorSpeciality; + data['DoctorTitle'] = this.doctorTitle; + data['Gender'] = this.gender; + data['GenderDescription'] = this.genderDescription; + data['ISAllowOnlineCheckedIN'] = this.iSAllowOnlineCheckedIN; + data['IsActiveDoctor'] = this.isActiveDoctor; + data['IsActiveDoctorProfile'] = this.isActiveDoctorProfile; + data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall; + data['IsExecludeDoctor'] = this.isExecludeDoctor; + data['IsFollowup'] = this.isFollowup; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; + data['IsMedicalReportRequested'] = this.isMedicalReportRequested; + data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN; + data['Latitude'] = this.latitude; + data['List_HIS_GetContactLensPerscription'] = + this.listHISGetContactLensPerscription; + data['List_HIS_GetGlassPerscription'] = this.listHISGetGlassPerscription; + data['Longitude'] = this.longitude; + data['NextAction'] = this.nextAction; + data['NoOfPatientsRate'] = this.noOfPatientsRate; + data['OriginalClinicID'] = this.originalClinicID; + data['OriginalProjectID'] = this.originalProjectID; + data['ProjectName'] = this.projectName; + data['QR'] = this.qR; + data['RemaniningHoursTocanPay'] = this.remaniningHoursTocanPay; + data['SMSButtonVisable'] = this.sMSButtonVisable; + return data; + } +} diff --git a/lib/models/Appointments/InsertAppointmentRequest.dart b/lib/models/Appointments/InsertAppointmentRequest.dart index 09b7d923..badbb6a7 100644 --- a/lib/models/Appointments/InsertAppointmentRequest.dart +++ b/lib/models/Appointments/InsertAppointmentRequest.dart @@ -17,4 +17,5 @@ class InsertAppointmentRequest extends Request { bool IsForLiveCare; String OriginalClinicID; String OriginalProjectID; + } diff --git a/lib/models/Appointments/PatientShareResposne.dart b/lib/models/Appointments/PatientShareResposne.dart new file mode 100644 index 00000000..e4a05e04 --- /dev/null +++ b/lib/models/Appointments/PatientShareResposne.dart @@ -0,0 +1,204 @@ +class PatientShareResponse { + int advanceNumber; + String appointmentDate; + int appointmentNo; + int cashPrice; + int cashPriceTax; + int cashPriceWithTax; + int clinicID; + String clinicName; + int companyId; + String companyName; + int companyShareWithTax; + String doctorImageURL; + String doctorNameObj; + List doctorSpeciality; + Null errCode; + int groupID; + bool iSAllowOnlineCheckedIN; + Null insurancePolicyNo; + bool isExcludedForOnlineCheckin; + int isFollowup; + bool isLiveCareAppointment; + bool isOnlineCheckedIN; + String message; + int nextAction; + Null patientCardID; + int patientID; + dynamic patientShare; + dynamic patientShareWithTax; + int patientStatusType; + dynamic patientTaxAmount; + String patientType; + int paymentAmount; + String paymentDate; + Null paymentMethodName; + Null paymentReferenceNumber; + int policyId; + String policyName; + String procedureName; + int projectID; + String projectName; + Null setupID; + int sourceType; + String startTime; + int status; + int statusCode; + Null statusDesc; + Null subPolicyNo; + int userID; + + PatientShareResponse( + {this.advanceNumber, + this.appointmentDate, + this.appointmentNo, + this.cashPrice, + this.cashPriceTax, + this.cashPriceWithTax, + this.clinicID, + this.clinicName, + this.companyId, + this.companyName, + this.companyShareWithTax, + this.doctorImageURL, + this.doctorNameObj, + this.doctorSpeciality, + this.errCode, + this.groupID, + this.iSAllowOnlineCheckedIN, + this.insurancePolicyNo, + this.isExcludedForOnlineCheckin, + this.isFollowup, + this.isLiveCareAppointment, + this.isOnlineCheckedIN, + this.message, + this.nextAction, + this.patientCardID, + this.patientID, + this.patientShare, + this.patientShareWithTax, + this.patientStatusType, + this.patientTaxAmount, + this.patientType, + this.paymentAmount, + this.paymentDate, + this.paymentMethodName, + this.paymentReferenceNumber, + this.policyId, + this.policyName, + this.procedureName, + this.projectID, + this.projectName, + this.setupID, + this.sourceType, + this.startTime, + this.status, + this.statusCode, + this.statusDesc, + this.subPolicyNo, + this.userID}); + + PatientShareResponse.fromJson(Map json) { + advanceNumber = json['AdvanceNumber']; + appointmentDate = json['AppointmentDate']; + appointmentNo = json['AppointmentNo']; + cashPrice = json['CashPrice']; + cashPriceTax = json['CashPriceTax']; + cashPriceWithTax = json['CashPriceWithTax']; + clinicID = json['ClinicID']; + clinicName = json['ClinicName']; + companyId = json['CompanyId']; + companyName = json['CompanyName']; + companyShareWithTax = json['CompanyShareWithTax']; + doctorImageURL = json['DoctorImageURL']; + doctorNameObj = json['DoctorNameObj']; + doctorSpeciality = json['DoctorSpeciality'].cast(); + errCode = json['ErrCode']; + groupID = json['GroupID']; + iSAllowOnlineCheckedIN = json['ISAllowOnlineCheckedIN']; + insurancePolicyNo = json['InsurancePolicyNo']; + isExcludedForOnlineCheckin = json['IsExcludedForOnlineCheckin']; + isFollowup = json['IsFollowup']; + isLiveCareAppointment = json['IsLiveCareAppointment']; + isOnlineCheckedIN = json['IsOnlineCheckedIN']; + message = json['Message']; + nextAction = json['NextAction']; + patientCardID = json['PatientCardID']; + patientID = json['PatientID']; + patientShare = json['PatientShare']; + patientShareWithTax = json['PatientShareWithTax']; + patientStatusType = json['PatientStatusType']; + patientTaxAmount = json['PatientTaxAmount']; + patientType = json['PatientType']; + paymentAmount = json['PaymentAmount']; + paymentDate = json['PaymentDate']; + paymentMethodName = json['PaymentMethodName']; + paymentReferenceNumber = json['PaymentReferenceNumber']; + policyId = json['PolicyId']; + policyName = json['PolicyName']; + procedureName = json['ProcedureName']; + projectID = json['ProjectID']; + projectName = json['ProjectName']; + setupID = json['SetupID']; + sourceType = json['SourceType']; + startTime = json['StartTime']; + status = json['Status']; + statusCode = json['StatusCode']; + statusDesc = json['StatusDesc']; + subPolicyNo = json['SubPolicyNo']; + userID = json['UserID']; + } + + Map toJson() { + final Map data = new Map(); + data['AdvanceNumber'] = this.advanceNumber; + data['AppointmentDate'] = this.appointmentDate; + data['AppointmentNo'] = this.appointmentNo; + data['CashPrice'] = this.cashPrice; + data['CashPriceTax'] = this.cashPriceTax; + data['CashPriceWithTax'] = this.cashPriceWithTax; + data['ClinicID'] = this.clinicID; + data['ClinicName'] = this.clinicName; + data['CompanyId'] = this.companyId; + data['CompanyName'] = this.companyName; + data['CompanyShareWithTax'] = this.companyShareWithTax; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorNameObj'] = this.doctorNameObj; + data['DoctorSpeciality'] = this.doctorSpeciality; + data['ErrCode'] = this.errCode; + data['GroupID'] = this.groupID; + data['ISAllowOnlineCheckedIN'] = this.iSAllowOnlineCheckedIN; + data['InsurancePolicyNo'] = this.insurancePolicyNo; + data['IsExcludedForOnlineCheckin'] = this.isExcludedForOnlineCheckin; + data['IsFollowup'] = this.isFollowup; + data['IsLiveCareAppointment'] = this.isLiveCareAppointment; + data['IsOnlineCheckedIN'] = this.isOnlineCheckedIN; + data['Message'] = this.message; + data['NextAction'] = this.nextAction; + data['PatientCardID'] = this.patientCardID; + data['PatientID'] = this.patientID; + data['PatientShare'] = this.patientShare; + data['PatientShareWithTax'] = this.patientShareWithTax; + data['PatientStatusType'] = this.patientStatusType; + data['PatientTaxAmount'] = this.patientTaxAmount; + data['PatientType'] = this.patientType; + data['PaymentAmount'] = this.paymentAmount; + data['PaymentDate'] = this.paymentDate; + data['PaymentMethodName'] = this.paymentMethodName; + data['PaymentReferenceNumber'] = this.paymentReferenceNumber; + data['PolicyId'] = this.policyId; + data['PolicyName'] = this.policyName; + data['ProcedureName'] = this.procedureName; + data['ProjectID'] = this.projectID; + data['ProjectName'] = this.projectName; + data['SetupID'] = this.setupID; + data['SourceType'] = this.sourceType; + data['StartTime'] = this.startTime; + data['Status'] = this.status; + data['StatusCode'] = this.statusCode; + data['StatusDesc'] = this.statusDesc; + data['SubPolicyNo'] = this.subPolicyNo; + data['UserID'] = this.userID; + return data; + } +} diff --git a/lib/pages/BookAppointment/BookConfirm.dart b/lib/pages/BookAppointment/BookConfirm.dart index 6e1bb358..2666f327 100644 --- a/lib/pages/BookAppointment/BookConfirm.dart +++ b/lib/pages/BookAppointment/BookConfirm.dart @@ -1,4 +1,7 @@ import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; @@ -10,11 +13,19 @@ import 'BookSuccess.dart'; class BookConfirm extends StatefulWidget { DoctorList doctor; - DateTime selectedDateTime; String selectedDate; String selectedTime; - BookConfirm({@required this.doctor, this.selectedDateTime, @required this.selectedDate, @required this.selectedTime}); + String appoDateFormatted = ""; + String appoTimeFormatted = ""; + + BookConfirm( + {@required this.doctor, + @required this.selectedDate, + @required this.selectedTime}); + + DoctorsListService service; + PatientShareResponse patientShareResponse; @override _BookConfirmState createState() => _BookConfirmState(); @@ -23,8 +34,8 @@ class BookConfirm extends StatefulWidget { class _BookConfirmState extends State { @override void initState() { - print(widget.doctor.toString()); - print(widget.selectedDateTime); + widget.service = new DoctorsListService(); + widget.patientShareResponse = new PatientShareResponse(); super.initState(); } @@ -213,7 +224,8 @@ class _BookConfirmState extends State { margin: EdgeInsets.fromLTRB(20.0, 5.0, 10.0, 5.0), child: Text( TranslationBase.of(context).date + - ": " + getDate(), + ": " + + getDate(), style: TextStyle( fontSize: 14.0, color: Colors.grey[700], @@ -331,7 +343,8 @@ class _BookConfirmState extends State { disabledTextColor: Colors.white, disabledColor: new Color(0xFFbcc2c4), onPressed: () { - navigateToBookSuccess(context); +// navigateToBookSuccess(context); + insertAppointment(context, widget.doctor); }, child: Text(TranslationBase.of(context).bookNow, style: TextStyle(fontSize: 18.0)), @@ -341,20 +354,67 @@ class _BookConfirmState extends State { ); } + insertAppointment(context, DoctorList docObject) { + widget.service + .insertAppointment(docObject.doctorID, docObject.clinicID, + docObject.projectID, widget.selectedTime, widget.selectedDate) + .then((res) { + if (res['MessageStatus'] == 1) { + AppToast.showSuccessToast(message: "Appointment Booked Successfully"); + print(res['AppointmentNo']); + getPatientShare(context, res['AppointmentNo'], docObject.clinicID, + docObject.projectID, docObject); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + print(err); + }); + } + + getPatientShare(context, String appointmentNo, int clinicID, int projectID, + DoctorList docObject) { + widget.service + .getPatientShare(appointmentNo, clinicID, projectID) + .then((res) { + print(res); + widget.patientShareResponse = new PatientShareResponse.fromJson(res); + navigateToBookSuccess(context, docObject, widget.patientShareResponse); + }).catchError((err) { + print(err); + }); + } + String getTime(DateTime dateTime) { final DateFormat formatter = DateFormat('HH:mm'); - return formatter.format(dateTime); + setState(() { + widget.appoTimeFormatted = formatter.format(dateTime); + print(widget.appoTimeFormatted); + }); + return widget.appoTimeFormatted; } String getDate() { - var dateObj = new DateTime(int.parse(widget.selectedDate.split("-")[0]), int.parse(widget.selectedDate.split("-")[1]), int.parse(widget.selectedDate.split("-")[2]), 0, 0, 0, 0); - return DateUtil.getWeekDay(dateObj.weekday) + - ", " + - dateObj.day.toString() + - " " + - DateUtil.getMonth(dateObj.month) + - " " + - dateObj.year.toString(); + var dateObj = new DateTime( + int.parse(widget.selectedDate.split("-")[0]), + int.parse(widget.selectedDate.split("-")[1]), + int.parse(widget.selectedDate.split("-")[2]), + 0, + 0, + 0, + 0); + + setState(() { + widget.appoDateFormatted = DateUtil.getWeekDay(dateObj.weekday) + + ", " + + dateObj.day.toString() + + " " + + DateUtil.getMonth(dateObj.month) + + " " + + dateObj.year.toString(); + }); + + return widget.appoDateFormatted; } String getDoctorSpeciality(List docSpecial) { @@ -365,8 +425,19 @@ class _BookConfirmState extends State { return docSpeciality; } - Future navigateToBookSuccess(context) async { + Future navigateToBookSuccess(context, DoctorList docObject, + PatientShareResponse patientShareResponse) async { + + print(widget.appoDateFormatted); +// print(widget.appoTimeFormatted); + Navigator.push( - context, MaterialPageRoute(builder: (context) => BookSuccess())); + context, + MaterialPageRoute( + builder: (context) => BookSuccess( + docObject: docObject, + patientShareResponse: patientShareResponse, + appoDateFormatted: widget.appoDateFormatted, + appoTimeFormatted: widget.selectedTime))); } } diff --git a/lib/pages/BookAppointment/BookSuccess.dart b/lib/pages/BookAppointment/BookSuccess.dart index 460d4fff..4745abe3 100644 --- a/lib/pages/BookAppointment/BookSuccess.dart +++ b/lib/pages/BookAppointment/BookSuccess.dart @@ -1,12 +1,26 @@ +import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; +import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:flutter/material.dart'; class BookSuccess extends StatefulWidget { + PatientShareResponse patientShareResponse; + DoctorList docObject; + + String appoDateFormatted; + String appoTimeFormatted; + + BookSuccess( + {@required this.patientShareResponse, + @required this.docObject, + @required this.appoDateFormatted, + @required this.appoTimeFormatted}); + @override - _BookSucceState createState() => _BookSucceState(); + _BookSuccessState createState() => _BookSuccessState(); } -class _BookSucceState extends State { +class _BookSuccessState extends State { @override Widget build(BuildContext context) { return Scaffold( @@ -57,7 +71,8 @@ class _BookSucceState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: [ - Text("Olaya Hospital", style: _getTextStyling()), + Text(widget.docObject.projectName, + style: _getTextStyling()), Container( margin: EdgeInsets.only(top: 5.0), child: @@ -65,18 +80,23 @@ class _BookSucceState extends State { ), Container( margin: EdgeInsets.only(top: 5.0, bottom: 3.0), - child: Text("INTERNAL MEDICINE CLINIC", + child: Text(widget.docObject.clinicName, style: _getTextStyling()), ), Container( margin: EdgeInsets.only(top: 5.0, bottom: 3.0), child: Text( - "Thursday, 31 December 2020, 13:15:00", + widget.appoDateFormatted + + ", " + + widget.appoTimeFormatted, style: _getTextStyling()), ), Container( margin: EdgeInsets.only(top: 5.0, bottom: 3.0), - child: Text("Dr. EYAD ISMAIL ABU-JAYAB", + child: Text( + widget.docObject.doctorTitle + + " " + + widget.docObject.name, style: _getTextStyling()), ), ], @@ -96,13 +116,23 @@ class _BookSucceState extends State { BorderSide(width: 0.5, color: Colors.white)), children: [ TableRow(children: [ - TableCell(child: _getNormalText(TranslationBase.of(context).patientShare)), TableCell( - child: _getNormalText(TranslationBase.of(context).patientShareWithTax)), + child: _getNormalText( + TranslationBase.of(context).patientShare)), + TableCell( + child: _getNormalText(TranslationBase.of(context) + .patientShareWithTax)), ]), TableRow(children: [ - TableCell(child: _getHeadingText("SR 35.7")), - TableCell(child: _getHeadingText("SR 41.06")), + TableCell( + child: _getHeadingText("SR " + + widget.patientShareResponse.patientShare + .toString())), + TableCell( + child: _getHeadingText("SR " + + widget + .patientShareResponse.patientShareWithTax + .toString())), ]), ], ), @@ -189,15 +219,15 @@ class _BookSucceState extends State { textColor: Colors.white, disabledTextColor: Colors.white, disabledColor: new Color(0xFFbcc2c4), - onPressed: () { - }, - child: - Text(TranslationBase.of(context).confirm.toUpperCase(), style: TextStyle(fontSize: 18.0)), + onPressed: () {}, + child: Text( + TranslationBase.of(context).confirm.toUpperCase(), + style: TextStyle(fontSize: 18.0)), ), ), ButtonTheme( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10.0), ), minWidth: MediaQuery.of(context).size.width * 0.7, height: 45.0, @@ -209,8 +239,11 @@ class _BookSucceState extends State { onPressed: () { navigateToHome(context); }, - child: - Text(TranslationBase.of(context).confirmLater.toUpperCase(), style: TextStyle(fontSize: 18.0)), + child: Text( + TranslationBase.of(context) + .confirmLater + .toUpperCase(), + style: TextStyle(fontSize: 18.0)), ), ), ], @@ -257,8 +290,7 @@ class _BookSucceState extends State { } Future navigateToHome(context) async { - Navigator.popUntil( - context, ModalRoute.withName('/')); + Navigator.popUntil(context, ModalRoute.withName('/')); } _getNormalText(text) { diff --git a/lib/pages/BookAppointment/BookingOptions.dart b/lib/pages/BookAppointment/BookingOptions.dart index c207f366..7a9f449e 100644 --- a/lib/pages/BookAppointment/BookingOptions.dart +++ b/lib/pages/BookAppointment/BookingOptions.dart @@ -8,7 +8,7 @@ class BookingOptions extends StatelessWidget { @override Widget build(BuildContext context) { return AppScaffold( - isShowAppBar: true, + isShowAppBar: false, appBarTitle: TranslationBase.of(context).bookAppo, body: Container( margin: EdgeInsets.fromLTRB(10.0, 20.0, 10.0, 10.0), diff --git a/lib/pages/BookAppointment/DoctorProfile.dart b/lib/pages/BookAppointment/DoctorProfile.dart index 0d2ba9cb..42f2b3e8 100644 --- a/lib/pages/BookAppointment/DoctorProfile.dart +++ b/lib/pages/BookAppointment/DoctorProfile.dart @@ -35,6 +35,7 @@ class _DoctorProfileState extends State Widget build(BuildContext context) { return AppScaffold( appBarTitle: TranslationBase.of(context).bookAppo, + isShowAppBar: true, bottomSheet: showFooterButton ? Container( width: MediaQuery.of(context).size.width, @@ -187,7 +188,6 @@ class _DoctorProfileState extends State MaterialPageRoute( builder: (context) => BookConfirm( doctor: widget.doctor, - selectedDateTime: DocAvailableAppointments.selectedAppoDateTime, selectedDate: DocAvailableAppointments.selectedDate, selectedTime: DocAvailableAppointments.selectedTime))); } diff --git a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart index 307e8ed7..df5d1b75 100644 --- a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart +++ b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart @@ -262,6 +262,7 @@ class _DocAvailableAppointmentsState extends State List slotsList = []; DateTime date; final DateFormat formatter = DateFormat('HH:mm'); + final DateFormat dateFormatter = DateFormat('yyyy-MM-dd'); for (var i = 0; i < freeSlotsResponse.length; i++) { date = DateUtil.convertStringToDate(freeSlotsResponse[i]); slotsList.add(FreeSlot(date, ['slot'])); @@ -273,6 +274,7 @@ class _DocAvailableAppointmentsState extends State _eventsParsed = Map.fromIterable(slotsList, key: (e) => e.slot, value: (e) => e.event); setState(() { + DocAvailableAppointments.selectedDate = dateFormatter.format(DateUtil.convertStringToDate(freeSlotsResponse[0])); selectedDate = DateUtil.getMonthDayYearDateFormatted( DateUtil.convertStringToDate(freeSlotsResponse[0])); selectedDateJSON = freeSlotsResponse[0]; @@ -327,6 +329,8 @@ class _DocAvailableAppointmentsState extends State if (res['MessageStatus'] == 1) { if (res['FreeTimeSlots'].length != 0) { freeSlotsResponse = res['FreeTimeSlots']; + print("res['FreeTimeSlots']"); + print(res['FreeTimeSlots'].length); _getJSONSlots().then((value) => { setState(() => {_events.clear(), _events = value}) }); diff --git a/lib/pages/BookAppointment/widgets/DoctorView.dart b/lib/pages/BookAppointment/widgets/DoctorView.dart index fd1ded27..e50829a1 100644 --- a/lib/pages/BookAppointment/widgets/DoctorView.dart +++ b/lib/pages/BookAppointment/widgets/DoctorView.dart @@ -56,6 +56,14 @@ class DoctorView extends StatelessWidget { color: Colors.grey[600], letterSpacing: 1.0)), ), + Container( + margin: EdgeInsets.only(top: 3.0), + child: Text(this.doctor.projectName, + style: TextStyle( + fontSize: 12.0, + color: Colors.grey[600], + letterSpacing: 1.0)), + ), Container( margin: EdgeInsets.only(top: 3.0, bottom: 3.0), child: Text( diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index a6621333..4982035f 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -1,30 +1,70 @@ +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/widgets/upcomingCard.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; class ToDo extends StatefulWidget { + DoctorsListService service; + List appoList = []; + @override _ToDoState createState() => _ToDoState(); } class _ToDoState extends State { + @override + void initState() { + widget.service = new DoctorsListService(); + getPatientAppointmentHistory(); + super.initState(); + } + @override Widget build(BuildContext context) { return AppScaffold( appBarTitle: TranslationBase.of(context).todoList, body: SingleChildScrollView( child: Container( - child: Column( - children: [ - TodoListCard(), - TodoListCard(), - TodoListCard(), - TodoListCard(), - ], + child: ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + physics: ScrollPhysics(), + padding: EdgeInsets.all(0.0), + itemCount: widget.appoList.length, + itemBuilder: (context, index) { + return TodoListCard( + appo: widget.appoList[index], + ); + }, ), ), ), ); } + + getPatientAppointmentHistory() { + widget.service.getPatientAppointmentHistory(true).then((res) { + print(res['AppoimentAllHistoryResultList']); + + if (res['MessageStatus'] == 1) { + setState(() { + if (res['AppoimentAllHistoryResultList'].length != 0) { + widget.appoList.clear(); + res['AppoimentAllHistoryResultList'].forEach((v) { + widget.appoList + .add(new AppoitmentAllHistoryResultList.fromJson(v)); + }); + } else {} + }); + print(widget.appoList.length); + } else { + AppToast.showErrorToast(message: res['ErrorEndUserMessage']); + } + }).catchError((err) { + print(err); + }); + } } diff --git a/lib/pages/ToDoList/widgets/upcomingCard.dart b/lib/pages/ToDoList/widgets/upcomingCard.dart index e6c7fa84..324f9c3e 100644 --- a/lib/pages/ToDoList/widgets/upcomingCard.dart +++ b/lib/pages/ToDoList/widgets/upcomingCard.dart @@ -1,13 +1,25 @@ +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/AppointmentDetails.dart'; import 'package:flutter/material.dart'; import 'package:rating_bar/rating_bar.dart'; class TodoListCard extends StatefulWidget { + + AppoitmentAllHistoryResultList appo; + + TodoListCard({@required this.appo}); + @override _TodoListCardState createState() => _TodoListCardState(); } class _TodoListCardState extends State { + + @override + void initState() { + super.initState(); + } + @override Widget build(BuildContext context) { return Container( @@ -40,7 +52,7 @@ class _TodoListCardState extends State { height: 20.0), Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), - child: Text("Olaya Hospital", + child: Text(widget.appo.projectName, style: TextStyle(fontSize: 12.0)), ), ], @@ -62,7 +74,7 @@ class _TodoListCardState extends State { child: ClipRRect( borderRadius: BorderRadius.circular(100.0), child: Image.network( - "https://hmgwebservices.com/Images/MobileImages/OALAY/2477.png", + widget.appo.doctorImageURL, fit: BoxFit.fill), ), ), @@ -75,7 +87,7 @@ class _TodoListCardState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Dr. EYAD ISMAIL ABU-JAYAD", + Text(widget.appo.doctorTitle + " " + widget.appo.doctorNameObj, style: TextStyle( fontSize: 14.0, color: Colors.black, diff --git a/lib/pages/base/base_view.dart b/lib/pages/base/base_view.dart new file mode 100644 index 00000000..3ed2baad --- /dev/null +++ b/lib/pages/base/base_view.dart @@ -0,0 +1,38 @@ +import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../locator.dart'; + +class BaseView extends StatefulWidget { + final Widget Function(BuildContext context, T model, Widget child) builder; + final Function(T) onModelReady; + + BaseView({ + this.builder, + this.onModelReady, + }); + + @override + _BaseViewState createState() => _BaseViewState(); +} + +class _BaseViewState extends State> { + T model = locator(); + + @override + void initState() { + if (widget.onModelReady != null) { + widget.onModelReady(model); + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (BuildContext context) => model, + child: Consumer(builder: widget.builder), + ); + } +} diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart deleted file mode 100644 index f76f7321..00000000 --- a/lib/pages/home_page.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } -} \ No newline at end of file diff --git a/lib/pages/landing/home_page.dart b/lib/pages/landing/home_page.dart new file mode 100644 index 00000000..0c449410 --- /dev/null +++ b/lib/pages/landing/home_page.dart @@ -0,0 +1,69 @@ +import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/hospital_view_model.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 '../base/base_view.dart'; + +class HomePage extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + Widget build(BuildContext context) { + return BaseView( + onModelReady: (model) => model.getHospitals(), + builder: (BuildContext context, HospitalViewModel model, Widget child) => + AppScaffold( + baseViewModel: model, + body: Column( + children: [ + InkWell( + onTap: () { + model.getHospitals(); + }, + child: Container( + child: Texts('call api '), + ), + + ), + Expanded( + child: _getHospitals(model.hospitals), + ) +// BaseView( +// onModelReady: (dctorViewModel) => dctorViewModel.getHospitals(), +// builder: (BuildContext context, DoctorViewModel dctorViewModel, +// Widget child) => +// InkWell( +// onTap: () { +// dctorViewModel.getHospitals(); +// }, +// child: Container( +// width: double.infinity, +// height: 150, +// child: NetworkBaseView( +// baseViewModel: dctorViewModel, +// child: Container( +// child: Texts('The API 2'), +// ), +// ), +// ), +// ), +// ), + ], + ), + ), + ); + } + + Widget _getHospitals(List hospitals) => ListView.builder( + itemCount: hospitals.length, + itemBuilder: (BuildContext context, int index) => Container( + child: Texts(hospitals[index].name), + ), + ); +} diff --git a/lib/pages/landing_page.dart b/lib/pages/landing/landing_page.dart similarity index 61% rename from lib/pages/landing_page.dart rename to lib/pages/landing/landing_page.dart index 20eac20a..4ed6dc97 100644 --- a/lib/pages/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -1,9 +1,18 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/auth/select_device_imei_res.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/BookingOptions.dart'; +import 'package:diplomaticquarterapp/pages/ToDoList/ToDo.dart'; +import 'package:diplomaticquarterapp/pages/landing/replay_page.dart'; +import 'package:diplomaticquarterapp/providers/auth_provider.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/bottom_navigation/bottom_nav_bar.dart'; import 'package:diplomaticquarterapp/widgets/drawer/app_drawer_widget.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'home_page.dart'; + class LandingPage extends StatefulWidget { @override _LandingPageState createState() => _LandingPageState(); @@ -12,6 +21,8 @@ class LandingPage extends StatefulWidget { class _LandingPageState extends State { int currentTab = 0; PageController pageController; + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); + final authService = new AuthProvider(); _changeCurrentTab(int tab) { setState(() { @@ -24,6 +35,14 @@ class _LandingPageState extends State { void initState() { super.initState(); pageController = PageController(keepPage: true); + _firebaseMessaging.getToken().then((String token) { + sharedPref.setString(PUSH_TOKEN, token); + if (token != null) { + checkUserStatus(token); + } + + //assert(token != null); + }); } @override @@ -31,6 +50,7 @@ class _LandingPageState extends State { return Scaffold( appBar: AppBar( elevation: 0, + backgroundColor: Colors.grey, textTheme: TextTheme( headline6: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), @@ -52,7 +72,13 @@ class _LandingPageState extends State { body: PageView( physics: NeverScrollableScrollPhysics(), controller: pageController, - children: [Container(), Container(), Container(), Container()], + children: [ + HomePage(), + ReplayPage(), + Container(), + ToDo(), + BookingOptions(), + ], ), bottomNavigationBar: BottomNavBar(changeIndex: _changeCurrentTab), ); @@ -69,7 +95,13 @@ class _LandingPageState extends State { case 3: return TranslationBase.of(context).services; case 4: - return TranslationBase.of(context).bookAppo; // Added Case For Book Appointment button in bottom navbar + return TranslationBase.of(context).bookAppo; } } + + void checkUserStatus(token) { + authService + .selectDeviceImei(token) + .then((SelectDeviceIMEIRES value) => print(value)); + } } diff --git a/lib/pages/landing/replay_page.dart b/lib/pages/landing/replay_page.dart new file mode 100644 index 00000000..368f7a1c --- /dev/null +++ b/lib/pages/landing/replay_page.dart @@ -0,0 +1,15 @@ +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'; + +class ReplayPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return AppScaffold( + body: Center( + child: InkWell(onTap: () {}, child: Texts('Replay Page')), + ), + ); + } +} diff --git a/lib/pages/login/forgot-password.dart b/lib/pages/login/forgot-password.dart new file mode 100644 index 00000000..c1fa7b18 --- /dev/null +++ b/lib/pages/login/forgot-password.dart @@ -0,0 +1,95 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; +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'; + +class ForgotPassword extends StatefulWidget { + @override + _ForgotPassword createState() => _ForgotPassword(); +} + +class _ForgotPassword extends State { + String selectedType = 'Saudi Arabia'; + final TextEditingController nationalIDorFile = null; + final TextEditingController mobileNo = null; + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).forgotPassword, + isShowAppBar: true, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10, left: 20, right: 20), + height: SizeConfig.realScreenHeight * .8, + width: SizeConfig.realScreenWidth, + child: Column(children: [ + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context).forgotDesc, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + )), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + // add Expanded to have your dropdown button fill remaining space + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + value: selectedType, + iconSize: 40, + elevation: 16, + onChanged: (String newValue) => { + setState(() { + selectedType = newValue; + }) + }, + items: [ + 'Saudi Arabia', + 'Dubai', + ].map>( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList()))), + ], + ), + MobileNo(controller: mobileNo), + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.grey, + textColor: Colors.white, + child: Text(TranslationBase.of(context).submit), + onPressed: () => {}, + )) + ], + ), + ], + )) + ]), + ))); + } +} diff --git a/lib/pages/login/login-type.dart b/lib/pages/login/login-type.dart new file mode 100644 index 00000000..c0697099 --- /dev/null +++ b/lib/pages/login/login-type.dart @@ -0,0 +1,162 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; +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:diplomaticquarterapp/routes.dart'; + +class LoginType extends StatelessWidget { + static int loginType = 0; + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).welcome, + isShowAppBar: true, + body: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + Expanded( + flex: 4, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/habib-logo.png', + height: 80, + width: 80, + ), + AppText( + TranslationBase.of(context).logintypeRadio, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: InkWell( + onTap: () => { + LoginType.loginType = 1, + Navigator.of(context) + .pushNamed(LOGIN_PAGE) + }, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB( + 20, 10, 20, 10), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/id_card_icon.png', + height: SizeConfig + .imageSizeMultiplier * + 12, + width: SizeConfig + .imageSizeMultiplier * + 15, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .nationalID, + fontSize: + SizeConfig.textMultiplier * + 2, + ) + ], + ), + )))), + Expanded( + child: InkWell( + onTap: () => { + LoginType.loginType = 2, + Navigator.of(context) + .pushNamed(LOGIN_PAGE) + }, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB( + 25, 10, 25, 10), + child: Column( + children: [ + Image.asset( + 'assets/images/my_file_white_icon.png', + height: SizeConfig + .imageSizeMultiplier * + 12, + width: SizeConfig + .imageSizeMultiplier * + 15, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .fileNo, + fontSize: + SizeConfig.textMultiplier * + 2, + ) + ], + ), + )))) + ], + ), + Divider( + color: Colors.grey, + height: 2, + ), + Center( + child: InkWell( + onTap: () => { + Navigator.of(context) + .pushNamed(FORGOT_PASSWORD) + }, + child: AppText( + TranslationBase.of(context).forgotPassword, + fontSize: SizeConfig.textMultiplier * 3, + margin: 10, + underline: true))) + ]), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.grey, + textColor: Colors.white, + child: + Text(TranslationBase.of(context).registerNow), + onPressed: () => { + Navigator.of(context).pushNamed( + REGISTER, + ) + }, + )) + ], + ), + ], + )) + ], + ))); + } +} diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart new file mode 100644 index 00000000..7bb61da5 --- /dev/null +++ b/lib/pages/login/login.dart @@ -0,0 +1,163 @@ +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/model/auth/check_paitent_authentication_req.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/pages/login/login-type.dart'; +import 'package:diplomaticquarterapp/providers/auth_provider.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; +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'; + +class Login extends StatefulWidget { + @override + _Login createState() => _Login(); +} + +class _Login extends State { + final util = Utils(); + final nationalIDorFile = TextEditingController(); + final int loginType = LoginType.loginType; + String mobileNo; + String countryCode = '966'; + bool isButtonDisabled = true; + final authService = new AuthProvider(); + var sharedPref = new AppSharedPreferences(); + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).login, + isShowAppBar: true, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10, left: 20, right: 20), + height: SizeConfig.realScreenHeight * .8, + width: SizeConfig.realScreenWidth, + child: Column(children: [ + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context).enterNationalId, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + )), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + MobileNo( + onNumberChange: (value) => + {mobileNo = value, validateForm()}, + onCountryChange: (value) => countryCode = value), + Container( + child: TextFields( + controller: nationalIDorFile, + onChanged: (value) => {validateForm()}, + prefixIcon: Icon( + loginType == 1 + ? Icons.chrome_reader_mode + : Icons.receipt, + color: Colors.red), + padding: EdgeInsets.only( + top: 20, bottom: 20, left: 10, right: 10), + hintText: loginType == 1 + ? TranslationBase.of(context).nationalID + : TranslationBase.of(context).fileNo, + )) + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: isButtonDisabled == true + ? Colors.grey + : Colors.grey[600], + textColor: Colors.white, + child: Text(TranslationBase.of(context).login), + onPressed: () => {this.startLogin()}, + )) + ], + ), + ], + )) + ]), + ))); + } + + startLogin() { + if (isButtonDisabled == false) { + checkUserAuthentication(); + } + } + + void validateForm() { + if (validateIDBox(nationalIDorFile.text) == true && + mobileNo != null && + util.isSAUDIIDValid(nationalIDorFile.text) == true) { + setState(() { + isButtonDisabled = false; + }); + } else { + setState(() { + isButtonDisabled = true; + }); + } + } + + bool validateIDBox(String value) { + Pattern pattern = loginIDPattern(); //r'^\d+(?:\.\d+)?$'; + + RegExp regex = new RegExp(pattern); + return regex.hasMatch(value); + } + + String loginIDPattern() { + var length = loginType == 1 ? 10 : 7; + return "([0-9]{" + length.toString() + "})"; + } + + checkUserAuthentication() { + var request = CheckPatientAuthenticationReq(); + request.isRegister = false; + request.patientMobileNumber = int.parse(mobileNo); + request.zipCode = countryCode; + request.searchType = this.loginType; + request.deviceTypeID = this.loginType; + if (this.loginType == 1) { + request.patientIdentificationID = this.nationalIDorFile.text; + request.patientID = 0; + } else { + request.patientIdentificationID = ''; + request.patientID = int.parse(nationalIDorFile.text); + } + sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request); + authService.checkPatientAuthentication(request).then((value) => { + if (value.isSMSSent) + { + sharedPref.setString(LOGIN_TOKEN_ID, value.LogInTokenID), + sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), + } + else + { + if (value.IsAuthenticated) {this.checkActivationCode()} + } + }); + } + + checkActivationCode() {} +} diff --git a/lib/pages/login/register.dart b/lib/pages/login/register.dart new file mode 100644 index 00000000..6c58ba72 --- /dev/null +++ b/lib/pages/login/register.dart @@ -0,0 +1,139 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/pages/login/login-type.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/card/rounded_container.dart'; +import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; +import 'package:diplomaticquarterapp/widgets/mobile-no/mobile_no.dart'; +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'; + +class Register extends StatefulWidget { + @override + _Register createState() => _Register(); +} + +class _Register extends State { + final TextEditingController nationalIDorFile = null; + final int loginType = LoginType.loginType; + final TextEditingController mobileNo = null; + var isHijri; + + DateTime selectedDate; + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).login, + isShowAppBar: true, + body: SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10, left: 20, right: 20), + height: SizeConfig.realScreenHeight * .8, + width: SizeConfig.realScreenWidth, + child: Column(children: [ + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context).enterNationalId, + fontSize: SizeConfig.textMultiplier * 3.5, + textAlign: TextAlign.left, + )), + Expanded( + flex: 4, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + MobileNo(controller: mobileNo), + Container( + child: TextFields( + controller: nationalIDorFile, + prefixIcon: + Icon(Icons.chrome_reader_mode, color: Colors.red), + padding: EdgeInsets.only( + top: 20, bottom: 20, left: 10, right: 10), + hintText: TranslationBase.of(context).nationalID, + )), + Row( + children: [ + Expanded( + child: Row( + children: [ + Radio( + value: 1, + groupValue: isHijri, + onChanged: (value) { + setState(() { + isHijri = value; + }); + }, + ), + Text(TranslationBase.of(context).hijriDate), + ], + ), + ), + Expanded( + child: Row( + children: [ + Radio( + value: 0, + groupValue: isHijri, + onChanged: (value) { + setState(() { + isHijri = value; + }); + }, + ), + Text(TranslationBase.of(context).gregorianDate), + ], + ), + ), + ], + ), + Row(children: [ + Expanded( + child: RaisedButton.icon( + onPressed: () => {_selectDate(context)}, + icon: Icon(Icons.date_range), + label: Text(selectedDate != null + ? "${selectedDate.toLocal()}".split(' ')[0] + : TranslationBase.of(context).dob))) + ]) + ], + ), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.grey, + textColor: Colors.white, + child: Text(TranslationBase.of(context).login), + onPressed: () => {}, + )) + ], + ), + ], + )) + ]), + ))); + } + + Future _selectDate(BuildContext context) async { + final DateTime picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2015, 8), + lastDate: DateTime(2101)); + if (picked != null && picked != selectedDate) + setState(() { + selectedDate = picked; + }); + } +} diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart new file mode 100644 index 00000000..978ff449 --- /dev/null +++ b/lib/pages/login/welcome.dart @@ -0,0 +1,85 @@ +import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:diplomaticquarterapp/routes.dart'; + +class WelcomeLogin extends StatelessWidget { + @override + Widget build(BuildContext context) { + return AppScaffold( + appBarTitle: TranslationBase.of(context).welcome, + isShowAppBar: true, + body: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + Expanded( + flex: 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/images/habib-logo.png', + height: 80, + width: 80, + ), + Text( + TranslationBase.of(context).welcome, + style: TextStyle(fontSize: 30), + textAlign: TextAlign.left, + ), + Text( + TranslationBase.of(context).welcomeText, + style: TextStyle(fontSize: 24), + textAlign: TextAlign.left, + ), + Text( + TranslationBase.of(context).welcomeText2, + style: TextStyle(fontSize: 24), + textAlign: TextAlign.left, + ) + ]), + ), + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Expanded( + child: RaisedButton( + color: Colors.red[900], + textColor: Colors.white, + child: Text(TranslationBase.of(context).yes), + onPressed: () => { + Navigator.of(context).pushNamed( + LOGIN_TYPE, + ) + }, + )) + ], + ), + Row( + children: [ + Expanded( + child: RaisedButton( + child: Text(TranslationBase.of(context).no), + onPressed: () => { + Navigator.of(context).pushNamed( + REGISTER, + ) + }, + )) + ], + ), + ], + )) + ], + ))); + } +} diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart new file mode 100644 index 00000000..3590355b --- /dev/null +++ b/lib/providers/auth_provider.dart @@ -0,0 +1,124 @@ +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/model/auth/check_paitent_authentication_req.dart'; +import 'package:diplomaticquarterapp/core/model/auth/select_device_imei_res.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:flutter/cupertino.dart'; + +// SharedPreferences sharedPref = new SharedPreferences(); +enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED } +AppSharedPreferences sharedPref = new AppSharedPreferences(); + +const String INSERT_DEVICE_IMEI = '/Patients.svc/REST/Patient_INSERTDeviceIMEI'; +const String SELECT_DEVICE_IMEI = + '/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; +const String CHECK_PATIENT_AUTH = + '/Authentication.svc/REST/CheckPatientAuthentication'; + +class AuthProvider with ChangeNotifier { + bool isLogin = false; + bool isLoading = true; + AuthProvider() { + getUserAuthentication(); + } + + void getUserAuthentication() async { + Map profile = await sharedPref.getObject(USER_PROFILE); + if (profile != null) { + isLoading = false; + isLogin = true; + } else { + isLoading = false; + isLogin = false; + } + notifyListeners(); + } + + APP_STATUS get stutas { + if (isLoading) { + return APP_STATUS.LOADING; + } else { + if (this.isLogin) { + return APP_STATUS.AUTHENTICATED; + } else { + return APP_STATUS.UNAUTHENTICATED; + } + } + } + + // Future login(UserModel userInfo) async { + // try { + // dynamic localRes; + + // await BaseAppClient.post(LOGIN_URL, + // onSuccess: (dynamic response, int statusCode) { + // localRes = response; + // }, onFailure: (String error, int statusCode) { + // throw error; + // }, body: userInfo.toJson()); + + // return Future.value(localRes); + // } catch (error) { + // print(error); + // throw error; + // } + // } + + Future insertDeviceImei(imei) async { + try { + dynamic localRes; + + await new BaseAppClient().post(INSERT_DEVICE_IMEI, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: imei); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } + + Future selectDeviceImei(imei) async { + try { + dynamic localRes; + await new BaseAppClient().post(SELECT_DEVICE_IMEI, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: imei); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } + + Future checkPatientAuthentication( + CheckPatientAuthenticationReq request) async { + request.versionID = VERSION_ID; + request.channel = CHANNEL; + request.iPAdress = IP_ADDRESS; + request.generalid = GENERAL_ID; + request.languageID = 2; + request.patientOutSA = request.zipCode == '966' ? 0 : 1; + try { + dynamic localRes; + await new BaseAppClient().post(CHECK_PATIENT_AUTH, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request.toJson()); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } +} diff --git a/lib/routes.dart b/lib/routes.dart new file mode 100644 index 00000000..8b3d1d4b --- /dev/null +++ b/lib/routes.dart @@ -0,0 +1,25 @@ +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/pages/login/forgot-password.dart'; +import 'package:diplomaticquarterapp/pages/login/welcome.dart'; +import 'package:diplomaticquarterapp/pages/login/login-type.dart'; +import 'package:diplomaticquarterapp/pages/login/login.dart'; +import 'package:diplomaticquarterapp/pages/login/register.dart'; + +const String INIT_ROUTE = '/'; +const String ROOT = 'root'; +const String HOME = '/'; +const String LOGIN = 'login'; +const String WELCOME_LOGIN = 'welcome-login'; +const String LOGIN_TYPE = 'login-type'; +const String LOGIN_PAGE = 'login-page'; +const String FORGOT_PASSWORD = 'forgot-password'; +const String REGISTER = 'register'; +var routes = { + // ROOT: (_) => RootPage(), + HOME: (_) => LandingPage(), + WELCOME_LOGIN: (_) => WelcomeLogin(), + LOGIN_TYPE: (_) => LoginType(), + LOGIN_PAGE: (_) => Login(), + FORGOT_PASSWORD: (_) => ForgotPassword(), + REGISTER: (_) => Register() +}; diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index 0c929a81..387d06d5 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -1,11 +1,11 @@ -import 'package:diplomaticquarterapp/client/base_app_client.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:diplomaticquarterapp/models/Appointments/InsertAppointmentRequest.dart'; import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -class DoctorsListService { +class DoctorsListService extends BaseService { AppSharedPreferences sharedPref = AppSharedPreferences(); AppGlobal appGlobal = new AppGlobal(); @@ -20,11 +20,11 @@ class DoctorsListService { "Channel": req.Channel, "generalid": 'Cs2020@2016\$2958', "PatientOutSA": 0, - "TokenID": "@dm!n", + "TokenID": "", "DeviceTypeID": req.DeviceTypeID, "SessionID": null, "ClinicID": clinicID, - "ProjectID": 0, + "ProjectID": projectID, "ContinueDentalPlan": false, "IsSearchAppointmnetByClinicID": true, "PatientID": 0, @@ -38,12 +38,12 @@ class DoctorsListService { dynamic localRes; - await BaseAppClient.post(GET_DOCTORS_LIST_URL, + await baseAppClient.post(GET_DOCTORS_LIST_URL, onSuccess: (response, statusCode) async { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: request); + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); return Future.value(localRes); } @@ -77,12 +77,12 @@ class DoctorsListService { dynamic localRes; - await BaseAppClient.post(GET_DOCTORS_LIST_URL, + await baseAppClient.post(GET_DOCTORS_LIST_URL, onSuccess: (response, statusCode) async { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: request); + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); return Future.value(localRes); } @@ -111,12 +111,12 @@ class DoctorsListService { dynamic localRes; - await BaseAppClient.post(GET_DOCTOR_PROFILE, + await baseAppClient.post(GET_DOCTOR_PROFILE, onSuccess: (response, statusCode) async { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: request); + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); return Future.value(localRes); } @@ -145,60 +145,129 @@ class DoctorsListService { dynamic localRes; - await BaseAppClient.post(GET_DOCTOR_FREE_SLOTS, + await baseAppClient.post(GET_DOCTOR_FREE_SLOTS, + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + + Future insertAppointment(int docID, int clinicID, int projectID, + String selectedTime, String selectedDate) async { + Map request; + var languageID = await sharedPref.getString(APP_LANGUAGE); + Request req = appGlobal.getPublicRequest(); + + request = { + "IsForLiveCare": false, + "ProjectID": projectID, + "ClinicID": clinicID, + "DoctorID": docID, + "StartTime": selectedTime, + "SelectedTime": selectedTime, + "EndTime": selectedTime, + "InitialSlotDuration": 0, + "StrAppointmentDate": selectedDate, + "IsVirtual": false, + "DeviceType": "iOS", + "BookedBy": 102, + "VisitType": 1, + "VisitFor": 1, + "VersionID": req.VersionID, + "Channel": req.Channel, + "LanguageID": languageID == 'ar' ? 1 : 2, + "IPAdress": req.IPAdress, + "generalid": req.generalid, + "PatientOutSA": 0, + "SessionID": "YckwoXhUmWBsnHKEKig", + "isDentalAllowedBackend": false, + "DeviceTypeID": 1, + "PatientID": 1231755, + "TokenID": "@dm!n", + "PatientTypeID": 1, + "PatientType": 1 + }; + + dynamic localRes; + + await baseAppClient.post(INSERT_SPECIFIC_APPOINTMENT, + onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + + Future getPatientShare(String appoID, int clinicID, int projectID) async { + Map request; + var languageID = await sharedPref.getString(APP_LANGUAGE); + Request req = appGlobal.getPublicRequest(); + + request = { + "ProjectID": projectID, + "ClinicID": clinicID, + "AppointmentNo": appoID, + "IsActiveAppointment": true, + "VersionID": req.VersionID, + "Channel": req.Channel, + "LanguageID": languageID == 'ar' ? 1 : 2, + "IPAdress": req.IPAdress, + "generalid": req.generalid, + "PatientOutSA": 0, + "SessionID": "YckwoXhUmWBsnHKEKig", + "isDentalAllowedBackend": false, + "DeviceTypeID": 1, + "PatientID": 1231755, + "TokenID": "@dm!n", + "PatientTypeID": 1, + "PatientType": 1 + }; + + dynamic localRes; + + await baseAppClient.post(GET_PATIENT_SHARE, onSuccess: (response, statusCode) async { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: request); + localRes = response['OnlineCheckInAppointments'][0]; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); return Future.value(localRes); } - Future insertAppointment(int docID, int clinicID, int projectID, String selectedTime, String selectedDate) async { + Future getPatientAppointmentHistory(bool isActiveAppointment) async { Map request; var languageID = await sharedPref.getString(APP_LANGUAGE); Request req = appGlobal.getPublicRequest(); - InsertAppointmentRequest insertAppointmentRequest = - new InsertAppointmentRequest(); - - insertAppointmentRequest.VersionID = req.VersionID; - insertAppointmentRequest.Channel = "3"; - insertAppointmentRequest.LanguageID = languageID == 'ar' ? 1 : 2; - insertAppointmentRequest.IPAdress = "10.20.10.20"; - insertAppointmentRequest.generalid = "Cs2020@2016\$2958"; - insertAppointmentRequest.PatientOutSA = 0; - insertAppointmentRequest.SessionID = ""; - insertAppointmentRequest.isDentalAllowedBackend = false; - insertAppointmentRequest.DeviceTypeID = 1; - insertAppointmentRequest.DeviceType = "Android"; - - insertAppointmentRequest.DoctorID = docID; - insertAppointmentRequest.ClinicID = clinicID; - insertAppointmentRequest.ProjectID = projectID; - insertAppointmentRequest.IsForLiveCare = false; - insertAppointmentRequest.BookedBy = 102; - insertAppointmentRequest.IsVirtual = false; - insertAppointmentRequest.PatientID = "1231755"; - insertAppointmentRequest.VisitFor = 1; - insertAppointmentRequest.VisitType = 1; - insertAppointmentRequest.PatientType = 1; - insertAppointmentRequest.PatientTypeID = 1; - insertAppointmentRequest.InitialSlotDuration = 0; - - insertAppointmentRequest.EndTime = selectedTime; - insertAppointmentRequest.StartTime = selectedTime; - insertAppointmentRequest.SelectedTime = selectedTime; - insertAppointmentRequest.StrAppointmentDate = selectedDate; + request = { + "IsActiveAppointment": isActiveAppointment, + "VersionID": req.VersionID, + "Channel": req.Channel, + "LanguageID": languageID == 'ar' ? 1 : 2, + "IPAdress": req.IPAdress, + "generalid": req.generalid, + "PatientOutSA": 0, + "SessionID": "YckwoXhUmWBsnHKEKig", + "isDentalAllowedBackend": false, + "DeviceTypeID": 1, + "PatientID": 1231755, + "TokenID": "@dm!n", + "PatientTypeID": 1, + "PatientType": 1 + }; dynamic localRes; - await BaseAppClient.post(GET_DOCTOR_FREE_SLOTS, + await baseAppClient.post(GET_PATIENT_APPOINTMENT_HISTORY, onSuccess: (response, statusCode) async { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: request); + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); return Future.value(localRes); } + } diff --git a/lib/services/clinic_services/get_clinic_service.dart b/lib/services/clinic_services/get_clinic_service.dart index 5aaaab3b..b9a023f0 100644 --- a/lib/services/clinic_services/get_clinic_service.dart +++ b/lib/services/clinic_services/get_clinic_service.dart @@ -1,10 +1,11 @@ -import 'package:diplomaticquarterapp/client/base_app_client.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart'; import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; -class ClinicListService { +class ClinicListService extends BaseService { AppSharedPreferences sharedPref = AppSharedPreferences(); AppGlobal appGlobal = new AppGlobal(); @@ -26,7 +27,7 @@ class ClinicListService { dynamic localRes; - await BaseAppClient.post(GET_CLINICS_LIST_URL, + await baseAppClient.post(GET_CLINICS_LIST_URL, onSuccess: (response, statusCode) async { localRes = response; }, onFailure: (String error, int statusCode) { diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 8c0b1c9d..3916efeb 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -54,9 +54,11 @@ class TranslationBase { String get nearestAppo => localizedValues['nearestAppo'][locale.languageCode]; - String get searchByDocText => localizedValues['searchByDocText'][locale.languageCode]; + String get searchByDocText => + localizedValues['searchByDocText'][locale.languageCode]; - String get enterDocName => localizedValues['enterDocName'][locale.languageCode]; + String get enterDocName => + localizedValues['enterDocName'][locale.languageCode]; String get search => localizedValues['search'][locale.languageCode]; @@ -66,29 +68,35 @@ class TranslationBase { String get appoInfo => localizedValues['appoInfo'][locale.languageCode]; - String get availableAppo => localizedValues['availableAppo'][locale.languageCode]; + String get availableAppo => + localizedValues['availableAppo'][locale.languageCode]; String get gender => localizedValues['gender'][locale.languageCode]; String get nationality => localizedValues['nationality'][locale.languageCode]; - String get docQualifications => localizedValues['docQualifications'][locale.languageCode]; + String get docQualifications => + localizedValues['docQualifications'][locale.languageCode]; - String get confirmAppoHeading => localizedValues['confirmAppoHeading'][locale.languageCode]; + String get confirmAppoHeading => + localizedValues['confirmAppoHeading'][locale.languageCode]; String get patientInfo => localizedValues['patientInfo'][locale.languageCode]; String get bookSuccess => localizedValues['bookSuccess'][locale.languageCode]; - String get patientShare => localizedValues['patientShare'][locale.languageCode]; + String get patientShare => + localizedValues['patientShare'][locale.languageCode]; - String get patientShareWithTax => localizedValues['patientShareWithTax'][locale.languageCode]; + String get patientShareWithTax => + localizedValues['patientShareWithTax'][locale.languageCode]; String get confirmAppo => localizedValues['confirmAppo'][locale.languageCode]; String get confirm => localizedValues['confirm'][locale.languageCode]; - String get confirmLater => localizedValues['confirmLater'][locale.languageCode]; + String get confirmLater => + localizedValues['confirmLater'][locale.languageCode]; String get todoList => localizedValues['todoList'][locale.languageCode]; @@ -101,6 +109,52 @@ class TranslationBase { String get date => localizedValues['date'][locale.languageCode]; String get time => localizedValues['time'][locale.languageCode]; + + String get login => localizedValues['login'][locale.languageCode]; + + String get loginregister => + localizedValues['loginregister'][locale.languageCode]; + + String get welcome => localizedValues['welcome'][locale.languageCode]; + + String get welcomeText => + localizedValues['welcome_text'][locale.languageCode]; + + String get welcomeText2 => + localizedValues['welcome_text2'][locale.languageCode]; + + String get yes => localizedValues['yes'][locale.languageCode]; + + String get no => localizedValues['no'][locale.languageCode]; + + String get logintypeRadio => + localizedValues['logintyperadio'][locale.languageCode]; + + String get registerNow => localizedValues['registernow'][locale.languageCode]; + + String get nationalID => localizedValues['nationalID'][locale.languageCode]; + + String get fileNo => localizedValues['fileNo'][locale.languageCode]; + + String get forgotPassword => + localizedValues['forgotFileNo'][locale.languageCode]; + + String get enterNationalId => + localizedValues['enter-national-id'][locale.languageCode]; + + String get profileInfo => + localizedValues['profile-info'][locale.languageCode]; + + String get submit => localizedValues['submit'][locale.languageCode]; + + String get forgotDesc => localizedValues['forgot-desc'][locale.languageCode]; + + String get dob => localizedValues['dob'][locale.languageCode]; + + String get hijriDate => localizedValues['hijri-date'][locale.languageCode]; + + String get gregorianDate => + localizedValues['gregorian-date'][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index 02d66c01..ac586b7d 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -1,12 +1,12 @@ - import 'package:connectivity/connectivity.dart'; +import 'package:flutter/cupertino.dart'; + import 'app_shared_preferences.dart'; import 'app_toast.dart'; AppSharedPreferences sharedPref = new AppSharedPreferences(); class Utils { - ///show custom Error Toast /// [message] to show for user static showErrorToast([String message]) { @@ -37,4 +37,47 @@ class Utils { } return localMsg; } + + /// hides the keyboard if its already open + static hideKeyboard(BuildContext context) { + FocusScope.of(context).unfocus(); + } + + bool isSAUDIIDValid(String id) { + if (id == null) { + return false; + } + try { + id = id.toString(); + id = id.trim(); + var returnValue = int.parse(id); + var sum = 0; + if (returnValue > 0) { + var type = int.parse(id[0]); + + if (id.length != 10) { + return false; + } + if (type != 2 && type != 1) { + return false; + } + + for (var i = 0; i < 10; i++) { + if (i % 2 == 0) { + var a = id[i]; + var x = int.parse(a) * 2; + var b = x.toString(); + if (b.length == 1) { + b = "0" + b; + } + sum += int.parse(b[0]) + int.parse(b[1]); + } else { + sum += int.parse(id[i]); + } + } + return sum % 10 == 0; + } + } catch (err) {} + return false; + } } diff --git a/lib/widgets/bottom_navigation/bottom_nav_bar.dart b/lib/widgets/bottom_navigation/bottom_nav_bar.dart index 737ad603..5966ec46 100644 --- a/lib/widgets/bottom_navigation/bottom_nav_bar.dart +++ b/lib/widgets/bottom_navigation/bottom_nav_bar.dart @@ -25,10 +25,10 @@ class _BottomNavBarState extends State { _index = index; // Navigate to Appointment Booking Flow - if (_index == 4) navigateToBookingOptions(context); + // if (_index == 4) navigateToBookingOptions(context); // Navigate to upcoming list - if (_index == 3) navigateToToDoList(context); + //if (_index == 3) navigateToToDoList(context); }); } diff --git a/lib/widgets/buttons/BottomButton.dart b/lib/widgets/buttons/BottomButton.dart new file mode 100644 index 00000000..3e85aa1e --- /dev/null +++ b/lib/widgets/buttons/BottomButton.dart @@ -0,0 +1,148 @@ +import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; +import 'package:flutter/material.dart'; + +/// [label] button label +/// [icon] button icon its optional +/// [color] the background color +/// [textColor] the text color +/// [onTap] button function +/// [loading] show the progress indicator +/// [disabled] disabled the button +/// [borderColor] the button border color +/// [child] the child inside the button +/// [disabledPadding] remove padding +class BottomButton extends StatelessWidget { + final bool loading; + final bool disabled; + final String label; + final Widget icon; + final Color color; + final Color textColor; + final Color borderColor; + final Function onTap; + final Widget child; + final bool disabledPadding; + + BottomButton( + {Key key, + this.loading = false, + this.disabled = false, + this.label, + this.icon, + this.color, + this.textColor, + this.disabledPadding = false, + this.borderColor, + this.onTap, + this.child}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + stops: [ + 0.0, + 0.9 + ], + colors: [ + Theme.of(context).backgroundColor, + Theme.of(context).backgroundColor.withOpacity(0) + ]), + ), + alignment: Alignment.center, + child: SafeArea( + top: false, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: child != null + ? EdgeInsets.only( + left: 14.0, right: 14.0, top: 14.0, bottom: 14) + : EdgeInsets.only( + left: 30.0, right: 30.0, top: 14.0, bottom: 14), + decoration: BoxDecoration( + color: child != null + ? Theme.of(context).backgroundColor + : null, + border: child != null + ? Border.all( + color: Theme.of(context).dividerColor, width: 2.0) + : Border.all(color: Colors.transparent, width: 0.0), + borderRadius: child != null + ? BorderRadius.circular(16.0) + : BorderRadius.circular(0.0), + boxShadow: child != null + ? [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.04), + spreadRadius: -0.0, + offset: Offset(0, 4.0), + blurRadius: 18.0) + ] + : []), + child: Column( + children: [ + if (child != null) + Padding( + padding: disabledPadding + ? EdgeInsets.only( + left: 0.0, + right: 0.0, + top: 14.0, + bottom: label != null ? 0.0 : 14) + : EdgeInsets.only( + left: 18.0, + right: 18.0, + top: 14.0, + bottom: label != null ? 0.0 : 14), + child: child, + ), + if (child != null) + Padding( + padding: EdgeInsets.only(top: 14.0, bottom: 14), + child: Divider(), + ), + if (label != null) + label == null + ? SizedBox(height: 50.0) + : Padding( + padding: child != null + ? EdgeInsets.only( + bottom: 16.0, left: 16.0, right: 16.0) + : EdgeInsets.zero, + child: SecondaryButton( + borderColor: borderColor, + onTap: () { + if (onTap != null) onTap(); + }, + loading: loading, + disabled: disabled, + label: label, + icon: icon, + color: color, + textColor: textColor), + ), + ], + ), + ), + if (label == null && child == null) + Padding( + padding: EdgeInsets.only( + left: 30.0, right: 30.0, top: 14.0, bottom: 14), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/buttons/button.dart b/lib/widgets/buttons/button.dart index d5d8f34e..d63babb5 100644 --- a/lib/widgets/buttons/button.dart +++ b/lib/widgets/buttons/button.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; + /// Button widget /// [label] button label /// [icon] button icon its optional @@ -100,24 +102,12 @@ class _ButtonState extends State