diff --git a/android/app/build.gradle b/android/app/build.gradle index d843c7f9..f154f114 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -210,6 +210,7 @@ dependencies { implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'com.google.android.material:material:1.9.0' + implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.22' androidTestImplementation "androidx.test:core:1.4.0" implementation 'com.airbnb.android:lottie:5.2.0' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.22' diff --git a/android/app/libs/PenNavUI.aar b/android/app/libs/PenNavUI.aar index 6291c4ec..d423bc11 100644 Binary files a/android/app/libs/PenNavUI.aar and b/android/app/libs/PenNavUI.aar differ diff --git a/android/app/libs/Penguin.aar b/android/app/libs/Penguin.aar index 7cdc0b71..5c789c6f 100644 Binary files a/android/app/libs/Penguin.aar and b/android/app/libs/Penguin.aar differ diff --git a/android/app/libs/PenguinRenderer.aar b/android/app/libs/PenguinRenderer.aar index c60248c9..b657ac66 100644 Binary files a/android/app/libs/PenguinRenderer.aar and b/android/app/libs/PenguinRenderer.aar differ diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 64d3eed4..2856e8f1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -34,8 +34,8 @@ - - + + diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinView.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinView.kt index 743ce93b..238765b2 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinView.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinView.kt @@ -207,12 +207,12 @@ internal class PenguinView( .build() // Set location delegate to handle location updates - PlugAndPlaySDK.setPiLocationDelegate { +// PlugAndPlaySDK.setPiLocationDelegate { // Example code to handle location updates // Uncomment and modify as needed // if (location.size() > 0) // Toast.makeText(_context, "Location Info Latitude: ${location[0]}, Longitude: ${location[1]}", Toast.LENGTH_SHORT).show() - } +// } // Set events delegate for reporting issues PlugAndPlaySDK.setPiEventsDelegate { } @@ -231,14 +231,8 @@ internal class PenguinView( try { if (refID.isBlank()) { Log.e("navigateTo", "Invalid refID: The reference ID is blank.") - } - - - // referenceId = refID - - navigator.navigateTo(mContext, refID,object : RefIdDelegate { override fun onRefByIDSuccess(PoiId: String?) { Log.e("navigateTo", "PoiId is penguin view+++++++ $PoiId") diff --git a/assets/images/progress-loading-red-crop-1.gif b/assets/images/progress-loading-red-crop-1.gif new file mode 100644 index 00000000..6dba7901 Binary files /dev/null and b/assets/images/progress-loading-red-crop-1.gif differ diff --git a/ios/Podfile b/ios/Podfile index a4d27ccb..7721bb87 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -3,7 +3,7 @@ platform :ios, '14.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' - +# use_frameworks! :linkage => :static project 'Runner', { 'Debug' => :debug, 'Profile' => :release, @@ -34,6 +34,7 @@ target 'Runner' do pod 'OpenTok', '~> 2.22.0' pod 'VTO2Lib' pod 'MapboxMaps', '10.18.2' + pod 'FLAnimatedImage' flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 5dad833f..2c0073ff 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -31,7 +31,6 @@ 76D71B6E2C6B81CC00DAFB84 /* PenguinPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76D71B6D2C6B81CC00DAFB84 /* PenguinPlugin.swift */; }; 76D71B702C6B81EA00DAFB84 /* PenguinViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76D71B6F2C6B81EA00DAFB84 /* PenguinViewFactory.swift */; }; 76F2556127F1FFED0062C1CD /* PassKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76F2556027F1FFED0062C1CD /* PassKit.framework */; }; - 76F9B0E22C6DED310064C51B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13E5B711BC29EB6ECCE1964C /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -52,6 +51,7 @@ E9C8C136256BACDA00EFFB62 /* HMG_Guest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */; }; E9E27168256E3A4000F49B69 /* LocalizedFromFlutter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */; }; E9F7623B25922BCE00FB5CCF /* FlutterConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F7623A25922BCE00FB5CCF /* FlutterConstants.swift */; }; + FD7241B0D73FB24C87572FAC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E413842321D0D624872E9BE /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -71,7 +71,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 13E5B711BC29EB6ECCE1964C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = ""; }; 29631B9D2C96C7F600DF5916 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = ""; }; @@ -101,6 +100,7 @@ 76F2556027F1FFED0062C1CD /* PassKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PassKit.framework; path = System/Library/Frameworks/PassKit.framework; sourceTree = SDKROOT; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 838788A2BEDC4910F4B029A6 /* 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 = ""; }; + 8E413842321D0D624872E9BE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -134,13 +134,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 76F9B0E22C6DED310064C51B /* Pods_Runner.framework in Frameworks */, 76F2556127F1FFED0062C1CD /* PassKit.framework in Frameworks */, 76815B27275F381C00E66E94 /* HealthKit.framework in Frameworks */, E9620805255C2ED100D3A35D /* NetworkExtension.framework in Frameworks */, 47C935042C91766A00981BA7 /* PenNavUI.xcframework in Frameworks */, 47C935002C91766800981BA7 /* Penguin.xcframework in Frameworks */, 47C935022C91766900981BA7 /* PenguinINRenderer.xcframework in Frameworks */, + FD7241B0D73FB24C87572FAC /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -166,7 +166,7 @@ 76F2556027F1FFED0062C1CD /* PassKit.framework */, 76815B26275F381C00E66E94 /* HealthKit.framework */, E9620804255C2ED100D3A35D /* NetworkExtension.framework */, - 13E5B711BC29EB6ECCE1964C /* Pods_Runner.framework */, + 8E413842321D0D624872E9BE /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -600,7 +600,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 4.5.95; + MARKETING_VERSION = 4.5.991; PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -751,7 +751,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 4.5.95; + MARKETING_VERSION = 4.5.991; PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -794,7 +794,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 4.5.95; + MARKETING_VERSION = 4.5.991; PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift b/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift index 00383010..c4a44243 100644 --- a/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift +++ b/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift @@ -1,11 +1,6 @@ -// -// HMGPenguinInPlatformBridge.swift -// Runner -// -// Created by Haroon Amjad on 13/08/2024. -// - import Foundation +import FLAnimatedImage + var flutterMethodChannelPenguinIn:FlutterMethodChannel? = nil fileprivate var mainViewController:MainFlutterVC! @@ -34,6 +29,7 @@ class HMGPenguinInPlatformBridge{ if let arguments = methodCall.arguments as Any? { if methodCall.method == "launchPenguin"{ + print("====== launchPenguinView Launched =========") self.launchPenguinView(arguments: arguments, result: result) } } else { @@ -41,8 +37,9 @@ class HMGPenguinInPlatformBridge{ } } } - + private func launchPenguinView(arguments: Any, result: @escaping FlutterResult) { + let penguinView = PenguinView( frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height), viewIdentifier: 0, @@ -53,9 +50,45 @@ class HMGPenguinInPlatformBridge{ let penguinUIView = penguinView.view() penguinUIView.frame = mainViewController.view.bounds penguinUIView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + mainViewController.view.addSubview(penguinUIView) - result(nil) // Call result to indicate the method was successfully handled - } + guard let args = arguments as? [String: Any], + let loaderImageData = args["loaderImage"] as? FlutterStandardTypedData else { + print("loaderImage data not found in arguments") + result(FlutterError(code: "ARGUMENT_ERROR", message: "Missing loaderImage data", details: nil)) + return + } + + let loadingOverlay = UIView(frame: UIScreen.main.bounds) + loadingOverlay.backgroundColor = UIColor.black.withAlphaComponent(0.5) // Semi-transparent overlay + loadingOverlay.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + // Display the GIF using FLAnimatedImage + let animatedImage = FLAnimatedImage(animatedGIFData: loaderImageData.data) + let gifImageView = FLAnimatedImageView() + gifImageView.animatedImage = animatedImage + gifImageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) + gifImageView.center = loadingOverlay.center + gifImageView.contentMode = .scaleAspectFit + loadingOverlay.addSubview(gifImageView) + + + if let window = UIApplication.shared.windows.first { + window.addSubview(loadingOverlay) + + } else { + print("Error: Main window not found") + } + + penguinView.onSuccess = { + // Hide and remove the loader + DispatchQueue.main.async { + loadingOverlay.removeFromSuperview() + + } + } + result(nil) + } } diff --git a/ios/Runner/Penguin/PenguinView.swift b/ios/Runner/Penguin/PenguinView.swift index 81377f7b..b5161eb0 100644 --- a/ios/Runner/Penguin/PenguinView.swift +++ b/ios/Runner/Penguin/PenguinView.swift @@ -1,10 +1,17 @@ // + // BlueGpsView.swift + // Runner + // + // Created by Penguin. + // + + import Foundation import UIKit import Flutter @@ -14,211 +21,425 @@ import Foundation import Flutter import UIKit + + /** + * A custom Flutter platform view for displaying Penguin UI components. + * This class integrates with the Penguin navigation SDK and handles UI events. + */ -class PenguinView: NSObject, FlutterPlatformView -, PIEventsDelegate, PenNavInitializationDelegate +class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitializationDelegate + { - // The main view displayed within the platform view + private var _view: UIView + private var model: PenguinModel? + + private var methodChannel: FlutterMethodChannel + + var onSuccess: (() -> Void)? + + + + + /** + * Initializes the PenguinView with the provided parameters. + * + * @param frame The frame of the view, specifying its size and position. + * @param viewId A unique identifier for this view instance. + * @param args Optional arguments provided for creating the view. + * @param messenger The [FlutterBinaryMessenger] used for communication with Dart. + */ + init( + frame: CGRect, + viewIdentifier viewId: Int64, + arguments args: Any?, + binaryMessenger messenger: FlutterBinaryMessenger? + ) { + _view = UIView() + + methodChannel = FlutterMethodChannel(name: "launch_penguin_ui", binaryMessenger: messenger!) + + + super.init() + + // Get the screen's width and height to set the view's frame + let screenWidth = UIScreen.main.bounds.width + let screenHeight = UIScreen.main.bounds.height + + // Uncomment to set the background color of the view + // _view.backgroundColor = UIColor.red + + // Set the frame of the view to cover the entire screen + _view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) + print("========Inside Penguin View ========") + print(args) + guard let arguments = args as? [String: Any] else { + print("Error: Arguments are not in the expected format.") + return + } + print("===== i got tha Args=======") + + // Initialize the model from the arguments + if let penguinModel = PenguinModel(from: arguments) { + self.model = penguinModel + initPenguin(args: penguinModel) + } else { + print("Error: Failed to initialize PenguinModel from arguments ") + } + // Initialize the Penguin SDK with required configurations + // initPenguin( arguments: args) + } + + /** + * Initializes the Penguin SDK with custom configuration settings. + */ + func initPenguin(args: PenguinModel) { + // Set the initialization delegate to handle SDK initialization events + PenNavUIManager.shared.initializationDelegate = self + // Configure the Penguin SDK with necessary parameters + PenNavUIManager.shared + .setClientKey(args.clientKey) + .setClientID(args.clientID) + .setUsername(args.username) + .setSimulationModeEnabled(isEnable: args.isSimulationModeEnabled) + .setBaseURL(dataURL: args.dataURL, positionURL: args.positionURL) + .setServiceName(dataServiceName: args.dataServiceName, positionServiceName: args.positionServiceName) + .setIsShowUserName(args.isShowUserName) + .setIsUpdateUserLocationSmoothly(args.isUpdateUserLocationSmoothly) + .setEnableReportIssue(enable: args.isEnableReportIssue) + .setLanguage(args.languageCode) + .setBackButtonVisibility(true) + .build() + } + + + + /** + * Returns the main view associated with this platform view. + * + * @return The UIView instance that represents this platform view. + */ + func view() -> UIView { + return _view + } + + // MARK: - PIEventsDelegate Methods + + + + + + + + /** + * Called when the Penguin UI is dismissed. + */ + func onPenNavUIDismiss() { + // Handle UI dismissal if needed + print("====== onPenNavUIDismiss =========") + + + self.view().removeFromSuperview() + } + + /** + * Called when a report issue is generated. + * + * @param issue The type of issue reported. + */ + func onReportIssue(_ issue: PenNavUI.IssueType) { + // Handle report issue events if needed + print("====== onReportIssueError =========") + + methodChannel.invokeMethod("onReportIssue", arguments: ["issueType": issue]) + + + } + + /** + * Called when the Penguin UI setup is successful. + */ + func onPenNavSuccess() { + print("====== onPenNavSuccess =========") + + onSuccess?() + + methodChannel.invokeMethod("onPenNavSuccess", arguments: nil) + // Obtain the FlutterViewController instance + let controller: FlutterViewController = UIApplication.shared.windows.first?.rootViewController as! FlutterViewController + - print("====== after contoller onPenNavSuccess =========") + + print("====== after controller onPenNavSuccess =========") + + // Set the events delegate to handle SDK events + PenNavUIManager.shared.eventsDelegate = self + + print("====== after eventsDelegate onPenNavSuccess =========") + + // Present the Penguin UI on top of the Flutter view controller + PenNavUIManager.shared.present(root: controller, view: _view) + + + print("====== after present onPenNavSuccess =========") + print(model?.clinicID) + print("====== after present onPenNavSuccess =========") + + guard let config = self.model else { + print("Error: Config Model is nil") + return + } + + guard let clinicID = self.model?.clinicID, + let clientID = self.model?.clientID, !clientID.isEmpty else { + print("Error: Config Client ID is nil or empty") + return + } + + let navigator = PenguinNavigator(config: config) + + PenNavUIManager.shared.getToken(clientID: config.clientID, clientKey: config.clientKey) { [weak self] token, error in + if let error = error { + let errorMessage = "Token error while getting the for Navigate to method" + print("Failed to get token: \(errorMessage)") + return + } + + guard let token = token else { + print("Token is nil") + return + } + print("Token Generated") + print(token); + + self?.handleNavigation(clinicID: clinicID, token: token) { success, errorMessage in + if success { + print("Navigation successful") + } else { + print("Navigation failed: \(errorMessage ?? "Unknown error")") + } + + } + + print("====== after Token onPenNavSuccess =========") + } + + } + + + + private func handleNavigation(clinicID: String, token: String, completion: @escaping (Bool, String?) -> Void) { + DispatchQueue.main.async { + PenNavUIManager.shared.setToken(token: token) + PenNavUIManager.shared.navigate(to: clinicID) + completion(true,nil) + } + } + + + + + /** + * Called when there is an initialization error with the Penguin UI. + * + * @param errorType The type of initialization error. + * @param errorDescription A description of the error. + */ + func onPenNavInitializationError(errorType: PenNavUI.PenNavUIError, errorDescription: String) { + // Handle initialization errors if needed - + print("onPenNavInitializationErrorType: \(errorType.rawValue)") + print("onPenNavInitializationError: \(errorDescription)") - } - - - - } diff --git a/lib/config/config.dart b/lib/config/config.dart index 53b28a48..1d28ade7 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -22,16 +22,17 @@ var PACKAGES_ORDER_HISTORY = '/api/orders/items'; var PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; // var BASE_URL = 'http://10.50.100.198:2018/'; // var BASE_URL = 'http://10.50.100.198:4422/'; -var BASE_URL = 'https://uat.hmgwebservices.com/'; +var BASE_URL = 'https://uat.hmgwebservices.com/'; // var BASE_URL = 'https://hmgwebservices.com/'; // var BASE_URL = 'http://10.20.200.111:1010/'; +// var BASE_URL = 'https://hmgwebservices.com/'; // var BASE_URL = 'https://orash.cloudsolutions.com.sa/'; // var BASE_URL = 'https://vidauat.cloudsolutions.com.sa/'; // var BASE_URL = 'https://vidamergeuat.cloudsolutions.com.sa/'; // var BASE_URL = 'https://webservices.hmg.com/'; - // var BASE_URL = 'http://10.200.204.42/'; +// var BASE_URL = 'http://10.50.100.198:4422/'; // Pharmacy UAT URLs // var BASE_PHARMACY_URL = 'https://uat.hmgwebservices.com/epharmacy/api/'; @@ -657,6 +658,8 @@ var GET_BIRTH_NOTIFICATION = 'Services/INPs.svc/REST/getBirthNotification_bymoth var SAVE_BIRTH_NOTIFICATION = 'Services/INPs.svc/REST/SaveBirthNotification'; +var INSERT_GENERAL_ADMISSION_CONSENT = 'Services/INPs.svc/REST/Inp_insertAAForGeneralAdmissionConsent'; + //Meal Plan APIs var GET_ADMITTED_PATIENTS = 'Services/MOP.svc/REST/GetAdmittedPatients'; var GET_CURRENT_WEEKID_WEEKDAY = 'Services/MOP.svc/REST/GetCurrentWeekAndDayHMGMP'; @@ -677,6 +680,21 @@ var GET_DENTAL_INSTRUCTIONS = 'Services/OUTPs.svc/Rest/getProcedureNotification' var INSERT_WALKIN_APPOINTMENT = "Services/Doctors.svc/REST/InsertWalkinAppointment"; +//Usage Agreement APIs +var CHECK_USAGE_AGREEMENT = "Services/Patients.svc/REST/CheckForUsageAgreement"; +var GET_USAGE_AGREEMENT = "Services/Patients.svc/REST/GetUsageAgreementText"; +var ADD_USAGE_AGREEMENT = "Services/Patients.svc/REST/AddUsageAgreement"; + +var GET_ER_ONLINE_PAYMENT_DETAILS = 'Services/OUTPs.svc/Rest/Outp_GetPatientPaymentInformationForERClinic'; + +var AUTO_GENERATE_INVOICE_ER = 'Services/OUTPs.svc/Rest/Outp_AutoGenerateInvoiceForER'; + +var CHECK_IF_PATIENT_ARRIVED_ER_ONLINE_CHECKIN = 'Services/OUTPs.svc/Rest/IsPatientArrived'; + +var CHECK_PATIENT_ER_ADVANCE_BALANCE = 'Services/OUTPs.svc/Rest/getPatientAdvanceBalanceAmountByClinic'; + +var GET_PROJECT_FROM_NFC = 'Services/OUTPs.svc/Rest/GetProjectByNFC'; + //PAYFORT var getPayFortProjectDetails = "Services/PayFort_Serv.svc/REST/GetPayFortProjectDetails"; var addPayFortApplePayResponse = "Services/PayFort_Serv.svc/REST/AddResponse"; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 546c2aeb..8bd2ae36 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1964,6 +1964,12 @@ const Map localizedValues = { "admissionReqNo": {"en": "Admission Request No", "ar": "رقم طلب القبول:"}, "dischargeDate": {"en": "Discharge Date", "ar": "تاريخ التفريغ"}, "selectAdmissionText": {"en": "Please select one of the admissions from below to view medical reports:", "ar": "يرجى تحديد أحد حالات القبول من الأسفل لعرض التقارير الطبية:"}, + "onlyAdmitted": {"en": "This service is only available for admitted patients", "ar": "هذه الخدمة متاحة فقط للمرضى المقبولين"}, + "assistYou": {"en": "How we may assist you?", "ar": "كيف يمكننا مساعدتك؟"}, + "receive": {"en": "Receive", "ar": "تجهيز"}, + "PRO": {"en": "PRO", "ar": "علاقات المرضى"}, + "patientRelationOffice": {"en": "Patient Relation Office", "ar": "علاقات المرضى"}, + "roomNo": {"en": "Room No.", "ar": "رقم الغرفة"}, "invalidEligibility": { "en": "You cannot make online payment because you are not eligible to use the provided service.", "ar": "لا يمكنك إجراء الدفع عبر الإنترنت لأنك غير مؤهل لاستخدام الخدمة المقدمة." @@ -2013,4 +2019,99 @@ const Map localizedValues = { "searchByBranch": {"en": "Search By Branch Name", "ar": "البحث عن طريق اسم الفرع"}, "hospitalNavigationTitle": {"en": "Hospital", "ar": "الملاحة"}, "hospitalNavigationSubtitle": {"en": "Navigation", "ar": "المستشفى"}, + "continueAgreeTerms": {"en": "By continuing, You agree to the above Terms and Conditions.", "ar": "من خلال المتابعة، فإنك توافق على الشروط والأحكام المذكورة أعلاه."}, + "agreeText": {"en": "Agree", "ar": "أوافق"}, + "ERCheckInSuccess": {"en": "Your ER Online Check-In has been successfully done.", "ar": "لقد تم تسجيل وصولك للطوارئ عبر الإنترنت بنجاح."}, + "generalConsent": {"en": "General Consent: ", "ar": "موافقة عامة:"}, + + "generalConsent1": { + "en": + "I authorize the Hospital and their staff to conduct any diagnostic examinations, test (including, but not limited to, HIV, HBsAg and any other as the clinician may deem fit), procedures and to provide any medications, treatments or therapy necessary to effectively assess and maintain my health, and to assess, diagnose and treat my illness or injuries. I understand that it is the responsibility of my health care providers to explain the patient's condition and thereby reasons for any particular diagnostic examination, test or procedure, the available treatment options, the common risks, anticipated benefits associated with these options, alternative courses of treatment and possible outcomes of non-treatment.", + "ar": + "أفوض المستشفى وموظفيه بإجراء أية فحوصات واختبارات وإجراءات تشخيصية (بما في ذلك مثالاً وليس حصراً فحوصات أمراض الكبد الوبائية أو نقص المناعة المكتسبة أو أي فحوصات أخرى يرى الطبيب المعالج (مناسبتها وتقديم أية أدوية أو علاج ضروري لتقييم . صحتي والمحافظة عليها بفاعلية والتقييم وتشخيص ومعالجة مرضي او الإصابات اللاحقة بي، وأدرك بأنه من مسؤولية مقدمي الرعاية الصحية بيان أسباب أي فحص أو إختبار أو إجراء تشخيصي محدد وخيارات العلاج المتوفرة والمخاطرة الشائعة والمنافع المتوقعة المرتبطة بهذه الخيارات والعلاج البديل والنتائج المحتملة لرفض العلاج." + }, + "hospitalRules": {"en": "HOSPITAL RULES: ", "ar": "أنظمة المستشفى: "}, + "generalConsent2": { + "en": + "Agree to be obliged to adhere to the Hospital rules, and to ensure compliance by all visitors. In the event of any severe violations of the rules, the hospital reserves the right to take the necessary measures according to the applicable Laws.", + "ar": + "أوافق على التقيد بقواعد وأنظمة المستشفى، وأضمن التزام جميع الزوار بذلك ، في حالة حدوث أي إنتهاكات جسيمة لقواعد وأنظمة المستشفى، يحتفظ المستشفى بالحق في إتخاذ جميع الاجراءات النظامية المكفولة." + }, + "communicationConsent": {"en": "COMMUNICATION VIA EMAIL, TEXT MESSAGES AND PHONE CALLS: ", "ar": "الاتصال عبر البريد الإلكتروني والرسائل النصية والمكالمات الهاتفية: "}, + "generalConsent3": { + "en": + "I understand that the contact number or Email that I have provided on registration will be used for communication by the Hospital. I hereby agree to be notified by the Hospital through SMS, Email, phone calls or any other method, for appointments notifications, special promotions, new features or products, current HMG's medical services, and of any services introduced by the Hospital or any third party in the future or any modifications made to the services offered by the Hospital. And these messages may be submitted as evidence where the Hospital has the right to use at any time whatsoever and as it sees fit. I understand the risks of communicating by email and text messages, in particular the privacy risks. I understand that the Hospital cannot guarantee the security and confidentiality of email or text communication. The Hospital will not be responsible for messages that are not received or delivered due to technical failure, or for disclosure of confidential information unless caused by intentional misconduct.", + "ar": + "المستشفى أدرك بأن رقم الجوال الهاتف أو البريد الإلكتروني الذي قدمته في نموذج التسجيل سيستخدم كوسيلة اتصال بيني وبين | وأقر بموافقتي على قيام المستشفى بإخطاري عن طريق رسائل البريد أو الرسائل القصيرة أو البريد الإلكتروني أو المكالمات الهاتفية أو أي طريقة أخرى بالمواعيد والعروض الترويجية أو المميزات والمنتجات الخاصة بالمستشفى أو) خاصة بأي طرف خارجي) وبأي خدمات طبية تقدمها المجموعة أو قد يطرحها المستشفى في المستقبل أو أي تعديلات قد تطرأ على الخدمات المقدمة من قبل المستشفى. وتعتبر هذه الرسائل دليل إثبات يحق للمستشفى استخدامه في اي وقت يشاء. أفهم مخاطر التواصل عبر البريد الإلكتروني والرسائل النصية خاصة مخاطر الخصوصية وأدرك أن المستشفى لا يمكنه ضمان أمن وسرية البريد الإلكتروني أو الرسائل النصية ولن يكون المستشفى مسؤول عن الرسائل التي لم يتم استلامها أو تسليمها بسبب الفشل التقني أو الكشف عن المعلومات السرية ما لم يكن سببها سوء سلوك متعمد." + }, + "releaseConsent": {"en": "RELEASE OF PERSONAL AND MEDICAL INFORMATION: ", "ar": "الإفصاح عن المعلومات الشخصية والطبية: "}, + "generalConsent4": { + "en": + "On completion of this consent I hereby authorize the hospital to provide any information of whatever nature concerning my treatment, including but not limited to, current conditions/co-morbidities to my insurance carrier or third party payer, for the purpose of determining benefit entitlement and to process payment, therefore taking responsibility for the financial settlement of my medical bills.", + "ar": + "عند تعبئة هذا النموذج ، أصرح بموجبه للمستشفي بتقديم أية معلومات أياً كانت طبيعتها بخصوص حالتي الصحية وعلاجي لشركة التأمين أو لأي طرف آخر مسؤول عن الدفع لأغراض تحديد حق الاستفادة والقيام بالدفع وبالتالي تحمل المسؤولية عن التسوية المالية للفواتير الطبية الخاصة بي." + }, + "generalConsent5": { + "en": + "The Hospital is obliged by local and government regulations to submit certain patient information and I hereby give consent for the disclosure or use of my information as per statutory requirement. I also acknowledge that this consent is subject to the laws and jurisdiction of the country in which the Hospital is located.", + "ar": + " إن المستشفى ملزم بموجب الأنظمة المحلية وأنظمة الدولة بتقديم بعض المعلومات المتعلقة بالمريض وأوافق بموجبه على إفصاح أو استخدام المستشفى للمعلومات الخاصة بي حسبما هو مطلوب نظاماً، وأن هذا الإقرار خاضع للأنظمة والقوانين والاختصاص القضائي للدولة حيث يقع المستشفى." + }, + "valuables": {"en": "VALUABLES: ", "ar": "الممتلكات الثمينة: "}, + "generalConsent6": { + "en": "The Hospital is not liable for the loss or damage of any money, jewelry, documents or other personal articles of value.", + "ar": "المستشفى غير مسؤول عن ضياع أو تلف أي أموال أو مجوهرات أو مستندات أو أي أشياء أخري ذات قيمة." + }, + "financialConsent": {"en": "FINANCIAL AGREEMENT: ", "ar": "الموافقة المالية: "}, + "generalConsent7": { + "en": + "Within the expected time frame during their hospital visit or stay, patients/relatives are required to take personal responsibility and meet any financial obligation towards the Hospital regardless of the mode and source of payment (i.e. self-paying, insurance company, sponsoring company & others). I understand that for credit cases (Insurance covered or corporate patients) approval letter is essential at the time of admission. In case the approval letter is not available, I, the undersigned, agree to be treated as cash patient and advance deposit shall be made. Once approval is obtained the amount paid as advance shall be refunded to me / patient and if there is no approval till discharge the bill shall be settled in full by me/patient.", + "ar": + "يتوجب علي ضمن الاطار الزمني المتوقع أثناء زيارة المستشفى أو الإقامة فيها تحمل المسؤولية الشخصية والوفاء بأي التزام مالي تجاه المستشفى بغض النظر عن طريقة ومصدر الدفع (أي: الدفع الذاتي أو شركة التأمين أو صاحب العمل أو غيره، وأن الموافقة المسبقة ضرورية قبل دخول المستشفى في حالة التغطية المالية من قبل شركة التأمين أو شركة الكفالة في الحالات التي يتم فيها تأخر الموافقة أتعهد أنا الموقع أدناه بالموافقة على العلاج كمريض دفع ذاتي ويجب إيداع مبلغ تحت الحساب يتم استرداده بعد الحصول على موافقة التأمين، ويجب دفع الحساب بالكامل في حالة عدم الحصول على موافقة التأمين حتى موعد الخروج." + }, + "dataSharingConsent": {"en": "DATA SHARING AND INQUIRY: ", "ar": "تبادل المعلومات والاستفسارات: "}, + "generalConsent8": { + "en": + "Hereby, I, the undersigned, agree to provide the Hospital with any information that it requires for the establishing and/or auditing and/or administering my accounts and facilities therewith and I authorize it to obtain and collect any information as it deems necessary or in need for regarding me, my accounts and facilities therewith, from the Saudi Credit Bureau (SIMAH) or to any other agency approved by Saudi Arabian Monetary Agency (SAMA) and to disclose and share (inclusive of Data Pooling) that information to the said company (SIMAH) or to any other agency approved by Saudi Arabian Monetary Agency (SAMA) in accordance with the Membership Agreement and Code of Conduct approved. I agree and acknowledge that the delay in payment or non-payment of Hospital dues is a failure and as a result, SIMAH and/or any other agency approved by will be provided with my name and information to be added to the lists at SIMAH. These lists are accessed by other parties, and I will not be removed from these lists until I pay all of the outstanding amounts.", + "ar": + "بهذا أنا الموقع أدناه أوافق على تزويد المستشفى بأي معلومات أو بيانات يطلبها مني لتأسيس ملفي لدى المستشفى و/أو لمراجعته و/ أو لإدارته وأفوض المستشفى بأن يحصل على ما يلزم أو يحتاج إليه من معلومات تخصني من الشركة السعودية للمعلومات الائتمانية (سمة) واو اي جهة أخرى معتمدة من مؤسسة النقد العربي السعودي (ساما). كما أوافق على أن يفصح المستشفى عن المعلومات الخاصة بي لدى المستشفى للشركة السعودية للمعلومات الائتمانية (سمة) واو اي جهة أخرى معتمدة من مؤسسة النقد العربي السعودي (ساما) من خلال إتفاقية العضوية المبرمة وقواعد العمل المقرة والخاصة بتبادل المعلومات. كما أوافق وأقر بان التأخير في السداد أو عدم السداد لمستحقات المستشفى يعتبر تقصيراً وإخلالاً مني ونتيجة لذلك سيتم تزويد الشركة السعودية للمعلومات الائتمانية (سمه) و/أو أي جهة أخرى توافق عليها مؤسسة النقد العربي السعودي (ساما) بإسمي ومعلوماتي الإضافتها على القوائم لديها هذه القوائم يتم الوصول اليها والإطلاع عليها من قبل جهات أخرى، ولن يتم رفع اسمي من تلك القوائم إلا بعد أداء كافة ما علي من مبالغ مستحقة." + }, + "permissionLeaveConsent": {"en": "PERMISSION TO LEAVE THE HOSPITAL: ", "ar": "قواعد المستشفى: "}, + "generalConsent9": { + "en": + "Fully understand that, at no time, patient can leave the Hospital without prior consent and approval of treating doctor. In case I insist on leaving the Hospital, I must sign an undertaking of my responsibility on leaving the Hospital against the medical advice.", + "ar": "اتفهم انه ليس بإمكاني مغادرة المستشفى في أي وقت شئت دون أخذ إذن طبيبي المعالج. وفي حالة إصراري على مغادرة المستشفى يتعين علي توقيع اقرار مغادرتي ضد النصيحة الطبية وعلى مسؤوليتي." + }, + "observeConsent": {"en": "CONSENT TO OBSERVE: ", "ar": "قواعد المستشفى: "}, + "generalConsent10": { + "en": + "Observers will be allowed according to the Hospital policy as will the taking of pictures of medical or surgical procedures and the use of same for internal staff education or process improvement purposes. Observation and photography or medical or surgical procedures may be done with the approval of the Hospital and in accordance with the Hospital's policy and related laws. I, the undersigned, fully understand that electronically-transmitted information may be used and/or shared by the Hospital with other hospitals for my diagnosis, therapy, follow-up and/or patient education, and may include patient medical records, medical images, interactive audio, video, and/or data communications, output data from medical devices, sound and video files etc. for betterment of patient care.", + "ar": + "وفقاً لسياسة المستشفى، سيتم السماح للمراقبين بمتابعة الإجراءات الطبية والجراحية وسيتم استخدامها لتعليم الموظفين الداخليين أو لأغراض التحسين والتطوير ويمكن إجراء المراقبة والتصوير الفوتوغرافي أو الإجراءات الطبية أو الجراحية بموافقة المستشفى ووفقاً لسياسة المستشفى والانظمة ذات العلاقة. أنا الموقع ادناه أتفهم انه قد يتم الكترونياً إرسال معلومات متعلقة بالتشخيص الطبي لي، العلاج المتابعة وتثقيف المريض، والتي قد تتضمن ملف المريض الطبي النتائج الإشعاعية، التسجيلات الصوتية والمرئية، وذلك بين المستشفى ومستشفيات أخرى بهدف تقديم رعاية صحية أفضل." + }, + "noGuaranteeConsent": {"en": "NO GUARENTEE OF THE RESULTS OF TREATMENT OR EXAMINATION: ", "ar": "لا ضمان لنتائج العلاج أو الفحوصات: "}, + "generalConsent11": { + "en": "I fully understand that no guarantee can be made to me as to the results of treatment or examinations done in the hospital during my hospitalization.", + "ar": "أنا الموقع أدناه أتفهم أنه لا يمكن ضمان نتائج العلاج أو الفحوصات أو الإجراءات التي قد تجرى لي خلال فترة وجودي بالمستشفى." + }, + "disputeConsent": {"en": "GOVERNING LAWS AND DISPUTE RESOLUTION: ", "ar": "النظام الحاكم وحل النزاعات: "}, + "generalConsent12": { + "en": + "This General Consent and Conditions of Admissions is governed by and shall be construed in accordance with the laws of the Kingdom of Saudi Arabia. Any dispute which arises during the execution of it, in which the parties have failed to resolve amicably, will be referred to the concerned judicial authorities in the city of Riyadh, Kingdom of Saudi Arabia.", + "ar": + "تخضع وتفسر هذه الموافقة العامة وشروط القبول للأنظمة المعمول بها في المملكة العربية السعودية. كل خلاف ينشأ عن تنفيذها ولا يتوصل إلى تسويته بين الطرفين وديا يحال إلى الجهة القضائية المختصة بالفصل في النزاع في مدينة الرياض، المملكة العربية السعودية." + }, + "patientsRightsConsent": {"en": "ACKNOWLEDGEMENT OF NOTICE OF PATIENT RIGHTS AND RESPONSIBILITIES: ", "ar": "الإقرار بحقوق ومسؤوليات المرضى: "}, + "generalConsent13": { + "en": + "I, the undersigned, acknowledge that I have been provided with a copy of the Patients' Bill of Right and Responsibilities and the admission staff has explained to me Patients' Bill of Right and Responsibilities.", + "ar": "أنا الموقع أدناه أقر بانه تم تزويدي بـ وثيقة حقوق ومسؤوليات المرضى وقام الموظف المختص بشرح وثيقة حقوق ومسؤوليات المرضى لي." + }, + "acknowledgementConsent": {"en": "ACKNOWLEDGEMENTS: ", "ar": "الإقرارات: "}, + "generalConsent14": { + "en": + "I, the undersigned, acknowledge that I have been provided with a copy of the Patients' Bill of Right and Responsibilities and the admission staff has explained to me Patients' Bill of Right and Responsibilities.", + "ar": + "لقد قرأت وفهمت وأوافق على الشروط والأحكام المبينة أعلاه وأوافق على الإلتزام بالمتطلبات المذكورة تجاه المستشفى ، لقد قرأت التفاصيل المبينة في نموذج التسجيل الخاص بي وأقر بأنها صحيحة. أنا الموقع ادناه أقر بأنه أتيحت لي الفرصة لطرح الأسئلة والتحفظات بشأن هذه الموافقة، وتلقيت إجابات مرضية على جميع إستفساراتي." + }, }; diff --git a/lib/core/viewModels/project_view_model.dart b/lib/core/viewModels/project_view_model.dart index 57362d6f..238ee0f5 100644 --- a/lib/core/viewModels/project_view_model.dart +++ b/lib/core/viewModels/project_view_model.dart @@ -41,6 +41,7 @@ class ProjectViewModel extends BaseViewModel { dynamic searchvalue; bool isLogin = false; bool _isAllAppointmentsLoaded = false; + bool get isAllAppointmentsLoaded => _isAllAppointmentsLoaded; bool isPatientAdmitted = false; bool patientHasAdmissionRequest = false; @@ -74,10 +75,10 @@ class ProjectViewModel extends BaseViewModel { notifyListeners(); } - RegisterInfoResponse _registerInfo = RegisterInfoResponse(); RegisterInfoResponse get registerInfo => _registerInfo; + dynamic get searchValue => searchvalue; Locale get appLocal => _appLocale; @@ -94,7 +95,9 @@ class ProjectViewModel extends BaseViewModel { List _projectDetailListModel = []; List get privileges => isLoginChild ? privilegeChildUser : privilegeChildUser; + List get vidaPlusProjectList => _vidaPlusProjectListModel; + List get hMCProjectListModel => _hMCProjectListModel; List get projectDetailListModel => _projectDetailListModel; @@ -229,8 +232,6 @@ class ProjectViewModel extends BaseViewModel { notifyListeners(); } - - bool havePrivilege(int id) { bool isHavePrivilege = false; try { @@ -251,7 +252,7 @@ class ProjectViewModel extends BaseViewModel { @override void dispose() { - if (subscription != null) subscription.cancel(); + if (subscription != null) subscription.cancel(); super.dispose(); } diff --git a/lib/models/Clinics/EROnlineCheckInPaymentDetailsResponse.dart b/lib/models/Clinics/EROnlineCheckInPaymentDetailsResponse.dart new file mode 100644 index 00000000..884c2e0c --- /dev/null +++ b/lib/models/Clinics/EROnlineCheckInPaymentDetailsResponse.dart @@ -0,0 +1,96 @@ +class EROnlineCheckInPaymentDetailsResponse { + num? cashPrice; + num? cashPriceTax; + num? cashPriceWithTax; + int? companyId; + String? companyName; + num? companyShareWithTax; + dynamic errCode; + int? groupID; + String? insurancePolicyNo; + String? message; + String? patientCardID; + num? patientShare; + num? patientShareWithTax; + num? patientTaxAmount; + int? policyId; + String? policyName; + String? procedureId; + String? procedureName; + dynamic setupID; + int? statusCode; + String? subPolicyNo; + + EROnlineCheckInPaymentDetailsResponse( + {this.cashPrice, + this.cashPriceTax, + this.cashPriceWithTax, + this.companyId, + this.companyName, + this.companyShareWithTax, + this.errCode, + this.groupID, + this.insurancePolicyNo, + this.message, + this.patientCardID, + this.patientShare, + this.patientShareWithTax, + this.patientTaxAmount, + this.policyId, + this.policyName, + this.procedureId, + this.procedureName, + this.setupID, + this.statusCode, + this.subPolicyNo}); + + EROnlineCheckInPaymentDetailsResponse.fromJson(Map json) { + cashPrice = json['CashPrice']; + cashPriceTax = json['CashPriceTax']; + cashPriceWithTax = json['CashPriceWithTax']; + companyId = json['CompanyId']; + companyName = json['CompanyName']; + companyShareWithTax = json['CompanyShareWithTax']; + errCode = json['ErrCode']; + groupID = json['GroupID']; + insurancePolicyNo = json['InsurancePolicyNo']; + message = json['Message']; + patientCardID = json['PatientCardID']; + patientShare = json['PatientShare']; + patientShareWithTax = json['PatientShareWithTax']; + patientTaxAmount = json['PatientTaxAmount']; + policyId = json['PolicyId']; + policyName = json['PolicyName']; + procedureId = json['ProcedureId']; + procedureName = json['ProcedureName']; + setupID = json['SetupID']; + statusCode = json['StatusCode']; + subPolicyNo = json['SubPolicyNo']; + } + + Map toJson() { + final Map data = new Map(); + data['CashPrice'] = this.cashPrice; + data['CashPriceTax'] = this.cashPriceTax; + data['CashPriceWithTax'] = this.cashPriceWithTax; + data['CompanyId'] = this.companyId; + data['CompanyName'] = this.companyName; + data['CompanyShareWithTax'] = this.companyShareWithTax; + data['ErrCode'] = this.errCode; + data['GroupID'] = this.groupID; + data['InsurancePolicyNo'] = this.insurancePolicyNo; + data['Message'] = this.message; + data['PatientCardID'] = this.patientCardID; + data['PatientShare'] = this.patientShare; + data['PatientShareWithTax'] = this.patientShareWithTax; + data['PatientTaxAmount'] = this.patientTaxAmount; + data['PolicyId'] = this.policyId; + data['PolicyName'] = this.policyName; + data['ProcedureId'] = this.procedureId; + data['ProcedureName'] = this.procedureName; + data['SetupID'] = this.setupID; + data['StatusCode'] = this.statusCode; + data['SubPolicyNo'] = this.subPolicyNo; + return data; + } +} diff --git a/lib/models/InPatientServices/get_admission_info_response_model.dart b/lib/models/InPatientServices/get_admission_info_response_model.dart index 85fe08d1..901adda8 100644 --- a/lib/models/InPatientServices/get_admission_info_response_model.dart +++ b/lib/models/InPatientServices/get_admission_info_response_model.dart @@ -19,6 +19,9 @@ class GetAdmissionInfoResponseModel { int? status; String? statusDesc; String? statusDescN; + String? clinicName; + String? doctorName; + String? projectName; GetAdmissionInfoResponseModel( {this.setupID, @@ -40,7 +43,10 @@ class GetAdmissionInfoResponseModel { this.approvalNo, this.status, this.statusDesc, - this.statusDescN}); + this.statusDescN, + this.clinicName, + this.doctorName, + this.projectName}); GetAdmissionInfoResponseModel.fromJson(Map json) { setupID = json['SetupID']; @@ -63,6 +69,9 @@ class GetAdmissionInfoResponseModel { status = json['Status']; statusDesc = json['StatusDesc']; statusDescN = json['StatusDescN']; + clinicName = json['ClinicName']; + doctorName = json['DoctorName']; + projectName = json['ProjectName']; } Map toJson() { @@ -87,6 +96,9 @@ class GetAdmissionInfoResponseModel { data['Status'] = this.status; data['StatusDesc'] = this.statusDesc; data['StatusDescN'] = this.statusDescN; + data['ClinicName'] = this.clinicName; + data['DoctorName'] = this.doctorName; + data['ProjectName'] = this.projectName; return data; } } diff --git a/lib/models/LiveCare/IncomingCallData.dart b/lib/models/LiveCare/IncomingCallData.dart index 06cfd150..e357a5df 100644 --- a/lib/models/LiveCare/IncomingCallData.dart +++ b/lib/models/LiveCare/IncomingCallData.dart @@ -6,7 +6,7 @@ class IncomingCallData { String? notificationForeground; String? count; String? message; - String? appointmentNo; + String? appointmentNo; // 1 for Video call, 2 for Audio call String? title; String? projectID; String? notificationType; diff --git a/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInBookAppointment.dart b/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInBookAppointment.dart new file mode 100644 index 00000000..b5da50d5 --- /dev/null +++ b/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInBookAppointment.dart @@ -0,0 +1,203 @@ +import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/ErService/EROnlineCheckIn/EROnlineCheckInPaymentDetails.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class EROnlineCheckInBookAppointment extends StatefulWidget { + const EROnlineCheckInBookAppointment(); + + @override + State createState() => _EROnlineCheckInBookAppointmentState(); +} + +class _EROnlineCheckInBookAppointmentState extends State with SingleTickerProviderStateMixin { + late ProjectViewModel projectViewModel; + List projectsList = []; + final GlobalKey projectDropdownKey = GlobalKey(); + HospitalsModel? selectedHospital; + String projectDropdownValue = ""; + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + getProjectsList(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + return AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).emergency + " ${TranslationBase.of(context).checkinOptions}", + isShowDecPage: false, + showNewAppBar: true, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: Padding( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + onTap: () { + openDropdown(projectDropdownKey); + }, + child: Container( + width: double.infinity, + decoration: containerRadius(Colors.white, 12), + padding: EdgeInsets.only(left: 10, right: 10, top: 12, bottom: 12), + child: Row( + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).selectHospital, + style: TextStyle( + fontSize: 11, + letterSpacing: -0.44, + fontWeight: FontWeight.w600, + ), + ), + Container( + height: 18, + child: DropdownButtonHideUnderline( + child: DropdownButton( + key: projectDropdownKey, + hint: new Text(TranslationBase.of(context).selectHospital), + value: selectedHospital, + iconSize: 0, + isExpanded: true, + style: TextStyle(fontSize: 14, letterSpacing: -0.56, color: Colors.black), + items: projectsList.map((item) { + return new DropdownMenuItem( + value: item, + child: new Text(item.name!), + ); + }).toList(), + onChanged: (newValue) async { + setState(() { + selectedHospital = newValue; + projectDropdownValue = newValue!.mainProjectID.toString(); + }); + }, + ), + ), + ), + ], + ), + ), + Icon(Icons.keyboard_arrow_down), + ], + ), + ), + ), + mHeight(16), + Container( + width: double.infinity, + decoration: containerRadius(Colors.white, 12), + padding: EdgeInsets.only(left: 10, right: 10, top: 12, bottom: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).clinicName, + style: TextStyle( + fontSize: 11, + letterSpacing: -0.44, + fontWeight: FontWeight.w600, + ), + ), + Text( + "ER Clinic", + style: TextStyle(fontSize: 14, letterSpacing: -0.56, color: Colors.black), + ), + ], + ), + ), + ], + ), + ), + bottomSheet: Container( + height: 80, + color: CustomColors.white, + padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 25.0), + child: DefaultButton( + TranslationBase.of(context).bookAppo, + () { + if (projectDropdownValue == "" || selectedHospital == null) { + AppToast.showErrorToast(message: TranslationBase.of(context).selectHospital); + } else { + Navigator.push( + context, + FadePage( + page: EROnlineCheckInPaymentDetails( + projectID: selectedHospital!.iD, + isERBookAppointment: true, + projectName: selectedHospital!.name ?? "", + ), + ), + ); + } + }, + color: CustomColors.accentColor, + ), + ), + ); + } + + getProjectsList() { + int languageID = projectViewModel.isArabic ? 1 : 2; + GifLoaderDialogUtils.showMyDialog(context); + ClinicListService service = new ClinicListService(); + List projectsListLocal = []; + service.getProjectsList(languageID, context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (res['MessageStatus'] == 1) { + setState(() { + res['ListProject'].forEach((v) { + projectsListLocal.add(new HospitalsModel.fromJson(v)); + }); + projectsList = projectsListLocal; + }); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } + + void openDropdown(GlobalKey key) { + GestureDetector? detector; + void searchForGestureDetector(BuildContext element) { + element.visitChildElements((element) { + if (element.widget != null && element.widget is GestureDetector) { + detector = element.widget as GestureDetector?; + // return false; + } else { + searchForGestureDetector(element); + } + // return true; + }); + } + + searchForGestureDetector(key.currentContext!); + assert(detector != null); + detector!.onTap!(); + } +} diff --git a/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInHome.dart b/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInHome.dart new file mode 100644 index 00000000..6bc73b21 --- /dev/null +++ b/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInHome.dart @@ -0,0 +1,451 @@ +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/pages/ErService/EROnlineCheckIn/EROnlineCheckInBookAppointment.dart'; +import 'package:diplomaticquarterapp/pages/ErService/EROnlineCheckIn/EROnlineCheckInPaymentDetails.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/nfc/nfc_reader_sheet.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_nfc_kit/flutter_nfc_kit.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; + +class EROnlineCheckInHomePage extends StatefulWidget { + const EROnlineCheckInHomePage(); + + @override + State createState() => _EROnlineCheckInHomePageState(); +} + +class _EROnlineCheckInHomePageState extends State with SingleTickerProviderStateMixin { + late ProjectViewModel projectViewModel; + bool _supportsNFC = false; + bool isPatientArrived = false; + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + // checkIfPatientHasArrived(); + if (projectViewModel.isLogin) checkPatientERAdvanceBalance(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + FlutterNfcKit.nfcAvailability.then((value) { + _supportsNFC = (value == NFCAvailability.available); + }); + return AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).emergency + " ${TranslationBase.of(context).checkinOptions}", + isShowDecPage: true, + showNewAppBar: true, + showNewAppBarTitle: true, + description: TranslationBase.of(context).HHCNotAuthMsg, + imagesInfo: [ImagesInfo(imageAr: 'https://hmgwebservices.com/Images/MobileApp/HHC/ar/0.png', imageEn: 'https://hmgwebservices.com/Images/MobileApp/HHC/en/0.png')], + backgroundColor: Color(0xffF8F8F8), + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.check_circle, + size: 50, + color: CustomColors.green, + ), + mHeight(6), + Text( + "What is Online Check-In?", + maxLines: 1, + style: TextStyle( + fontSize: 20, fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 35 / 24), + ), + Text( + "online check-in lets patients fill out forms, share insurance details, and book appointments online, making their visit smoother and quicker.", + style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.44, height: 35 / 24), + ), + mHeight(16), + Text( + "How can i use Online Check-In?", + maxLines: 1, + style: TextStyle( + fontSize: 20, fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 35 / 24), + ), + Text( + "online check-in lets patients fill out forms, share insurance details, and book appointments online, making their visit smoother and quicker.", + style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.44, height: 35 / 24), + ), + ], + ), + ), + ), + mHeight(24), + Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 35, + height: 35, + decoration: BoxDecoration( + color: CustomColors.green, + borderRadius: BorderRadius.circular(50), + ), + child: Center( + child: Text( + "1", + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700, color: CustomColors.white, letterSpacing: -1.44, height: 35 / 24), + ), + ), + ), + mWidth(12), + SvgPicture.asset( + "assets/images/new/tap.svg", + width: 35, + height: 35, + ), + ], + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: Text( + "Tap On", + maxLines: 1, + style: TextStyle( + fontSize: 20, + fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), + fontWeight: FontWeight.w700, + color: Color(0xff2B353E), + letterSpacing: -1.44, + height: 35 / 24), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: Text( + "Tap on the check-in button within the app", + style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.44, height: 35 / 24), + ), + ), + mHeight(16), + Row( + children: [ + Container( + width: 35, + height: 35, + decoration: BoxDecoration( + color: CustomColors.green, + borderRadius: BorderRadius.circular(50), + ), + child: Center( + child: Text( + "2", + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700, color: CustomColors.white, letterSpacing: -1.44, height: 35 / 24), + ), + ), + ), + mWidth(12), + SvgPicture.asset( + "assets/images/new/NFC_Hold.svg", + width: 35, + height: 35, + ), + ], + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: Text( + "Hold your phone", + maxLines: 1, + style: TextStyle( + fontSize: 20, + fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), + fontWeight: FontWeight.w700, + color: Color(0xff2B353E), + letterSpacing: -1.44, + height: 35 / 24), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: Text( + "Hold the phone 1 to 2 cm from the NFC sign displayed on the board", + style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.44, height: 35 / 24), + ), + ), + mHeight(16), + Row( + children: [ + Container( + width: 35, + height: 35, + decoration: BoxDecoration( + color: CustomColors.green, + borderRadius: BorderRadius.circular(50), + ), + child: Center( + child: Text( + "3", + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700, color: CustomColors.white, letterSpacing: -1.44, height: 35 / 24), + ), + ), + ), + mWidth(12), + SvgPicture.asset( + "assets/images/new/hourglass.svg", + width: 35, + height: 35, + ), + ], + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: Text( + "Wait your turn", + maxLines: 1, + style: TextStyle( + fontSize: 20, + fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), + fontWeight: FontWeight.w700, + color: Color(0xff2B353E), + letterSpacing: -1.44, + height: 35 / 24), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: Text( + "Please wait in the waiting area until called by the nurse", + style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.44, height: 35 / 24), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + bottomSheet: Container( + height: projectViewModel.isLogin ? 80 : 1, + color: CustomColors.white, + padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 25.0), + child: isPatientArrived + ? Container( + child: DefaultButton( + TranslationBase.of(context).arrived, + () { + if (_supportsNFC) { + Future.delayed(const Duration(milliseconds: 500), () { + showNfcReader(context, onNcfScan: (String nfcId) { + Future.delayed(const Duration(milliseconds: 100), () { + print(nfcId); + getProjectIDFromNFC(nfcId, true); + // Navigator.push(context, FadePage(page: EROnlineCheckInPaymentDetails())); + }); + }, onCancel: () { + Navigator.of(context).pop(); + }); + }); + } else { + //NFCNotSupported + AppToast.showErrorToast(message: TranslationBase.of(context).NFCNotSupported); + } + }, + color: CustomColors.accentColor, + ), + ) + : Row( + children: [ + Expanded( + flex: 1, + child: DefaultButton( + TranslationBase.of(context).checkinOptions, + () { + if (_supportsNFC) { + Future.delayed(const Duration(milliseconds: 500), () { + showNfcReader(context, onNcfScan: (String nfcId) { + Future.delayed(const Duration(milliseconds: 100), () { + print(nfcId); + getProjectIDFromNFC(nfcId, false); + }); + }, onCancel: () { + Navigator.of(context).pop(); + }); + }); + } else { + //NFCNotSupported + AppToast.showErrorToast(message: TranslationBase.of(context).NFCNotSupported); + } + }, + color: CustomColors.green, + ), + ), + mWidth(12), + Expanded( + flex: 1, + child: DefaultButton( + TranslationBase.of(context).bookAppo, + () { + Navigator.push(context, FadePage(page: EROnlineCheckInBookAppointment())); + }, + color: CustomColors.accentColor, + ), + ), + ], + ), + ), + ); + } + + void getProjectIDFromNFC(String nfcID, bool isArrived) { + GifLoaderDialogUtils.showMyDialog(context); + ClinicListService ancillaryOrdersService = new ClinicListService(); + ancillaryOrdersService.getProjectIDFromNFC(nfcID).then((response) { + if (response["GetProjectByNFC"].length != 0) { + print(response["GetProjectByNFC"]); + int projectID = response['GetProjectByNFC'][0]["ProjectID"]; + String projectName = response['GetProjectByNFC'][0]["ProjectName"]; + GifLoaderDialogUtils.hideDialog(context); + if (isArrived) { + autoGenerateInvoiceER(projectID); + } else { + Navigator.push( + context, + FadePage( + page: EROnlineCheckInPaymentDetails( + projectID: projectID, + isERBookAppointment: false, + projectName: projectName, + ), + ), + ); + } + } else { + AppToast.showErrorToast(message: "Invalid NFC Card Scanned."); + } + }).catchError((err) { + AppToast.showErrorToast(message: err.toString()); + GifLoaderDialogUtils.hideDialog(context); + }); + } + + autoGenerateInvoiceER(int projectID) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + service.autoGenerateInvoiceERClinic(projectID, 4, null, null, null, null, null, null, true).then((res) { + GifLoaderDialogUtils.hideDialog(context); + _showMyDialog(TranslationBase.of(context).ERCheckInSuccess, context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + Future _showMyDialog(String message, BuildContext context) async { + return showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Alert'), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(message), + ], + ), + ), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LandingPage()), (Route r) => false); + }, + ), + ], + ); + }, + ); + } + + void checkIfPatientHasArrived() { + GifLoaderDialogUtils.showMyDialog(context); + ClinicListService ancillaryOrdersService = new ClinicListService(); + ancillaryOrdersService.checkIfPatientHasArrived(15, 10).then((response) { + print(response["IsPatientArrivedResponse"]); + isPatientArrived = response['IsPatientArrivedResponse']["IsPatientArrived"]; + GifLoaderDialogUtils.hideDialog(context); + // erOnlineCheckInPaymentDetailsResponse = EROnlineCheckInPaymentDetailsResponse.fromJson(response["ResponsePatientShare"]); + setState(() {}); + }).catchError((err) { + AppToast.showErrorToast(message: err.toString()); + GifLoaderDialogUtils.hideDialog(context); + }); + } + + void checkPatientERAdvanceBalance() { + GifLoaderDialogUtils.showMyDialog(context); + ClinicListService ancillaryOrdersService = new ClinicListService(); + ancillaryOrdersService.checkPatientERAdvanceBalance(10).then((response) { + print(response["BalanceAmount"]); + isPatientArrived = response['BalanceAmount'] > 0; + GifLoaderDialogUtils.hideDialog(context); + setState(() {}); + }).catchError((err) { + AppToast.showErrorToast(message: err.toString()); + GifLoaderDialogUtils.hideDialog(context); + }); + } +} diff --git a/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInPaymentDetails.dart b/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInPaymentDetails.dart new file mode 100644 index 00000000..13e5c733 --- /dev/null +++ b/lib/pages/ErService/EROnlineCheckIn/EROnlineCheckInPaymentDetails.dart @@ -0,0 +1,620 @@ +import 'dart:developer'; + +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; +import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/Clinics/EROnlineCheckInPaymentDetailsResponse.dart'; +import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; +import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/dragable_sheet.dart'; +import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class EROnlineCheckInPaymentDetails extends StatefulWidget { + int projectID = 0; + bool isERBookAppointment = false; + String projectName = ""; + + EROnlineCheckInPaymentDetails({required this.projectID, required this.isERBookAppointment, required this.projectName}); + + @override + State createState() => _EROnlineCheckInPaymentDetailsState(); +} + +class _EROnlineCheckInPaymentDetailsState extends State with SingleTickerProviderStateMixin { + late ProjectViewModel projectViewModel; + EROnlineCheckInPaymentDetailsResponse? erOnlineCheckInPaymentDetailsResponse; + String? selectedPaymentMethod; + String? selectedInstallmentPlan; + String transID = ""; + late MyInAppBrowser browser; + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + getEROnlineCheckInPaymentDetails(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + return AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).emergency + " ${TranslationBase.of(context).checkinOptions}", + isShowDecPage: false, + showNewAppBar: true, + showNewAppBarTitle: true, + backgroundColor: Color(0xffF8F8F8), + body: Padding( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Padding( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + TranslationBase.of(context).patientInfo, + style: TextStyle( + fontSize: 18, fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 35 / 24), + ), + mHeight(12), + Row( + children: [ + Text( + TranslationBase.of(context).patientName + ":", + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 12, + letterSpacing: -0.6, + color: CustomColors.grey, + ), + ), + mWidth(3), + Text( + projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!, + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + letterSpacing: -0.48, + ), + ), + ], + ), + Row( + children: [ + Text( + TranslationBase.of(context).mrn + ":", + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 12, + letterSpacing: -0.6, + color: CustomColors.grey, + ), + ), + mWidth(3), + Text( + projectViewModel.user.patientID.toString(), + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + letterSpacing: -0.48, + ), + ), + ], + ), + ], + ), + ), + ), + mHeight(24), + Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Padding( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "ER Visit Details", + style: TextStyle( + fontSize: 18, fontFamily: (projectViewModel.isArabic ? 'Cairo' : 'Poppins'), fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 35 / 24), + ), + mHeight(12), + Row( + children: [ + Text( + TranslationBase.of(context).hospital + ":", + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 12, + letterSpacing: -0.6, + color: CustomColors.grey, + ), + ), + mWidth(3), + Text( + widget.projectName, + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + letterSpacing: -0.48, + ), + ), + ], + ), + Row( + children: [ + Text( + TranslationBase.of(context).clinicName + ":", + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 12, + letterSpacing: -0.6, + color: CustomColors.grey, + ), + ), + mWidth(3), + Text( + "ER Clinic", + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + letterSpacing: -0.48, + ), + ), + ], + ), + Row( + children: [ + Text( + "Time Check-In" + ":", + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 12, + letterSpacing: -0.6, + color: CustomColors.grey, + ), + ), + mWidth(3), + Text( + DateUtil.getMonthDayYearDateFormatted(DateTime.now()), + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + letterSpacing: -0.48, + ), + ), + ], + ), + ], + ), + ), + ) + ], + ), + ), + bottomSheet: erOnlineCheckInPaymentDetailsResponse != null + ? Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + padding: EdgeInsets.only(left: 21, right: 21, top: 15, bottom: 15), + width: double.infinity, + // color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: 12), + Text( + TranslationBase.of(context).YouCanPayByTheFollowingOptions, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width * 0.75, + child: getPaymentMethods(), + ), + _amountView(TranslationBase.of(context).patientShareTotalToDo, erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax.toString() + " " + TranslationBase.of(context).sar, + isBold: true, isTotal: true), + SizedBox(height: 12), + DefaultButton( + TranslationBase.of(context).payNow.toUpperCase(), + () { + makePayment(); + }, + color: CustomColors.green, + disabledColor: CustomColors.grey2, + ), + ], + ), + ) + : Container(), + ); + } + + makePayment() { + showDraggableDialog( + context, + PaymentMethod( + onSelectedMethod: (String method, [String? selectedInstallmentPlan]) { + selectedPaymentMethod = method; + this.selectedInstallmentPlan = selectedInstallmentPlan; + if (selectedPaymentMethod == "ApplePay") { + if (projectViewModel.havePrivilege(103)) { + startApplePay(); + } else { + AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); + appo.projectID = widget.projectID; + openPayment(selectedPaymentMethod!, projectViewModel.user, erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax!, AppoitmentAllHistoryResultList()); + } + } else { + openPayment(selectedPaymentMethod!, projectViewModel.user, erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax!, AppoitmentAllHistoryResultList()); + } + }, + patientShare: erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax, + isFromAdvancePayment: false, + ), + ); + } + + openPayment(String paymentMethod, AuthenticatedUser authenticatedUser, num amount, AppoitmentAllHistoryResultList appo) { + transID = Utils.getAdvancePaymentTransID(widget.projectID, projectViewModel.user.patientID!); + + browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart); + + browser.openPaymentBrowser(amount, "ER Online Check-In Payment", transID, widget.projectID.toString(), authenticatedUser.emailAddress!, paymentMethod, authenticatedUser.patientType, + authenticatedUser.firstName!, authenticatedUser.patientID, authenticatedUser, browser, false, "3", "", context); + } + + onBrowserLoadStart(String url) { + print("onBrowserLoadStart"); + print(url); + + MyInAppBrowser.successURLS.forEach((element) { + if (url.contains(element)) { + if (browser.isOpened()) browser.close(); + MyInAppBrowser.isPaymentDone = true; + return; + } + }); + + MyInAppBrowser.errorURLS.forEach((element) { + if (url.contains(element)) { + if (browser.isOpened()) browser.close(); + MyInAppBrowser.isPaymentDone = false; + return; + } + }); + } + + onBrowserExit(AppoitmentAllHistoryResultList appo, bool isPaymentMade) { + print("onBrowserExit Called!!!!"); + checkPaymentStatus(appo); + } + + void startApplePay() async { + transID = Utils.getAdvancePaymentTransID(widget.projectID, projectViewModel.user.patientID!); + + print("TransactionID: $transID"); + GifLoaderDialogUtils.showMyDialog(context); + + LiveCareService service = new LiveCareService(); + ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest(); + + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel; + await context.read().getProjectDetailsForPayfort(projectId: widget.projectID, serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum()).then((value) { + payfortProjectDetailsRespModel = value!; + }); + + applePayInsertRequest.clientRequestID = transID; + applePayInsertRequest.clinicID = 0; + applePayInsertRequest.currency = projectViewModel.user.outSA == 1 ? "AED" : "SAR"; + // applePayInsertRequest.customerEmail = projectViewModel.authenticatedUserObject.user.emailAddress; + applePayInsertRequest.customerEmail = "CustID_${projectViewModel.user.patientID}@HMG.com"; + applePayInsertRequest.customerID = projectViewModel.user.patientID; + applePayInsertRequest.customerName = projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!; + applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN); + applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN); + applePayInsertRequest.doctorID = 0; + applePayInsertRequest.projectID = widget.projectID.toString(); + applePayInsertRequest.serviceID = ServiceTypeEnum.advancePayment.getIdFromServiceEnum().toString(); + applePayInsertRequest.channelID = 3; + applePayInsertRequest.patientID = projectViewModel.user.patientID; + applePayInsertRequest.patientTypeID = projectViewModel.user.patientType; + applePayInsertRequest.patientOutSA = projectViewModel.user.outSA; + applePayInsertRequest.appointmentDate = null; + applePayInsertRequest.appointmentNo = 0; + applePayInsertRequest.orderDescription = "ER Online Check-In Payment"; + applePayInsertRequest.liveServiceID = "0"; + applePayInsertRequest.latitude = "0.0"; + applePayInsertRequest.longitude = "0.0"; + applePayInsertRequest.amount = erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax.toString(); + applePayInsertRequest.isSchedule = "0"; + applePayInsertRequest.language = projectViewModel.isArabic ? 'ar' : 'en'; + applePayInsertRequest.languageID = projectViewModel.isArabic ? 1 : 2; + applePayInsertRequest.userName = projectViewModel.user.patientID; + applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.paymentOption = "ApplePay"; + + applePayInsertRequest.isMobSDK = true; + applePayInsertRequest.merchantReference = transID; + applePayInsertRequest.merchantIdentifier = payfortProjectDetailsRespModel!.merchantIdentifier; + applePayInsertRequest.commandType = "PURCHASE"; + applePayInsertRequest.signature = payfortProjectDetailsRespModel!.signature; + applePayInsertRequest.accessCode = payfortProjectDetailsRespModel!.accessCode; + applePayInsertRequest.shaRequestPhrase = payfortProjectDetailsRespModel!.shaRequest; + applePayInsertRequest.shaResponsePhrase = payfortProjectDetailsRespModel!.shaResponse; + applePayInsertRequest.returnURL = ""; + + service.applePayInsertRequest(applePayInsertRequest, context).then((res) async { + if (res["MessageStatus"] == 1) { + await context.read().initiateApplePayWithPayfort( + customerName: projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!, + // customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress, + customerEmail: "CustID_${projectViewModel.user.patientID}@HMG.com", + orderDescription: "ER Online Check-In Payment", + orderAmount: erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax, + merchantReference: transID, + payfortProjectDetailsRespModel: payfortProjectDetailsRespModel, + currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR", + onFailed: (failureResult) async { + log("failureResult: ${failureResult.toString()}"); + AppToast.showErrorToast(message: failureResult.toString()); + }, + onSuccess: (successResult) async { + log("Payfort: ${successResult.responseMessage}"); + await context.read().addPayfortApplePayResponse(projectViewModel.user.patientID!, result: successResult); + GifLoaderDialogUtils.hideDialog(context); + checkPaymentStatus(AppoitmentAllHistoryResultList()); + }, + projectId: widget.projectID, + serviceTypeEnum: ServiceTypeEnum.appointmentPayment, + ); + } else { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: "An error occurred while processing your request"); + } + }).catchError((err) { + print(err); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + }); + } + + checkPaymentStatus(AppoitmentAllHistoryResultList appo) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + service.checkPaymentStatus(transID, false, context).then((res) { + String paymentInfo = res['Response_Message']; + if (paymentInfo == 'Success') { + GifLoaderDialogUtils.hideDialog(context); + if (widget.isERBookAppointment) { + // createAdvancePayment(res, appo); + ER_createAdvancePayment(res, appo); + } else { + autoGenerateInvoiceER(res); + } + } else { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: res['Response_Message']); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + ER_createAdvancePayment(payment_res, AppoitmentAllHistoryResultList appo) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + String paymentReference = payment_res['Fort_id'].toString(); + service.ER_createAdvancePayment(appo, widget.projectID.toString(), payment_res['Amount'], payment_res['Fort_id'], payment_res['PaymentMethod'], context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + addAdvancedNumberRequest( + // Utils.isVidaPlusProject(projectViewModel, widget.projectID) + // ? res['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString() + // : res['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(), + res['ER_AdvancePaymentResponse']['AdvanceNumber'].toString(), + paymentReference, + 0, + appo, + payment_res); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + createAdvancePayment(paymentRes, AppoitmentAllHistoryResultList appo) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + String paymentReference = paymentRes['Fort_id'].toString(); + service.HIS_createAdvancePayment(appo, widget.projectID.toString(), paymentRes['Amount'], paymentRes['Fort_id'], paymentRes['PaymentMethod'], projectViewModel.user.patientType, + projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!, projectViewModel.user.patientID, context) + .then((res) { + addAdvancedNumberRequest( + Utils.isVidaPlusProject(projectViewModel, widget.projectID) + ? res['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString() + : res['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(), + paymentReference, + 0, + appo, + paymentRes); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + addAdvancedNumberRequest(String advanceNumber, String paymentReference, dynamic appointmentID, AppoitmentAllHistoryResultList appo, paymentRes) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, context).then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (widget.isERBookAppointment) { + AppToast.showSuccessToast(message: "Your appointment has been booked successfully. Please perform Check-In once you arrive at the hospital."); + Navigator.pop(context); + Navigator.pop(context); + Navigator.pop(context); + } else { + autoGenerateInvoiceER(paymentRes); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err.toString()); + print(err); + }); + } + + autoGenerateInvoiceER(res) { + GifLoaderDialogUtils.showMyDialog(context); + DoctorsListService service = new DoctorsListService(); + service.autoGenerateInvoiceERClinic(widget.projectID, 4, res['Fort_id'], res['Amount'], res['PaymentMethod'], res['CardNumber'], res['Merchant_Reference'], res['RRN'], false).then((res) { + GifLoaderDialogUtils.hideDialog(context); + _showMyDialog(TranslationBase.of(context).ERCheckInSuccess, context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + Future _showMyDialog(String message, BuildContext context) async { + return showDialog( + context: context, + barrierDismissible: true, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Alert'), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(message), + ], + ), + ), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LandingPage()), (Route r) => false); + }, + ), + ], + ); + }, + ); + } + + getEROnlineCheckInPaymentDetails() { + GifLoaderDialogUtils.showMyDialog(context); + ClinicListService ancillaryOrdersService = new ClinicListService(); + ancillaryOrdersService.getEROnlineCheckInPaymentDetails(widget.projectID, 10).then((response) { + erOnlineCheckInPaymentDetailsResponse = EROnlineCheckInPaymentDetailsResponse.fromJson(response["ResponsePatientShare"]); + GifLoaderDialogUtils.hideDialog(context); + setState(() {}); + }).catchError((err) { + AppToast.showErrorToast(message: err.toString()); + GifLoaderDialogUtils.hideDialog(context); + }); + } + + _amountView(String title, String value, {bool isBold = false, bool isTotal = false}) { + return Padding( + padding: const EdgeInsets.only(top: 10, bottom: 10), + child: Row(children: [ + Expanded( + child: _getNormalText(title), + ), + Expanded( + child: _getNormalText(value, isBold: isBold, isTotal: isTotal), + ), + ]), + ); + } + + _getNormalText(text, {bool isBold = false, bool isTotal = false}) { + return Text( + text, + style: TextStyle( + fontSize: isBold + ? isTotal + ? 16 + : 12 + : 11, + letterSpacing: -0.5, + color: isBold ? Color(0xff2E303A) : Color(0xff575757), + fontWeight: isTotal ? FontWeight.bold : FontWeight.w600, + ), + ); + } +} diff --git a/lib/pages/InPatientServices/admission_notice.dart b/lib/pages/InPatientServices/admission_notice.dart new file mode 100644 index 00000000..276774ba --- /dev/null +++ b/lib/pages/InPatientServices/admission_notice.dart @@ -0,0 +1,218 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/custom_text_button.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class AdmissionNotice extends StatefulWidget { + const AdmissionNotice(); + + @override + State createState() => _AdmissionNoticeState(); +} + +class _AdmissionNoticeState extends State { + late ProjectViewModel projectViewModel; + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + List inPatientServiceList = getAdmissionNoticeServicesList(context); + return AppScaffold( + isShowAppBar: true, + isShowDecPage: false, + showNewAppBarTitle: true, + showNewAppBar: true, + appBarTitle: TranslationBase.of(context).admissionNoticeTitle, + body: Container( + margin: EdgeInsets.all(20.0), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(left: 12, right: 12), + child: GridView.builder( + shrinkWrap: true, + primary: false, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 2 / 2, crossAxisSpacing: 12, mainAxisSpacing: 12), + padding: EdgeInsets.zero, + itemCount: inPatientServiceList.length, + itemBuilder: (BuildContext context, int index) { + return inPatientServiceList[index]; + }, + ), + ), + ], + ), + ), + ); + } + + List getAdmissionNoticeServicesList(BuildContext context) { + List serviceList = []; + + serviceList.add( + InkWell( + onTap: () { + // openBirthNotificationsPage(context); + viewModalBottomSheet(); + }, + child: MedicalProfileItem( + title: TranslationBase.of(context).admissionNoticeTitle, + imagePath: 'admission.svg', + subTitle: TranslationBase.of(context).insuranceSubtitle, + width: 50.0, + height: 40.0, + isInPatient: true, + ), + ), + ); + + return serviceList; + } + + void viewModalBottomSheet() { + showModalBottomSheet( + context: context, + builder: (context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 20), + child: Text( + "Admission Card", + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 21, + letterSpacing: -0.25, + height: 25 / 17, + ), + ), + ), + Container( + padding: EdgeInsets.all(16.0), + height: 250, + child: Container( + decoration: cardRadius(20, color: Color(0xFFF2B353E)), + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.zero, + child: Container( + width: double.infinity, + height: double.infinity, + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.zero, + decoration: projectViewModel.isArabic + ? containerBottomRightRadiusWithGradientForAr(MediaQuery.of(context).size.width / 4) + : containerBottomRightRadiusWithGradient(MediaQuery.of(context).size.width / 4), + child: Card( + color: Colors.transparent, + margin: EdgeInsets.zero, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + mFlex(2), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Text( + projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user.lastName!, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 17, + letterSpacing: -0.25, + height: 25 / 17, + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Text( + TranslationBase.of(context).roomNo + " " + (projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.roomID! : "Not assigned yet"), + style: TextStyle( + color: Colors.white, + fontSize: 15, + letterSpacing: -0.25, + height: 25 / 17, + ), + ), + ), + mFlex(2), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Text( + projectViewModel.isPatientAdmitted + ? projectViewModel.getAdmissionInfoResponseModel.doctorName!.toString() + : projectViewModel.getAdmissionRequestInfoResponseModel.doctorName!, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 17, + letterSpacing: -0.25, + height: 25 / 17, + ), + ), + ), + // mFlex(2), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Text( + TranslationBase.of(context).clinic + + ": " + + (projectViewModel.isPatientAdmitted + ? projectViewModel.getAdmissionInfoResponseModel.clinicName!.toString() + : projectViewModel.getAdmissionRequestInfoResponseModel.clinicName!), + style: TextStyle( + color: Colors.white, + fontSize: 15, + letterSpacing: -0.25, + height: 25 / 17, + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: Text( + TranslationBase.of(context).hospital + + ": " + + (projectViewModel.isPatientAdmitted + ? projectViewModel.getAdmissionInfoResponseModel.projectName!.toString() + : projectViewModel.getAdmissionRequestInfoResponseModel.projectName!), + style: TextStyle( + color: Colors.white, + fontSize: 15, + letterSpacing: -0.25, + height: 25 / 17, + ), + ), + ), + mFlex(1), + ], + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 30), + child: DefaultButton( + TranslationBase.of(context).close.toUpperCase(), + () { + Navigator.pop(context); + }, + color: CustomColors.accentColor, + disabledColor: CustomColors.grey2, + ), + ), + ], + ); + }); + } +} diff --git a/lib/pages/InPatientServices/inpatient_general_consent.dart b/lib/pages/InPatientServices/inpatient_general_consent.dart new file mode 100644 index 00000000..f0164cda --- /dev/null +++ b/lib/pages/InPatientServices/inpatient_general_consent.dart @@ -0,0 +1,527 @@ +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/custom_text_button.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class InPatientGeneralConsent extends StatelessWidget { + late ProjectViewModel projectViewModel; + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + return AppScaffold( + isShowAppBar: true, + isShowDecPage: false, + showNewAppBarTitle: true, + showNewAppBar: true, + appBarTitle: TranslationBase.of(context).InPatientServicesHeader, + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(21.0), + child: Text( + TranslationBase.of(context).generalConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + Expanded( + child: SingleChildScrollView( + child: Container( + width: MediaQuery.of(context).size.width, + child: Card( + elevation: 0.0, + margin: EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0), + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: BorderSide(color: Colors.transparent, width: 0.0), + ), + child: Padding( + padding: EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent1, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).hospitalRules, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent2, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).communicationConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent3, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).releaseConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent4, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent5, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).valuables, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent6, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).financialConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent7, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).dataSharingConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent8, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).permissionLeaveConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent9, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).observeConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent10, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).noGuaranteeConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent11, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).disputeConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent12, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).patientsRightsConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent13, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(24.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).acknowledgementConsent, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 21.0, + fontWeight: FontWeight.bold, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + mHeight(12.0), + Container( + width: MediaQuery.of(context).size.width * 0.85, + margin: EdgeInsets.only(left: 5.0, right: 5.0), + child: Text( + TranslationBase.of(context).generalConsent14, + overflow: TextOverflow.clip, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 21.0, right: 21.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + flex: 1, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + height: 45.0, + child: CustomTextButton( + backgroundColor: Color(0xffc5272d), + elevation: 0, + onPressed: () { + acceptRejectConsent(context, 0); + }, + child: Text(TranslationBase.of(context).reject, style: TextStyle(fontSize: 16.0, color: Colors.white)), + ), + ), + ), + mWidth(7), + Expanded( + flex: 1, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + height: 45.0, + child: CustomTextButton( + backgroundColor: CustomColors.green, + elevation: 0, + onPressed: () { + acceptRejectConsent(context, 1); + }, + child: Text(TranslationBase.of(context).acceptLbl, style: TextStyle(fontSize: 16.0, color: Colors.white)), + ), + ), + ), + ], + ), + ), + ], + ), + ); + } + + void acceptRejectConsent(BuildContext context, int status) { + ClinicListService service = new ClinicListService(); + GifLoaderDialogUtils.showMyDialog(context); + service + .insertForGeneralAdmissionConsent( + projectViewModel.user.patientID!, + projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionRequestNo! : projectViewModel.getAdmissionRequestInfoResponseModel.admissionRequestNo!, + projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.clinicID! : projectViewModel.getAdmissionRequestInfoResponseModel.clinicId!, + projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.projectID! : projectViewModel.getAdmissionRequestInfoResponseModel.projectId!, + status, + context) + .then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (res["MessageStatus"] == 1) { + AppToast.showErrorToast(message: res["SuccessMsg"]); + } else { + AppToast.showErrorToast(message: res["endUserMessage"]); + } + Navigator.pop(context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } +} diff --git a/lib/pages/InPatientServices/inpatient_home.dart b/lib/pages/InPatientServices/inpatient_home.dart index 4aba8274..d93c93c4 100644 --- a/lib/pages/InPatientServices/inpatient_home.dart +++ b/lib/pages/InPatientServices/inpatient_home.dart @@ -1,9 +1,11 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/InPatientServices/get_general_instructions_response_model.dart'; +import 'package:diplomaticquarterapp/pages/InPatientServices/admission_notice.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/birth_notification.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/general_instructions.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/help_PRO.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/inpatient_advance_payment.dart'; +import 'package:diplomaticquarterapp/pages/InPatientServices/inpatient_general_consent.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/meal_plan.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/medical_instructions.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; @@ -78,6 +80,23 @@ class _InPatientServicesHomeState extends State { List getInPatientServicesList(BuildContext context) { List serviceList = []; + serviceList.add( + InkWell( + onTap: () { + openPatientGeneralConsent(); + }, + child: MedicalProfileItem( + title: TranslationBase.of(context).generalInstructionsTitle, + imagePath: 'general_instructions.svg', + subTitle: TranslationBase.of(context).consent, + width: 50.0, + height: 40.0, + isInPatient: true, + isEnable: true, + ), + ), + ); + serviceList.add( InkWell( onTap: () { @@ -180,6 +199,23 @@ class _InPatientServicesHomeState extends State { ), ); + serviceList.add( + InkWell( + onTap: () { + Navigator.push(context, FadePage(page: AdmissionNotice())); + // if (isReceivePrescriptionEnabled) receivePrescriptionAPI(context); + }, + child: MedicalProfileItem( + title: TranslationBase.of(context).admissionNoticeTitle, + imagePath: 'admission_notice.svg', + subTitle: TranslationBase.of(context).admissionNoticeSubTitle, + width: 50.0, + height: 40.0, + isInPatient: true, + isEnable: true), + ), + ); + serviceList.add( InkWell( onTap: () { @@ -241,18 +277,18 @@ class _InPatientServicesHomeState extends State { void checkDischargeMedications(BuildContext context) { ClinicListService service = new ClinicListService(); GifLoaderDialogUtils.showMyDialog(context); - // service.getDischargeMedicationOrder(projectViewModel.getAdmissionInfoResponseModel).then((res) { - // print(res["PatientHasDischargeMedicineList"].length); - // setState(() { - // if (res["PatientHasDischargeMedicineList"].length != 0) { - // isReceivePrescriptionEnabled = true; - // } - // }); - // GifLoaderDialogUtils.hideDialog(context); - // }).catchError((err) { - // GifLoaderDialogUtils.hideDialog(context); - // print(err); - // }); + service.getDischargeMedicationOrder(projectViewModel.getAdmissionInfoResponseModel).then((res) { + print(res["PatientHasDischargeMedicineList"].length); + setState(() { + if (res["PatientHasDischargeMedicineList"].length != 0) { + isReceivePrescriptionEnabled = true; + } + }); + GifLoaderDialogUtils.hideDialog(context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); } void callReceivePrescriptionAPI(BuildContext context) { @@ -285,6 +321,10 @@ class _InPatientServicesHomeState extends State { }); } + void openPatientGeneralConsent() { + Navigator.push(context, FadePage(page: InPatientGeneralConsent())); + } + void openGeneralInstructions(BuildContext context) { ClinicListService service = new ClinicListService(); GifLoaderDialogUtils.showMyDialog(context); @@ -298,6 +338,7 @@ class _InPatientServicesHomeState extends State { print(res['generalInstructions']); Navigator.push(context, FadePage(page: GeneralInstructions(getGeneralInstructionsList: getGeneralInstructionsList))); } else { + GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: TranslationBase.of(context).noGeneralInstructions); } }).catchError((err) { diff --git a/lib/pages/MyAppointments/widgets/AppointmentActions.dart b/lib/pages/MyAppointments/widgets/AppointmentActions.dart index e7e7b1d0..feb7a514 100644 --- a/lib/pages/MyAppointments/widgets/AppointmentActions.dart +++ b/lib/pages/MyAppointments/widgets/AppointmentActions.dart @@ -204,7 +204,7 @@ class _AppointmentActionsState extends State { Permission.bluetoothScan, Permission.activityRecognition, ].request().whenComplete(() { - PenguinMethodChannel.launch("penguin", widget.projectViewModel!.isArabic ? "ar" : "en", widget.projectViewModel!.authenticatedUserObject.user.patientID.toString(), details: data); + PenguinMethodChannel().launch("penguin", widget.projectViewModel!.isArabic ? "ar" : "en", widget.projectViewModel!.authenticatedUserObject.user.patientID.toString(), details: data); }); } } diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index 6ab67f12..c225987c 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -576,7 +576,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { Permission.bluetoothScan, Permission.activityRecognition, ].request().whenComplete(() { - PenguinMethodChannel.launch("penguin", projectViewModel.isArabic ? "ar" : "en", projectViewModel.authenticatedUserObject.user.patientID.toString(), details: data); + PenguinMethodChannel().launch("penguin", projectViewModel.isArabic ? "ar" : "en", projectViewModel.authenticatedUserObject.user.patientID.toString(), details: data); }); } } diff --git a/lib/pages/landing/fragments/home_page_fragment2.dart b/lib/pages/landing/fragments/home_page_fragment2.dart index a1e12240..b6e9f2d4 100644 --- a/lib/pages/landing/fragments/home_page_fragment2.dart +++ b/lib/pages/landing/fragments/home_page_fragment2.dart @@ -45,6 +45,9 @@ class _HomePageFragment2State extends State { void initState() { // TODO: implement initState super.initState(); + + // getPatientAppointmentHistory1(); + // getFamilyFiles(); } initialiseHmgServices(bool isLogin) { @@ -57,6 +60,7 @@ class _HomePageFragment2State extends State { ? hmgServices.add(HmgServices(2, TranslationBase.of(context).hospitalNavigationTitle, TranslationBase.of(context).hospitalNavigationSubtitle, "assets/images/new/indoor_nav_home.svg", isLogin)) : hmgServices.add(HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + hmgServices.add(HmgServices(9, TranslationBase.of(context).emergency, TranslationBase.of(context).checkinOptions, "assets/images/new/emergency.svg", isLogin)); hmgServices.add(HmgServices(3, TranslationBase.of(context).hhcHome, TranslationBase.of(context).healthCare, "assets/images/new/HHC.svg", isLogin)); hmgServices.add(HmgServices(4, TranslationBase.of(context).checkup, TranslationBase.of(context).comprehensive, "assets/images/new/comprehensive_checkup.svg", isLogin)); hmgServices.add(HmgServices(5, TranslationBase.of(context).online, TranslationBase.of(context).payment, "assets/images/new/paymentMethods.png", isLogin)); @@ -70,9 +74,17 @@ class _HomePageFragment2State extends State { // hmgServices.add(new HmgServices(0, TranslationBase.of(context).liveCare, TranslationBase.of(context).onlineConsulting, "assets/images/new/Live_Care.svg", isLogin)); // hmgServices.add(new HmgServices(1, TranslationBase.of(context).covidTest, TranslationBase.of(context).driveThru, "assets/images/new/CoronaIcon.svg", isLogin)); // hmgServices.add(new HmgServices(2, TranslationBase.of(context).online, TranslationBase.of(context).payment, "assets/images/new/paymentMethods.png", isLogin)); + hmgServices.add(new HmgServices(9, TranslationBase.of(context).emergency, TranslationBase.of(context).checkinOptions, "assets/images/new/emergency.svg", isLogin)); + + projectViewModel.isIndoorNavigationEnabled + ? hmgServices.add(HmgServices(2, TranslationBase.of(context).hospitalNavigationTitle, TranslationBase.of(context).hospitalNavigationSubtitle, "assets/images/new/indoor_nav_home.svg", isLogin)) + : hmgServices.add(HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + hmgServices.add(new HmgServices(3, TranslationBase.of(context).hhcHome, TranslationBase.of(context).healthCare, "assets/images/new/HHC.svg", isLogin)); hmgServices.add(new HmgServices(4, TranslationBase.of(context).checkup, TranslationBase.of(context).comprehensive, "assets/images/new/comprehensive_checkup.svg", isLogin)); - hmgServices.add(new HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + + // hmgServices.add(new HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + hmgServices.add(new HmgServices(6, TranslationBase.of(context).ereferralTitle, TranslationBase.of(context).ereferralSubtitle, "assets/images/new/E_Referral.svg", isLogin)); hmgServices.add(new HmgServices(7, "H\u2082O", TranslationBase.of(context).dailyWater, "assets/images/new/h2o.svg", isLogin)); hmgServices.add(new HmgServices(8, TranslationBase.of(context).connectTitle, TranslationBase.of(context).connectSubtitle, "assets/images/new/reach_us.svg", isLogin)); @@ -346,7 +358,8 @@ class _HomePageFragment2State extends State { itemCount: hmgServices.length, padding: EdgeInsets.zero, itemBuilder: (BuildContext context, int index) { - return ServicesView(hmgServices[index], index, true, projectViewModel, isLocked: (hmgServices[index].action == 2 && projectViewModel.isIndoorNavigationEnabled) ? !projectViewModel.havePrivilege(107) : false); + return ServicesView(hmgServices[index], index, true, projectViewModel, + isLocked: (hmgServices[index].action == 2 && projectViewModel.isIndoorNavigationEnabled) ? !projectViewModel.havePrivilege(107) : false); }, ), ), diff --git a/lib/pages/landing/home_page_2.dart b/lib/pages/landing/home_page_2.dart index 9b52958b..af02e200 100644 --- a/lib/pages/landing/home_page_2.dart +++ b/lib/pages/landing/home_page_2.dart @@ -33,6 +33,11 @@ class _HomePageState2 extends State { PharmacyModuleViewModel pharmacyModuleViewModel = locator(); late ProjectViewModel projectViewModel; + @override + void initState() { + super.initState(); + } + @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); diff --git a/lib/pages/landing/widgets/services_view.dart b/lib/pages/landing/widgets/services_view.dart index e98855aa..a98da010 100644 --- a/lib/pages/landing/widgets/services_view.dart +++ b/lib/pages/landing/widgets/services_view.dart @@ -23,6 +23,7 @@ import 'package:diplomaticquarterapp/pages/ChildVaccines/new/child_initial_page. import 'package:diplomaticquarterapp/pages/ContactUs/contact_us_page.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-drivethru-location.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; +import 'package:diplomaticquarterapp/pages/ErService/EROnlineCheckIn/EROnlineCheckInHome.dart'; import 'package:diplomaticquarterapp/pages/ErService/ErOptions.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/inpatient_home.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; @@ -216,7 +217,7 @@ class ServicesView extends StatelessWidget { Permission.bluetoothScan, Permission.activityRecognition, ].request().whenComplete(() { - PenguinMethodChannel.launch("penguin", projectViewModel.isArabic ? "ar" : "en", projectViewModel.authenticatedUserObject.user.patientID.toString()); + PenguinMethodChannel().launch("penguin", projectViewModel.isArabic ? "ar" : "en", projectViewModel.authenticatedUserObject.user.patientID.toString()); }); } // } @@ -256,6 +257,9 @@ class ServicesView extends StatelessWidget { } else if (hmgServices.action == 23) { Navigator.push(context, FadePage(page: InPatientServicesHome())); locator().hmgServices.logServiceName('find us reach us'); + } else if (hmgServices.action == 9) { + Navigator.push(context, FadePage(page: EROnlineCheckInHomePage())); + locator().hmgServices.logServiceName('ER Online CheckIn'); } } diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart index e4a55d25..bd5a64a6 100644 --- a/lib/pages/login/confirm-login.dart +++ b/lib/pages/login/confirm-login.dart @@ -19,6 +19,7 @@ import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_requ import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/login/login.dart'; import 'package:diplomaticquarterapp/pages/login/register_new.dart'; +import 'package:diplomaticquarterapp/pages/login/user-login-agreement-page.dart'; import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; @@ -48,11 +49,7 @@ class ConfirmLogin extends StatefulWidget { final fromRegistration; final bool isDubai; - const ConfirmLogin({Key? key, - this.changePageViewIndex, - this.fromRegistration = false, - this.isDubai = false}) - : super(key: key); + const ConfirmLogin({Key? key, this.changePageViewIndex, this.fromRegistration = false, this.isDubai = false}) : super(key: key); @override _ConfirmLogin createState() => _ConfirmLogin(); @@ -64,8 +61,7 @@ class _ConfirmLogin extends State { var sharedPref = AppSharedPreferences(); bool authenticated = false; final authService = AuthProvider(); - PharmacyModuleViewModel pharmacyModuleViewModel = - locator(); + PharmacyModuleViewModel pharmacyModuleViewModel = locator(); late int mobileNumber; String errorMsg = ''; SelectDeviceIMEIRES? user; @@ -95,10 +91,8 @@ class _ConfirmLogin extends State { int fingrePrintBefore = 0; - AuthenticatedUserObject authenticatedUserObject = - locator(); - AppointmentRateViewModel appointmentRateViewModel = - locator(); + AuthenticatedUserObject authenticatedUserObject = locator(); + AppointmentRateViewModel appointmentRateViewModel = locator(); late ProjectViewModel projectViewModel; late ToDoCountProviderModel toDoProvider; @@ -145,35 +139,17 @@ class _ConfirmLogin extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - TranslationBase - .of(context) - .welcomeBack, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64), + TranslationBase.of(context).welcomeBack, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64), ), Text( user!.name!.toLowerCase().capitalizeFirstofEach, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w700, - color: Color(0xff2B353E), - height: 1, - letterSpacing: -1.44), + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xff2B353E), height: 1, letterSpacing: -1.44), ), SizedBox(height: 10), Text( - TranslationBase - .of(context) - .accountInfo, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 25 / 16), + TranslationBase.of(context).accountInfo, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), ), Container( height: 72, @@ -192,48 +168,28 @@ class _ConfirmLogin extends State { mainAxisSize: MainAxisSize.min, children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - TranslationBase - .of(context) - .lastLoginAt - .toCamelCase, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64), + TranslationBase.of(context).lastLoginAt.toCamelCase, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64), ), Text( // user!.editedOn != null // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user!.editedOn!)) // : - user!.createdOn != null - ? DateUtil.getDayMonthYearDateFormatted( - DateUtil.convertStringToDate( - user!.createdOn!)) - : '--', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.48), + user!.createdOn != null ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user!.createdOn!)) : '--', + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48), ), ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - TranslationBase - .of(context) - .lastLoginWith - .toCamelCase, + TranslationBase.of(context).lastLoginWith.toCamelCase, style: TextStyle( fontSize: 10, fontWeight: FontWeight.w600, @@ -256,17 +212,8 @@ class _ConfirmLogin extends State { // user!.editedOn!), // false) // : - user!.createdOn != null - ? DateUtil.formatDateToTimeLang( - DateUtil.convertStringToDate( - user!.createdOn!), - false) - : '--', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff575757), - letterSpacing: -0.48), + user!.createdOn != null ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user!.createdOn!), false) : '--', + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.48), ), ], ) @@ -274,21 +221,11 @@ class _ConfirmLogin extends State { ), ), Text( - TranslationBase - .of(context) - .pleaseVerify, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2E303A), - letterSpacing: -0.64), + TranslationBase.of(context).pleaseVerify, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64), ), GridView( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 13, - mainAxisSpacing: 9), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.only(top: 9), shrinkWrap: true, @@ -302,67 +239,40 @@ class _ConfirmLogin extends State { ], ) else - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/habib-logo.png', - height: 90, - width: 90, - ), - SizedBox(height: 23), - this.onlySMSBox == false - ? Text( - TranslationBase - .of(context) - .verifyLoginWith, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 25 / 16), - ) - : Text( - TranslationBase - .of(context) - .verifyFingerprint2, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 25 / 16), - ), - SizedBox(height: 23), - Text( - TranslationBase - .of(context) - .pleaseVerify, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2E303A), - letterSpacing: -0.64), - ), - GridView( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 13, - mainAxisSpacing: 9), - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(top: 9), - shrinkWrap: true, - children: [ - if (onlySMSBox == false) getButton(3), - if (onlySMSBox == false) getButton(2), - getButton(1), - getButton(4), - ], - ), - ]), + Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + Image.asset( + 'assets/images/habib-logo.png', + height: 90, + width: 90, + ), + SizedBox(height: 23), + this.onlySMSBox == false + ? Text( + TranslationBase.of(context).verifyLoginWith, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), + ) + : Text( + TranslationBase.of(context).verifyFingerprint2, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), + ), + SizedBox(height: 23), + Text( + TranslationBase.of(context).pleaseVerify, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64), + ), + GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(top: 9), + shrinkWrap: true, + children: [ + if (onlySMSBox == false) getButton(3), + if (onlySMSBox == false) getButton(2), + getButton(1), + getButton(4), + ], + ), + ]), ], ), ), @@ -370,13 +280,10 @@ class _ConfirmLogin extends State { height: 12, ), DefaultButton( - TranslationBase - .of(context) - .useAnotherAccount, - () { + TranslationBase.of(context).useAnotherAccount, + () { Navigator.of(context).pushNamed(LOGIN_TYPE); - projectViewModel.analytics.loginRegistration - .login_with_other_account(); + projectViewModel.analytics.loginRegistration.login_with_other_account(); }, ), ], @@ -387,8 +294,7 @@ class _ConfirmLogin extends State { Future _getAvailableBiometrics() async { final bool canAuthenticateWithBiometrics = await auth.canCheckBiometrics; - final bool canAuthenticate = - canAuthenticateWithBiometrics || await auth.isDeviceSupported(); + final bool canAuthenticate = canAuthenticateWithBiometrics || await auth.isDeviceSupported(); var availableBiometrics; try { @@ -417,8 +323,7 @@ class _ConfirmLogin extends State { login_method = type; LoginRegistration.verificationMethod = type; // if(!widget.fromRegistration) - projectViewModel.analytics.loginRegistration - .login_verfication(forRegistration: widget.fromRegistration); + projectViewModel.analytics.loginRegistration.login_verfication(forRegistration: widget.fromRegistration); switch (type) { case 1: @@ -436,8 +341,7 @@ class _ConfirmLogin extends State { default: break; } - sharedPref.setInt(LAST_LOGIN, - this.selectedOption); //this.cs.sharedService.setStorage(this.selectedOption, AuthenticationService.LAST_LOGIN); + sharedPref.setInt(LAST_LOGIN, this.selectedOption); //this.cs.sharedService.setStorage(this.selectedOption, AuthenticationService.LAST_LOGIN); } loginWithSMS(type) { @@ -465,23 +369,22 @@ class _ConfirmLogin extends State { sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request); authService .checkPatientAuthentication(request) - .then((value) => - { - GifLoaderDialogUtils.hideDialog(context), - if (value['isSMSSent']) - { - sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']), - this.loginTokenID = value['LogInTokenID'], - sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), - // Future.delayed(Duration(seconds: 1), () { - this.sendActivationCode(type) - // }) - } - else - { - if (value['IsAuthenticated']) {this.checkActivationCode()} - } - }) + .then((value) => { + GifLoaderDialogUtils.hideDialog(context), + if (value['isSMSSent']) + { + sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']), + this.loginTokenID = value['LogInTokenID'], + sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), + // Future.delayed(Duration(seconds: 1), () { + this.sendActivationCode(type) + // }) + } + else + { + if (value['IsAuthenticated']) {this.checkActivationCode()} + } + }) .catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); @@ -494,8 +397,7 @@ class _ConfirmLogin extends State { GifLoaderDialogUtils.showMyDialog(context); if (healthId != null || widget.isDubai) { if (!widget.isDubai) { - request.dob = - dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); + request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); } request.healthId = healthId; request.isHijri = isHijri; @@ -532,11 +434,10 @@ class _ConfirmLogin extends State { context, type, this.mobileNumber, - (value) { + (value) { this.checkActivationCode(value: value); }, - () => - { + () => { Navigator.pop(context), }, ).displayDialog(context); @@ -612,28 +513,23 @@ class _ConfirmLogin extends State { setDefault() async { showLoader(true); - if (await sharedPref.getObject(IMEI_USER_DATA) != null) - user = SelectDeviceIMEIRES.fromJson( - await sharedPref.getObject(IMEI_USER_DATA)); + if (await sharedPref.getObject(IMEI_USER_DATA) != null) user = SelectDeviceIMEIRES.fromJson(await sharedPref.getObject(IMEI_USER_DATA)); if (await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN) != null) { isMoreOption = true; - this.registerd_data = await CheckPatientAuthenticationReq.fromJson( - await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN)); + this.registerd_data = await CheckPatientAuthenticationReq.fromJson(await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN)); } - this.mobileNumber = this.registerd_data != null - ? this.registerd_data.patientMobileNumber - : int.parse(this.user!.mobile!); + this.mobileNumber = this.registerd_data != null ? this.registerd_data.patientMobileNumber : int.parse(this.user!.mobile!); this.zipCode = this.registerd_data != null ? this.registerd_data.zipCode : this.user!.outSA == true - ? "971" - : "966"; + ? "971" + : "966"; this.patientOutSA = this.registerd_data != null ? this.registerd_data.zipCode == "966" - ? 0 - : 1 + ? 0 + : 1 : this.user!.outSA; if (this.registerd_data != null) { this.loginTokenID = await sharedPref.getString(LOGIN_TOKEN_ID); @@ -643,9 +539,7 @@ class _ConfirmLogin extends State { if (nhic != null) { final DateFormat dateFormat = DateFormat('MM/dd/yyyy'); final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy'); - dob = nhic['IsHijri'] - ? nhic['DateOfBirth'] - : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth'])); + dob = nhic['IsHijri'] ? nhic['DateOfBirth'] : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth'])); isHijri = nhic['IsHijri'] ? 1 : 0; healthId = nhic['HealthId']; @@ -654,8 +548,8 @@ class _ConfirmLogin extends State { this.lastLogin = await sharedPref.getInt(LAST_LOGIN) != null ? await sharedPref.getInt(LAST_LOGIN) : user != null - ? user!.logInType - : null; + ? user!.logInType + : null; showLoader(false); //this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN); @@ -668,34 +562,22 @@ class _ConfirmLogin extends State { request.deviceToken = this.deviceToken; request.projectOutSA = this.patientOutSA == true ? true : false; request.loginType = this.selectedOption; - request.oTPSendType = - type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; + request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; request.zipCode = this.zipCode; request.logInTokenID = this.loginTokenID ?? ""; if (this.registerd_data != null) { - request.searchType = this.registerd_data.searchType != null - ? this.registerd_data.searchType - : 1; - request.patientID = this.registerd_data.patientID != null - ? this.registerd_data.patientID - : 0; - request.patientIdentificationID = request.nationalID = - this.registerd_data.patientIdentificationID != null - ? this.registerd_data.patientIdentificationID - : '0'; + request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1; + request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0; + request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0'; request.dob = this.registerd_data.dob; request.isRegister = this.registerd_data.isRegister; } else { request.searchType = request.searchType != null ? request.searchType : 2; - request.patientID = - this.user!.patientID != null ? this.user!.patientID : 0; - request.nationalID = - request.nationalID != null ? request.nationalID : '0'; - request.patientIdentificationID = request.patientIdentificationID != null - ? request.patientIdentificationID - : '0'; + request.patientID = this.user!.patientID != null ? this.user!.patientID : 0; + request.nationalID = request.nationalID != null ? request.nationalID : '0'; + request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0'; request.isRegister = false; } request.deviceTypeID = request.searchType; @@ -716,40 +598,31 @@ class _ConfirmLogin extends State { authService .checkActivationCodeRegister(request, value) - .then((result) => - { - res = result, - if (result is Map) - { - result = CheckActivationCode.fromJson( - result as Map), - if (this.registerd_data != null && - this.registerd_data.isRegister == true) - { - // if(widget.isDubai ==false){ - widget.changePageViewIndex!(1), - // if(widget.isDubai ==false){ - - Navigator.popUntil( - context, - (route) => - Utils.route(route, equalsTo: RegisterNew)), - } - } - else - { - // Navigator.of(context).pop(), - GifLoaderDialogUtils.hideDialog(context), - Future.delayed(Duration(seconds: 1), () { - AppToast.showErrorToast(message: result); - }), - projectViewModel.analytics.loginRegistration - .login_fail(error: result), - projectViewModel.analytics.errorTracking.log( - 'otp_verification_at_confirm_login', - error: result), - } - }) + .then((result) => { + res = result, + if (result is Map) + { + result = CheckActivationCode.fromJson(result as Map), + if (this.registerd_data != null && this.registerd_data.isRegister == true) + { + // if(widget.isDubai ==false){ + widget.changePageViewIndex!(1), + // if(widget.isDubai ==false){ + + Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)), + } + } + else + { + // Navigator.of(context).pop(), + GifLoaderDialogUtils.hideDialog(context), + Future.delayed(Duration(seconds: 1), () { + AppToast.showErrorToast(message: result); + }), + projectViewModel.analytics.loginRegistration.login_fail(error: result), + projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result), + } + }) .catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); @@ -762,62 +635,56 @@ class _ConfirmLogin extends State { authService .checkActivationCode(request, value) .then((result) => { - res = result, - if (result is Map) - { - result = CheckActivationCode.fromJson(result as Map), - if(result.errorCode =='699'){ - //699 block run here - GifLoaderDialogUtils.hideDialog(context), - Future.delayed(Duration(seconds: 2), () { - AppToast.showErrorToast(message: result.errorEndUserMessage); - Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: Login)); + res = result, + if (result is Map) + { + result = CheckActivationCode.fromJson(result as Map), + if (result.errorCode == '699') + { + //699 block run here + GifLoaderDialogUtils.hideDialog(context), + Future.delayed(Duration(seconds: 2), () { + AppToast.showErrorToast(message: result.errorEndUserMessage); + Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: Login)); + }) + } + else if (this.registerd_data != null && this.registerd_data.isRegister == true) + { + widget.changePageViewIndex!(1), + Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)), + } + else + { + sharedPref.remove(FAMILY_FILE), + result.list.isFamily = false, + userData = result.list, + sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""), + //Remove o+ from here Added by Aamir + authenticatedUserObject.user = result.list, + projectViewModel.setPrivilege(privilegeList: res), + sharedPref.setObject(MAIN_USER, result.list), + sharedPref.setObject(USER_PROFILE, result.list), + loginTokenID = result.logInTokenID, + sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), + sharedPref.setString(TOKEN, result.authenticationTokenID), + checkIfUserAgreedBefore(result), + projectViewModel.analytics.loginRegistration.login_successful(), + } + } + else + { + // Navigator.of(context).pop(), + GifLoaderDialogUtils.hideDialog(context), + Future.delayed(Duration(seconds: 1), () { + Navigator.of(context).pop(); + AppToast.showErrorToast(message: result, localContext: context); + startSMSService(tempType); + }), + + projectViewModel.analytics.loginRegistration.login_fail(error: result), + projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result) + } }) - } - else if (this.registerd_data != null && - this.registerd_data.isRegister == true) - { - widget.changePageViewIndex!(1), - Navigator.popUntil( - context, - (route) => - Utils.route(route, equalsTo: RegisterNew)), - } - else - { - sharedPref.remove(FAMILY_FILE), - result.list.isFamily = false, - userData = result.list, - sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""), - //Remove o+ from here Added by Aamir - authenticatedUserObject.user = result.list, - projectViewModel.setPrivilege(privilegeList: res), - sharedPref.setObject(MAIN_USER, result.list), - sharedPref.setObject(USER_PROFILE, result.list), - loginTokenID = result.logInTokenID, - sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), - sharedPref.setString(TOKEN, result.authenticationTokenID), - checkIfUserAgreedBefore(result), - projectViewModel.analytics.loginRegistration.login_successful(), - - } - } - else - { - // Navigator.of(context).pop(), - GifLoaderDialogUtils.hideDialog(context), - Future.delayed(Duration(seconds: 1), () { - Navigator.of(context).pop(); - AppToast.showErrorToast(message: result, localContext: context); - startSMSService(tempType); - }), - - projectViewModel.analytics.loginRegistration - .login_fail(error: result), - projectViewModel.analytics.errorTracking - .log('otp_verification_at_confirm_login', error: result) - } - }) .catchError((err) { GifLoaderDialogUtils.hideDialog(context); Future.delayed(Duration(seconds: 1), () { @@ -830,10 +697,37 @@ class _ConfirmLogin extends State { } checkIfUserAgreedBefore(CheckActivationCode result) { + this.authService.checkIfUserAgreed().then((result) { + if (result['IsPatientAlreadyAgreed']) { + goToHome(); + } else { + this.authService.getUserAgreementContent().then((result) { + GifLoaderDialogUtils.hideDialog(AppGlobal.context); + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: UserLoginAgreementPage( + userAgreementText: result['UserAgreementContent'], + authenticatedUserObject: authenticatedUserObject, + appointmentRateViewModel: appointmentRateViewModel, + selectedOption: selectedOption, + ), + ), + (r) => false); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + print(err); + }); + // if (result.isNeedUserAgreement == true) { //move to agreement page. // } else { - goToHome(); + // goToHome(); // } } @@ -851,25 +745,18 @@ class _ConfirmLogin extends State { print("Has Admission Request: $hasAdmissionRequest"); if (isAdmitted) { if (res['PatientAdmittedInformation'].length != 0) { - getAdmissionInfoResponseModel = - GetAdmissionInfoResponseModel.fromJson( - res['PatientAdmittedInformation'][0]); - projectViewModel.setInPatientProjectID( - res['PatientAdmittedInformation'][0]['ProjectID']); - projectViewModel - .setInPatientAdmissionInfo(getAdmissionInfoResponseModel); + getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel.fromJson(res['PatientAdmittedInformation'][0]); + projectViewModel.setInPatientProjectID(res['PatientAdmittedInformation'][0]['ProjectID']); + projectViewModel.setInPatientAdmissionInfo(getAdmissionInfoResponseModel); projectViewModel.setIsPatientAdmitted(true); } } if (hasAdmissionRequest) { if (res['MedicalInstruction'].length != 0) { - getAdmissionRequestInfoResponseModel = - GetAdmissionRequestInfoResponseModel.fromJson( - res['MedicalInstruction'][0]); - projectViewModel.setInPatientProjectID( - res['MedicalInstruction'][0]['ProjectID']); - projectViewModel.setInPatientAdmissionRequest( - getAdmissionRequestInfoResponseModel); + getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel.fromJson(res['MedicalInstruction'][0]); + // projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['ProjectID']); + projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['projectId']); + projectViewModel.setInPatientAdmissionRequest(getAdmissionRequestInfoResponseModel); projectViewModel.setPatientHasAdmissionRequest(true); } } @@ -878,10 +765,7 @@ class _ConfirmLogin extends State { } insertIMEI() { - authService - .insertDeviceImei(selectedOption) - .then((value) => {}) - .catchError((err) { + authService.insertDeviceImei(selectedOption).then((value) => {}).catchError((err) { print(err); }); } @@ -891,8 +775,7 @@ class _ConfirmLogin extends State { ClinicListService service = new ClinicListService(); service.getActiveAppointmentNo(context).then((res) { if (res['MessageStatus'] == 1) { - toDoProvider.setState(res['AppointmentActiveNumber'], - res['AncillaryOrderListCount'], true, "0"); + toDoProvider.setState(res['AppointmentActiveNumber'], res['AncillaryOrderListCount'], true, "0"); // toDoProvider.setState(res['AppointmentActiveNumber'], true, "0"); } else {} }).catchError((err) { @@ -909,44 +792,34 @@ class _ConfirmLogin extends State { // GifLoaderDialogUtils.hideDialog(context); getToDoCount(); + checkIfIsInPatient(); appointmentRateViewModel .getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2) - .then((value) => - { - GifLoaderDialogUtils.hideDialog(AppGlobal.context), - if (appointmentRateViewModel.isHaveAppointmentNotRate) - { - Navigator.pushAndRemoveUntil( - context, - FadePage( - page: RateAppointmentDoctor(), - ), - (r) => false) - } - else - { - Navigator.pushAndRemoveUntil( - context, - FadePage( - page: LandingPage(), - ), - (r) => false) - }, - insertIMEI() - }) + .then((value) => { + GifLoaderDialogUtils.hideDialog(AppGlobal.context), + if (appointmentRateViewModel.isHaveAppointmentNotRate) + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: RateAppointmentDoctor(), + ), + (r) => false) + } + else + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false) + }, + insertIMEI() + }) .catchError((err) { print(err); }); - - // getToDoCount(); - - // Navigator.pushAndRemoveUntil( - // context, - // FadePage( - // page: LandingPage(), - // ), - // (r) => false); - // insertIMEI(); } loading(flag) { @@ -956,26 +829,21 @@ class _ConfirmLogin extends State { } Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { - bool isDisable = - (_flag == 3 && !checkIfBiometricAvailable(BiometricType.face) || - _flag == 2 && - !checkIfBiometricAvailable(BiometricType.fingerprint) && - _flag == 2 && - !checkIfBiometricAvailable(BiometricType.strong)); + bool isDisable = (_flag == 3 && !checkIfBiometricAvailable(BiometricType.face) || + _flag == 2 && !checkIfBiometricAvailable(BiometricType.fingerprint) && _flag == 2 && !checkIfBiometricAvailable(BiometricType.strong)); return InkWell( onTap: isDisable ? null : () { - if (_flag == 0) { - setState(() { - isMoreOption = true; - }); - } else { - authenticateUser(_flag, isActive: _loginIndex); - projectViewModel.analytics.loginRegistration.verify_otp_method( - forRegistration: widget.fromRegistration); - } - }, + if (_flag == 0) { + setState(() { + isMoreOption = true; + }); + } else { + authenticateUser(_flag, isActive: _loginIndex); + projectViewModel.analytics.loginRegistration.verify_otp_method(forRegistration: widget.fromRegistration); + } + }, child: Container( padding: EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28), decoration: BoxDecoration( @@ -997,17 +865,8 @@ class _ConfirmLogin extends State { color: isDisable ? Color(0xff2B353E).withOpacity(0.7) : null, ), Text( - TranslationBase - .of(context) - .verifyThrough + " " + _title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: isDisable - ? Color(0xff2B353E).withOpacity(0.7) - : Color(0xff2B353E), - letterSpacing: -0.48, - height: 20 / 16), + TranslationBase.of(context).verifyThrough + " " + _title, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: isDisable ? Color(0xff2B353E).withOpacity(0.7) : Color(0xff2B353E), letterSpacing: -0.48, height: 20 / 16), ), ], ), @@ -1019,49 +878,28 @@ class _ConfirmLogin extends State { Widget getButton(int flag) { switch (flag) { case 4: - return _loginOptionButton(TranslationBase - .of(context) - .verifyWhatsApp, - 'assets/images/new/verify_whatsapp.svg', flag, null); + return _loginOptionButton(TranslationBase.of(context).verifyWhatsApp, 'assets/images/new/verify_whatsapp.svg', flag, null); break; case 1: - return _loginOptionButton(TranslationBase - .of(context) - .verifySMS, - 'assets/images/new/verify_sms.svg', flag, null); + return _loginOptionButton(TranslationBase.of(context).verifySMS, 'assets/images/new/verify_sms.svg', flag, null); break; case 2: - return _loginOptionButton( - TranslationBase - .of(context) - .verifyFingerprint, - 'assets/images/new/verify_thumb.svg', - flag, - BiometricType.fingerprint.index); + return _loginOptionButton(TranslationBase.of(context).verifyFingerprint, 'assets/images/new/verify_thumb.svg', flag, BiometricType.fingerprint.index); break; case 3: - return _loginOptionButton( - TranslationBase - .of(context) - .verifyFaceID, - 'assets/images/new/verify_face.svg', - flag, - BiometricType.face.index); + return _loginOptionButton(TranslationBase.of(context).verifyFaceID, 'assets/images/new/verify_face.svg', flag, BiometricType.face.index); break; default: return InkWell( - onTap: () => - { + onTap: () => { setState(() { isMoreOption = true; }) }, child: RoundedContainer( height: 150, - backgroundColor: BiometricType.fingerprint.index == 1 - ? Colors.white - : Colors.white.withOpacity(.7), + backgroundColor: BiometricType.fingerprint.index == 1 ? Colors.white : Colors.white.withOpacity(.7), borderColor: Colors.grey, showBorder: true, child: Padding( @@ -1075,17 +913,12 @@ class _ConfirmLogin extends State { ), projectViewModel.isArabic ? SizedBox( - height: 15, - ) + height: 15, + ) : SizedBox( - height: 20, - ), - Texts(TranslationBase - .of(context) - .moreVerification, - fontSize: SizeConfig.textMultiplier! * 1.8, - textAlign: TextAlign.center, - color: Colors.black) + height: 20, + ), + Texts(TranslationBase.of(context).moreVerification, fontSize: SizeConfig.textMultiplier! * 1.8, textAlign: TextAlign.center, color: Colors.black) ], ), ), @@ -1097,29 +930,19 @@ class _ConfirmLogin extends State { getType(type, context) { switch (type) { case 1: - return TranslationBase - .of(context) - .verifySMS; + return TranslationBase.of(context).verifySMS; break; case 2: - return TranslationBase - .of(context) - .verifyFingerprint; + return TranslationBase.of(context).verifyFingerprint; break; case 3: - return TranslationBase - .of(context) - .verifyFaceID; + return TranslationBase.of(context).verifyFaceID; break; case 4: - return TranslationBase - .of(context) - .verifyWhatsApp; + return TranslationBase.of(context).verifyWhatsApp; break; default: - return TranslationBase - .of(context) - .verifySMS; + return TranslationBase.of(context).verifySMS; break; } } diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart index 18ed5440..64bc3ac1 100644 --- a/lib/pages/login/login.dart +++ b/lib/pages/login/login.dart @@ -386,6 +386,7 @@ class _Login extends State { // ), // (r) => false); getToDoCount(); + checkIfIsInPatient(); appointmentRateViewModel .getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2) .then((value) => { diff --git a/lib/pages/login/user-login-agreement-page.dart b/lib/pages/login/user-login-agreement-page.dart new file mode 100644 index 00000000..f01a0c96 --- /dev/null +++ b/lib/pages/login/user-login-agreement-page.dart @@ -0,0 +1,215 @@ +import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; +import 'package:diplomaticquarterapp/core/viewModels/TermsConditionsViewModel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/custom_text_button.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:provider/provider.dart'; + +class UserLoginAgreementPage extends StatefulWidget { + final String userAgreementText; + final AuthenticatedUserObject authenticatedUserObject; + final AppointmentRateViewModel appointmentRateViewModel; + final int selectedOption; + + UserLoginAgreementPage({required this.userAgreementText, required this.authenticatedUserObject, required this.appointmentRateViewModel, required this.selectedOption}); + + @override + State createState() => _UserLoginAgreementPageState(); +} + +class _UserLoginAgreementPageState extends State { + late ProjectViewModel projectViewModel; + late ToDoCountProviderModel toDoProvider; + final authService = AuthProvider(); + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + toDoProvider = Provider.of(context); + return BaseView( + builder: (_, model, w) => AppScaffold( + isShowAppBar: true, + showNewAppBarTitle: true, + showNewAppBar: true, + isShowDecPage: false, + appBarTitle: TranslationBase.of(context).userAgreement, + body: Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + child: Html( + data: widget.userAgreementText, + ), + ), + ), + bottomSheet: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + padding: EdgeInsets.only(left: 21, right: 21, top: 15, bottom: 15), + width: double.infinity, + // color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: 12), + Text( + TranslationBase.of(context).continueAgreeTerms, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + flex: 1, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + height: 45.0, + child: CustomTextButton( + backgroundColor: CustomColors.green, + elevation: 0, + onPressed: () { + addUsageAgreement(); + }, + child: Text(TranslationBase.of(context).acceptLbl.toUpperCase(), + style: TextStyle( + fontSize: 18.0, + color: Colors.white, + )), + ), + ), + ), + mWidth(7), + Expanded( + flex: 1, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + height: 45.0, + child: CustomTextButton( + backgroundColor: Color(0xffc5272d), + elevation: 0, + onPressed: () { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false); + }, + child: Text(TranslationBase.of(context).declineLbl.toUpperCase(), style: TextStyle(fontSize: 18.0, color: Colors.white)), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } + + addUsageAgreement() { + GifLoaderDialogUtils.showMyDialog(context); + this.authService.addUserAgreementContent().then((result) { + goToHome(); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + goToHome() async { + widget.authenticatedUserObject.isLogin = true; + widget.appointmentRateViewModel.isLogin = true; + projectViewModel.isLogin = true; + projectViewModel.user = widget.authenticatedUserObject.user; + await widget.authenticatedUserObject.getUser(getUser: true); + + // GifLoaderDialogUtils.hideDialog(context); + getToDoCount(); + widget.appointmentRateViewModel + .getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2) + .then((value) => { + GifLoaderDialogUtils.hideDialog(context), + if (widget.appointmentRateViewModel.isHaveAppointmentNotRate) + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: RateAppointmentDoctor(), + ), + (r) => false) + } + else + { + GifLoaderDialogUtils.hideDialog(context), + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false) + }, + insertIMEI() + }) + .catchError((err) { + print(err); + }); + } + + insertIMEI() { + authService.insertDeviceImei(widget.selectedOption).then((value) => {}).catchError((err) { + print(err); + }); + } + + getToDoCount() { + toDoProvider.setState(0, 0, true, "0"); + ClinicListService service = new ClinicListService(); + service.getActiveAppointmentNo(context).then((res) { + if (res['MessageStatus'] == 1) { + toDoProvider.setState(res['AppointmentActiveNumber'], res['AncillaryOrderListCount'], true, "0"); + // toDoProvider.setState(res['AppointmentActiveNumber'], true, "0"); + } else {} + }).catchError((err) { + print(err); + }); + } +} diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index 35b6d163..2b039701 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -1475,7 +1475,7 @@ class DoctorsListService extends BaseService { Future HIS_createAdvancePayment(AppoitmentAllHistoryResultList appo, String projectID, double payedAmount, String paymentReference, String paymentMethodName, dynamic patientType, String patientName, dynamic patientID, BuildContext context, - {bool isAncillaryOrder = false}) async { + {bool isAncillaryOrder = false, int clinicID = 0}) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); @@ -1530,12 +1530,12 @@ class DoctorsListService extends BaseService { Request req = appGlobal.getPublicRequest(); request = { - "VersionID": req.VersionID, - "Channel": req.Channel, - "IPAdress": req.IPAdress, - "generalid": req.generalid, - "PatientOutSA": authUser.outSA, - "PatientTypeID": authUser.patientType, + // "VersionID": req.VersionID, + // "Channel": req.Channel, + // "IPAdress": req.IPAdress, + // "generalid": req.generalid, + // "PatientOutSA": authUser.outSA, + // "PatientTypeID": authUser.patientType, "LanguageID": 1, "ERAdvanceAmount": { "ProjectId": projectID, @@ -1880,6 +1880,32 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future autoGenerateInvoiceERClinic(int? projectID, int? paymentMethod, String? paymentReferenceNo, num? amount, String? cardType, String? cardNumber, String? orderID, String? rrn, bool isAdvanceAvailable) async { + Map request; + request = { + "ProjectID": projectID, + "ClinicID": "10", + // "PaymentMethod": paymentMethod, + "PaymentMethod": "VISA", + "PaymentReferenceNo": paymentReferenceNo, + "PaymentAmount": amount, + "CardType": cardType, + "CardNumber": cardNumber, + "OrderId": orderID, + "MemberID": 102, + "RRN": rrn, + "IsAdvanceAvailable": isAdvanceAvailable + }; + dynamic localRes; + await baseAppClient.post(AUTO_GENERATE_INVOICE_ER, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + + return Future.value(localRes); + } + Future checkPatientNphiesEligibility(int projectID) async { Map request; request = {"ProjectID": projectID, "LanguageID": 1}; diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart index 4f4e6a1d..81a3dfad 100644 --- a/lib/services/authentication/auth_provider.dart +++ b/lib/services/authentication/auth_provider.dart @@ -1775,6 +1775,60 @@ class AuthProvider with ChangeNotifier { } } + Future checkIfUserAgreed() async { + Map request; + request = {"Region": 1}; + dynamic localRes; + try { + await new BaseAppClient().post(CHECK_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request); + return Future.value(localRes); + } catch (error) { + throw error; + } + } + + Future getUserAgreementContent() async { + Map request; + request = {"Region": 1}; + dynamic localRes; + try { + await new BaseAppClient().post(GET_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request); + return Future.value(localRes); + } catch (error) { + throw error; + } + } + + Future addUserAgreementContent() async { + Map request; + request = {"Region": 1}; + dynamic localRes; + try { + await new BaseAppClient().post(ADD_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request); + return Future.value(localRes); + } catch (error) { + throw error; + } + } + Future getDashboard() async { Map request = {}; diff --git a/lib/services/clinic_services/get_clinic_service.dart b/lib/services/clinic_services/get_clinic_service.dart index fb7ae8c1..9969d898 100644 --- a/lib/services/clinic_services/get_clinic_service.dart +++ b/lib/services/clinic_services/get_clinic_service.dart @@ -452,4 +452,110 @@ class ClinicListService extends BaseService { return Future.value(localRes); } + Future getEROnlineCheckInPaymentDetails(int projectID, int clinicID) async { + Map request = {"ProjectID": projectID, "ClinicID": clinicID}; + dynamic localRes; + await baseAppClient.post(GET_ER_ONLINE_PAYMENT_DETAILS, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + + Future checkIfPatientHasArrived(int projectID, int clinicID) async { + Map request = {"ProjectID": projectID, "ClinicID": clinicID}; + dynamic localRes; + await baseAppClient.post(CHECK_IF_PATIENT_ARRIVED_ER_ONLINE_CHECKIN, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future checkPatientERAdvanceBalance(int clinicID) async { + Map request = {"ClinicID": clinicID}; + dynamic localRes; + await baseAppClient.post(CHECK_PATIENT_ER_ADVANCE_BALANCE, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future getProjectIDFromNFC(String nfcID) async { + Map request = {"nFC_Code": nfcID}; + dynamic localRes; + await baseAppClient.post(GET_PROJECT_FROM_NFC, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future getDischargeMedicationOrder(GetAdmissionInfoResponseModel getAdmissionInfoResponseModel) async { + Map request; + request = { + "ProjectID": getAdmissionInfoResponseModel.projectID, + "ClinicID": getAdmissionInfoResponseModel.clinicID, + "DoctorID": getAdmissionInfoResponseModel.doctorID, + "AdmissionNo": getAdmissionInfoResponseModel.admissionNo + }; + + // request = { + // "ProjectID": 12, + // "VersionID": 10.8, + // "Channel": 3, + // "LanguageID": 2, + // "IPAdress": "10.20.10.20", + // "generalid": "Cs2020@2016\$2958", + // "DeviceTypeID": 2, + // "PatientType": 1, + // "PatientTypeID": 1, + // "TokenID": "@dm!n", + // "PatientID": 869588, + // "PatientOutSA": 0, + // "SessionID": "rVuK3nzN4UKN0SW95un0jQ==", + // "ClinicID": 2, + // "DoctorID": "7600", + // "AdmissionNo": 2011001258 + // }; + + dynamic localRes; + + await baseAppClient.post(INPATIENT_DISCHARGE_MEDICATIONS, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future insertForGeneralAdmissionConsent(int patientID, int admissionReqNo, int clinicID, int projectID, int status, context) async { + Map request; + request = { + "AdmissionRequestNo": admissionReqNo, + "ClinicID": clinicID, + "CreatedBy": 102, + "PatientID": patientID, + "ProjectID": projectID, + "status": status, + "searchKey": "", + "pageIndex": 0, + "pageSize": 0, + }; + + dynamic localRes; + + await baseAppClient.post(INSERT_GENERAL_ADMISSION_CONSENT, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + } diff --git a/lib/services/payfort_services/payfort_service.dart b/lib/services/payfort_services/payfort_service.dart index 9983a22c..5dedd006 100644 --- a/lib/services/payfort_services/payfort_service.dart +++ b/lib/services/payfort_services/payfort_service.dart @@ -143,7 +143,7 @@ class PayfortService extends BaseService { String? customerName, String? customerEmail, String? orderDescription, - double? orderAmount, + num? orderAmount, String? merchantIdentifier, String? applePayAccessCode, String? applePayShaRequestPhrase, diff --git a/lib/services/payfort_services/payfort_view_model.dart b/lib/services/payfort_services/payfort_view_model.dart index 17f739db..29a79f14 100644 --- a/lib/services/payfort_services/payfort_view_model.dart +++ b/lib/services/payfort_services/payfort_view_model.dart @@ -45,7 +45,7 @@ class PayfortViewModel extends ChangeNotifier { String? customerEmail, String? orderDescription, String? merchantReference, - double? orderAmount, + num? orderAmount, PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel, SucceededCallback? onSuccess, FailedCallback? onFailed, diff --git a/lib/uitl/penguin_method_channel.dart b/lib/uitl/penguin_method_channel.dart index 7b50d635..50a642a7 100644 --- a/lib/uitl/penguin_method_channel.dart +++ b/lib/uitl/penguin_method_channel.dart @@ -3,7 +3,12 @@ import 'package:flutter/services.dart'; class PenguinMethodChannel { static const MethodChannel _channel = MethodChannel('launch_penguin_ui'); - static Future launch(String storyboardName, String languageCode, String username, {NavigationClinicDetails? details}) async { + Future loadGif() async { + return await rootBundle.load("assets/images/progress-loading-red-crop-1.gif").then((data) => data.buffer.asUint8List()); + } + + Future launch(String storyboardName, String languageCode, String username, {NavigationClinicDetails? details}) async { + Uint8List image = await loadGif(); try { await _channel.invokeMethod('launchPenguin', { "storyboardName": storyboardName, @@ -26,10 +31,11 @@ class PenguinMethodChannel { "languageCode": languageCode, "clientKey": "UGVuZ3VpbklOX1Blbk5hdl9QSUY=", "mapBoxKey": "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg", - // "clinicID": details?.clinicId ?? "", - "clinicID": details?.clinicId ?? "", // 46 ,49, 133 + "clinicID": details?.clinicId ?? "", + // "clinicID": "108", // 46 ,49, 133 "patientID": details?.patientId ?? "", "projectID": details?.projectId ?? "", + "loaderImage": image, }); } on PlatformException catch (e) { print("Failed to launch PenguinIn: '${e.message}'."); diff --git a/lib/uitl/push-notification-handler.dart b/lib/uitl/push-notification-handler.dart index 5bf073b3..2ad0203a 100644 --- a/lib/uitl/push-notification-handler.dart +++ b/lib/uitl/push-notification-handler.dart @@ -426,7 +426,7 @@ class PushNotificationHandler { Permission.bluetoothScan, Permission.activityRecognition, ].request().whenComplete(() { - PenguinMethodChannel.launch("penguin", "en", "1231755", details: data); + PenguinMethodChannel().launch("penguin", "en", "1231755", details: data); }); } } diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index be20b67a..7686e463 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -2948,6 +2948,34 @@ class TranslationBase { String get receive => localizedValues["receive"][locale.languageCode]; String get PRO => localizedValues["PRO"][locale.languageCode]; String get patientRelationOffice => localizedValues["patientRelationOffice"][locale.languageCode]; + String get roomNo => localizedValues["roomNo"][locale.languageCode]; + String get generalConsent => localizedValues["generalConsent"][locale.languageCode]; + String get generalConsent1 => localizedValues["generalConsent1"][locale.languageCode]; + String get hospitalRules => localizedValues["hospitalRules"][locale.languageCode]; + String get generalConsent2 => localizedValues["generalConsent2"][locale.languageCode]; + String get communicationConsent => localizedValues["communicationConsent"][locale.languageCode]; + String get generalConsent3 => localizedValues["generalConsent3"][locale.languageCode]; + String get releaseConsent => localizedValues["releaseConsent"][locale.languageCode]; + String get generalConsent4 => localizedValues["generalConsent4"][locale.languageCode]; + String get generalConsent5 => localizedValues["generalConsent5"][locale.languageCode]; + String get valuables => localizedValues["valuables"][locale.languageCode]; + String get generalConsent6 => localizedValues["generalConsent6"][locale.languageCode]; + String get financialConsent => localizedValues["financialConsent"][locale.languageCode]; + String get generalConsent7 => localizedValues["generalConsent7"][locale.languageCode]; + String get dataSharingConsent => localizedValues["dataSharingConsent"][locale.languageCode]; + String get generalConsent8 => localizedValues["generalConsent8"][locale.languageCode]; + String get permissionLeaveConsent => localizedValues["permissionLeaveConsent"][locale.languageCode]; + String get generalConsent9 => localizedValues["generalConsent9"][locale.languageCode]; + String get observeConsent => localizedValues["observeConsent"][locale.languageCode]; + String get generalConsent10 => localizedValues["generalConsent10"][locale.languageCode]; + String get noGuaranteeConsent => localizedValues["noGuaranteeConsent"][locale.languageCode]; + String get generalConsent11 => localizedValues["generalConsent11"][locale.languageCode]; + String get disputeConsent => localizedValues["disputeConsent"][locale.languageCode]; + String get generalConsent12 => localizedValues["generalConsent12"][locale.languageCode]; + String get patientsRightsConsent => localizedValues["patientsRightsConsent"][locale.languageCode]; + String get generalConsent13 => localizedValues["generalConsent13"][locale.languageCode]; + String get acknowledgementConsent => localizedValues["acknowledgementConsent"][locale.languageCode]; + String get generalConsent14 => localizedValues["generalConsent14"][locale.languageCode]; String get invalidEligibility => localizedValues["invalidEligibility"][locale.languageCode]; String get invalidInsurance => localizedValues["invalidInsurance"][locale.languageCode]; String get continueCash => localizedValues["continueCash"][locale.languageCode]; @@ -2984,10 +3012,14 @@ class TranslationBase { String get proceedPackage => localizedValues["proceedPackage"][locale.languageCode]; String get hospitalNavigationTitle => localizedValues["hospitalNavigationTitle"][locale.languageCode]; String get hospitalNavigationSubtitle => localizedValues["hospitalNavigationSubtitle"][locale.languageCode]; - String get workplaceNameAr => localizedValues["workplaceNameAr"][locale.languageCode]; String get occupationNameEn => localizedValues["occupationNameEn"][locale.languageCode]; String get occupationNameAr => localizedValues["occupationNameAr"][locale.languageCode]; + String get continueAgreeTerms => localizedValues["continueAgreeTerms"][locale.languageCode]; + String get agreeText => localizedValues["agreeText"][locale.languageCode]; + String get ERCheckInSuccess => localizedValues["ERCheckInSuccess"][locale.languageCode]; + + } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/in_app_browser/InAppBrowser.dart b/lib/widgets/in_app_browser/InAppBrowser.dart index ee68f743..6f61ac8a 100644 --- a/lib/widgets/in_app_browser/InAppBrowser.dart +++ b/lib/widgets/in_app_browser/InAppBrowser.dart @@ -38,9 +38,9 @@ class MyInAppBrowser extends InAppBrowser { static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL LIVE // static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL UAT - // static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT + static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT - static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE + // static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE // static String SERVICE_URL = 'https://uat.hmgwebservices.com/payfortforvidaplus/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL UAT VIDA PLUS diff --git a/pubspec.yaml b/pubspec.yaml index 143df07f..16e395b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: diplomaticquarterapp description: A new Flutter application. -version: 4.5.068+4050068 +version: 4.5.069+4050069 environment: sdk: ">=3.0.0 <3.13.0" @@ -36,7 +36,7 @@ dependencies: #Google Fit & Apple HealthKit # health: ^3.0.3 health: ^11.1.0 - pedometer: ^4.0.2 +# pedometer: ^4.0.2 #chart fl_chart: ^0.64.0