diff --git a/.gitignore b/.gitignore
index cff0e374..55ad4693 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ pubspec.lock
.pub-cache/
.pub/
/build/
+/ios/Frameworks/
# Web related
lib/generated_plugin_registrant.dart
diff --git a/android/app/build.gradle b/android/app/build.gradle
index f1799225..f154f114 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -56,6 +56,10 @@ android {
compileSdkVersion 34
// ndkVersion "24.0.8215888"
+ buildFeatures {
+ viewBinding true
+ }
+
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
@@ -69,7 +73,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.ejada.hmg"
- minSdkVersion 24
+ minSdkVersion 26
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@@ -117,15 +121,16 @@ android {
packagingOptions {
exclude 'META-INF/proguard/androidx-annotations.pro'
-// pickFirst 'lib/x86/libc++_shared.so'
-// pickFirst 'lib/x86_64/libc++_shared.so'
-// pickFirst 'lib/armeabi-v7a/libc++_shared.so'
-// pickFirst 'lib/arm64-v8a/libc++_shared.so'
-// pickFirst '**/*.so'
+ pickFirst 'lib/x86/libc++_shared.so'
+ pickFirst 'lib/x86_64/libc++_shared.so'
+ pickFirst 'lib/armeabi-v7a/libc++_shared.so'
+ pickFirst 'lib/arm64-v8a/libc++_shared.so'
+ pickFirst '**/*.so'
}
compileOptions {
+// coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
@@ -136,13 +141,15 @@ flutter {
}
dependencies {
+// coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.google.firebase:firebase-messaging:21.0.0"
// implementation ('com.google.firebase:firebase-inappmessaging-display:19.1.2',{
// exclude group: 'com.google.protobuf',module: 'protobuf-javalite'
// exclude group: 'com.google.protobuf',module: 'protobuf-lite'
// })
- implementation 'pub.devrel:easypermissions:0.4.0'
+ implementation 'pub.devrel:easypermissions:3.0.0'
// implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0'
// implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0'
implementation 'com.google.guava:guava:27.0.1-android'
@@ -163,11 +170,36 @@ dependencies {
// implementation "us.zoom.videosdk:ZoomVideoSDK:1.10.11"
// implementation group: 'us.zoom.videosdk', name: 'zoomvideosdk-core', version: '1.10.11'
- implementation "us.zoom.videosdk:zoomvideosdk-core:1.10.1"
- implementation "us.zoom.videosdk:zoomvideosdk-annotation:1.10.1"
- implementation "us.zoom.videosdk:zoomvideosdk-videoeffects:1.10.1"
-
- implementation "org.jetbrains.anko:anko-commons:0.10.4"
+// implementation "us.zoom.videosdk:zoomvideosdk-core:1.10.1"
+// implementation "us.zoom.videosdk:zoomvideosdk-annotation:1.10.1"
+// implementation "us.zoom.videosdk:zoomvideosdk-videoeffects:1.10.1"
+
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
+ implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
+ implementation 'com.squareup.retrofit2:adapter-java8:2.4.0'
+ implementation 'com.google.code.gson:gson:2.8.9'
+ implementation 'com.google.android.gms:play-services-location:21.3.0'
+ implementation 'com.squareup.okhttp3:okhttp:4.10.0'
+ implementation 'androidx.test.ext:junit:1.1.5'
+ implementation 'com.android.volley:volley:1.2.1'
+ def room_version = "2.4.0-alpha04"
+ implementation "androidx.room:room-runtime:$room_version"
+ annotationProcessor "androidx.room:room-compiler:$room_version"
+ implementation 'net.zetetic:android-database-sqlcipher:4.5.2'
+ implementation 'com.intuit.ssp:ssp-android:1.1.0'
+ implementation 'com.intuit.sdp:sdp-android:1.1.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+
+// implementation "com.mapbox.maps:android:10.16.6"
+ implementation 'com.mapbox.maps:android:11.3.1'
+
+ implementation files('libs/PenNavUI.aar')
+ implementation files('libs/Penguin.aar')
+ implementation files('libs/PenguinRenderer.aar')
+
+// implementation "org.jetbrains.anko:anko-commons:0.10.4"
implementation 'com.github.kittinunf.fuel:fuel:2.3.0' //for JVM
implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0'
implementation 'com.google.android.gms:play-services-location:17.1.0'//for Android
@@ -177,6 +209,10 @@ dependencies {
implementation 'com.facebook.stetho:stetho-urlconnection:1.5.1'
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/google-services.json b/android/app/google-services.json
index 5806fa5f..3707617c 100644
--- a/android/app/google-services.json
+++ b/android/app/google-services.json
@@ -21,7 +21,7 @@
],
"api_key": [
{
- "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw"
+ "current_key": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg"
}
],
"services": {
diff --git a/android/app/libs/PenNavUI.aar b/android/app/libs/PenNavUI.aar
new file mode 100644
index 00000000..d423bc11
Binary files /dev/null and b/android/app/libs/PenNavUI.aar differ
diff --git a/android/app/libs/Penguin.aar b/android/app/libs/Penguin.aar
new file mode 100644
index 00000000..5c789c6f
Binary files /dev/null and b/android/app/libs/Penguin.aar differ
diff --git a/android/app/libs/PenguinRenderer.aar b/android/app/libs/PenguinRenderer.aar
new file mode 100644
index 00000000..b657ac66
Binary files /dev/null and b/android/app/libs/PenguinRenderer.aar differ
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
index 69cd8026..ab7b2ca4 100644
--- a/android/app/proguard-rules.pro
+++ b/android/app/proguard-rules.pro
@@ -53,4 +53,20 @@
}
-dontwarn com.opentok.android.**
--dontwarn com.opentok.otc.**
\ No newline at end of file
+-dontwarn com.opentok.otc.**
+
+-dontwarn penguin.com.pennav.Model.Navigation.NearLandmark
+
+-keep,includedescriptorclasses class net.sqlcipher.** { *; }
+-keep,includedescriptorclasses interface net.sqlcipher.** { *; }
+
+-keep class retrofit2.** { *; }
+-keep class okhttp3.** { *; }
+-dontwarn retrofit2.**
+
+-keep class com.google.gson.** { *; }
+-dontwarn com.google.gson.**
+
+# Penguin classes
+-keep class com.peng.pennavmap.models.** { *; }
+-keep class com.peng.pennavmap.db.** { *; }
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index b1540644..2856e8f1 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,21 +8,35 @@
FlutterApplication and put your custom class here. -->
-
-
-
-
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -42,6 +56,7 @@
+
@@ -59,13 +74,13 @@
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
index 8aa1ef85..df41e342 100644
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt
@@ -1,21 +1,19 @@
package com.ejada.hmg
-import android.app.NotificationChannel
-import android.app.NotificationManager
-import android.content.ContentResolver
-import android.media.AudioAttributes
-import android.net.Uri
-import android.os.Bundle
-import android.util.Log
+import android.content.Intent
+import android.content.pm.PackageManager
import android.os.Build
+import android.util.Log
import android.view.WindowManager
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi
+import com.cloud.diplomaticquarterapp.PenguinInPlatformBridge
import com.ejada.hmg.utils.*
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
-import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterFragmentActivity() {
+ @RequiresApi(Build.VERSION_CODES.O)
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
// Create Flutter Platform Bridge
@@ -23,6 +21,7 @@ class MainActivity: FlutterFragmentActivity() {
PlatformBridge(flutterEngine, this).create()
OpenTokPlatformBridge(flutterEngine, this).create()
+ PenguinInPlatformBridge(flutterEngine, this).create()
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// val mChannel = NotificationChannel("video_call_noti", "video call", NotificationManager.IMPORTANCE_HIGH)
@@ -43,6 +42,25 @@ class MainActivity: FlutterFragmentActivity() {
// val time = timeToMillis("04:00:00", "HH:mm:ss")
+ }
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ val granted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
+ val intent = Intent("PERMISSION_RESULT_ACTION").apply {
+ putExtra("PERMISSION_GRANTED", granted)
+ }
+ sendBroadcast(intent)
+
+ // Log the request code and permission results
+ Log.d("PermissionsResult", "Request Code: $requestCode")
+ Log.d("PermissionsResult", "Permissions: ${permissions.joinToString()}")
+ Log.d("PermissionsResult", "Grant Results: ${grantResults.joinToString()}")
+
}
override fun onResume() {
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PenguinInPlatformBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PenguinInPlatformBridge.kt
new file mode 100644
index 00000000..93affaef
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PenguinInPlatformBridge.kt
@@ -0,0 +1,52 @@
+package com.cloud.diplomaticquarterapp
+import com.ejada.hmg.MainActivity
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import com.cloud.diplomaticquarterapp.penguin.PenguinView
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+
+class PenguinInPlatformBridge(
+ private var flutterEngine: FlutterEngine,
+ private var mainActivity: MainActivity
+) {
+
+ private lateinit var channel: MethodChannel
+
+ companion object {
+ private const val CHANNEL = "launch_penguin_ui"
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun create() {
+// openTok = OpenTok(mainActivity, flutterEngine)
+ channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
+ channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
+ when (call.method) {
+ "launchPenguin" -> {
+ print("the platform channel is being called")
+ val args = call.arguments as Map?
+ Log.d("TAG", "configureFlutterEngine: $args")
+ println("args")
+ args?.let {
+ PenguinView(
+ mainActivity,
+ 100,
+ args,
+ flutterEngine.dartExecutor.binaryMessenger,
+ activity = mainActivity,
+ channel
+ )
+ }
+ }
+
+ else -> {
+ result.notImplemented()
+ }
+ }
+ }
+ }
+
+}
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionHelper.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionHelper.kt
new file mode 100644
index 00000000..b308af05
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionHelper.kt
@@ -0,0 +1,28 @@
+package com.cloud.diplomaticquarterapp.PermissionManager
+
+import android.Manifest
+import android.os.Build
+
+object PermissionHelper {
+
+ fun getRequiredPermissions(): Array {
+ val permissions = mutableListOf(
+ Manifest.permission.INTERNET,
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Manifest.permission.BLUETOOTH,
+ Manifest.permission.BLUETOOTH_ADMIN,
+// Manifest.permission.ACTIVITY_RECOGNITION
+ )
+
+ // For Android 12 (API level 31) and above, add specific permissions
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12 (API 31) and above
+ permissions.add(Manifest.permission.BLUETOOTH_SCAN)
+ permissions.add(Manifest.permission.BLUETOOTH_CONNECT)
+ permissions.add(Manifest.permission.HIGH_SAMPLING_RATE_SENSORS)
+ }
+
+ return permissions.toTypedArray()
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionManager.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionManager.kt
new file mode 100644
index 00000000..81f2a6f0
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionManager.kt
@@ -0,0 +1,50 @@
+package com.cloud.diplomaticquarterapp.PermissionManager
+
+import android.app.Activity
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+
+class PermissionManager(
+ private val context: Context,
+ val listener: PermissionListener,
+ private val requestCode: Int,
+ vararg permissions: String
+) {
+
+ private val permissionsArray = permissions
+
+ interface PermissionListener {
+ fun onPermissionGranted()
+ fun onPermissionDenied()
+ }
+
+ fun arePermissionsGranted(): Boolean {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ permissionsArray.all {
+ ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
+ }
+ } else {
+ true
+ }
+ }
+
+ fun requestPermissions(activity: Activity) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ ActivityCompat.requestPermissions(activity, permissionsArray, requestCode)
+ }
+ }
+
+ fun handlePermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ if (this.requestCode == requestCode) {
+ val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
+ if (allGranted) {
+ listener.onPermissionGranted()
+ } else {
+ listener.onPermissionDenied()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionResultReceiver.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionResultReceiver.kt
new file mode 100644
index 00000000..33765192
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/PermissionManager/PermissionResultReceiver.kt
@@ -0,0 +1,15 @@
+package com.cloud.diplomaticquarterapp.PermissionManager
+
+// PermissionResultReceiver.kt
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+
+class PermissionResultReceiver(
+ private val callback: (Boolean) -> Unit
+) : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ val granted = intent?.getBooleanExtra("PERMISSION_GRANTED", false) ?: false
+ callback(granted)
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinMethod.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinMethod.kt
new file mode 100644
index 00000000..c76f9784
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinMethod.kt
@@ -0,0 +1,13 @@
+package com.cloud.diplomaticquarterapp.penguin
+
+enum class PenguinMethod {
+ // initializePenguin("initializePenguin"),
+ // configurePenguin("configurePenguin"),
+ // showPenguinUI("showPenguinUI"),
+ // onPenNavUIDismiss("onPenNavUIDismiss"),
+ // onReportIssue("onReportIssue"),
+ // onPenNavSuccess("onPenNavSuccess"),
+ onPenNavInitializationError // onLocationOffCampus("onLocationOffCampus"),
+ // navigateToPOI("navigateToPOI"),
+ // openSharedLocation("openSharedLocation");
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinNavigator.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinNavigator.kt
new file mode 100644
index 00000000..98245cc9
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinNavigator.kt
@@ -0,0 +1,97 @@
+package com.cloud.diplomaticquarterapp.penguin
+
+import android.content.Context
+import com.google.gson.Gson
+import com.peng.pennavmap.PlugAndPlaySDK
+import com.peng.pennavmap.connections.ApiController
+import com.peng.pennavmap.interfaces.RefIdDelegate
+import com.peng.pennavmap.models.TokenModel
+import com.peng.pennavmap.models.postmodels.PostToken
+import com.peng.pennavmap.utils.AppSharedData
+import okhttp3.ResponseBody
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+import android.util.Log
+
+
+class PenguinNavigator() {
+
+ fun navigateTo(mContext: Context, refID: String, delegate: RefIdDelegate,clientID : String,clientKey : String ) {
+ val postToken = PostToken(clientID, clientKey)
+ getToken(mContext, postToken, object : RefIdDelegate {
+ override fun onRefByIDSuccess(PoiId: String?) {
+ Log.e("navigateTo", "PoiId is+++++++ $PoiId")
+
+ PlugAndPlaySDK.navigateTo(mContext, refID, object : RefIdDelegate {
+ override fun onRefByIDSuccess(PoiId: String?) {
+ Log.e("navigateTo", "PoiId 2is+++++++ $PoiId")
+
+ delegate.onRefByIDSuccess(refID)
+
+ }
+
+ override fun onGetByRefIDError(error: String?) {
+ delegate.onRefByIDSuccess(error)
+ }
+
+ })
+
+
+ }
+
+ override fun onGetByRefIDError(error: String?) {
+ delegate.onRefByIDSuccess(error)
+ }
+
+ })
+
+ }
+
+ fun getToken(mContext: Context, postToken: PostToken?, apiTokenCallBack: RefIdDelegate) {
+ try {
+ // Create the API call
+ val purposesCall: Call = ApiController.getInstance(mContext)
+ .apiMethods
+ .getToken(postToken)
+
+ // Enqueue the call for asynchronous execution
+ purposesCall.enqueue(object : Callback {
+ override fun onResponse(
+ call: Call,
+ response: Response
+ ) {
+ if (response.isSuccessful() && response.body() != null) {
+ try {
+ response.body()?.use { responseBody ->
+ val responseBodyString: String = responseBody.string() // Use `string()` to get the actual response content
+ if (responseBodyString.isNotEmpty()) {
+ val tokenModel = Gson().fromJson(responseBodyString, TokenModel::class.java)
+ if (tokenModel != null && tokenModel.token != null) {
+ AppSharedData.apiToken = tokenModel.token
+ apiTokenCallBack.onRefByIDSuccess(tokenModel.token)
+ } else {
+ apiTokenCallBack.onGetByRefIDError("Failed to parse token model")
+ }
+ } else {
+ apiTokenCallBack.onGetByRefIDError("Response body is empty")
+ }
+ }
+ } catch (e: Exception) {
+ apiTokenCallBack.onGetByRefIDError("An error occurred: ${e.message}")
+ }
+ } else {
+ apiTokenCallBack.onGetByRefIDError("Unsuccessful response: " + response.code())
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ apiTokenCallBack.onGetByRefIDError(t.message)
+ }
+ })
+ } catch (error: Exception) {
+ apiTokenCallBack.onGetByRefIDError("Exception during API call: $error")
+ }
+ }
+
+}
\ No newline at end of file
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
new file mode 100644
index 00000000..238765b2
--- /dev/null
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/penguin/PenguinView.kt
@@ -0,0 +1,310 @@
+package com.cloud.diplomaticquarterapp.penguin
+
+import android.app.Activity
+import android.content.Context
+import android.content.Context.RECEIVER_EXPORTED
+import android.content.IntentFilter
+import android.graphics.Color
+import android.os.Build
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import android.widget.RelativeLayout
+import android.widget.Toast
+import androidx.annotation.RequiresApi
+import com.cloud.diplomaticquarterapp.PermissionManager.PermissionHelper
+import com.cloud.diplomaticquarterapp.PermissionManager.PermissionManager
+import com.cloud.diplomaticquarterapp.PermissionManager.PermissionResultReceiver
+import com.ejada.hmg.MainActivity
+import com.peng.pennavmap.PlugAndPlayConfiguration
+import com.peng.pennavmap.PlugAndPlaySDK
+import com.peng.pennavmap.enums.InitializationErrorType
+import com.peng.pennavmap.interfaces.PenNavUIDelegate
+import com.peng.pennavmap.utils.Languages
+import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.platform.PlatformView
+import com.cloud.diplomaticquarterapp.penguin.PenguinNavigator
+import com.peng.pennavmap.interfaces.PIEventsDelegate
+import com.peng.pennavmap.interfaces.PILocationDelegate
+import com.peng.pennavmap.interfaces.RefIdDelegate
+import com.peng.pennavmap.models.PIReportIssue
+/**
+ * Custom PlatformView for displaying Penguin UI components within a Flutter app.
+ * Implements `PlatformView` for rendering the view, `MethodChannel.MethodCallHandler` for handling method calls,
+ * and `PenNavUIDelegate` for handling SDK events.
+ */
+@RequiresApi(Build.VERSION_CODES.O)
+internal class PenguinView(
+ context: Context,
+ id: Int,
+ val creationParams: Map,
+ messenger: BinaryMessenger,
+ activity: MainActivity,
+ val channel: MethodChannel
+) : PlatformView, MethodChannel.MethodCallHandler, PenNavUIDelegate {
+ // The layout for displaying the Penguin UI
+ private val mapLayout: RelativeLayout = RelativeLayout(context)
+ private val _context: Context = context
+
+ private val permissionResultReceiver: PermissionResultReceiver
+ private val permissionIntentFilter = IntentFilter("PERMISSION_RESULT_ACTION")
+
+ private companion object {
+ const val PERMISSIONS_REQUEST_CODE = 1
+ }
+
+ private lateinit var permissionManager: PermissionManager
+
+ // Reference to the main activity
+ private var _activity: Activity = activity
+
+ private lateinit var mContext: Context
+
+ lateinit var navigator: PenguinNavigator
+
+ init {
+ // Set layout parameters for the mapLayout
+ mapLayout.layoutParams = ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
+ )
+
+ mContext = context
+
+
+ permissionResultReceiver = PermissionResultReceiver { granted ->
+ if (granted) {
+ onPermissionsGranted()
+ } else {
+ onPermissionsDenied()
+ }
+ }
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ mContext.registerReceiver(
+ permissionResultReceiver,
+ permissionIntentFilter,
+ RECEIVER_EXPORTED
+ )
+ } else {
+ mContext.registerReceiver(
+ permissionResultReceiver,
+ permissionIntentFilter,
+ )
+ }
+
+ // Set the background color of the layout
+ mapLayout.setBackgroundColor(Color.RED)
+
+ permissionManager = PermissionManager(
+ context = mContext,
+ listener = object : PermissionManager.PermissionListener {
+ override fun onPermissionGranted() {
+ // Handle permissions granted
+ onPermissionsGranted()
+ }
+
+ override fun onPermissionDenied() {
+ // Handle permissions denied
+ onPermissionsDenied()
+ }
+ },
+ requestCode = PERMISSIONS_REQUEST_CODE,
+ *PermissionHelper.getRequiredPermissions()
+ )
+
+ if (!permissionManager.arePermissionsGranted()) {
+ permissionManager.requestPermissions(_activity)
+ } else {
+ // Permissions already granted
+ permissionManager.listener.onPermissionGranted()
+ }
+
+
+ }
+
+ private fun onPermissionsGranted() {
+ // Handle the actions when permissions are granted
+ Log.d("PermissionsResult", "onPermissionsGranted")
+ // Register the platform view factory for creating custom views
+
+ // Initialize the Penguin SDK
+ initPenguin()
+
+
+ }
+
+ private fun onPermissionsDenied() {
+ // Handle the actions when permissions are denied
+ Log.d("PermissionsResult", "onPermissionsDenied")
+
+ }
+
+ /**
+ * Returns the view associated with this PlatformView.
+ *
+ * @return The main view for this PlatformView.
+ */
+ override fun getView(): View {
+ return mapLayout
+ }
+
+ /**
+ * Cleans up resources associated with this PlatformView.
+ */
+ override fun dispose() {
+ // Cleanup code if needed
+ }
+
+ /**
+ * Handles method calls from Dart code.
+ *
+ * @param call The method call from Dart.
+ * @param result The result callback to send responses back to Dart.
+ */
+ override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
+ // Handle method calls from Dart code here
+ }
+
+ /**
+ * Initializes the Penguin SDK with custom configuration and delegates.
+ */
+ private fun initPenguin() {
+ navigator = PenguinNavigator()
+ // Configure the PlugAndPlaySDK
+ val language = when (creationParams["languageCode"] as String) {
+ "ar" -> Languages.ar
+ "en" -> Languages.en
+ else -> {
+ Languages.en
+ }
+ }
+ Log.d(
+ "TAG",
+ "initPenguin: ${Languages.getLanguageEnum(creationParams["languageCode"] as String)}"
+ )
+ PlugAndPlaySDK.configuration = PlugAndPlayConfiguration.Builder()
+ .setBaseUrl(
+ creationParams["dataURL"] as String,
+ creationParams["positionURL"] as String
+ )
+ .setServiceName(
+ creationParams["dataServiceName"] as String,
+ creationParams["positionServiceName"] as String
+ )
+ .setClientData(
+ creationParams["clientID"] as String,
+ creationParams["clientKey"] as String
+ )
+ .setUserName(creationParams["username"] as String)
+// .setLanguageID(Languages.en)
+ .setLanguageID(language)
+ .setSimulationModeEnabled(creationParams["isSimulationModeEnabled"] as Boolean)
+ .setEnableBackButton(true)
+// .setDeepLinkData("deeplink")
+ .setCustomizeColor("#2CA0AF")
+ .setDeepLinkSchema("")
+ .build()
+
+ // Set location delegate to handle location updates
+// 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 { }
+
+ // Start the Penguin SDK
+ PlugAndPlaySDK.start(mContext, this)
+ }
+
+
+ /**
+ * Navigates to the specified reference ID.
+ *
+ * @param refID The reference ID to navigate to.
+ */
+ fun navigateTo(refID: String) {
+ 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")
+
+// channelFlutter.invokeMethod(
+// PenguinMethod.navigateToPOI.name,
+// "navigateTo Success"
+// )
+ }
+
+ override fun onGetByRefIDError(error: String?) {
+ Log.e("navigateTo", "error is penguin view+++++++ $error")
+
+// channelFlutter.invokeMethod(
+// PenguinMethod.navigateToPOI.name,
+// "navigateTo Failed: Invalid refID"
+// )
+ }
+ } , creationParams["clientID"] as String, creationParams["clientKey"] as String )
+
+ } catch (e: Exception) {
+ Log.e("navigateTo", "Exception occurred during navigation: ${e.message}", e)
+// channelFlutter.invokeMethod(
+// PenguinMethod.navigateToPOI.name,
+// "Failed: Exception - ${e.message}"
+// )
+ }
+ }
+
+ /**
+ * Called when Penguin UI setup is successful.
+ *
+ * @param warningCode Optional warning code received from the SDK.
+ */
+ override fun onPenNavSuccess(warningCode: String?) {
+ val clinicId = creationParams["clinicID"] as String
+
+ if(clinicId.isEmpty()) return
+
+ navigateTo(clinicId)
+ }
+
+ /**
+ * Called when there is an initialization error with Penguin UI.
+ *
+ * @param description Description of the error.
+ * @param errorType Type of initialization error.
+ */
+ override fun onPenNavInitializationError(
+ description: String?,
+ errorType: InitializationErrorType?
+ ) {
+ val arguments: Map = mapOf(
+ "description" to description,
+ "type" to errorType?.name
+ )
+
+ channel.invokeMethod(PenguinMethod.onPenNavInitializationError.name, arguments)
+ Toast.makeText(mContext, "Navigation Error: $description", Toast.LENGTH_SHORT).show()
+ }
+
+ /**
+ * Called when Penguin UI is dismissed.
+ */
+ override fun onPenNavUIDismiss() {
+ // Handle UI dismissal if needed
+ try {
+ mContext.unregisterReceiver(permissionResultReceiver)
+ dispose();
+ } catch (e: IllegalArgumentException) {
+ Log.e("PenguinView", "Receiver not registered: $e")
+ }
+ }
+}
+
diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt
index 7fbf859a..57da2eb8 100644
--- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt
+++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/HMGUtils.kt
@@ -22,7 +22,7 @@ import com.github.kittinunf.fuel.httpPost
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import io.flutter.plugin.common.MethodChannel
-import org.jetbrains.anko.doAsyncResult
+//import org.jetbrains.anko.doAsyncResult
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
@@ -149,7 +149,7 @@ fun sendNotification(context: Context, title: String, @Nullable subtitle: String
val notificationPendingIntent = stackBuilder.getPendingIntent(getUniqueId(), PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
- .setSmallIcon(R.mipmap.ic_launcher)
+ .setSmallIcon(R.mipmap.ic_launcher_local)
.setContentIntent(notificationPendingIntent)
.setAutoCancel(true)
.setContentTitle(title)
@@ -208,7 +208,6 @@ fun httpPost(url: String, body: Map, onSuccess: (response: HTTP
.header("Content-Type", "application/json")
.header("Allow", "*/*")
.response { request, response, result ->
- result.doAsyncResult { }
result.fold({ data ->
val dataString = String(data)
if (isJSONValid(dataString)) {
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_local.png
similarity index 100%
rename from android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to android/app/src/main/res/mipmap-hdpi/ic_launcher_local.png
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_local.png
similarity index 100%
rename from android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to android/app/src/main/res/mipmap-mdpi/ic_launcher_local.png
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_local.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to android/app/src/main/res/mipmap-xhdpi/ic_launcher_local.png
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_local.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to android/app/src/main/res/mipmap-xxhdpi/ic_launcher_local.png
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_local.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_local.png
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 4e107030..1093435a 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -19,4 +19,5 @@
Geofence requests happened too frequently.
+ sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg
diff --git a/android/build.gradle b/android/build.gradle
index b5185cca..cc067af7 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -12,7 +12,23 @@ buildscript {
repositories {
google()
jcenter()
+ mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
+ maven {
+ url 'https://api.mapbox.com/downloads/v2/releases/maven'
+
+ credentials {
+ username = 'mapbox'
+// password = "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
+ password = "pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ"
+ if (password == null || password == "") {
+ throw new GradleException("MAPBOX_DOWNLOADS_TOKEN isn't set. Set it to the project properties or to the enviroment variables.")
+ }
+ }
+ authentication {
+ basic(BasicAuthentication)
+ }
+ }
// maven {
// url "https://dl.bintray.com/kotlin/kotlin-eap/"
@@ -26,6 +42,7 @@ buildscript {
// classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12'
+ classpath "com.mapbox.gradle.plugins:access-token:0.4.0"
}
}
@@ -34,12 +51,29 @@ allprojects {
google()
// jcenter()
mavenCentral()
+ flatDir {
+ dirs 'libs'
+ }
maven {
url 'https://developer.huawei.com/repo/'
}
maven {
url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local"
}
+ maven {
+ url 'https://api.mapbox.com/downloads/v2/releases/maven'
+
+ credentials {
+ username = 'mapbox'
+ password = "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
+ if (password == null || password == "") {
+ throw new GradleException("MAPBOX_DOWNLOADS_TOKEN isn't set. Set it to the project properties or to the enviroment variables.")
+ }
+ }
+ authentication {
+ basic(BasicAuthentication)
+ }
+ }
}
}
diff --git a/android/google-services.json b/android/google-services.json
index dd4038cf..3707617c 100644
--- a/android/google-services.json
+++ b/android/google-services.json
@@ -21,19 +21,24 @@
],
"api_key": [
{
- "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw"
+ "current_key": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg"
}
],
"services": {
- "analytics_service": {
- "status": 1
- },
"appinvite_service": {
- "status": 1,
- "other_platform_oauth_client": []
- },
- "ads_service": {
- "status": 2
+ "other_platform_oauth_client": [
+ {
+ "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "815750722565-0cq9366orvsk5ipivq6lijcj56u03fr7.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.void.demo"
+ }
+ }
+ ]
}
}
}
diff --git a/android/gradle.properties b/android/gradle.properties
index 06a44c05..cb9913a1 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -3,3 +3,6 @@ org.gradle.jvmargs=-Xmx4096m
android.useAndroidX=true
android.enableJetifier=true
android.suppressUnsupportedCompileSdk=33
+MAPBOX_USER_NAME = "mapbox"
+#MAPBOX_DOWNLOADS_TOKEN="sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
+MAPBOX_DOWNLOADS_TOKEN="pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ"
\ No newline at end of file
diff --git a/assets/images/new/NFCCheckIn_QR_gps_HMG.png b/assets/images/new/NFCCheckIn_QR_gps_HMG.png
new file mode 100644
index 00000000..20fc0ef6
Binary files /dev/null and b/assets/images/new/NFCCheckIn_QR_gps_HMG.png differ
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/google-services_HMG.json b/google-services_HMG.json
index dd4038cf..5806fa5f 100644
--- a/google-services_HMG.json
+++ b/google-services_HMG.json
@@ -25,15 +25,20 @@
}
],
"services": {
- "analytics_service": {
- "status": 1
- },
"appinvite_service": {
- "status": 1,
- "other_platform_oauth_client": []
- },
- "ads_service": {
- "status": 2
+ "other_platform_oauth_client": [
+ {
+ "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "815750722565-0cq9366orvsk5ipivq6lijcj56u03fr7.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.void.demo"
+ }
+ }
+ ]
}
}
}
diff --git a/google-services_HMG_old.json b/google-services_HMG_old.json
new file mode 100644
index 00000000..dd4038cf
--- /dev/null
+++ b/google-services_HMG_old.json
@@ -0,0 +1,42 @@
+{
+ "project_info": {
+ "project_number": "815750722565",
+ "firebase_url": "https://api-project-815750722565.firebaseio.com",
+ "project_id": "api-project-815750722565",
+ "storage_bucket": "api-project-815750722565.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063",
+ "android_client_info": {
+ "package_name": "com.ejada.hmg"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw"
+ }
+ ],
+ "services": {
+ "analytics_service": {
+ "status": 1
+ },
+ "appinvite_service": {
+ "status": 1,
+ "other_platform_oauth_client": []
+ },
+ "ads_service": {
+ "status": 2
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/google-services_old.json b/google-services_old.json
new file mode 100644
index 00000000..5806fa5f
--- /dev/null
+++ b/google-services_old.json
@@ -0,0 +1,47 @@
+{
+ "project_info": {
+ "project_number": "815750722565",
+ "firebase_url": "https://api-project-815750722565.firebaseio.com",
+ "project_id": "api-project-815750722565",
+ "storage_bucket": "api-project-815750722565.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063",
+ "android_client_info": {
+ "package_name": "com.ejada.hmg"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyDUfg6AKM1-00WyzpvLImUBC46wFrq9-qw"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "815750722565-0cq9366orvsk5ipivq6lijcj56u03fr7.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.void.demo"
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index cb6be309..c5ff5d37 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 13.0
diff --git a/ios/Podfile b/ios/Podfile
index 2350b703..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,
@@ -33,6 +33,8 @@ 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
@@ -54,6 +56,7 @@ post_install do |installer|
]
build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64 i386'
build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
+ build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
xcconfig_path = build_configuration.base_configuration_reference.real_path
xcconfig = File.read(xcconfig_path)
xcconfig_mod = xcconfig.gsub(/DT_TOOLCHAIN_DIR/, "TOOLCHAIN_DIR")
@@ -62,6 +65,17 @@ post_install do |installer|
if build_configuration.build_settings['WRAPPER_EXTENSION'] == 'bundle'
build_configuration.build_settings['DEVELOPMENT_TEAM'] = '3A359E86ZF'
end
+ if target.name == 'MapboxMobileEvents'
+ `xcrun -sdk iphoneos bitcode_strip -r Pods/MapboxMobileEvents/MapboxMobileEvents.xcframework/ios-arm64_armv7/MapboxMobileEvents.framework/MapboxMobileEvents -o Pods/MapboxMobileEvents/MapboxMobileEvents.xcframework/ios-arm64_armv7/MapboxMobileEvents.framework/MapboxMobileEvents`
+ end
+
+ if target.name == 'MapboxCommon'
+ `xcrun -sdk iphoneos bitcode_strip -r Pods/MapboxCommon/MapboxCommon.xcframework/ios-arm64/MapboxCommon.framework/MapboxCommon -o Pods/MapboxCommon/MapboxCommon.xcframework/ios-arm64/MapboxCommon.framework/MapboxCommon`
+ end
+
+ if target.name == 'MapboxCoreMaps'
+ `xcrun -sdk iphoneos bitcode_strip -r Pods/MapboxCoreMaps/MapboxCoreMaps.xcframework/ios-arm64/MapboxCoreMaps.framework/MapboxCoreMaps -o Pods/MapboxCoreMaps/MapboxCoreMaps.xcframework/ios-arm64/MapboxCoreMaps.framework/MapboxCoreMaps`
+ end
end
end
end
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index e7357518..2c0073ff 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -8,17 +8,28 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 29631B9E2C96C7F600DF5916 /* PenguinNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29631B9D2C96C7F600DF5916 /* PenguinNavigator.swift */; };
301C79AE27200D9F0016307B /* OpenTokRemoteVideoFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 301C79AD27200D9F0016307B /* OpenTokRemoteVideoFactory.swift */; };
301C79B027200DED0016307B /* OpenTokLocalVideoFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 301C79AF27200DED0016307B /* OpenTokLocalVideoFactory.swift */; };
306FE6C8271D790C002D6EFC /* OpenTokPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */; };
306FE6CB271D8B73002D6EFC /* OpenTok.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6CA271D8B73002D6EFC /* OpenTok.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
- 4EE411B2E3CB5D4F81AE5078 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D1513E0724DAFB89C198BDD /* Pods_Runner.framework */; };
+ 47C935002C91766800981BA7 /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FC2C91766400981BA7 /* Penguin.xcframework */; };
+ 47C935012C91766800981BA7 /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FC2C91766400981BA7 /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 47C935022C91766900981BA7 /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */; };
+ 47C935032C91766900981BA7 /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 47C935042C91766A00981BA7 /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FB2C91766400981BA7 /* PenNavUI.xcframework */; };
+ 47C935052C91766A00981BA7 /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FB2C91766400981BA7 /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
762D738E274E42650063CE73 /* ring_30Sec.caf in Resources */ = {isa = PBXBuildFile; fileRef = 762D738C274E42650063CE73 /* ring_30Sec.caf */; };
762D738F274E42650063CE73 /* ring_30Sec.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 762D738D274E42650063CE73 /* ring_30Sec.mp3 */; };
76815B27275F381C00E66E94 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76815B26275F381C00E66E94 /* HealthKit.framework */; };
76962ECE28AE5C10004EAE09 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 76962ECD28AE5C10004EAE09 /* GoogleService-Info.plist */; };
+ 76D71B672C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76D71B662C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift */; };
+ 76D71B6A2C6B819000DAFB84 /* PenguinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76D71B692C6B819000DAFB84 /* PenguinModel.swift */; };
+ 76D71B6C2C6B81B300DAFB84 /* PenguinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76D71B6B2C6B81B300DAFB84 /* PenguinView.swift */; };
+ 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 */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
@@ -40,15 +51,19 @@
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 */
- 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ 768D81742C6DF6E4005C655F /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
+ 47C935032C91766900981BA7 /* PenguinINRenderer.xcframework in Embed Frameworks */,
+ 47C935012C91766800981BA7 /* Penguin.xcframework in Embed Frameworks */,
+ 47C935052C91766A00981BA7 /* PenNavUI.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -58,12 +73,15 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 29631B9D2C96C7F600DF5916 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = ""; };
301C79AD27200D9F0016307B /* OpenTokRemoteVideoFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokRemoteVideoFactory.swift; sourceTree = ""; };
301C79AF27200DED0016307B /* OpenTokLocalVideoFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokLocalVideoFactory.swift; sourceTree = ""; };
306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokPlatformBridge.swift; sourceTree = ""; };
306FE6CA271D8B73002D6EFC /* OpenTok.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTok.swift; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 3D1513E0724DAFB89C198BDD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = ""; };
+ 47C934FB2C91766400981BA7 /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = ""; };
+ 47C934FC2C91766400981BA7 /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = ""; };
6EE8819867EC2775AB578377 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
@@ -74,9 +92,15 @@
7643E4062BE0D0B400BD2F25 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/LaunchScreen.strings; sourceTree = ""; };
76815B26275F381C00E66E94 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
76962ECD28AE5C10004EAE09 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 76D71B662C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPenguinInPlatformBridge.swift; sourceTree = ""; };
+ 76D71B692C6B819000DAFB84 /* PenguinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinModel.swift; sourceTree = ""; };
+ 76D71B6B2C6B81B300DAFB84 /* PenguinView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinView.swift; sourceTree = ""; };
+ 76D71B6D2C6B81CC00DAFB84 /* PenguinPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinPlugin.swift; sourceTree = ""; };
+ 76D71B6F2C6B81EA00DAFB84 /* PenguinViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinViewFactory.swift; sourceTree = ""; };
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; };
@@ -113,7 +137,10 @@
76F2556127F1FFED0062C1CD /* PassKit.framework in Frameworks */,
76815B27275F381C00E66E94 /* HealthKit.framework in Frameworks */,
E9620805255C2ED100D3A35D /* NetworkExtension.framework in Frameworks */,
- 4EE411B2E3CB5D4F81AE5078 /* Pods_Runner.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;
};
@@ -133,10 +160,13 @@
555EAAA626EFB641859EF0BE /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 47C934FC2C91766400981BA7 /* Penguin.xcframework */,
+ 47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */,
+ 47C934FB2C91766400981BA7 /* PenNavUI.xcframework */,
76F2556027F1FFED0062C1CD /* PassKit.framework */,
76815B26275F381C00E66E94 /* HealthKit.framework */,
E9620804255C2ED100D3A35D /* NetworkExtension.framework */,
- 3D1513E0724DAFB89C198BDD /* Pods_Runner.framework */,
+ 8E413842321D0D624872E9BE /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -151,6 +181,18 @@
path = Pods;
sourceTree = "";
};
+ 76D71B682C6B817500DAFB84 /* Penguin */ = {
+ isa = PBXGroup;
+ children = (
+ 76D71B692C6B819000DAFB84 /* PenguinModel.swift */,
+ 76D71B6B2C6B81B300DAFB84 /* PenguinView.swift */,
+ 76D71B6D2C6B81CC00DAFB84 /* PenguinPlugin.swift */,
+ 76D71B6F2C6B81EA00DAFB84 /* PenguinViewFactory.swift */,
+ 29631B9D2C96C7F600DF5916 /* PenguinNavigator.swift */,
+ );
+ path = Penguin;
+ sourceTree = "";
+ };
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@@ -186,6 +228,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
+ 76D71B682C6B817500DAFB84 /* Penguin */,
762D738C274E42650063CE73 /* ring_30Sec.caf */,
762D738D274E42650063CE73 /* ring_30Sec.mp3 */,
306FE6C9271D8B54002D6EFC /* OpenTok */,
@@ -220,6 +263,7 @@
E923EFD52587443800E3E751 /* HMGPlatformBridge.swift */,
306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */,
E9F7623A25922BCE00FB5CCF /* FlutterConstants.swift */,
+ 76D71B662C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift */,
);
path = Helper;
sourceTree = "";
@@ -254,7 +298,7 @@
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
- 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 768D81742C6DF6E4005C655F /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
487FDD6493EB9AE7D8E39485 /* [CP] Embed Pods Frameworks */,
4671D3CD126F6635F4B75A6E /* [CP] Copy Pods Resources */,
@@ -274,7 +318,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -419,12 +463,18 @@
buildActionMask = 2147483647;
files = (
306FE6C8271D790C002D6EFC /* OpenTokPlatformBridge.swift in Sources */,
+ 76D71B6E2C6B81CC00DAFB84 /* PenguinPlugin.swift in Sources */,
E923EFD225863FDF00E3E751 /* GeoZoneModel.swift in Sources */,
E91B539A256AAA6500E96549 /* MainFlutterVC.swift in Sources */,
+ 76D71B672C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift in Sources */,
E91B539C256AAA6500E96549 /* HMG_GUEST_bkp.swift in Sources */,
E91B5396256AAA6500E96549 /* GlobalHelper.swift in Sources */,
E923EFD4258645C100E3E751 /* HMG_Geofence.swift in Sources */,
E923EFD62587443800E3E751 /* HMGPlatformBridge.swift in Sources */,
+ 76D71B6C2C6B81B300DAFB84 /* PenguinView.swift in Sources */,
+ 29631B9E2C96C7F600DF5916 /* PenguinNavigator.swift in Sources */,
+ 76D71B6A2C6B819000DAFB84 /* PenguinModel.swift in Sources */,
+ 76D71B702C6B81EA00DAFB84 /* PenguinViewFactory.swift in Sources */,
301C79AE27200D9F0016307B /* OpenTokRemoteVideoFactory.swift in Sources */,
E9F7623B25922BCE00FB5CCF /* FlutterConstants.swift in Sources */,
306FE6CB271D8B73002D6EFC /* OpenTok.swift in Sources */,
@@ -528,6 +578,7 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
@@ -549,14 +600,17 @@
"$(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 = "";
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_COMPILATION_MODE = singlefile;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
@@ -675,6 +729,7 @@
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
@@ -696,14 +751,18 @@
"$(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 = "";
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_COMPILATION_MODE = singlefile;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
@@ -713,6 +772,7 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
@@ -734,15 +794,18 @@
"$(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 = "";
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+ SUPPORTS_MACCATALYST = NO;
+ SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_COMPILATION_MODE = singlefile;
"SWIFT_COMPILATION_MODE[arch=*]" = singlefile;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index fab8f735..b2d2f7e5 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
HMGPenguinInPlatformBridge{
+ assert((HMGPenguinInPlatformBridge.shared_ != nil), "HMGPenguinInPlatformBridge is not initialized, call initialize(mainViewController:MainFlutterVC) function first.")
+ return HMGPenguinInPlatformBridge.shared_!
+ }
+
+ private func openChannel(){
+ flutterMethodChannelPenguinIn = FlutterMethodChannel(name: channelName, binaryMessenger: mainViewController.binaryMessenger)
+
+ flutterMethodChannelPenguinIn?.setMethodCallHandler { (methodCall, result) in
+ print("Called function \(methodCall.method)")
+
+ if let arguments = methodCall.arguments as Any? {
+ if methodCall.method == "launchPenguin"{
+ print("====== launchPenguinView Launched =========")
+ self.launchPenguinView(arguments: arguments, result: result)
+ }
+ } else {
+ result(FlutterError(code: "INVALID_ARGUMENT", message: "Storyboard name is required", details: nil))
+ }
+ }
+ }
+
+ 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,
+ arguments: arguments,
+ binaryMessenger: mainViewController.binaryMessenger
+ )
+
+ let penguinUIView = penguinView.view()
+ penguinUIView.frame = mainViewController.view.bounds
+ penguinUIView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+
+ mainViewController.view.addSubview(penguinUIView)
+
+ 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/Info.plist b/ios/Runner/Info.plist
index 43474d39..a67c0647 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -39,7 +39,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 11.0
+ 13.0
NFCReaderUsageDescription
This app requires NFC Usage access to allow for Online CheckIn for appointments.
NSAppTransportSecurity
@@ -60,7 +60,7 @@
NSCalendarsUsageDescription
This app requires calendar access to set reminders for Virtual & Normal Appointments.
NSCalendarsWriteOnlyAccessUsageDescription
- This app requires calendar access to set reminders for Virtual & Normal Appointments.
+ This app requires calendar access to set reminders for Virtual & Normal Appointments.
NSCalendarsFullAccessUsageDescription
This app requires calendar access to set reminders for Virtual & Normal Appointments.
NSCameraUsageDescription
@@ -120,5 +120,7 @@
UIApplicationSupportsIndirectInputEvents
+ MBXAccessToken
+ pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ
diff --git a/ios/Runner/Penguin/PenguinModel.swift b/ios/Runner/Penguin/PenguinModel.swift
new file mode 100644
index 00000000..e41979d6
--- /dev/null
+++ b/ios/Runner/Penguin/PenguinModel.swift
@@ -0,0 +1,76 @@
+//
+// PenguinModel.swift
+// Runner
+//
+// Created by Amir on 06/08/2024.
+//
+
+import Foundation
+
+// Define the model class
+struct PenguinModel {
+ let baseURL: String
+ let dataURL: String
+ let dataServiceName: String
+ let positionURL: String
+ let clientKey: String
+ let storyboardName: String
+ let mapBoxKey: String
+ let clientID: String
+ let positionServiceName: String
+ let username: String
+ let isSimulationModeEnabled: Bool
+ let isShowUserName: Bool
+ let isUpdateUserLocationSmoothly: Bool
+ let isEnableReportIssue: Bool
+ let languageCode: String
+ let clinicID: String
+ let patientID: String
+ let projectID: String
+
+ // Initialize the model from a dictionary
+ init?(from dictionary: [String: Any]) {
+ guard
+ let baseURL = dictionary["baseURL"] as? String,
+ let dataURL = dictionary["dataURL"] as? String,
+ let dataServiceName = dictionary["dataServiceName"] as? String,
+ let positionURL = dictionary["positionURL"] as? String,
+ let clientKey = dictionary["clientKey"] as? String,
+ let storyboardName = dictionary["storyboardName"] as? String,
+ let mapBoxKey = dictionary["mapBoxKey"] as? String,
+ let clientID = dictionary["clientID"] as? String,
+ let positionServiceName = dictionary["positionServiceName"] as? String,
+ let username = dictionary["username"] as? String,
+ let isSimulationModeEnabled = dictionary["isSimulationModeEnabled"] as? Bool,
+ let isShowUserName = dictionary["isShowUserName"] as? Bool,
+ let isUpdateUserLocationSmoothly = dictionary["isUpdateUserLocationSmoothly"] as? Bool,
+ let isEnableReportIssue = dictionary["isEnableReportIssue"] as? Bool,
+ let languageCode = dictionary["languageCode"] as? String,
+ let clinicID = dictionary["clinicID"] as? String,
+ let patientID = dictionary["patientID"] as? String,
+ let projectID = dictionary["projectID"] as? String
+ else {
+ print("Initialization failed due to missing or invalid keys.")
+ return nil
+ }
+
+ self.baseURL = baseURL
+ self.dataURL = dataURL
+ self.dataServiceName = dataServiceName
+ self.positionURL = positionURL
+ self.clientKey = clientKey
+ self.storyboardName = storyboardName
+ self.mapBoxKey = mapBoxKey
+ self.clientID = clientID
+ self.positionServiceName = positionServiceName
+ self.username = username
+ self.isSimulationModeEnabled = isSimulationModeEnabled
+ self.isShowUserName = isShowUserName
+ self.isUpdateUserLocationSmoothly = isUpdateUserLocationSmoothly
+ self.isEnableReportIssue = isEnableReportIssue
+ self.languageCode = languageCode
+ self.clinicID = clinicID
+ self.patientID = patientID
+ self.projectID = projectID
+ }
+}
diff --git a/ios/Runner/Penguin/PenguinNavigator.swift b/ios/Runner/Penguin/PenguinNavigator.swift
new file mode 100644
index 00000000..e7ce55b4
--- /dev/null
+++ b/ios/Runner/Penguin/PenguinNavigator.swift
@@ -0,0 +1,57 @@
+import PenNavUI
+import UIKit
+
+class PenguinNavigator {
+ private var config: PenguinModel
+
+ init(config: PenguinModel) {
+ self.config = config
+ }
+
+ private func logError(_ message: String) {
+ // Centralized logging function
+ print("PenguinSDKNavigator Error: \(message)")
+ }
+
+ func navigateToPOI( referenceId:String,completion: @escaping (Bool, String?) -> Void) {
+ 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"
+ completion(false, "Failed to get token: \(errorMessage)")
+
+ print("Failed to get token: \(errorMessage)")
+ return
+ }
+
+ guard let token = token else {
+ completion(false, "Token is nil")
+ print("Token is nil")
+ return
+ }
+ print("Token Generated")
+ print(token);
+
+
+ }
+ }
+
+ private func handleNavigation(referenceId: String, token: String, completion: @escaping (Bool, String?) -> Void) {
+ DispatchQueue.main.async {
+ PenNavUIManager.shared.setToken(token: token)
+
+ PenNavUIManager.shared.navigate(to: referenceId) { [weak self] _, navError in
+ guard let self = self else { return }
+
+ if let navError = navError {
+ self.logError("Navigation error: Reference ID invalid")
+ completion(false, "Navigation error: \(navError.localizedDescription)")
+ return
+ }
+
+ // Navigation successful
+ completion(true, nil)
+ }
+ }
+ }
+}
diff --git a/ios/Runner/Penguin/PenguinPlugin.swift b/ios/Runner/Penguin/PenguinPlugin.swift
new file mode 100644
index 00000000..029bec35
--- /dev/null
+++ b/ios/Runner/Penguin/PenguinPlugin.swift
@@ -0,0 +1,31 @@
+//
+// BlueGpsPlugin.swift
+// Runner
+//
+// Created by Penguin .
+//
+
+//import Foundation
+//import Flutter
+//
+///**
+// * A Flutter plugin for integrating Penguin SDK functionality.
+// * This class registers a view factory with the Flutter engine to create native views.
+// */
+//class PenguinPlugin: NSObject, FlutterPlugin {
+//
+// /**
+// * Registers the plugin with the Flutter engine.
+// *
+// * @param registrar The [FlutterPluginRegistrar] used to register the plugin.
+// * This method is called when the plugin is initialized, and it sets up the communication
+// * between Flutter and native code.
+// */
+// public static func register(with registrar: FlutterPluginRegistrar) {
+// // Create an instance of PenguinViewFactory with the binary messenger from the registrar
+// let factory = PenguinViewFactory(messenger: registrar.messenger())
+//
+// // Register the view factory with a unique ID for use in Flutter code
+// registrar.register(factory, withId: "penguin_native")
+// }
+//}
diff --git a/ios/Runner/Penguin/PenguinView.swift b/ios/Runner/Penguin/PenguinView.swift
new file mode 100644
index 00000000..b5161eb0
--- /dev/null
+++ b/ios/Runner/Penguin/PenguinView.swift
@@ -0,0 +1,445 @@
+//
+
+// BlueGpsView.swift
+
+// Runner
+
+//
+
+// Created by Penguin.
+
+//
+
+
+
+import Foundation
+import UIKit
+import Flutter
+import PenNavUI
+
+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
+
+{
+ // 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 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/ios/Runner/Penguin/PenguinViewFactory.swift b/ios/Runner/Penguin/PenguinViewFactory.swift
new file mode 100644
index 00000000..a88bb5d0
--- /dev/null
+++ b/ios/Runner/Penguin/PenguinViewFactory.swift
@@ -0,0 +1,59 @@
+//
+// BlueGpsViewFactory.swift
+// Runner
+//
+// Created by Penguin .
+//
+
+import Foundation
+import Flutter
+
+/**
+ * A factory class for creating instances of [PenguinView].
+ * This class implements `FlutterPlatformViewFactory` to create and manage native views.
+ */
+class PenguinViewFactory: NSObject, FlutterPlatformViewFactory {
+
+ // The binary messenger used for communication with the Flutter engine
+ private var messenger: FlutterBinaryMessenger
+
+ /**
+ * Initializes the PenguinViewFactory with the given messenger.
+ *
+ * @param messenger The [FlutterBinaryMessenger] used to communicate with Dart code.
+ */
+ init(messenger: FlutterBinaryMessenger) {
+ self.messenger = messenger
+ super.init()
+ }
+
+ /**
+ * Creates a new instance of [PenguinView].
+ *
+ * @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.
+ * @return An instance of [PenguinView] configured with the provided parameters.
+ */
+ func create(
+ withFrame frame: CGRect,
+ viewIdentifier viewId: Int64,
+ arguments args: Any?
+ ) -> FlutterPlatformView {
+ return PenguinView(
+ frame: frame,
+ viewIdentifier: viewId,
+ arguments: args,
+ binaryMessenger: messenger)
+ }
+
+ /**
+ * Returns the codec used for encoding and decoding method channel arguments.
+ * This method is required when `arguments` in `create` is not `nil`.
+ *
+ * @return A [FlutterMessageCodec] instance used for serialization.
+ */
+ public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
+ return FlutterStandardMessageCodec.sharedInstance()
+ }
+}
diff --git a/lib/config/config.dart b/lib/config/config.dart
index b779da36..145ecfde 100644
--- a/lib/config/config.dart
+++ b/lib/config/config.dart
@@ -22,8 +22,8 @@ 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://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://orash.cloudsolutions.com.sa/';
// var BASE_URL = 'https://vidauat.cloudsolutions.com.sa/';
@@ -215,6 +215,7 @@ var GET_QR_PARKING = 'Services/SWP.svc/REST/GetQRParkingByID';
//URL to get clinic list
var GET_CLINICS_LIST_URL = "Services/lists.svc/REST/GetClinicCentralized";
+var GET_CLINICS_LIST_WRT_HOSPITAL_URL = "Services/Lists.svc/REST/GetClinicFromDoctorSchedule";
//URL to get active appointment list
var GET_ACTIVE_APPOINTMENTS_LIST_URL = "Services/Doctors.svc/Rest/Dr_GetAppointmentActiveNumber";
@@ -313,6 +314,8 @@ var GET_LIVECARE_CLINIC_TIMING = 'Services/ER_VirtualCall.svc/REST/PatientER_Get
var GET_ER_APPOINTMENT_FEES = 'Services/DoctorApplication.svc/REST/GetERAppointmentFees';
var GET_ER_APPOINTMENT_TIME = 'Services/ER_VirtualCall.svc/REST/GetRestTime';
+var CHECK_PATIENT_DERMA_PACKAGE = 'Services/OUTPs.svc/REST/getPatientPackageComponentsForOnlineCheckIn';
+
var ADD_NEW_CALL_FOR_PATIENT_ER = 'Services/DoctorApplication.svc/REST/NewCallForPatientER';
var GET_LIVECARE_HISTORY = 'Services/ER_VirtualCall.svc/REST/GetPatientErVirtualHistory';
@@ -333,18 +336,25 @@ var GET_PATIENT_HEALTH_STATS = 'Services/Patients.svc/REST/Med_GetTransactionsSt
var SEND_CHECK_IN_NFC_REQUEST = 'Services/Patients.svc/REST/Patient_CheckAppointmentValidation_ForNFC';
+var CHECK_SCANNED_NFC_QR_CODE = 'Services/Patients.svc/REST/Patient_ValidationMachine_ForNFC';
+
var HAS_DENTAL_PLAN = 'Services/Doctors.svc/REST/Dental_IsPatientHasOnGoingEstimation';
var LASER_BODY_PARTS = 'Services/Patients.svc/REST/Laser_GetBodyPartsByCategory';
var INSERT_COVID_QUESTIONNAIRE = 'Services/Doctors.svc/REST/COVID19_Questionnarie_Insert';
+
var UPDATE_COVID_QUESTIONNAIRE = 'Services/Doctors.svc/REST/COVID19_Questionnarie_Update';
+var GET_PATIENT_SHARE_FOR_WALKIN_APPOINTMENT = 'Services/Doctors.svc/REST/GetCheckinScreenAppointmentDetailsByAppointmentNOForWalkIn';
+
+var CAN_PAY_FOR_FOR_WALKIN_APPOINTMENT = 'Services/Doctors.svc/REST/CanPayForWalkinAppointment';
+
//URL to get medicine and pharmacies list
var CHANNEL = 3;
var GENERAL_ID = 'Cs2020@2016\$2958';
var IP_ADDRESS = '10.20.10.20';
-var VERSION_ID = 16.0;
+var VERSION_ID = 16.7;
var SETUP_ID = '91877';
var LANGUAGE = 2;
// var PATIENT_OUT_SA = 0;
@@ -647,6 +657,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';
@@ -665,6 +677,23 @@ var GET_WE_CARE_TOUR_URL = 'Services/Consent.svc/Rest/Consent_VirtualJurny_Url_G
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 5babf3ea..1c318407 100644
--- a/lib/config/localized_values.dart
+++ b/lib/config/localized_values.dart
@@ -45,6 +45,8 @@ const Map localizedValues = {
'name': {'en': 'Name', 'ar': 'الإسم'},
'doctor': {'en': 'Doctor', 'ar': 'الطبيب'},
'clinicName': {'en': 'Clinic Name', 'ar': 'اسم العيادة'},
+ 'hospitalName': {'en': 'Hospital Name', 'ar': 'اسم المستشفى'},
+ 'NoClinicFound': {'en': 'No Clinic Found', 'ar': 'لم يتم العثور على عيادة'},
'doctorName': {'en': 'Doctor Name', 'ar': 'إسم الطبيب'},
'nearestAppo': {'en': 'Nearest Appointment', 'ar': 'أقرب موعد'},
'searchByDocText': {'en': 'Type the name of the doctor to help you find him', 'ar': 'اكتب اسم الطبيب لمساعدتك في العثور عليه'},
@@ -1870,8 +1872,14 @@ const Map localizedValues = {
"insuranceClassName": {"en": "Insurance Class", "ar": "فئة التأمين"},
"insuranceRequestSubmit": {"en": "Your insurance update request has been submitted successfully.", "ar": "تم تقديم طلب تحديث التأمين الخاص بك بنجاح."},
"NFCNotSupported": {"en": "Your device does not support NFC. Please visit reception to Check-In", "ar": "جهازك لا يدعم NFC. يرجى زيارة مكتب الاستقبال لتسجيل الوصول"},
- "enter-workplace-name": {"en": "Please enter your workplace name:", "ar": "رجاء إدخال مكان العمل:"},
- "workplaceName": {"en": "Workplace name:", "ar": "مكان العمل:"},
+ "enter-workplace-name": {"en": "Please enter your workplace details:", "ar": "الرجاء إدخال تفاصيل مكان عملك:"},
+
+ // "workplaceName": {"en": "Workplace name:", "ar": "مكان العمل:"},
+ "workplaceName": {"en": "Workplace name English", "ar": "مكان العمل انجليزي:"},
+ "workplaceNameAr": {"en": "Workplace name Arabic *", "ar": "مكان العمل عربي:"},
+ "occupationNameEn": {"en": "Occupation name English", "ar": "مكان العمل انجليزي:"},
+ "occupationNameAr": {"en": "Occupation name Arabic *", "ar": "مكان العمل عربي:"},
+
"callLiveCareSupport": {"en": "Call LiveCare Support", "ar": "اتصل بدعم اللايف كير"},
"needApproval": {
"en": "Your sick leave is under process in medical administration, you will be notified once approved.",
@@ -1943,12 +1951,25 @@ const Map localizedValues = {
"generalInstructions": {"en": "General Instructions:", "ar": "تعليمات عامة:"},
"copyLink": {"en": "COPY LINK", "ar": "نسخ الوصلة:"},
"paymentLinkCopied": {"en": "Payment link copied to your clipboard!'", "ar": "تم نسخ رابط الدفع إلى الحافظة الخاصة بك!"},
- "copyLinkTxt": {"en": "Or you can copy the payment link from below & send it to someone who can pay on your behalf: ", "ar": "أو يمكنك نسخ رابط الدفع من الأسفل وإرساله إلى شخص يمكنه الدفع نيابة عنك:"},
- "proErrorMessage": {"en": "Dear patient, Our staff is currently out of office, please note that our working hours are from 7:00 AM to 10:00 PM, and we'd love to help you during that time, or you can call ", "ar": "عزيزي المريض ، طاقم العمل لدينا خارج المكتب حاليًا ، يرجى ملاحظة أن ساعات العمل لدينا من 7:00 صباحًا إلى 10:00 مساءً ، ويسعدنا مساعدتك خلال هذا الوقت ، أو يمكنك الاتصال بـ <أدخل الرقم هنا>"},
+ "copyLinkTxt": {
+ "en": "Or you can copy the payment link from below & send it to someone who can pay on your behalf: ",
+ "ar": "أو يمكنك نسخ رابط الدفع من الأسفل وإرساله إلى شخص يمكنه الدفع نيابة عنك:"
+ },
+ "proErrorMessage": {
+ "en":
+ "Dear patient, Our staff is currently out of office, please note that our working hours are from 7:00 AM to 10:00 PM, and we'd love to help you during that time, or you can call ",
+ "ar": "عزيزي المريض ، طاقم العمل لدينا خارج المكتب حاليًا ، يرجى ملاحظة أن ساعات العمل لدينا من 7:00 صباحًا إلى 10:00 مساءً ، ويسعدنا مساعدتك خلال هذا الوقت ، أو يمكنك الاتصال بـ <أدخل الرقم هنا>"
+ },
"admissionNo": {"en": "Admission No", "ar": "رقم القبول:"},
"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": "لا يمكنك إجراء الدفع عبر الإنترنت لأنك غير مؤهل لاستخدام الخدمة المقدمة."
@@ -1965,10 +1986,7 @@ const Map localizedValues = {
"validInsurance": {"en": "Do you have a valid insurance?", "ar": "هل لديك تأمين صالح؟"},
"contactRRT": {"en": "Contact RRT", "ar": "تواصل مع فريق الاستجابة السريعة"},
"checkInViaLocation": {"en": "Check-In Via Location", "ar": "تسجيل الوصول عبر الموقع"},
- "locationCheckInError": {
- "en": "Please make sure that you're within the hospital location to perform online check-in.",
- "ar": "يرجى التأكد من تواجدك داخل موقع المستشفى لإجراء تسجيل الوصول عبر الإنترنت."
- },
+ "locationCheckInError": {"en": "Please ensure you're within the hospital location to perform online check-in.", "ar": "يرجى التأكد من تواجدك داخل موقع المستشفى لإجراء تسجيل الوصول عبر الإنترنت."},
"upcoming": {"en": "Upcoming", "ar": "المواعيد القادمة"},
"noUpcomingAppointment": {"en": "No upcoming appointments", "ar": "لا توجد مواعيد القادمة"},
"locationTimeoutError": {"en": "Unable to fetch your location, Please try again.", "ar": "غير قادر على جلب موقعك، يرجى المحاولة مرة أخرى."},
@@ -1976,6 +1994,26 @@ const Map localizedValues = {
"selectHospitalBloodDonation": {"en": "Please select the hospital you want to book an appointment with: ", "ar": "يرجى اختيار المستشفى الذي تريد حجز موعد معه:"},
"wecare": {"en": "We Care", "ar": "نحن نهتم"},
"myinstructions": {"en": "My Instructions", "ar": "تعليماتي"},
+ "existingPackage": {"en": "This patient has a package under this clinic,", "ar": "هذا المريض لديه حزمة تحت هذه العيادة،"},
+ "continueOrbookNew": {"en": "do you want to continue with that package? or book new appointment?", "ar": "هل تريد الاستمرار في هذه الباقة؟ أو حجز موعد جديد؟"},
+ "newAppointment": {"en": "New Appointment", "ar": "موعد جديد"},
+ "proceedPackage": {"en": "Proceed with package", "ar": "المضي قدما في الحزمة"},
+
+ "clinicLocation": {"en": "Clinic Location", "ar": "موقع العيادة"},
+ "waitingAppointment": {"en": "Waiting appointment", "ar": "انتظار الموعد"},
+ "whatWaitingAppointment": {"en": "What is Waiting appointment?", "ar": "ما هو انتظار الموعد؟"},
+ "waitingAppointmentText1": {
+ "en": "The waiting appointments feature allows you to book an appointment while you are inside the hospital building, and in case there is no available slot in the doctor’s schedule.",
+ "ar": "تتيح لك خاصية انتظار المواعيد حجز موعد أثناء تواجدك داخل مبنى المستشفى، وفي حالة عدم وجود وقت متاح في جدول الطبيب."
+ },
+ "waitingAppointmentText2": {"en": "The appointment with the doctor is confirmed, but the time of entry is uncertain", "ar": "دخول الموعد مؤكد, التوقيت غير محدد."},
+ "waitingAppointmentText3": {
+ "en": "Note: You must have to pay within 10 minutes of booking, otherwise your appointment will be cancelled automatically",
+ "ar": "ملحوظة: يجب عليك الدفع خلال 10 دقائق من الحجز، وإلا سيتم إلغاء موعدك تلقائيًا"
+ },
+ "waitingAppointmentVerificationMethod": {"en": "Please select verification method", "ar": "الرجاء تحديد طريقة التحقق"},
+ "howToUseVerificationMethod": {"en": "How to use verification methods?", "ar": "كيفية استخدام طرق التحقق؟"},
+ "addToWaitingList": {"en": "Add to waiting list", "ar": "اضافه الى قائمة الانتظار"},
"searchClinic": {"en": "Search Clinic", "ar": "بحث العيادة"},
"enterMobileNumber": {"en": "Enter Mobile Number", "ar": "أدخل رقم الجوال"},
"videoCall": {"en": "Video Call", "ar": "اتصال فيديو"},
@@ -1983,4 +2021,103 @@ const Map localizedValues = {
"phoneCall": {"en": "Phone Call", "ar": "اتصال هاتفية"},
"selectCallType": {"en": "Select Call Type", "ar": "حدد نوع المكالمة"},
"selectedCallType": {"en": "Selected Call Type", "ar": "نوع المكالمة المحدد"},
+ "selectBranch": {"en": "Select Branch", "ar": "اختر الفرع"},
+ "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/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart
index d8f30f0c..37a3a722 100644
--- a/lib/core/service/client/base_app_client.dart
+++ b/lib/core/service/client/base_app_client.dart
@@ -31,8 +31,7 @@ AppSharedPreferences sharedPref = new AppSharedPreferences();
/// onFailure: (String error, int statusCode) {},
/// body: Map();
///
-AuthenticatedUserObject authenticatedUserObject =
- locator();
+AuthenticatedUserObject authenticatedUserObject = locator();
VitalSignService _vitalSignService = locator();
class BaseAppClient {
@@ -40,12 +39,12 @@ class BaseAppClient {
post(String endPoint,
{required Map body,
- required Function(dynamic response, int statusCode) onSuccess,
- required Function(String error, int statusCode) onFailure,
- bool isAllowAny = false,
- bool isExternal = false,
- bool isRCService = false,
- bool bypassConnectionCheck = false}) async {
+ required Function(dynamic response, int statusCode) onSuccess,
+ required Function(String error, int statusCode) onFailure,
+ bool isAllowAny = false,
+ bool isExternal = false,
+ bool isRCService = false,
+ bool bypassConnectionCheck = false}) async {
String url;
if (isExternal) {
url = endPoint;
@@ -56,25 +55,20 @@ class BaseAppClient {
url = BASE_URL + endPoint;
}
try {
- String? pharmacyToken =
- await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
+ String? pharmacyToken = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
var user = await sharedPref.getObject(USER_PROFILE);
- Map headers = {
- 'Content-Type': 'application/json',
- 'Accept': 'application/json'
- };
+ Map headers = {'Content-Type': 'application/json', 'Accept': 'application/json'};
if (!isExternal) {
String? token = await sharedPref.getString(TOKEN);
- String? languageID =
- await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
+ String? languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
if (endPoint == SEND_ACTIVATION_CODE) {
languageID = 'en';
}
if (body.containsKey('SetupID')) {
body['SetupID'] = body.containsKey('SetupID')
? body['SetupID'] != null
- ? body['SetupID']
- : SETUP_ID
+ ? body['SetupID']
+ : SETUP_ID
: SETUP_ID;
}
@@ -87,8 +81,8 @@ class BaseAppClient {
body['LanguageID'] = body['LanguageID'] == 'ar'
? 1
: body['LanguageID'] == 'en'
- ? 2
- : body['LanguageID'];
+ ? 2
+ : body['LanguageID'];
} else {
body['LanguageID'] = Provider.of(AppGlobal.context, listen: false).isArabic ? 1 : 2;
}
@@ -120,16 +114,16 @@ class BaseAppClient {
if (body.containsKey('isDentalAllowedBackend')) {
body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
? body['isDentalAllowedBackend'] != null
- ? body['isDentalAllowedBackend']
- : IS_DENTAL_ALLOWED_BACKEND
+ ? body['isDentalAllowedBackend']
+ : IS_DENTAL_ALLOWED_BACKEND
: IS_DENTAL_ALLOWED_BACKEND;
}
body['DeviceTypeID'] = Platform.isIOS
? 1
: await Utils.isGoogleServicesAvailable()
- ? 2
- : 3;
+ ? 2
+ : 3;
if (!body.containsKey('IsPublicRequest')) {
// if (!body.containsKey('PatientType')) {
@@ -166,17 +160,14 @@ class BaseAppClient {
if (user != null) {
body['TokenID'] = body['TokenID'] != null ? body['TokenID'] : token;
- body['PatientID'] = body['PatientID'] != null
- ? body['PatientID']
- : user['PatientID'];
+ body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID'];
body['PatientOutSA'] = body.containsKey('PatientOutSA')
? body['PatientOutSA'] != null
- ? body['PatientOutSA']
- : user['OutSA']
+ ? body['PatientOutSA']
+ : user['OutSA']
: user['OutSA'];
- body['SessionID'] = getSessionId(
- body['TokenID'] != null ? body['TokenID'] : ""); //getSe
+ body['SessionID'] = getSessionId(body['TokenID'] != null ? body['TokenID'] : ""); //getSe
// body['SessionID'] = body['TokenID']; //getSe
// headers = {
@@ -193,7 +184,7 @@ class BaseAppClient {
// body['IdentificationNo'] = 1023854217;
// body['MobileNo'] = "531940021"; //0560717232
- // body['PatientID'] = 283093; //4609100
+ // body['PatientID'] = 4768303; //4609100
// body['TokenID'] = "@dm!n";
// Patient ID: 3027574
@@ -202,21 +193,23 @@ class BaseAppClient {
body.removeWhere((key, value) => key == null || value == null);
+ // if (url == 'https://uat.hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo') {
+ // url = "https://hmgwebservices.com/Services/NHIC.svc/REST/GetPatientInfo";
+ // body['TokenID'] = "@dm!n";
+ // }
+
// if (AppGlobal.isNetworkDebugEnabled) {
- print("URL : $url");
- final jsonBody = json.encode(body);
- print(jsonBody);
+ print("URL : $url");
+ final jsonBody = json.encode(body);
+ print(jsonBody);
// }
- if (await Utils.checkConnection(
- bypassConnectionCheck: bypassConnectionCheck)) {
- final response = await http.post(Uri.parse(url.trim()),
- body: json.encode(body), headers: headers);
+ if (await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck)) {
+ final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400 || json == null) {
onFailure('Error While Fetching data', statusCode);
- logApiEndpointError(
- endPoint, 'Error While Fetching data', statusCode);
+ logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
} else {
// var decoded = utf8.decode(response.bodyBytes);
var parsed = json.decode(utf8.decode(response.bodyBytes));
@@ -230,12 +223,8 @@ class BaseAppClient {
onSuccess(parsed, statusCode);
} else {
if (parsed['ErrorType'] == 4) {
- navigateToAppUpdate(
- AppGlobal.context, parsed['ErrorEndUserMessage']);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
if (parsed['ErrorType'] == 2) {
await logout();
@@ -254,46 +243,28 @@ class BaseAppClient {
// if (parsed != null) {
// onSuccess(parsed, statusCode);
// } else {
- onFailure(
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
// logout();
// }
}
- } else if (parsed['MessageStatus'] == 1 ||
- parsed['SMSLoginRequired'] == true) {
+ } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
onSuccess(parsed, statusCode);
- } else if (parsed['MessageStatus'] == 2 &&
- parsed['IsAuthenticated']) {
+ } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode);
} else {
- if (parsed['message'] == null &&
- parsed['ErrorEndUserMessage'] == null) {
+ if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
if (parsed['ErrorSearchMsg'] == null) {
- onFailure("Server Error found with no available message",
- statusCode);
- logApiEndpointError(
- endPoint,
- "Server Error found with no available message",
- statusCode);
+ onFailure("Server Error found with no available message", statusCode);
+ logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
} else {
onFailure(parsed['ErrorSearchMsg'], statusCode);
- logApiEndpointError(
- endPoint, parsed['ErrorSearchMsg'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode);
}
} else {
- onFailure(
- parsed['message'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(endPoint,
- parsed['message'] ?? parsed['message'], statusCode);
+ onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
}
}
}
@@ -305,18 +276,11 @@ class BaseAppClient {
onSuccess(parsed, statusCode);
} else {
if (parsed['message'] != null) {
- onFailure(
- parsed['message'] ?? parsed['message'], statusCode);
- logApiEndpointError(endPoint,
- parsed['message'] ?? parsed['message'], statusCode);
+ onFailure(parsed['message'] ?? parsed['message'], statusCode);
+ logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
} else {
- onFailure(
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
}
}
@@ -325,23 +289,17 @@ class BaseAppClient {
}
} else {
onFailure('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
} catch (e) {
print(e);
onFailure(e.toString(), -1);
- _analytics.errorTracking
- .log(endPoint, error: "api exception: $e - API Path: $url");
+ _analytics.errorTracking.log(endPoint, error: "api exception: $e - API Path: $url");
}
}
postPharmacy(String endPoint,
- {Map? body,
- Function(dynamic response, int statusCode)? onSuccess,
- Function(String error, int statusCode)? onFailure,
- bool isAllowAny = false,
- bool isExternal = false}) async {
+ {Map? body, Function(dynamic response, int statusCode)? onSuccess, Function(String error, int statusCode)? onFailure, bool isAllowAny = false, bool isExternal = false}) async {
var token = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
var user = await sharedPref.getObject(USER_PROFILE);
String url;
@@ -358,16 +316,13 @@ class BaseAppClient {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': pharmacyToken ?? '',
- 'Mobilenumber': user != null
- ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString())
- : "",
+ 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
'Username': user != null ? user['PatientID'].toString() : "",
};
if (!isExternal) {
String token = await sharedPref.getString(TOKEN);
- var languageID =
- await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
+ var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
// if (body.containsKey('SetupID')) {
// body['SetupID'] = body.containsKey('SetupID')
@@ -429,14 +384,12 @@ class BaseAppClient {
print("Headers : ${json.encode(headers)}");
if (await Utils.checkConnection()) {
- final response = await http.post(Uri.parse(url.trim()),
- body: json.encode(body), headers: headers);
+ final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
final int statusCode = response.statusCode;
// print("statusCode :$statusCode");
if (statusCode < 200 || statusCode >= 400 || json == null) {
onFailure!('Error While Fetching data', statusCode);
- logApiEndpointError(
- endPoint, 'Error While Fetching data', statusCode);
+ logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
} else {
// var parsed = json.decode(response.body.toString());
var parsed = json.decode(utf8.decode(response.bodyBytes));
@@ -444,12 +397,8 @@ class BaseAppClient {
onSuccess!(parsed, statusCode);
} else {
if (parsed['ErrorType'] == 4) {
- navigateToAppUpdate(
- AppGlobal.context, parsed['ErrorEndUserMessage']);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
if (isAllowAny) {
onSuccess!(parsed, statusCode);
@@ -464,56 +413,29 @@ class BaseAppClient {
if (parsed != null) {
onSuccess!(parsed, statusCode);
} else {
- onFailure!(
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint, 'session logged out', statusCode);
+ onFailure!(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, 'session logged out', statusCode);
logout();
}
}
- } else if (parsed['MessageStatus'] == 1 ||
- parsed['SMSLoginRequired'] == true) {
+ } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
onSuccess!(parsed, statusCode);
- } else if (parsed['MessageStatus'] == 2 &&
- parsed['IsAuthenticated']) {
+ } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
if (parsed['SameClinicApptList'] != null) {
onSuccess!(parsed, statusCode);
} else {
- if (parsed['message'] == null &&
- parsed['ErrorEndUserMessage'] == null) {
+ if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
if (parsed['ErrorSearchMsg'] == null) {
- onFailure!("Server Error found with no available message",
- statusCode);
- logApiEndpointError(
- endPoint,
- "Server Error found with no available message",
- statusCode);
+ onFailure!("Server Error found with no available message", statusCode);
+ logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
} else {
onFailure!(parsed['ErrorSearchMsg'], statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorSearchMsg'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorSearchMsg'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
} else {
- onFailure!(
- parsed['message'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['message'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
+ onFailure!(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
}
} else if (!parsed['IsAuthenticated']) {
@@ -525,22 +447,11 @@ class BaseAppClient {
onSuccess!(parsed, statusCode);
} else {
if (parsed['message'] != null) {
- onFailure!(
- parsed['message'] ?? parsed['message'], statusCode);
- logApiEndpointError(
- endPoint,
- parsed['message'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
+ onFailure!(parsed['message'] ?? parsed['message'], statusCode);
+ logApiEndpointError(endPoint, parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
} else {
- onFailure!(
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ onFailure!(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
}
}
@@ -548,8 +459,7 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
} catch (e) {
print(e);
@@ -560,18 +470,18 @@ class BaseAppClient {
Future navigateToAppUpdate(context, String text) async {
Navigator.pushAndRemoveUntil(
- locator().navigatorKey.currentContext!,
+ locator().navigatorKey.currentContext!,
MaterialPageRoute(builder: (context) => AppUpdatePage(appUpdateText: text)),
- (Route route) => false,
+ (Route route) => false,
);
}
get(String endPoint,
{required Function(dynamic response, int statusCode) onSuccess,
- required Function(String error, int statusCode) onFailure,
- Map? queryParams,
- bool isExternal = false,
- bool isRCService = false}) async {
+ required Function(String error, int statusCode) onFailure,
+ Map? queryParams,
+ bool isExternal = false,
+ bool isRCService = false}) async {
String url;
if (isExternal) {
url = endPoint;
@@ -592,10 +502,7 @@ class BaseAppClient {
if (await Utils.checkConnection()) {
final response = await http.get(
Uri.parse(url.trim()),
- headers: {
- 'Content-Type': 'application/json',
- 'Accept': 'application/json'
- },
+ headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
);
final int statusCode = response.statusCode;
// print("statusCode :$statusCode");
@@ -609,17 +516,16 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
}
getPharmacy(String endPoint,
{required Function(dynamic response, int statusCode) onSuccess,
- required Function(String error, int statusCode) onFailure,
- bool isAllowAny = false,
- bool isExternal = false,
- Map? queryParams}) async {
+ required Function(String error, int statusCode) onFailure,
+ bool isAllowAny = false,
+ bool isExternal = false,
+ Map? queryParams}) async {
var token = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
var user = await sharedPref.getObject(USER_PROFILE);
@@ -642,9 +548,7 @@ class BaseAppClient {
'Content-Type': 'text/html; charset=utf-8',
'Accept': 'application/json',
'Authorization': token ?? '',
- 'Mobilenumber': user != null
- ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString())
- : "",
+ 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
'Username': user != null ? user['PatientID'].toString() : "",
// 'Host': "mdlaboratories.com",
@@ -654,19 +558,14 @@ class BaseAppClient {
if (statusCode < 200 || statusCode >= 400 || json == null) {
if (statusCode == 401) {
- onFailure!(TranslationBase.of(AppGlobal.context).pharmacyRelogin,
- statusCode);
- logApiEndpointError(
- endPoint,
- TranslationBase.of(AppGlobal.context).pharmacyRelogin,
- statusCode);
+ onFailure!(TranslationBase.of(AppGlobal.context).pharmacyRelogin, statusCode);
+ logApiEndpointError(endPoint, TranslationBase.of(AppGlobal.context).pharmacyRelogin, statusCode);
Navigator.of(AppGlobal.context).pushNamed(HOME);
} else {
var bodyUtf = json.decode(utf8.decode(response.bodyBytes));
// print(bodyUtf);
onFailure!(bodyUtf['error']['ErrorEndUserMsg'], statusCode);
- logApiEndpointError(
- endPoint, bodyUtf['error']['ErrorEndUserMsg'], statusCode);
+ logApiEndpointError(endPoint, bodyUtf['error']['ErrorEndUserMsg'], statusCode);
}
} else {
// var parsed = json.decode(response.body.toString());
@@ -675,25 +574,23 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
}
simplePost(
- String fullUrl, {
- required Map body,
- required Map headers,
- required Function(dynamic response, int statusCode) onSuccess,
- required Function(String error, int statusCode) onFailure,
- }) async {
+ String fullUrl, {
+ required Map body,
+ required Map headers,
+ required Function(dynamic response, int statusCode) onSuccess,
+ required Function(String error, int statusCode) onFailure,
+ }) async {
String url = fullUrl;
// print("URL Query String: $url");
// print("body: $body");
if (await Utils.checkConnection()) {
- headers!.addAll(
- {'Content-Type': 'application/json', 'Accept': 'application/json'});
+ headers!.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
final response = await http.post(
Uri.parse(url.trim()),
body: json.encode(body),
@@ -701,12 +598,7 @@ class BaseAppClient {
);
final int statusCode = response.statusCode;
// print("statusCode :$statusCode");
- if (await handleUnauthorized(statusCode, forUrl: fullUrl))
- simplePost(fullUrl,
- onFailure: onFailure,
- onSuccess: onSuccess,
- body: body,
- headers: headers);
+ if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simplePost(fullUrl, onFailure: onFailure, onSuccess: onSuccess, body: body, headers: headers);
// print(response.body.toString());
@@ -718,16 +610,12 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
}
simpleGet(String fullUrl,
- {Function(dynamic response, int statusCode)? onSuccess,
- Function(String error, int statusCode)? onFailure,
- Map? queryParams,
- Map? headers}) async {
+ {Function(dynamic response, int statusCode)? onSuccess, Function(String error, int statusCode)? onFailure, Map? queryParams, Map? headers}) async {
headers = headers ?? {};
String url = fullUrl;
@@ -739,8 +627,7 @@ class BaseAppClient {
}
if (await Utils.checkConnection()) {
- headers.addAll(
- {'Content-Type': 'application/json', 'Accept': 'application/json'});
+ headers.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
final response = await http.get(
Uri.parse(url.trim()),
headers: headers,
@@ -748,12 +635,7 @@ class BaseAppClient {
final int statusCode = response.statusCode;
// print("statusCode :$statusCode");
- if (await handleUnauthorized(statusCode, forUrl: fullUrl))
- simpleGet(fullUrl,
- onFailure: onFailure,
- onSuccess: onSuccess,
- headers: headers,
- queryParams: queryParams);
+ if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simpleGet(fullUrl, onFailure: onFailure, onSuccess: onSuccess, headers: headers, queryParams: queryParams);
if (statusCode < 200 || statusCode >= 400 || json == null) {
onFailure!('Error While Fetching data', statusCode);
@@ -763,22 +645,17 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
}
simplePut(String fullUrl,
- {Map? body,
- Map? headers,
- Function(dynamic response, int statusCode)? onSuccess,
- Function(String error, int statusCode)? onFailure}) async {
+ {Map? body, Map? headers, Function(dynamic response, int statusCode)? onSuccess, Function(String error, int statusCode)? onFailure}) async {
String url = fullUrl;
// print("URL Query String: $url");
if (await Utils.checkConnection()) {
- headers!.addAll(
- {'Content-Type': 'application/json', 'Accept': 'application/json'});
+ headers!.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
final response = await http.put(
Uri.parse(url.trim()),
body: json.encode(body),
@@ -787,12 +664,7 @@ class BaseAppClient {
final int statusCode = response.statusCode;
// print("statusCode :$statusCode");
- if (await handleUnauthorized(statusCode, forUrl: fullUrl))
- simplePut(fullUrl,
- onFailure: onFailure,
- onSuccess: onSuccess,
- headers: headers,
- body: body);
+ if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simplePut(fullUrl, onFailure: onFailure, onSuccess: onSuccess, headers: headers, body: body);
if (statusCode < 200 || statusCode >= 400 || json == null) {
onFailure!('Error While Fetching data', statusCode);
@@ -802,16 +674,12 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
}
simpleDelete(String fullUrl,
- {Function(dynamic response, int statusCode)? onSuccess,
- Function(String error, int statusCode)? onFailure,
- Map? queryParams,
- Map? headers}) async {
+ {Function(dynamic response, int statusCode)? onSuccess, Function(String error, int statusCode)? onFailure, Map? queryParams, Map? headers}) async {
String url = fullUrl;
// print("URL Query String: $url");
@@ -823,8 +691,7 @@ class BaseAppClient {
}
if (await Utils.checkConnection()) {
- headers!.addAll(
- {'Content-Type': 'application/json', 'Accept': 'application/json'});
+ headers!.addAll({'Content-Type': 'application/json', 'Accept': 'application/json'});
final response = await http.delete(
Uri.parse(url.trim()),
headers: headers,
@@ -832,12 +699,7 @@ class BaseAppClient {
final int statusCode = response.statusCode;
// print("statusCode :$statusCode");
- if (await handleUnauthorized(statusCode, forUrl: fullUrl))
- simpleDelete(fullUrl,
- onFailure: onFailure,
- onSuccess: onSuccess,
- queryParams: queryParams,
- headers: headers);
+ if (await handleUnauthorized(statusCode, forUrl: fullUrl)) simpleDelete(fullUrl, onFailure: onFailure, onSuccess: onSuccess, queryParams: queryParams, headers: headers);
if (statusCode < 200 || statusCode >= 400 || json == null) {
onFailure!('Error While Fetching data', statusCode);
@@ -847,13 +709,11 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
}
- Future handleUnauthorized(int statusCode,
- {required String forUrl}) async {
+ Future handleUnauthorized(int statusCode, {required String forUrl}) async {
if (forUrl.startsWith(EXA_CART_API_BASE_URL) && statusCode == 401) {
final token = await generatePackagesToken();
packagesAuthHeader['Authorization'] = 'Bearer $token';
@@ -866,10 +726,8 @@ class BaseAppClient {
await sharedPref.remove(LOGIN_TOKEN_ID);
await sharedPref.remove(PHARMACY_CUSTOMER_ID);
await authenticatedUserObject.getUser();
- Provider.of(AppGlobal.context, listen: false).isLogin =
- false;
- var model =
- Provider.of(AppGlobal.context, listen: false);
+ Provider.of(AppGlobal.context, listen: false).isLogin = false;
+ var model = Provider.of(AppGlobal.context, listen: false);
_vitalSignService.weightKg = "";
_vitalSignService.heightCm = "";
model.setState(0, 0, false, null);
@@ -884,8 +742,7 @@ class BaseAppClient {
static defaultHttpParameters() async {
String token = await sharedPref.getString(TOKEN);
- var languageID =
- await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
+ var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
var user = await sharedPref.getObject(USER_PROFILE);
var params = {};
if (user != null) {
@@ -905,11 +762,7 @@ class BaseAppClient {
}
pharmacyPost(String endPoint,
- {Map? body,
- Function(dynamic response, int statusCode)? onSuccess,
- Function(String error, int statusCode)? onFailure,
- bool isAllowAny = false,
- bool isExternal = false}) async {
+ {Map? body, Function(dynamic response, int statusCode)? onSuccess, Function(String error, int statusCode)? onFailure, bool isAllowAny = false, bool isExternal = false}) async {
var token = await sharedPref.getString(PHARMACY_AUTORZIE_TOKEN);
var user = await sharedPref.getObject(USER_PROFILE);
String url;
@@ -921,14 +774,13 @@ class BaseAppClient {
try {
if (isExternal) {
String token = await sharedPref.getString(TOKEN);
- var languageID =
- await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
+ var languageID = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
var user = await sharedPref.getObject(USER_PROFILE);
if (body!.containsKey('SetupID')) {
body['SetupID'] = body.containsKey('SetupID')
? body['SetupID'] != null
- ? body['SetupID']
- : SETUP_ID
+ ? body['SetupID']
+ : SETUP_ID
: SETUP_ID;
}
@@ -940,15 +792,15 @@ class BaseAppClient {
body['generalid'] = GENERAL_ID;
body['PatientOutSA'] = body.containsKey('PatientOutSA')
? body['PatientOutSA'] != null
- ? body['PatientOutSA']
- : user['OutSA']
+ ? body['PatientOutSA']
+ : user['OutSA']
: user['OutSA'];
if (body.containsKey('isDentalAllowedBackend')) {
body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
? body['isDentalAllowedBackend'] != null
- ? body['isDentalAllowedBackend']
- : IS_DENTAL_ALLOWED_BACKEND
+ ? body['isDentalAllowedBackend']
+ : IS_DENTAL_ALLOWED_BACKEND
: IS_DENTAL_ALLOWED_BACKEND;
}
@@ -957,24 +809,22 @@ class BaseAppClient {
if (!body.containsKey('IsPublicRequest')) {
body['PatientType'] = body.containsKey('PatientType')
? body['PatientType'] != null
- ? body['PatientType']
- : user['PatientType'] != null
- ? user['PatientType']
- : user['PatientType']
+ ? body['PatientType']
+ : user['PatientType'] != null
+ ? user['PatientType']
+ : user['PatientType']
: user['PatientType'];
body['PatientTypeID'] = body.containsKey('PatientTypeID')
? body['PatientTypeID'] != null
- ? body['PatientTypeID']
- : user['PatientType'] != null
- ? user['PatientType']
- : user['PatientType']
+ ? body['PatientTypeID']
+ : user['PatientType'] != null
+ ? user['PatientType']
+ : user['PatientType']
: user['PatientType'];
if (user != null) {
body['TokenID'] = token;
- body['PatientID'] = body['PatientID'] != null
- ? body['PatientID']
- : user['PatientID'];
+ body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : user['PatientID'];
body['PatientOutSA'] = user['OutSA'];
// body['SessionID'] = SESSION_ID; //getSessionId(token);
}
@@ -986,14 +836,11 @@ class BaseAppClient {
var ss = json.encode(body);
if (await Utils.checkConnection()) {
- final response = await http
- .post(Uri.parse(url.trim()), body: json.encode(body), headers: {
+ final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': token ?? '',
- 'Mobilenumber': user != null
- ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString())
- : "",
+ 'Mobilenumber': user != null ? Utils.getPhoneNumberWithoutZero(user['MobileNumber'].toString()) : "",
'Statictoken': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
'Username': user != null ? user['PatientID'].toString() : "",
});
@@ -1001,15 +848,8 @@ class BaseAppClient {
// print("statusCode :$statusCode");
if (statusCode < 200 || statusCode >= 400 || json == null) {
var parsed = json.decode(utf8.decode(response.bodyBytes));
- onFailure!(
- parsed['error']['ErrorEndUserMsgN'] ??
- 'Error While Fetching data',
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['error']['ErrorEndUserMsgN'] ??
- 'Error While Fetching data',
- statusCode);
+ onFailure!(parsed['error']['ErrorEndUserMsgN'] ?? 'Error While Fetching data', statusCode);
+ logApiEndpointError(endPoint, parsed['error']['ErrorEndUserMsgN'] ?? 'Error While Fetching data', statusCode);
} else {
// var parsed = json.decode(response.body.toString());
var parsed = json.decode(utf8.decode(response.bodyBytes));
@@ -1017,8 +857,7 @@ class BaseAppClient {
onSuccess!(parsed, statusCode);
} else {
if (parsed['ErrorType'] == 4) {
- navigateToAppUpdate(
- AppGlobal.context, parsed['ErrorEndUserMessage']);
+ navigateToAppUpdate(AppGlobal.context, parsed['ErrorEndUserMessage']);
}
if (isAllowAny) {
onSuccess!(parsed, statusCode);
@@ -1033,47 +872,25 @@ class BaseAppClient {
if (parsed != null) {
onSuccess!(parsed, statusCode);
} else {
- onFailure!(
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ onFailure!(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
logout();
}
}
- } else if (parsed['MessageStatus'] == 1 ||
- parsed['SMSLoginRequired'] == true) {
+ } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
onSuccess!(parsed, statusCode);
- } else if (parsed['MessageStatus'] == 2 &&
- parsed['IsAuthenticated']) {
- if (parsed['message'] == null &&
- parsed['ErrorEndUserMessage'] == null) {
+ } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
+ if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
if (parsed['ErrorSearchMsg'] == null) {
- onFailure!("Server Error found with no available message",
- statusCode);
- logApiEndpointError(
- endPoint,
- "Server Error found with no available message",
- statusCode);
+ onFailure!("Server Error found with no available message", statusCode);
+ logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
} else {
onFailure!(parsed['ErrorSearchMsg'], statusCode);
- logApiEndpointError(
- endPoint, parsed['ErrorSearchMsg'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode);
}
} else {
- onFailure!(
- parsed['message'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['message'] ??
- parsed['ErrorEndUserMessage'] ??
- parsed['ErrorMessage'],
- statusCode);
+ onFailure!(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
} else if (!parsed['IsAuthenticated']) {
await logout();
@@ -1084,18 +901,11 @@ class BaseAppClient {
onSuccess!(parsed, statusCode);
} else {
if (parsed['message'] != null) {
- onFailure!(
- parsed['message'] ?? parsed['message'], statusCode);
- logApiEndpointError(endPoint,
- parsed['message'] ?? parsed['message'], statusCode);
+ onFailure!(parsed['message'] ?? parsed['message'], statusCode);
+ logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
} else {
- onFailure!(
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
- logApiEndpointError(
- endPoint,
- parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
- statusCode);
+ onFailure!(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
+ logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
}
}
@@ -1103,8 +913,7 @@ class BaseAppClient {
}
} else {
onFailure!('Please Check The Internet Connection', -1);
- _analytics.errorTracking
- .log("internet_connectivity", error: "no internet available");
+ _analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
} catch (e) {
print(e);
@@ -1116,15 +925,11 @@ class BaseAppClient {
Future generatePackagesToken() async {
var url = EXA_CART_API_BASE_URL + PACKAGES_TOKEN;
var body = {
- "api_client": {
- "client_id": "a4ab6be4-424f-4836-b032-46caed88e184",
- "client_secret": "3c1a3e07-4a40-4510-9fb0-ee5f0a72752c"
- }
+ "api_client": {"client_id": "a4ab6be4-424f-4836-b032-46caed88e184", "client_secret": "3c1a3e07-4a40-4510-9fb0-ee5f0a72752c"}
};
String? token;
final completer = Completer();
- simplePost(url, body: body, headers: {},
- onSuccess: (dynamic stringResponse, int statusCode) {
+ simplePost(url, body: body, headers: {}, onSuccess: (dynamic stringResponse, int statusCode) {
if (statusCode == 200) {
var jsonResponse = json.decode(stringResponse);
token = jsonResponse['auth_token'];
diff --git a/lib/core/service/medical/labs_service.dart b/lib/core/service/medical/labs_service.dart
index 77ea728e..8ca246a0 100644
--- a/lib/core/service/medical/labs_service.dart
+++ b/lib/core/service/medical/labs_service.dart
@@ -124,12 +124,15 @@ class LabsService extends BaseService {
return Future.value(localRes);
}
- Future updateWorkplaceName(String workplaceName, String workplaceNameAR, int requestNumber, String setupID, int projectID) async {
+ Future updateWorkplaceName(String workplaceName, String workplaceNameAR, String occupation, String occupationAR, int requestNumber, String setupID, int projectID) async {
+ // Future updateWorkplaceName(String workplaceName, String workplaceNameAR, int requestNumber, String setupID, int projectID) async {
hasError = false;
Map body = Map();
body['Placeofwork'] = workplaceName;
- body['Placeofworkar'] = workplaceNameAR;
+ body['PlaceofworkAr'] = workplaceNameAR;
+ body['Occupation'] = occupation;
+ body['OccupationAr'] = occupationAR;
body['Req_ID'] = requestNumber;
body['TargetSetupID'] = setupID;
body['ProjectID'] = projectID;
diff --git a/lib/core/service/medical/medical_service.dart b/lib/core/service/medical/medical_service.dart
index a77729c9..445f5ab6 100644
--- a/lib/core/service/medical/medical_service.dart
+++ b/lib/core/service/medical/medical_service.dart
@@ -72,11 +72,15 @@ class MedicalService extends BaseService {
dynamic localRes;
await baseAppClient.post(GET_DOCTOR_FREE_SLOTS, onSuccess: (response, statusCode) async {
localRes = response;
+ freeSlots.clear();
+ localRes['FreeTimeSlots'].forEach((item) => freeSlots.add(item));
}, onFailure: (String error, int statusCode) {
- throw error;
+ hasError = true;
+ super.error = error;
+ // throw error;
}, body: request);
- freeSlots.clear();
- localRes['FreeTimeSlots'].forEach((item) => freeSlots.add(item));
+ // freeSlots.clear();
+ // localRes['FreeTimeSlots'].forEach((item) => freeSlots.add(item));
// localRes['List_DoctorWorkingHoursTable'].forEach((item) =>
// {doctorScheduleResponse.add(DoctorScheduleResponse.fromJson(item))});
}
diff --git a/lib/core/viewModels/project_view_model.dart b/lib/core/viewModels/project_view_model.dart
index 7216da7b..238ee0f5 100644
--- a/lib/core/viewModels/project_view_model.dart
+++ b/lib/core/viewModels/project_view_model.dart
@@ -18,7 +18,10 @@ import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_datetime_picker_plus/flutter_datetime_picker_plus.dart';
+import '../../models/Appointments/DoctorListResponse.dart';
+
bool isAppArabic = false;
+
class ProjectViewModel extends BaseViewModel {
GAnalytics get analytics => locator();
@@ -38,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;
@@ -45,15 +49,36 @@ class ProjectViewModel extends BaseViewModel {
GetAdmissionInfoResponseModel getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel();
GetAdmissionRequestInfoResponseModel getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel();
+ bool isIndoorNavigationEnabled = true;
+
+ int waitingAppointmentProjectID = 0;
+ DoctorList? waitingAppointmentDoctor;
+ String waitingAppointmentNFCCode = "";
+
+ setWaitingAppointmentDoctor(DoctorList waitingAppointmentDoctor) {
+ this.waitingAppointmentDoctor = waitingAppointmentDoctor;
+ notifyListeners();
+ }
+
+ setWaitingAppointmentNFCCode(String waitingAppointmentNFCCode) {
+ this.waitingAppointmentNFCCode = waitingAppointmentNFCCode;
+ notifyListeners();
+ }
+
+ setWaitingAppointmentProjectID(int projectID) {
+ this.waitingAppointmentProjectID = projectID;
+ notifyListeners();
+ }
+
void setIsAllAppointmentsLoaded(bool value) {
_isAllAppointmentsLoaded = value;
notifyListeners();
}
-
RegisterInfoResponse _registerInfo = RegisterInfoResponse();
RegisterInfoResponse get registerInfo => _registerInfo;
+
dynamic get searchValue => searchvalue;
Locale get appLocal => _appLocale;
@@ -70,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;
@@ -137,6 +164,11 @@ class ProjectViewModel extends BaseViewModel {
notifyListeners();
}
+ setIsIndoorNavigationEnabled(bool isEnabled) {
+ this.isIndoorNavigationEnabled = isEnabled;
+ notifyListeners();
+ }
+
setPatientHasAdmissionRequest(bool hasAdmissionRequest) {
this.patientHasAdmissionRequest = hasAdmissionRequest;
notifyListeners();
@@ -200,8 +232,6 @@ class ProjectViewModel extends BaseViewModel {
notifyListeners();
}
-
-
bool havePrivilege(int id) {
bool isHavePrivilege = false;
try {
@@ -222,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/Appointments/DoctorListResponse.dart b/lib/models/Appointments/DoctorListResponse.dart
index 205909c9..93cb81e5 100644
--- a/lib/models/Appointments/DoctorListResponse.dart
+++ b/lib/models/Appointments/DoctorListResponse.dart
@@ -44,6 +44,8 @@ class DoctorList {
List? specialityN;
dynamic workingHours;
dynamic decimalDoctorRate;
+ String? projectBottomName;
+ String? projectTopName;
DoctorList(
{this.clinicID,
@@ -90,7 +92,9 @@ class DoctorList {
this.speciality,
this.specialityN,
this.workingHours,
- this.decimalDoctorRate});
+ this.decimalDoctorRate,
+ this.projectBottomName,
+ this.projectTopName});
DoctorList.fromJson(Map json) {
clinicID = json['ClinicID'];
@@ -138,6 +142,8 @@ class DoctorList {
if (json.containsKey('SpecialityN') && json['SpecialityN'] != null) specialityN = json['SpecialityN'].cast();
workingHours = json['WorkingHours'];
decimalDoctorRate = json['DecimalDoctorRate'];
+ projectBottomName = json['ProjectNameBottom'];
+ projectTopName = json['ProjectNameTop'];
}
Map toJson() {
@@ -188,6 +194,10 @@ class DoctorList {
data['DecimalDoctorRate'] = this.decimalDoctorRate;
return data;
}
+
+ String getProjectCompleteName(){
+ return "${this.projectTopName} ${this.projectBottomName}";
+ }
}
class PatientDoctorAppointmentList {
diff --git a/lib/models/Appointments/PatientPackageComponent b/lib/models/Appointments/PatientPackageComponent
new file mode 100644
index 00000000..e69de29b
diff --git a/lib/models/Appointments/PatientPackageComponent.dart b/lib/models/Appointments/PatientPackageComponent.dart
new file mode 100644
index 00000000..26ce9229
--- /dev/null
+++ b/lib/models/Appointments/PatientPackageComponent.dart
@@ -0,0 +1,59 @@
+class PatientPackageComponent {
+ List? patientPackageComponents;
+
+ PatientPackageComponent({this.patientPackageComponents});
+
+ PatientPackageComponent.fromJson(Map json) {
+ if (json['PatientPackageComponents'] != null) {
+ patientPackageComponents = [];
+ json['PatientPackageComponents'].forEach((v) {
+ patientPackageComponents!.add(new PatientPackageComponents.fromJson(v));
+ });
+ }
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ if (this.patientPackageComponents != null) {
+ data['PatientPackageComponents'] = this.patientPackageComponents!.map((v) => v.toJson()).toList();
+ }
+ return data;
+ }
+}
+
+class PatientPackageComponents {
+ int? invoiceNo;
+ int? lineItemNo;
+ String? procedureID;
+ String? procedureName;
+ int? projectID;
+ int? sequence;
+ String? setupID;
+ num? invoiceNo_VP;
+
+ PatientPackageComponents({this.invoiceNo, this.lineItemNo, this.procedureID, this.procedureName, this.projectID, this.sequence, this.setupID, this.invoiceNo_VP});
+
+ PatientPackageComponents.fromJson(Map json) {
+ invoiceNo = json['InvoiceNo'];
+ lineItemNo = json['LineItemNo'];
+ procedureID = json['ProcedureID'];
+ procedureName = json['ProcedureName'];
+ projectID = json['ProjectID'];
+ sequence = json['Sequence'];
+ setupID = json['SetupID'];
+ invoiceNo_VP = json['InvoiceNo_VP'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['InvoiceNo'] = this.invoiceNo;
+ data['LineItemNo'] = this.lineItemNo;
+ data['ProcedureID'] = this.procedureID;
+ data['ProcedureName'] = this.procedureName;
+ data['ProjectID'] = this.projectID;
+ data['Sequence'] = this.sequence;
+ data['SetupID'] = this.setupID;
+ data['InvoiceNo_VP'] = this.invoiceNo_VP;
+ return data;
+ }
+}
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/ERAppointmentFeesResponse.dart b/lib/models/LiveCare/ERAppointmentFeesResponse.dart
index b8a88aba..3deaa05b 100644
--- a/lib/models/LiveCare/ERAppointmentFeesResponse.dart
+++ b/lib/models/LiveCare/ERAppointmentFeesResponse.dart
@@ -24,6 +24,8 @@ class GetERAppointmentFeesList {
String? companyName;
bool? isInsured;
bool? isShowInsuranceUpdateModule;
+ bool? isCash;
+ bool? isEligible;
String? tax;
String? total;
String? currency;
@@ -41,6 +43,8 @@ class GetERAppointmentFeesList {
amount = json['Amount'];
companyName = json['CompanyName'];
isInsured = json['IsInsured'];
+ isCash = json['IsCash'];
+ isEligible = json['IsEligible'];
isShowInsuranceUpdateModule = json['IsShowInsuranceUpdateModule'];
tax = json['Tax'];
total = json['Total'];
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/models/SmartWatch/WeeklyHeartRateResModel.dart b/lib/models/SmartWatch/WeeklyHeartRateResModel.dart
index 1c21c22d..26341ee0 100644
--- a/lib/models/SmartWatch/WeeklyHeartRateResModel.dart
+++ b/lib/models/SmartWatch/WeeklyHeartRateResModel.dart
@@ -8,7 +8,7 @@ class WeeklyHeartRateResModel {
{this.valueAvg, this.machineDate, this.medCategoryID, this.patientID});
WeeklyHeartRateResModel.fromJson(Map json) {
- num value = json['ValueAvg'];
+ num value = json['ValueAvg'] != null ? json['ValueAvg'] : 0.0;
valueAvg = json['ValueAvg'] != null ? value.toInt() : 0;
machineDate = json['MachineDate'];
medCategoryID = json['MedCategoryID'];
diff --git a/lib/models/SmartWatch/YearlyHeartRateResModel.dart b/lib/models/SmartWatch/YearlyHeartRateResModel.dart
index 331d5adb..3d81ff2c 100644
--- a/lib/models/SmartWatch/YearlyHeartRateResModel.dart
+++ b/lib/models/SmartWatch/YearlyHeartRateResModel.dart
@@ -15,7 +15,7 @@ class YearlyHeartRateResModel {
this.year});
YearlyHeartRateResModel.fromJson(Map json) {
- num value = json['ValueAvg'];
+ num value = json['ValueAvg'] != null ? json['ValueAvg'] : 0.0;
valueAvg = json['ValueAvg'] != null ? value.toInt() : 0;
medCategoryID = json['MedCategoryID'];
month = json['Month'];
diff --git a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/Dialog/confirm_dialog.dart b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/Dialog/confirm_dialog.dart
index 536af3cd..94379af8 100644
--- a/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/Dialog/confirm_dialog.dart
+++ b/lib/pages/AlHabibMedicalService/ComprehensiveMedicalCheckup/Dialog/confirm_dialog.dart
@@ -100,7 +100,7 @@ class ConfirmDialog extends StatelessWidget {
onClick();
Navigator.pop(context);
},
- textColor: Theme.of(context).backgroundColor),
+ textColor: CustomColors.white),
),
],
),
diff --git a/lib/pages/AlHabibMedicalService/E-Referral/e_referral_confirm_sms_dialog.dart b/lib/pages/AlHabibMedicalService/E-Referral/e_referral_confirm_sms_dialog.dart
index b9eefe08..3b5d585e 100644
--- a/lib/pages/AlHabibMedicalService/E-Referral/e_referral_confirm_sms_dialog.dart
+++ b/lib/pages/AlHabibMedicalService/E-Referral/e_referral_confirm_sms_dialog.dart
@@ -6,6 +6,7 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart';
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/EReferral/check_activation_code_for_e_referral_request_model.dart';
import 'package:diplomaticquarterapp/core/viewModels/all_habib_medical_services/e_referral_view_model.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
+import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart';
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
@@ -367,11 +368,11 @@ class _EReferralConfirmSMSDialogState extends State {
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
- borderSide: BorderSide(color: Theme.of(context).errorColor),
+ borderSide: BorderSide(color: CustomColors.accentColor),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
- borderSide: BorderSide(color: Theme.of(context).errorColor),
+ borderSide: BorderSide(color: CustomColors.accentColor),
),
);
}
diff --git a/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart b/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart
index 89091886..05b0d753 100644
--- a/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart
+++ b/lib/pages/AlHabibMedicalService/HomeHealthCare/home_health_care_index_page.dart
@@ -1,3 +1,4 @@
+import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart';
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
@@ -36,9 +37,7 @@ class HomeHealthCareIndexPage extends StatelessWidget {
SizedBox(
height: 22,
),
- Center(
- child: Image.asset(
- 'assets/images/AlHabibMedicalService/Wifi-AR.png')),
+ Center(child: Image.asset('assets/images/AlHabibMedicalService/Wifi-AR.png')),
SizedBox(
height: 77,
),
@@ -53,13 +52,13 @@ class HomeHealthCareIndexPage extends StatelessWidget {
width: MediaQuery.of(context).size.width * 0.9,
child: SecondaryButton(
onTap: () => Navigator.push(
- context,
- FadePage(
- page: HomeHealthCarePage(),
- ),
- ),
+ context,
+ FadePage(
+ page: HomeHealthCarePage(),
+ ),
+ ),
label: TranslationBase.of(context).loginRegister,
- textColor: Theme.of(context).backgroundColor),
+ textColor: CustomColors.white),
),
],
),
diff --git a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page2.dart b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page2.dart
index f23d175d..420f08f1 100644
--- a/lib/pages/AlHabibMedicalService/all_habib_medical_service_page2.dart
+++ b/lib/pages/AlHabibMedicalService/all_habib_medical_service_page2.dart
@@ -37,6 +37,7 @@ class _AllHabibMedicalSevicePage2State extends State
AuthProvider authProvider = new AuthProvider();
WeatherService _weatherService = WeatherService();
double weatherNum = 30;
+ late ProjectViewModel projectViewModel;
@override
void initState() {
@@ -235,7 +236,7 @@ class _AllHabibMedicalSevicePage2State extends State
itemCount: hmgServices.length,
padding: EdgeInsets.zero,
itemBuilder: (BuildContext context, int index) {
- return ServicesView(hmgServices[index], index, false);
+ return ServicesView(hmgServices[index], index, false, projectViewModel);
},
),
),
diff --git a/lib/pages/AlHabibMedicalService/h2o/h2o_index_page.dart b/lib/pages/AlHabibMedicalService/h2o/h2o_index_page.dart
index df8d3cc8..a28c0d3e 100644
--- a/lib/pages/AlHabibMedicalService/h2o/h2o_index_page.dart
+++ b/lib/pages/AlHabibMedicalService/h2o/h2o_index_page.dart
@@ -1,4 +1,5 @@
import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/h2o/h2o_page.dart';
+import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart';
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
@@ -57,9 +58,7 @@ class H2OPageIndexPage extends StatelessWidget {
onTap: () =>
Navigator.push(context, FadePage(page: H2OPage())),
label: "Water Tracker",
- textColor: Theme
- .of(context)
- .backgroundColor),
+ textColor: CustomColors.white),
),
],
),
diff --git a/lib/pages/AlHabibMedicalService/my_web_view.dart b/lib/pages/AlHabibMedicalService/my_web_view.dart
index 1779b127..bd824cd4 100644
--- a/lib/pages/AlHabibMedicalService/my_web_view.dart
+++ b/lib/pages/AlHabibMedicalService/my_web_view.dart
@@ -4,31 +4,57 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
-class MyWebView extends StatelessWidget {
+class MyWebView extends StatefulWidget {
final String title;
final String selectedUrl;
- final Completer _controller = Completer();
-
MyWebView({
required this.title,
required this.selectedUrl,
});
@override
- Widget build(BuildContext context) {
- return AppScaffold(
- isShowAppBar: true,
- appBarTitle: title,
- isShowDecPage: false,
- showNewAppBar: true,
- showNewAppBarTitle: true,
- body: WebView(
- initialUrl: selectedUrl,
- javascriptMode: JavascriptMode.unrestricted,
- onWebViewCreated: (WebViewController webViewController) {
- _controller.complete(webViewController);
+ State createState() => _MyWebViewState();
+}
+
+class _MyWebViewState extends State {
+ // final Completer _controller = Completer();
+ late final WebViewController _controller;
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = WebViewController()
+ ..setJavaScriptMode(JavaScriptMode.unrestricted)
+ ..setNavigationDelegate(
+ NavigationDelegate(
+ onProgress: (int progress) {
+ // Update loading bar.
},
- ));
+ onPageStarted: (String url) {},
+ onPageFinished: (String url) {},
+ onHttpError: (HttpResponseError error) {},
+ onWebResourceError: (WebResourceError error) {},
+ onNavigationRequest: (NavigationRequest request) {
+ if (request.url.startsWith('https://www.youtube.com/')) {
+ return NavigationDecision.prevent;
+ }
+ return NavigationDecision.navigate;
+ },
+ ),
+ )
+ ..loadRequest(Uri.parse(widget.selectedUrl));
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return AppScaffold(isShowAppBar: true, appBarTitle: widget.title, isShowDecPage: false, showNewAppBar: true, showNewAppBarTitle: true, body: WebViewWidget(controller: _controller)
+ // WebView(
+ // initialUrl: widget.selectedUrl,
+ // javascriptMode: JavascriptMode.unrestricted,
+ // onWebViewCreated: (WebViewController webViewController) {
+ // _controller.complete(webViewController);
+ // },
+ );
}
}
diff --git a/lib/pages/Blood/blood_donation_book_appointment.dart b/lib/pages/Blood/blood_donation_book_appointment.dart
index a0b9f6f7..6485b2d8 100644
--- a/lib/pages/Blood/blood_donation_book_appointment.dart
+++ b/lib/pages/Blood/blood_donation_book_appointment.dart
@@ -445,7 +445,7 @@ class _BloodDonationBookAppointmentState extends State {
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
- borderSide: BorderSide(color: Theme.of(context).errorColor),
+ borderSide: BorderSide(color: CustomColors.accentColor),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
- borderSide: BorderSide(color: Theme.of(context).errorColor),
+ borderSide: BorderSide(color: CustomColors.accentColor),
),
);
}
diff --git a/lib/pages/Blood/new_text_Field.dart b/lib/pages/Blood/new_text_Field.dart
index e6431f1f..61a97eb8 100644
--- a/lib/pages/Blood/new_text_Field.dart
+++ b/lib/pages/Blood/new_text_Field.dart
@@ -1,3 +1,4 @@
+import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -183,7 +184,8 @@ class _NewTextFieldsState extends State {
validator: widget.validator,
onSaved: widget.onSaved,
- style: Theme.of(context).textTheme.bodyText2!.copyWith(fontSize: widget.fontSize, fontWeight: widget.fontWeight),
+ // style: Theme.of(context).textTheme.bodyText2!.copyWith(fontSize: widget.fontSize, fontWeight: widget.fontWeight),
+ style: TextStyle(color: Colors.black, letterSpacing: 0.6, fontSize: widget.fontSize, fontWeight: widget.fontWeight),
inputFormatters: widget.keyboardType == TextInputType.phone
? [
FilteringTextInputFormatter.digitsOnly,
@@ -193,8 +195,8 @@ class _NewTextFieldsState extends State {
decoration: InputDecoration(
labelText: widget.hintText,
labelStyle: TextStyle(color: Colors.black),
- errorBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).errorColor.withOpacity(0.5), width: 1.0), borderRadius: BorderRadius.circular(12.0)),
- focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).errorColor.withOpacity(0.5), width: 1.0), borderRadius: BorderRadius.circular(8.0)),
+ errorBorder: OutlineInputBorder(borderSide: BorderSide(color: CustomColors.accentColor.withOpacity(0.5), width: 1.0), borderRadius: BorderRadius.circular(12.0)),
+ focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: CustomColors.accentColor.withOpacity(0.5), width: 1.0), borderRadius: BorderRadius.circular(8.0)),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.white, width: 1.0), borderRadius: BorderRadius.circular(12)),
disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.white, width: 1.0), borderRadius: BorderRadius.circular(12)),
enabledBorder: OutlineInputBorder(
diff --git a/lib/pages/BookAppointment/BookConfirm.dart b/lib/pages/BookAppointment/BookConfirm.dart
index b2ccf085..65dfa1b1 100644
--- a/lib/pages/BookAppointment/BookConfirm.dart
+++ b/lib/pages/BookAppointment/BookConfirm.dart
@@ -1,26 +1,38 @@
import 'dart:convert';
+import 'dart:developer';
+import 'dart:io';
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/Appointments/DoctorListResponse.dart';
import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart';
import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart';
+import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
+import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart';
import 'package:diplomaticquarterapp/models/header_model.dart';
+import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart';
+import 'package:diplomaticquarterapp/pages/ToDoList/widgets/paymentDialog.dart';
import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/routes.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/custom_text_button.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart';
+import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart';
import 'package:diplomaticquarterapp/widgets/new_design/doctor_header.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
@@ -28,6 +40,7 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
+import '../../models/Appointments/PatientPackageComponent.dart';
import 'book_reminder_page.dart';
import 'components/DocAvailableAppointments.dart';
@@ -41,7 +54,10 @@ class BookConfirm extends StatefulWidget {
bool isLiveCareAppointment;
int initialSlotDuration;
- BookConfirm({required this.doctor, required this.selectedDate, required this.isLiveCareAppointment, required this.selectedTime, required this.initialSlotDuration});
+ bool isWalkinAppointment = false;
+
+ BookConfirm(
+ {required this.doctor, required this.selectedDate, required this.isLiveCareAppointment, required this.selectedTime, required this.initialSlotDuration, required this.isWalkinAppointment});
late DoctorsListService service;
late PatientShareResponse patientShareResponse;
@@ -62,6 +78,13 @@ class _BookConfirmState extends State {
bool isEligible = false;
bool isCash = false;
+ String? selectedPaymentMethod = "";
+ String? selectedInstallments = "";
+ String? tamaraPaymentStatus;
+ String? tamaraOrderID;
+ String? transID;
+ late MyInAppBrowser browser;
+
@override
void initState() {
// widget.authUser = new AuthenticatedUser();
@@ -212,13 +235,19 @@ class _BookConfirmState extends State {
elevation: 0,
onPressed: () async {
bool isLiveCareSchedule = await this.sharedPref.getBool(IS_LIVECARE_APPOINTMENT) ?? false;
- if (isLiveCareSchedule) {
- insertLiveCareScheduledAppointment(context, widget.doctor);
+
+ if (widget.isWalkinAppointment) {
+ getWalkinAppointmentPatientShare();
} else {
- insertAppointment(context, widget.doctor, widget.initialSlotDuration);
+ if (isLiveCareSchedule) {
+ insertLiveCareScheduledAppointment(context, widget.doctor);
+ } else {
+ checkPatientHasDermaPackage(widget.doctor, projectViewModel.user.patientID!);
+ }
}
},
- child: Text(TranslationBase.of(context).bookAppo, style: TextStyle(fontSize: 16.0, letterSpacing: -0.48, color: Colors.white)),
+ child: Text(widget.isWalkinAppointment ? TranslationBase.of(context).addToWaitingList : TranslationBase.of(context).bookAppo,
+ style: TextStyle(fontSize: 16.0, letterSpacing: -0.48, color: Colors.white)),
),
),
),
@@ -226,6 +255,404 @@ class _BookConfirmState extends State {
);
}
+ getWalkinAppointmentPatientShare() {
+ String errorMsg = "";
+ AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList();
+ GifLoaderDialogUtils.showMyDialog(context);
+ appo.doctorTitle = widget.doctor.doctorTitle;
+ appo.doctorNameObj = widget.doctor.name;
+ appo.appointmentDate = DateUtil.convertDateToString(DateTime.now());
+ appo.projectName = widget.doctor.projectName;
+
+ widget.service
+ .getPatientShareForWalkInAppointment(
+ widget.doctor.clinicID!,
+ widget.doctor.projectID!,
+ widget.doctor.doctorID!,
+ )
+ .then((res) {
+ widget.patientShareResponse = new PatientShareResponse.fromJson(res["OnlineCheckInAppointmentsWalkInModel"]);
+ GifLoaderDialogUtils.hideDialog(context);
+
+ isInsured = res["IsInsured"];
+ isEligible = res["IsEligible"];
+ isCash = res["IsCash"];
+
+ if (isCash) {
+ if (widget.patientShareResponse.patientShareWithTax != 0 || widget.patientShareResponse.patientShareWithTax != 0.0) {
+ openPaymentDialog(appo, widget.patientShareResponse!);
+ } else {
+ insertWalkInAppointment(context, widget.doctor, widget.initialSlotDuration, null);
+ }
+ } else {
+ if (isInsured && isEligible) {
+ if (widget.patientShareResponse.patientShareWithTax != 0 || widget.patientShareResponse.patientShareWithTax != 0.0) {
+ openPaymentDialog(appo, widget.patientShareResponse!);
+ } else {
+ insertWalkInAppointment(context, widget.doctor, widget.initialSlotDuration, null);
+ }
+ } else {
+ if (isInsured && !isEligible) {
+ errorMsg = TranslationBase.of(context).invalidEligibility;
+ } else {
+ errorMsg = TranslationBase.of(context).invalidInsurance;
+ }
+ ConfirmDialog dialog = new ConfirmDialog(
+ isDissmissable: false,
+ context: context,
+ confirmMessage: errorMsg,
+ okText: TranslationBase.of(context).updateInsuranceText,
+ cancelText: TranslationBase.of(context).continueCash,
+ okFunction: () => {openUpdateInsurance()},
+ cancelFunction: () => {continueAsCashForWalkIn(widget.doctor.projectID!)});
+ dialog.showAlertDialog(context);
+ }
+ }
+
+ // widget.patientShareResponse = new PatientShareResponse.fromJson(res["OnlineCheckInAppointmentsWalkInModel"]);
+ // GifLoaderDialogUtils.hideDialog(context);
+ // if (widget.patientShareResponse.patientShareWithTax != 0 || widget.patientShareResponse.patientShareWithTax != 0.0) {
+ // openPaymentDialog(appo, widget.patientShareResponse!);
+ // } else {
+ // insertWalkInAppointment(context, widget.doctor, widget.initialSlotDuration, null);
+ // }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ openPaymentDialog(AppoitmentAllHistoryResultList appo, PatientShareResponse patientShareResponse) {
+ showGeneralDialog(
+ barrierColor: Colors.black.withOpacity(0.5),
+ transitionBuilder: (context, a1, a2, widget) {
+ final curvedValue = Curves.easeInOutBack.transform(a1.value) - 1.0;
+ return Transform(
+ transform: Matrix4.translationValues(0.0, curvedValue * 200, 0.0),
+ child: Opacity(
+ opacity: a1.value,
+ child: PaymentDialog(
+ appo: appo,
+ patientShareResponse: patientShareResponse,
+ isCashPatient: isCash,
+ onPaymentMethodSelected: () {},
+ ),
+ ),
+ );
+ },
+ transitionDuration: Duration(milliseconds: 500),
+ barrierDismissible: false,
+ barrierLabel: '',
+ context: context,
+ pageBuilder: (context, animation1, animation2) => SizedBox()).then((value) {
+ print(value);
+ if (value != null) {
+ navigateToPaymentMethod(context, value as PatientShareResponse);
+ // projectViewModel.analytics.todoList.to_do_list_confirm_payment_details(appo);
+ } else {
+ // projectViewModel.analytics.todoList.to_do_list_cancel_payment_details(appo);
+ }
+ });
+ }
+
+ Future navigateToPaymentMethod(context, PatientShareResponse patientShareResponse) async {
+ AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList();
+ appo.projectID = widget.doctor.projectID;
+ appo.clinicID = widget.doctor.clinicID;
+ appo.clinicName = widget.doctor.clinicName;
+ appo.projectName = widget.doctor.projectName;
+ appo.appointmentNo = DateTime.now().millisecondsSinceEpoch;
+ appo.isLiveCareAppointment = false;
+ appo.doctorID = widget.doctor.doctorID;
+ appo.appointmentDate = DateUtil.convertDateToString(DateTime.now()); //widget.patientShareResponse.appointmentDate;
+ appo.serviceID = widget.patientShareResponse.serviceID;
+
+ Navigator.push(
+ context,
+ FadePage(
+ page: PaymentMethod(
+ onSelectedMethod: (String metohd, [String? selectedInstallmentPlan]) {
+ setState(() {});
+ },
+ patientShare: widget.patientShareResponse.patientShareWithTax)))
+ .then((value) {
+ selectedPaymentMethod = value[0];
+ if (value != null) {
+ if (selectedPaymentMethod == "ApplePay") {
+ if (projectViewModel.havePrivilege(103)) {
+ startApplePay(appo, patientShareResponse);
+ } else {
+ openPayment(value, projectViewModel.user, double.parse(patientShareResponse.patientShareWithTax.toString()), patientShareResponse, appo);
+ }
+ } else {
+ openPayment(value, projectViewModel.user, double.parse(patientShareResponse.patientShareWithTax.toString()), patientShareResponse, appo);
+ }
+ projectViewModel.analytics.appointment.payment_method(appointment_type: 'Walk-In', clinic: widget.doctor.clinicName, payment_method: value[0], payment_type: 'appointment');
+ }
+ });
+ }
+
+ void startApplePay(AppoitmentAllHistoryResultList appo, PatientShareResponse patientShareResponse) async {
+ transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo);
+ print("TransactionID: $transID");
+ GifLoaderDialogUtils.showMyDialog(context);
+
+ LiveCareService service = new LiveCareService();
+ ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest();
+
+ PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel;
+ await context.read().getProjectDetailsForPayfort(projectId: appo.projectID, serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum()).then((value) {
+ payfortProjectDetailsRespModel = value!;
+ });
+
+ applePayInsertRequest.clientRequestID = transID;
+ applePayInsertRequest.clinicID = appo.clinicID;
+ 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 = appo.doctorID;
+ applePayInsertRequest.projectID = appo.projectID.toString();
+ applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
+ applePayInsertRequest.channelID = 3;
+ applePayInsertRequest.patientID = projectViewModel.user.patientID;
+ applePayInsertRequest.patientTypeID = projectViewModel.user.patientType;
+ applePayInsertRequest.patientOutSA = projectViewModel.user.outSA;
+ applePayInsertRequest.appointmentDate = appo.appointmentDate;
+ applePayInsertRequest.appointmentNo = appo.appointmentNo;
+ applePayInsertRequest.orderDescription = "Appointment Payment";
+ applePayInsertRequest.liveServiceID = "0";
+ applePayInsertRequest.latitude = "0.0";
+ applePayInsertRequest.longitude = "0.0";
+ applePayInsertRequest.amount = patientShareResponse.patientShareWithTax.toString();
+ applePayInsertRequest.isSchedule = appo.isLiveCareAppointment! ? "1" : "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: "Walk-In appointment payment",
+ orderAmount: double.parse(patientShareResponse.patientShareWithTax.toString()),
+ 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);
+ checkPaymentStatus(appo);
+ },
+ projectId: appo.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);
+ });
+ }
+
+ openPayment(List paymentMethod, AuthenticatedUser authenticatedUser, num amount, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appo) async {
+ browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart, context: context);
+ selectedPaymentMethod = paymentMethod[0];
+ selectedInstallments = paymentMethod[1];
+ transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo);
+ browser.openPaymentBrowser(
+ amount,
+ "Walk-In appointment payment",
+ transID!,
+ appo.projectID.toString(),
+ authenticatedUser.emailAddress!,
+ paymentMethod[0]!,
+ authenticatedUser.patientType,
+ authenticatedUser.firstName!,
+ authenticatedUser.patientID,
+ authenticatedUser,
+ browser,
+ widget.patientShareResponse.isLiveCareAppointment!,
+ "2",
+ widget.patientShareResponse.isLiveCareAppointment! ? widget.patientShareResponse.clinicID.toString() : "",
+ context,
+ widget.patientShareResponse.appointmentDate,
+ widget.patientShareResponse.appointmentNo,
+ widget.patientShareResponse.clinicID,
+ widget.patientShareResponse.doctorID,
+ paymentMethod[1]);
+ // }
+ }
+
+ onBrowserLoadStart(String url) {
+ if (selectedPaymentMethod == "TAMARA") {
+ if (Platform.isAndroid) {
+ Uri uri = new Uri.dataFromString(url);
+ tamaraPaymentStatus = uri.queryParameters['status'];
+ tamaraOrderID = uri.queryParameters['AuthorizePaymentId'];
+ } else {
+ Uri uri = new Uri.dataFromString(url);
+ tamaraPaymentStatus = uri.queryParameters['paymentStatus'];
+ tamaraOrderID = uri.queryParameters['orderId'];
+ }
+ }
+
+ 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) {
+ try {
+ if (selectedPaymentMethod == "TAMARA") {
+ checkTamaraPaymentStatus(transID!, appo);
+ // if (tamaraPaymentStatus != null && tamaraPaymentStatus!.toLowerCase() == "approved") {
+ // updateTamaraRequestStatus("success", "14", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID!, num.parse(selectedInstallments!), appo);
+ // } else {
+ // updateTamaraRequestStatus(
+ // "Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID! != null ? tamaraOrderID! : "", num.parse(selectedInstallments!), appo);
+ // }
+ } else {
+ checkPaymentStatus(appo);
+ }
+ } catch (err) {
+ print(err);
+ }
+ }
+
+ checkTamaraPaymentStatus(String orderID, AppoitmentAllHistoryResultList appo) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ DoctorsListService service = new DoctorsListService();
+ service.getTamaraPaymentStatus(orderID).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ if (res["status"].toString().toLowerCase() == "success") {
+ updateTamaraRequestStatus("success", "14", orderID, tamaraOrderID!, int.parse(selectedInstallments!), appo);
+ } else {
+ updateTamaraRequestStatus(
+ "Failed", "00", Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), tamaraOrderID != null ? tamaraOrderID! : "", int.parse(selectedInstallments!), appo);
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ updateTamaraRequestStatus(String responseMessage, String status, String clientRequestID, String tamaraOrderID, num selectedInstallments, AppoitmentAllHistoryResultList appo) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ try {
+ DoctorsListService service = new DoctorsListService();
+ service.updateTamaraRequestStatus(responseMessage, status, clientRequestID, tamaraOrderID, selectedInstallments).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ if (tamaraPaymentStatus!.toLowerCase() == "approved") {
+ insertWalkInAppointment(context, widget.doctor, widget.initialSlotDuration, tamaraOrderID);
+ }
+ }).catchError((err) {
+ print(err);
+ AppToast.showErrorToast(message: err);
+ GifLoaderDialogUtils.hideDialog(context);
+ });
+ } catch (err) {
+ print(err);
+ }
+ }
+
+ addAdvancedNumberRequestTamara(String advanceNumber, String paymentReference, String appointmentID, AppoitmentAllHistoryResultList appo) {
+ DoctorsListService service = new DoctorsListService();
+ service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, context).then((res) {}).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ markAppointmentForTamara(AppoitmentAllHistoryResultList appo) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ DoctorsListService service = new DoctorsListService();
+ service.markAppointmentForTamara(appo.projectID!, appo.appointmentNo.toString()).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ sendNfcCheckInRequest(projectViewModel.waitingAppointmentNFCCode, 2, int.parse(appo.appointmentNo), projectViewModel.waitingAppointmentProjectID, appo.clinicID);
+ }).catchError((err) {
+ print(err);
+ AppToast.showErrorToast(message: err);
+ GifLoaderDialogUtils.hideDialog(context);
+ });
+ }
+
+ checkPaymentStatus(AppoitmentAllHistoryResultList appo) {
+ String txn_ref;
+ num amount;
+ String payment_method;
+ final currency = projectViewModel.user!.outSA == 0 ? "sar" : 'aed';
+ GifLoaderDialogUtils.showMyDialog(context);
+ DoctorsListService service = new DoctorsListService();
+ service.checkPaymentStatus(transID!, false, context).then((res) {
+ String paymentInfo = res['Response_Message'];
+ if (paymentInfo == 'Success') {
+ txn_ref = res['Merchant_Reference'];
+ amount = res['Amount'];
+ payment_method = res['PaymentMethod'];
+ GifLoaderDialogUtils.hideDialog(context);
+ insertWalkInAppointment(context, widget.doctor, widget.initialSlotDuration, res);
+ projectViewModel.analytics.appointment.payment_success(
+ appointment_type: 'Walk-In', payment_method: payment_method, clinic: appo.clinicName, hospital: appo.projectName, txn_amount: "$amount", txn_currency: currency, txn_number: txn_ref);
+ } else {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: res['Response_Message']);
+ projectViewModel.analytics.appointment.payment_fail(
+ appointment_type: 'Walk-In',
+ payment_method: selectedPaymentMethod,
+ clinic: appo.clinicName,
+ hospital: appo.projectName,
+ txn_amount: widget.patientShareResponse.patientShareWithTax.toString(),
+ txn_currency: currency,
+ error_type: res['Response_Message']);
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err.toString());
+ print(err);
+ });
+ }
+
Widget showInfo(String title, String des) {
return Container(
child: Row(
@@ -253,7 +680,7 @@ class _BookConfirmState extends State {
);
}
- cancelAppointment(DoctorList docObject, AppoitmentAllHistoryResultList appo, BuildContext context) async {
+ cancelAppointment(DoctorList docObject, AppoitmentAllHistoryResultList appo, BuildContext context, {int? invoiceNumber, int? lineItemNo, String? invoiceNoVP}) async {
ConfirmDialog.closeAlertDialog(context);
GifLoaderDialogUtils.showMyDialog(context, barrierDismissible: false);
DoctorsListService service = new DoctorsListService();
@@ -265,7 +692,7 @@ class _BookConfirmState extends State {
if (isLiveCareSchedule != null && isLiveCareSchedule) {
insertLiveCareScheduledAppointment(context, widget.doctor);
} else {
- insertAppointment(context, widget.doctor, widget.initialSlotDuration);
+ insertAppointment(context, widget.doctor, widget.initialSlotDuration, invoiceNumber: invoiceNumber, lineItemNo: lineItemNo, invoiceNoVP: invoiceNoVP);
}
});
} else {
@@ -290,7 +717,7 @@ class _BookConfirmState extends State {
okText: "Update insurance",
cancelText: "Continue as cash",
okFunction: () => {openUpdateInsurance()},
- cancelFunction: () => {continueAsCash(docObject, appointmentNo)});
+ cancelFunction: () => {continueAsCash(docObject, appointmentNo, false)});
dialog.showAlertDialog(context);
}
}).catchError((err) {
@@ -304,23 +731,172 @@ class _BookConfirmState extends State {
Navigator.push(context, FadePage(page: InsuranceUpdate()));
}
- void continueAsCash(DoctorList docObject, String appointmentNo) {
+ void continueAsCash(DoctorList docObject, String appointmentNo, bool isLiveCareAppointment) {
GifLoaderDialogUtils.showMyDialog(context);
widget.service.convertPatientToCash(docObject.projectID!).then((res) {
GifLoaderDialogUtils.hideDialog(context);
if (res["MessageStatus"] == 1) {
- getPatientShare(context, appointmentNo, docObject.clinicID!, docObject.projectID!, docObject);
+ if (isLiveCareAppointment) {
+ getLiveCareAppointmentPatientShare(context, appointmentNo, docObject!.clinicID!, docObject.projectID!, docObject);
+ } else {
+ getPatientShare(context, appointmentNo, docObject.clinicID!, docObject.projectID!, docObject);
+ }
getToDoCount();
} else {
AppToast.showErrorToast(message: res["ErrorEndUserMessage"]);
}
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ void continueAsCashForWalkIn(int projectID) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ widget.service.convertPatientToCash(projectID).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ if (res["MessageStatus"] == 1) {
+ getWalkinAppointmentPatientShare();
+ } else {
+ AppToast.showErrorToast(message: res["ErrorEndUserMessage"]);
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ insertWalkInAppointment(context, DoctorList docObject, int initialSlotDuration, paymentRes) async {
+ GifLoaderDialogUtils.showMyDialog(
+ context,
+ );
+ AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList();
+ appo.doctorID = docObject.doctorID;
+ appo.clinicID = docObject.clinicID;
+ appo.projectID = docObject.projectID;
+
+ widget.service
+ .insertWalkInAppointment(
+ docObject.doctorID!, docObject.clinicID!, docObject.projectID!, widget.selectedTime, widget.selectedDate, initialSlotDuration, projectViewModel.isArabic ? 1 : 2, context)
+ .then((res) {
+ if (res['MessageStatus'] == 1) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess);
+ appo.appointmentNo = res["AppointmentNo"]; // Add appointment No to the appointment project
+ Future.delayed(Duration(milliseconds: 500), () {
+ if (selectedPaymentMethod == "TAMARA") {
+ markAppointmentForTamara(appo);
+ addAdvancedNumberRequestTamara("Tamara-Advance-0000", paymentRes, res["AppointmentNo"].toString(), appo);
+ } else {
+ if (widget.patientShareResponse.patientShareWithTax != 0 || widget.patientShareResponse.patientShareWithTax != 0.0) {
+ createAdvancePayment(paymentRes, appo);
+ } else {
+ sendNfcCheckInRequest(projectViewModel.waitingAppointmentNFCCode, 2, int.parse(res["AppointmentNo"]), projectViewModel.waitingAppointmentProjectID, appo.clinicID);
+ }
+ }
+ });
+ } else {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: res['ErrorEndUserMessage']);
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ });
+ }
+
+ createAdvancePayment(res, AppoitmentAllHistoryResultList appo) {
+ GifLoaderDialogUtils.showMyDialog(
+ context,
+ );
+ DoctorsListService service = new DoctorsListService();
+ String paymentReference = res['Fort_id'].toString();
+ service.createAdvancePayment(appo, appo.projectID.toString(), res['Amount'], res['Fort_id'], res['PaymentMethod'], context).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ addAdvancedNumberRequest(
+ Utils.isVidaPlusProject(projectViewModel, appo.projectID!)
+ ? res['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
+ : res['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
+ paymentReference,
+ appo.appointmentNo.toString(),
+ appo);
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ addAdvancedNumberRequest(String advanceNumber, String paymentReference, String appointmentID, AppoitmentAllHistoryResultList appo) {
+ GifLoaderDialogUtils.showMyDialog(
+ context,
+ );
+ DoctorsListService service = new DoctorsListService();
+ service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, context).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ sendNfcCheckInRequest(projectViewModel.waitingAppointmentNFCCode, 2, int.parse(appointmentID), projectViewModel.waitingAppointmentProjectID, appo.clinicID);
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err);
+ print(err);
+ });
+ }
+
+ sendNfcCheckInRequest(String nfcId, int checkInBy, int appoNo, int projectID, int clinicID) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ DoctorsListService service = new DoctorsListService();
+ service.sendCheckinNfcRequest(appoNo, nfcId, projectID, checkInBy, clinicID, context).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ _showMyDialog(res["SuccessMsg"], this.context);
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
print(err);
+ _showMyDialog(err, this.context);
});
}
- insertAppointment(context, DoctorList docObject, int initialSlotDuration) async {
+ checkPatientHasDermaPackage(DoctorList doctor, int patientID) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ widget.service
+ .checkPatientHasDermaPackage(
+ patientID!,
+ doctor.clinicID!,
+ doctor.projectID!,
+ doctor.doctorID!,
+ projectViewModel.isArabic ? 1 : 2,
+ context,
+ )
+ .then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ if (res['MessageStatus'] == 1 && res['PatientPackageComponent']['Message'] == 'Success') {
+ PatientPackageComponent package = PatientPackageComponent.fromJson(res['PatientPackageComponent']);
+
+ ConfirmDialog dialog = ConfirmDialog(
+ context: context,
+ confirmMessage: "${TranslationBase.of(context).existingPackage} ${package.patientPackageComponents![0].procedureName}, ${TranslationBase.of(context).continueOrbookNew}",
+ okText: TranslationBase.of(context).proceedPackage,
+ cancelText: TranslationBase.of(context).newAppointment,
+ okFunction: () => {
+ ConfirmDialog.closeAlertDialog(context),
+ insertAppointment(context, widget.doctor, widget.initialSlotDuration,
+ invoiceNumber: package.patientPackageComponents![0].invoiceNo,
+ lineItemNo: package.patientPackageComponents![0].lineItemNo,
+ invoiceNoVP: package.patientPackageComponents![0].invoiceNo_VP.toString())
+ },
+ cancelFunction: () => {insertAppointment(context, widget.doctor, widget.initialSlotDuration)},
+ );
+ dialog.showAlertDialog(context);
+ } else {
+ insertAppointment(context, widget.doctor, widget.initialSlotDuration);
+ }
+ }).onError((error, stackTrace) {
+ insertAppointment(context, widget.doctor, widget.initialSlotDuration);
+ });
+ }
+
+ insertAppointment(context, DoctorList docObject, int initialSlotDuration, {int? invoiceNumber, int? lineItemNo, String? invoiceNoVP}) async {
final timeSlot = DocAvailableAppointments.selectedAppoDateTime;
String logs = await sharedPref.getString('selectedLogSlots');
List decodedLogs = json.decode(logs);
@@ -329,7 +905,7 @@ class _BookConfirmState extends State {
widget.service
// .insertAppointment(docObject.doctorID!, docObject.clinicID!, docObject.projectID!, widget.selectedTime, widget.selectedDate, initialSlotDuration, context, 'null', null, null, projectViewModel)
.insertAppointment(docObject.doctorID!, docObject.clinicID!, docObject.projectID!, widget.selectedTime, widget.selectedDate, initialSlotDuration, projectViewModel.isArabic ? 1 : 2, context,
- null, null, null, projectViewModel)
+ null, null, null, projectViewModel, invoiceNumber, lineItemNo, invoiceNoVP)
.then((res) {
if (res['MessageStatus'] == 1) {
AppToast.showSuccessToast(message: TranslationBase.of(context).bookedSuccess);
@@ -366,14 +942,14 @@ class _BookConfirmState extends State {
confirmMessage: res['ErrorEndUserMessage'],
okText: TranslationBase.of(context).confirm,
cancelText: TranslationBase.of(context).cancel_nocaps,
- okFunction: () => {cancelAppointment(docObject, appo, context)},
+ okFunction: () => {cancelAppointment(docObject, appo, context, invoiceNumber: invoiceNumber, lineItemNo: lineItemNo)},
cancelFunction: () => {},
);
dialog.showAlertDialog(context);
}
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
- AppToast.showErrorToast(message: err);
+ AppToast.showErrorToast(message: err, localContext: context);
});
projectViewModel.analytics.appointment.book_appointment_click_confirm(appointment_type: 'regular', dateTime: timeSlot!, doctor: widget.doctor);
}
@@ -476,7 +1052,7 @@ class _BookConfirmState extends State {
okText: TranslationBase.of(context).updateInsuranceText,
cancelText: TranslationBase.of(context).continueCash,
okFunction: () => {openUpdateInsurance()},
- cancelFunction: () => {continueAsCash(docObject, appointmentNo)});
+ cancelFunction: () => {continueAsCash(docObject, appointmentNo, false)});
dialog.showAlertDialog(context);
}
}
@@ -491,10 +1067,40 @@ class _BookConfirmState extends State {
}
getLiveCareAppointmentPatientShare(context, String appointmentNo, int clinicID, int projectID, DoctorList docObject) {
+ String errorMsg = "";
+
widget.service.getLiveCareAppointmentPatientShare(appointmentNo, clinicID, projectID, projectViewModel.isArabic ? 1 : 2, context).then((res) {
widget.patientShareResponse = new PatientShareResponse.fromJson(res);
GifLoaderDialogUtils.hideDialog(context);
- navigateToBookSuccess(context, docObject, widget.patientShareResponse, false);
+
+ isInsured = res["IsInsured"];
+ isEligible = res["IsEligible"];
+ isCash = res["IsCash"];
+
+ if (isCash) {
+ navigateToBookSuccess(context, docObject, widget.patientShareResponse, isCash);
+ } else {
+ if (isInsured && isEligible) {
+ navigateToBookSuccess(context, docObject, widget.patientShareResponse, isCash);
+ } else {
+ if (isInsured && !isEligible) {
+ errorMsg = TranslationBase.of(context).invalidEligibility;
+ } else {
+ errorMsg = TranslationBase.of(context).invalidInsurance;
+ }
+ ConfirmDialog dialog = new ConfirmDialog(
+ isDissmissable: false,
+ context: context,
+ confirmMessage: errorMsg,
+ okText: TranslationBase.of(context).updateInsuranceText,
+ cancelText: TranslationBase.of(context).continueCash,
+ okFunction: () => {openUpdateInsurance()},
+ cancelFunction: () => {continueAsCash(docObject, appointmentNo, true)});
+ dialog.showAlertDialog(context);
+ }
+ }
+
+ // navigateToBookSuccess(context, docObject, widget.patientShareResponse, false);
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
AppToast.showErrorToast(message: err);
@@ -575,4 +1181,32 @@ class _BookConfirmState extends State {
),
);
}
+
+ 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);
+ },
+ ),
+ ],
+ );
+ },
+ );
+ }
}
diff --git a/lib/pages/BookAppointment/DoctorProfile.dart b/lib/pages/BookAppointment/DoctorProfile.dart
index f1738c85..1674c43d 100644
--- a/lib/pages/BookAppointment/DoctorProfile.dart
+++ b/lib/pages/BookAppointment/DoctorProfile.dart
@@ -10,6 +10,7 @@ import 'package:diplomaticquarterapp/models/Clinics/ClinicListResponse.dart';
import 'package:diplomaticquarterapp/models/header_model.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/DentalComplaints.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/doctor_post_pre_images_page.dart';
+import 'package:diplomaticquarterapp/pages/BookAppointment/waiting_appointment/waiting_appointment_info.dart';
import 'package:diplomaticquarterapp/pages/MyAppointments/SchedulePage.dart';
import 'package:diplomaticquarterapp/routes.dart';
import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart';
@@ -520,15 +521,9 @@ class _DoctorProfileState extends State with TickerProviderStateM
// if (widget.isDoctorNameSearch && widget.doctor.clinicID == 17) {
// navigateToDentalComplaints(context);
// } else {
- if (DocAvailableAppointments.areSlotsAvailable) {
+ if (DocAvailableAppointments.selectedTime == TranslationBase.of(context).waitingAppointment) {
if (projectViewModel.isLogin) {
- if (widget.isDoctorNameSearch && widget.doctor.clinicID == 17 && projectViewModel.user!.age! > 12) {
- navigateToDentalComplaints(context);
- } else {
- final timeSlot = DocAvailableAppointments.selectedAppoDateTime;
- navigateToBookConfirm(context);
- projectViewModel.analytics.appointment.book_appointment_review(appointment_type: 'regular', dateTime: timeSlot!, doctor: widget.doctor);
- }
+ canPayForWalkInAppointment();
} else {
ConfirmDialog dialog = new ConfirmDialog(
context: context,
@@ -539,9 +534,30 @@ class _DoctorProfileState extends State with TickerProviderStateM
cancelFunction: () => {});
dialog.showAlertDialog(context);
}
- } else
- AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot);
- // }
+ } else {
+ if (DocAvailableAppointments.areSlotsAvailable) {
+ if (projectViewModel.isLogin) {
+ if (widget.isDoctorNameSearch && widget.doctor.clinicID == 17 && projectViewModel.user!.age! > 12) {
+ navigateToDentalComplaints(context);
+ } else {
+ final timeSlot = DocAvailableAppointments.selectedAppoDateTime;
+ navigateToBookConfirm(context);
+ projectViewModel.analytics.appointment.book_appointment_review(appointment_type: 'regular', dateTime: timeSlot!, doctor: widget.doctor);
+ }
+ } else {
+ ConfirmDialog dialog = new ConfirmDialog(
+ context: context,
+ confirmMessage: TranslationBase.of(context).loginToUseService,
+ okText: TranslationBase.of(context).confirm,
+ cancelText: TranslationBase.of(context).cancel_nocaps,
+ okFunction: () => {navigateToLogin()},
+ cancelFunction: () => {});
+ dialog.showAlertDialog(context);
+ }
+ } else {
+ AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot);
+ }
+ }
}
Future navigateToDentalComplaints(BuildContext context) async {
@@ -586,8 +602,33 @@ class _DoctorProfileState extends State with TickerProviderStateM
selectedDate: DocAvailableAppointments.selectedDate!,
selectedTime: DocAvailableAppointments.selectedTime!,
initialSlotDuration: DocAvailableAppointments.initialSlotDuration!,
+ isWalkinAppointment: false,
),
),
);
}
+
+ Future navigateToWaitingAppointment(context) async {
+ projectViewModel.setWaitingAppointmentProjectID(widget.doctor.projectID!);
+ projectViewModel.setWaitingAppointmentDoctor(widget.doctor);
+ Navigator.push(
+ context,
+ FadePage(
+ page: WaitingAppointmentInfo(),
+ ),
+ );
+ }
+
+ canPayForWalkInAppointment() {
+ DoctorsListService service = new DoctorsListService();
+ GifLoaderDialogUtils.showMyDialog(context);
+ service.canPayForWalkInAppointment(widget.doctor.clinicID!, widget.doctor.projectID!, widget.doctor.doctorID!).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ navigateToWaitingAppointment(context);
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: err, localContext: context);
+ print(err);
+ });
+ }
}
diff --git a/lib/pages/BookAppointment/QRCode.dart b/lib/pages/BookAppointment/QRCode.dart
index a96e8dc6..e27a55bb 100644
--- a/lib/pages/BookAppointment/QRCode.dart
+++ b/lib/pages/BookAppointment/QRCode.dart
@@ -387,7 +387,7 @@ class _QRCodeState extends State {
DoctorsListService service = new DoctorsListService();
- service.sendCheckinNfcRequest(widget!.patientShareResponse!.appointmentNo!, nfcId, widget.patientShareResponse!.projectID!, checkInBy, context).then((res) {
+ service.sendCheckinNfcRequest(widget!.patientShareResponse!.appointmentNo!, nfcId, widget.patientShareResponse!.projectID!, checkInBy, widget.patientShareResponse!.clinicID!, context).then((res) {
print(res);
GifLoaderDialogUtils.hideDialog(context);
diff --git a/lib/pages/BookAppointment/Search.dart b/lib/pages/BookAppointment/Search.dart
index b5680c1c..c7989cbf 100644
--- a/lib/pages/BookAppointment/Search.dart
+++ b/lib/pages/BookAppointment/Search.dart
@@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/components/SearchByClinic.dart';
import 'package:diplomaticquarterapp/pages/BookAppointment/components/SearchByDoctor.dart';
+import 'package:diplomaticquarterapp/pages/BookAppointment/components/search_by_hospital_name.dart';
import 'package:diplomaticquarterapp/uitl/location_util.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
@@ -28,15 +29,20 @@ class _SearchState extends State with TickerProviderStateMixin {
@override
void initState() {
- _tabController = new TabController(length: 2, vsync: this, initialIndex: widget.type, );
+ _tabController = new TabController(
+ length: 3,
+ vsync: this,
+ initialIndex: widget.type,
+ );
super.initState();
}
@override
Widget build(BuildContext context) {
AppGlobal.context = context;
- // ProjectViewModel projectViewModel = Provider.of(context);
- GAnalytics.TREATMENT_TYPE = null; // reset treatment type on start new booking
+ // ProjectViewModel projectViewModel = Provider.of(context);
+ GAnalytics.TREATMENT_TYPE =
+ null; // reset treatment type on start new booking
return AppScaffold(
isShowAppBar: false,
@@ -54,32 +60,58 @@ class _SearchState extends State with TickerProviderStateMixin {
indicatorSize: TabBarIndicatorSize.tab,
labelColor: Color(0xff2B353E),
unselectedLabelColor: Color(0xff575757),
- labelPadding: EdgeInsets.only(top: 15, bottom: 13, left: 20, right: 20),
+ labelPadding:
+ EdgeInsets.only(top: 15, bottom: 13, left: 20, right: 20),
labelStyle: TextStyle(
- fontFamily: context.read().isArabic ? 'Cairo' : 'Poppins',
+ fontFamily: context.read().isArabic
+ ? 'Cairo'
+ : 'Poppins',
fontSize: 16,
fontWeight: FontWeight.w600,
letterSpacing: -0.48,
),
unselectedLabelStyle: TextStyle(
- fontFamily: context.read().isArabic ? 'Cairo' : 'Poppins',
+ fontFamily: context.read().isArabic
+ ? 'Cairo'
+ : 'Poppins',
fontSize: 16,
fontWeight: FontWeight.w600,
letterSpacing: -0.48,
),
- tabs: [Text(TranslationBase.of(context).clinicName), Text(TranslationBase.of(context).doctorName)],
+ tabs: [
+ Text(
+ TranslationBase.of(context).hospitalName,
+ style: TextStyle(fontSize: 12),
+ ),
+ Text(
+ TranslationBase.of(context).clinicName,
+ style: TextStyle(fontSize: 12),
+ ),
+ Text(
+ TranslationBase.of(context).doctorName,
+ style: TextStyle(fontSize: 12),
+ )
+ ],
onTap: (idx) {
if (idx == 0)
- context.read().analytics.appointment.book_appointment_by_clinic();
+ context
+ .read()
+ .analytics
+ .appointment
+ .book_appointment_by_clinic();
else
- context.read().analytics.appointment.book_appointment_by_doctor();
+ context
+ .read()
+ .analytics
+ .appointment
+ .book_appointment_by_doctor();
},
),
Expanded(
child: TabBarView(
-
physics: NeverScrollableScrollPhysics(),
children: [
+ SearchByHospital(),
SearchByClinic(clnicIds: widget.clnicIds),
SearchByDoctor(),
],
diff --git a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart
index a2940ce8..6e12c68e 100644
--- a/lib/pages/BookAppointment/components/DocAvailableAppointments.dart
+++ b/lib/pages/BookAppointment/components/DocAvailableAppointments.dart
@@ -60,6 +60,8 @@ class _DocAvailableAppointmentsState extends State wit
var language;
bool isLiveCareSchedule = false;
+ bool isWaitingAppointmentAvailable = false;
+
// String selectedLogSlots ='';
@override
@@ -198,7 +200,7 @@ class _DocAvailableAppointmentsState extends State wit
_events.forEach((key, value) {
final DateTime startTime = DateTime(key.year, key.month, key.day, 9, 0, 0);
final DateTime endTime = startTime.add(const Duration(hours: 2));
- meetings.add(Meeting("", startTime, endTime, CustomColors.green, false));
+ meetings.add(Meeting("", startTime, endTime, CustomColors.green, false, ""));
});
return meetings;
}
@@ -206,7 +208,9 @@ class _DocAvailableAppointmentsState extends State wit
openTimeSlotsPickerForDate(DateTime dateStart, List freeSlots) {
dayEvents.clear();
DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0);
-
+ if (isWaitingAppointmentAvailable && DateUtils.isSameDay(dateStart, DateTime.now())) {
+ dayEvents.add(TimeSlot(isoTime: TranslationBase.of(context).waitingAppointment, start: DateTime.now(), end: DateTime.now(), vidaDate: ""));
+ }
freeSlots.forEach((v) {
if (v.start == dateStartObj) dayEvents.add(v);
});
@@ -276,23 +280,27 @@ class _DocAvailableAppointmentsState extends State wit
selectedDateJSON = freeSlotsResponse[0];
});
openTimeSlotsPickerForDate(
- (isLiveCareSchedule != null && isLiveCareSchedule)
+ isWaitingAppointmentAvailable
+ ? DateTime.now()
+ : (isLiveCareSchedule != null && isLiveCareSchedule)
+ ? DateUtil.convertStringToDate(selectedDateJSON)
+ : DateUtil.convertStringToDateSaudiTimezone(
+ selectedDateJSON,
+ int.parse(
+ widget.doctor.projectID.toString(),
+ ),
+ ),
+ docFreeSlots);
+ _calendarController.selectedDate = isWaitingAppointmentAvailable
+ ? DateTime.now()
+ : (isLiveCareSchedule != null && isLiveCareSchedule)
? DateUtil.convertStringToDate(selectedDateJSON)
: DateUtil.convertStringToDateSaudiTimezone(
selectedDateJSON,
int.parse(
widget.doctor.projectID.toString(),
),
- ),
- docFreeSlots);
- _calendarController.selectedDate = (isLiveCareSchedule != null && isLiveCareSchedule)
- ? DateUtil.convertStringToDate(selectedDateJSON)
- : DateUtil.convertStringToDateSaudiTimezone(
- selectedDateJSON,
- int.parse(
- widget.doctor.projectID.toString(),
- ),
- );
+ );
_calendarController.displayDate = _calendarController.selectedDate;
return _eventsParsed;
}
@@ -323,10 +331,10 @@ class _DocAvailableAppointmentsState extends State wit
Widget getSelectedButton(int index) {
return CustomTextButton(
- backgroundColor: CustomColors.green,
+ backgroundColor: dayEvents[index].isoTime == TranslationBase.of(context).waitingAppointment ? CustomColors.darkOrange : CustomColors.green,
elevation: 0,
side: BorderSide(
- color: CustomColors.green, //Color of the border
+ color: dayEvents[index].isoTime == TranslationBase.of(context).waitingAppointment ? CustomColors.darkOrange : CustomColors.green, //Color of the border
style: BorderStyle.solid, //Style of the border
width: 1.5 //width of the border
),
@@ -349,21 +357,23 @@ class _DocAvailableAppointmentsState extends State wit
GifLoaderDialogUtils.hideDialog(context);
if (res['MessageStatus'] == 1) {
if (res['FreeTimeSlots'].length != 0) {
+ isWaitingAppointmentAvailable = res['IsAllowToBookWaitingAppointment']; // true;
+ // isWaitingAppointmentAvailable = true; // true;
DocAvailableAppointments.initialSlotDuration = res['InitialSlotDuration'];
DocAvailableAppointments.areAppointmentsAvailable = true;
freeSlotsResponse = res['FreeTimeSlots'];
_getJSONSlots().then((value) {
- setState(() => {
- _events.clear(),
- _events = value,
- if (widget.doctorSchedule != null)
- {
- _onDaySelected(DateUtil.convertStringToDate(widget.doctorSchedule['Date'])),
- _calendarController.selectedDate = DateUtil.convertStringToDate(
- widget.doctorSchedule['Date'],
- )
- }
- });
+ setState(() {
+ _events.clear();
+ _events = value;
+ if (widget.doctorSchedule != null) {
+ _onDaySelected(DateUtil.convertStringToDate(widget.doctorSchedule['Date']));
+ _calendarController.selectedDate = DateUtil.convertStringToDate(
+ widget.doctorSchedule['Date'],
+ );
+ }
+ ;
+ });
});
} else {
DocAvailableAppointments.areAppointmentsAvailable = false;
@@ -464,11 +474,12 @@ class MeetingDataSource extends CalendarDataSource {
}
class Meeting {
- Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay);
+ Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay, this.notes);
String eventName;
DateTime from;
DateTime to;
Color background;
bool isAllDay;
+ String notes;
}
diff --git a/lib/pages/BookAppointment/components/SearchByClinic.dart b/lib/pages/BookAppointment/components/SearchByClinic.dart
index 849a0afc..a113e81b 100644
--- a/lib/pages/BookAppointment/components/SearchByClinic.dart
+++ b/lib/pages/BookAppointment/components/SearchByClinic.dart
@@ -1,6 +1,7 @@
import "dart:collection";
import 'package:auto_size_text/auto_size_text.dart';
+import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/config/size_config.dart';
import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart';
@@ -95,6 +96,7 @@ class _SearchByClinicState extends State {
@override
Widget build(BuildContext context) {
+ AppGlobal.context = context;
return Container(
child: SingleChildScrollView(
child: Column(
@@ -648,7 +650,7 @@ class _SearchByClinicState extends State {
doctorsList.forEach((element) {
List doctorByHospital = _patientDoctorAppointmentListHospital
.where(
- (elementClinic) => elementClinic.filterName == element.projectName,
+ (elementClinic) => elementClinic.filterName == element.getProjectCompleteName(),
)
.toList();
@@ -656,7 +658,7 @@ class _SearchByClinicState extends State {
_patientDoctorAppointmentListHospital[_patientDoctorAppointmentListHospital.indexOf(doctorByHospital[0])].patientDoctorAppointmentList!.add(element);
} else {
_patientDoctorAppointmentListHospital
- .add(PatientDoctorAppointmentList(filterName: element.projectName, distanceInKMs: element.projectDistanceInKiloMeters.toString(), patientDoctorAppointment: element));
+ .add(PatientDoctorAppointmentList(filterName: element.getProjectCompleteName(), distanceInKMs: element.projectDistanceInKiloMeters.toString(), patientDoctorAppointment: element));
}
});
} else {}
diff --git a/lib/pages/BookAppointment/components/SearchByDoctor.dart b/lib/pages/BookAppointment/components/SearchByDoctor.dart
index f5c98d87..bc17a2ca 100644
--- a/lib/pages/BookAppointment/components/SearchByDoctor.dart
+++ b/lib/pages/BookAppointment/components/SearchByDoctor.dart
@@ -105,13 +105,13 @@ class _SearchByDoctorState extends State {
});
doctorsList.forEach((element) {
- List doctorByHospital = _patientDoctorAppointmentListHospital.where((elementClinic) => elementClinic.filterName == element.projectName).toList();
+ List doctorByHospital = _patientDoctorAppointmentListHospital.where((elementClinic) => elementClinic.filterName == element.getProjectCompleteName()).toList();
if (doctorByHospital.length != 0) {
_patientDoctorAppointmentListHospital[_patientDoctorAppointmentListHospital.indexOf(doctorByHospital[0])].patientDoctorAppointmentList!.add(element);
} else {
_patientDoctorAppointmentListHospital
- .add(PatientDoctorAppointmentList(filterName: element.projectName, distanceInKMs: element.projectDistanceInKiloMeters.toString(), patientDoctorAppointment: element));
+ .add(PatientDoctorAppointmentList(filterName: element.getProjectCompleteName(), distanceInKMs: element.projectDistanceInKiloMeters.toString(), patientDoctorAppointment: element));
}
});
} else {
diff --git a/lib/pages/BookAppointment/components/search_by_hospital_name.dart b/lib/pages/BookAppointment/components/search_by_hospital_name.dart
new file mode 100644
index 00000000..72503cb4
--- /dev/null
+++ b/lib/pages/BookAppointment/components/search_by_hospital_name.dart
@@ -0,0 +1,559 @@
+import 'dart:collection';
+
+import 'package:auto_size_text/auto_size_text.dart';
+import 'package:diplomaticquarterapp/config/config.dart';
+import 'package:diplomaticquarterapp/theme/colors.dart';
+import 'package:diplomaticquarterapp/uitl/utils_new.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../../../config/shared_pref_kay.dart';
+import '../../../config/size_config.dart';
+import '../../../core/model/hospitals/hospitals_model.dart';
+import '../../../core/viewModels/project_view_model.dart';
+import '../../../models/Appointments/DoctorListResponse.dart';
+import '../../../models/Appointments/SearchInfoModel.dart';
+import '../../../models/Clinics/ClinicListResponse.dart';
+import '../../../services/appointment_services/GetDoctorsList.dart';
+import '../../../services/authentication/auth_provider.dart';
+import '../../../services/clinic_services/get_clinic_service.dart';
+import '../../../uitl/app_toast.dart';
+import '../../../uitl/gif_loader_dialog_utils.dart';
+import '../../../uitl/translations_delegate_base.dart';
+import '../../../widgets/transitions/fade_page.dart';
+import '../../livecare/livecare_home.dart';
+import '../DentalComplaints.dart';
+import '../LaserBooking.dart';
+import '../SearchResults.dart';
+import '../dialog/clinic_list_dialog.dart';
+import 'LiveCareBookAppointment.dart';
+
+class SearchByHospital extends StatefulWidget {
+ @override
+ State createState() => _SearchByHospitalState();
+}
+
+class _SearchByHospitalState extends State {
+ HospitalsModel? selectedHospital;
+ bool nearestAppo = false;
+
+ String? selectedClinicName;
+ List projectsList = [];
+ List? clinicIds = List.empty();
+
+ final GlobalKey projectDropdownKey = GlobalKey();
+
+ List clinicsList = [];
+ bool isMobileAppDentalAllow = false;
+ ListClinicCentralized? selectedClinic;
+
+ String? dropdownValue;
+ String dropdownTitle = "";
+
+ @override
+ void initState() {
+ WidgetsBinding.instance.addPostFrameCallback((_) => getProjectsList());
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ AppGlobal.context = context;
+
+ return Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(left: 6, right: 6, top: 16),
+ child: Row(
+ children: [
+ Checkbox(
+ activeColor: CustomColors.accentColor,
+ value: nearestAppo,
+ onChanged: (bool? value) {
+ nearestAppo = value ?? false;
+ setState(() {});
+ },
+ ),
+ AutoSizeText(
+ TranslationBase.of(context).nearestAppo.trim(),
+ maxLines: 1,
+ minFontSize: 10,
+ style: TextStyle(
+ fontSize: SizeConfig.textMultiplier! * 1.4,
+ fontWeight: FontWeight.w600,
+ letterSpacing: -0.39,
+ height: 0.8,
+ ),
+ ),
+ // Text(TranslationBase.of(context).nearestAppo, style: TextStyle(fontSize: 14.0, letterSpacing: -0.56)),
+ ],
+ ),
+ ),
+ mHeight(8),
+ InkWell(
+ onTap: () {
+ openDropdown(projectDropdownKey);
+ },
+ child: Container(
+ width: double.infinity,
+ decoration: containerRadius(Colors.white, 12),
+ margin: EdgeInsets.only(left: 20, right: 20),
+ 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,
+ width: double.infinity,
+ child: DropdownButtonHideUnderline(
+ child: DropdownButton(
+ key: projectDropdownKey,
+ hint: Text(
+ TranslationBase.of(context).selectHospital),
+ value: selectedHospital,
+ iconSize: 0,
+ isExpanded: true,
+ style: TextStyle(
+ fontSize: 14,
+ letterSpacing: -0.56,
+ color: Colors.black),
+ items: projectsList.map((HospitalsModel item) {
+ return DropdownMenuItem(
+ value: item,
+ child: AutoSizeText(
+ item.name!,
+ maxLines: 1,
+ minFontSize: 10,
+ style: TextStyle(
+ fontSize: SizeConfig.textMultiplier! * 1.6,
+ fontWeight: FontWeight.w600,
+ letterSpacing: -0.39,
+ height: 0.8,
+ ),
+ ),
+ // Text('${item.name!}'),
+ );
+ }).toList(),
+ onChanged: (HospitalsModel? newValue) {
+ getClinicWrtHospital(newValue);
+ setState(() {
+ selectedHospital = newValue;
+ });
+ },
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ Icon(Icons.keyboard_arrow_down),
+ ],
+ )),
+ ),
+ if (clinicIds?.isNotEmpty == true) ...[
+ mHeight(8),
+ InkWell(
+ onTap: () {
+ showClickListDialog(context, clinicIds ?? List.empty(),
+ onSelection: (ListClinicCentralized clincs) {
+ selectedClinic = clincs;
+ Navigator.pop(context);
+ setState(() {
+ dropdownTitle = clincs.clinicDescription!;
+ dropdownValue = clincs.clinicID.toString() +
+ "-" +
+ clincs.isLiveCareClinicAndOnline.toString() +
+ "-" +
+ clincs.liveCareClinicID.toString() +
+ "-" +
+ clincs.liveCareServiceID.toString();
+ });
+ getDoctorsList(context);
+
+ context
+ .read()
+ .analytics
+ .appointment
+ .book_appointment_select_clinic(
+ appointment_type: 'regular',
+ clinic: clincs.clinicDescription);
+ });
+ },
+ child: Container(
+ width: double.infinity,
+ decoration: containerRadius(Colors.white, 12),
+ margin: EdgeInsets.only(left: 20, right: 20),
+ padding: EdgeInsets.only(left: 10, right: 10, top: 12, bottom: 8),
+ child: Row(
+ children: [
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ TranslationBase.of(context).selectClinic,
+ style: TextStyle(
+ fontSize: 11,
+ letterSpacing: -0.44,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 4, bottom: 2),
+ child: Text(
+ dropdownTitle,
+ style: TextStyle(
+ fontSize: 13,
+ letterSpacing: -0.44,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ Icon(Icons.keyboard_arrow_down),
+ ],
+ ),
+ ),
+ )
+ ]
+ ],
+ );
+ }
+
+ 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!();
+ }
+
+ GestureDetector? searchForGestureDetector(BuildContext element) {
+ GestureDetector? detector;
+ element.visitChildElements((element) {
+ if (element.widget != null && element.widget is GestureDetector) {
+ detector = element.widget as GestureDetector?;
+ //return false;
+ } else {
+ searchForGestureDetector(element);
+ }
+ });
+ return detector;
+ }
+
+ getProjectsList() {
+ GifLoaderDialogUtils.showMyDialog(context);
+
+ int languageID = context.read().isArabic ? 1 : 2;
+ 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;
+ });
+ } else {}
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+
+ print(err);
+ });
+ }
+
+ void getClinicWrtHospital(HospitalsModel? newValue) async {
+ GifLoaderDialogUtils.showMyDialog(context);
+ ClinicListService service = new ClinicListService();
+ List projectsListLocal = [];
+ setState(() {
+ clinicIds = List.empty();
+ });
+ List clinicId = [];
+ try {
+ Map res = await service.getClinicByHospital(
+ projectID: newValue?.mainProjectID.toString() ?? "");
+ GifLoaderDialogUtils.hideDialog(context);
+ if (res['MessageStatus'] == 1) {
+ List list = res['ListClinic'];
+
+ if (list.isEmpty) {
+ AppToast.showErrorToast(
+ message: TranslationBase.of(context).NoClinicFound,
+ );
+ }
+ res['ListClinic'].forEach((v) {
+ clinicId.add(ListClinicCentralized.fromJson(v));
+ });
+ clinicIds = clinicId;
+ setState(() {});
+ } else {
+ AppToast.showErrorToast(
+ message: TranslationBase.of(context).NoClinicFound,
+ );
+ }
+ } catch (e) {
+ print("the error is $e");
+ AppToast.showErrorToast(
+ message: TranslationBase.of(context).NoClinicFound,
+ );
+ GifLoaderDialogUtils.hideDialog(context);
+ }
+
+ // .then((res) {
+ // print("the result is obtained");
+ // GifLoaderDialogUtils.hideDialog(context);
+ // if (res['MessageStatus'] == 1) {
+ // List list = res['ListClinic'];
+ //
+ // if(list.isEmpty){
+ // AppToast.showErrorToast(message:
+ // TranslationBase.of(context).NoClinicFound,
+ // );
+ //
+ // }
+ // res['ListClinic'].forEach((v) {
+ // clinicId?.add(ListClinicCentralized.fromJson(v));
+ // });
+ // clinicIds = clinicId;
+ // setState(() {
+ //
+ // });
+ // } else {
+ // AppToast.showErrorToast(message:
+ // TranslationBase.of(context).NoClinicFound,
+ // );
+ // }
+ // }).catchError((err) {
+ // print('the error is $err');
+ // AppToast.showErrorToast(message:
+ // TranslationBase.of(context).NoClinicFound,
+ // );
+ // GifLoaderDialogUtils.hideDialog(context);
+ // }).catchError((err) {
+ // AppToast.showErrorToast(message:
+ // TranslationBase.of(context).NoClinicFound,
+ // );
+ // GifLoaderDialogUtils.hideDialog(context);
+ //
+ // print(err);
+ // });
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ Future navigateToDentalComplaints(
+ BuildContext context, SearchInfo searchInfo) async {
+ Navigator.push(
+ context,
+ FadePage(
+ page: DentalComplaints(searchInfo: searchInfo),
+ ),
+ ).then((value) {
+ setState(() {
+ dropdownValue = null;
+ selectedHospital = null;
+ dropdownTitle = "";
+ clinicIds = List.empty();
+ });
+ });
+ }
+
+ callDoctorsSearchAPI(int clinicID) {
+ int languageID = context.read().isArabic ? 1 : 2;
+ GifLoaderDialogUtils.showMyDialog(context);
+ List doctorsList = [];
+ List arr = [];
+ List arrDistance = [];
+ List result;
+ int numAll;
+ List _patientDoctorAppointmentListHospital =
+ [];
+
+ DoctorsListService service = new DoctorsListService();
+ service
+ .getDoctorsList(
+ clinicID,
+ selectedHospital?.mainProjectID.toString() != ""
+ ? int.parse(selectedHospital?.mainProjectID.toString() ?? "-1")
+ : 0,
+ nearestAppo,
+ languageID,
+ null)
+ .then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ if (res['MessageStatus'] == 1) {
+ setState(() {
+ if (res['DoctorList'].length != 0) {
+ doctorsList.clear();
+ res['DoctorList'].forEach((v) {
+ doctorsList.add(DoctorList.fromJson(v));
+ });
+ doctorsList.forEach((element) {
+ List doctorByHospital =
+ _patientDoctorAppointmentListHospital
+ .where(
+ (elementClinic) =>
+ elementClinic.filterName == element.getProjectCompleteName(),
+ )
+ .toList();
+
+ if (doctorByHospital.length != 0) {
+ _patientDoctorAppointmentListHospital[
+ _patientDoctorAppointmentListHospital
+ .indexOf(doctorByHospital[0])]
+ .patientDoctorAppointmentList!
+ .add(element);
+ } else {
+ _patientDoctorAppointmentListHospital.add(
+ PatientDoctorAppointmentList(
+ filterName: element.getProjectCompleteName(),
+ distanceInKMs:
+ element.projectDistanceInKiloMeters.toString(),
+ patientDoctorAppointment: element));
+ }
+ });
+ } else {}
+ });
+
+ result = LinkedHashSet.from(arr).toList();
+ numAll = result.length;
+ navigateToSearchResults(
+ context, doctorsList, _patientDoctorAppointmentListHospital);
+ } else {
+ AppToast.showErrorToast(message: res['ErrorEndUserMessage']);
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ print(err);
+ AppToast.showErrorToast(message: err, localContext: context);
+ });
+ }
+
+ Future navigateToSearchResults(
+ context,
+ List docList,
+ List
+ patientDoctorAppointmentListHospital) async {
+ Navigator.push(
+ context,
+ FadePage(
+ page: SearchResults(
+ isLiveCareAppointment: false,
+ doctorsList: docList,
+ patientDoctorAppointmentListHospital:
+ patientDoctorAppointmentListHospital)))
+ .then((value) {
+ print("navigation return ");
+ dropdownValue = null;
+ dropdownTitle = "";
+ selectedHospital = null;
+ clinicIds = List.empty();
+ setState(() {});
+ // getProjectsList();
+ });
+ }
+
+ Future navigateToLaserClinic(BuildContext context) async {
+ Navigator.push(
+ context,
+ FadePage(
+ page: LaserBooking(),
+ ),
+ ).then((value) {
+ print("LaserBooking navigation return ");
+ setState(() {
+ dropdownValue = null;
+ selectedHospital = null;
+ dropdownTitle = "";
+ clinicIds = List.empty();
+ });
+ });
+ }
+
+ getDoctorsList(BuildContext context) {
+ SearchInfo searchInfo = new SearchInfo();
+ if (dropdownValue != null) if (dropdownValue!.split("-")[0] == "17") {
+ searchInfo.ProjectID = int.parse(selectedHospital?.mainProjectID.toString() ?? "");
+ searchInfo.ClinicID = int.parse(dropdownValue!.split("-")[0]);
+ searchInfo.hospital = selectedHospital;
+ searchInfo.clinic = selectedClinic;
+ searchInfo.date = DateTime.now();
+
+ if (context.read().isLogin) {
+ if (context.read().user.age! > 12) {
+ navigateToDentalComplaints(context, searchInfo);
+ } else {
+ callDoctorsSearchAPI(17);
+ }
+ } else {
+ navigateToDentalComplaints(context, searchInfo);
+ }
+ } else if (dropdownValue!.split("-")[0] == "253") {
+ navigateToLaserClinic(context);
+ // callDoctorsSearchAPI();
+ } else if (dropdownValue!.split("-")[1] == "true"
+ // && authProvider.isLogin &&
+ // authUser.patientType == 1
+ ) {
+ Navigator.push(
+ context,
+ FadePage(
+ page: LiveCareBookAppointment(
+ clinicName: dropdownTitle,
+ liveCareClinicID: dropdownValue!.split("-")[2],
+ liveCareServiceID: dropdownValue!.split("-")[3]),
+ ),
+ ).then((value) {
+ print("navigation return ");
+ if (value == "false") dropdownValue = null;
+
+ // setState(() {
+ // });
+ if (value == "livecare") {
+ Navigator.push(context, FadePage(page: LiveCareHome()));
+ }
+ if (value == "schedule") {
+ callDoctorsSearchAPI(int.parse(dropdownValue!.split("-")[0]));
+ }
+ });
+ setState(() {});
+ } else {
+ callDoctorsSearchAPI(int.parse(dropdownValue!.split("-")[0]));
+ }
+ }
+}
diff --git a/lib/pages/BookAppointment/dialog/clinic_list_dialog.dart b/lib/pages/BookAppointment/dialog/clinic_list_dialog.dart
index ecbe1003..c3d82c74 100644
--- a/lib/pages/BookAppointment/dialog/clinic_list_dialog.dart
+++ b/lib/pages/BookAppointment/dialog/clinic_list_dialog.dart
@@ -115,7 +115,7 @@ class _ClickListDialogState extends State {
),
),
),
- tempClinicsList[index].isLiveCareClinicAndOnline!
+ tempClinicsList[index].isLiveCareClinicAndOnline == true
? SvgPicture.asset(
'assets/images/new-design/video_icon_green_right.svg',
height: 12,
diff --git a/lib/pages/BookAppointment/waiting_appointment/waiting_appointment_info.dart b/lib/pages/BookAppointment/waiting_appointment/waiting_appointment_info.dart
new file mode 100644
index 00000000..f1f8d934
--- /dev/null
+++ b/lib/pages/BookAppointment/waiting_appointment/waiting_appointment_info.dart
@@ -0,0 +1,113 @@
+import 'package:diplomaticquarterapp/pages/BookAppointment/waiting_appointment/waiting_appointment_verification.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/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:flutter_svg/flutter_svg.dart';
+
+class WaitingAppointmentInfo extends StatelessWidget {
+ const WaitingAppointmentInfo({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return AppScaffold(
+ appBarTitle: TranslationBase.of(context).waitingAppointment,
+ isShowAppBar: true,
+ isShowDecPage: false,
+ showNewAppBar: true,
+ showNewAppBarTitle: true,
+ backgroundColor: CustomColors.appBackgroudGreyColor,
+ body: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ width: MediaQuery.of(context).size.width,
+ decoration: containerRadius(Colors.white, 10),
+ child: Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SvgPicture.asset(
+ "assets/images/new/waitingAppo.svg",
+ width: 52.0,
+ height: 52.0,
+ ),
+ mHeight(11),
+ Text(
+ TranslationBase.of(context).whatWaitingAppointment,
+ maxLines: 1,
+ style: TextStyle(fontSize: 17, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 35 / 24),
+ ),
+ mHeight(11),
+ Container(
+ width: MediaQuery.of(context).size.width * 0.8,
+ child: Text(
+ TranslationBase.of(context).waitingAppointmentText1,
+ style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
+ ),
+ ),
+ mHeight(18),
+ Container(
+ width: MediaQuery.of(context).size.width * 0.8,
+ child: Text(
+ TranslationBase.of(context).waitingAppointmentText2,
+ style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
+ ),
+ ),
+ mHeight(24),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Icon(
+ Icons.warning,
+ size: 20,
+ color: Color(0xffA78618),
+ ),
+ mWidth(10),
+ Container(
+ width: MediaQuery.of(context).size.width * 0.7,
+ child: Text(
+ TranslationBase.of(context).waitingAppointmentText3,
+ style: TextStyle(
+ fontSize: 14, fontStyle: FontStyle.italic, fontWeight: FontWeight.w600, color: Color(0xffA78618), letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ bottomSheet: Container(
+ height: 80,
+ color: CustomColors.white,
+ padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 25.0),
+ child: Container(
+ child: DefaultButton(
+ TranslationBase.of(context).continues,
+ () {
+ Navigator.push(
+ context,
+ FadePage(
+ page: WaitingAppointmentVerification(),
+ ),
+ );
+ },
+ color: CustomColors.accentColor,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/BookAppointment/waiting_appointment/waiting_appointment_verification.dart b/lib/pages/BookAppointment/waiting_appointment/waiting_appointment_verification.dart
new file mode 100644
index 00000000..6853c6d9
--- /dev/null
+++ b/lib/pages/BookAppointment/waiting_appointment/waiting_appointment_verification.dart
@@ -0,0 +1,292 @@
+import 'package:barcode_scan2/barcode_scan2.dart';
+import 'package:diplomaticquarterapp/core/model/privilege/ProjectDetailListModel.dart';
+import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
+import 'package:diplomaticquarterapp/pages/BookAppointment/BookConfirm.dart';
+import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart';
+import 'package:diplomaticquarterapp/theme/colors.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/location_util.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_svg/flutter_svg.dart';
+import 'package:intl/intl.dart';
+import 'package:provider/provider.dart';
+
+import '../../../uitl/utils.dart';
+
+class WaitingAppointmentVerification extends StatefulWidget {
+ const WaitingAppointmentVerification({super.key});
+
+ @override
+ State createState() => _WaitingAppointmentVerificationState();
+}
+
+class _WaitingAppointmentVerificationState extends State {
+ String selectedVerificationMethod = "QR";
+
+ late ProjectViewModel projectViewModel;
+ late LocationUtils locationUtils;
+ ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
+
+ @override
+ Widget build(BuildContext context) {
+ projectViewModel = Provider.of(context);
+ return AppScaffold(
+ appBarTitle: TranslationBase.of(context).waitingAppointment,
+ isShowAppBar: true,
+ isShowDecPage: false,
+ showNewAppBar: true,
+ showNewAppBarTitle: true,
+ backgroundColor: CustomColors.appBackgroudGreyColor,
+ body: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ mHeight(11),
+ Text(
+ TranslationBase.of(context).waitingAppointmentVerificationMethod,
+ maxLines: 1,
+ style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.04, height: 35 / 24),
+ ),
+ mHeight(12),
+ Container(
+ width: MediaQuery.of(context).size.width,
+ decoration: containerRadius(Colors.white, 10),
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 0.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ InkWell(
+ onTap: () {
+ setState(() {
+ selectedVerificationMethod = "QR";
+ });
+ },
+ child: Row(
+ children: [
+ Container(
+ width: 20,
+ height: 20,
+ decoration: containerColorRadiusBorderWidth(selectedVerificationMethod == "QR" ? CustomColors.accentColor : Colors.transparent, 100, Colors.grey, 0.5),
+ ),
+ mWidth(6),
+ Container(
+ height: 40.0,
+ width: 40.0,
+ padding: EdgeInsets.all(7.0),
+ child: SvgPicture.asset(
+ "assets/images/new/services/qr_code.svg",
+ ),
+ ),
+ Text(
+ TranslationBase.of(context).pharmaLiveCareScanQR,
+ style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, fontWeight: FontWeight.w600, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
+ ),
+ ],
+ ),
+ ),
+ Divider(),
+ InkWell(
+ onTap: () {
+ setState(() {
+ selectedVerificationMethod = "NFC";
+ });
+ },
+ child: Row(
+ children: [
+ Container(
+ width: 20,
+ height: 20,
+ decoration: containerColorRadiusBorderWidth(selectedVerificationMethod == "NFC" ? CustomColors.accentColor : Colors.transparent, 100, Colors.grey, 0.5),
+ ),
+ mWidth(6),
+ Container(
+ height: 40.0,
+ width: 40.0,
+ padding: EdgeInsets.all(7.0),
+ child: SvgPicture.asset(
+ "assets/images/new/services/contactless.svg",
+ ),
+ ),
+ Text(
+ TranslationBase.of(context).scanNFC,
+ style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, fontWeight: FontWeight.w600, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
+ ),
+ ],
+ ),
+ ),
+ Divider(),
+ InkWell(
+ onTap: () {
+ setState(() {
+ selectedVerificationMethod = "Location";
+ });
+ },
+ child: Row(
+ children: [
+ Container(
+ width: 20,
+ height: 20,
+ decoration: containerColorRadiusBorderWidth(selectedVerificationMethod == "Location" ? CustomColors.accentColor : Colors.transparent, 100, Colors.grey, 0.5),
+ ),
+ mWidth(6),
+ Container(
+ height: 40.0,
+ width: 40.0,
+ padding: EdgeInsets.all(7.0),
+ child: SvgPicture.asset(
+ "assets/images/new/services/location.svg",
+ ),
+ ),
+ Text(
+ TranslationBase.of(context).checkInViaLocation,
+ style: TextStyle(fontSize: 14, color: CustomColors.textDarkColor, fontWeight: FontWeight.w600, letterSpacing: -1.04, height: 35 / 24, overflow: TextOverflow.clip),
+ ),
+ ],
+ ),
+ ),
+ mHeight(6),
+ ],
+ ),
+ ),
+ ),
+ mHeight(12),
+ Container(
+ width: MediaQuery.of(context).size.width,
+ decoration: containerRadius(Colors.white, 10),
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 0.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ mHeight(12),
+ Text(
+ TranslationBase.of(context).howToUseVerificationMethod,
+ maxLines: 1,
+ style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -1.04, height: 35 / 24),
+ ),
+ mHeight(12),
+ Image.asset(
+ 'assets/images/new/NFCCheckIn_QR_gps_HMG.png',
+ fit: BoxFit.fitWidth,
+ width: MediaQuery.of(context).size.width,
+ ),
+ mHeight(12),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ bottomSheet: Container(
+ height: 80,
+ color: CustomColors.white,
+ padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 25.0),
+ child: Container(
+ child: DefaultButton(
+ TranslationBase.of(context).continues,
+ () {
+ startVerification();
+ },
+ color: CustomColors.accentColor,
+ ),
+ ),
+ ),
+ );
+ }
+
+ startVerification() {
+ switch (selectedVerificationMethod) {
+ case "QR":
+ startQRCodeScan();
+ break;
+ case "NFC":
+ startNFCScan();
+ break;
+ case "Location":
+ startLocationCheckIn();
+ break;
+ }
+ }
+
+ checkScannedNFCAndQRCode(String nfcId) {
+ GifLoaderDialogUtils.showMyDialog(context);
+ DoctorsListService service = new DoctorsListService();
+ service.checkScannedNFCAndQRCode(nfcId, projectViewModel.waitingAppointmentDoctor!.projectID!).then((res) {
+ GifLoaderDialogUtils.hideDialog(context);
+ projectViewModel.setWaitingAppointmentNFCCode(nfcId);
+ if (res["returnValue"] == 1) {
+ navigateToBookConfirm(context);
+ } else {
+ AppToast.showErrorToast(message: "Invalid verification point scanned.");
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ print(err);
+ });
+ }
+
+ Future navigateToBookConfirm(context) async {
+ final DateFormat formatter = DateFormat('yyyy-MM-dd');
+ Navigator.push(
+ context,
+ FadePage(
+ page: BookConfirm(
+ doctor: projectViewModel.waitingAppointmentDoctor!,
+ isLiveCareAppointment: false,
+ selectedDate: formatter.format(DateTime.now()),
+ selectedTime: TranslationBase.of(context).waitingAppointment,
+ initialSlotDuration: 15,
+ isWalkinAppointment: true,
+ ),
+ ),
+ );
+ }
+
+ startLocationCheckIn() async {
+ locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context);
+ locationUtils.getCurrentLocation(callBack: (value) {
+ projectDetailListModel = Utils.getProjectDetailObj(projectViewModel, projectViewModel.waitingAppointmentProjectID);
+ double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
+ projectViewModel.setWaitingAppointmentNFCCode(projectDetailListModel.checkInQrCode!);
+ print(dist);
+ if (dist <= projectDetailListModel.geofenceRadius!) {
+ navigateToBookConfirm(context);
+ } else {
+ AppToast.showErrorToast(message: TranslationBase.of(context).locationCheckInError);
+ }
+ });
+ }
+
+ startNFCScan() {
+ Future.delayed(const Duration(milliseconds: 500), () {
+ showNfcReader(context, onNcfScan: (String nfcId) {
+ Future.delayed(const Duration(milliseconds: 100), () {
+ checkScannedNFCAndQRCode(nfcId);
+ });
+ }, onCancel: () {
+ // Navigator.of(context).pop();
+ // locator().todoList.to_do_list_nfc_cancel(widget.appointment!);
+ });
+ });
+ }
+
+ startQRCodeScan() async {
+ String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
+ if (onlineCheckInQRCode != "") {
+ checkScannedNFCAndQRCode(onlineCheckInQRCode);
+ } else {}
+ }
+}
diff --git a/lib/pages/BookAppointment/widgets/reminder_dialog.dart b/lib/pages/BookAppointment/widgets/reminder_dialog.dart
index a16876db..b3c39861 100644
--- a/lib/pages/BookAppointment/widgets/reminder_dialog.dart
+++ b/lib/pages/BookAppointment/widgets/reminder_dialog.dart
@@ -1,6 +1,7 @@
import 'dart:io';
import 'package:diplomaticquarterapp/analytics/google-analytics.dart';
+import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/locator.dart';
import 'package:diplomaticquarterapp/services/permission/permission_service.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
@@ -44,10 +45,10 @@ showReminderDialog(BuildContext context, DateTime dateTime, String doctorName, S
}
}
-Future _showReminderDialog(BuildContext context, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
+Future _showReminderDialog(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
{required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async {
return showDialog(
- context: context,
+ context: providedContext,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return Dialog(
@@ -81,7 +82,7 @@ Future _showReminderDialog(BuildContext context, DateTime dateTime, String
if (onMultiDateSuccess == null) {
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
await calendarUtils.createOrUpdateEvent(
- title: title ?? TranslationBase.of(context).reminderTitle + " " + doctorName,
+ title: title ?? TranslationBase.of(providedContext).reminderTitle + " " + doctorName,
description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted,
scheduleDateTime: dateTime,
eventId: eventId);
diff --git a/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart b/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart
index a9a16ce7..88be72dd 100644
--- a/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart
+++ b/lib/pages/Covid-DriveThru/Covid-TimeSlots.dart
@@ -260,7 +260,7 @@ class _CovidTimeSlotsState extends State with TickerProviderStat
_events.forEach((key, value) {
final DateTime startTime = DateTime(key.year, key.month, key.day, 9, 0, 0);
final DateTime endTime = startTime.add(const Duration(minutes: 20));
- meetings.add(Meeting("", startTime, endTime, CustomColors.green, false));
+ meetings.add(Meeting("", startTime, endTime, CustomColors.green, false, ""));
});
return meetings;
}
@@ -584,11 +584,12 @@ class MeetingDataSource extends CalendarDataSource {
}
class Meeting {
- Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay);
+ Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay, this.notes);
String eventName;
DateTime from;
DateTime to;
Color background;
bool isAllDay;
+ String notes;
}
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..313d4551
--- /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 ?? ""
+ : 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/components/inpatient_pending_advance_payment.dart b/lib/pages/InPatientServices/components/inpatient_pending_advance_payment.dart
index 82e6ab96..e636e810 100644
--- a/lib/pages/InPatientServices/components/inpatient_pending_advance_payment.dart
+++ b/lib/pages/InPatientServices/components/inpatient_pending_advance_payment.dart
@@ -255,7 +255,8 @@ class _InPatientPendingAdvancePaymentState extends State[
+ 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..2ce47152 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) {
@@ -272,7 +308,7 @@ class _InPatientServicesHomeState extends State {
void openBirthNotificationsPage(BuildContext context) {
ClinicListService service = new ClinicListService();
GifLoaderDialogUtils.showMyDialog(context);
- service.getBirthNotification(projectViewModel.user.patientID!, context).then((res) {
+ service.getBirthNotification(projectViewModel.user.patientID!, projectViewModel.isArabic ? 1 : 2, context).then((res) {
GifLoaderDialogUtils.hideDialog(context);
if (res["MessageStatus"] == 1) {
print(res['birthNotification']);
@@ -285,10 +321,14 @@ class _InPatientServicesHomeState extends State {
});
}
+ void openPatientGeneralConsent() {
+ Navigator.push(context, FadePage(page: InPatientGeneralConsent()));
+ }
+
void openGeneralInstructions(BuildContext context) {
ClinicListService service = new ClinicListService();
GifLoaderDialogUtils.showMyDialog(context);
- service.getGeneralInstructions(projectViewModel.inPatientProjectID, context).then((res) {
+ service.getGeneralInstructions(projectViewModel.inPatientProjectID, projectViewModel.isArabic ? 1 : 2, context).then((res) {
if (res['generalInstructions'].length != 0) {
List getGeneralInstructionsList = [];
res['generalInstructions'].forEach((v) {
@@ -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) {
@@ -308,7 +349,7 @@ class _InPatientServicesHomeState extends State