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 { void openMedicalInstructions(BuildContext context) { ClinicListService service = new ClinicListService(); GifLoaderDialogUtils.showMyDialog(context); - service.getMedicalInstructions(projectViewModel.inPatientProjectID, context).then((res) { + service.getMedicalInstructions(projectViewModel.inPatientProjectID, projectViewModel.isArabic ? 1 : 2, context).then((res) { if (res['MedicalInstruction'] != null && res['MedicalInstruction'].length != 0) { List getMedicalInstructionsList = []; res['MedicalInstruction'].forEach((v) { @@ -334,6 +375,7 @@ class _InPatientServicesHomeState extends State { projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.projectID! : projectViewModel.getAdmissionRequestInfoResponseModel.projectId!, projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionNo! : 0, projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionRequestNo! : projectViewModel.getAdmissionRequestInfoResponseModel.admissionRequestNo!, + projectViewModel.isArabic ? 1 : 2, context) .then((res) { GifLoaderDialogUtils.hideDialog(context); diff --git a/lib/pages/MyAppointments/AppointmentDetails.dart b/lib/pages/MyAppointments/AppointmentDetails.dart index 7d552c4f..db6eb173 100644 --- a/lib/pages/MyAppointments/AppointmentDetails.dart +++ b/lib/pages/MyAppointments/AppointmentDetails.dart @@ -10,6 +10,7 @@ import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel. import 'package:diplomaticquarterapp/models/header_model.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/BookConfirm.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/components/DocAvailableAppointments.dart'; +import 'package:diplomaticquarterapp/pages/BookAppointment/waiting_appointment/waiting_appointment_info.dart'; import 'package:diplomaticquarterapp/pages/MyAppointments/SchedulePage.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; @@ -299,23 +300,68 @@ class _AppointmentDetailsState extends State with SingleTick } void goToBookConfirm() { - if (DocAvailableAppointments.areSlotsAvailable) - navigateToBookConfirm(context); - else - AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot); + if (DocAvailableAppointments.selectedTime == TranslationBase.of(context).waitingAppointment) { + canPayForWalkInAppointment(); + } else { + if (DocAvailableAppointments.areSlotsAvailable) + navigateToBookConfirm(context); + else + AppToast.showErrorToast(message: TranslationBase.of(context).selectSlot); + } + } + + canPayForWalkInAppointment() { + DoctorsListService service = new DoctorsListService(); + GifLoaderDialogUtils.showMyDialog(context); + service.canPayForWalkInAppointment(widget.appo.clinicID!, widget.appo.projectID!, widget.appo.doctorID!).then((res) { + GifLoaderDialogUtils.hideDialog(context); + navigateToWaitingAppointment(context); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err, localContext: context); + print(err); + }); + } + + Future navigateToWaitingAppointment(context) async { + DoctorList doctor = new DoctorList(); + doctor.name = widget.appo.doctorNameObj; + doctor.clinicID = widget.appo.clinicID; + doctor.projectID = widget.appo.projectID; + doctor.doctorID = widget.appo.doctorID; + doctor.clinicName = widget.appo.clinicName; + doctor.projectName = widget.appo.projectName; + doctor.doctorTitle = widget.appo.doctorTitle; + doctor.doctorImageURL = widget.appo.doctorImageURL; + doctor.speciality = widget.appo.doctorSpeciality; + doctor.nationalityFlagURL = ""; + doctor.doctorRate = widget.appo.doctorRate; + doctor.noOfPatientsRate = widget.appo.noOfPatientsRate; + + projectViewModel?.setWaitingAppointmentProjectID(widget.appo.projectID!); + projectViewModel?.setWaitingAppointmentDoctor(doctor); + Navigator.push( + context, + FadePage( + page: WaitingAppointmentInfo(), + ), + ); } Future navigateToBookConfirm(context) async { Navigator.push( - context, - FadePage( - page: BookConfirm( + context, + FadePage( + page: BookConfirm( doctor: getDoctorObject(), isLiveCareAppointment: widget.appo.isLiveCareAppointment!, selectedDate: DocAvailableAppointments.selectedDate!, selectedTime: DocAvailableAppointments.selectedTime!, initialSlotDuration: 0, - ))); + isWalkinAppointment: false, + ), + ), + ); } void getDoctorRatingsDetails() { diff --git a/lib/pages/MyAppointments/models/BookedButtons.dart b/lib/pages/MyAppointments/models/BookedButtons.dart index 66e4366f..39aed7cc 100644 --- a/lib/pages/MyAppointments/models/BookedButtons.dart +++ b/lib/pages/MyAppointments/models/BookedButtons.dart @@ -39,6 +39,7 @@ class BookedButtons { "icon": "hosp_location.svg", "caller": "navigateToProject", }, - {"title": TranslationBase.of(AppGlobal.context).online, "subtitle": TranslationBase.of(AppGlobal.context).payment, "icon": "online_payment.svg", "caller": "goToTodoList"} + {"title": TranslationBase.of(AppGlobal.context).online, "subtitle": TranslationBase.of(AppGlobal.context).payment, "icon": "online_payment.svg", "caller": "goToTodoList"}, + // {"title": TranslationBase.of(AppGlobal.context).clinic, "subtitle": TranslationBase.of(AppGlobal.context).locationa, "icon": "hosp_location.svg", "caller": "goToNavigation"} ]; } diff --git a/lib/pages/MyAppointments/models/ConfirmedButtons.dart b/lib/pages/MyAppointments/models/ConfirmedButtons.dart index 7ba3ce1c..d49723e9 100644 --- a/lib/pages/MyAppointments/models/ConfirmedButtons.dart +++ b/lib/pages/MyAppointments/models/ConfirmedButtons.dart @@ -19,6 +19,7 @@ class ConfirmedButtons { // "icon": "assets/images/new-design/generate_visit_ticket.png", // "caller": "visitTicket" // }, - {"title": TranslationBase.of(AppGlobal.context).online, "subtitle": TranslationBase.of(AppGlobal.context).payment, "icon": "online_payment.svg", "caller": "goToTodoList"} + {"title": TranslationBase.of(AppGlobal.context).online, "subtitle": TranslationBase.of(AppGlobal.context).payment, "icon": "online_payment.svg", "caller": "goToTodoList"}, + // {"title": TranslationBase.of(AppGlobal.context).clinic, "subtitle": TranslationBase.of(AppGlobal.context).locationa, "icon": "hosp_location.svg", "caller": "goToNavigation"} ]; } diff --git a/lib/pages/MyAppointments/widgets/AppointmentActions.dart b/lib/pages/MyAppointments/widgets/AppointmentActions.dart index 6347d3f4..feb7a514 100644 --- a/lib/pages/MyAppointments/widgets/AppointmentActions.dart +++ b/lib/pages/MyAppointments/widgets/AppointmentActions.dart @@ -27,9 +27,11 @@ import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescription_it import 'package:diplomaticquarterapp/pages/medical/radiology/radiology_details_page.dart'; import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sign_details_screen.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/uitl/app-permissions.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/penguin_method_channel.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart'; @@ -40,6 +42,7 @@ import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; import 'package:huawei_map/huawei_map.dart' as hmsMap; import 'package:intl/intl.dart'; import 'package:map_launcher/map_launcher.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -178,6 +181,31 @@ class _AppointmentActionsState extends State { navigateToInsertComplaint(); locator().appointment.appointment_detail_action(appointment: widget.appo, action: 'raise complaint'); break; + + case "goToNavigation": + initPenguinSDK(); + locator().appointment.appointment_detail_action(appointment: widget.appo, action: 'navigate to clinic'); + break; + } + } + + initPenguinSDK() async { + NavigationClinicDetails data = NavigationClinicDetails(); + data.clinicId = widget.appo.clinicID.toString(); + // data.clinicId = "49"; + data.patientId = widget.appo.patientID.toString(); + data.projectId = widget.appo.projectID.toString(); + final bool permited = await AppPermission.askPenguinPermissions(); + if (!permited) { + Map statuses = await [ + Permission.location, + Permission.bluetooth, + Permission.bluetoothConnect, + Permission.bluetoothScan, + Permission.activityRecognition, + ].request().whenComplete(() { + PenguinMethodChannel().launch("penguin", widget.projectViewModel!.isArabic ? "ar" : "en", widget.projectViewModel!.authenticatedUserObject.user.patientID.toString(), details: data); + }); } } diff --git a/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart b/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart index 38c09047..9660a616 100644 --- a/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart +++ b/lib/pages/ToDoList/ObGyne/ObGyne-TimeSlots.dart @@ -253,7 +253,7 @@ class _CovidTimeSlotsState extends State with TickerProviderSta _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; } @@ -534,11 +534,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/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index 31ad875e..c225987c 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -29,10 +29,12 @@ import 'package:diplomaticquarterapp/services/livecare_services/livecare_provide 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-permissions.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/penguin_method_channel.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/uitl/utils_new.dart'; @@ -50,6 +52,7 @@ import 'package:flutter_countdown_timer/current_remaining_time.dart'; import 'package:flutter_countdown_timer/flutter_countdown_timer.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; class ToDo extends StatefulWidget { @@ -354,23 +357,56 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.48, height: 25 / 16), ), ), - InkWell( - onTap: () { - navigateToAppointmentDetails(context, appoList[index]); - }, - child: Padding( - padding: const EdgeInsets.only(top: 0.0), - child: Text( - TranslationBase.of(context).moreDetails, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w600, - color: CustomColors.accentColor, - letterSpacing: -0.48, - height: 25 / 16, - decoration: TextDecoration.underline), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + onTap: () { + navigateToAppointmentDetails(context, appoList[index]); + }, + child: Padding( + padding: const EdgeInsets.only(top: 0.0), + child: Text( + TranslationBase.of(context).moreDetails, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w600, + color: CustomColors.accentColor, + letterSpacing: -0.48, + height: 25 / 16, + decoration: TextDecoration.underline), + ), + ), ), - ), + if (projectViewModel.isIndoorNavigationEnabled && projectViewModel.havePrivilege(107) && appoList[index].projectID == 130) + InkWell( + onTap: () { + NavigationClinicDetails data = NavigationClinicDetails(); + data.clinicId = appoList[index].clinicID.toString(); + // data.clinicId = "46"; + data.patientId = appoList[index].patientID.toString(); + data.projectId = appoList[index].projectID.toString(); + initPenguinSDK(data); + }, + child: Column( + children: [ + SvgPicture.asset( + "assets/images/new/Indoor_nav_appo.svg", + ), + Text( + TranslationBase.of(context).clinicLocation, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w600, + color: CustomColors.accentColor, + letterSpacing: -0.48, + height: 25 / 16, + decoration: TextDecoration.underline), + ), + ], + ), + ), + ], ), ], ), @@ -530,6 +566,21 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { ); } + initPenguinSDK(NavigationClinicDetails data) async { + final bool permited = await AppPermission.askPenguinPermissions(); + if (!permited) { + Map statuses = await [ + Permission.location, + Permission.bluetooth, + Permission.bluetoothConnect, + Permission.bluetoothScan, + Permission.activityRecognition, + ].request().whenComplete(() { + PenguinMethodChannel().launch("penguin", projectViewModel.isArabic ? "ar" : "en", projectViewModel.authenticatedUserObject.user.patientID.toString(), details: data); + }); + } + } + String getNextActionImage(nextAction) { switch (nextAction) { case 0: @@ -949,7 +1000,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { okText: "Update insurance", cancelText: "Continue as cash", okFunction: () => {openUpdateInsurance()}, - cancelFunction: () => {continueAsCash(appo)}); + cancelFunction: () => {continueAsCash(appo, false)}); dialog.showAlertDialog(context); } }).catchError((err) { @@ -963,19 +1014,24 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { Navigator.push(context, FadePage(page: InsuranceUpdate())); } - void continueAsCash(AppoitmentAllHistoryResultList appo) { + void continueAsCash(AppoitmentAllHistoryResultList appo, bool isLiveCareAppointment) { DoctorsListService service = new DoctorsListService(); GifLoaderDialogUtils.showMyDialog(context); service.convertPatientToCash(appo.projectID!).then((res) { GifLoaderDialogUtils.hideDialog(context); if (res["MessageStatus"] == 1) { - getPatientShare(context, appo); + if (isLiveCareAppointment) { + getLiveCareAppointmentPatientShare(context, service, appo); + } else { + getPatientShare(context, appo); + } // getToDoCount(); } else { AppToast.showErrorToast(message: res["ErrorEndUserMessage"]); } }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); print(err); }); } @@ -1015,7 +1071,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { okText: TranslationBase.of(context).updateInsuranceText, cancelText: TranslationBase.of(context).continueCash, okFunction: () => {openUpdateInsurance()}, - cancelFunction: () => {continueAsCash(appo)}); + cancelFunction: () => {continueAsCash(appo, false)}); dialog.showAlertDialog(context); } } @@ -1028,11 +1084,40 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { } getLiveCareAppointmentPatientShare(context, DoctorsListService service, AppoitmentAllHistoryResultList appo) { + String errorMsg = ""; GifLoaderDialogUtils.showMyDialog(context); service.getLiveCareAppointmentPatientShare(appo.appointmentNo.toString(), appo.clinicID, appo.projectID, projectViewModel.isArabic ? 1 : 2, context).then((res) { GifLoaderDialogUtils.hideDialog(context); widget.patientShareResponse = new PatientShareResponse.fromJson(res); - openPaymentDialog(appo, widget.patientShareResponse!); + + isInsured = res["IsInsured"]; + isEligible = res["IsEligible"]; + isCash = res["IsCash"]; + + if (isCash) { + openPaymentDialog(appo, widget.patientShareResponse!); + } else { + if (isInsured && isEligible) { + openPaymentDialog(appo, widget.patientShareResponse!); + } 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(appo, true)}); + dialog.showAlertDialog(context); + } + } + + // openPaymentDialog(appo, widget.patientShareResponse!); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); AppToast.showErrorToast(message: err); @@ -1114,7 +1199,6 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { projectViewModel.analytics.todoList.to_do_list_cancel_payment_details(appo); } }); - projectViewModel.analytics.todoList.to_do_list_pay_now(appo); } @@ -1464,7 +1548,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { }).catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); + AppToast.showErrorToast(message: err.toString()); }); } diff --git a/lib/pages/conference/zoom/call_screen.dart b/lib/pages/conference/zoom/call_screen.dart index daa70a2c..6de59807 100644 --- a/lib/pages/conference/zoom/call_screen.dart +++ b/lib/pages/conference/zoom/call_screen.dart @@ -472,7 +472,7 @@ class _CallScreenState extends State { ], ), ); - if (errorType == Errors.SessionJoinFailed) { + if (errorType == Errors.SessionJoinFailed || errorType == Errors.SessionDisconnecting) { Timer( const Duration(milliseconds: 1000), () => Navigator.pop(context), diff --git a/lib/pages/insurance/insurance_update_screen.dart b/lib/pages/insurance/insurance_update_screen.dart index 191170ef..4c4d5686 100644 --- a/lib/pages/insurance/insurance_update_screen.dart +++ b/lib/pages/insurance/insurance_update_screen.dart @@ -167,7 +167,7 @@ class _InsuranceUpdateState extends State with SingleTickerProv Container( margin: EdgeInsets.only(top: 6.5, left: 2.0), child: Text( - model.insuranceUpdate[index].statusDescription!, + model.insuranceUpdate[index].statusDescription ?? "", style: TextStyle( fontSize: 10, fontWeight: FontWeight.w600, diff --git a/lib/pages/landing/fragments/home_page_fragment2.dart b/lib/pages/landing/fragments/home_page_fragment2.dart index c1c922ac..d0c32fca 100644 --- a/lib/pages/landing/fragments/home_page_fragment2.dart +++ b/lib/pages/landing/fragments/home_page_fragment2.dart @@ -45,6 +45,9 @@ class _HomePageFragment2State extends State { void initState() { // TODO: implement initState super.initState(); + + // getPatientAppointmentHistory1(); + // getFamilyFiles(); } initialiseHmgServices(bool isLogin) { @@ -52,7 +55,12 @@ class _HomePageFragment2State extends State { hmgServices.add(HmgServices(0, TranslationBase.of(context).book, TranslationBase.of(context).appointmentLabel, "assets/images/new/book appointment.svg", isLogin)); hmgServices.add(HmgServices(1, TranslationBase.of(context).liveCare, TranslationBase.of(context).onlineConsulting, "assets/images/new/Live_Care.svg", isLogin)); - hmgServices.add(HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + + projectViewModel.isIndoorNavigationEnabled + ? hmgServices.add(HmgServices(2, TranslationBase.of(context).hospitalNavigationTitle, TranslationBase.of(context).hospitalNavigationSubtitle, "assets/images/new/indoor_nav_home.svg", isLogin)) + : hmgServices.add(HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + + hmgServices.add(HmgServices(9, TranslationBase.of(context).emergency, TranslationBase.of(context).checkinOptions, "assets/images/new/emergency.svg", isLogin)); hmgServices.add(HmgServices(3, TranslationBase.of(context).hhcHome, TranslationBase.of(context).healthCare, "assets/images/new/HHC.svg", isLogin)); hmgServices.add(HmgServices(4, TranslationBase.of(context).checkup, TranslationBase.of(context).comprehensive, "assets/images/new/comprehensive_checkup.svg", isLogin)); hmgServices.add(HmgServices(5, TranslationBase.of(context).online, TranslationBase.of(context).payment, "assets/images/new/paymentMethods.png", isLogin)); @@ -66,9 +74,17 @@ class _HomePageFragment2State extends State { // hmgServices.add(new HmgServices(0, TranslationBase.of(context).liveCare, TranslationBase.of(context).onlineConsulting, "assets/images/new/Live_Care.svg", isLogin)); // hmgServices.add(new HmgServices(1, TranslationBase.of(context).covidTest, TranslationBase.of(context).driveThru, "assets/images/new/CoronaIcon.svg", isLogin)); // hmgServices.add(new HmgServices(2, TranslationBase.of(context).online, TranslationBase.of(context).payment, "assets/images/new/paymentMethods.png", isLogin)); + + projectViewModel.isIndoorNavigationEnabled + ? hmgServices.add(HmgServices(2, TranslationBase.of(context).hospitalNavigationTitle, TranslationBase.of(context).hospitalNavigationSubtitle, "assets/images/new/indoor_nav_home.svg", isLogin)) + : hmgServices.add(HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + + hmgServices.add(new HmgServices(9, TranslationBase.of(context).emergency, TranslationBase.of(context).checkinOptions, "assets/images/new/emergency.svg", isLogin)); hmgServices.add(new HmgServices(3, TranslationBase.of(context).hhcHome, TranslationBase.of(context).healthCare, "assets/images/new/HHC.svg", isLogin)); hmgServices.add(new HmgServices(4, TranslationBase.of(context).checkup, TranslationBase.of(context).comprehensive, "assets/images/new/comprehensive_checkup.svg", isLogin)); - hmgServices.add(new HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + + // hmgServices.add(new HmgServices(2, TranslationBase.of(context).emergencyTitle, TranslationBase.of(context).emergencySubtitle, "assets/images/new/emergency.svg", isLogin)); + hmgServices.add(new HmgServices(6, TranslationBase.of(context).ereferralTitle, TranslationBase.of(context).ereferralSubtitle, "assets/images/new/E_Referral.svg", isLogin)); hmgServices.add(new HmgServices(7, "H\u2082O", TranslationBase.of(context).dailyWater, "assets/images/new/h2o.svg", isLogin)); hmgServices.add(new HmgServices(8, TranslationBase.of(context).connectTitle, TranslationBase.of(context).connectSubtitle, "assets/images/new/reach_us.svg", isLogin)); @@ -296,15 +312,16 @@ class _HomePageFragment2State extends State { child: ServicesView( new HmgServices(23, TranslationBase.of(context).InPatient, TranslationBase.of(context).inPatientServices, "assets/images/new/InPatient.svg", false), 23, - true)), + true, + projectViewModel)), ), ), Expanded( flex: 4, child: AspectRatio( aspectRatio: 1.0, - child: ServicesView( - new HmgServices(5, TranslationBase.of(context).online, TranslationBase.of(context).payment, "assets/images/new/paymentMethods.png", false), 2, true)), + child: ServicesView(new HmgServices(5, TranslationBase.of(context).online, TranslationBase.of(context).payment, "assets/images/new/paymentMethods.png", false), 2, + true, projectViewModel)), ), ], ), @@ -322,7 +339,7 @@ class _HomePageFragment2State extends State { itemCount: hmgServices.length, padding: EdgeInsets.zero, itemBuilder: (BuildContext context, int index) { - return ServicesView(hmgServices[index], index, true); + return ServicesView(hmgServices[index], index, true, projectViewModel); }, ), ), @@ -341,7 +358,8 @@ class _HomePageFragment2State extends State { itemCount: hmgServices.length, padding: EdgeInsets.zero, itemBuilder: (BuildContext context, int index) { - return ServicesView(hmgServices[index], index, true); + return ServicesView(hmgServices[index], index, true, projectViewModel, + isLocked: (hmgServices[index].action == 2 && projectViewModel.isIndoorNavigationEnabled) ? !projectViewModel.havePrivilege(107) : false); }, ), ), @@ -489,8 +507,7 @@ class _HomePageFragment2State extends State { flex: 1, child: InkWell( onTap: () { - if (projectViewModel.havePrivilege(100)) - widget.onPharmacyClick!(); + if (projectViewModel.havePrivilege(100)) widget.onPharmacyClick!(); }, child: Stack(children: [ Container( diff --git a/lib/pages/landing/home_page_2.dart b/lib/pages/landing/home_page_2.dart index 9b52958b..af02e200 100644 --- a/lib/pages/landing/home_page_2.dart +++ b/lib/pages/landing/home_page_2.dart @@ -33,6 +33,11 @@ class _HomePageState2 extends State { PharmacyModuleViewModel pharmacyModuleViewModel = locator(); late ProjectViewModel projectViewModel; + @override + void initState() { + super.initState(); + } + @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 256662a3..05d90571 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -44,7 +44,7 @@ import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_app_icon_badge/flutter_app_icon_badge.dart'; +// import 'package:flutter_app_icon_badge/flutter_app_icon_badge.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_zoom_videosdk/native/zoom_videosdk.dart'; @@ -76,8 +76,7 @@ class LandingPage extends StatefulWidget { class _LandingPageState extends State with WidgetsBindingObserver { var authProvider = new AuthProvider(); - AppointmentRateViewModel appointmentRateViewModel = - locator(); + AppointmentRateViewModel appointmentRateViewModel = locator(); int currentTab = 0; late PageController pageController; @@ -94,8 +93,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { bool _showBottomNavigationBar = true; ///inject the user data - AuthenticatedUserObject authenticatedUserObject = - locator(); + AuthenticatedUserObject authenticatedUserObject = locator(); final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; final authService = new AuthProvider(); @@ -122,22 +120,17 @@ class _LandingPageState extends State with WidgetsBindingObserver { "appointmentdate": "2022-01-19", "appointmenttime": "12:10", "PatientName": "Testing", - "session_id": - "1_MX40NjIwOTk2Mn5-MTY0NzI1NjYxNDI2OX5ySXhlVjZjam13RFdMVmdleWVsSDhzQkx-fg", + "session_id": "1_MX40NjIwOTk2Mn5-MTY0NzI1NjYxNDI2OX5ySXhlVjZjam13RFdMVmdleWVsSDhzQkx-fg", "token": "T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9OGMyY2IyYWFiZmZmMzI4ZmEwMjgxNDdmMGFhZGI0N2JiZjdmZWY4MjpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWTBOekkxTmpZeE5ESTJPWDV5U1hobFZqWmphbTEzUkZkTVZtZGxlV1ZzU0RoelFreC1mZyZjcmVhdGVfdGltZT0xNjQ3MjU2NjE0Jm5vbmNlPTAuMjgzNDgyNjM1NDczNjQ2OCZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjQ3MjU4NDE0JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9", - "DoctorImageURL": - "https://image.shutterstock.com/image-vector/sample-stamp-square-grunge-sign-260nw-1474408826.jpg", + "DoctorImageURL": "https://image.shutterstock.com/image-vector/sample-stamp-square-grunge-sign-260nw-1474408826.jpg", "callerID": "9920", "PatientID": "1231755", "is_call": "true" }; void _requestIOSPermissions() { - flutterLocalNotificationsPlugin - .resolvePlatformSpecificImplementation< - IOSFlutterLocalNotificationsPlugin>() - ?.requestPermissions( + flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions( alert: true, badge: true, sound: true, @@ -153,8 +146,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { return Future.value(false); } else { DateTime now = DateTime.now(); - if (currentBackPressTime == null || - now.difference(currentBackPressTime!) > Duration(seconds: 2)) { + if (currentBackPressTime == null || now.difference(currentBackPressTime!) > Duration(seconds: 2)) { currentBackPressTime = now; AppToast.showToast(message: TranslationBase.of(context).pressAgain); return Future.value(false); @@ -169,18 +161,14 @@ class _LandingPageState extends State with WidgetsBindingObserver { List imagesInfo = []; imagesInfo.add( ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/0.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/0.png'), + imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/0.png', + imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/0.png'), ); imagesInfo.add( ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/1.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/1.png'), + imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/en/1.png', + imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/family-file/ar/1.png'), ); Navigator.push( @@ -199,11 +187,8 @@ class _LandingPageState extends State with WidgetsBindingObserver { } if (tab == 4) { List imagesInfo = []; - imagesInfo.add(ImagesInfo( - imageEn: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/en/0.png', - imageAr: - 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/ar/0.png')); + imagesInfo.add( + ImagesInfo(imageEn: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/en/0.png', imageAr: 'https://hmgwebservices.com/Images/MobileApp/images-info-home/todo/ar/0.png')); Navigator.push( context, @@ -248,8 +233,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { }); }); - projectViewModel.analytics.bottomTabNavigation - .log(tabIndex: tab, isLoggedIn: projectViewModel.isLogin); + projectViewModel.analytics.bottomTabNavigation.log(tabIndex: tab, isLoggedIn: projectViewModel.isLogin); } getToDoCount() { @@ -260,11 +244,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { print(res['AppointmentActiveNumber']); if (res['MessageStatus'] == 1) { // toDoProvider.setState(res['AppointmentActiveNumber'], true, toDoProvider.notificationsCount); - toDoProvider.setState( - res['AppointmentActiveNumber'], - res['AncillaryOrderListCount'], - true, - toDoProvider.notificationsCount); + toDoProvider.setState(res['AppointmentActiveNumber'], res['AncillaryOrderListCount'], true, toDoProvider.notificationsCount); } else {} }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); @@ -303,10 +283,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addPostFrameCallback((_) { if (projectViewModel.isLogin && !projectViewModel.isLoginChild) { - int languageID = - Provider.of(context, listen: false).isArabic - ? 1 - : 2; + int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; familyFileProvider.getSharedRecordByStatus(languageID); } // Future.delayed(Duration(seconds: 3)).then((result) async { @@ -322,31 +299,34 @@ class _LandingPageState extends State with WidgetsBindingObserver { // HMGNetworkConnectivity(context).start(); _firebaseMessaging.getToken().then((String? token) { - // print("Firebase Token: " + token!); - sharedPref.setString(PUSH_TOKEN, token!); - if (Platform.isIOS) { - FirebaseMessaging.instance.getAPNSToken().then((value) { - print("Push APNS getToken: " + value!); - AppSharedPreferences().setString(APNS_TOKEN, value); - AppSharedPreferences().setString(ONESIGNAL_APNS_TOKEN, value); - }); - // voIPKit.getVoIPToken().then((value) { - // print('🎈 example: getVoIPToken: $value'); - // AppSharedPreferences().setString(APNS_TOKEN, value!); - // // getOneSignalVOIPToken(value); - // }); - } + // print("Firebase Token: " + token!); + sharedPref.setString(PUSH_TOKEN, token!); + if (Platform.isIOS) { + FirebaseMessaging.instance.getAPNSToken().then((value) { + print("Push APNS getToken: " + value!); + AppSharedPreferences().setString(APNS_TOKEN, value); + AppSharedPreferences().setString(ONESIGNAL_APNS_TOKEN, value); + }); + // voIPKit.getVoIPToken().then((value) { + // print('🎈 example: getVoIPToken: $value'); + // AppSharedPreferences().setString(APNS_TOKEN, value!); + // // getOneSignalVOIPToken(value); + // }); + } if (token != null) { DEVICE_TOKEN = token; if (!projectViewModel.isLoginChild) { checkUserStatus(token); } } + }).catchError((err) { + print(err); }); startZoom(); // HMG_Geofencing(context).loadZones().then((instance) => instance.init()); } - void startZoom(){ + + void startZoom() { var zoom = ZoomVideoSdk(); InitConfig initConfig = InitConfig( domain: "zoom.us", @@ -476,20 +456,14 @@ class _LandingPageState extends State with WidgetsBindingObserver { getNotificationCount(token) async { if (await sharedPref.getObject(USER_PROFILE) != null) { - var data = - AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); + var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); if (data != null) { authService.getDashboard().then((value) => { if (value != null) { setState(() { - notificationCount = value['List_PatientDashboard'][0] - ['UnreadPatientNotificationCount'] > - 99 - ? '99+' - : value['List_PatientDashboard'][0] - ['UnreadPatientNotificationCount'] - .toString(); + notificationCount = + value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString(); model.setState(model.count, 0, true, notificationCount); sharedPref.setString(NOTIFICATION_COUNT, notificationCount); }) @@ -519,11 +493,9 @@ class _LandingPageState extends State with WidgetsBindingObserver { getText(currentTab).toUpperCase(), style: TextStyle( fontWeight: FontWeight.bold, - color: currentTab == 0 - ? CustomColors.backgroudGreyColor - : Theme.of(context).textTheme.headline1!.color, - fontFamily: - projectViewModel.isArabic ? 'Cairo' : 'Poppins'), + color: currentTab == 0 ? CustomColors.backgroudGreyColor : CustomColors.accentColor, + // : Theme.of(context).textTheme.headline1!.color, + fontFamily: projectViewModel.isArabic ? 'Cairo' : 'Poppins'), // bold: true, ), leading: Builder( @@ -532,14 +504,10 @@ class _LandingPageState extends State with WidgetsBindingObserver { children: [ currentTab == 0 ? IconButton( - icon: SvgPicture.asset( - "assets/images/new/menu.svg"), - color: Theme.of(context) - .textTheme - .headline1! - .color, - onPressed: () => - Scaffold.of(context).openDrawer(), + icon: SvgPicture.asset("assets/images/new/menu.svg"), + // color: Theme.of(context).textTheme.headline1!.color, + color: CustomColors.white, + onPressed: () => Scaffold.of(context).openDrawer(), ) : IconButton( icon: Icon(Icons.arrow_back), @@ -550,9 +518,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { pageController.jumpToPage(0); }, ), - projectViewModel.isLogin && - model.notificationsCount != null && - !projectViewModel.isLoginChild + projectViewModel.isLogin && model.notificationsCount != null && !projectViewModel.isLoginChild ? Positioned( right: projectViewModel.isArabic ? 35 : 0, top: 5, @@ -570,8 +536,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { model.notificationsCount.toString(), style: TextStyle( color: Colors.white, - fontSize: - projectViewModel.isArabic ? 8 : 9, + fontSize: projectViewModel.isArabic ? 8 : 9, ), textAlign: TextAlign.center, ), @@ -655,16 +620,15 @@ class _LandingPageState extends State with WidgetsBindingObserver { index: currentTab, ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: - (projectViewModel.havePrivilege(34) && currentTab == 0) - ? FloatingButton( - elevation: true, - onTap: () { - changeCurrentTab(2); - projectViewModel.analytics.appointment.book_appointment(); - }, - ) - : null); + floatingActionButton: (projectViewModel.havePrivilege(34) && currentTab == 0) + ? FloatingButton( + elevation: true, + onTap: () { + changeCurrentTab(2); + projectViewModel.analytics.appointment.book_appointment(); + }, + ) + : null); } triggerRobot() { @@ -692,25 +656,16 @@ class _LandingPageState extends State with WidgetsBindingObserver { await PushNotificationHandler.getInstance().requestPermissions(); // authService.selectDeviceImei(token).then((SelectDeviceIMEIRES? value) => setUserValues(value)); if (authenticatedUserObject.isLogin) { - var data = - AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); + var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); if (data != null) { - authService - .registeredAuthenticatedUser(data, token, 0, 0) - .then((res) => {}); + authService.registeredAuthenticatedUser(data, token, 0, 0).then((res) => {}); authService.getDashboard().then((value) async { setState(() { if (value != null) { - notificationCount = value['List_PatientDashboard'][0] - ['UnreadPatientNotificationCount'] > - 99 - ? '99+' - : value['List_PatientDashboard'][0] - ['UnreadPatientNotificationCount'] - .toString(); + notificationCount = value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString(); model.setState(model.count, 0, true, notificationCount); sharedPref.setString(NOTIFICATION_COUNT, notificationCount); - FlutterAppIconBadge.updateBadge(int.parse(notificationCount)); + // FlutterAppIconBadge.updateBadge(int.parse(notificationCount)); } }); // if (await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN) == null || !await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN)) { diff --git a/lib/pages/landing/widgets/services_view.dart b/lib/pages/landing/widgets/services_view.dart index 5635a4a6..a98da010 100644 --- a/lib/pages/landing/widgets/services_view.dart +++ b/lib/pages/landing/widgets/services_view.dart @@ -4,7 +4,9 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/pharmacy_module_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/models/hmg_services.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/%E2%80%8B%20health_calculators.dart'; @@ -21,6 +23,7 @@ import 'package:diplomaticquarterapp/pages/ChildVaccines/new/child_initial_page. import 'package:diplomaticquarterapp/pages/ContactUs/contact_us_page.dart'; import 'package:diplomaticquarterapp/pages/Covid-DriveThru/covid-drivethru-location.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/my-family.dart'; +import 'package:diplomaticquarterapp/pages/ErService/EROnlineCheckIn/EROnlineCheckInHome.dart'; import 'package:diplomaticquarterapp/pages/ErService/ErOptions.dart'; import 'package:diplomaticquarterapp/pages/InPatientServices/inpatient_home.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; @@ -31,14 +34,20 @@ import 'package:diplomaticquarterapp/pages/medical/smart_watch_health_data/smart import 'package:diplomaticquarterapp/pages/paymentService/payment_service.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app-permissions.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/location_util.dart'; +import 'package:diplomaticquarterapp/uitl/penguin_method_channel.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/dialogs/covid_consent_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/location_selection_dialog.dart'; +import 'package:diplomaticquarterapp/widgets/dialogs/radio_selection_dialog.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../locator.dart'; @@ -52,8 +61,10 @@ class ServicesView extends StatelessWidget { PharmacyModuleViewModel pharmacyModuleViewModel = locator(); late LocationUtils locationUtils; bool isHomePage; + late ProjectViewModel projectViewModel; + bool isLocked; - ServicesView(this.hmgServices, this.index, this.isHomePage); + ServicesView(this.hmgServices, this.index, this.isHomePage, this.projectViewModel, {this.isLocked = false}); @override Widget build(BuildContext context) { @@ -159,12 +170,58 @@ class ServicesView extends StatelessWidget { ], ), ), + isLocked + ? Container( + width: double.infinity, + height: double.infinity, + decoration: containerRadiusWithGradientServices(20, lightColor: Colors.grey.withOpacity(0.6), darkColor: Colors.grey.withOpacity(0.6)), + child: Icon( + Icons.lock_outline, + size: 40, + ), + ) + : Container() ], ), ), ); } + openNavigationProjectSelection(BuildContext context) { + int _selectedHospitalIndex = 0; + List projectsListLocal = []; + Utils.navigationProjectsList.forEach((v) { + projectsListLocal.add(new HospitalsModel.fromJson(v)); + }); + showDialog( + context: context, + builder: (cxt) => LocationSelectionDialog( + isArabic: projectViewModel.isArabic, + data: projectsListLocal, + selectedIndex: _selectedHospitalIndex, + onValueSelected: (index) { + _selectedHospitalIndex = index; + initPenguinSDK(projectsListLocal[index].iD); + }, + ), + ); + } + + initPenguinSDK(int projectID) async { + final bool permited = await AppPermission.askPenguinPermissions(); + if (!permited) { + Map statuses = await [ + Permission.location, + Permission.bluetooth, + Permission.bluetoothConnect, + Permission.bluetoothScan, + Permission.activityRecognition, + ].request().whenComplete(() { + PenguinMethodChannel().launch("penguin", projectViewModel.isArabic ? "ar" : "en", projectViewModel.authenticatedUserObject.user.patientID.toString()); + }); + } // + } + handleHomePageServices(HmgServices hmgServices, BuildContext context) { if (hmgServices.action == 0) { Navigator.push(context, FadePage(page: Search())); @@ -172,8 +229,13 @@ class ServicesView extends StatelessWidget { } else if (hmgServices.action == 1) { openLiveCare(context); } else if (hmgServices.action == 2) { - Navigator.push(context, FadePage(page: ErOptions(isAppbar: true))); - locator().hmgServices.logServiceName('emergency service'); + // initPenguinSDK(); + if (projectViewModel.isIndoorNavigationEnabled) { + if (!isLocked) openNavigationProjectSelection(context); + } else { + Navigator.push(context, FadePage(page: ErOptions(isAppbar: true))); + locator().hmgServices.logServiceName('emergency service'); + } } else if (hmgServices.action == 3) { Navigator.push(context, FadePage(page: HomeHealthCarePage())); locator().hmgServices.logServiceName('home health care'); @@ -195,6 +257,9 @@ class ServicesView extends StatelessWidget { } else if (hmgServices.action == 23) { Navigator.push(context, FadePage(page: InPatientServicesHome())); locator().hmgServices.logServiceName('find us reach us'); + } else if (hmgServices.action == 9) { + Navigator.push(context, FadePage(page: EROnlineCheckInHomePage())); + locator().hmgServices.logServiceName('ER Online CheckIn'); } } @@ -266,10 +331,8 @@ class ServicesView extends StatelessWidget { } else if (hmgServices.action == 21) { Navigator.of(context).push( MaterialPageRoute( - builder: (BuildContext context) => MyWebView( - title: "HMG News", - selectedUrl:"https://twitter.com/hmg" //"https://twitter.com/hashtag/مجموعة_د_سليمان_الحبيب_الطبية?src=hashtag_click&f=live", - ), + builder: (BuildContext context) => MyWebView(title: "HMG News", selectedUrl: "https://twitter.com/hmg" //"https://twitter.com/hashtag/مجموعة_د_سليمان_الحبيب_الطبية?src=hashtag_click&f=live", + ), ), ); locator().hmgServices.logServiceName('latest news'); diff --git a/lib/pages/livecare/live_care_payment_page.dart b/lib/pages/livecare/live_care_payment_page.dart index c1f63e66..ccec389b 100644 --- a/lib/pages/livecare/live_care_payment_page.dart +++ b/lib/pages/livecare/live_care_payment_page.dart @@ -4,6 +4,8 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/LiveCare/ERAppointmentFeesResponse.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; @@ -15,6 +17,7 @@ import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart'; import 'package:diplomaticquarterapp/widgets/dialogs/covid_consent_dialog.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:permission_handler/permission_handler.dart'; @@ -317,53 +320,87 @@ class _LiveCarePatmentPageState extends State { Container( padding: EdgeInsets.all(12), color: Colors.white, - child: Flex( - direction: Axis.horizontal, - children: [ - Expanded( - child: DefaultButton( - TranslationBase.of(context).cancel, - () { - if (widget.isPharmaLiveCare) cancelAPI(); - Navigator.pop(context, false); - }, - ), - ), - mWidth(12), - Expanded( - child: DefaultButton( - TranslationBase.of(context).next, - () { - if (_selected == 0) { - AppToast.showErrorToast(message: TranslationBase.of(context).pleaseAcceptTerms); - } else { - if (widget.isPharmaLiveCare) { - Navigator.pop(context, true); - } else { - askVideoCallPermission().then((value) async { - if (value == true) { - locationUtils = new LocationUtils(isShowConfirmDialog: false, context: context); - locationUtils.getCurrentLocation(callBack: (value) { - print(value); - }); - if (Platform.isAndroid && !(await PlatformBridge.shared().isDrawOverAppsPermissionAllowed())) { - await drawOverAppsMessageDialog(context).then((value) { - return false; - }); - } else { - Navigator.pop(context, true); - projectViewModel.analytics.liveCare.livecare_immediate_consultation_TnC(clinic: widget.clinicName); - } + child: Column( + children: [ + Flex( + direction: Axis.horizontal, + children: [ + Expanded( + child: DefaultButton( + TranslationBase.of(context).cancel, + () { + if (widget.isPharmaLiveCare) cancelAPI(); + Navigator.pop(context, false); + }, + ), + ), + mWidth(12), + Expanded( + child: DefaultButton( + TranslationBase.of(context).next, + () { + if (_selected == 0) { + AppToast.showErrorToast(message: TranslationBase.of(context).pleaseAcceptTerms); + } else { + if (widget.isPharmaLiveCare) { + Navigator.pop(context, true); } else { - openPermissionsDialog(); + askVideoCallPermission().then((value) async { + if (value == true) { + locationUtils = new LocationUtils(isShowConfirmDialog: false, context: context); + locationUtils.getCurrentLocation(callBack: (value) { + print(value); + }); + if (Platform.isAndroid && !(await PlatformBridge.shared().isDrawOverAppsPermissionAllowed())) { + await drawOverAppsMessageDialog(context).then((value) { + return false; + }); + } else { + Navigator.pop(context, true); + projectViewModel.analytics.liveCare.livecare_immediate_consultation_TnC(clinic: widget.clinicName); + } + } else { + openPermissionsDialog(); + } + }); } - }); - } - } - }, - color: CustomColors.green, - ), + } + }, + color: CustomColors.green, + ), + ), + ], ), + widget.getERAppointmentFeesList.isCash! + ? Column( + children: [ + mHeight(10.0), + Text( + TranslationBase.of(context).cashAmountUpdateInsurance, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2E303A), + ), + ), + mHeight(5.0), + DefaultButton( + TranslationBase.of(context).updateInsuranceText, + () { + Navigator.pop(context, null); + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => LandingPage()), + (Route route) => false, + ); + Navigator.push(context, FadePage(page: InsuranceUpdate())); + }, + color: Color(0xffEAA118), + textColor: Colors.white, + ), + ], + ) + : Container(), ], ), ), diff --git a/lib/pages/livecare/livecare_home.dart b/lib/pages/livecare/livecare_home.dart index 4c14eeb2..6381ce8a 100644 --- a/lib/pages/livecare/livecare_home.dart +++ b/lib/pages/livecare/livecare_home.dart @@ -171,7 +171,7 @@ class _LiveCareHomeState extends State with SingleTickerProviderSt }); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); - AppToast.showErrorToast(message: err); + AppToast.showErrorToast(message: err, localContext: context); print(err); }); } diff --git a/lib/pages/livecare/video-call-web-page.dart b/lib/pages/livecare/video-call-web-page.dart index 46a29924..f755d1b0 100644 --- a/lib/pages/livecare/video-call-web-page.dart +++ b/lib/pages/livecare/video-call-web-page.dart @@ -14,7 +14,7 @@ class VideoCallWebPage extends StatelessWidget{ final String receiverId; final String callerId; VideoCallWebPage({required this.receiverId, required this.callerId}){ - request = URLRequest(url: Uri.parse("https://vcallapi.hmg.com/Mobileindex.html?username=$receiverId&doctorid=$callerId")); + request = URLRequest(url: WebUri.uri(Uri.parse("https://vcallapi.hmg.com/Mobileindex.html?username=$receiverId&doctorid=$callerId"))); } InAppWebViewGroupOptions options = InAppWebViewGroupOptions( diff --git a/lib/pages/livecare/widgets/clinic_list.dart b/lib/pages/livecare/widgets/clinic_list.dart index f7c60e0e..0a0baa74 100644 --- a/lib/pages/livecare/widgets/clinic_list.dart +++ b/lib/pages/livecare/widgets/clinic_list.dart @@ -15,6 +15,7 @@ import 'package:diplomaticquarterapp/models/LiveCare/LiveCareClinicsListResponse import 'package:diplomaticquarterapp/models/LiveCare/LiveCareScheduleClinicsListResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/SearchResults.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart'; +import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/livecare/livecare_call_type_select.dart'; import 'package:diplomaticquarterapp/pages/livecare/livecare_home.dart'; @@ -180,11 +181,39 @@ class _clinic_listState extends State { getERAppointmentTime(GetERAppointmentFeesList getERAppointmentFeesList) { int languageID = projectViewModel.isArabic ? 1 : 2; + String errorMsg = ""; LiveCareService service = new LiveCareService(); GifLoaderDialogUtils.showMyDialog(context); service.getERAppointmentTime(selectedClinicID, widget.isPharmacyLiveCare, languageID, context).then((res) { GifLoaderDialogUtils.hideDialog(context); - showLiveCarePaymentDialog(getERAppointmentFeesList, res['WatingtimeInteger']); + + // getERAppointmentFeesList.isCash = false; + // getERAppointmentFeesList.isInsured = true; + // getERAppointmentFeesList.isEligible = false; + + if (getERAppointmentFeesList.isCash!) { + showLiveCarePaymentDialog(getERAppointmentFeesList, res['WatingtimeInteger']); + } else { + if (getERAppointmentFeesList.isInsured! && getERAppointmentFeesList.isEligible!) { + showLiveCarePaymentDialog(getERAppointmentFeesList, res['WatingtimeInteger']); + } else { + if (getERAppointmentFeesList.isInsured! && !getERAppointmentFeesList.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()}); + dialog.showAlertDialog(context); + } + } + // showLiveCarePaymentDialog(getERAppointmentFeesList, res['WatingtimeInteger']); }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); print(err); @@ -192,6 +221,28 @@ class _clinic_listState extends State { }); } + void continueAsCash() { + DoctorsListService service = new DoctorsListService(); + GifLoaderDialogUtils.showMyDialog(context); + service.convertPatientToCash(BASE_URL.contains("uat.") ? 15 : 12).then((res) { + GifLoaderDialogUtils.hideDialog(context); + if (res["MessageStatus"] == 1) { + startLiveCare(); + } else { + AppToast.showErrorToast(message: res["ErrorEndUserMessage"]); + } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + void openUpdateInsurance() { + Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LandingPage()), (Route r) => false); + Navigator.push(context, FadePage(page: InsuranceUpdate())); + } + showLiveCarePaymentDialog(GetERAppointmentFeesList getERAppointmentFeesList, int waitingTime) { navigateTo( context, @@ -333,15 +384,17 @@ class _clinic_listState extends State { String pharmaLiveCareQRCodeValue = widget.pharmacyLiveCareQRCode; Navigator.push( - context, - FadePage( - page: PaymentMethod( + context, + FadePage( + page: PaymentMethod( onSelectedMethod: (String metohd, [String? selectedInstallmentPlan]) { setState(() {}); }, patientShare: num.parse(getERAppointmentFeesList.total!), isFromAdvancePayment: widget.isPharmacyLiveCare, - ))).then((value) { + ), + ), + ).then((value) { if (value != null) { selectedPaymentMethod = value[0]; print(value); diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart index 608943ac..b43d9823 100644 --- a/lib/pages/login/confirm-login.dart +++ b/lib/pages/login/confirm-login.dart @@ -19,6 +19,7 @@ import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_requ import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/login/login.dart'; import 'package:diplomaticquarterapp/pages/login/register_new.dart'; +import 'package:diplomaticquarterapp/pages/login/user-login-agreement-page.dart'; import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; @@ -41,18 +42,14 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; import 'package:local_auth/local_auth.dart'; import 'package:provider/provider.dart'; -import 'package:local_auth_ios/types/auth_messages_ios.dart'; +// import 'package:local_auth_ios/types/auth_messages_ios.dart'; class ConfirmLogin extends StatefulWidget { final Function? changePageViewIndex; final fromRegistration; final bool isDubai; - const ConfirmLogin({Key? key, - this.changePageViewIndex, - this.fromRegistration = false, - this.isDubai = false}) - : super(key: key); + const ConfirmLogin({Key? key, this.changePageViewIndex, this.fromRegistration = false, this.isDubai = false}) : super(key: key); @override _ConfirmLogin createState() => _ConfirmLogin(); @@ -64,8 +61,7 @@ class _ConfirmLogin extends State { var sharedPref = AppSharedPreferences(); bool authenticated = false; final authService = AuthProvider(); - PharmacyModuleViewModel pharmacyModuleViewModel = - locator(); + PharmacyModuleViewModel pharmacyModuleViewModel = locator(); late int mobileNumber; String errorMsg = ''; SelectDeviceIMEIRES? user; @@ -95,10 +91,8 @@ class _ConfirmLogin extends State { int fingrePrintBefore = 0; - AuthenticatedUserObject authenticatedUserObject = - locator(); - AppointmentRateViewModel appointmentRateViewModel = - locator(); + AuthenticatedUserObject authenticatedUserObject = locator(); + AppointmentRateViewModel appointmentRateViewModel = locator(); late ProjectViewModel projectViewModel; late ToDoCountProviderModel toDoProvider; @@ -145,35 +139,17 @@ class _ConfirmLogin extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - TranslationBase - .of(context) - .welcomeBack, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64), + TranslationBase.of(context).welcomeBack, + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64), ), Text( user!.name!.toLowerCase().capitalizeFirstofEach, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w700, - color: Color(0xff2B353E), - height: 1, - letterSpacing: -1.44), + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xff2B353E), height: 1, letterSpacing: -1.44), ), SizedBox(height: 10), Text( - TranslationBase - .of(context) - .accountInfo, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 25 / 16), + TranslationBase.of(context).accountInfo, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), ), Container( height: 72, @@ -192,48 +168,28 @@ class _ConfirmLogin extends State { mainAxisSize: MainAxisSize.min, children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - TranslationBase - .of(context) - .lastLoginAt - .toCamelCase, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64), + TranslationBase.of(context).lastLoginAt.toCamelCase, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64), ), Text( // user!.editedOn != null // ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user!.editedOn!)) // : - user!.createdOn != null - ? DateUtil.getDayMonthYearDateFormatted( - DateUtil.convertStringToDate( - user!.createdOn!)) - : '--', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.48), + user!.createdOn != null ? DateUtil.getDayMonthYearDateFormatted(DateUtil.convertStringToDate(user!.createdOn!)) : '--', + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.48), ), ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - TranslationBase - .of(context) - .lastLoginWith - .toCamelCase, + TranslationBase.of(context).lastLoginWith.toCamelCase, style: TextStyle( fontSize: 10, fontWeight: FontWeight.w600, @@ -256,17 +212,8 @@ class _ConfirmLogin extends State { // user!.editedOn!), // false) // : - user!.createdOn != null - ? DateUtil.formatDateToTimeLang( - DateUtil.convertStringToDate( - user!.createdOn!), - false) - : '--', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Color(0xff575757), - letterSpacing: -0.48), + user!.createdOn != null ? DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(user!.createdOn!), false) : '--', + style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.48), ), ], ) @@ -274,21 +221,11 @@ class _ConfirmLogin extends State { ), ), Text( - TranslationBase - .of(context) - .pleaseVerify, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2E303A), - letterSpacing: -0.64), + TranslationBase.of(context).pleaseVerify, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64), ), GridView( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 13, - mainAxisSpacing: 9), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.only(top: 9), shrinkWrap: true, @@ -302,67 +239,40 @@ class _ConfirmLogin extends State { ], ) else - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/habib-logo.png', - height: 90, - width: 90, - ), - SizedBox(height: 23), - this.onlySMSBox == false - ? Text( - TranslationBase - .of(context) - .verifyLoginWith, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 25 / 16), - ) - : Text( - TranslationBase - .of(context) - .verifyFingerprint2, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.64, - height: 25 / 16), - ), - SizedBox(height: 23), - Text( - TranslationBase - .of(context) - .pleaseVerify, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color(0xff2E303A), - letterSpacing: -0.64), - ), - GridView( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 13, - mainAxisSpacing: 9), - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(top: 9), - shrinkWrap: true, - children: [ - if (onlySMSBox == false) getButton(3), - if (onlySMSBox == false) getButton(2), - getButton(1), - getButton(4), - ], - ), - ]), + Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + Image.asset( + 'assets/images/habib-logo.png', + height: 90, + width: 90, + ), + SizedBox(height: 23), + this.onlySMSBox == false + ? Text( + TranslationBase.of(context).verifyLoginWith, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), + ) + : Text( + TranslationBase.of(context).verifyFingerprint2, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), + ), + SizedBox(height: 23), + Text( + TranslationBase.of(context).pleaseVerify, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64), + ), + GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(top: 9), + shrinkWrap: true, + children: [ + if (onlySMSBox == false) getButton(3), + if (onlySMSBox == false) getButton(2), + getButton(1), + getButton(4), + ], + ), + ]), ], ), ), @@ -370,13 +280,10 @@ class _ConfirmLogin extends State { height: 12, ), DefaultButton( - TranslationBase - .of(context) - .useAnotherAccount, - () { + TranslationBase.of(context).useAnotherAccount, + () { Navigator.of(context).pushNamed(LOGIN_TYPE); - projectViewModel.analytics.loginRegistration - .login_with_other_account(); + projectViewModel.analytics.loginRegistration.login_with_other_account(); }, ), ], @@ -387,13 +294,12 @@ class _ConfirmLogin extends State { Future _getAvailableBiometrics() async { final bool canAuthenticateWithBiometrics = await auth.canCheckBiometrics; - final bool canAuthenticate = - canAuthenticateWithBiometrics || await auth.isDeviceSupported(); + final bool canAuthenticate = canAuthenticateWithBiometrics || await auth.isDeviceSupported(); var availableBiometrics; try { availableBiometrics = await auth.getAvailableBiometrics(); - print(availableBiometrics); + // print(availableBiometrics); } on PlatformException catch (e) { AppToast.showErrorToast(message: e.message!); print(e); @@ -417,8 +323,7 @@ class _ConfirmLogin extends State { login_method = type; LoginRegistration.verificationMethod = type; // if(!widget.fromRegistration) - projectViewModel.analytics.loginRegistration - .login_verfication(forRegistration: widget.fromRegistration); + projectViewModel.analytics.loginRegistration.login_verfication(forRegistration: widget.fromRegistration); switch (type) { case 1: @@ -436,8 +341,7 @@ class _ConfirmLogin extends State { default: break; } - sharedPref.setInt(LAST_LOGIN, - this.selectedOption); //this.cs.sharedService.setStorage(this.selectedOption, AuthenticationService.LAST_LOGIN); + sharedPref.setInt(LAST_LOGIN, this.selectedOption); //this.cs.sharedService.setStorage(this.selectedOption, AuthenticationService.LAST_LOGIN); } loginWithSMS(type) { @@ -465,23 +369,22 @@ class _ConfirmLogin extends State { sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request); authService .checkPatientAuthentication(request) - .then((value) => - { - GifLoaderDialogUtils.hideDialog(context), - if (value['isSMSSent']) - { - sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']), - this.loginTokenID = value['LogInTokenID'], - sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), - // Future.delayed(Duration(seconds: 1), () { - this.sendActivationCode(type) - // }) - } - else - { - if (value['IsAuthenticated']) {this.checkActivationCode()} - } - }) + .then((value) => { + GifLoaderDialogUtils.hideDialog(context), + if (value['isSMSSent']) + { + sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']), + this.loginTokenID = value['LogInTokenID'], + sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), + // Future.delayed(Duration(seconds: 1), () { + this.sendActivationCode(type) + // }) + } + else + { + if (value['IsAuthenticated']) {this.checkActivationCode()} + } + }) .catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); @@ -494,8 +397,7 @@ class _ConfirmLogin extends State { GifLoaderDialogUtils.showMyDialog(context); if (healthId != null || widget.isDubai) { if (!widget.isDubai) { - request.dob = - dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); + request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); } request.healthId = healthId; request.isHijri = isHijri; @@ -532,11 +434,10 @@ class _ConfirmLogin extends State { context, type, this.mobileNumber, - (value) { + (value) { this.checkActivationCode(value: value); }, - () => - { + () => { Navigator.pop(context), }, ).displayDialog(context); @@ -552,11 +453,11 @@ class _ConfirmLogin extends State { stickyAuth: true, ), authMessages: [ - IOSAuthMessages( - cancelButton: 'cancel', - goToSettingsButton: 'settings', - goToSettingsDescription: 'Please set up your Touch ID.', - lockOut: 'Please reenable your Touch ID'), + // IOSAuthMessages( + // cancelButton: 'cancel', + // goToSettingsButton: 'settings', + // goToSettingsDescription: 'Please set up your Touch ID.', + // lockOut: 'Please reenable your Touch ID'), ], ); } on PlatformException catch (e) { @@ -612,28 +513,23 @@ class _ConfirmLogin extends State { setDefault() async { showLoader(true); - if (await sharedPref.getObject(IMEI_USER_DATA) != null) - user = SelectDeviceIMEIRES.fromJson( - await sharedPref.getObject(IMEI_USER_DATA)); + if (await sharedPref.getObject(IMEI_USER_DATA) != null) user = SelectDeviceIMEIRES.fromJson(await sharedPref.getObject(IMEI_USER_DATA)); if (await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN) != null) { isMoreOption = true; - this.registerd_data = await CheckPatientAuthenticationReq.fromJson( - await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN)); + this.registerd_data = await CheckPatientAuthenticationReq.fromJson(await sharedPref.getObject(REGISTER_DATA_FOR_LOGIIN)); } - this.mobileNumber = this.registerd_data != null - ? this.registerd_data.patientMobileNumber - : int.parse(this.user!.mobile!); + this.mobileNumber = this.registerd_data != null ? this.registerd_data.patientMobileNumber : int.parse(this.user!.mobile!); this.zipCode = this.registerd_data != null ? this.registerd_data.zipCode : this.user!.outSA == true - ? "971" - : "966"; + ? "971" + : "966"; this.patientOutSA = this.registerd_data != null ? this.registerd_data.zipCode == "966" - ? 0 - : 1 + ? 0 + : 1 : this.user!.outSA; if (this.registerd_data != null) { this.loginTokenID = await sharedPref.getString(LOGIN_TOKEN_ID); @@ -643,9 +539,7 @@ class _ConfirmLogin extends State { if (nhic != null) { final DateFormat dateFormat = DateFormat('MM/dd/yyyy'); final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy'); - dob = nhic['IsHijri'] - ? nhic['DateOfBirth'] - : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth'])); + dob = nhic['IsHijri'] ? nhic['DateOfBirth'] : dateFormat2.format(dateFormat.parse(nhic['DateOfBirth'])); isHijri = nhic['IsHijri'] ? 1 : 0; healthId = nhic['HealthId']; @@ -654,8 +548,8 @@ class _ConfirmLogin extends State { this.lastLogin = await sharedPref.getInt(LAST_LOGIN) != null ? await sharedPref.getInt(LAST_LOGIN) : user != null - ? user!.logInType - : null; + ? user!.logInType + : null; showLoader(false); //this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN); @@ -668,34 +562,22 @@ class _ConfirmLogin extends State { request.deviceToken = this.deviceToken; request.projectOutSA = this.patientOutSA == true ? true : false; request.loginType = this.selectedOption; - request.oTPSendType = - type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; + request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2; request.zipCode = this.zipCode; request.logInTokenID = this.loginTokenID ?? ""; if (this.registerd_data != null) { - request.searchType = this.registerd_data.searchType != null - ? this.registerd_data.searchType - : 1; - request.patientID = this.registerd_data.patientID != null - ? this.registerd_data.patientID - : 0; - request.patientIdentificationID = request.nationalID = - this.registerd_data.patientIdentificationID != null - ? this.registerd_data.patientIdentificationID - : '0'; + request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1; + request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0; + request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0'; request.dob = this.registerd_data.dob; request.isRegister = this.registerd_data.isRegister; } else { request.searchType = request.searchType != null ? request.searchType : 2; - request.patientID = - this.user!.patientID != null ? this.user!.patientID : 0; - request.nationalID = - request.nationalID != null ? request.nationalID : '0'; - request.patientIdentificationID = request.patientIdentificationID != null - ? request.patientIdentificationID - : '0'; + request.patientID = this.user!.patientID != null ? this.user!.patientID : 0; + request.nationalID = request.nationalID != null ? request.nationalID : '0'; + request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0'; request.isRegister = false; } request.deviceTypeID = request.searchType; @@ -716,40 +598,31 @@ class _ConfirmLogin extends State { authService .checkActivationCodeRegister(request, value) - .then((result) => - { - res = result, - if (result is Map) - { - result = CheckActivationCode.fromJson( - result as Map), - if (this.registerd_data != null && - this.registerd_data.isRegister == true) - { - // if(widget.isDubai ==false){ - widget.changePageViewIndex!(1), - // if(widget.isDubai ==false){ - - Navigator.popUntil( - context, - (route) => - Utils.route(route, equalsTo: RegisterNew)), - } - } - else - { - // Navigator.of(context).pop(), - GifLoaderDialogUtils.hideDialog(context), - Future.delayed(Duration(seconds: 1), () { - AppToast.showErrorToast(message: result); - }), - projectViewModel.analytics.loginRegistration - .login_fail(error: result), - projectViewModel.analytics.errorTracking.log( - 'otp_verification_at_confirm_login', - error: result), - } - }) + .then((result) => { + res = result, + if (result is Map) + { + result = CheckActivationCode.fromJson(result as Map), + if (this.registerd_data != null && this.registerd_data.isRegister == true) + { + // if(widget.isDubai ==false){ + widget.changePageViewIndex!(1), + // if(widget.isDubai ==false){ + + Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)), + } + } + else + { + // Navigator.of(context).pop(), + GifLoaderDialogUtils.hideDialog(context), + Future.delayed(Duration(seconds: 1), () { + AppToast.showErrorToast(message: result); + }), + projectViewModel.analytics.loginRegistration.login_fail(error: result), + projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result), + } + }) .catchError((err) { print(err); GifLoaderDialogUtils.hideDialog(context); @@ -762,62 +635,56 @@ class _ConfirmLogin extends State { authService .checkActivationCode(request, value) .then((result) => { - res = result, - if (result is Map) - { - result = CheckActivationCode.fromJson(result as Map), - if(result.errorCode =='699'){ - //699 block run here - GifLoaderDialogUtils.hideDialog(context), - Future.delayed(Duration(seconds: 2), () { - AppToast.showErrorToast(message: result.errorEndUserMessage); - Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: Login)); + res = result, + if (result is Map) + { + result = CheckActivationCode.fromJson(result as Map), + if (result.errorCode == '699') + { + //699 block run here + GifLoaderDialogUtils.hideDialog(context), + Future.delayed(Duration(seconds: 2), () { + AppToast.showErrorToast(message: result.errorEndUserMessage); + Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: Login)); + }) + } + else if (this.registerd_data != null && this.registerd_data.isRegister == true) + { + widget.changePageViewIndex!(1), + Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)), + } + else + { + sharedPref.remove(FAMILY_FILE), + result.list.isFamily = false, + userData = result.list, + sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""), + //Remove o+ from here Added by Aamir + authenticatedUserObject.user = result.list, + projectViewModel.setPrivilege(privilegeList: res), + sharedPref.setObject(MAIN_USER, result.list), + sharedPref.setObject(USER_PROFILE, result.list), + loginTokenID = result.logInTokenID, + sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), + sharedPref.setString(TOKEN, result.authenticationTokenID), + checkIfUserAgreedBefore(result), + projectViewModel.analytics.loginRegistration.login_successful(), + } + } + else + { + // Navigator.of(context).pop(), + GifLoaderDialogUtils.hideDialog(context), + Future.delayed(Duration(seconds: 1), () { + Navigator.of(context).pop(); + AppToast.showErrorToast(message: result, localContext: context); + startSMSService(tempType); + }), + + projectViewModel.analytics.loginRegistration.login_fail(error: result), + projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result) + } }) - } - else if (this.registerd_data != null && - this.registerd_data.isRegister == true) - { - widget.changePageViewIndex!(1), - Navigator.popUntil( - context, - (route) => - Utils.route(route, equalsTo: RegisterNew)), - } - else - { - sharedPref.remove(FAMILY_FILE), - result.list.isFamily = false, - userData = result.list, - sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""), - //Remove o+ from here Added by Aamir - authenticatedUserObject.user = result.list, - projectViewModel.setPrivilege(privilegeList: res), - sharedPref.setObject(MAIN_USER, result.list), - sharedPref.setObject(USER_PROFILE, result.list), - loginTokenID = result.logInTokenID, - sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), - sharedPref.setString(TOKEN, result.authenticationTokenID), - checkIfUserAgreedBefore(result), - projectViewModel.analytics.loginRegistration.login_successful(), - - } - } - else - { - // Navigator.of(context).pop(), - GifLoaderDialogUtils.hideDialog(context), - Future.delayed(Duration(seconds: 1), () { - Navigator.of(context).pop(); - AppToast.showErrorToast(message: result); - startSMSService(tempType); - }), - - projectViewModel.analytics.loginRegistration - .login_fail(error: result), - projectViewModel.analytics.errorTracking - .log('otp_verification_at_confirm_login', error: result) - } - }) .catchError((err) { GifLoaderDialogUtils.hideDialog(context); Future.delayed(Duration(seconds: 1), () { @@ -830,6 +697,33 @@ class _ConfirmLogin extends State { } checkIfUserAgreedBefore(CheckActivationCode result) { + // this.authService.checkIfUserAgreed().then((result) { + // if (result['IsPatientAlreadyAgreed']) { + // goToHome(); + // } else { + // this.authService.getUserAgreementContent().then((result) { + // GifLoaderDialogUtils.hideDialog(AppGlobal.context); + // Navigator.pushAndRemoveUntil( + // context, + // FadePage( + // page: UserLoginAgreementPage( + // userAgreementText: result['UserAgreementContent'], + // authenticatedUserObject: authenticatedUserObject, + // appointmentRateViewModel: appointmentRateViewModel, + // selectedOption: selectedOption, + // ), + // ), + // (r) => false); + // }).catchError((err) { + // GifLoaderDialogUtils.hideDialog(context); + // print(err); + // }); + // } + // }).catchError((err) { + // GifLoaderDialogUtils.hideDialog(context); + // print(err); + // }); + // if (result.isNeedUserAgreement == true) { //move to agreement page. // } else { @@ -851,25 +745,18 @@ class _ConfirmLogin extends State { print("Has Admission Request: $hasAdmissionRequest"); if (isAdmitted) { if (res['PatientAdmittedInformation'].length != 0) { - getAdmissionInfoResponseModel = - GetAdmissionInfoResponseModel.fromJson( - res['PatientAdmittedInformation'][0]); - projectViewModel.setInPatientProjectID( - res['PatientAdmittedInformation'][0]['ProjectID']); - projectViewModel - .setInPatientAdmissionInfo(getAdmissionInfoResponseModel); + getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel.fromJson(res['PatientAdmittedInformation'][0]); + projectViewModel.setInPatientProjectID(res['PatientAdmittedInformation'][0]['ProjectID']); + projectViewModel.setInPatientAdmissionInfo(getAdmissionInfoResponseModel); projectViewModel.setIsPatientAdmitted(true); } } if (hasAdmissionRequest) { if (res['MedicalInstruction'].length != 0) { - getAdmissionRequestInfoResponseModel = - GetAdmissionRequestInfoResponseModel.fromJson( - res['MedicalInstruction'][0]); - projectViewModel.setInPatientProjectID( - res['MedicalInstruction'][0]['ProjectID']); - projectViewModel.setInPatientAdmissionRequest( - getAdmissionRequestInfoResponseModel); + getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel.fromJson(res['MedicalInstruction'][0]); + // projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['ProjectID']); + projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['projectId']); + projectViewModel.setInPatientAdmissionRequest(getAdmissionRequestInfoResponseModel); projectViewModel.setPatientHasAdmissionRequest(true); } } @@ -878,10 +765,7 @@ class _ConfirmLogin extends State { } insertIMEI() { - authService - .insertDeviceImei(selectedOption) - .then((value) => {}) - .catchError((err) { + authService.insertDeviceImei(selectedOption).then((value) => {}).catchError((err) { print(err); }); } @@ -891,8 +775,7 @@ class _ConfirmLogin extends State { ClinicListService service = new ClinicListService(); service.getActiveAppointmentNo(context).then((res) { if (res['MessageStatus'] == 1) { - toDoProvider.setState(res['AppointmentActiveNumber'], - res['AncillaryOrderListCount'], true, "0"); + toDoProvider.setState(res['AppointmentActiveNumber'], res['AncillaryOrderListCount'], true, "0"); // toDoProvider.setState(res['AppointmentActiveNumber'], true, "0"); } else {} }).catchError((err) { @@ -909,44 +792,34 @@ class _ConfirmLogin extends State { // GifLoaderDialogUtils.hideDialog(context); getToDoCount(); + checkIfIsInPatient(); appointmentRateViewModel .getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2) - .then((value) => - { - GifLoaderDialogUtils.hideDialog(AppGlobal.context), - if (appointmentRateViewModel.isHaveAppointmentNotRate) - { - Navigator.pushAndRemoveUntil( - context, - FadePage( - page: RateAppointmentDoctor(), - ), - (r) => false) - } - else - { - Navigator.pushAndRemoveUntil( - context, - FadePage( - page: LandingPage(), - ), - (r) => false) - }, - insertIMEI() - }) + .then((value) => { + GifLoaderDialogUtils.hideDialog(AppGlobal.context), + if (appointmentRateViewModel.isHaveAppointmentNotRate) + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: RateAppointmentDoctor(), + ), + (r) => false) + } + else + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false) + }, + insertIMEI() + }) .catchError((err) { print(err); }); - - // getToDoCount(); - - // Navigator.pushAndRemoveUntil( - // context, - // FadePage( - // page: LandingPage(), - // ), - // (r) => false); - // insertIMEI(); } loading(flag) { @@ -956,26 +829,21 @@ class _ConfirmLogin extends State { } Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { - bool isDisable = - (_flag == 3 && !checkIfBiometricAvailable(BiometricType.face) || - _flag == 2 && - !checkIfBiometricAvailable(BiometricType.fingerprint) && - _flag == 2 && - !checkIfBiometricAvailable(BiometricType.strong)); + bool isDisable = (_flag == 3 && !checkIfBiometricAvailable(BiometricType.face) || + _flag == 2 && !checkIfBiometricAvailable(BiometricType.fingerprint) && _flag == 2 && !checkIfBiometricAvailable(BiometricType.strong)); return InkWell( onTap: isDisable ? null : () { - if (_flag == 0) { - setState(() { - isMoreOption = true; - }); - } else { - authenticateUser(_flag, isActive: _loginIndex); - projectViewModel.analytics.loginRegistration.verify_otp_method( - forRegistration: widget.fromRegistration); - } - }, + if (_flag == 0) { + setState(() { + isMoreOption = true; + }); + } else { + authenticateUser(_flag, isActive: _loginIndex); + projectViewModel.analytics.loginRegistration.verify_otp_method(forRegistration: widget.fromRegistration); + } + }, child: Container( padding: EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28), decoration: BoxDecoration( @@ -997,17 +865,8 @@ class _ConfirmLogin extends State { color: isDisable ? Color(0xff2B353E).withOpacity(0.7) : null, ), Text( - TranslationBase - .of(context) - .verifyThrough + " " + _title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: isDisable - ? Color(0xff2B353E).withOpacity(0.7) - : Color(0xff2B353E), - letterSpacing: -0.48, - height: 20 / 16), + TranslationBase.of(context).verifyThrough + " " + _title, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: isDisable ? Color(0xff2B353E).withOpacity(0.7) : Color(0xff2B353E), letterSpacing: -0.48, height: 20 / 16), ), ], ), @@ -1019,49 +878,28 @@ class _ConfirmLogin extends State { Widget getButton(int flag) { switch (flag) { case 4: - return _loginOptionButton(TranslationBase - .of(context) - .verifyWhatsApp, - 'assets/images/new/verify_whatsapp.svg', flag, null); + return _loginOptionButton(TranslationBase.of(context).verifyWhatsApp, 'assets/images/new/verify_whatsapp.svg', flag, null); break; case 1: - return _loginOptionButton(TranslationBase - .of(context) - .verifySMS, - 'assets/images/new/verify_sms.svg', flag, null); + return _loginOptionButton(TranslationBase.of(context).verifySMS, 'assets/images/new/verify_sms.svg', flag, null); break; case 2: - return _loginOptionButton( - TranslationBase - .of(context) - .verifyFingerprint, - 'assets/images/new/verify_thumb.svg', - flag, - BiometricType.fingerprint.index); + return _loginOptionButton(TranslationBase.of(context).verifyFingerprint, 'assets/images/new/verify_thumb.svg', flag, BiometricType.fingerprint.index); break; case 3: - return _loginOptionButton( - TranslationBase - .of(context) - .verifyFaceID, - 'assets/images/new/verify_face.svg', - flag, - BiometricType.face.index); + return _loginOptionButton(TranslationBase.of(context).verifyFaceID, 'assets/images/new/verify_face.svg', flag, BiometricType.face.index); break; default: return InkWell( - onTap: () => - { + onTap: () => { setState(() { isMoreOption = true; }) }, child: RoundedContainer( height: 150, - backgroundColor: BiometricType.fingerprint.index == 1 - ? Colors.white - : Colors.white.withOpacity(.7), + backgroundColor: BiometricType.fingerprint.index == 1 ? Colors.white : Colors.white.withOpacity(.7), borderColor: Colors.grey, showBorder: true, child: Padding( @@ -1075,17 +913,12 @@ class _ConfirmLogin extends State { ), projectViewModel.isArabic ? SizedBox( - height: 15, - ) + height: 15, + ) : SizedBox( - height: 20, - ), - Texts(TranslationBase - .of(context) - .moreVerification, - fontSize: SizeConfig.textMultiplier! * 1.8, - textAlign: TextAlign.center, - color: Colors.black) + height: 20, + ), + Texts(TranslationBase.of(context).moreVerification, fontSize: SizeConfig.textMultiplier! * 1.8, textAlign: TextAlign.center, color: Colors.black) ], ), ), @@ -1097,35 +930,24 @@ class _ConfirmLogin extends State { getType(type, context) { switch (type) { case 1: - return TranslationBase - .of(context) - .verifySMS; + return TranslationBase.of(context).verifySMS; break; case 2: - return TranslationBase - .of(context) - .verifyFingerprint; + return TranslationBase.of(context).verifyFingerprint; break; case 3: - return TranslationBase - .of(context) - .verifyFaceID; + return TranslationBase.of(context).verifyFaceID; break; case 4: - return TranslationBase - .of(context) - .verifyWhatsApp; + return TranslationBase.of(context).verifyWhatsApp; break; default: - return TranslationBase - .of(context) - .verifySMS; + return TranslationBase.of(context).verifySMS; break; } } bool checkIfBiometricAvailable(BiometricType biometricType) { - print(biometricType); bool isAvailable = false; if (_availableBiometrics != null) { for (var i = 0; i < _availableBiometrics.length; i++) { diff --git a/lib/pages/login/forgot-password.dart b/lib/pages/login/forgot-password.dart index 7207e602..529d0b8f 100644 --- a/lib/pages/login/forgot-password.dart +++ b/lib/pages/login/forgot-password.dart @@ -1,4 +1,6 @@ +import 'package:cloudflare_turnstile/cloudflare_turnstile.dart'; import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; @@ -27,6 +29,23 @@ class _ForgotPassword extends State { String mobileNo = ""; var con; + final TurnstileController _controller = TurnstileController(); + final TurnstileOptions _options = TurnstileOptions( + size: TurnstileSize.normal, + theme: TurnstileTheme.light, + refreshExpired: TurnstileRefreshExpired.manual, + language: 'en', + retryAutomatically: false, + ); + + String? _token; + + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + @override Widget build(BuildContext context) { con = context; @@ -66,6 +85,25 @@ class _ForgotPassword extends State { countryCode = value; }); }), + const SizedBox(height: 12.0), + CloudFlareTurnstile( + siteKey: '0x4AAAAAAAkmbvEy63pcxBBt', + baseUrl: BASE_URL, + options: _options, + controller: _controller, + onTokenRecived: (token) { + setState(() { + print("Cloudflare token: $token"); + _token = token; + }); + }, + onTokenExpired: () {}, + mode: TurnstileMode.managed, + errorBuilder: (context, error) { + return Text(error.message); + }, + ), + const SizedBox(height: 48.0), ], ), ), diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart index 18ed5440..14ea9ab3 100644 --- a/lib/pages/login/login.dart +++ b/lib/pages/login/login.dart @@ -386,6 +386,7 @@ class _Login extends State { // ), // (r) => false); getToDoCount(); + checkIfIsInPatient(); appointmentRateViewModel .getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2) .then((value) => { @@ -462,7 +463,7 @@ class _Login extends State { GetAdmissionRequestInfoResponseModel.fromJson( res['MedicalInstruction'][0]); projectViewModel.setInPatientProjectID( - res['MedicalInstruction'][0]['ProjectID']); + res['MedicalInstruction'][0]['projectId']); projectViewModel.setInPatientAdmissionRequest( getAdmissionRequestInfoResponseModel); projectViewModel.setPatientHasAdmissionRequest(true); diff --git a/lib/pages/login/register-info.dart b/lib/pages/login/register-info.dart index e2b7db20..e3d2f020 100644 --- a/lib/pages/login/register-info.dart +++ b/lib/pages/login/register-info.dart @@ -450,15 +450,15 @@ class _RegisterInfo extends State { else request = getTempUserRequest(); - GifLoaderDialogUtils.showMyDialog(context); + GifLoaderDialogUtils.showMyDialog(context, barrierDismissible: false); dynamic res; this .authService .registerUser(request) - .then((result) => { - GifLoaderDialogUtils.hideDialog(context), + .then((result) async => { if (result is String) { + GifLoaderDialogUtils.hideDialog(context), new ConfirmDialog( context: context, confirmMessage: result, @@ -480,14 +480,14 @@ class _RegisterInfo extends State { sharedPref.remove(FAMILY_FILE), result.list.isFamily = false, - sharedPref.setString(BLOOD_TYPE, result.patientBloodType), + await sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""), authenticatedUserObject.user = result.list, projectViewModel.setPrivilege(privilegeList: res), - sharedPref.setObject(MAIN_USER, result.list), - sharedPref.setObject(USER_PROFILE, result.list), + await sharedPref.setObject(MAIN_USER, result.list), + await sharedPref.setObject(USER_PROFILE, result.list), - sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), - sharedPref.setString(TOKEN, result.authenticationTokenID), + await sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID), + await sharedPref.setString(TOKEN, result.authenticationTokenID), AppToast.showSuccessToast(message: TranslationBase.of(context).successRegister), checkIfUserAgreedBefore(result), projectViewModel.analytics.loginRegistration.registration_confirmation() @@ -695,6 +695,7 @@ class _RegisterInfo extends State { insertIMEI() async { var selectedOption = await sharedPref.getInt(LAST_LOGIN); authService.insertDeviceImei(selectedOption).then((value) => {goToHome()}).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); print(err); }); } @@ -705,45 +706,70 @@ class _RegisterInfo extends State { projectViewModel.isLogin = true; projectViewModel.user = authenticatedUserObject.user; await authenticatedUserObject.getUser(getUser: true); - int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; - appointmentRateViewModel.getIsLastAppointmentRatedList(languageID).then((value) { - getToDoCount(); - GifLoaderDialogUtils.hideDialog(AppGlobal.context); - if (appointmentRateViewModel.isHaveAppointmentNotRate) { - Navigator.pushAndRemoveUntil( + getToDoCount(); + GifLoaderDialogUtils.hideDialog(AppGlobal.context); + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: TranslationBase.of(context).validInsurance, + okText: TranslationBase.of(context).yes, + cancelText: TranslationBase.of(context).no, + okFunction: () { + ConfirmDialog.closeAlertDialog(context); + Navigator.pushAndRemoveUntil( context, - FadePage( - page: RateAppointmentDoctor(isFromRegistration: true), - ), - (r) => false); - } else { - ConfirmDialog dialog = new ConfirmDialog( - context: context, - confirmMessage: TranslationBase.of(context).validInsurance, - okText: TranslationBase.of(context).yes, - cancelText: TranslationBase.of(context).no, - okFunction: () { - ConfirmDialog.closeAlertDialog(context); - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) => LandingPage()), + MaterialPageRoute(builder: (context) => LandingPage()), (Route route) => false, - ); - Navigator.push(context, FadePage(page: InsuranceUpdate())); - }, - cancelFunction: () { - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) => LandingPage()), - (Route route) => false, - ); - }); - dialog.showAlertDialog(context); - } - }).catchError((err) { - print(err); - //GifLoaderDialogUtils.hideDialog(context); - }); + ); + Navigator.push(context, FadePage(page: InsuranceUpdate())); + }, + cancelFunction: () { + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => LandingPage()), + (Route route) => false, + ); + }); + dialog.showAlertDialog(context); + + // int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; + // appointmentRateViewModel.getIsLastAppointmentRatedList(languageID).then((value) { + // getToDoCount(); + // GifLoaderDialogUtils.hideDialog(AppGlobal.context); + // if (appointmentRateViewModel.isHaveAppointmentNotRate) { + // Navigator.pushAndRemoveUntil( + // context, + // FadePage( + // page: RateAppointmentDoctor(isFromRegistration: true), + // ), + // (r) => false); + // } else { + // ConfirmDialog dialog = new ConfirmDialog( + // context: context, + // confirmMessage: TranslationBase.of(context).validInsurance, + // okText: TranslationBase.of(context).yes, + // cancelText: TranslationBase.of(context).no, + // okFunction: () { + // ConfirmDialog.closeAlertDialog(context); + // Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (context) => LandingPage()), + // (Route route) => false, + // ); + // Navigator.push(context, FadePage(page: InsuranceUpdate())); + // }, + // cancelFunction: () { + // Navigator.pushAndRemoveUntil( + // context, + // MaterialPageRoute(builder: (context) => LandingPage()), + // (Route route) => false, + // ); + // }); + // dialog.showAlertDialog(context); + // } + // }).catchError((err) { + // print(err); + // //GifLoaderDialogUtils.hideDialog(context); + // }); // SMSOTP.showLoadingDialog(context, false), } diff --git a/lib/pages/login/register.dart b/lib/pages/login/register.dart index a010150d..2dd32163 100644 --- a/lib/pages/login/register.dart +++ b/lib/pages/login/register.dart @@ -2,6 +2,7 @@ import 'package:diplomaticquarterapp/analytics/flows/login_registration.dart'; import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_user_status_reponse.dart'; import 'package:diplomaticquarterapp/models/Authentication/check_user_status_req.dart'; @@ -25,6 +26,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_datetime_picker_plus/flutter_datetime_picker_plus.dart'; import 'package:intl/intl.dart' as intl; +import 'package:provider/provider.dart'; class Register extends StatefulWidget { final Function? changePageViewIndex; @@ -297,8 +299,9 @@ class _Register extends State { } checkPatientForRegisteration(request) { + int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; GifLoaderDialogUtils.showMyDialog(context); - this.authService.checkPatientForRegisteration(request).then((response) => {checkUserStatus(response, request)}).catchError((err) { + this.authService.checkPatientForRegisteration(request, languageID).then((response) => {checkUserStatus(response, request)}).catchError((err) { GifLoaderDialogUtils.hideDialog(context); ConfirmDialog dialog = new ConfirmDialog( context: context, diff --git a/lib/pages/login/user-login-agreement-page.dart b/lib/pages/login/user-login-agreement-page.dart new file mode 100644 index 00000000..f01a0c96 --- /dev/null +++ b/lib/pages/login/user-login-agreement-page.dart @@ -0,0 +1,215 @@ +import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart'; +import 'package:diplomaticquarterapp/core/viewModels/TermsConditionsViewModel.dart'; +import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; +import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; +import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart'; +import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; +import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_toast.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; +import 'package:diplomaticquarterapp/uitl/utils_new.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/custom_text_button.dart'; +import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:provider/provider.dart'; + +class UserLoginAgreementPage extends StatefulWidget { + final String userAgreementText; + final AuthenticatedUserObject authenticatedUserObject; + final AppointmentRateViewModel appointmentRateViewModel; + final int selectedOption; + + UserLoginAgreementPage({required this.userAgreementText, required this.authenticatedUserObject, required this.appointmentRateViewModel, required this.selectedOption}); + + @override + State createState() => _UserLoginAgreementPageState(); +} + +class _UserLoginAgreementPageState extends State { + late ProjectViewModel projectViewModel; + late ToDoCountProviderModel toDoProvider; + final authService = AuthProvider(); + + @override + Widget build(BuildContext context) { + projectViewModel = Provider.of(context); + toDoProvider = Provider.of(context); + return BaseView( + builder: (_, model, w) => AppScaffold( + isShowAppBar: true, + showNewAppBarTitle: true, + showNewAppBar: true, + isShowDecPage: false, + appBarTitle: TranslationBase.of(context).userAgreement, + body: Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + child: Html( + data: widget.userAgreementText, + ), + ), + ), + bottomSheet: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 7, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + padding: EdgeInsets.only(left: 21, right: 21, top: 15, bottom: 15), + width: double.infinity, + // color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: 12), + Text( + TranslationBase.of(context).continueAgreeTerms, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w600, + color: Color(0xff2B353E), + letterSpacing: -0.64, + ), + ), + SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + flex: 1, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + height: 45.0, + child: CustomTextButton( + backgroundColor: CustomColors.green, + elevation: 0, + onPressed: () { + addUsageAgreement(); + }, + child: Text(TranslationBase.of(context).acceptLbl.toUpperCase(), + style: TextStyle( + fontSize: 18.0, + color: Colors.white, + )), + ), + ), + ), + mWidth(7), + Expanded( + flex: 1, + child: ButtonTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + height: 45.0, + child: CustomTextButton( + backgroundColor: Color(0xffc5272d), + elevation: 0, + onPressed: () { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false); + }, + child: Text(TranslationBase.of(context).declineLbl.toUpperCase(), style: TextStyle(fontSize: 18.0, color: Colors.white)), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } + + addUsageAgreement() { + GifLoaderDialogUtils.showMyDialog(context); + this.authService.addUserAgreementContent().then((result) { + goToHome(); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + print(err); + }); + } + + goToHome() async { + widget.authenticatedUserObject.isLogin = true; + widget.appointmentRateViewModel.isLogin = true; + projectViewModel.isLogin = true; + projectViewModel.user = widget.authenticatedUserObject.user; + await widget.authenticatedUserObject.getUser(getUser: true); + + // GifLoaderDialogUtils.hideDialog(context); + getToDoCount(); + widget.appointmentRateViewModel + .getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2) + .then((value) => { + GifLoaderDialogUtils.hideDialog(context), + if (widget.appointmentRateViewModel.isHaveAppointmentNotRate) + { + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: RateAppointmentDoctor(), + ), + (r) => false) + } + else + { + GifLoaderDialogUtils.hideDialog(context), + Navigator.pushAndRemoveUntil( + context, + FadePage( + page: LandingPage(), + ), + (r) => false) + }, + insertIMEI() + }) + .catchError((err) { + print(err); + }); + } + + insertIMEI() { + authService.insertDeviceImei(widget.selectedOption).then((value) => {}).catchError((err) { + print(err); + }); + } + + getToDoCount() { + toDoProvider.setState(0, 0, true, "0"); + ClinicListService service = new ClinicListService(); + service.getActiveAppointmentNo(context).then((res) { + if (res['MessageStatus'] == 1) { + toDoProvider.setState(res['AppointmentActiveNumber'], res['AncillaryOrderListCount'], true, "0"); + // toDoProvider.setState(res['AppointmentActiveNumber'], true, "0"); + } else {} + }).catchError((err) { + print(err); + }); + } +} diff --git a/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart b/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart index ce69e8c0..de22c7af 100644 --- a/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart +++ b/lib/pages/medical/balance/dialogs/ConfirmSMSDialog.dart @@ -7,6 +7,7 @@ import 'package:diplomaticquarterapp/core/model/my_balance/AdvanceModel.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/patient_info_and_mobile_number.dart'; import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; @@ -363,11 +364,11 @@ class _ConfirmSMSDialogState 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/medical/balance/new_text_Field.dart b/lib/pages/medical/balance/new_text_Field.dart index b00e4274..fb9d8bed 100644 --- a/lib/pages/medical/balance/new_text_Field.dart +++ b/lib/pages/medical/balance/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'; @@ -184,7 +185,8 @@ class _NewTextFieldsState extends State { autofocus: widget.autoFocus ?? false, 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, @@ -194,9 +196,9 @@ class _NewTextFieldsState extends State { decoration: InputDecoration( labelText: widget.hintText, counterText: widget.counterText, - labelStyle: TextStyle(color: Theme.of(context).textTheme.bodyText1!.color), - 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)), + labelStyle: TextStyle(color: Colors.black), + 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/medical/sickleave_workplace_update_page.dart b/lib/pages/medical/sickleave_workplace_update_page.dart index 0e555bab..ec7991cb 100644 --- a/lib/pages/medical/sickleave_workplace_update_page.dart +++ b/lib/pages/medical/sickleave_workplace_update_page.dart @@ -25,6 +25,10 @@ class WorkplaceUpdatePage extends StatefulWidget { class _WorkplaceUpdatePageState extends State { TextEditingController workplaceName = new TextEditingController(); + + TextEditingController workplaceNameAr = new TextEditingController(); + TextEditingController occupationNameEn = new TextEditingController(); + TextEditingController occupationNameAr = new TextEditingController(); bool? _isButtonDisabled; ProjectViewModel? projectViewModel; @@ -66,7 +70,14 @@ class _WorkplaceUpdatePageState extends State { ), ), mHeight(8), - inputWidget(TranslationBase.of(context).workplaceName, "", workplaceName), + // inputWidget(TranslationBase.of(context).workplaceName, "", workplaceName), + inputWidget(TranslationBase.of(context).workplaceName, "", workplaceName, FilteringTextInputFormatter.allow(RegExp("[a-zA-Z ]"))), + mHeight(8), + inputWidget(TranslationBase.of(context).workplaceNameAr, "", workplaceNameAr, FilteringTextInputFormatter.allow(RegExp("[ء-ي ]"))), + mHeight(8), + inputWidget(TranslationBase.of(context).occupationNameEn, "", occupationNameEn, FilteringTextInputFormatter.allow(RegExp("[a-zA-Z ]"))), + mHeight(8), + inputWidget(TranslationBase.of(context).occupationNameAr, "", occupationNameAr, FilteringTextInputFormatter.allow(RegExp("[ء-ي ]"))), ], ), ), @@ -83,7 +94,7 @@ class _WorkplaceUpdatePageState extends State { height: 50, elevation: 0, color: CustomColors.accentColor, - disabledColor:Colors.grey.withOpacity(0.25), + disabledColor: Colors.grey.withOpacity(0.25), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Text( TranslationBase.of(context).submit, @@ -94,10 +105,12 @@ class _WorkplaceUpdatePageState extends State { ), ), onPressed: () { - if (_isButtonDisabled == false) + // if (_isButtonDisabled == false) + if (workplaceNameAr.text.isNotEmpty && occupationNameAr.text.isNotEmpty) + // AppToast.showSuccessToast(message: "API Called"); updateWorkplaceNameDialog(); else - AppToast.showErrorToast(message: TranslationBase.of(context).enterWorkplaceName); + AppToast.showErrorToast(message: TranslationBase.of(context).enterDetailBelow); }, ), ), @@ -109,7 +122,8 @@ class _WorkplaceUpdatePageState extends State { ); } - Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller, {String? prefix, bool isEnable = true, bool hasSelection = false}) { + Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller, TextInputFormatter inputFormatter, {String? prefix, bool isEnable = true, bool hasSelection = false}) { + // Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller, {String? prefix, bool isEnable = true, bool hasSelection = false}) { return Container( padding: EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15), alignment: Alignment.center, @@ -145,7 +159,8 @@ class _WorkplaceUpdatePageState extends State { keyboardType: TextInputType.name, controller: _controller, inputFormatters: [ - projectViewModel!.isArabic ? FilteringTextInputFormatter.allow(RegExp("[ء-ي ]")) : FilteringTextInputFormatter.allow(RegExp("[a-zA-Z ]")), + // projectViewModel!.isArabic ? FilteringTextInputFormatter.allow(RegExp("[ء-ي ]")) : FilteringTextInputFormatter.allow(RegExp("[a-zA-Z ]")), + inputFormatter ], onChanged: (value) => {_onPassportTextChanged(value)}, style: TextStyle( @@ -207,8 +222,8 @@ class _WorkplaceUpdatePageState extends State { } updateWorkplaceNameDialog() { - var messageEn = "The workplace name you entered is: " + workplaceName.text + ". Please confirm!"; - var messageAr = "اسم مكان العمل الذي أدخلته هو: " + workplaceName.text + ". يرجى تأكيد!"; + var messageEn = "The workplace name you entered is: " + workplaceNameAr.text + ". Please confirm!"; + var messageAr = "اسم مكان العمل الذي أدخلته هو: " + workplaceNameAr.text + ". يرجى تأكيد!"; ConfirmDialog dialog = new ConfirmDialog( context: context, confirmMessage: projectViewModel!.isArabic ? messageAr : messageEn, @@ -226,9 +241,10 @@ class _WorkplaceUpdatePageState extends State { LabsService service = new LabsService(); GifLoaderDialogUtils.showMyDialog(context); - service - .updateWorkplaceName(projectViewModel!.isArabic ? "-" : workplaceName.text, projectViewModel!.isArabic ? workplaceName.text : "-", widget.requestNumber, widget.setupID, widget.projectID) - .then((res) { + service.updateWorkplaceName(workplaceName.text, workplaceNameAr.text, occupationNameEn.text, occupationNameAr.text, widget.requestNumber, widget.setupID, widget.projectID).then((res) { + // service + // .updateWorkplaceName(projectViewModel!.isArabic ? "-" : workplaceName.text, projectViewModel!.isArabic ? workplaceName.text : "-", widget.requestNumber, widget.setupID, widget.projectID) + // .then((res) { GifLoaderDialogUtils.hideDialog(context); Navigator.of(context).pop(true); }).catchError((err) { diff --git a/lib/pages/medical/smart_watch_health_data/distance/distanceTracker.dart b/lib/pages/medical/smart_watch_health_data/distance/distanceTracker.dart index 0e356b78..432707ce 100644 --- a/lib/pages/medical/smart_watch_health_data/distance/distanceTracker.dart +++ b/lib/pages/medical/smart_watch_health_data/distance/distanceTracker.dart @@ -216,7 +216,7 @@ class _DistanceTrackerState extends State with SingleTickerProv (element) { weeklyTimeSeriesData.add( TimeSeriesSales2( - DateUtil.convertStringToDate(element.machineDate!), + DateUtil.convertStringToDate(element.machineDate ?? DateUtil.convertDateToString(DateTime.now())), element.value != null ? (element.value!.toDouble() / 1000) : 0.0, ), ); @@ -501,7 +501,7 @@ class _DistanceTrackerState extends State with SingleTickerProv children: [ Utils.tableColumnValue( '${DateUtil.getDayMonthYearDateFormatted( - DateUtil.convertStringToDate(step.machineDate!), + DateUtil.convertStringToDate(step.machineDate ?? DateUtil.convertDateToString(DateTime.now())), )} ', isCapitable: false, mProjectViewModel: projectViewModel), diff --git a/lib/pages/medical/smart_watch_health_data/steps/stepsTracker.dart b/lib/pages/medical/smart_watch_health_data/steps/stepsTracker.dart index fcd87cfd..a9a19945 100644 --- a/lib/pages/medical/smart_watch_health_data/steps/stepsTracker.dart +++ b/lib/pages/medical/smart_watch_health_data/steps/stepsTracker.dart @@ -212,7 +212,7 @@ class _StepsTrackerState extends State with SingleTickerProviderSt (element) { weeklyTimeSeriesData.add( TimeSeriesSales2( - DateUtil.convertStringToDate(element.machineDate!), + DateUtil.convertStringToDate(element.machineDate ?? DateUtil.convertDateToString(DateTime.now())), element.value != null ? element.value!.toDouble() : 0.0, ), ); @@ -527,7 +527,7 @@ class _StepsTrackerState extends State with SingleTickerProviderSt children: [ Utils.tableColumnValue( '${DateUtil.getDayMonthYearDateFormatted( - DateUtil.convertStringToDate(step.machineDate!), + DateUtil.convertStringToDate(step.machineDate ?? DateUtil.convertDateToString(DateTime.now())), )} ', isCapitable: false, mProjectViewModel: projectViewModel), diff --git a/lib/pages/medical/smart_watch_health_data/syncHealthData.dart b/lib/pages/medical/smart_watch_health_data/syncHealthData.dart index e6ec5c9a..6d6fdf4f 100644 --- a/lib/pages/medical/smart_watch_health_data/syncHealthData.dart +++ b/lib/pages/medical/smart_watch_health_data/syncHealthData.dart @@ -34,7 +34,7 @@ class _syncHealthDataButtonState extends State { int MedCategoryID = 0; - HealthFactory health = HealthFactory(); + // HealthFactory health = HealthFactory(); List types = [HealthDataType.STEPS, HealthDataType.HEART_RATE, Platform.isAndroid ? HealthDataType.DISTANCE_DELTA : HealthDataType.DISTANCE_WALKING_RUNNING]; @override @@ -48,29 +48,29 @@ class _syncHealthDataButtonState extends State { } checkPermissions() async { - if (Platform.isAndroid) { - if (await PermissionService.isHealthDataPermissionEnabled()) { - await health.requestAuthorization(types).then((value) { - if (value) { - readAll(); - } - }); - } else { - Utils.showPermissionConsentDialog(context, TranslationBase.of(context).physicalActivityPermission, () async { - await health.requestAuthorization(types).then((value) { - if (value) { - readAll(); - } - }); - }); - } - } else { - await health.requestAuthorization(types).then((value) { - if (value) { - readAll(); - } - }); - } + // if (Platform.isAndroid) { + // if (await PermissionService.isHealthDataPermissionEnabled()) { + // await health.requestAuthorization(types).then((value) { + // if (value) { + // readAll(); + // } + // }); + // } else { + // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).physicalActivityPermission, () async { + // await health.requestAuthorization(types).then((value) { + // if (value) { + // readAll(); + // } + // }); + // }); + // } + // } else { + // await health.requestAuthorization(types).then((value) { + // if (value) { + // readAll(); + // } + // }); + // } } void readAll() async { @@ -83,13 +83,13 @@ class _syncHealthDataButtonState extends State { DateTime startDate = DateTime.now().subtract(new Duration(days: 30)); try { - List healthData = await health.getHealthDataFromTypes(startDate, DateTime.now(), types); - _healthDataList.addAll(healthData); + // List healthData = await health.getHealthDataFromTypes(startDate, DateTime.now(), types); + // _healthDataList.addAll(healthData); } catch (e) { print("Caught exception in getHealthDataFromTypes: $e"); } - _healthDataList = HealthFactory.removeDuplicates(_healthDataList); + // _healthDataList = HealthFactory.removeDuplicates(_healthDataList); _healthDataList.forEach((x) { if (x.type == HealthDataType.STEPS) { diff --git a/lib/pages/paymentService/payment_service.dart b/lib/pages/paymentService/payment_service.dart index 1878a658..29161b50 100644 --- a/lib/pages/paymentService/payment_service.dart +++ b/lib/pages/paymentService/payment_service.dart @@ -71,9 +71,9 @@ class PaymentService extends StatelessWidget { projectViewModel!.analytics.advancePayments.payment_services(service_type: 'payment service'); }, child: MedicalProfileItem( - title: TranslationBase.of(context).payment, + title: TranslationBase.of(context).onlinePayment, imagePath: 'assets/images/new-design/online_payment_icon.png', - subTitle: TranslationBase.of(context).paymentOnline, + subTitle: TranslationBase.of(context).onlinePaymentSubtitle, isPngImage: true, width: 65.0, height: 55.0, @@ -182,19 +182,25 @@ class PaymentService extends StatelessWidget { ClinicListService service = new ClinicListService(); GifLoaderDialogUtils.showMyDialog(context); service - .getInPatientAdvancePaymentRequests(projectViewModel.inPatientProjectID, projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionNo! : 0, - projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionRequestNo! : projectViewModel.getAdmissionRequestInfoResponseModel.admissionRequestNo!, context) + .getInPatientAdvancePaymentRequests( + projectViewModel.inPatientProjectID, + projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionNo! : 0, + projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionRequestNo! : projectViewModel.getAdmissionRequestInfoResponseModel.admissionRequestNo!, + projectViewModel.isArabic ? 1 : 2, + context) .then((res) { GifLoaderDialogUtils.hideDialog(context); if (res["MessageStatus"] == 1) { if (res['responseInpatient'] != null) { inPatientAdvanceResponseModel = InPatientAdvanceResponseModel.fromJson(res["responseInpatient"]); - Navigator.push(context, FadePage(page: InPatientAdvancePayment(isHasData: inPatientAdvanceResponseModel.responseInpatientAdvanceInfo != null, inPatientAdvanceResponseModel: inPatientAdvanceResponseModel))); + Navigator.push(context, + FadePage(page: InPatientAdvancePayment(isHasData: inPatientAdvanceResponseModel.responseInpatientAdvanceInfo != null, inPatientAdvanceResponseModel: inPatientAdvanceResponseModel))); } else { AppToast.showErrorToast(message: TranslationBase.of(context).noData); } } else { - Navigator.push(context, FadePage(page: InPatientAdvancePayment(isHasData: inPatientAdvanceResponseModel.responseInpatientAdvanceInfo != null, inPatientAdvanceResponseModel: inPatientAdvanceResponseModel))); + Navigator.push(context, + FadePage(page: InPatientAdvancePayment(isHasData: inPatientAdvanceResponseModel.responseInpatientAdvanceInfo != null, inPatientAdvanceResponseModel: inPatientAdvanceResponseModel))); } }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); diff --git a/lib/pages/rateAppointment/rate_appointment_clinic.dart b/lib/pages/rateAppointment/rate_appointment_clinic.dart index 44484373..4dbc3edd 100644 --- a/lib/pages/rateAppointment/rate_appointment_clinic.dart +++ b/lib/pages/rateAppointment/rate_appointment_clinic.dart @@ -75,7 +75,7 @@ class _RateAppointmentClinicState extends State { style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), ), Text( - model.appointmentDetails.startTime.toString().substring(0, 5), + model.appointmentDetails.startTime != "" ? model.appointmentDetails.startTime.toString().substring(0, 5) : "", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64, height: 25 / 16), ), ], diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index aaf30b97..2b039701 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -28,13 +28,13 @@ class DoctorsListService extends BaseService { AuthenticatedUser authUser = new AuthenticatedUser(); AuthProvider authProvider = new AuthProvider(); - double? lat; - double? long; - String? deviceToken; + double? lat; + double? long; + String? deviceToken; String? tokenID; List selectedBodyPartList = []; - Future getDoctorsList(int clinicID, int projectID, bool isNearest, int languageID, BuildContext context, {doctorId, doctorName, isContinueDentalPlan = false}) async { + Future getDoctorsList(int clinicID, int projectID, bool isNearest, int languageID, BuildContext? context, {doctorId, doctorName, isContinueDentalPlan = false}) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { @@ -92,8 +92,8 @@ class DoctorsListService extends BaseService { Future getDoctorsListByName(String docName, int languageID, BuildContext context) async { Map request; - late double lat; - late double long; + late double lat = 0.0; + late double long = 0.0; if (await this.sharedPref.getObject(USER_PROFILE) != null) { var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); @@ -334,8 +334,60 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future insertWalkInAppointment(int docID, int clinicID, int projectID, String selectedTime, String selectedDate, int initialSlotDuration, int languageID, BuildContext context) async { + Map request; + + if (await this.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); + authUser = data; + } + + Request req = appGlobal.getPublicRequest(); + request = { + "IsForLiveCare": false, + "ProjectID": projectID, + "ClinicID": clinicID, + "DoctorID": docID, + "StartTime": selectedTime, + "SelectedTime": selectedTime, + "EndTime": selectedTime, + "InitialSlotDuration": initialSlotDuration, + "StrAppointmentDate": selectedDate, + "IsVirtual": false, + "DeviceType": Platform.isIOS ? 'iOS' : 'Android', + "BookedBy": 102, + "VisitType": 1, + "VisitFor": 1, + "GenderID": authUser.gender, + "Age": authUser.age != null ? authUser.age : 0, + "VersionID": req.VersionID, + "Channel": req.Channel, + "IPAdress": req.IPAdress, + "generalid": req.generalid, + "PatientOutSA": authUser.outSA, + "SessionID": "YckwoXhUmWBsnHKEKig", + "isDentalAllowedBackend": false, + "DeviceTypeID": req.DeviceTypeID, + "PatientID": authUser.patientID, + "PatientTypeID": authUser.patientType, + "PatientType": authUser.patientType + }; + + dynamic localRes; + try { + await baseAppClient.post(INSERT_WALKIN_APPOINTMENT, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } catch (e) { + return Future.error(e); + } + } + Future insertAppointment(int docID, int clinicID, int projectID, String selectedTime, String selectedDate, int initialSlotDuration, int languageID, BuildContext context, - [String? procedureID, num? testTypeEnum, num? testProcedureEnum, ProjectViewModel? projectViewModel]) async { + [String? procedureID, num? testTypeEnum, num? testProcedureEnum, ProjectViewModel? projectViewModel, int? invoiceNumber, int? lineItemNo, String? invoiceNoVP]) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { @@ -374,7 +426,11 @@ class DoctorsListService extends BaseService { "DeviceTypeID": req.DeviceTypeID, "PatientID": authUser.patientID, "PatientTypeID": authUser.patientType, - "PatientType": authUser.patientType + "PatientType": authUser.patientType, + "InvoiceNo": invoiceNumber, + "InvoiceNo_VP": invoiceNoVP, + "LineItemNo": lineItemNo, + // "TokenID":"@dm!n" }; if (clinicID == 253) { @@ -509,6 +565,26 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future checkPatientHasDermaPackage(int patientID, int clinicID, int projectID, int doctorID, int languageID, BuildContext context) async { + Map request; + + if (await this.sharedPref.getObject(USER_PROFILE) != null) { + var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); + authUser = data; + } + request = {"PatientID": patientID, "ClinicID": clinicID, "ProjectID": projectID, "LanguageID": languageID}; + //request = { "PatientID":4768732, "ClinicID":1, "ProjectID": 15, "LanguageID": languageID, "TokenID":"@dm!n" }; + + dynamic localRes; + + await baseAppClient.post(CHECK_PATIENT_DERMA_PACKAGE, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + Future getLiveCareAppointmentPatientShare(String appoID, int clinicID, int projectID, int languageID, BuildContext context) async { Map request; @@ -615,6 +691,32 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future getPatientShareForWalkInAppointment(int clinicID, int projectID, int doctorID) async { + Map request; + request = {"ProjectID": projectID, "ClinicID": clinicID, "DoctorID": doctorID}; + dynamic localRes; + await baseAppClient.post(GET_PATIENT_SHARE_FOR_WALKIN_APPOINTMENT, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + + return Future.value(localRes); + } + + Future canPayForWalkInAppointment(int clinicID, int projectID, int doctorID) async { + Map request; + request = {"ProjectID": projectID, "ClinicID": clinicID, "DoctorID": doctorID, "StartTime": "12:00", "EndTime": "12:00"}; + dynamic localRes; + await baseAppClient.post(CAN_PAY_FOR_FOR_WALKIN_APPOINTMENT, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + + return Future.value(localRes); + } + Future getPatientAppointmentHistory(bool isActiveAppointment, int languageID, BuildContext context, {bool isForCOC = false, isForUpcomming = false, IsForArrived = false}) async { Map request; @@ -1373,7 +1475,7 @@ class DoctorsListService extends BaseService { Future HIS_createAdvancePayment(AppoitmentAllHistoryResultList appo, String projectID, double payedAmount, String paymentReference, String paymentMethodName, dynamic patientType, String patientName, dynamic patientID, BuildContext context, - {bool isAncillaryOrder = false}) async { + {bool isAncillaryOrder = false, int clinicID = 0}) async { Map request; if (await this.sharedPref.getObject(USER_PROFILE) != null) { var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); @@ -1428,12 +1530,12 @@ class DoctorsListService extends BaseService { Request req = appGlobal.getPublicRequest(); request = { - "VersionID": req.VersionID, - "Channel": req.Channel, - "IPAdress": req.IPAdress, - "generalid": req.generalid, - "PatientOutSA": authUser.outSA, - "PatientTypeID": authUser.patientType, + // "VersionID": req.VersionID, + // "Channel": req.Channel, + // "IPAdress": req.IPAdress, + // "generalid": req.generalid, + // "PatientOutSA": authUser.outSA, + // "PatientTypeID": authUser.patientType, "LanguageID": 1, "ERAdvanceAmount": { "ProjectId": projectID, @@ -1535,10 +1637,10 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } - Future sendCheckinNfcRequest(int appointmentNo, String nfcCode, int projectId, int checkInBy, BuildContext context) async { + Future sendCheckinNfcRequest(int appointmentNo, String nfcCode, int projectId, int checkInBy, int clinicID, BuildContext context) async { Map request; - request = {"AppointmentNo": appointmentNo, "NFC_Code": nfcCode, "ProjectID": projectId, "CheckinBy": checkInBy}; + request = {"AppointmentNo": appointmentNo, "NFC_Code": nfcCode, "ProjectID": projectId, "ClinicID": clinicID, "CheckinBy": checkInBy}; dynamic localRes; await baseAppClient.post(SEND_CHECK_IN_NFC_REQUEST, onSuccess: (response, statusCode) async { localRes = response; @@ -1548,6 +1650,19 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future checkScannedNFCAndQRCode(String nfcCode, int projectId) async { + Map request; + + request = {"NFC_Code": nfcCode, "ProjectID": projectId}; + dynamic localRes; + await baseAppClient.post(CHECK_SCANNED_NFC_QR_CODE, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + Future checkIfHasDentalPlan(int projectID, BuildContext context) async { Map request; @@ -1765,6 +1880,32 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } + Future autoGenerateInvoiceERClinic(int? projectID, int? paymentMethod, String? paymentReferenceNo, num? amount, String? cardType, String? cardNumber, String? orderID, String? rrn, bool isAdvanceAvailable) async { + Map request; + request = { + "ProjectID": projectID, + "ClinicID": "10", + // "PaymentMethod": paymentMethod, + "PaymentMethod": "VISA", + "PaymentReferenceNo": paymentReferenceNo, + "PaymentAmount": amount, + "CardType": cardType, + "CardNumber": cardNumber, + "OrderId": orderID, + "MemberID": 102, + "RRN": rrn, + "IsAdvanceAvailable": isAdvanceAvailable + }; + dynamic localRes; + await baseAppClient.post(AUTO_GENERATE_INVOICE_ER, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + + return Future.value(localRes); + } + Future checkPatientNphiesEligibility(int projectID) async { Map request; request = {"ProjectID": projectID, "LanguageID": 1}; diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart index 1a61ecca..81a3dfad 100644 --- a/lib/services/authentication/auth_provider.dart +++ b/lib/services/authentication/auth_provider.dart @@ -339,12 +339,12 @@ class AuthProvider with ChangeNotifier { return authenticatedUser; } - Future checkPatientForRegisteration(CheckPatientForRegistration request) async { + Future checkPatientForRegisteration(CheckPatientForRegistration request, int languageID) async { request.versionID = VERSION_ID; request.channel = CHANNEL; request.iPAdress = IP_ADDRESS; request.generalid = GENERAL_ID; - request.languageID = (languageID == 'ar' ? 1 : 2); + request.languageID = languageID; request.deviceTypeID = Platform.isIOS ? 1 : 2; request.isRegister = false; // request.tokenID = ''; @@ -410,6 +410,1282 @@ class AuthProvider with ChangeNotifier { dynamic localRes; try { + // localRes = { + // "Date": null, + // "LanguageID": 0, + // "ServiceName": 0, + // "Time": null, + // "AndroidLink": null, + // "AuthenticationTokenID": "d+TXwG6BFkSjRuFPvTdSwA==", + // "Data": null, + // "Dataw": false, + // "DietType": 0, + // "DietTypeID": 0, + // "ErrorCode": null, + // "ErrorEndUserMessage": "Patient verified Successfully", + // "ErrorEndUserMessageN": null, + // "ErrorMessage": null, + // "ErrorStatusCode": 0, + // "ErrorType": 0, + // "FoodCategory": 0, + // "IOSLink": null, + // "IsAuthenticated": true, + // "MealOrderStatus": 0, + // "MealType": 0, + // "MessageStatus": 1, + // "NumberOfResultRecords": 0, + // "PatientBlodType": null, + // "SuccessMsg": null, + // "SuccessMsgN": null, + // "VidaUpdatedResponse": null, + // "DoctorInformation_List": null, + // "GetAllPendingRecordsList": null, + // "GetAllSharedRecordsByStatusList": null, + // "GetResponseFileList": null, + // "IsHMGPatient": false, + // "IsLoginSuccessfully": false, + // "IsNeedUpdateIdintificationNo": false, + // "IsPatientAuthorized": false, + // "IsVidaPlus": false, + // "KioskSendSMS": false, + // "List": [ + // { + // "SetupID": "010266", + // "PatientType": 1, + // "PatientID": 5318335, + // "FirstName": "SYED TAHA", + // "MiddleName": "ALAM", + // "LastName": "ALAM", + // "FirstNameN": "سيد طه", + // "MiddleNameN": "علام", + // "LastNameN": "علام", + // "RelationshipID": 0, + // "Gender": 1, + // "DateofBirth": "/Date(839106000000+0300)/", + // "DateofBirthN": null, + // "NationalityID": "PAK", + // "PhoneResi": " ", + // "PhoneOffice": " ", + // "MobileNumber": "0560960398", + // "FaxNumber": " ", + // "EmailAddress": "testtaha@gmail.com", + // "BloodGroup": null, + // "RHFactor": null, + // "IsEmailAlertRequired": false, + // "IsSMSAlertRequired": true, + // "PreferredLanguage": "1", + // "IsPrivilegedMember": false, + // "MemberID": null, + // "ExpiryDate": null, + // "IsHmgEmployee": null, + // "EmployeeID": null, + // "EmergencyContactName": "", + // "EmergencyContactNo": "", + // "PatientPayType": 0, + // "DHCCPatientRefID": null, + // "IsPatientDummy": false, + // "Status": 2, + // "IsStatusCleared": null, + // "PatientIdentificationType": 2, + // "PatientIdentificationNo": "2579628724", + // "ProjectID": 15, + // "InfoSourceID": 0, + // "Address": "", + // "Age": 28, + // "AgeDesc": "28 Yr", + // "AreaID": 0, + // "CRSVerificationStatus": 2, + // "CRSVerificationStatusDesc": "verified", + // "CRSVerificationStatusDescN": "تم التوثيق", + // "CreatedBy": 0, + // "GenderDescription": "Male", + // "HealthIDFromNHICViaVida": "2bcc1b1a-96b7-4f33-86e2-fa955d0e3764", + // "IR": null, + // "ISOCityID": null, + // "ISOCountryID": null, + // "IsVerfiedFromNHIC": true, + // "ListPrivilege": [ + // { + // "ID": 1, + // "ServiceName": "Notifications", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 2, + // "ServiceName": "Family Files", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 3, + // "ServiceName": "Settings", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 4, + // "ServiceName": "My Profile", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 5, + // "ServiceName": "My Appointment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 6, + // "ServiceName": "My Doctors", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 7, + // "ServiceName": "Radiology", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 8, + // "ServiceName": "Radiology Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 9, + // "ServiceName": "Radiology View Image", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 10, + // "ServiceName": "Lab Results", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 11, + // "ServiceName": "Lab Results Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 12, + // "ServiceName": "Precriptions", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 13, + // "ServiceName": "Precriptions Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 14, + // "ServiceName": "Eye Measurments", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 15, + // "ServiceName": "Eye Measurments Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 16, + // "ServiceName": "Sick Leaves", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 17, + // "ServiceName": "Sick Leaves Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 18, + // "ServiceName": "Approvals", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 19, + // "ServiceName": "Monthly Reports", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 20, + // "ServiceName": "Request Medical Report", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 21, + // "ServiceName": "Request Medical Report Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 22, + // "ServiceName": "Insurance Cards", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 23, + // "ServiceName": "Allergies", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 24, + // "ServiceName": "My Trackers", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 25, + // "ServiceName": "Vital Signs", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 26, + // "ServiceName": "My Vaccines", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 27, + // "ServiceName": "My Vaccines Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 28, + // "ServiceName": "Ask Doctors", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 29, + // "ServiceName": "Live Chat", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 30, + // "ServiceName": "Health Data", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 31, + // "ServiceName": "Online Check-in", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 32, + // "ServiceName": "Connect to internet", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 33, + // "ServiceName": "Advance Payment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 34, + // "ServiceName": "Book Appointment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 35, + // "ServiceName": "Child Vaccines", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 36, + // "ServiceName": "Blood Donation", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 38, + // "ServiceName": "H2O", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 40, + // "ServiceName": "ChatBot", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 41, + // "ServiceName": "Parking", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 42, + // "ServiceName": "SymptomChecker", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 47, + // "ServiceName": "AdvanceBalance", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 48, + // "ServiceName": "ActiveMedications", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 49, + // "ServiceName": "VaccineAvailability", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 51, + // "ServiceName": "UpcomingAppointment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 52, + // "ServiceName": "PushNotificationCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 53, + // "ServiceName": "ActiveMedicationCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 54, + // "ServiceName": "LabOrderUnreadCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 55, + // "ServiceName": "RadOrderUnreadCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 56, + // "ServiceName": "MedicalReportUnreadCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 57, + // "ServiceName": "ERWaittingTimeShowing", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 58, + // "ServiceName": "OnlinePayment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 59, + // "ServiceName": "RadiologyDisplayImage", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 60, + // "ServiceName": "EmergencyConsultation", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 61, + // "ServiceName": "PatientQueueCall", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 62, + // "ServiceName": "OnlinePrescriptionOrder", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 63, + // "ServiceName": "Transportations", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 64, + // "ServiceName": "HomeHealthCareService", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 65, + // "ServiceName": "Al-HabibPharmacyOnline", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 66, + // "ServiceName": "Al-HabibOffers", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 67, + // "ServiceName": "ComprehensiveMedicalCheckup", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 68, + // "ServiceName": "RRT", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 72, + // "ServiceName": "CancelLiveCareRequest", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 74, + // "ServiceName": "Exacart", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 76, + // "ServiceName": "Covid19-CarThrow", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 77, + // "ServiceName": "VoiceBot", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 78, + // "ServiceName": "LiveCareBookOnDoctorSchedule", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 79, + // "ServiceName": "CheckIn_QR", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 80, + // "ServiceName": "CheckIn_NFC", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 81, + // "ServiceName": "ED", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 82, + // "ServiceName": "Packages_&_Offers", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 83, + // "ServiceName": "Lakum_Points", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 84, + // "ServiceName": "QR_Reader", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 85, + // "ServiceName": "AncillaryOrders", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 86, + // "ServiceName": "Payment-MADA", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 87, + // "ServiceName": "Payment-VISA", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 88, + // "ServiceName": "Payment-MasterCard", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 89, + // "ServiceName": "Payment-ApplePay", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 90, + // "ServiceName": "Payment-Tamara", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 91, + // "ServiceName": "Payment-Installment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 92, + // "ServiceName": "ED-Checkin", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 93, + // "ServiceName": "NetworkDebug", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 94, + // "ServiceName": "TamaraAncillary", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 95, + // "ServiceName": "Verif-Face", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 96, + // "ServiceName": "Verif-Finger", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 97, + // "ServiceName": "Verif-SMS", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 98, + // "ServiceName": "Verif-WhatsApp", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 99, + // "ServiceName": "PharmacyLivecare", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 100, + // "ServiceName": "ePharmacy", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 102, + // "ServiceName": "CheckIn_Geofence", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 103, + // "ServiceName": "Payment-ApplePay-Web", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 104, + // "ServiceName": "Livecare_Zoom", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 105, + // "ServiceName": "Dental Virtual Tour", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 106, + // "ServiceName": "Dental Medical Instructions", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 107, + // "ServiceName": "Navigation Service", + // "Previlege": false, + // "Region": null + // } + // ], + // "Marital": null, + // "OutSA": 0, + // "POBox": "", + // "ReceiveHealthSummaryReport": false, + // "SourceType": 0, + // "StrDateofBirth": null, + // "TempAddress": "", + // "ZipCode": "", + // "eHealthIDField": null, + // "patientPayType": null, + // "patientType": null, + // "status": null + // } + // ], + // "List_AskHabibMobileLoginInfo": null, + // "List_AskHabibPatientFile": null, + // "List_FamilyRelationships": null, + // "List_MergeFiles": null, + // "List_MobileLoginInfo": null, + // "List_PatientCount": null, + // "LogInTokenID": null, + // "MohemmPrivilege_List": null, + // "PateintID": 5318335, + // "PatientBloodType": "", + // "PatientER_AdminDriverFileList": null, + // "PatientER_AdminFile": null, + // "PatientER_DriverFile": null, + // "PatientER_DriverFileList": null, + // "PatientHasFile": false, + // "PatientMergedIDs": null, + // "PatientOutSA": false, + // "PatientShareRequestID": 0, + // "PatientType": 0, + // "ProjectIDOut": 0, + // "ReturnMessage": null, + // "SMSLoginRequired": false, + // "ServicePrivilege_List": [ + // { + // "ID": 1, + // "ServiceName": "Notifications", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 2, + // "ServiceName": "Family Files", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 3, + // "ServiceName": "Settings", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 4, + // "ServiceName": "My Profile", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 5, + // "ServiceName": "My Appointment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 6, + // "ServiceName": "My Doctors", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 7, + // "ServiceName": "Radiology", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 8, + // "ServiceName": "Radiology Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 9, + // "ServiceName": "Radiology View Image", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 10, + // "ServiceName": "Lab Results", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 11, + // "ServiceName": "Lab Results Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 12, + // "ServiceName": "Precriptions", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 13, + // "ServiceName": "Precriptions Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 14, + // "ServiceName": "Eye Measurments", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 15, + // "ServiceName": "Eye Measurments Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 16, + // "ServiceName": "Sick Leaves", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 17, + // "ServiceName": "Sick Leaves Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 18, + // "ServiceName": "Approvals", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 19, + // "ServiceName": "Monthly Reports", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 20, + // "ServiceName": "Request Medical Report", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 21, + // "ServiceName": "Request Medical Report Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 22, + // "ServiceName": "Insurance Cards", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 23, + // "ServiceName": "Allergies", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 24, + // "ServiceName": "My Trackers", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 25, + // "ServiceName": "Vital Signs", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 26, + // "ServiceName": "My Vaccines", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 27, + // "ServiceName": "My Vaccines Email", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 28, + // "ServiceName": "Ask Doctors", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 29, + // "ServiceName": "Live Chat", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 30, + // "ServiceName": "Health Data", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 31, + // "ServiceName": "Online Check-in", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 32, + // "ServiceName": "Connect to internet", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 33, + // "ServiceName": "Advance Payment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 34, + // "ServiceName": "Book Appointment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 35, + // "ServiceName": "Child Vaccines", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 36, + // "ServiceName": "Blood Donation", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 38, + // "ServiceName": "H2O", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 40, + // "ServiceName": "ChatBot", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 41, + // "ServiceName": "Parking", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 42, + // "ServiceName": "SymptomChecker", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 47, + // "ServiceName": "AdvanceBalance", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 48, + // "ServiceName": "ActiveMedications", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 49, + // "ServiceName": "VaccineAvailability", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 51, + // "ServiceName": "UpcomingAppointment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 52, + // "ServiceName": "PushNotificationCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 53, + // "ServiceName": "ActiveMedicationCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 54, + // "ServiceName": "LabOrderUnreadCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 55, + // "ServiceName": "RadOrderUnreadCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 56, + // "ServiceName": "MedicalReportUnreadCount", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 57, + // "ServiceName": "ERWaittingTimeShowing", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 58, + // "ServiceName": "OnlinePayment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 59, + // "ServiceName": "RadiologyDisplayImage", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 60, + // "ServiceName": "EmergencyConsultation", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 61, + // "ServiceName": "PatientQueueCall", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 62, + // "ServiceName": "OnlinePrescriptionOrder", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 63, + // "ServiceName": "Transportations", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 64, + // "ServiceName": "HomeHealthCareService", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 65, + // "ServiceName": "Al-HabibPharmacyOnline", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 66, + // "ServiceName": "Al-HabibOffers", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 67, + // "ServiceName": "ComprehensiveMedicalCheckup", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 68, + // "ServiceName": "RRT", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 72, + // "ServiceName": "CancelLiveCareRequest", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 74, + // "ServiceName": "Exacart", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 76, + // "ServiceName": "Covid19-CarThrow", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 77, + // "ServiceName": "VoiceBot", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 78, + // "ServiceName": "LiveCareBookOnDoctorSchedule", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 79, + // "ServiceName": "CheckIn_QR", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 80, + // "ServiceName": "CheckIn_NFC", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 81, + // "ServiceName": "ED", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 82, + // "ServiceName": "Packages_&_Offers", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 83, + // "ServiceName": "Lakum_Points", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 84, + // "ServiceName": "QR_Reader", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 85, + // "ServiceName": "AncillaryOrders", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 86, + // "ServiceName": "Payment-MADA", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 87, + // "ServiceName": "Payment-VISA", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 88, + // "ServiceName": "Payment-MasterCard", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 89, + // "ServiceName": "Payment-ApplePay", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 90, + // "ServiceName": "Payment-Tamara", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 91, + // "ServiceName": "Payment-Installment", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 92, + // "ServiceName": "ED-Checkin", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 93, + // "ServiceName": "NetworkDebug", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 94, + // "ServiceName": "TamaraAncillary", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 95, + // "ServiceName": "Verif-Face", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 96, + // "ServiceName": "Verif-Finger", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 97, + // "ServiceName": "Verif-SMS", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 98, + // "ServiceName": "Verif-WhatsApp", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 99, + // "ServiceName": "PharmacyLivecare", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 100, + // "ServiceName": "ePharmacy", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 102, + // "ServiceName": "CheckIn_Geofence", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 103, + // "ServiceName": "Payment-ApplePay-Web", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 104, + // "ServiceName": "Livecare_Zoom", + // "Previlege": false, + // "Region": null + // }, + // { + // "ID": 105, + // "ServiceName": "Dental Virtual Tour", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 106, + // "ServiceName": "Dental Medical Instructions", + // "Previlege": true, + // "Region": null + // }, + // { + // "ID": 107, + // "ServiceName": "Navigation Service", + // "Previlege": false, + // "Region": null + // } + // ], + // "SharePatientName": null, + // "UserAccountIsActivated": false, + // "VerificationCode": null, + // "email": null, + // "errorList": null, + // "hasFile": false, + // "isActiveCode": false, + // "isMerged": false, + // "isNeedUserAgreement": false, + // "isSMSSent": false, + // "memberList": null, + // "message": "Patient Registered Successfully", + // "statusCode": 1 + // }; await new BaseAppClient().post(REGISTER_USER, onSuccess: (dynamic response, int statusCode) { localRes = response; }, onFailure: (String error, int statusCode) { @@ -458,7 +1734,7 @@ class AuthProvider with ChangeNotifier { Request req = appGlobal.getPublicRequest(); request = { - "PatientOutSA": zipCode == '+966' ? 0 : 1, + "PatientOutSA": zipCode == '966' ? 0 : 1, "PatientMobileNumber": mobileNo, "SearchType": 2, "ZipCode": zipCode, @@ -499,6 +1775,60 @@ class AuthProvider with ChangeNotifier { } } + Future checkIfUserAgreed() async { + Map request; + request = {"Region": 1}; + dynamic localRes; + try { + await new BaseAppClient().post(CHECK_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request); + return Future.value(localRes); + } catch (error) { + throw error; + } + } + + Future getUserAgreementContent() async { + Map request; + request = {"Region": 1}; + dynamic localRes; + try { + await new BaseAppClient().post(GET_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request); + return Future.value(localRes); + } catch (error) { + throw error; + } + } + + Future addUserAgreementContent() async { + Map request; + request = {"Region": 1}; + dynamic localRes; + try { + await new BaseAppClient().post(ADD_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + localRes = error; + return Future.value(error); + // throw error; + }, body: request); + return Future.value(localRes); + } catch (error) { + throw error; + } + } + Future getDashboard() async { Map request = {}; diff --git a/lib/services/clinic_services/get_clinic_service.dart b/lib/services/clinic_services/get_clinic_service.dart index dc494a61..4aa10e51 100644 --- a/lib/services/clinic_services/get_clinic_service.dart +++ b/lib/services/clinic_services/get_clinic_service.dart @@ -34,6 +34,19 @@ class ClinicListService extends BaseService { return Future.value(localRes); } + Future getClinicByHospital({required String projectID}) async { + Map request = {"ProjectID": projectID}; + + dynamic localRes; + + await baseAppClient.post(GET_CLINICS_LIST_WRT_HOSPITAL_URL, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + Future getActiveAppointmentNo(context) async { Map request = {}; @@ -156,6 +169,7 @@ class ClinicListService extends BaseService { }, body: request); return Future.value(localRes); } + Future getInPatientAdvancePaymentHistory(int projectID, int admissionNo, int admissionReqNo, context) async { Map request; request = {"ProjectID": projectID, "AdmissionNo": admissionNo, "AdmissionReqNo": admissionReqNo}; @@ -200,6 +214,7 @@ class ClinicListService extends BaseService { }, body: request, isAllowAny: true); return Future.value(localRes); } + Future submitBirthNotification(num motherMRN, int projectID, String fatherNameAR, String fatherNameEN, String babyNameAR, String babyNameEN, String contactNum, String idImage, context) async { Map request; request = { @@ -223,8 +238,8 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future insertInPatientOrder(GetAdmissionInfoResponseModel getAdmissionInfoResponseModel, int typeID, String patientName, String patientNameAR, String patientMobileNo, String comments, - context) async { + Future insertInPatientOrder( + GetAdmissionInfoResponseModel getAdmissionInfoResponseModel, int typeID, String patientName, String patientNameAR, String patientMobileNo, String comments, context) async { Map request; request = { "ProjectID": getAdmissionInfoResponseModel.projectID, @@ -249,9 +264,9 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future getGeneralInstructions(int projectID, context) async { + Future getGeneralInstructions(int projectID, int languageID, context) async { Map request; - request = {"ProjectID": projectID}; + request = {"ProjectID": projectID, "LanguageID": languageID}; dynamic localRes; @@ -262,9 +277,10 @@ class ClinicListService extends BaseService { }, body: request, isAllowAny: true); return Future.value(localRes); } - Future getMedicalInstructions(int projectID, context) async { + + Future getMedicalInstructions(int projectID, int languageID, context) async { Map request; - request = {"ProjectID": projectID}; + request = {"ProjectID": projectID, "LanguageID": languageID}; dynamic localRes; @@ -276,9 +292,9 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future getInPatientAdvancePaymentRequests(int projectID, int admissionNo, int admissionReqNo, context) async { + Future getInPatientAdvancePaymentRequests(int projectID, int admissionNo, int admissionReqNo, int languageID, context) async { Map request; - request = {"ProjectID": projectID, "AdmissionReqNo": admissionReqNo, "AdmissionNo": admissionNo}; + request = {"ProjectID": projectID, "AdmissionReqNo": admissionReqNo, "AdmissionNo": admissionNo, "LanguageID": languageID}; dynamic localRes; @@ -290,11 +306,9 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future getBirthNotification(num motherMRN, context) async { + Future getBirthNotification(num motherMRN, int languageID, context) async { Map request; - request = { - "mothermrn": motherMRN, - }; + request = {"mothermrn": motherMRN, "LanguageID": languageID}; dynamic localRes; @@ -319,6 +333,7 @@ class ClinicListService extends BaseService { }, body: request, isAllowAny: true); return Future.value(localRes); } + Future getCurrentWeekIDAndDay(BuildContext context) async { dynamic localRes; await baseAppClient.get(GET_CURRENT_WEEKID_WEEKDAY, isExternal: false, isRCService: false, onSuccess: (response, statusCode) async { @@ -400,6 +415,7 @@ class ClinicListService extends BaseService { }, body: request, isAllowAny: true); return Future.value(localRes); } + Future checkIfInPatientAPI(context) async { Map request; request = { @@ -416,7 +432,6 @@ class ClinicListService extends BaseService { return Future.value(localRes); } - Future getWeCareURL(int projectID) async { Map request = {"ProjectID": projectID}; dynamic localRes; @@ -439,4 +454,109 @@ class ClinicListService extends BaseService { return Future.value(localRes); } + Future getEROnlineCheckInPaymentDetails(int projectID, int clinicID) async { + Map request = {"ProjectID": projectID, "ClinicID": clinicID}; + dynamic localRes; + await baseAppClient.post(GET_ER_ONLINE_PAYMENT_DETAILS, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request); + return Future.value(localRes); + } + + Future checkIfPatientHasArrived(int projectID, int clinicID) async { + Map request = {"ProjectID": projectID, "ClinicID": clinicID}; + dynamic localRes; + await baseAppClient.post(CHECK_IF_PATIENT_ARRIVED_ER_ONLINE_CHECKIN, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future checkPatientERAdvanceBalance(int clinicID) async { + Map request = {"ClinicID": clinicID}; + dynamic localRes; + await baseAppClient.post(CHECK_PATIENT_ER_ADVANCE_BALANCE, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future getProjectIDFromNFC(String nfcID) async { + Map request = {"nFC_Code": nfcID}; + dynamic localRes; + await baseAppClient.post(GET_PROJECT_FROM_NFC, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future getDischargeMedicationOrder(GetAdmissionInfoResponseModel getAdmissionInfoResponseModel) async { + Map request; + request = { + "ProjectID": getAdmissionInfoResponseModel.projectID, + "ClinicID": getAdmissionInfoResponseModel.clinicID, + "DoctorID": getAdmissionInfoResponseModel.doctorID, + "AdmissionNo": getAdmissionInfoResponseModel.admissionNo + }; + + // request = { + // "ProjectID": 12, + // "VersionID": 10.8, + // "Channel": 3, + // "LanguageID": 2, + // "IPAdress": "10.20.10.20", + // "generalid": "Cs2020@2016\$2958", + // "DeviceTypeID": 2, + // "PatientType": 1, + // "PatientTypeID": 1, + // "TokenID": "@dm!n", + // "PatientID": 869588, + // "PatientOutSA": 0, + // "SessionID": "rVuK3nzN4UKN0SW95un0jQ==", + // "ClinicID": 2, + // "DoctorID": "7600", + // "AdmissionNo": 2011001258 + // }; + + dynamic localRes; + + await baseAppClient.post(INPATIENT_DISCHARGE_MEDICATIONS, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } + + Future insertForGeneralAdmissionConsent(int patientID, int admissionReqNo, int clinicID, int projectID, int status, context) async { + Map request; + request = { + "AdmissionRequestNo": admissionReqNo, + "ClinicID": clinicID, + "CreatedBy": 102, + "PatientID": patientID, + "ProjectID": projectID, + "status": status, + "searchKey": "", + "pageIndex": 0, + "pageSize": 0, + }; + + dynamic localRes; + + await baseAppClient.post(INSERT_GENERAL_ADMISSION_CONSENT, onSuccess: (response, statusCode) async { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: request, isAllowAny: true); + return Future.value(localRes); + } } diff --git a/lib/services/payfort_services/payfort_service.dart b/lib/services/payfort_services/payfort_service.dart index 64a015cd..5dedd006 100644 --- a/lib/services/payfort_services/payfort_service.dart +++ b/lib/services/payfort_services/payfort_service.dart @@ -143,7 +143,7 @@ class PayfortService extends BaseService { String? customerName, String? customerEmail, String? orderDescription, - double? orderAmount, + num? orderAmount, String? merchantIdentifier, String? applePayAccessCode, String? applePayShaRequestPhrase, @@ -168,16 +168,16 @@ class PayfortService extends BaseService { /// Step 4: Processing Payment [Don't multiply with 100] /// Amount value send always round ex. [100] not [100.00, 100.21] FortRequest request = FortRequest( - amount: orderAmount!, - customerName: customerName!, - customerEmail: customerEmail!, - orderDescription: orderDescription!, - sdkToken: sdkTokenResponse?.sdkToken ?? '', - merchantReference: merchantReference!, - currency: currency, - customerIp: (await _info.getWifiIP() ?? ''), - language: 'en' - ); + amount: orderAmount!, + customerName: customerName!, + customerEmail: customerEmail!, + // orderDescription: orderDescription!, + orderDescription: "Dr. Sulaiman Al Habib Hospital", + sdkToken: sdkTokenResponse?.sdkToken ?? '', + merchantReference: merchantReference!, + currency: currency, + customerIp: (await _info.getWifiIP() ?? ''), + language: 'en'); _payfort.callPayFortForApplePay( request: request, diff --git a/lib/services/payfort_services/payfort_view_model.dart b/lib/services/payfort_services/payfort_view_model.dart index 17f739db..29a79f14 100644 --- a/lib/services/payfort_services/payfort_view_model.dart +++ b/lib/services/payfort_services/payfort_view_model.dart @@ -45,7 +45,7 @@ class PayfortViewModel extends ChangeNotifier { String? customerEmail, String? orderDescription, String? merchantReference, - double? orderAmount, + num? orderAmount, PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel, SucceededCallback? onSuccess, FailedCallback? onFailed, diff --git a/lib/services/permission/permission_service.dart b/lib/services/permission/permission_service.dart index 641d6444..cc73c303 100644 --- a/lib/services/permission/permission_service.dart +++ b/lib/services/permission/permission_service.dart @@ -3,7 +3,7 @@ import 'package:diplomaticquarterapp/core/service/base_service.dart'; import 'package:flutter/material.dart'; import 'package:localstorage/localstorage.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:vibration/vibration.dart'; +// import 'package:vibration/vibration.dart'; import 'package:geolocator/geolocator.dart' as geo; class PermissionService extends BaseService { @@ -25,10 +25,10 @@ class PermissionService extends BaseService { vibrate(callback, context) async { if (callback == null) return null; if (isVibrationEnabled() == true) { - if (await Vibration.hasVibrator() !=null) { - Vibration.vibrate(duration: 100); - callback(); - } + // if (await Vibration.hasVibrator() !=null) { + // Vibration.vibrate(duration: 100); + // callback(); + // } } else { callback(); } diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart index 328af105..a9d4e437 100644 --- a/lib/theme/colors.dart +++ b/lib/theme/colors.dart @@ -21,6 +21,7 @@ class CustomColors { static const Color appBackgroudGrey2Color = Color(0xFFF8F8F8); static const Color green = Color(0xFF359846); static const Color orange = Color(0xFFCC9B14); + static const Color darkOrange = Color(0xFFE16F17); static const Color femaleColor = Color(0xFF359846); static const Color maleColor = Color(0xFFCC9B14); diff --git a/lib/theme/theme_value.dart b/lib/theme/theme_value.dart index 5cf871ab..4fd06d9c 100644 --- a/lib/theme/theme_value.dart +++ b/lib/theme/theme_value.dart @@ -27,22 +27,22 @@ defaultTheme({fontName}) { ), hintColor: Colors.grey[400], disabledColor: Colors.grey[300], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), + // errorColor: Color.fromRGBO(235, 80, 60, 1.0), scaffoldBackgroundColor: Color(0xffF8F8F8), canvasColor: Colors.white, - backgroundColor: Color.fromRGBO(255, 255, 255, 1), + // backgroundColor: Color.fromRGBO(255, 255, 255, 1), highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, primaryColor: Color(0xff515A5D), - toggleableActiveColor: secondaryColor, + // toggleableActiveColor: secondaryColor, indicatorColor: secondaryColor, bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xFFE0E0E0)), - primaryTextTheme: TextTheme(bodyText2: TextStyle(color: Colors.white)), + // primaryTextTheme: TextTheme(bodyText2: TextStyle(color: Colors.white)), iconTheme: IconThemeData(), textTheme: TextTheme( - bodyText1: TextStyle(color: Colors.black, letterSpacing: 0.6), - headline1: TextStyle(color: Colors.white, letterSpacing: 0.6), - headline2: TextStyle(color: Colors.white, letterSpacing: 0.6), + // bodyText1: TextStyle(color: Colors.black, letterSpacing: 0.6), + // headline1: TextStyle(color: Colors.white, letterSpacing: 0.6), + // headline2: TextStyle(color: Colors.white, letterSpacing: 0.6), ), floatingActionButtonTheme: FloatingActionButtonThemeData(highlightElevation: 2, disabledElevation: 0, elevation: 2), @@ -71,16 +71,16 @@ invertThemes({fontName}) { }, ), hintColor: Colors.grey[400], - textTheme: TextTheme(bodyText1: TextStyle(color: Colors.white), headline1: TextStyle(color: Colors.white), headline2: TextStyle(color: Colors.white)), + // textTheme: TextTheme(bodyText1: TextStyle(color: Colors.white), headline1: TextStyle(color: Colors.white), headline2: TextStyle(color: Colors.white)), disabledColor: Colors.grey[800], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), + // errorColor: Color.fromRGBO(235, 80, 60, 1.0), scaffoldBackgroundColor: Color(0xff000000), canvasColor: Colors.black, - backgroundColor: Color.fromRGBO(255, 255, 255, 1), + // backgroundColor: Color.fromRGBO(255, 255, 255, 1), highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, primaryColor: Color(0xff515A5D), - toggleableActiveColor: secondaryColor, + // toggleableActiveColor: secondaryColor, indicatorColor: secondaryColor, bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xFFE0E0E0)), iconTheme: IconThemeData(), @@ -113,24 +113,24 @@ bwThemes({fontName}) { hintColor: Colors.grey[400], textTheme: TextTheme( - bodyText1: TextStyle(color: Colors.red[900]), - headline1: TextStyle(color: Colors.red[900]), - headline2: TextStyle(color: Colors.white), - bodyText2: TextStyle(color: Colors.red[900]), - subtitle1: TextStyle(color: Colors.red[900]), + // bodyText1: TextStyle(color: Colors.red[900]), + // headline1: TextStyle(color: Colors.red[900]), + // headline2: TextStyle(color: Colors.white), + // bodyText2: TextStyle(color: Colors.red[900]), + // subtitle1: TextStyle(color: Colors.red[900]), ), tabBarTheme: TabBarTheme(labelColor: Colors.red[900]), disabledColor: Colors.grey[800], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), + // errorColor: Color.fromRGBO(235, 80, 60, 1.0), scaffoldBackgroundColor: Color(0xffffffe4), canvasColor: Colors.black, - backgroundColor: Color(0xffffffe4), + // backgroundColor: Color(0xffffffe4), highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, primaryColor: Color(0xfffffff4), - toggleableActiveColor: secondaryColor, + // toggleableActiveColor: secondaryColor, indicatorColor: secondaryColor, bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xFFE0E0E0)), iconTheme: IconThemeData(), @@ -160,10 +160,10 @@ dimTheme({fontName}) { ), hintColor: Colors.grey[400], disabledColor: Colors.grey[300], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), + // errorColor: Color.fromRGBO(235, 80, 60, 1.0), scaffoldBackgroundColor: Color(0xffEEEEEE), canvasColor: Colors.white, - backgroundColor: Color.fromRGBO(255, 255, 255, 1), + // backgroundColor: Color.fromRGBO(255, 255, 255, 1), highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, primaryColor: Color(0xff40ACC9), diff --git a/lib/uitl/CalendarUtils.dart b/lib/uitl/CalendarUtils.dart index 57ec961a..cf67bb57 100644 --- a/lib/uitl/CalendarUtils.dart +++ b/lib/uitl/CalendarUtils.dart @@ -108,10 +108,10 @@ class CalendarUtils { TZDateTime scheduleDateTimeUTZ = TZDateTime.from(scheduleDateTime!, _currentLocation); - // print("writableCalendars-name: " + writableCalendars.name); - // print("writableCalendars-Id: " + writableCalendars.id); - // print("writableCalendarsToString: " + writableCalendars.toString()); - // print("writableCalendarsToString: " + writableCalendars!.id!); + print("writableCalendars-name: " + writableCalendars.name); + print("writableCalendars-Id: " + writableCalendars.id); + print("writableCalendarsToString: " + writableCalendars.toString()); + print("writableCalendarsToString: " + writableCalendars!.id!); Event event = Event( writableCalendars!.id, start: scheduleDateTimeUTZ, @@ -119,11 +119,21 @@ class CalendarUtils { title: title, description: description, ); - await deviceCalendarPlugin.createOrUpdateEvent(event).catchError((e) { - print("catchError " + e.toString()); - }).whenComplete(() { - print("whenComplete " + eventId!); - }); + + + if(Platform.isAndroid) { + Result result = await deviceCalendarPlugin.hasPermissions(); + print(result); + await deviceCalendarPlugin.createOrUpdateEvent(event).catchError((e) { + print("catchError " + e.toString()); + }).whenComplete(() { + print("whenComplete Calender ID " + eventId!); + }); + } + + + + } deleteEvent(Calendar _calendar, Event _event) async { diff --git a/lib/uitl/app-permissions.dart b/lib/uitl/app-permissions.dart index 62fd484a..94697e4f 100644 --- a/lib/uitl/app-permissions.dart +++ b/lib/uitl/app-permissions.dart @@ -7,9 +7,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'PlatformBridge.dart'; -class AppPermission{ - - +class AppPermission { static Future askVideoCallPermission(BuildContext context) async { if (!(await Permission.camera.request().isGranted) || !(await Permission.microphone.request().isGranted)) { return false; @@ -21,6 +19,30 @@ class AppPermission{ return true; } +// + + // 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.BLUETOOTH_SCAN, + // Manifest.permission.BLUETOOTH_CONNECT, + // Manifest.permission.HIGH_SAMPLING_RATE_SENSORS, + // Manifest.permission.ACTIVITY_RECOGNITION + + static Future askPenguinPermissions() async { + if (!(await Permission.location.request().isGranted) || + !(await Permission.bluetooth.request().isGranted) || + !(await Permission.bluetoothScan.request().isGranted) || + !(await Permission.bluetoothConnect.request().isGranted) || + !(await Permission.activityRecognition.request().isGranted)) { + return false; + } + return true; + } + static Future _drawOverAppsMessageDialog(BuildContext context) async { ConfirmDialog dialog = new ConfirmDialog( context: context, @@ -34,4 +56,4 @@ class AppPermission{ cancelFunction: () => {}); dialog.showAlertDialog(context); } -} \ No newline at end of file +} diff --git a/lib/uitl/penguin_method_channel.dart b/lib/uitl/penguin_method_channel.dart new file mode 100644 index 00000000..50a642a7 --- /dev/null +++ b/lib/uitl/penguin_method_channel.dart @@ -0,0 +1,105 @@ +import 'package:flutter/services.dart'; + +class PenguinMethodChannel { + static const MethodChannel _channel = MethodChannel('launch_penguin_ui'); + + Future loadGif() async { + return await rootBundle.load("assets/images/progress-loading-red-crop-1.gif").then((data) => data.buffer.asUint8List()); + } + + Future launch(String storyboardName, String languageCode, String username, {NavigationClinicDetails? details}) async { + Uint8List image = await loadGif(); + try { + await _channel.invokeMethod('launchPenguin', { + "storyboardName": storyboardName, + "baseURL": "https://prod.hmg.nav.penguinin.com", + // "dataURL": "https://hmg.nav.penguinin.com", + // "positionURL": "https://hmg.nav.penguinin.com", + // "dataURL": "https://hmg-v33.local.penguinin.com", + // "positionURL": "https://hmg-v33.local.penguinin.com", + "dataURL": "https://prod.hmg.nav.penguinin.com", + "positionURL": "https://prod.hmg.nav.penguinin.com", + "dataServiceName": "api", + "positionServiceName": "pe", + "clientID": "HMG", + // "username": "Haroon", + "username": username, + "isSimulationModeEnabled": false, + "isShowUserName": false, + "isUpdateUserLocationSmoothly": true, + "isEnableReportIssue": true, + "languageCode": languageCode, + "clientKey": "UGVuZ3VpbklOX1Blbk5hdl9QSUY=", + "mapBoxKey": "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg", + "clinicID": details?.clinicId ?? "", + // "clinicID": "108", // 46 ,49, 133 + "patientID": details?.patientId ?? "", + "projectID": details?.projectId ?? "", + "loaderImage": image, + }); + } on PlatformException catch (e) { + print("Failed to launch PenguinIn: '${e.message}'."); + } + } + + void setMethodCallHandler(){ + _channel.setMethodCallHandler((MethodCall call) async { + try { + + print(call.method); + + switch (call.method) { + + case PenguinMethodNames.onPenNavInitializationError: + _handleInitializationError(call.arguments); // Handle onPenNavInitializationError errors. + break; + case PenguinMethodNames.onPenNavUIDismiss: + //todo handle pen dismissable + // _handlePenNavUIDismiss(); // Handle UI dismissal event. + break; + case PenguinMethodNames.onReportIssue: + // Handle the report issue event. + _handleInitializationError(call.arguments); + break; + default: + _handleUnknownMethod(call.method); // Handle unknown method calls. + } + } catch (e) { + print("Error handling method call '${call.method}': $e"); + // Optionally, log this error to an external service + } + }); + } + static void _handleUnknownMethod(String method) { + print("Unknown method: $method"); + // Optionally, handle this unknown method case, such as reporting or ignoring it + } + + + static void _handleInitializationError(Map error) { + final type = error['type'] as String?; + final description = error['description'] as String?; + print("Initialization Error: ${type ?? 'Unknown Type'}, ${description ?? 'No Description'}"); + + } + +} +// Define constants for method names +class PenguinMethodNames { + static const String showPenguinUI = 'showPenguinUI'; + static const String openSharedLocation = 'openSharedLocation'; + + // ---- Handler Method + static const String onPenNavSuccess = 'onPenNavSuccess'; // Tested Android,iOS + static const String onPenNavInitializationError = 'onPenNavInitializationError'; // Tested Android,iOS + static const String onPenNavUIDismiss = 'onPenNavUIDismiss'; //Tested Android,iOS + static const String onReportIssue = 'onReportIssue'; // Tested Android,iOS + static const String onLocationOffCampus = 'onLocationOffCampus'; // Tested iOS,Android + static const String navigateToPOI = 'navigateToPOI'; // Tested Android,iOS +} + +class NavigationClinicDetails { + String? clinicId; + String? patientId; + String? projectId; +} diff --git a/lib/uitl/push-notification-handler.dart b/lib/uitl/push-notification-handler.dart index 8d730102..2ad0203a 100644 --- a/lib/uitl/push-notification-handler.dart +++ b/lib/uitl/push-notification-handler.dart @@ -15,6 +15,7 @@ import 'package:diplomaticquarterapp/pages/webRTC/OpenTok/OpenTok.dart'; import 'package:diplomaticquarterapp/uitl/LocalNotification.dart'; import 'package:diplomaticquarterapp/uitl/app-permissions.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; +import 'package:diplomaticquarterapp/uitl/penguin_method_channel.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart' as fir; @@ -356,6 +357,8 @@ class PushNotificationHandler { FirebaseMessaging.instance.getToken(vapidKey: 'BHRJG8sIzcysWxPw3B6xQjz_85nUuCfU6EAmpH18kyUTmB2cj35IdFwCyWSab80SA1v6oBSWVh-p6PcHPw_y00Y').then((String? token) { print("Push Notification getToken: " + token!); onToken(token!); + }).catchError((err) { + print(err); }); FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) { @@ -386,9 +389,16 @@ class PushNotificationHandler { if (remoteMessage.data.isEmpty) { return; } + debugPrint('the value of the remote message is ${remoteMessage.data}'); if (remoteMessage.data['is_call'] == 'true' || remoteMessage.data['is_call'] == true) { _incomingCall(remoteMessage.data); // showCallkitIncoming(remoteMessage.data); + }if(remoteMessage.data['is_navigation'] == 'true' || remoteMessage.data['is_navigation'] == true ){ + NavigationClinicDetails data = NavigationClinicDetails(); + data.clinicId = remoteMessage.data['clinic_Id']; + data.patientId = remoteMessage.data['patient_Id']; + data.projectId = remoteMessage.data['project_Id']; + initPenguinSDK(data); } else { GetNotificationsResponseModel notification = new GetNotificationsResponseModel(); @@ -406,6 +416,21 @@ class PushNotificationHandler { } } + initPenguinSDK(NavigationClinicDetails data) async { + final bool permited = await AppPermission.askPenguinPermissions(); + if (!permited) { + Map statuses = await [ + Permission.location, + Permission.bluetooth, + Permission.bluetoothConnect, + Permission.bluetoothScan, + Permission.activityRecognition, + ].request().whenComplete(() { + PenguinMethodChannel().launch("penguin", "en", "1231755", details: data); + }); + } + } + onToken(String token) async { // print("Push Notification Token: " + token); await AppSharedPreferences().setString(PUSH_TOKEN, token); diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 006c3e7a..8fbf5faa 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -59,7 +59,10 @@ class TranslationBase { String get clinicName => localizedValues['clinicName'][locale.languageCode]; + String get hospitalName => localizedValues['hospitalName'][locale.languageCode]; + String get doctorName => localizedValues['doctorName'][locale.languageCode]; + String get NoClinicFound => localizedValues['NoClinicFound'][locale.languageCode]; String get nearestAppo => localizedValues['nearestAppo'][locale.languageCode]; @@ -2945,6 +2948,34 @@ class TranslationBase { String get receive => localizedValues["receive"][locale.languageCode]; String get PRO => localizedValues["PRO"][locale.languageCode]; String get patientRelationOffice => localizedValues["patientRelationOffice"][locale.languageCode]; + String get roomNo => localizedValues["roomNo"][locale.languageCode]; + String get generalConsent => localizedValues["generalConsent"][locale.languageCode]; + String get generalConsent1 => localizedValues["generalConsent1"][locale.languageCode]; + String get hospitalRules => localizedValues["hospitalRules"][locale.languageCode]; + String get generalConsent2 => localizedValues["generalConsent2"][locale.languageCode]; + String get communicationConsent => localizedValues["communicationConsent"][locale.languageCode]; + String get generalConsent3 => localizedValues["generalConsent3"][locale.languageCode]; + String get releaseConsent => localizedValues["releaseConsent"][locale.languageCode]; + String get generalConsent4 => localizedValues["generalConsent4"][locale.languageCode]; + String get generalConsent5 => localizedValues["generalConsent5"][locale.languageCode]; + String get valuables => localizedValues["valuables"][locale.languageCode]; + String get generalConsent6 => localizedValues["generalConsent6"][locale.languageCode]; + String get financialConsent => localizedValues["financialConsent"][locale.languageCode]; + String get generalConsent7 => localizedValues["generalConsent7"][locale.languageCode]; + String get dataSharingConsent => localizedValues["dataSharingConsent"][locale.languageCode]; + String get generalConsent8 => localizedValues["generalConsent8"][locale.languageCode]; + String get permissionLeaveConsent => localizedValues["permissionLeaveConsent"][locale.languageCode]; + String get generalConsent9 => localizedValues["generalConsent9"][locale.languageCode]; + String get observeConsent => localizedValues["observeConsent"][locale.languageCode]; + String get generalConsent10 => localizedValues["generalConsent10"][locale.languageCode]; + String get noGuaranteeConsent => localizedValues["noGuaranteeConsent"][locale.languageCode]; + String get generalConsent11 => localizedValues["generalConsent11"][locale.languageCode]; + String get disputeConsent => localizedValues["disputeConsent"][locale.languageCode]; + String get generalConsent12 => localizedValues["generalConsent12"][locale.languageCode]; + String get patientsRightsConsent => localizedValues["patientsRightsConsent"][locale.languageCode]; + String get generalConsent13 => localizedValues["generalConsent13"][locale.languageCode]; + String get acknowledgementConsent => localizedValues["acknowledgementConsent"][locale.languageCode]; + String get generalConsent14 => localizedValues["generalConsent14"][locale.languageCode]; String get invalidEligibility => localizedValues["invalidEligibility"][locale.languageCode]; String get invalidInsurance => localizedValues["invalidInsurance"][locale.languageCode]; String get continueCash => localizedValues["continueCash"][locale.languageCode]; @@ -2963,6 +2994,15 @@ class TranslationBase { String get selectHospitalBloodDonation => localizedValues["selectHospitalBloodDonation"][locale.languageCode]; String get wecare => localizedValues["wecare"][locale.languageCode]; String get myinstructions => localizedValues["myinstructions"][locale.languageCode]; + String get clinicLocation => localizedValues["clinicLocation"][locale.languageCode]; + String get waitingAppointment => localizedValues["waitingAppointment"][locale.languageCode]; + String get whatWaitingAppointment => localizedValues["whatWaitingAppointment"][locale.languageCode]; + String get waitingAppointmentText1 => localizedValues["waitingAppointmentText1"][locale.languageCode]; + String get waitingAppointmentText2 => localizedValues["waitingAppointmentText2"][locale.languageCode]; + String get waitingAppointmentText3 => localizedValues["waitingAppointmentText3"][locale.languageCode]; + String get waitingAppointmentVerificationMethod => localizedValues["waitingAppointmentVerificationMethod"][locale.languageCode]; + String get howToUseVerificationMethod => localizedValues["howToUseVerificationMethod"][locale.languageCode]; + String get addToWaitingList => localizedValues["addToWaitingList"][locale.languageCode]; String get searchClinic => localizedValues["searchClinic"][locale.languageCode]; String get enterMobileNumber => localizedValues["enterMobileNumber"][locale.languageCode]; String get videoCall => localizedValues["videoCall"][locale.languageCode]; @@ -2970,7 +3010,20 @@ class TranslationBase { String get phoneCall => localizedValues["phoneCall"][locale.languageCode]; String get selectCallType => localizedValues["selectCallType"][locale.languageCode]; String get selectedCallType => localizedValues["selectedCallType"][locale.languageCode]; - + String get selectBranch => localizedValues["selectBranch"][locale.languageCode]; + String get searchByBranch => localizedValues["searchByBranch"][locale.languageCode]; + String get existingPackage => localizedValues["existingPackage"][locale.languageCode]; + String get continueOrbookNew => localizedValues["continueOrbookNew"][locale.languageCode]; + String get newAppointment => localizedValues["newAppointment"][locale.languageCode]; + String get proceedPackage => localizedValues["proceedPackage"][locale.languageCode]; + String get hospitalNavigationTitle => localizedValues["hospitalNavigationTitle"][locale.languageCode]; + String get hospitalNavigationSubtitle => localizedValues["hospitalNavigationSubtitle"][locale.languageCode]; + String get workplaceNameAr => localizedValues["workplaceNameAr"][locale.languageCode]; + String get occupationNameEn => localizedValues["occupationNameEn"][locale.languageCode]; + String get occupationNameAr => localizedValues["occupationNameAr"][locale.languageCode]; + String get continueAgreeTerms => localizedValues["continueAgreeTerms"][locale.languageCode]; + String get agreeText => localizedValues["agreeText"][locale.languageCode]; + String get ERCheckInSuccess => localizedValues["ERCheckInSuccess"][locale.languageCode]; } diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index 9b59e200..1529d605 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -65,6 +65,30 @@ AppSharedPreferences sharedPref = new AppSharedPreferences(); class Utils { // static ProgressDialog pr; + static var navigationProjectsList = [ + { + "Desciption": "Sahafa Hospital", + "DesciptionN": "مستشفى الصحافة", + "ID": 130, + "LegalName": "Sahafa Hospital", + "LegalNameN": "مستشفى الصحافة", + "Name": "Sahafa Hospital", + "NameN": "مستشفى الصحافة", + "PhoneNumber": "+966115222222", + "SetupID": "013311", + "DistanceInKilometers": 0, + "HasVida3": false, + "IsActive": true, + "IsHmg": true, + "IsVidaPlus": false, + "Latitude": "24.8113774", + "Longitude": "46.6239813", + "MainProjectID": 130, + "ProjectOutSA": false, + "UsingInDoctorApp": false + } + ]; + ///show custom Error Toast /// [message] to show for user static showErrorToast([String? message]) { @@ -807,7 +831,8 @@ class Utils { children: [ SizedBox(height: 12), Text( - isCapitable && !projectViewModel.isArabic ? text.toLowerCase().capitalizeFirstofEach : text, + // isCapitable && !projectViewModel.isArabic ? text.toLowerCase().capitalizeFirstofEach : text, + text, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xff575757), letterSpacing: -0.4, height: 16 / 10), @@ -908,7 +933,7 @@ class Utils { return projectDetailListModel; } - //static String generateSignature() {} +//static String generateSignature() {} } Widget applyShadow({Color color = Colors.grey, double shadowOpacity = 0.5, double spreadRadius = 2, double blurRadius = 7, Offset offset = const Offset(2, 2), required Widget child}) { diff --git a/lib/widgets/LoadingButton.dart b/lib/widgets/LoadingButton.dart index 8f94cdde..6a497198 100644 --- a/lib/widgets/LoadingButton.dart +++ b/lib/widgets/LoadingButton.dart @@ -138,14 +138,15 @@ class _AnimatedButtonState extends State /// sets width and size animation void _updateWidth() { final theme = Theme.of(context); - final fontSize = theme.textTheme.button!.fontSize; + // final fontSize = theme.textTheme.button!.fontSize; + final fontSize = 12.0; final renderParagraph = RenderParagraph( TextSpan( text: widget.text, style: TextStyle( fontSize: fontSize, - fontWeight: theme.textTheme.button!.fontWeight, - letterSpacing: theme.textTheme.button!.letterSpacing, + fontWeight: FontWeight.normal, + letterSpacing: 0.6, ), ), textDirection: TextDirection.ltr, diff --git a/lib/widgets/bottom_options/BottomSheet.dart b/lib/widgets/bottom_options/BottomSheet.dart index 3a49f3d8..135a9731 100644 --- a/lib/widgets/bottom_options/BottomSheet.dart +++ b/lib/widgets/bottom_options/BottomSheet.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/services/permission/permission_service.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; @@ -122,7 +123,7 @@ class _BottomSheet extends StatelessWidget { Widget build(BuildContext context) { return Container( padding: EdgeInsets.symmetric(vertical: 12.0), - decoration: BoxDecoration(color: Theme.of(context).backgroundColor, borderRadius: BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0))), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0))), child: SafeArea( top: false, child: Column( @@ -165,14 +166,14 @@ class _BottomSheetItem extends StatelessWidget { if (icon != null) Icon( icon, - color: color == ITEM_COLOR.error ? Theme.of(context).errorColor : Theme.of(context).primaryColor, + color: color == ITEM_COLOR.error ? CustomColors.accentColor : Theme.of(context).primaryColor, size: 18.0, ), if (icon != null) SizedBox(width: 24.0), Texts( title ?? "", style: "bodyText2", - color: color == ITEM_COLOR.error ? Theme.of(context).errorColor : null, + color: color == ITEM_COLOR.error ? CustomColors.accentColor : null, ), ], ), diff --git a/lib/widgets/buttons/BottomButton.dart b/lib/widgets/buttons/BottomButton.dart index f4aafdb4..1746ee13 100644 --- a/lib/widgets/buttons/BottomButton.dart +++ b/lib/widgets/buttons/BottomButton.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart'; import 'package:flutter/material.dart'; @@ -23,18 +24,7 @@ class BottomButton extends StatelessWidget { final Widget? child; final bool disabledPadding; - BottomButton( - {Key? key, - this.loading = false, - this.disabled = false, - this.label, - this.icon, - this.color, - this.textColor, - this.disabledPadding = false, - this.borderColor, - this.onTap, - this.child}) + BottomButton({Key? key, this.loading = false, this.disabled = false, this.label, this.icon, this.color, this.textColor, this.disabledPadding = false, this.borderColor, this.onTap, this.child}) : super(key: key); @override @@ -44,17 +34,7 @@ class BottomButton extends StatelessWidget { children: [ Container( decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - stops: [ - 0.0, - 0.9 - ], - colors: [ - Theme.of(context).backgroundColor, - Theme.of(context).backgroundColor.withOpacity(0) - ]), + gradient: LinearGradient(begin: Alignment.bottomCenter, end: Alignment.topCenter, stops: [0.0, 0.9], colors: [CustomColors.white, CustomColors.white.withOpacity(0)]), ), alignment: Alignment.center, child: SafeArea( @@ -63,46 +43,19 @@ class BottomButton extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Container( - margin: child != null - ? EdgeInsets.only( - left: 14.0, right: 14.0, top: 14.0, bottom: 14) - : EdgeInsets.only( - left: 30.0, right: 30.0, top: 14.0, bottom: 14), + margin: child != null ? EdgeInsets.only(left: 14.0, right: 14.0, top: 14.0, bottom: 14) : EdgeInsets.only(left: 30.0, right: 30.0, top: 14.0, bottom: 14), decoration: BoxDecoration( - color: child != null - ? Theme.of(context).backgroundColor - : null, - border: child != null - ? Border.all( - color: Theme.of(context).dividerColor, width: 2.0) - : Border.all(color: Colors.transparent, width: 0.0), - borderRadius: child != null - ? BorderRadius.circular(16.0) - : BorderRadius.circular(0.0), - boxShadow: child != null - ? [ - BoxShadow( - color: Color.fromRGBO(0, 0, 0, 0.04), - spreadRadius: -0.0, - offset: Offset(0, 4.0), - blurRadius: 18.0) - ] - : []), + color: child != null ? CustomColors.white : null, + border: child != null ? Border.all(color: Theme.of(context).dividerColor, width: 2.0) : Border.all(color: Colors.transparent, width: 0.0), + borderRadius: child != null ? BorderRadius.circular(16.0) : BorderRadius.circular(0.0), + boxShadow: child != null ? [BoxShadow(color: Color.fromRGBO(0, 0, 0, 0.04), spreadRadius: -0.0, offset: Offset(0, 4.0), blurRadius: 18.0)] : []), child: Column( children: [ if (child != null) Padding( padding: disabledPadding - ? EdgeInsets.only( - left: 0.0, - right: 0.0, - top: 14.0, - bottom: label != null ? 0.0 : 14) - : EdgeInsets.only( - left: 18.0, - right: 18.0, - top: 14.0, - bottom: label != null ? 0.0 : 14), + ? EdgeInsets.only(left: 0.0, right: 0.0, top: 14.0, bottom: label != null ? 0.0 : 14) + : EdgeInsets.only(left: 18.0, right: 18.0, top: 14.0, bottom: label != null ? 0.0 : 14), child: child, ), if (child != null) @@ -114,10 +67,7 @@ class BottomButton extends StatelessWidget { label == null ? SizedBox(height: 50.0) : Padding( - padding: child != null - ? EdgeInsets.only( - bottom: 16.0, left: 16.0, right: 16.0) - : EdgeInsets.zero, + padding: child != null ? EdgeInsets.only(bottom: 16.0, left: 16.0, right: 16.0) : EdgeInsets.zero, child: SecondaryButton( borderColor: borderColor, onTap: () { @@ -135,8 +85,7 @@ class BottomButton extends StatelessWidget { ), if (label == null && child == null) Padding( - padding: EdgeInsets.only( - left: 30.0, right: 30.0, top: 14.0, bottom: 14), + padding: EdgeInsets.only(left: 30.0, right: 30.0, top: 14.0, bottom: 14), ), ], ), diff --git a/lib/widgets/data_display/list/flexible_container.dart b/lib/widgets/data_display/list/flexible_container.dart index 8f374ca3..63053401 100644 --- a/lib/widgets/data_display/list/flexible_container.dart +++ b/lib/widgets/data_display/list/flexible_container.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:flutter/material.dart'; /// Flexible container widget /// [widthFactor] If non-null, the fraction of the incoming width given to the child. @@ -33,7 +34,7 @@ class FlexibleContainer extends StatelessWidget { child: ClipRRect( borderRadius: BorderRadius.circular(8.0), child: Material( - color: Theme.of(context).backgroundColor, + color: CustomColors.white, child: Container( padding: padding, width: double.infinity, diff --git a/lib/widgets/data_display/services)contaniner.dart b/lib/widgets/data_display/services)contaniner.dart index e18507f4..246fad78 100644 --- a/lib/widgets/data_display/services)contaniner.dart +++ b/lib/widgets/data_display/services)contaniner.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:flutter/material.dart'; @@ -15,7 +16,8 @@ class ServicesContainer extends StatelessWidget { height: 60, margin: EdgeInsets.all(8), decoration: BoxDecoration( - color: Theme.of(context).textTheme.headline2!.color, + // color: Theme.of(context).textTheme.headline2!.color, + color: CustomColors.white, shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(7), ), diff --git a/lib/widgets/data_display/text.dart b/lib/widgets/data_display/text.dart index 498e5e48..8a5b5954 100644 --- a/lib/widgets/data_display/text.dart +++ b/lib/widgets/data_display/text.dart @@ -1,4 +1,5 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -26,30 +27,31 @@ class Texts extends StatefulWidget { final TextDecoration? decoration; final double? heightFactor; - Texts(this.text, - {Key? key, - this.variant, - this.color, - this.bold, - this.regular, - this.medium, - this.allowExpand = true, - this.italic= false, - this.textAlign, - this.maxLength = 60, - this.maxLines, - this.readMore = false, - this.style, - this.fontSize, - this.fontWeight, - this.margin, - this.marginBottom, - this.marginLeft, - this.marginRight, - this.marginTop, - this.decoration, - this.heightFactor,}) - : super(key: key); + Texts( + this.text, { + Key? key, + this.variant, + this.color, + this.bold, + this.regular, + this.medium, + this.allowExpand = true, + this.italic = false, + this.textAlign, + this.maxLength = 60, + this.maxLines, + this.readMore = false, + this.style, + this.fontSize, + this.fontWeight, + this.margin, + this.marginBottom, + this.marginLeft, + this.marginRight, + this.marginTop, + this.decoration, + this.heightFactor, + }) : super(key: key); @override _TextsState createState() => _TextsState(); @@ -172,27 +174,28 @@ class _TextsState extends State { TextStyle? _getFontStyle() { switch (widget.style) { case "headline2": - return Theme.of(context).textTheme.headline2; + // return Theme.of(context).textTheme.headline2; + return TextStyle(color: Colors.white); case "headline3": - return Theme.of(context).textTheme.headline3; + return TextStyle(color: Colors.white); case "headline4": - return Theme.of(context).textTheme.headline4; + return TextStyle(color: Colors.white); case "headline5": - return Theme.of(context).textTheme.headline5; + return TextStyle(color: Colors.white); case "headline6": - return Theme.of(context).textTheme.headline6; + return TextStyle(color: Colors.white); case "bodyText2": - return Theme.of(context).textTheme.bodyText2; + return TextStyle(color: Colors.white); case "bodyText_15": - return Theme.of(context).textTheme.bodyText2!.copyWith(fontSize: 15.0); + return TextStyle(color: Colors.white, fontSize: 15.0); case "bodyText1": - return Theme.of(context).textTheme.bodyText1; + return TextStyle(color: Colors.white); case "caption": - return Theme.of(context).textTheme.caption; + return TextStyle(color: Colors.white); case "overline": - return Theme.of(context).textTheme.overline; + return TextStyle(color: Colors.white); case "button": - return Theme.of(context).textTheme.button; + return TextStyle(color: Colors.white); default: return TextStyle(); } @@ -205,39 +208,25 @@ class _TextsState extends State { Stack( children: [ Text( - !hidden - ? text - : (text.substring( - 0, - text.length > widget.maxLength! - ? widget.maxLength - : text.length)), + !hidden ? text : (text.substring(0, text.length > widget.maxLength! ? widget.maxLength : text.length)), textAlign: widget.textAlign, - overflow: widget.maxLines != null - ? ((widget.maxLines! > 1) - ? TextOverflow.fade - : TextOverflow.ellipsis) - : null, + overflow: widget.maxLines != null ? ((widget.maxLines! > 1) ? TextOverflow.fade : TextOverflow.ellipsis) : null, maxLines: widget.maxLines ?? null, style: widget.style != null ? _getFontStyle()!.copyWith( fontStyle: widget.italic! ? FontStyle.italic : null, - color: widget.color != null - ? widget.color - : Theme.of(context).textTheme.bodyText1!.color, + color: widget.color != null ? widget.color : Colors.black, fontWeight: widget.fontWeight ?? _getFontWeight(), ) : TextStyle( height: widget.heightFactor, decoration: widget.decoration, fontStyle: widget.italic! ? FontStyle.italic : null, - color: widget.color ?? - Theme.of(context).textTheme.bodyText1!.color, + color: widget.color ?? Colors.black, fontSize: widget.fontSize ?? _getFontSize(), letterSpacing: widget.variant == "overline" ? 1 : null, fontWeight: widget.fontWeight ?? _getFontWeight(), - fontFamily: - projectViewModel.isArabic ? 'Cairo' : 'Poppins'), + fontFamily: projectViewModel.isArabic ? 'Cairo' : 'Poppins'), ), if (widget.readMore! && text.length > widget.maxLength! && hidden) Positioned( @@ -247,8 +236,8 @@ class _TextsState extends State { child: Container( decoration: BoxDecoration( gradient: LinearGradient(colors: [ - Theme.of(context).backgroundColor, - Theme.of(context).backgroundColor.withOpacity(0), + CustomColors.white, + CustomColors.white.withOpacity(0), ], begin: Alignment.bottomCenter, end: Alignment.topCenter), ), height: 30.0, @@ -256,9 +245,7 @@ class _TextsState extends State { ) ], ), - if (widget.allowExpand! && - widget.readMore! && - text.length > widget.maxLength!) + if (widget.allowExpand! && widget.readMore! && text.length > widget.maxLength!) Padding( padding: EdgeInsets.only(top: 8.0, right: 8.0, bottom: 8.0), child: InkWell( diff --git a/lib/widgets/dialogs/confirm_dialog.dart b/lib/widgets/dialogs/confirm_dialog.dart index a493f14e..1da92ac5 100644 --- a/lib/widgets/dialogs/confirm_dialog.dart +++ b/lib/widgets/dialogs/confirm_dialog.dart @@ -73,7 +73,9 @@ class Mdialog extends StatelessWidget { Text( // title != null ? title : TranslationBase.of(context).confirm, title!, + style: TextStyle( + fontSize: 24, letterSpacing: -0.94, fontWeight: FontWeight.w600, @@ -82,6 +84,7 @@ class Mdialog extends StatelessWidget { Text( // this.confirmMessage, description!, + style: TextStyle( fontSize: 12, letterSpacing: -0.48, @@ -101,7 +104,7 @@ class Mdialog extends StatelessWidget { child: Container( decoration: containerRadius(CustomColors.accentColor, 12), padding: EdgeInsets.only(top: 8,bottom: 8), - child: Center(child: Texts(cancelText, variant: "caption3", color: CustomColors.white,)), + child: Center(child: Texts(cancelText, textAlign: TextAlign.center, variant: "caption3", color: CustomColors.white,)), ), ), ), @@ -115,6 +118,7 @@ class Mdialog extends StatelessWidget { child: Center( child: Texts( okText, + textAlign: TextAlign.center, color: Colors.white, variant: "caption3", ), diff --git a/lib/widgets/dialogs/location_selection_dialog.dart b/lib/widgets/dialogs/location_selection_dialog.dart new file mode 100644 index 00000000..9ffb2635 --- /dev/null +++ b/lib/widgets/dialogs/location_selection_dialog.dart @@ -0,0 +1,261 @@ +import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/medical/radiology_view_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart'; +import 'package:flutter/material.dart'; + +import '../../uitl/translations_delegate_base.dart'; + +class LocationSelectionDialog extends StatelessWidget { + final List data; + final Function(int)? onValueSelected; + final int? selectedIndex; + final bool isArabic; + + const LocationSelectionDialog({super.key, required this.data, this.onValueSelected, this.selectedIndex, required this.isArabic}); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: LocationDialogBody( + isArabic: isArabic, + data: data, + onValueSelected: onValueSelected, + selectedIndex: selectedIndex, + )); + } +} + +class LocationDialogBody extends StatefulWidget { + final List data; + final Function(int)? onValueSelected; + final int? selectedIndex; + final bool isArabic; + + const LocationDialogBody({super.key, required this.data, this.onValueSelected, this.selectedIndex, required this.isArabic}); + + @override + State createState() => _LocationDialogBodyState(); +} + +class _LocationDialogBodyState extends State { + bool isListVisible = false; + int currentlySelected = -1; + + @override + Widget build(BuildContext context) { + return isListVisible + ? LocationListExpandedBody( + isArabic: widget.isArabic, + data: widget.data, + onItemClick: (data) { + if (data.isEmpty) return; + var selected = widget.data.indexWhere( + (item) => item.name == data, + ); + + if (selected == -1) return; + setState(() { + currentlySelected = selected; + isListVisible = false; + }); + }, + ) + : LocationListWrapBody( + onConfirmClicked: () { + widget.onValueSelected?.call(currentlySelected); + }, + onTextBoxClicked: () { + setState(() { + isListVisible = true; + }); + }, + selectedText: currentlySelected == -1 ? "" : widget.data[currentlySelected].name ?? ""); + } +} + +class LocationListExpandedBody extends StatefulWidget { + final List data; + final Function(String) onItemClick; + final bool isArabic; + + const LocationListExpandedBody({super.key, required this.data, required this.onItemClick, required this.isArabic}); + + @override + State createState() => _LocationListExpandedBodyState(); +} + +class _LocationListExpandedBodyState extends State { + List tempListData = []; + TextEditingController controller = new TextEditingController(); + + @override + void initState() { + super.initState(); + setState(() { + tempListData.addAll(widget.data); + }); + } + + @override + Widget build(BuildContext context) { + return Container( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SelectBranchHeader(), + SizedBox( + height: 8, + ), + TextField( + controller: controller, + onChanged: (v) { + tempListData.clear(); + if (v.length > 0) { + for (int i = 0; i < widget.data.length; i++) { + if (widget.data[i].name?.toLowerCase().contains(v.toLowerCase()) == true) { + tempListData.add(widget.data[i]); + } + } + } else { + tempListData.addAll(widget.data); + } + setState(() {}); + }, + decoration: InputDecoration( + hintStyle: TextStyle(fontSize: 12), + hintText: TranslationBase.of(context).searchByBranch, + suffixIcon: Icon(Icons.search), + contentPadding: EdgeInsets.symmetric(vertical: 9, horizontal: 14), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide( + color: Colors.grey, // Normal border color + width: 1.0, + ), + ), + ), + ), + SizedBox( + height: 16, + ), + ListView.builder( + itemCount: tempListData.length, + shrinkWrap: true, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.only(bottom: 8), + child: SizedBox( + height: 24, + child: InkWell( + onTap: () { + widget.onItemClick(tempListData[index].name ?? ""); + }, + child: Text( + "${widget.isArabic ? tempListData[index].nameN : tempListData[index].name ?? ""}", + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Colors.black, letterSpacing: -0.96), + ), + ), + ), + ); + }) + ], + ), + ), + ); + } +} + +class LocationListWrapBody extends StatelessWidget { + final VoidCallback? onConfirmClicked; + final VoidCallback? onTextBoxClicked; + final String selectedText; + + const LocationListWrapBody({super.key, this.onConfirmClicked, this.onTextBoxClicked, required this.selectedText}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SelectBranchHeader(), + SizedBox( + height: 24, + ), + ListTile( + onTap: () { + onTextBoxClicked?.call(); + }, + title: Text( + TranslationBase.of(context).selectBranch, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Colors.black, letterSpacing: -0.96), + ), + subtitle: selectedText.isEmpty + ? null + : Text( + selectedText, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, letterSpacing: -0.96), + ), + trailing: Icon( + Icons.arrow_drop_down_outlined, + color: Colors.black, + ), + shape: RoundedRectangleBorder( + side: BorderSide(color: Colors.grey, width: 1), + borderRadius: BorderRadius.circular(8), + ), + ), + SizedBox( + height: 24, + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: DefaultButton( + TranslationBase.of(context).confirm, + () { + Navigator.pop(context); + onConfirmClicked?.call(); + }, + color: CustomColors.accentColor, + ), + ), + ], + ), + ], + ), + ); + } +} + +class SelectBranchHeader extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + TranslationBase.of(context).selectBranch, + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black, letterSpacing: -0.96), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Icon(Icons.close), + )) + ], + ); + } +} diff --git a/lib/widgets/drawer/app_drawer_widget.dart b/lib/widgets/drawer/app_drawer_widget.dart index 95e259d1..f82047a5 100644 --- a/lib/widgets/drawer/app_drawer_widget.dart +++ b/lib/widgets/drawer/app_drawer_widget.dart @@ -171,7 +171,7 @@ class _AppDrawerState extends State { // ), mHeight(20.0), (user != null && projectProvider!.isLogin) - ? Image.network("https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${user!.patientID.toString()}", fit: BoxFit.fill, height: 73.5, width: 73.5) + ? Image.network("https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${user!.patientID.toString()}", fit: BoxFit.fill, height: 70, width: 70) : Container(), ], ), @@ -218,8 +218,8 @@ class _AppDrawerState extends State { child: DrawerItem(TranslationBase.of(context).family, SvgPicture.asset("assets/images/new/family_files.svg"), isImageIcon: true, bottomLine: false, - textColor: Theme.of(context).textTheme.bodyText1!.color, - iconColor: Theme.of(context).textTheme.bodyText1!.color, + textColor: CustomColors.black, + iconColor: CustomColors.black, sideArrow: true, letterSpacing: -0.84, projectProvider: projectProvider), @@ -719,7 +719,7 @@ class _AppDrawerState extends State { // result.list.cRSVerificationStatus = result['CRSVerificationStatus']; await this.sharedPref.setString(APP_LANGUAGE, currentLang); await this.sharedPref.setString(BLOOD_TYPE, bloodType); - await this.sharedPref.setInt(LAST_LOGIN, loginType ?? 1 ); + await this.sharedPref.setInt(LAST_LOGIN, loginType ?? 1); await this.sharedPref.setObject(MAIN_USER, mainUser); await this.sharedPref.setObject(USER_PROFILE, result.list); await this.sharedPref.setObject(FAMILY_FILE, familyFile); diff --git a/lib/widgets/drawer/drawer_item_widget.dart b/lib/widgets/drawer/drawer_item_widget.dart index d5bac14f..2af437e4 100644 --- a/lib/widgets/drawer/drawer_item_widget.dart +++ b/lib/widgets/drawer/drawer_item_widget.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/widgets/text/app_texts_widget.dart'; import 'package:flutter/material.dart'; @@ -53,7 +54,7 @@ class _DrawerItemState extends State { ? widget.icon : Icon( widget.icon, - color: widget.iconColor == null ? Theme.of(context).textTheme.bodyText1?.color : widget.iconColor, + color: widget.iconColor == null ? CustomColors.black : widget.iconColor, size: SizeConfig.imageSizeMultiplier! * 5, )), Expanded( diff --git a/lib/widgets/in_app_browser/InAppBrowser.dart b/lib/widgets/in_app_browser/InAppBrowser.dart index 9ffec736..6f61ac8a 100644 --- a/lib/widgets/in_app_browser/InAppBrowser.dart +++ b/lib/widgets/in_app_browser/InAppBrowser.dart @@ -138,7 +138,7 @@ class MyInAppBrowser extends InAppBrowser { openPackagesPaymentBrowser({required int customer_id, required int order_id}) { paymentType = _PAYMENT_TYPE.PACKAGES; var full_url = '$PACKAGES_REQUEST_PAYMENT_URL?customer_id=$customer_id&order_id=$order_id'; - this.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(full_url)), options: _InAppBrowserOptions); + this.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(full_url))), options: _InAppBrowserOptions); } openPaymentBrowser(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID, @@ -190,7 +190,7 @@ class MyInAppBrowser extends InAppBrowser { String url = "https://hmgwebservices.com/HMGApplePayLive/applepay/pay?apq=" + res['result']; // Prod // String url = "https://uat.hmgwebservices.com/HMGApplePayLive/applepay/pay?apq=" + res['result']; // UAT // safariBrowser.open(url: Uri.parse(url)); - this.browser.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(url)), options: _InAppBrowserOptions); + this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(url))), options: _InAppBrowserOptions); }).catchError((err) { print(err); if (context != null) GifLoaderDialogUtils.hideDialog(context); @@ -218,7 +218,7 @@ class MyInAppBrowser extends InAppBrowser { tamaraRequestModel.customerName = patientName; tamaraRequestModel.fileNumber = patientID.toString(); tamaraRequestModel.patientOutSA = authenticatedUser.outSA == 1 ? true : false; - tamaraRequestModel.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN); + tamaraRequestModel.deviceToken = await AppSharedPreferences().getStringWithDefaultValue(PUSH_TOKEN, ""); tamaraRequestModel.latitude = this.lat.toString(); tamaraRequestModel.longitude = this.long.toString(); tamaraRequestModel.serviceID = servID; @@ -233,7 +233,7 @@ class MyInAppBrowser extends InAppBrowser { appoNo, clinicID, doctorID, "", installments) .then((value) { paymentType = _PAYMENT_TYPE.PATIENT; - this.browser.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(value)), options: _InAppBrowserOptions); + this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions); }); }).catchError((err) { print(err); @@ -245,7 +245,7 @@ class MyInAppBrowser extends InAppBrowser { clinicID, doctorID) .then((value) { paymentType = _PAYMENT_TYPE.PATIENT; - this.browser.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(value)), options: _InAppBrowserOptions); + this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions); }); } } @@ -258,16 +258,16 @@ class MyInAppBrowser extends InAppBrowser { // getPatientData(); generatePharmacyURL(order, amount, orderDesc, transactionID, emailId, paymentMethod, patientName, patientID, authenticatedUser).then((value) { if (order.customValuesXml!.contains("ApplePay")) { - safariBrowser.open(url: Uri.parse(value)); + safariBrowser.open(url: WebUri.uri(Uri.parse(value))); } else { - this.browser.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(value)), options: _InAppBrowserOptions); + this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions); } }); } openBrowser(String url) { this.browser = browser; - this.browser.openUrlRequest(urlRequest: URLRequest(url: Uri.parse(url)), options: _InAppBrowserOptions); + this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(url))), options: _InAppBrowserOptions); } Future generateURL(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID, @@ -290,8 +290,8 @@ class MyInAppBrowser extends InAppBrowser { form = form.replaceFirst('PATIENT_TYPE_ID', patientData == null ? patientType.toString() : "1"); Platform.isIOS - ? form = form.replaceFirst('DEVICE_TOKEN', await AppSharedPreferences().getString(PUSH_TOKEN) + "," + await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN)) - : form = form.replaceFirst('DEVICE_TOKEN', await sharedPref.getString(PUSH_TOKEN) ?? ""); + ? form = form.replaceFirst('DEVICE_TOKEN', await AppSharedPreferences().getStringWithDefaultValue(PUSH_TOKEN, "") + "," + await AppSharedPreferences().getStringWithDefaultValue(ONESIGNAL_APNS_TOKEN, "")) + : form = form.replaceFirst('DEVICE_TOKEN', await sharedPref.getStringWithDefaultValue(PUSH_TOKEN, "") ?? ""); // form = form.replaceFirst('DEVICE_TOKEN', await AppSharedPreferences().getString(PUSH_TOKEN) + "," + await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN)); // form = form.replaceFirst('DEVICE_TOKEN', await sharedPref.getString(PUSH_TOKEN)); @@ -343,7 +343,7 @@ class MyInAppBrowser extends InAppBrowser { form = form.replaceFirst('PROJECT_ID_VALUE', projId); form = form.replaceFirst('PAYMENT_OPTION_VALUE', paymentMethod); form = form.replaceFirst('LANG_VALUE', currentLanguageID); - form = form.replaceFirst('SERVICE_URL_VALUE', "https://mdlaboratories.com/tamaralive/Home/Checkout"); + form = form.replaceFirst('SERVICE_URL_VALUE', "https://mdlaboratories.com/tamara/Home/Checkout"); form = form.replaceFirst('INSTALLMENTS_VALUE', installments); form = form.replaceFirst('CUSTNATIONALID_VALUE', authUser.patientIdentificationNo!); @@ -489,7 +489,7 @@ class MyChromeSafariBrowser extends ChromeSafariBrowser { } @override - void onCompletedInitialLoad() { + void onCompletedInitialLoad(bool? didLoadSuccessfully) { print("ChromeSafari browser initial load completed"); onLoadStartCallback!("ApplePay"); } diff --git a/lib/widgets/input/text_field.dart b/lib/widgets/input/text_field.dart index be6c9989..db467112 100644 --- a/lib/widgets/input/text_field.dart +++ b/lib/widgets/input/text_field.dart @@ -1,10 +1,10 @@ +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class NumberTextInputFormatter extends TextInputFormatter { @override - TextEditingValue formatEditUpdate( - TextEditingValue oldValue, TextEditingValue newValue) { + TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { final int newTextLength = newValue.text.length; int selectionIndex = newValue.selection.end; int usedSubstringIndex = 0; @@ -26,8 +26,7 @@ class NumberTextInputFormatter extends TextInputFormatter { if (newValue.selection.end >= 10) selectionIndex++; } // Dump the rest. - if (newTextLength >= usedSubstringIndex) - newText.write(newValue.text.substring(usedSubstringIndex)); + if (newTextLength >= usedSubstringIndex) newText.write(newValue.text.substring(usedSubstringIndex)); return TextEditingValue( text: newText.toString(), selection: TextSelection.collapsed(offset: selectionIndex), @@ -63,7 +62,7 @@ class TextFields extends StatefulWidget { this.borderOnlyError = false, this.onSaved, this.onSuffixTap, - this.readOnly= false, + this.readOnly = false, this.maxLength, this.prefixIcon, this.bare = false, @@ -164,19 +163,14 @@ class _TextFieldsState extends State { view = true; }); }, - child: Icon(Icons.remove_red_eye_sharp, - size: 24.0, color: Colors.grey[500]), + child: Icon(Icons.remove_red_eye_sharp, size: 24.0, color: Colors.grey[500]), ), ); default: if (widget.suffixIcon != null) return InkWell( onTap: widget.onSuffixTap, - child: Icon(widget.suffixIcon, - size: 22.0, - color: widget.suffixIconColor != null - ? widget.suffixIconColor - : Colors.grey[500]), + child: Icon(widget.suffixIcon, size: 22.0, color: widget.suffixIconColor != null ? widget.suffixIconColor : Colors.grey[500]), ); else return SizedBox(); @@ -203,10 +197,7 @@ class _TextFieldsState extends State { // color: Color.fromRGBO(70, 68, 167, focus ? 0.20 : 0), // offset: Offset(0.0, 13.0), // blurRadius: focus ? 34.0 : 12.0) - BoxShadow( - color: Color.fromRGBO(110, 68, 80, focus! ? 0.20 : 0), - offset: Offset(0.0, 13.0), - blurRadius: focus! ? 34.0 : 12.0) + BoxShadow(color: Color.fromRGBO(110, 68, 80, focus! ? 0.20 : 0), offset: Offset(0.0, 13.0), blurRadius: focus! ? 34.0 : 12.0) ]), child: TextFormField( keyboardAppearance: Theme.of(context).brightness, @@ -234,10 +225,11 @@ class _TextFieldsState extends State { autofocus: widget.autoFocus ?? false, validator: widget.validator, onSaved: widget.onSaved, - style: Theme.of(context) - .textTheme - .bodyText1! - .copyWith(fontSize: widget.fontSize, fontWeight: widget.fontWeight), + // style: Theme.of(context) + // .textTheme + // .bodyText1! + // .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, @@ -252,41 +244,18 @@ class _TextFieldsState extends State { fontWeight: widget.fontWeight, color: widget.hintColor ?? Theme.of(context).hintColor, ), - contentPadding: widget.padding != null - ? widget.padding - : EdgeInsets.symmetric( - vertical: (widget.bare! && !widget.keepPadding!) ? 0.0 : 10.0, - horizontal: 16.0), + contentPadding: widget.padding != null ? widget.padding : EdgeInsets.symmetric(vertical: (widget.bare! && !widget.keepPadding!) ? 0.0 : 10.0, horizontal: 16.0), filled: true, - fillColor: widget.bare! - ? Colors.transparent - : Theme.of(context).backgroundColor, + fillColor: widget.bare! ? Colors.transparent : CustomColors.white, suffixIcon: _buildSuffixIcon(), prefixIcon: widget.prefixIcon, - errorStyle: TextStyle( - fontSize: 14.0, - fontWeight: widget.fontWeight, - height: widget.borderOnlyError! ? 0.0 : null), + errorStyle: TextStyle(fontSize: 14.0, fontWeight: widget.fontWeight, height: widget.borderOnlyError! ? 0.0 : null), errorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .errorColor - .withOpacity(widget.bare! ? 0.0 : 0.5), - width: 1.0), - borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), + borderSide: BorderSide(color: CustomColors.accentColor.withOpacity(widget.bare! ? 0.0 : 0.5), width: 1.0), borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), focusedErrorBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context) - .errorColor - .withOpacity(widget.bare! ? 0.0 : 0.5), - width: 1.0), - borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), - disabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), + borderSide: BorderSide(color: CustomColors.accentColor.withOpacity(widget.bare! ? 0.0 : 0.5), width: 1.0), borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), + focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 1.0), borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), + disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 1.0), borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0)), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.grey, width: 1.0), borderRadius: BorderRadius.circular(widget.bare! ? 0.0 : 8.0), diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index 883e2de3..1103b31b 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -494,7 +494,8 @@ class AppBarWidgetState extends State { // headline6: TextStyle(color: Theme.of(context).textTheme.headline1.color, fontWeight: FontWeight.bold), // ), title: Text(widget.authenticatedUserObject.isLogin || !widget.isShowDecPage ? widget.appBarTitle!.toUpperCase() : TranslationBase.of(context).serviceInformationTitle, - style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.headline1!.color, fontFamily: projectViewModel.isArabic ? 'Cairo' : 'WorkSans')), + // style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.headline1!.color, fontFamily: projectViewModel.isArabic ? 'Cairo' : 'WorkSans')), + style: TextStyle(fontWeight: FontWeight.bold, color: CustomColors.white, fontFamily: projectViewModel.isArabic ? 'Cairo' : 'WorkSans')), leading: Builder( builder: (BuildContext context) { return ArrowBack( diff --git a/lib/widgets/others/not_auh_page.dart b/lib/widgets/others/not_auh_page.dart index 063878bb..6389ba00 100644 --- a/lib/widgets/others/not_auh_page.dart +++ b/lib/widgets/others/not_auh_page.dart @@ -125,207 +125,207 @@ class _NotAutPageState extends State { ), ); - Scaffold( - backgroundColor: Color(0xfff8f8f8), - resizeToAvoidBottomInset: false, - appBar: AppBar( - backgroundColor: Colors.transparent, - leading: IconButton( - icon: Icon(Icons.arrow_back_ios), - color: Color(0xff2B353E), - onPressed: () => Navigator.pop(context), - ), - ), - body: Padding( - padding: EdgeInsets.only(bottom: 20, left: 21, right: 21), - child: Column(children: [ - Expanded( - child: ListView( - padding: EdgeInsets.zero, - physics: BouncingScrollPhysics(), - children: [ - SizedBox(height: 12), - if (widget.icon != null) - Align( - alignment: Alignment.centerLeft, - child: SvgPicture.asset( - widget.icon!, - height: 35, - width: 35, - ), - ), - SizedBox(height: 16), - Text( - widget.title, - style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 23 / 24), - ), - Text( - widget.description!, - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.56, height: 21 / 14), - ), - SizedBox( - height: 14, - ), - if (!projectViewModel.isInternetConnection) - Center( - child: SizedBox( - height: MediaQuery.of(context).size.height * 0.55, - width: MediaQuery.of(context).size.width * 0.50, - child: Image.asset(projectViewModel.isArabic ? 'assets/images/Wifi-AR.png' : 'assets/images/wifi-EN.png'), - ), - ), - if (projectViewModel.isInternetConnection && widget.imagesInfo != null) - CarouselSlider( - items: widget.imagesInfo?.map((image) { - return Builder( - builder: (BuildContext context) { - return SizedBox( - width: MediaQuery.of(context).size.width * 0.50, - child: image.isAsset! ? Image.asset(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!) : Image.network(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!)); - }, - ); - }).toList(), - options: CarouselOptions( - height: MediaQuery.of(context).size.height * 0.55, - autoPlay: widget.imagesInfo!.length > 1, - viewportFraction: 1.0, - ), - ), - ], - ), - ), - SizedBox( - height: 43, - width: double.infinity, - child: TextButton( - onPressed: () { - loginCheck(context); - }, - child: Text( - TranslationBase.of(context).loginregister, - style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.48), - ), - style: TextButton.styleFrom( - backgroundColor: Color(0xffD02127), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), - )), - ), - ]), - ), - ); - - return Scaffold( - body: SingleChildScrollView( - padding: EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts( - widget.title ?? 'Service', - fontWeight: FontWeight.w800, - fontSize: 25, - bold: true, - color: Color(0xff60686b), - ), - SizedBox( - height: 12, - ), - Texts( - widget.description ?? 'Description', - fontWeight: FontWeight.normal, - fontSize: 17, - ), - if (widget.infoList != null) - SizedBox( - height: 12, - ), - if (widget.infoList != null) - ...List.generate( - widget.infoList!.length, - (index) => Container( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: Theme.of(context).primaryColor), - child: Center( - child: Texts( - '${index + 1}', - color: Colors.white, - ), - ), - ), - SizedBox( - width: 6, - ), - Expanded(child: Texts('${widget.infoList![index]}')) - ], - ), - SizedBox( - height: 12, - ), - ], - ), - ), - ), - SizedBox( - height: 22, - ), - if (!projectViewModel.isInternetConnection) - Center( - child: SizedBox( - height: MediaQuery.of(context).size.height * 0.55, - width: MediaQuery.of(context).size.width * 0.50, - child: Image.asset(projectViewModel.isArabic ? 'assets/images/Wifi-AR.png' : 'assets/images/wifi-EN.png'), - ), - ), - if (projectViewModel.isInternetConnection && widget.imagesInfo != null) - CarouselSlider( - items: widget.imagesInfo!.map((image) { - return Builder( - builder: (BuildContext context) { - return SizedBox( - width: MediaQuery.of(context).size.width * 0.50, - child: image.isAsset! ? Image.asset(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!) : Image.network(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!)); - }, - ); - }).toList(), - options: CarouselOptions( - height: MediaQuery.of(context).size.height * 0.55, - autoPlay: widget.imagesInfo!.length > 1, - viewportFraction: 1.0, - ), - ), - SizedBox( - height: 77, - ), - ], - ), - ), - bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.10, - width: double.infinity, - child: Column( - children: [ - Container( - width: MediaQuery.of(context).size.width * 0.9, - child: SecondaryButton( - onTap: () { - loginCheck(context); - }, - label: TranslationBase.of(context).serviceInformationButton, - textColor: Theme.of(context).backgroundColor), - ), - ], - ), - ), - ); + // Scaffold( + // backgroundColor: Color(0xfff8f8f8), + // resizeToAvoidBottomInset: false, + // appBar: AppBar( + // backgroundColor: Colors.transparent, + // leading: IconButton( + // icon: Icon(Icons.arrow_back_ios), + // color: Color(0xff2B353E), + // onPressed: () => Navigator.pop(context), + // ), + // ), + // body: Padding( + // padding: EdgeInsets.only(bottom: 20, left: 21, right: 21), + // child: Column(children: [ + // Expanded( + // child: ListView( + // padding: EdgeInsets.zero, + // physics: BouncingScrollPhysics(), + // children: [ + // SizedBox(height: 12), + // if (widget.icon != null) + // Align( + // alignment: Alignment.centerLeft, + // child: SvgPicture.asset( + // widget.icon!, + // height: 35, + // width: 35, + // ), + // ), + // SizedBox(height: 16), + // Text( + // widget.title, + // style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 23 / 24), + // ), + // Text( + // widget.description!, + // style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.56, height: 21 / 14), + // ), + // SizedBox( + // height: 14, + // ), + // if (!projectViewModel.isInternetConnection) + // Center( + // child: SizedBox( + // height: MediaQuery.of(context).size.height * 0.55, + // width: MediaQuery.of(context).size.width * 0.50, + // child: Image.asset(projectViewModel.isArabic ? 'assets/images/Wifi-AR.png' : 'assets/images/wifi-EN.png'), + // ), + // ), + // if (projectViewModel.isInternetConnection && widget.imagesInfo != null) + // CarouselSlider( + // items: widget.imagesInfo?.map((image) { + // return Builder( + // builder: (BuildContext context) { + // return SizedBox( + // width: MediaQuery.of(context).size.width * 0.50, + // child: image.isAsset! ? Image.asset(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!) : Image.network(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!)); + // }, + // ); + // }).toList(), + // options: CarouselOptions( + // height: MediaQuery.of(context).size.height * 0.55, + // autoPlay: widget.imagesInfo!.length > 1, + // viewportFraction: 1.0, + // ), + // ), + // ], + // ), + // ), + // SizedBox( + // height: 43, + // width: double.infinity, + // child: TextButton( + // onPressed: () { + // loginCheck(context); + // }, + // child: Text( + // TranslationBase.of(context).loginregister, + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.48), + // ), + // style: TextButton.styleFrom( + // backgroundColor: Color(0xffD02127), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(6), + // ), + // )), + // ), + // ]), + // ), + // ); + // + // return Scaffold( + // body: SingleChildScrollView( + // padding: EdgeInsets.all(12), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Texts( + // widget.title ?? 'Service', + // fontWeight: FontWeight.w800, + // fontSize: 25, + // bold: true, + // color: Color(0xff60686b), + // ), + // SizedBox( + // height: 12, + // ), + // Texts( + // widget.description ?? 'Description', + // fontWeight: FontWeight.normal, + // fontSize: 17, + // ), + // if (widget.infoList != null) + // SizedBox( + // height: 12, + // ), + // if (widget.infoList != null) + // ...List.generate( + // widget.infoList!.length, + // (index) => Container( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Row( + // children: [ + // Container( + // width: 40, + // height: 40, + // decoration: BoxDecoration(borderRadius: BorderRadius.circular(20), color: Theme.of(context).primaryColor), + // child: Center( + // child: Texts( + // '${index + 1}', + // color: Colors.white, + // ), + // ), + // ), + // SizedBox( + // width: 6, + // ), + // Expanded(child: Texts('${widget.infoList![index]}')) + // ], + // ), + // SizedBox( + // height: 12, + // ), + // ], + // ), + // ), + // ), + // SizedBox( + // height: 22, + // ), + // if (!projectViewModel.isInternetConnection) + // Center( + // child: SizedBox( + // height: MediaQuery.of(context).size.height * 0.55, + // width: MediaQuery.of(context).size.width * 0.50, + // child: Image.asset(projectViewModel.isArabic ? 'assets/images/Wifi-AR.png' : 'assets/images/wifi-EN.png'), + // ), + // ), + // if (projectViewModel.isInternetConnection && widget.imagesInfo != null) + // CarouselSlider( + // items: widget.imagesInfo!.map((image) { + // return Builder( + // builder: (BuildContext context) { + // return SizedBox( + // width: MediaQuery.of(context).size.width * 0.50, + // child: image.isAsset! ? Image.asset(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!) : Image.network(projectViewModel.isArabic! ? image.imageAr! : image.imageEn!)); + // }, + // ); + // }).toList(), + // options: CarouselOptions( + // height: MediaQuery.of(context).size.height * 0.55, + // autoPlay: widget.imagesInfo!.length > 1, + // viewportFraction: 1.0, + // ), + // ), + // SizedBox( + // height: 77, + // ), + // ], + // ), + // ), + // bottomSheet: Container( + // height: MediaQuery.of(context).size.height * 0.10, + // width: double.infinity, + // child: Column( + // children: [ + // Container( + // width: MediaQuery.of(context).size.width * 0.9, + // child: SecondaryButton( + // onTap: () { + // loginCheck(context); + // }, + // label: TranslationBase.of(context).serviceInformationButton, + // textColor: Theme.of(context).backgroundColor), + // ), + // ], + // ), + // ), + // ); } loginCheck(context) async { diff --git a/lib/widgets/otp/sms-popup.dart b/lib/widgets/otp/sms-popup.dart index c87dceeb..b6a89573 100644 --- a/lib/widgets/otp/sms-popup.dart +++ b/lib/widgets/otp/sms-popup.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:diplomaticquarterapp/config/size_config.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:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; @@ -211,12 +212,12 @@ class SMSOTP { errorBorder: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), - borderSide: BorderSide(color: Theme.of(context).errorColor), + borderSide: BorderSide(color: CustomColors.accentColor), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), - borderSide: BorderSide(color: Theme.of(context).errorColor), + borderSide: BorderSide(color: CustomColors.accentColor), ), ); } diff --git a/lib/widgets/text/app_texts_widget.dart b/lib/widgets/text/app_texts_widget.dart index 01dce651..0d1e6477 100644 --- a/lib/widgets/text/app_texts_widget.dart +++ b/lib/widgets/text/app_texts_widget.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/config/size_config.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; +import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -62,7 +63,7 @@ class _AppTextState extends State { overflow: TextOverflow.clip, style: TextStyle( - color: widget.color == null ? Theme.of(context).textTheme.bodyText1!.color : widget.color, + color: widget.color == null ? CustomColors.black : widget.color, fontWeight: widget.fontWeight, fontSize: widget.fontSize ?? (SizeConfig.textMultiplier! * 2), height: widget.height, diff --git a/pubspec.yaml b/pubspec.yaml index 6757122d..16e395b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: diplomaticquarterapp description: A new Flutter application. -version: 4.5.063+4050063 +version: 4.5.069+4050069 environment: sdk: ">=3.0.0 <3.13.0" @@ -13,9 +13,11 @@ dependencies: # Localizations flutter_localizations: sdk: flutter - intl: ^0.18.1 +# intl: ^0.18.1 + intl: ^0.19.0 - webview_flutter: ^2.0.4 +# webview_flutter: ^2.0.4 + webview_flutter: ^4.8.0 # http client http: ^0.13.4 @@ -32,7 +34,9 @@ dependencies: get_it: ^7.2.0 #Google Fit & Apple HealthKit - health: ^3.0.3 +# health: ^3.0.3 + health: ^11.1.0 +# pedometer: ^4.0.2 #chart fl_chart: ^0.64.0 @@ -97,16 +101,17 @@ dependencies: flutter_rating_bar: ^4.0.1 # Calendar - syncfusion_flutter_calendar: ^23.1.42 + # syncfusion_flutter_calendar: ^23.1.42 + syncfusion_flutter_calendar: ^24.1.47 # SVG Images flutter_svg: ^2.0.8 #Calendar Events - manage_calendar_events: ^2.0.3 + manage_calendar_events: 2.0.3 #InAppBrowser - flutter_inappwebview: ^5.8.0 + flutter_inappwebview: ^6.1.5 #Circular progress bar for reverse timer circular_countdown_timer: ^0.2.0 @@ -121,7 +126,7 @@ dependencies: flutter_datetime_picker_plus: ^2.1.0 carousel_pro_nullsafety: ^2.0.0 flutter_local_notifications: any - device_calendar: ^4.3.2 + device_calendar: ^4.3.3 geolocator: ^9.0.2 geocoding: ^2.0.1 jiffy: ^6.2.1 @@ -132,13 +137,15 @@ dependencies: google_maps_place_picker_mb: ^3.0.0 map_launcher: ^3.0.1 flutter_countdown_timer: ^4.1.0 + carousel_slider: ^5.0.0 #Dependencies for video call implementation native_device_orientation: ^1.0.0 - wakelock: ^0.6.2 +# wakelock: ^0.6.2 + wakelock_plus: ^1.1.4 after_layout: ^1.1.0 cached_network_image: ^3.3.0 flutter_tts: ^3.6.1 - vibration: ^1.7.3 +# vibration: ^1.7.3 flutter_nfc_kit: ^3.3.1 #geofencing: any speech_to_text: ^6.1.1 @@ -148,16 +155,16 @@ dependencies: in_app_review: ^2.0.3 badges: ^3.1.2 - flutter_app_icon_badge: ^2.0.0 +# flutter_app_icon_badge: ^2.0.0 # dropdown_search: 5.0.6 - youtube_player_flutter: ^8.1.2 + youtube_player_flutter: ^9.1.0 # shimmer: ^3.0.0 - carousel_slider: ^4.0.0 +# carousel_slider: ^4.0.0 # flutter_staggered_grid_view: ^0.7.0 huawei_hmsavailability: ^6.11.0+301 huawei_location: ^6.11.0+301 - share_plus: ^6.3.4 + share_plus: ^10.0.2 # Marker Animation auto_size_text: ^3.0.0 equatable: ^2.0.3 @@ -167,12 +174,15 @@ dependencies: google_api_availability: ^5.0.0 open_filex: ^4.3.2 path_provider: ^2.0.8 - amazon_payfort: ^1.1.0 + amazon_payfort: ^1.1.3 logger: ^2.0.2+1 network_info_plus: any - flutter_zoom_videosdk: ^1.10.11 + flutter_zoom_videosdk: ^1.11.2 dart_jsonwebtoken: ^2.14.0 + win32: ^5.5.4 + + cloudflare_turnstile: ^2.0.1 dependency_overrides: