diff --git a/agconnect-services_NewApp.json b/agconnect-services_NewApp.json new file mode 100644 index 0000000..66f04d1 --- /dev/null +++ b/agconnect-services_NewApp.json @@ -0,0 +1 @@ +{"agcgw":{"url":"connect-drcn.dbankcloud.cn","backurl":"connect-drcn.hispace.hicloud.com","websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn","websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com"},"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"2640966000002322881","product_id":"736430079244816567","client_id":"563735388191982656","client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF","project_id":"736430079244816567","app_id":"116912301","api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI","package_name":"com.cloudsolutions.HMGPatientApp"},"oauth_client":{"client_id":"116912301","client_type":1},"app_info":{"app_id":"116912301","package_name":"com.cloudsolutions.HMGPatientApp"},"service":{"analytics":{"collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn","collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn","resource_id":"p1","channel_id":""},"ml":{"mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"},"cloudstorage":{"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg":"https://ops-dra.agcstorage.link","storage_url_de":"https://ops-dre.agcstorage.link","storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia","storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu","storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn"},"search":{"url":"https://search-drcn.cloud.huawei.com"},"edukit":{"edu_url":"edukit.cloud.huawei.com.cn","dh_url":"edukit.cloud.huawei.com.cn"}},"region":"CN","configuration_version":"3.0","appInfos":[{"package_name":"com.cloudsolutions.HMGPatientApp","client":{"app_id":"116912301"},"app_info":{"package_name":"com.cloudsolutions.HMGPatientApp","app_id":"116912301"},"oauth_client":{"client_type":1,"client_id":"116912301"}},{"package_name":"com.ejada.hmg","client":{"app_id":"102857389"},"app_info":{"package_name":"com.ejada.hmg","app_id":"102857389"},"oauth_client":{"client_type":1,"client_id":"102857389"}}]} \ No newline at end of file diff --git a/android/app/agconnect-services.json b/android/app/agconnect-services.json index 91aad2c..66f04d1 100644 --- a/android/app/agconnect-services.json +++ b/android/app/agconnect-services.json @@ -1,74 +1 @@ -{ - "agcgw":{ - "backurl":"connect-drcn.hispace.hicloud.com", - "url":"connect-drcn.dbankcloud.cn", - "websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com", - "websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn" - }, - "agcgw_all":{ - "CN":"connect-drcn.dbankcloud.cn", - "CN_back":"connect-drcn.hispace.hicloud.com", - "DE":"connect-dre.dbankcloud.cn", - "DE_back":"connect-dre.hispace.hicloud.com", - "RU":"connect-drru.dbankcloud.cn", - "RU_back":"connect-drru.hispace.hicloud.com", - "SG":"connect-dra.dbankcloud.cn", - "SG_back":"connect-dra.hispace.hicloud.com" - }, - "client":{ - "cp_id":"2640966000002322881", - "product_id":"736430079244816567", - "client_id":"563735388191982656", - "client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF", - "project_id":"736430079244816567", - "app_id":"102857389", - "api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI", - "package_name":"com.ejada.hmg" - }, - "oauth_client":{ - "client_id":"102857389", - "client_type":1 - }, - "app_info":{ - "app_id":"102857389", - "package_name":"com.ejada.hmg" - }, - "service":{ - "analytics":{ - "collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", - "collector_url_ru":"datacollector-drru.dt.hicloud.com,datacollector-drru.dt.dbankcloud.cn", - "collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn", - "collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn", - "collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", - "resource_id":"p1", - "channel_id":"" - }, - "search":{ - "url":"https://search-drcn.cloud.huawei.com" - }, - "cloudstorage":{ - "storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn" - }, - "ml":{ - "mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn" - } - }, - "region":"CN", - "configuration_version":"3.0", - "appInfos":[ - { - "package_name":"com.ejada.hmg", - "client":{ - "app_id":"102857389" - }, - "app_info":{ - "package_name":"com.ejada.hmg", - "app_id":"102857389" - }, - "oauth_client":{ - "client_type":1, - "client_id":"102857389" - } - } - ] -} +{"agcgw":{"url":"connect-drcn.dbankcloud.cn","backurl":"connect-drcn.hispace.hicloud.com","websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn","websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com"},"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"2640966000002322881","product_id":"736430079244816567","client_id":"563735388191982656","client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF","project_id":"736430079244816567","app_id":"116912301","api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI","package_name":"com.cloudsolutions.HMGPatientApp"},"oauth_client":{"client_id":"116912301","client_type":1},"app_info":{"app_id":"116912301","package_name":"com.cloudsolutions.HMGPatientApp"},"service":{"analytics":{"collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn","collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn","resource_id":"p1","channel_id":""},"ml":{"mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"},"cloudstorage":{"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg":"https://ops-dra.agcstorage.link","storage_url_de":"https://ops-dre.agcstorage.link","storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia","storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu","storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn"},"search":{"url":"https://search-drcn.cloud.huawei.com"},"edukit":{"edu_url":"edukit.cloud.huawei.com.cn","dh_url":"edukit.cloud.huawei.com.cn"}},"region":"CN","configuration_version":"3.0","appInfos":[{"package_name":"com.cloudsolutions.HMGPatientApp","client":{"app_id":"116912301"},"app_info":{"package_name":"com.cloudsolutions.HMGPatientApp","app_id":"116912301"},"oauth_client":{"client_type":1,"client_id":"116912301"}},{"package_name":"com.ejada.hmg","client":{"app_id":"102857389"},"app_info":{"package_name":"com.ejada.hmg","app_id":"102857389"},"oauth_client":{"client_type":1,"client_id":"102857389"}}]} \ No newline at end of file diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 5d74c4d..d9d2f0b 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -18,12 +18,14 @@ if (keystorePropertiesFile.exists()) { } android { - namespace = "com.ejada.hmg" +// namespace = "com.ejada.hmg" + namespace = "com.cloudsolutions.HMGPatientApp" compileSdk = 36 ndkVersion = "28.2.13676358" defaultConfig { - applicationId = "com.ejada.hmg" +// applicationId = "com.ejada.hmg" + applicationId = "com.cloudsolutions.HMGPatientApp" // minSdk = 24 minSdk = 26 targetSdk = 36 diff --git a/android/app/google-services.json b/android/app/google-services.json index 3707617..49bf1ac 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -3,9 +3,45 @@ "project_number": "815750722565", "firebase_url": "https://api-project-815750722565.firebaseio.com", "project_id": "api-project-815750722565", - "storage_bucket": "api-project-815750722565.appspot.com" + "storage_bucket": "api-project-815750722565.firebasestorage.app" }, "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:815750722565:android:fa20b3a2401e08633c186c", + "android_client_info": { + "package_name": "com.cloudsolutions.HMGPatientApp" + } + }, + "oauth_client": [ + { + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg" + } + ], + "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" + } + } + ] + } + } + }, { "client_info": { "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8c1388b..54e1a5e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + package="com.cloudsolutions.HMGPatientApp"> + + + + + + + + + --> - + + + + diff --git a/android/app/src/main/kotlin/com/ejada/hmg/Application.kt b/android/app/src/main/kotlin/com/ejada/hmg/Application.kt deleted file mode 100644 index 32eb97c..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/Application.kt +++ /dev/null @@ -1,27 +0,0 @@ -//package com.cloud.diplomaticquarterapp -package com.ejada.hmg - - -import io.flutter.app.FlutterApplication - -class Application : FlutterApplication() { - override fun onCreate() { - super.onCreate() - } -} - -//import io.flutter.app.FlutterApplication -//import io.flutter.plugin.common.PluginRegistry -//import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback -//import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService -// -//class Application : FlutterApplication(), PluginRegistrantCallback { -// override fun onCreate() { -// super.onCreate() -// FlutterFirebaseMessagingService.setPluginRegistrant(this) -// } -// -// override fun registerWith(registry: PluginRegistry?) { -// FirebaseCloudMessagingPluginRegistrant.registerWith(registry) -// } -//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/ejada/hmg/MainActivity.kt b/android/app/src/main/kotlin/com/ejada/hmg/MainActivity.kt deleted file mode 100644 index b81a6fb..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/MainActivity.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.ejada.hmg - -import android.app.PendingIntent -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.ejada.hmg.penguin.PenguinInPlatformBridge -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugins.GeneratedPluginRegistrant - -import io.flutter.embedding.android.FlutterFragmentActivity - - -class MainActivity: FlutterFragmentActivity() { - @RequiresApi(Build.VERSION_CODES.O) - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine); - // Create Flutter Platform Bridge - this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) - - PenguinInPlatformBridge(flutterEngine, this).create() - } - - 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() { - super.onResume() - } -} diff --git a/android/app/src/main/kotlin/com/ejada/hmg/PenguinInPlatformBridge.kt b/android/app/src/main/kotlin/com/ejada/hmg/PenguinInPlatformBridge.kt deleted file mode 100644 index 4df25bc..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PenguinInPlatformBridge.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.ejada.hmg.penguin - -import com.ejada.hmg.MainActivity -import android.os.Build -import android.util.Log -import androidx.annotation.RequiresApi -import com.ejada.hmg.penguin.PenguinView -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugin.common.MethodCall -import com.ejada.hmg.PermissionManager.HostNotificationPermissionManager -import com.ejada.hmg.PermissionManager.HostBgLocationManager -import com.ejada.hmg.PermissionManager.HostGpsStateManager -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") - - if (HostNotificationPermissionManager.isNotificationPermissionGranted(mainActivity)) - else HostNotificationPermissionManager.requestNotificationPermission(mainActivity) - HostBgLocationManager.requestLocationBackgroundPermission(mainActivity) - HostGpsStateManager.requestLocationPermission(mainActivity) - 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/ejada/hmg/PermissionManager/AppPreferences.java b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/AppPreferences.java deleted file mode 100644 index d012799..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/AppPreferences.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.ejada.hmg.PermissionManager; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Handler; -import android.os.HandlerThread; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; - - -/** - * This preferences for app level - */ - -public class AppPreferences { - - public static final String PREF_NAME = "PenguinINUI_AppPreferences"; - public static final int MODE = Context.MODE_PRIVATE; - - public static final String campusIdKey = "campusId"; - - public static final String LANG = "Lang"; - - public static final String settingINFO = "SETTING-INFO"; - - public static final String userName = "userName"; - public static final String passWord = "passWord"; - - private static HandlerThread handlerThread; - private static Handler handler; - - static { - handlerThread = new HandlerThread("PreferencesHandlerThread"); - handlerThread.start(); - handler = new Handler(handlerThread.getLooper()); - } - - - - public static SharedPreferences getPreferences(final Context context) { - return context.getSharedPreferences(AppPreferences.PREF_NAME, AppPreferences.MODE); - } - - public static SharedPreferences.Editor getEditor(final Context context) { - return getPreferences(context).edit(); - } - - - public static void writeInt(final Context context, final String key, final int value) { - handler.post(() -> { - SharedPreferences.Editor editor = getEditor(context); - editor.putInt(key, value); - editor.apply(); - }); - } - - - public static int readInt(final Context context, final String key, final int defValue) { - Callable callable = () -> { - SharedPreferences preferences = getPreferences(context); - return preferences.getInt(key, -1); - }; - - Future future = new FutureTask<>(callable); - handler.post((Runnable) future); - - try { - return future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); // Handle the exception appropriately - } - - return -1; // Return the default value in case of an error - } - - public static int getCampusId(final Context context) { - return readInt(context,campusIdKey,-1); - } - - - - public static void writeString(final Context context, final String key, final String value) { - handler.post(() -> { - SharedPreferences.Editor editor = getEditor(context); - editor.putString(key, value); - editor.apply(); - }); - } - - - public static String readString(final Context context, final String key, final String defValue) { - Callable callable = () -> { - SharedPreferences preferences = getPreferences(context); - return preferences.getString(key, defValue); - }; - - Future future = new FutureTask<>(callable); - handler.post((Runnable) future); - - try { - return future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); // Handle the exception appropriately - } - - return defValue; // Return the default value in case of an error - } - - - public static void writeBoolean(final Context context, final String key, final boolean value) { - handler.post(() -> { - SharedPreferences.Editor editor = getEditor(context); - editor.putBoolean(key, value); - editor.apply(); - }); - } - - public static boolean readBoolean(final Context context, final String key, final boolean defValue) { - Callable callable = () -> { - SharedPreferences preferences = getPreferences(context); - return preferences.getBoolean(key, defValue); - }; - - Future future = new FutureTask<>(callable); - handler.post((Runnable) future); - - try { - return future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); // Handle the exception appropriately - } - - return defValue; // Return the default value in case of an error - } - -} diff --git a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostBgLocationManager.java b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostBgLocationManager.java deleted file mode 100644 index 5bc332d..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostBgLocationManager.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.ejada.hmg.PermissionManager; - -import android.Manifest; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.provider.Settings; - -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import com.peng.pennavmap.PlugAndPlaySDK; -import com.peng.pennavmap.R; -import com.peng.pennavmap.enums.InitializationErrorType; - -/** - * Manages background location permission requests and handling for the application. - */ -public class HostBgLocationManager { - /** - * Request code for background location permission - */ - public static final int REQUEST_ACCESS_BACKGROUND_LOCATION_CODE = 301; - - /** - * Request code for navigating to app settings - */ - private static final int REQUEST_CODE_SETTINGS = 11234; - - /** - * Alert dialog for denied permissions - */ - private static AlertDialog deniedAlertDialog; - - /** - * Checks if the background location permission has been granted. - * - * @param context the context of the application or activity - * @return true if the permission is granted, false otherwise - */ - - public static boolean isLocationBackgroundGranted(Context context) { - return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) - == PackageManager.PERMISSION_GRANTED; - } - - /** - * Requests the background location permission from the user. - * - * @param activity the activity from which the request is made - */ - public static void requestLocationBackgroundPermission(Activity activity) { - // Check if the ACCESS_BACKGROUND_LOCATION permission is already granted - if (!isLocationBackgroundGranted(activity)) { - // Permission is not granted, so request it - ActivityCompat.requestPermissions(activity, - new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, - REQUEST_ACCESS_BACKGROUND_LOCATION_CODE); - } - } - - /** - * Displays a dialog prompting the user to grant the background location permission. - * - * @param activity the activity where the dialog is displayed - */ - public static void showLocationBackgroundPermission(Activity activity) { - AlertDialog alertDialog = new AlertDialog.Builder(activity) - .setCancelable(false) - .setMessage(activity.getString(R.string.com_penguin_nav_ui_geofence_alert_msg)) - .setPositiveButton(activity.getString(R.string.com_penguin_nav_ui_go_to_settings), (dialog, which) -> { - if (activity.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { - HostBgLocationManager.requestLocationBackgroundPermission(activity); - } else { - openAppSettings(activity); - } - if (dialog != null) { - dialog.dismiss(); - } - }) - .setNegativeButton(activity.getString(R.string.com_penguin_nav_ui_later), (dialog, which) -> { - dialog.cancel(); - }) - .create(); - - alertDialog.show(); - } - - /** - * Handles the scenario where permissions are denied by the user. - * Displays a dialog to guide the user to app settings or exit the activity. - * - * @param activity the activity where the dialog is displayed - */ - public static synchronized void handlePermissionsDenied(Activity activity) { - if (deniedAlertDialog != null && deniedAlertDialog.isShowing()) { - deniedAlertDialog.dismiss(); - } - - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setCancelable(false) - .setMessage(activity.getString(R.string.com_penguin_nav_ui_permission_denied_dialog_msg)) - .setNegativeButton(activity.getString(R.string.com_penguin_nav_ui_cancel), (dialogInterface, i) -> { - if (PlugAndPlaySDK.externalPenNavUIDelegate != null) { - PlugAndPlaySDK.externalPenNavUIDelegate.onPenNavInitializationError( - InitializationErrorType.permissions.getTypeKey(), - InitializationErrorType.permissions); - } - activity.finish(); - }) - .setPositiveButton(activity.getString(R.string.com_penguin_nav_ui_go_settings), (dialogInterface, i) -> { - dialogInterface.dismiss(); - openAppSettings(activity); - }); - deniedAlertDialog = builder.create(); - deniedAlertDialog.show(); - } - - /** - * Opens the application's settings screen to allow the user to modify permissions. - * - * @param activity the activity from which the settings screen is launched - */ - private static void openAppSettings(Activity activity) { - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - Uri uri = Uri.fromParts("package", activity.getPackageName(), null); - intent.setData(uri); - - if (intent.resolveActivity(activity.getPackageManager()) != null) { - activity.startActivityForResult(intent, REQUEST_CODE_SETTINGS); - } - } -} diff --git a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostGpsStateManager.java b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostGpsStateManager.java deleted file mode 100644 index adde120..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostGpsStateManager.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.ejada.hmg.PermissionManager; - -import android.Manifest; -import android.app.Activity; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.LocationManager; - -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import com.peng.pennavmap.managers.permissions.managers.BgLocationManager; - -public class HostGpsStateManager { - private static final int LOCATION_PERMISSION_REQUEST_CODE = 1; - - - public boolean checkGPSEnabled(Activity activity) { - LocationManager gpsStateManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); - return gpsStateManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - } - - public static boolean isGpsGranted(Activity activity) { - return BgLocationManager.isLocationBackgroundGranted(activity) - || ContextCompat.checkSelfPermission( - activity, - Manifest.permission.ACCESS_FINE_LOCATION - ) == PackageManager.PERMISSION_GRANTED - && ContextCompat.checkSelfPermission( - activity, - Manifest.permission.ACCESS_COARSE_LOCATION - ) == PackageManager.PERMISSION_GRANTED; - } - - - /** - * Checks if the location permission is granted. - * - * @param activity the Activity context - * @return true if permission is granted, false otherwise - */ - public static boolean isLocationPermissionGranted(Activity activity) { - return ContextCompat.checkSelfPermission( - activity, - Manifest.permission.ACCESS_FINE_LOCATION - ) == PackageManager.PERMISSION_GRANTED && - ContextCompat.checkSelfPermission( - activity, - Manifest.permission.ACCESS_COARSE_LOCATION - ) == PackageManager.PERMISSION_GRANTED; - } - - /** - * Requests the location permission. - * - * @param activity the Activity context - */ - public static void requestLocationPermission(Activity activity) { - ActivityCompat.requestPermissions( - activity, - new String[]{ - Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION, - }, - LOCATION_PERMISSION_REQUEST_CODE - ); - } -} diff --git a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostNotificationPermissionManager.java b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostNotificationPermissionManager.java deleted file mode 100644 index 5b9f19e..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/HostNotificationPermissionManager.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.ejada.hmg.PermissionManager; - -import android.app.Activity; -import android.content.pm.PackageManager; -import android.os.Build; - -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.core.app.NotificationManagerCompat; - -public class HostNotificationPermissionManager { - private static final int REQUEST_NOTIFICATION_PERMISSION = 100; - - - /** - * Checks if the notification permission is granted. - * - * @return true if the notification permission is granted, false otherwise. - */ - public static boolean isNotificationPermissionGranted(Activity activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - try { - return ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.POST_NOTIFICATIONS) - == PackageManager.PERMISSION_GRANTED; - } catch (Exception e) { - // Handle cases where the API is unavailable - e.printStackTrace(); - return NotificationManagerCompat.from(activity).areNotificationsEnabled(); - } - } else { - // Permissions were not required below Android 13 for notifications - return NotificationManagerCompat.from(activity).areNotificationsEnabled(); - } - } - - /** - * Requests the notification permission. - */ - public static void requestNotificationPermission(Activity activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - if (!isNotificationPermissionGranted(activity)) { - ActivityCompat.requestPermissions(activity, - new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, - REQUEST_NOTIFICATION_PERMISSION); - } - } - } - - /** - * Handles the result of the permission request. - * - * @param requestCode The request code passed in requestPermissions(). - * @param permissions The requested permissions. - * @param grantResults The grant results for the corresponding permissions. - */ - public static boolean handlePermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if (permissions.length > 0 && - permissions[0].equals(android.Manifest.permission.POST_NOTIFICATIONS) && - grantResults.length > 0 && - grantResults[0] == PackageManager.PERMISSION_GRANTED) { - // Permission granted - System.out.println("Notification permission granted."); - return true; - } else { - // Permission denied - System.out.println("Notification permission denied."); - return false; - } - - } - - -} diff --git a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionHelper.kt b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionHelper.kt deleted file mode 100644 index 9856a49..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionHelper.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.ejada.hmg.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/ejada/hmg/PermissionManager/PermissionManager.kt b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionManager.kt deleted file mode 100644 index d8aea7b..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionManager.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.ejada.hmg.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/ejada/hmg/PermissionManager/PermissionResultReceiver.kt b/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionResultReceiver.kt deleted file mode 100644 index c07d1de..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/PermissionManager/PermissionResultReceiver.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.ejada.hmg.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/ejada/hmg/penguin/PenguinMethod.kt b/android/app/src/main/kotlin/com/ejada/hmg/penguin/PenguinMethod.kt deleted file mode 100644 index 18463d2..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/penguin/PenguinMethod.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.ejada.hmg.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/ejada/hmg/penguin/PenguinNavigator.kt b/android/app/src/main/kotlin/com/ejada/hmg/penguin/PenguinNavigator.kt deleted file mode 100644 index 70889d3..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/penguin/PenguinNavigator.kt +++ /dev/null @@ -1,97 +0,0 @@ -package com.ejada.hmg.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+++++++ $refID") - - 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/ejada/hmg/penguin/PenguinView.kt b/android/app/src/main/kotlin/com/ejada/hmg/penguin/PenguinView.kt deleted file mode 100644 index 3925ca5..0000000 --- a/android/app/src/main/kotlin/com/ejada/hmg/penguin/PenguinView.kt +++ /dev/null @@ -1,377 +0,0 @@ -package com.ejada.hmg.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.ejada.hmg.PermissionManager.PermissionManager -import com.ejada.hmg.PermissionManager.PermissionResultReceiver -import com.ejada.hmg.MainActivity -import com.ejada.hmg.PermissionManager.PermissionHelper -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.ejada.hmg.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.LocationMessage -import com.peng.pennavmap.models.PIReportIssue -import java.util.ArrayList -import penguin.com.pennav.renderer.PIRendererSettings - -/** - * 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, PIEventsDelegate, - PILocationDelegate { - // 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().get(0) - ) - - 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 - } - } - - -// PlugAndPlaySDK.configuration = Builder() -// .setClientData(MConstantsDemo.CLIENT_ID, MConstantsDemo.CLIENT_KEY) -// .setLanguageID(selectedLanguage) -// .setBaseUrl(MConstantsDemo.DATA_URL, MConstantsDemo.POSITION_URL) -// .setServiceName(MConstantsDemo.DATA_SERVICE_NAME, MConstantsDemo.POSITION_SERVICE_NAME) -// .setUserName(name) -// .setSimulationModeEnabled(isSimulation) -// .setCustomizeColor(if (MConstantsDemo.APP_COLOR != null) MConstantsDemo.APP_COLOR else "#2CA0AF") -// .setEnableBackButton(MConstantsDemo.SHOW_BACK_BUTTON) -// .setCampusId(MConstantsDemo.selectedCampusId) -// -// .setShowUILoader(true) -// .build() - - PIRendererSettings.styleUri = "mapbox://styles/rwaid/cm3h30b36007v01qz7ik8a0sk" - - 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("", "") - .setIsEnableReportIssue(true) - .setDeepLinkData("") - .setEnableSharedLocationCallBack(false) - .setShowUILoader(true) - .setCampusId(creationParams["projectID"] as Int) - .build() - - - Log.d( - "TAG", - "initPenguin: ${creationParams["projectID"]}" - ) - - Log.d( - "TAG", - "initPenguin: creation param are ${creationParams}" - ) - - // 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(new PIEventsDelegate() { -// @Override -// public void onReportIssue(PIReportIssue issue) { -// Log.e("Issue Reported: ", issue.getReportType()); -// } -// // Implement issue reporting logic here } -// @Override -// public void onSharedLocation(String link) { -// // Implement Shared location logic here -// } -// }) - - // Start the Penguin SDK - PlugAndPlaySDK.setPiEventsDelegate(this) - PlugAndPlaySDK.setPiLocationDelegate(this) - 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) -// navigateTo("3-1") - } - - /** - * 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 - ) - Log.d( - "description", - "description : ${description}" - ) - - 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") - } - } - - override fun onReportIssue(issue: PIReportIssue?) { - TODO("Not yet implemented") - } - - override fun onSharedLocation(link: String?) { - TODO("Not yet implemented") - } - - override fun onLocationOffCampus(location: ArrayList?) { - TODO("Not yet implemented") - } - - override fun onLocationMessage(locationMessage: LocationMessage?) { - TODO("Not yet implemented") - } -} diff --git a/android/google-services.json b/android/google-services.json index 3707617..49bf1ac 100644 --- a/android/google-services.json +++ b/android/google-services.json @@ -3,9 +3,45 @@ "project_number": "815750722565", "firebase_url": "https://api-project-815750722565.firebaseio.com", "project_id": "api-project-815750722565", - "storage_bucket": "api-project-815750722565.appspot.com" + "storage_bucket": "api-project-815750722565.firebasestorage.app" }, "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:815750722565:android:fa20b3a2401e08633c186c", + "android_client_info": { + "package_name": "com.cloudsolutions.HMGPatientApp" + } + }, + "oauth_client": [ + { + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg" + } + ], + "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" + } + } + ] + } + } + }, { "client_info": { "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 6d0842d..1c91fb7 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,6 +19,9 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" // id("com.android.application") version "8.9.3" apply false + // START: FlutterFire Configuration + id("com.google.gms.google-services") version("4.4.1") apply false + // END: FlutterFire Configuration id("com.android.application") version "8.9.3" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false } diff --git a/assets/animations/lottie/checkmark.json b/assets/animations/lottie/checkmark.json old mode 100755 new mode 100644 index 998a915..57b67e2 --- a/assets/animations/lottie/checkmark.json +++ b/assets/animations/lottie/checkmark.json @@ -1,767 +1 @@ -{ - "nm": "HDFC Success", - "h": 512, - "w": 512, - "meta": { - "g": "LottieFiles AE 1.0.0" - }, - "layers": [ - { - "ty": 4, - "nm": "check", - "sr": 1, - "st": 0, - "op": 240, - "ip": 0, - "hasMask": false, - "ao": 0, - "ks": { - "a": { - "a": 0, - "k": [ - 0, - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 100, - 100, - 100 - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 256, - 256, - 0 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - }, - "ef": [], - "shapes": [ - { - "ty": "gr", - "nm": "Shape 1", - "it": [ - { - "ty": "sh", - "nm": "Path 1", - "d": 1, - "ks": { - "a": 0, - "k": { - "c": false, - "i": [ - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ] - ], - "o": [ - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ] - ], - "v": [ - [ - -82.5, - 4.5 - ], - [ - -31, - 55 - ], - [ - 73, - -52.5 - ] - ] - } - } - }, - { - "ty": "tm", - "nm": "Trim Paths 1", - "e": { - "a": 1, - "k": [ - { - "o": { - "x": 1, - "y": 0.076 - }, - "i": { - "x": 0.667, - "y": 1 - }, - "s": [ - 0 - ], - "t": 60 - }, - { - "s": [ - 100 - ], - "t": 85 - } - ] - }, - "o": { - "a": 0, - "k": 0 - }, - "s": { - "a": 0, - "k": 0 - }, - "m": 1 - }, - { - "ty": "st", - "nm": "Stroke 1", - "lc": 2, - "lj": 2, - "ml": 1, - "o": { - "a": 0, - "k": 100 - }, - "w": { - "a": 0, - "k": 30 - }, - "c": { - "a": 0, - "k": [ - 1, - 1, - 1 - ] - } - }, - { - "ty": "tr", - "a": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - } - ] - } - ], - "ind": 1 - }, - { - "ty": 4, - "nm": "Shape Layer 2", - "sr": 1, - "st": 0, - "op": 240, - "ip": 0, - "hasMask": false, - "ao": 0, - "ks": { - "a": { - "a": 0, - "k": [ - 0, - 0, - 0 - ] - }, - "s": { - "a": 1, - "k": [ - { - "o": { - "x": 0.656, - "y": 0.872 - }, - "i": { - "x": 0, - "y": 0.98 - }, - "s": [ - 0, - 0, - 100 - ], - "t": 20 - }, - { - "s": [ - 150, - 150, - 100 - ], - "t": 60 - } - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 256, - 257.86, - 0 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - }, - "ef": [], - "shapes": [ - { - "ty": "gr", - "nm": "Ellipse 1", - "it": [ - { - "ty": "el", - "nm": "Ellipse Path 1", - "d": 1, - "p": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 236, - 236 - ] - } - }, - { - "ty": "fl", - "nm": "Fill 1", - "c": { - "a": 0, - "k": [ - 0.094, - 0.761, - 0.451 - ] - }, - "r": 1, - "o": { - "a": 0, - "k": 100 - } - }, - { - "ty": "tr", - "a": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 0, - -3 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - } - ] - } - ], - "ind": 2 - }, - { - "ty": 4, - "nm": "Shape Layer 1", - "sr": 1, - "st": 0, - "op": 240, - "ip": 0, - "hasMask": false, - "ao": 0, - "ks": { - "a": { - "a": 0, - "k": [ - 0, - 0, - 0 - ] - }, - "s": { - "a": 1, - "k": [ - { - "o": { - "x": 0.477, - "y": 0.587 - }, - "i": { - "x": 0, - "y": 0.999 - }, - "s": [ - 0, - 0, - 100 - ], - "t": 10 - }, - { - "o": { - "x": 0.167, - "y": 0.167 - }, - "i": { - "x": 0.833, - "y": 0.833 - }, - "s": [ - 150, - 150, - 100 - ], - "t": 50 - }, - { - "o": { - "x": 0.167, - "y": 0 - }, - "i": { - "x": 0.833, - "y": 1 - }, - "s": [ - 150, - 150, - 100 - ], - "t": 76 - }, - { - "s": [ - 210, - 210, - 100 - ], - "t": 123 - } - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 256, - 257.86, - 0 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 1, - "k": [ - { - "o": { - "x": 0.912, - "y": 0.073 - }, - "i": { - "x": 0.626, - "y": 0.729 - }, - "s": [ - 100 - ], - "t": 76 - }, - { - "s": [ - 0 - ], - "t": 119 - } - ] - } - }, - "ef": [], - "shapes": [ - { - "ty": "gr", - "nm": "Ellipse 1", - "it": [ - { - "ty": "el", - "nm": "Ellipse Path 1", - "d": 1, - "p": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 236, - 236 - ] - } - }, - { - "ty": "st", - "nm": "Stroke 1", - "lc": 1, - "lj": 1, - "ml": 4, - "o": { - "a": 0, - "k": 100 - }, - "w": { - "a": 0, - "k": 2 - }, - "c": { - "a": 0, - "k": [ - 1, - 1, - 1 - ] - } - }, - { - "ty": "fl", - "nm": "Fill 1", - "c": { - "a": 0, - "k": [ - 0.784, - 0.945, - 0.878 - ] - }, - "r": 1, - "o": { - "a": 0, - "k": 100 - } - }, - { - "ty": "tr", - "a": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 0, - -3 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - } - ] - } - ], - "ind": 3 - }, - { - "ty": 4, - "nm": "BG", - "sr": 1, - "st": 0, - "op": 240, - "ip": 0, - "hasMask": false, - "ao": 0, - "ks": { - "a": { - "a": 0, - "k": [ - 0, - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 100, - 100, - 100 - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - 256, - 256, - 0 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - }, - "ef": [], - "shapes": [ - { - "ty": "gr", - "nm": "Rectangle 1", - "it": [ - { - "ty": "rc", - "nm": "Rectangle Path 1", - "d": 1, - "p": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "s": { - "a": 0, - "k": [ - 554, - 556 - ] - } - }, - { - "ty": "fl", - "nm": "Fill 1", - "c": { - "a": 0, - "k": [ - 0.972, - 0.972, - 0.972 - ] - }, - "r": 1, - "o": { - "a": 0, - "k": 100 - } - }, - { - "ty": "tr", - "a": { - "a": 0, - "k": [ - 0, - 0 - ] - }, - "s": { - "a": 0, - "k": [ - 100, - 100 - ] - }, - "sk": { - "a": 0, - "k": 0 - }, - "p": { - "a": 0, - "k": [ - -1, - 6 - ] - }, - "r": { - "a": 0, - "k": 0 - }, - "sa": { - "a": 0, - "k": 0 - }, - "o": { - "a": 0, - "k": 100 - } - } - ] - } - ], - "ind": 4 - } - ], - "v": "4.8.0", - "fr": 60, - "op": 130, - "ip": 0, - "assets": [] -} \ No newline at end of file +{"nm":"Main Scene","ddd":0,"h":512,"w":512,"meta":{"g":"@lottiefiles/creator 1.75.0"},"layers":[{"ty":4,"nm":"check","sr":1,"st":0,"op":240,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[256,256],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 1","ix":1,"cix":2,"np":4,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-82.5,4.5],[-31,55],[73,-52.5]]},"ix":2}},{"ty":"tm","bm":0,"hd":false,"mn":"ADBE Vector Filter - Trim","nm":"Trim Paths 1","ix":2,"e":{"a":1,"k":[{"o":{"x":1,"y":0.076},"i":{"x":0.667,"y":1},"s":[0],"t":60},{"s":[100],"t":85}],"ix":2},"o":{"a":0,"k":0,"ix":3},"s":{"a":0,"k":0,"ix":1},"m":1},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"c":{"a":0,"k":[1,1,1],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1},{"ty":4,"nm":"Shape Layer 2","sr":1,"st":0,"op":240,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.656,"y":0.872},"i":{"x":0,"y":0.98},"s":[0,0,100],"t":20},{"s":[150,150,100],"t":60}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[256,257.86],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[236,236],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.0941,0.7608,0.451],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,-3],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":2},{"ty":4,"nm":"Shape Layer 1","sr":1,"st":0,"op":240,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.477,"y":0.587},"i":{"x":0,"y":0.999},"s":[0,0,100],"t":10},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[150,150,100],"t":50},{"o":{"x":0.167,"y":0},"i":{"x":0.833,"y":1},"s":[150,150,100],"t":76},{"s":[210,210,100],"t":123}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[256,257.86],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.912,"y":0.073},"i":{"x":0.626,"y":0.729},"s":[100],"t":76},{"s":[0],"t":119}],"ix":11}},"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[236,236],"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"c":{"a":0,"k":[1,1,1],"ix":3}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.7843,0.9451,0.8784],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,-3],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":3}],"v":"5.7.0","fr":60,"op":130,"ip":0,"assets":[]} \ No newline at end of file diff --git a/assets/animations/lottie/checkmark_old.json b/assets/animations/lottie/checkmark_old.json new file mode 100755 index 0000000..998a915 --- /dev/null +++ b/assets/animations/lottie/checkmark_old.json @@ -0,0 +1,767 @@ +{ + "nm": "HDFC Success", + "h": 512, + "w": 512, + "meta": { + "g": "LottieFiles AE 1.0.0" + }, + "layers": [ + { + "ty": 4, + "nm": "check", + "sr": 1, + "st": 0, + "op": 240, + "ip": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 256, + 256, + 0 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "nm": "Shape 1", + "it": [ + { + "ty": "sh", + "nm": "Path 1", + "d": 1, + "ks": { + "a": 0, + "k": { + "c": false, + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -82.5, + 4.5 + ], + [ + -31, + 55 + ], + [ + 73, + -52.5 + ] + ] + } + } + }, + { + "ty": "tm", + "nm": "Trim Paths 1", + "e": { + "a": 1, + "k": [ + { + "o": { + "x": 1, + "y": 0.076 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 0 + ], + "t": 60 + }, + { + "s": [ + 100 + ], + "t": 85 + } + ] + }, + "o": { + "a": 0, + "k": 0 + }, + "s": { + "a": 0, + "k": 0 + }, + "m": 1 + }, + { + "ty": "st", + "nm": "Stroke 1", + "lc": 2, + "lj": 2, + "ml": 1, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 30 + }, + "c": { + "a": 0, + "k": [ + 1, + 1, + 1 + ] + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + } + ] + } + ], + "ind": 1 + }, + { + "ty": 4, + "nm": "Shape Layer 2", + "sr": 1, + "st": 0, + "op": 240, + "ip": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.656, + "y": 0.872 + }, + "i": { + "x": 0, + "y": 0.98 + }, + "s": [ + 0, + 0, + 100 + ], + "t": 20 + }, + { + "s": [ + 150, + 150, + 100 + ], + "t": 60 + } + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 256, + 257.86, + 0 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "nm": "Ellipse 1", + "it": [ + { + "ty": "el", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 236, + 236 + ] + } + }, + { + "ty": "fl", + "nm": "Fill 1", + "c": { + "a": 0, + "k": [ + 0.094, + 0.761, + 0.451 + ] + }, + "r": 1, + "o": { + "a": 0, + "k": 100 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + -3 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + } + ] + } + ], + "ind": 2 + }, + { + "ty": 4, + "nm": "Shape Layer 1", + "sr": 1, + "st": 0, + "op": 240, + "ip": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.477, + "y": 0.587 + }, + "i": { + "x": 0, + "y": 0.999 + }, + "s": [ + 0, + 0, + 100 + ], + "t": 10 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 150, + 150, + 100 + ], + "t": 50 + }, + { + "o": { + "x": 0.167, + "y": 0 + }, + "i": { + "x": 0.833, + "y": 1 + }, + "s": [ + 150, + 150, + 100 + ], + "t": 76 + }, + { + "s": [ + 210, + 210, + 100 + ], + "t": 123 + } + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 256, + 257.86, + 0 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 1, + "k": [ + { + "o": { + "x": 0.912, + "y": 0.073 + }, + "i": { + "x": 0.626, + "y": 0.729 + }, + "s": [ + 100 + ], + "t": 76 + }, + { + "s": [ + 0 + ], + "t": 119 + } + ] + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "nm": "Ellipse 1", + "it": [ + { + "ty": "el", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 236, + 236 + ] + } + }, + { + "ty": "st", + "nm": "Stroke 1", + "lc": 1, + "lj": 1, + "ml": 4, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 2 + }, + "c": { + "a": 0, + "k": [ + 1, + 1, + 1 + ] + } + }, + { + "ty": "fl", + "nm": "Fill 1", + "c": { + "a": 0, + "k": [ + 0.784, + 0.945, + 0.878 + ] + }, + "r": 1, + "o": { + "a": 0, + "k": 100 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + -3 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + } + ] + } + ], + "ind": 3 + }, + { + "ty": 4, + "nm": "BG", + "sr": 1, + "st": 0, + "op": 240, + "ip": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 256, + 256, + 0 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "nm": "Rectangle 1", + "it": [ + { + "ty": "rc", + "nm": "Rectangle Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "s": { + "a": 0, + "k": [ + 554, + 556 + ] + } + }, + { + "ty": "fl", + "nm": "Fill 1", + "c": { + "a": 0, + "k": [ + 0.972, + 0.972, + 0.972 + ] + }, + "r": 1, + "o": { + "a": 0, + "k": 100 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + -1, + 6 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + } + ] + } + ], + "ind": 4 + } + ], + "v": "4.8.0", + "fr": 60, + "op": 130, + "ip": 0, + "assets": [] +} \ No newline at end of file diff --git a/assets/images/svg/livecare_audio.svg b/assets/images/svg/livecare_audio.svg new file mode 100644 index 0000000..339d534 --- /dev/null +++ b/assets/images/svg/livecare_audio.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/livecare_phone.svg b/assets/images/svg/livecare_phone.svg new file mode 100644 index 0000000..1722f0f --- /dev/null +++ b/assets/images/svg/livecare_phone.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/livecare_video.svg b/assets/images/svg/livecare_video.svg new file mode 100644 index 0000000..bab506f --- /dev/null +++ b/assets/images/svg/livecare_video.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 11ab941..76e10ea 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -945,6 +945,7 @@ "offline": "غير متصل", "videoCall": "مكالمة فيديو", "liveVideoCallWithHMGDoctors": "مكالمة فيديو مباشرة مع أطباء مجموعة الحبيب الطبية", + "liveAudioCallWithHMGDoctors": "مكالمة صوتية مباشرة مع أطباء مجموعة الحبيب الطبية", "audioCall": "مكالمة صوتية", "phoneCall": "مكالمة هاتفية", "livePhoneCallWithHMGDoctors": "مكالمة هاتفية مباشرة مع أطباء مجموعة الحبيب الطبية", @@ -1571,5 +1572,14 @@ "noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.", "noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.", "unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة", - "loadingAIAnalysis": "جارٍ تحميل بياناتك وتحليلها، يُرجى التحلي بالصبر ودع الذكاء الاصطناعي يقوم بالمهمة. يُرجى التحلي بالصبر، فقد يستغرق هذا بعض الوقت." + "loadingAIAnalysis": "جارٍ تحليل نتائج المختبر، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.", + "symptoms": "أعراض", + "insuranceInActive": "التأمين غير نشط", + "insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.", + "updateAppNow": "تحديث التطبيق الآن", + "Dr": "الدكتور.", + "reschedulingAppo": "إعادة جدولة الموعد، يرجى الانتظار...", + "invalidEligibility": "لا يمكنك إجراء الدفع عبر الإنترنت لأنك غير مؤهل لاستخدام الخدمة المقدمة.", + "invalidInsurance": "لا يمكنك إجراء الدفع عبر الإنترنت لأنه ليس لديك تأمين صالح.", + "continueCash": "تواصل نقدا" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 3f1bc78..bf73d6d 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -937,6 +937,7 @@ "offline": "Offline", "videoCall": "Video Call", "liveVideoCallWithHMGDoctors": "Live Video Call with HMG Doctors", + "liveAudioCallWithHMGDoctors": "Live Audio Call with HMG Doctors", "audioCall": "Audio Call", "phoneCall": "Phone Call", "livePhoneCallWithHMGDoctors": "Live Phone Call with HMG Doctors", @@ -1562,5 +1563,14 @@ "contextDependent": "Context Dependent", "calculatedValue": "Calculated Value", "calculationFormula": "Calculation Formula", - "loadingAIAnalysis": "Loading and analysing your data, Please be patient and let the AI do the magic. Please be patient, This might take some time." + "loadingAIAnalysis": "Analysing your lab results, Please be patient and let the AI do the magic, This might take some time.", + "symptoms": "Symptoms", + "insuranceInActive": "Insurance Inactive", + "insuranceInActiveContactSupport": "You have a valid insurance but it is currently inactive in HMG. Please contact HMG customer support to activate it.", + "updateAppNow": "Update App Now", + "Dr": "Dr.", + "reschedulingAppo": "Rescheduling Appointment, Please wait...", + "invalidEligibility": "You cannot make online payment because you are not eligible to use the provided service.", + "invalidInsurance": "You cannot make online payment because you do not have a valid insurance.", + "continueCash": "Continue as cash" } diff --git a/assets/sounds/ring_30Sec.caf b/assets/sounds/ring_30Sec.caf new file mode 100644 index 0000000..b5bb4b8 Binary files /dev/null and b/assets/sounds/ring_30Sec.caf differ diff --git a/assets/sounds/ring_30Sec.mp3 b/assets/sounds/ring_30Sec.mp3 new file mode 100644 index 0000000..f647cca Binary files /dev/null and b/assets/sounds/ring_30Sec.mp3 differ diff --git a/assets/sounds/ring_60Sec.mp3 b/assets/sounds/ring_60Sec.mp3 new file mode 100644 index 0000000..ac32394 Binary files /dev/null and b/assets/sounds/ring_60Sec.mp3 differ diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..7d1b1fd --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"api-project-815750722565","appId":"1:815750722565:android:62281cd3e5df4063","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"api-project-815750722565","appId":"1:815750722565:ios:34ec03c09e02e21f3c186c","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"api-project-815750722565","configurations":{"android":"1:815750722565:android:62281cd3e5df4063","ios":"1:815750722565:ios:34ec03c09e02e21f3c186c"}}}}}} \ No newline at end of file diff --git a/google-services_NewApp.json b/google-services_NewApp.json new file mode 100644 index 0000000..49bf1ac --- /dev/null +++ b/google-services_NewApp.json @@ -0,0 +1,83 @@ +{ + "project_info": { + "project_number": "815750722565", + "firebase_url": "https://api-project-815750722565.firebaseio.com", + "project_id": "api-project-815750722565", + "storage_bucket": "api-project-815750722565.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:815750722565:android:fa20b3a2401e08633c186c", + "android_client_info": { + "package_name": "com.cloudsolutions.HMGPatientApp" + } + }, + "oauth_client": [ + { + "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg" + } + ], + "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" + } + } + ] + } + } + }, + { + "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": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg" + } + ], + "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/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index dd2d96e..e031a97 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -24,6 +24,8 @@ 765A5A8F2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 765A5A902F35CD8B0003FF7D /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */; }; 765A5A912F35CD8B0003FF7D /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 76AA18AE2F3B2A4D00DC8DFC /* ring_30Sec.caf in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */; }; + 76AA18AF2F3B2A4D00DC8DFC /* ring_30Sec.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -77,6 +79,8 @@ 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenguinINRenderer.xcframework; sourceTree = ""; }; 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenNavUI.xcframework; sourceTree = ""; }; 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; + 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ring_30Sec.caf; sourceTree = ""; }; + 76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ring_30Sec.mp3; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 8E12CEEB8E334EE22D5259D7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; @@ -189,6 +193,8 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */, + 76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */, 61243B412EC5FA3700D46FA0 /* Helper */, 61243B472EC5FA3700D46FA0 /* Penguin */, 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */, @@ -300,6 +306,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 76AA18AE2F3B2A4D00DC8DFC /* ring_30Sec.caf in Resources */, + 76AA18AF2F3B2A4D00DC8DFC /* ring_30Sec.mp3 in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */, @@ -515,7 +523,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 3A359E86ZF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -701,7 +709,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 3A359E86ZF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -730,7 +738,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 3A359E86ZF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist index c179ec6..a9b1f53 100644 --- a/ios/Runner/GoogleService-Info.plist +++ b/ios/Runner/GoogleService-Info.plist @@ -2,10 +2,6 @@ - CLIENT_ID - 815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com - REVERSED_CLIENT_ID - com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt ANDROID_CLIENT_ID 815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com API_KEY @@ -15,24 +11,24 @@ PLIST_VERSION 1 BUNDLE_ID - com.HMG.HMG-Smartphone + com.cloudsolutions.HMGPatientApp PROJECT_ID api-project-815750722565 STORAGE_BUCKET - api-project-815750722565.appspot.com + api-project-815750722565.firebasestorage.app IS_ADS_ENABLED - + IS_ANALYTICS_ENABLED - + IS_APPINVITE_ENABLED - + IS_GCM_ENABLED - + IS_SIGNIN_ENABLED - + GOOGLE_APP_ID - 1:815750722565:ios:328ec247a81a2ca23c186c + 1:815750722565:ios:34ec03c09e02e21f3c186c DATABASE_URL https://api-project-815750722565.firebaseio.com - + \ No newline at end of file diff --git a/ios/Runner/ring_30Sec 2.caf b/ios/Runner/ring_30Sec 2.caf new file mode 100644 index 0000000..b5bb4b8 Binary files /dev/null and b/ios/Runner/ring_30Sec 2.caf differ diff --git a/ios/Runner/ring_30Sec.caf b/ios/Runner/ring_30Sec.caf new file mode 100644 index 0000000..b5bb4b8 Binary files /dev/null and b/ios/Runner/ring_30Sec.caf differ diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 231b037..970b1e4 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -7,9 +7,11 @@ import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/presentation/home/app_update_page.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:http/http.dart' as http; import '../exceptions/api_failure.dart'; @@ -36,6 +38,7 @@ abstract class ApiClient { required Function(dynamic response, int statusCode) onSuccess, required Function(String error, int statusCode) onFailure, Map? queryParams, + Map apiHeaders, bool isAllowAny, bool isExternal, bool isRCService, @@ -192,10 +195,14 @@ class ApiClientImp implements ApiClient { } // body['TokenID'] = "@dm!n"; - // body['PatientID'] = 4768663; + // body['PatientID'] = 4773715; // body['PatientTypeID'] = 1; // body['PatientOutSA'] = 0; // body['SessionID'] = "45786230487560q"; + + // body['IdentificationNo'] = "2235558844"; + // body['MobileNo'] = "966533147722"; + // body['PatientID'] = 809289; } if(!url.contains("/paymentApi")) { @@ -220,7 +227,8 @@ class ApiClientImp implements ApiClient { // Handle body encoding based on isBodyPlainText flag final dynamic requestBody = isBodyPlainText ? body : json.encode(body); debugPrint("uri: ${Uri.parse(url.trim())}"); - debugPrint("body: ${json.encode(body)}", wrapWidth: 2048); + var requestBodyJSON = json.encode(body); + debugPrint("body: $requestBodyJSON", wrapWidth: 2048); final response = await http.post(Uri.parse(url.trim()), body: requestBody, headers: headers); final int statusCode = response.statusCode; // log("response.body: ${response.body}"); @@ -245,8 +253,16 @@ class ApiClientImp implements ApiClient { } else { if (parsed['ErrorType'] == 4) { //TODO : handle app update - onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, - failureType: AppUpdateFailure("parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']")); + // onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, + // failureType: AppUpdateFailure("parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']")); + + ApiClient._navigationService.pushAndRemoveUntil( + CustomPageRoute( + page: AppUpdatePage( + appUpdateMessage: parsed['ErrorEndUserMessage'], + )), + ModalRoute.withName("/appUpdate") + ); logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } if (parsed['ErrorType'] == 2) { @@ -366,6 +382,7 @@ class ApiClientImp implements ApiClient { {required Function(dynamic response, int statusCode) onSuccess, required Function(String error, int statusCode) onFailure, Map? queryParams, + Map? apiHeaders, bool isAllowAny = false, bool isExternal = false, bool isRCService = false}) async { @@ -390,7 +407,7 @@ class ApiClientImp implements ApiClient { if (await Utils.checkConnection(bypassConnectionCheck: true)) { final response = await http.get( Uri.parse(url.trim()), - headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, + headers: apiHeaders ?? {'Content-Type': 'application/json', 'Accept': 'application/json'}, ); final int statusCode = response.statusCode; // print("statusCode :$statusCode"); diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index f78c020..a57169d 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -1,6 +1,242 @@ import 'package:amazon_payfort/amazon_payfort.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; +class ApiConsts { + static const maxSmallScreen = 660; + + static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat; + + // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT + + static String baseUrl = 'https://hmgwebservices.com/'; // HIS API URL PROD + + static String rcBaseUrl = 'https://rc.hmg.com/'; // dRC API URL PROD + static String hmgPharmacyApiBaseUrl = 'https://hmgpharmacyapi.hmg.com/'; // dRC API URL PROD + static String symptomsCheckerApi = '${hmgPharmacyApiBaseUrl}symptomsapi/api/SymptomChecker'; // dRC API URL PROD + + static var payFortEnvironment = FortEnvironment.production; + static var applePayMerchantId = "merchant.com.hmgwebservices"; + + static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE + // static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT + + static String TAMARA_URL = "https://mdlaboratories.com/tamaralive/Home/Checkout"; + static String GET_TAMARA_INSTALLMENTS_URL = "https://mdlaboratories.com/tamaralive/Home/GetInstallments"; + static String GET_TAMARA_PAYMENT_STATUS = 'https://mdlaboratories.com/tamaralive/api/OnlineTamara/order_status?orderid='; + + static String QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + + static String CHAT_URL = "https://chat.hmg.com/Index.aspx?RequestedId="; + + // static String GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; + +// var payFortEnvironment = FortEnvironment.test; +// var applePayMerchantId = "merchant.com.hmgwebservices.uat"; + + static setBackendURLs() { + switch (appEnvironmentType) { + case AppEnvironmentTypeEnum.prod: + baseUrl = "https://hmgwebservices.com/"; + payFortEnvironment = FortEnvironment.production; + applePayMerchantId = "merchant.com.hmgwebservices"; + SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx"; + TAMARA_URL = "https://mdlaboratories.com/tamaralive/Home/Checkout"; + GET_TAMARA_INSTALLMENTS_URL = "https://mdlaboratories.com/tamaralive/Home/GetInstallments"; + GET_TAMARA_PAYMENT_STATUS = 'https://mdlaboratories.com/tamaralive/api/OnlineTamara/order_status?orderid='; + rcBaseUrl = 'https://rc.hmg.com/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + CHAT_URL = "https://chat.hmg.com/Index.aspx?RequestedId="; + break; + case AppEnvironmentTypeEnum.dev: + baseUrl = "https://uat.hmgwebservices.com/"; + payFortEnvironment = FortEnvironment.test; + applePayMerchantId = "merchant.com.hmgwebservices.uat"; + SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; + TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; + GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; + GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; + rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; + break; + case AppEnvironmentTypeEnum.uat: + baseUrl = "https://uat.hmgwebservices.com/"; + payFortEnvironment = FortEnvironment.test; + applePayMerchantId = "merchant.com.hmgwebservices.uat"; + SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; + TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; + GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; + GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; + rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; + break; + case AppEnvironmentTypeEnum.preProd: + baseUrl = "https://webservices.hmg.com/"; + payFortEnvironment = FortEnvironment.production; + applePayMerchantId = "merchant.com.hmgwebservices"; + SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx"; + TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; + GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; + GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; + rcBaseUrl = 'https://rc.hmg.com/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; + break; + case AppEnvironmentTypeEnum.qa: + baseUrl = "https://uat.hmgwebservices.com/"; + payFortEnvironment = FortEnvironment.test; + applePayMerchantId = "merchant.com.hmgwebservices.uat"; + SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; + TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; + GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; + GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; + rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; + break; + case AppEnvironmentTypeEnum.staging: + baseUrl = "https://uat.hmgwebservices.com/"; + payFortEnvironment = FortEnvironment.test; + applePayMerchantId = "merchant.com.hmgwebservices.uat"; + SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; + TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; + GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; + GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; + rcBaseUrl = 'https://rc.hmg.com/uat/'; + QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; + CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; + break; + } + } + + static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; + static final String checkPatientAuth = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; + + static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType'; + static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration'; + static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode'; + static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration'; + static final String checkUsageAgreement = 'Services/Patients.svc/REST/CheckForUsageAgreement'; + static final String getUserAgreementContent = 'Services/Patients.svc/REST/GetUsageAgreementText'; + + static final String checkPatientForRegistration = 'Services/Authentication.svc/REST/CheckPatientForRegisteration'; + static final String checkUserStatus = 'Services/NHIC.svc/REST/GetPatientInfo'; + + static final String insertPatientDeviceIMEIData = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI'; + static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo'; + static final String getPatientMobileData = '/Services/Authentication.svc/REST/GetMobileLoginInfo'; + static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege'; + static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration'; + + static final String addFamilyFile = 'Services/Patients.svc/REST/ShareFamilyFileService'; + static final String sendFamilyFileActivation = 'Services/Authentication.svc/REST/SendActivationCodeForFamilyFile'; + static final String checkActivationCodeForFamily = 'Services/Authentication.svc/REST/CheckActivationCodeForFamilyFile'; + static final String getAllPendingRecordsByResponseId = 'Services/Authentication.svc/REST/GetAllPendingRecordsByResponseId'; + static final String getAllSharedRecordsByStatus = 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatus'; + static final String removeFileFromFamilyMembers = 'Services/Authentication.svc/REST/ActiveDeactive_PatientFile'; + static final String acceptAndRejectFamilyFile = 'Services/Authentication.svc/REST/Update_FileStatus'; + static final String getActivePrescriptionsDetails = 'Services/Patients.svc/Rest/GetActivePrescriptionReportByPatientID'; + static final String getTermsConditions = 'Services/Patients.svc/Rest/GetUserTermsAndConditions'; + static final String getMonthlyReports = 'Services/Patients.svc/Rest/UpdatePateintHealthSummaryReport'; + static final String updatePatientEmail = 'Services/Patients.svc/Rest/UpdatePateintEmail'; + static final String getQrParkingDetails = 'Services/SWP.svc/REST/GetQRParkingByID'; + + // Ancillary Order Apis + static final String getOnlineAncillaryOrderList = 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderList'; + static final String getOnlineAncillaryOrderProcList = 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderProcList'; + static final String generateAncillaryOrderInvoice = 'Services/Doctors.svc/REST/AutoGenerateAncillaryOrderInvoice'; + static final String autoGenerateAncillaryOrdersInvoice = 'Services/Doctors.svc/REST/AutoGenerateAncillaryOrderInvoice'; + static final String getRequestStatusByRequestID = 'Services/PayFort_Serv.svc/REST/GetRequestStatusByRequestID'; + + //Payment APIs + static final String applePayInsertRequest = "Services/PayFort_Serv.svc/REST/PayFort_ApplePayRequestData_Insert"; + static final String createAdvancePayments = 'Services/Patients.svc/REST/HIS_CreateAdvancePayment'; + static final String addAdvanceNumberRequest = 'Services/PayFort_Serv.svc/REST/AddAdvancedNumberRequest'; + + // RC COMPREHENSIVE MEDICAL CHECKUP ServIces + static final String allCMCOrdersRc = 'api/cmc/list'; + static final String allCMCServicesRc = 'api/cmc/getallcmc'; + static final String updateCMCOrder = 'api/cmc/update'; + static final String addCMCOrder = 'api/cmc/add'; + static final String getHospitalsList = 'Services/Lists.svc/REST/GetProject'; + + // RC HOME HEALTHCARE ServIces + static final String allHHCOrdersRc = 'api/hhc/list'; + static final String allHHCServicesRc = 'api/HHC/getallhhc'; + static final String updateHHCOrder = 'api/hhc/update'; + static final String addHHCOrder = 'api/HHC/add'; + + // SYMPTOMS CHECKER API + static final String symptomsUserLogin = '$symptomsCheckerApi/user_login'; + static final String getBodySymptomsByName = '$symptomsCheckerApi/GetBodySymptomsByName'; + static final String getRiskFactors = '$symptomsCheckerApi/GetRiskFactors'; + static final String getSuggestions = '$symptomsCheckerApi/GetSuggestion'; + static final String diagnosis = '$symptomsCheckerApi/GetDiagnosis'; + static final String explain = '$symptomsCheckerApi/ExplainDiagnosisResult'; + static final String getClinicFromCondition = '$symptomsCheckerApi/GetClinicsByCondition?condition='; + + //E-REFERRAL SERVICES + static final getAllRelationshipTypes = "Services/Patients.svc/REST/GetAllRelationshipTypes"; + static final sendActivationCodeForEReferral = 'Services/Authentication.svc/REST/SendActivationCodeForEReferral'; + static final checkActivationCodeForEReferral = 'Services/Authentication.svc/REST/CheckActivationCodeForEReferral'; + static final getAllCities = 'services/Lists.svc/rest/GetAllCities'; + static final createEReferral = "Services/Patients.svc/REST/CreateEReferral"; + static final getEReferrals = "Services/Patients.svc/REST/GetEReferrals"; + + //WATER CONSUMPTION + static String h2oGetUserProgress = "Services/H2ORemainder.svc/REST/H2O_GetUserProgress"; + static String h2oInsertUserActivity = "Services/H2ORemainder.svc/REST/H2O_InsertUserActivity"; + static String h2oInsertUserDetailsNew = "Services/H2ORemainder.svc/REST/H2O_InsertUserDetails_New"; + static String h2oGetUserDetail = "Services/H2ORemainder.svc/REST/H2O_GetUserDetails_New"; + static String h2oUpdateUserDetail = "Services/H2ORemainder.svc/REST/H2O_UpdateUserDetails_New"; + static String h2oUndoUserActivity = "Services/H2ORemainder.svc/REST/H2o_UndoUserActivity"; + + // HEALTH TRACKERS + // Blood Sugar (Diabetic) + static String getDiabeticResultAverage = 'Services/Patients.svc/REST/Patient_GetDiabeticResultAverage'; + static String getDiabeticResult = 'Services/Patients.svc/REST/Patient_GetDiabtecResults'; + static String addDiabeticResult = 'Services/Patients.svc/REST/Patient_AddDiabtecResult'; + static String updateDiabeticResult = 'Services/Patients.svc/REST/Patient_UpdateDiabtecResult'; + static String deactivateDiabeticStatus = 'Services/Patients.svc/REST/Patient_DeactivateDiabeticStatus'; + static String sendAverageBloodSugarReport = 'Services/Notifications.svc/REST/SendAverageBloodSugarReport'; + + // Blood Pressure + static String getBloodPressureResultAverage = 'Services/Patients.svc/REST/Patient_GetBloodPressureResultAverage'; + static String getBloodPressureResult = 'Services/Patients.svc/REST/Patient_GetBloodPressureResult'; + static String addBloodPressureResult = 'Services/Patients.svc/REST/Patient_AddBloodPressureResult'; + static String updateBloodPressureResult = 'Services/Patients.svc/REST/Patient_UpdateBloodPressureResult'; + static String deactivateBloodPressureStatus = 'Services/Patients.svc/REST/Patient_DeactivateBloodPressureStatus'; + static String sendAverageBloodPressureReport = 'Services/Notifications.svc/REST/SendAverageBloodPressureReport'; + + // Weight Measurement + static String getWeightMeasurementResultAverage = 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResultAverage'; + static String getWeightMeasurementResult = 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResult'; + static String addWeightMeasurementResult = 'Services/Patients.svc/REST/Patient_AddWeightMeasurementResult'; + static String updateWeightMeasurementResult = 'Services/Patients.svc/REST/Patient_UpdateWeightMeasurementResult'; + static String deactivateWeightMeasurementStatus = 'Services/Patients.svc/REST/Patient_DeactivateWeightMeasurementStatus'; + static String sendAverageBodyWeightReport = 'Services/Notifications.svc/REST/SendAverageBodyWeightReport'; + + //Blood Donation + static String bloodGroupUpdate = "Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType"; + static String userAgreementForBloodGroupUpdate = "Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation"; + static String getProjectsHaveBDClinics = "Services/OUTPs.svc/REST/BD_getProjectsHaveBDClinics"; + static String getClinicsBDFreeSlots = "Services/OUTPs.svc/REST/BD_GetFreeSlots"; + + static String getPatientBloodGroup = "services/PatientVarification.svc/REST/BloodDonation_GetBloodGroupDetails"; + static String getPatientBloodAgreement = "Services/PatientVarification.svc/REST/CheckUserAgreementForBloodDonation"; + static String getAiOverViewLabOrders = "Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API"; + static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API"; + + // ************ static values for Api **************** + static final double appVersionID = 19.7; + // static final double appVersionID = 50.7; + static final int appChannelId = 3; + static final String appIpAddress = "10.20.10.20"; + static final String appGeneralId = "Cs2020@2016\$2958"; + static final String sessionID = 'TMRhVmkGhOsvamErw'; +} + // PACKAGES and OFFERS var EXA_CART_API_BASE_URL = 'https://mdlaboratories.com/offersdiscounts'; // var EXA_CART_API_BASE_URL = 'http://10.200.101.75:9000'; @@ -680,242 +916,6 @@ var GET_PRESCRIPTION_INSTRUCTIONS_PDF = 'Services/ChatBot_Service.svc/REST/Chatb const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard'; -class ApiConsts { - static const maxSmallScreen = 660; - - static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; - - // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT - - static String baseUrl = 'https://hmgwebservices.com/'; // HIS API URL PROD - - static String rcBaseUrl = 'https://rc.hmg.com/'; // dRC API URL PROD - static String hmgPharmacyApiBaseUrl = 'https://hmgpharmacyapi.hmg.com/'; // dRC API URL PROD - static String symptomsCheckerApi = '${hmgPharmacyApiBaseUrl}symptomsapi/api/SymptomChecker'; // dRC API URL PROD - - static var payFortEnvironment = FortEnvironment.production; - static var applePayMerchantId = "merchant.com.hmgwebservices"; - - static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE - // static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT - - static String TAMARA_URL = "https://mdlaboratories.com/tamaralive/Home/Checkout"; - static String GET_TAMARA_INSTALLMENTS_URL = "https://mdlaboratories.com/tamaralive/Home/GetInstallments"; - static String GET_TAMARA_PAYMENT_STATUS = 'https://mdlaboratories.com/tamaralive/api/OnlineTamara/order_status?orderid='; - - static String QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - - static String CHAT_URL = "https://chat.hmg.com/Index.aspx?RequestedId="; - - // static String GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; - -// var payFortEnvironment = FortEnvironment.test; -// var applePayMerchantId = "merchant.com.hmgwebservices.uat"; - - static setBackendURLs() { - switch (appEnvironmentType) { - case AppEnvironmentTypeEnum.prod: - baseUrl = "https://hmgwebservices.com/"; - payFortEnvironment = FortEnvironment.production; - applePayMerchantId = "merchant.com.hmgwebservices"; - SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx"; - TAMARA_URL = "https://mdlaboratories.com/tamaralive/Home/Checkout"; - GET_TAMARA_INSTALLMENTS_URL = "https://mdlaboratories.com/tamaralive/Home/GetInstallments"; - GET_TAMARA_PAYMENT_STATUS = 'https://mdlaboratories.com/tamaralive/api/OnlineTamara/order_status?orderid='; - rcBaseUrl = 'https://rc.hmg.com/'; - QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - CHAT_URL = "https://chat.hmg.com/Index.aspx?RequestedId="; - break; - case AppEnvironmentTypeEnum.dev: - baseUrl = "https://uat.hmgwebservices.com/"; - payFortEnvironment = FortEnvironment.test; - applePayMerchantId = "merchant.com.hmgwebservices.uat"; - SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; - TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; - GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; - GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; - rcBaseUrl = 'https://rc.hmg.com/uat/'; - QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; - break; - case AppEnvironmentTypeEnum.uat: - baseUrl = "https://uat.hmgwebservices.com/"; - payFortEnvironment = FortEnvironment.test; - applePayMerchantId = "merchant.com.hmgwebservices.uat"; - SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; - TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; - GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; - GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; - rcBaseUrl = 'https://rc.hmg.com/uat/'; - QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; - break; - case AppEnvironmentTypeEnum.preProd: - baseUrl = "https://webservices.hmg.com/"; - payFortEnvironment = FortEnvironment.production; - applePayMerchantId = "merchant.com.hmgwebservices"; - SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx"; - TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; - GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; - GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; - rcBaseUrl = 'https://rc.hmg.com/'; - QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; - break; - case AppEnvironmentTypeEnum.qa: - baseUrl = "https://uat.hmgwebservices.com/"; - payFortEnvironment = FortEnvironment.test; - applePayMerchantId = "merchant.com.hmgwebservices.uat"; - SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; - TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; - GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; - GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; - rcBaseUrl = 'https://rc.hmg.com/uat/'; - QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; - break; - case AppEnvironmentTypeEnum.staging: - baseUrl = "https://uat.hmgwebservices.com/"; - payFortEnvironment = FortEnvironment.test; - applePayMerchantId = "merchant.com.hmgwebservices.uat"; - SERVICE_URL = 'https://uat.hmgwebservices.com/HMGPayment/pages/SendPayFortRequest.aspx'; - TAMARA_URL = "https://epharmacy.hmg.com/tamara/Home/Checkout"; - GET_TAMARA_INSTALLMENTS_URL = "https://epharmacy.hmg.com/tamara/Home/getinstallments"; - GET_TAMARA_PAYMENT_STATUS = 'https://epharmacy.hmg.com/tamara/api/OnlineTamara/order_status?orderid='; - rcBaseUrl = 'https://rc.hmg.com/uat/'; - QLINE_URL = "https://ms.hmg.com/nscapi/api/PatientCall/PatientInQueue_Detail"; - CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId"; - break; - } - } - - static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; - static final String checkPatientAuth = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; - - static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType'; - static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration'; - static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode'; - static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration'; - static final String checkUsageAgreement = 'Services/Patients.svc/REST/CheckForUsageAgreement'; - static final String getUserAgreementContent = 'Services/Patients.svc/REST/GetUsageAgreementText'; - - static final String checkPatientForRegistration = 'Services/Authentication.svc/REST/CheckPatientForRegisteration'; - static final String checkUserStatus = 'Services/NHIC.svc/REST/GetPatientInfo'; - - static final String insertPatientDeviceIMEIData = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI'; - static final String insertPatientMobileData = 'Services/MobileNotifications.svc/REST/Insert_PatientMobileDeviceInfo'; - static final String getPatientMobileData = '/Services/Authentication.svc/REST/GetMobileLoginInfo'; - static final String getPrivileges = 'Services/Patients.svc/REST/Service_Privilege'; - static final String registerUser = 'Services/Authentication.svc/REST/PatientRegistration'; - - static final String addFamilyFile = 'Services/Patients.svc/REST/ShareFamilyFileService'; - static final String sendFamilyFileActivation = 'Services/Authentication.svc/REST/SendActivationCodeForFamilyFile'; - static final String checkActivationCodeForFamily = 'Services/Authentication.svc/REST/CheckActivationCodeForFamilyFile'; - static final String getAllPendingRecordsByResponseId = 'Services/Authentication.svc/REST/GetAllPendingRecordsByResponseId'; - static final String getAllSharedRecordsByStatus = 'Services/Authentication.svc/REST/GetAllSharedRecordsByStatus'; - static final String removeFileFromFamilyMembers = 'Services/Authentication.svc/REST/ActiveDeactive_PatientFile'; - static final String acceptAndRejectFamilyFile = 'Services/Authentication.svc/REST/Update_FileStatus'; - static final String getActivePrescriptionsDetails = 'Services/Patients.svc/Rest/GetActivePrescriptionReportByPatientID'; - static final String getTermsConditions = 'Services/Patients.svc/Rest/GetUserTermsAndConditions'; - static final String getMonthlyReports = 'Services/Patients.svc/Rest/UpdatePateintHealthSummaryReport'; - static final String updatePatientEmail = 'Services/Patients.svc/Rest/UpdatePateintEmail'; - static final String getQrParkingDetails = 'Services/SWP.svc/REST/GetQRParkingByID'; - - // Ancillary Order Apis - static final String getOnlineAncillaryOrderList = 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderList'; - static final String getOnlineAncillaryOrderProcList = 'Services/Doctors.svc/REST/GetOnlineAncillaryOrderProcList'; - static final String generateAncillaryOrderInvoice = 'Services/Doctors.svc/REST/AutoGenerateAncillaryOrderInvoice'; - static final String autoGenerateAncillaryOrdersInvoice = 'Services/Doctors.svc/REST/AutoGenerateAncillaryOrderInvoice'; - static final String getRequestStatusByRequestID = 'Services/PayFort_Serv.svc/REST/GetRequestStatusByRequestID'; - - //Payment APIs - static final String applePayInsertRequest = "Services/PayFort_Serv.svc/REST/PayFort_ApplePayRequestData_Insert"; - static final String createAdvancePayments = 'Services/Patients.svc/REST/HIS_CreateAdvancePayment'; - static final String addAdvanceNumberRequest = 'Services/PayFort_Serv.svc/REST/AddAdvancedNumberRequest'; - - // RC COMPREHENSIVE MEDICAL CHECKUP ServIces - static final String allCMCOrdersRc = 'api/cmc/list'; - static final String allCMCServicesRc = 'api/cmc/getallcmc'; - static final String updateCMCOrder = 'api/cmc/update'; - static final String addCMCOrder = 'api/cmc/add'; - static final String getHospitalsList = 'Services/Lists.svc/REST/GetProject'; - - // RC HOME HEALTHCARE ServIces - static final String allHHCOrdersRc = 'api/hhc/list'; - static final String allHHCServicesRc = 'api/HHC/getallhhc'; - static final String updateHHCOrder = 'api/hhc/update'; - static final String addHHCOrder = 'api/HHC/add'; - - // SYMPTOMS CHECKER API - static final String symptomsUserLogin = '$symptomsCheckerApi/user_login'; - static final String getBodySymptomsByName = '$symptomsCheckerApi/GetBodySymptomsByName'; - static final String getRiskFactors = '$symptomsCheckerApi/GetRiskFactors'; - static final String getSuggestions = '$symptomsCheckerApi/GetSuggestion'; - static final String diagnosis = '$symptomsCheckerApi/GetDiagnosis'; - static final String explain = '$symptomsCheckerApi/ExplainDiagnosisResult'; - - //E-REFERRAL SERVICES - static final getAllRelationshipTypes = "Services/Patients.svc/REST/GetAllRelationshipTypes"; - static final sendActivationCodeForEReferral = 'Services/Authentication.svc/REST/SendActivationCodeForEReferral'; - static final checkActivationCodeForEReferral = 'Services/Authentication.svc/REST/CheckActivationCodeForEReferral'; - static final getAllCities = 'services/Lists.svc/rest/GetAllCities'; - static final createEReferral = "Services/Patients.svc/REST/CreateEReferral"; - static final getEReferrals = "Services/Patients.svc/REST/GetEReferrals"; - - //WATER CONSUMPTION - static String h2oGetUserProgress = "Services/H2ORemainder.svc/REST/H2O_GetUserProgress"; - static String h2oInsertUserActivity = "Services/H2ORemainder.svc/REST/H2O_InsertUserActivity"; - static String h2oInsertUserDetailsNew = "Services/H2ORemainder.svc/REST/H2O_InsertUserDetails_New"; - static String h2oGetUserDetail = "Services/H2ORemainder.svc/REST/H2O_GetUserDetails_New"; - static String h2oUpdateUserDetail = "Services/H2ORemainder.svc/REST/H2O_UpdateUserDetails_New"; - static String h2oUndoUserActivity = "Services/H2ORemainder.svc/REST/H2o_UndoUserActivity"; - - // HEALTH TRACKERS - // Blood Sugar (Diabetic) - static String getDiabeticResultAverage = 'Services/Patients.svc/REST/Patient_GetDiabeticResultAverage'; - static String getDiabeticResult = 'Services/Patients.svc/REST/Patient_GetDiabtecResults'; - static String addDiabeticResult = 'Services/Patients.svc/REST/Patient_AddDiabtecResult'; - static String updateDiabeticResult = 'Services/Patients.svc/REST/Patient_UpdateDiabtecResult'; - static String deactivateDiabeticStatus = 'Services/Patients.svc/REST/Patient_DeactivateDiabeticStatus'; - static String sendAverageBloodSugarReport = 'Services/Notifications.svc/REST/SendAverageBloodSugarReport'; - - // Blood Pressure - static String getBloodPressureResultAverage = 'Services/Patients.svc/REST/Patient_GetBloodPressureResultAverage'; - static String getBloodPressureResult = 'Services/Patients.svc/REST/Patient_GetBloodPressureResult'; - static String addBloodPressureResult = 'Services/Patients.svc/REST/Patient_AddBloodPressureResult'; - static String updateBloodPressureResult = 'Services/Patients.svc/REST/Patient_UpdateBloodPressureResult'; - static String deactivateBloodPressureStatus = 'Services/Patients.svc/REST/Patient_DeactivateBloodPressureStatus'; - static String sendAverageBloodPressureReport = 'Services/Notifications.svc/REST/SendAverageBloodPressureReport'; - - // Weight Measurement - static String getWeightMeasurementResultAverage = 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResultAverage'; - static String getWeightMeasurementResult = 'Services/Patients.svc/REST/Patient_GetWeightMeasurementResult'; - static String addWeightMeasurementResult = 'Services/Patients.svc/REST/Patient_AddWeightMeasurementResult'; - static String updateWeightMeasurementResult = 'Services/Patients.svc/REST/Patient_UpdateWeightMeasurementResult'; - static String deactivateWeightMeasurementStatus = 'Services/Patients.svc/REST/Patient_DeactivateWeightMeasurementStatus'; - static String sendAverageBodyWeightReport = 'Services/Notifications.svc/REST/SendAverageBodyWeightReport'; - - //Blood Donation - static String bloodGroupUpdate = "Services/PatientVarification.svc/REST/BloodDonation_RegisterBloodType"; - static String userAgreementForBloodGroupUpdate = "Services/PatientVarification.svc/REST/AddUserAgreementForBloodDonation"; - static String getProjectsHaveBDClinics = "Services/OUTPs.svc/REST/BD_getProjectsHaveBDClinics"; - static String getClinicsBDFreeSlots = "Services/OUTPs.svc/REST/BD_GetFreeSlots"; - - - static String getPatientBloodGroup = "services/PatientVarification.svc/REST/BloodDonation_GetBloodGroupDetails"; - static String getPatientBloodAgreement = "Services/PatientVarification.svc/REST/CheckUserAgreementForBloodDonation"; - static String getAiOverViewLabOrders = "Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API"; - static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API"; - - // ************ static values for Api **************** - // static final double appVersionID = 19.7; - static final double appVersionID = 50.7; - static final int appChannelId = 3; - static final String appIpAddress = "10.20.10.20"; - static final String appGeneralId = "Cs2020@2016\$2958"; - static final String sessionID = 'TMRhVmkGhOsvamErw'; -} - class ApiKeyConstants { static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng'; } diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index 96c7cc0..942eb46 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -295,6 +295,10 @@ class AppAssets { static const String bulb = '$svgBasePath/bulb.svg'; static const String switchBtn = '$svgBasePath/switch.svg'; + static const String livecare_video = '$svgBasePath/livecare_video.svg'; + static const String livecare_audio = '$svgBasePath/livecare_audio.svg'; + static const String livecare_phone = '$svgBasePath/livecare_phone.svg'; + //Health Trackers static const String bloodPressureIcon = '$svgBasePath/blood_pressure_icon.svg'; static const String bloodSugarOnlyIcon = '$svgBasePath/blood_sugar_only_icon.svg'; diff --git a/lib/core/utils/penguin_method_channel.dart b/lib/core/utils/penguin_method_channel.dart index 69ef4be..c3da724 100644 --- a/lib/core/utils/penguin_method_channel.dart +++ b/lib/core/utils/penguin_method_channel.dart @@ -12,13 +12,17 @@ class PenguinMethodChannel { try { await _channel.invokeMethod('launchPenguin', { "storyboardName": storyboardName, - "baseURL": "https://penguinuat.hmg.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://penguinuat.hmg.com", - "positionURL": "https://penguinuat.hmg.com", + + // UAT URLs + // "baseURL": "https://penguinuat.hmg.com", + // "dataURL": "https://penguinuat.hmg.com", + // "positionURL": "https://penguinuat.hmg.com", + + // Prod URLs + "baseURL": "https://eagleiq.hmg.com", + "dataURL": "https://eagleiq.hmg.com", + "positionURL": "https://eagleiq.hmg.com", + "dataServiceName": "api", "positionServiceName": "pe", "clientID": "HMG", diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart index aef18f7..8215d57 100644 --- a/lib/core/utils/push_notification_handler.dart +++ b/lib/core/utils/push_notification_handler.dart @@ -95,7 +95,7 @@ _incomingCall(Map data) async { missedCallNotificationChannelName: "Missed Call", isShowCallID: false), ios: IOSParams( - iconName: 'Meena Health', + iconName: 'CallKitLogo', handleType: 'generic', supportsVideo: true, maximumCallGroups: 2, diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index 60925bc..671312d 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -408,6 +408,8 @@ class Utils { Widget? bodyWidget, Function? onConfirmTap, Function? onCancelTap, + String? cancelText, + String? confirmText, }) { return Column( mainAxisAlignment: MainAxisAlignment.center, @@ -425,7 +427,7 @@ class Utils { children: [ Expanded( child: CustomButton( - text: LocaleKeys.cancel.tr(), + text: cancelText ?? LocaleKeys.cancel.tr(), onPressed: () { if (onCancelTap != null) { onCancelTap(); @@ -434,14 +436,14 @@ class Utils { backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor, - icon: AppAssets.cancel, - iconColor: AppColors.whiteColor, + // icon: AppAssets.cancel, + // iconColor: AppColors.whiteColor, ), ), SizedBox(width: 8.h), Expanded( child: CustomButton( - text: LocaleKeys.confirm.tr(), + text: confirmText ?? LocaleKeys.confirm.tr(), onPressed: () async { if (onConfirmTap != null) { onConfirmTap(); @@ -450,7 +452,7 @@ class Utils { backgroundColor: AppColors.bgGreenColor, borderColor: AppColors.bgGreenColor, textColor: Colors.white, - icon: AppAssets.confirm, + // icon: AppAssets.confirm, ), ), ], @@ -988,6 +990,12 @@ class Utils { return isAllowed; } + static bool containsArabic(String text) { + // Using Unicode range for Arabic characters + final RegExp arabicRegex = RegExp(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]'); + return arabicRegex.hasMatch(text); + } + static String toEnglishNumbers(String input) { const english = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; const arabic = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩']; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index f087f74..792bff5 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -192,6 +192,7 @@ extension EmailValidator on String { int? maxlines, double? letterSpacing = 0, double? height, + String? fontFamily, TextOverflow? textOverflow, }) => Text( @@ -206,7 +207,7 @@ extension EmailValidator on String { height: height, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), decoration: isUnderLine ? TextDecoration.underline : null, - fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', + fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'), decorationColor: color ?? AppColors.blackColor), ); @@ -231,12 +232,13 @@ extension EmailValidator on String { TextAlign? textAlign, FontWeight? weight, TextOverflow? textOverflow, + String? fontFamily, double? letterSpacing = -0.4, Color decorationColor = AppColors.errorColor}) => Text( this, maxLines: maxlines, - textAlign: isCenter ? TextAlign.center : null, + textAlign: isCenter ? textAlign ?? TextAlign.center : null, // locale: Locale('en', 'US'), style: TextStyle( color: color ?? AppColors.blackColor, @@ -246,7 +248,7 @@ extension EmailValidator on String { overflow: textOverflow, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), decoration: isUnderLine ? TextDecoration.underline : null, - fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', + fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'), decorationColor: decorationColor), ); diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index 509b7cc..9a3fffc 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -847,7 +847,7 @@ class AuthenticationViewModel extends ChangeNotifier { } else { LoadingUtils.hideFullScreenLoader(); if (apiResponse.data["MessageStatus"] == 1) { - LoadingUtils.showFullScreenLoader(isSuccessDialog: true); + LoadingUtils.showFullScreenLoader(isSuccessDialog: true, loadingText: "Your medical file has been created successfully. \nPlease proceed to login."); //TODO: Here We Need to Show a Dialog Of Something in the case of Success. await clearDefaultInputValues(); // This will Clear All Default Values Of User. Future.delayed(Duration(seconds: 1), () { @@ -1064,7 +1064,10 @@ class AuthenticationViewModel extends ChangeNotifier { List projectDetailListModel = []; resultEither.fold( - (failure) async => await _errorHandlerService.handleError(failure: failure), + // (failure) async => await _errorHandlerService.handleError(failure: failure), + (failure) async { + print(failure.message); + }, (apiResponse) async { if (apiResponse.messageStatus == 2) { await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 9b53a13..c6c5faf 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -34,6 +34,7 @@ import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'models/resp_models/get_livecare_clinics_response_model.dart'; @@ -838,16 +839,11 @@ class BookAppointmentsViewModel extends ChangeNotifier { appointmentDate: apiResponse.data["SameClinicApptList"][0]['AppointmentDate'], ); - showCommonBottomSheet(navigationService.navigatorKey.currentContext!, - child: Utils.getLoadingWidget(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr()), - callBackFunc: (str) {}, - title: "", - height: ResponsiveExtension.screenHeight * 0.3, - isCloseButtonVisible: false, - isDismissible: false, - isFullScreen: false); + LoaderBottomSheet.showLoader( + loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), + ); await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { - navigationService.pop(); + LoaderBottomSheet.hideLoader(); Future.delayed(Duration(milliseconds: 50)).then((value) async {}); LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: LocaleKeys.bookingYourAppointment.tr()); await insertSpecificAppointment( diff --git a/lib/features/contact_us/contact_us_repo.dart b/lib/features/contact_us/contact_us_repo.dart index 5b9057b..c758155 100644 --- a/lib/features/contact_us/contact_us_repo.dart +++ b/lib/features/contact_us/contact_us_repo.dart @@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/req_models/request_insert_coc_item.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_patient_ic_projects.dart'; +import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; @@ -17,6 +18,8 @@ abstract class ContactUsRepo { Future>> getChatRequestID({required String name, required String mobileNo, required String workGroup}); Future>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment}); + + Future>>> getStatusForCOC(String identificationNo, String mobileNo, {Function(dynamic)? onSuccess, Function(String)? onError}); } class ContactUsRepoImp implements ContactUsRepo { @@ -181,4 +184,44 @@ class ContactUsRepoImp implements ContactUsRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>>> getStatusForCOC(String identificationNo, String mobileNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async { + Map body = {}; + body['IdentificationNo'] = identificationNo; + body['MobileNo'] = mobileNo; + body['Searching_type'] = 1; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + GET_STATUS_FOR_COCO, + body: body, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['ListCOCItems']; + final cocItemsList = list.map((item) => COCItem.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: cocItemsList, + ); + } catch (e) { + failure = DataParsingFailure(e.toString()); + } + }, + ); + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + return Left(UnknownFailure(e.toString())); + } + } } diff --git a/lib/features/contact_us/contact_us_view_model.dart b/lib/features/contact_us/contact_us_view_model.dart index 1029802..72bcff7 100644 --- a/lib/features/contact_us/contact_us_view_model.dart +++ b/lib/features/contact_us/contact_us_view_model.dart @@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/features/contact_us/models/feedback_type.dar import 'package:hmg_patient_app_new/features/contact_us/models/req_models/request_insert_coc_item.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_patient_ic_projects.dart'; +import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_status_coc_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; @@ -33,6 +34,9 @@ class ContactUsViewModel extends ChangeNotifier { List feedbackAttachmentList = []; + List cocItemsList = []; + bool isCOCItemsListLoading = false; + PatientAppointmentHistoryResponseModel? patientFeedbackSelectedAppointment; List feedbackTypeList = [ @@ -52,10 +56,12 @@ class ContactUsViewModel extends ChangeNotifier { isHMGLocationsListLoading = true; isHMGHospitalsListSelected = true; isLiveChatProjectsListLoading = true; + isCOCItemsListLoading = true; hmgHospitalsLocationsList.clear(); hmgPharmacyLocationsList.clear(); liveChatProjectsList.clear(); feedbackAttachmentList.clear(); + cocItemsList.clear(); selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'); setPatientFeedbackSelectedAppointment(null); getHMGLocations(); @@ -74,6 +80,9 @@ class ContactUsViewModel extends ChangeNotifier { setIsSendFeedbackTabSelected(bool isSelected) { isSendFeedbackTabSelected = isSelected; + if (!isSelected) { + getStatusForCOC(identificationNo: appState.getAuthenticatedUser()!.patientIdentificationNo!, mobileNo: "966${Utils.getPhoneNumberWithoutZero(appState.getAuthenticatedUser()!.mobileNumber!)}"); + } notifyListeners(); } @@ -223,4 +232,38 @@ class ContactUsViewModel extends ChangeNotifier { }, ); } + + Future getStatusForCOC({required String identificationNo, required String mobileNo, Function(dynamic)? onSuccess, Function(String)? onError}) async { + isCOCItemsListLoading = true; + cocItemsList.clear(); + notifyListeners(); + + final result = await contactUsRepo.getStatusForCOC(identificationNo, mobileNo); + + result.fold( + (failure) async { + await errorHandlerService.handleError(failure: failure); + if (onError != null) { + isCOCItemsListLoading = false; + onError(failure.toString()); + } + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + if (onError != null) { + isCOCItemsListLoading = false; + onError(apiResponse.errorMessage ?? 'Unknown error'); + } + } else if (apiResponse.messageStatus == 1) { + cocItemsList = apiResponse.data!; + cocItemsList.sort((a, b) => a.date!.compareTo(b.date!)); + isCOCItemsListLoading = false; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } } diff --git a/lib/features/contact_us/models/resp_models/get_status_coc_response_model.dart b/lib/features/contact_us/models/resp_models/get_status_coc_response_model.dart new file mode 100644 index 0000000..ed62d8b --- /dev/null +++ b/lib/features/contact_us/models/resp_models/get_status_coc_response_model.dart @@ -0,0 +1,124 @@ +class COCItem { + dynamic appointment; + String? appointmentClinicName; + String? appointmentDate; + String? appointmentProjectName; + String? cOCID; + String? cOCTitle; + String? channel; + dynamic clinic; + String? clinicID; + String? date; + dynamic detail; + dynamic doctor; + String? doctorID; + String? formType; + int? formTypeID; + dynamic identificationNo; + int? itemID; + dynamic mobileNo; + dynamic naturename; + dynamic patientID; + dynamic patientName; + dynamic project; + dynamic projectID; + String? solution; + String? status; + String? statusAr; + dynamic statusEn; + int? statusId; + + COCItem({ + this.appointment, + this.appointmentClinicName, + this.appointmentDate, + this.appointmentProjectName, + this.cOCID, + this.cOCTitle, + this.channel, + this.clinic, + this.clinicID, + this.date, + this.detail, + this.doctor, + this.doctorID, + this.formType, + this.formTypeID, + this.identificationNo, + this.itemID, + this.mobileNo, + this.naturename, + this.patientID, + this.patientName, + this.project, + this.projectID, + this.solution, + this.status, + this.statusAr, + this.statusEn, + this.statusId, + }); + + COCItem.fromJson(Map json) { + appointment = json['Appointment']; + appointmentClinicName = json['AppointmentClinicName']; + appointmentDate = json['AppointmentDate']; + appointmentProjectName = json['AppointmentProjectName']; + cOCID = json['COCID']; + cOCTitle = json['COCTitle']; + channel = json['Channel']; + clinic = json['Clinic']; + clinicID = json['ClinicID']; + date = json['Date']; + detail = json['Detail']; + doctor = json['Doctor']; + doctorID = json['DoctorID']; + formType = json['FormType']; + formTypeID = json['FormTypeID']; + identificationNo = json['IdentificationNo']; + itemID = json['ItemID']; + mobileNo = json['MobileNo']; + naturename = json['Naturename']; + patientID = json['PatientID']; + patientName = json['PatientName']; + project = json['Project']; + projectID = json['ProjectID']; + solution = json['Solution']; + status = json['Status']; + statusAr = json['StatusAr']; + statusEn = json['StatusEn']; + statusId = json['StatusId']; + } + + Map toJson() { + final Map data = new Map(); + data['Appointment'] = this.appointment; + data['AppointmentClinicName'] = this.appointmentClinicName; + data['AppointmentDate'] = this.appointmentDate; + data['AppointmentProjectName'] = this.appointmentProjectName; + data['COCID'] = this.cOCID; + data['COCTitle'] = this.cOCTitle; + data['Channel'] = this.channel; + data['Clinic'] = this.clinic; + data['ClinicID'] = this.clinicID; + data['Date'] = this.date; + data['Detail'] = this.detail; + data['Doctor'] = this.doctor; + data['DoctorID'] = this.doctorID; + data['FormType'] = this.formType; + data['FormTypeID'] = this.formTypeID; + data['IdentificationNo'] = this.identificationNo; + data['ItemID'] = this.itemID; + data['MobileNo'] = this.mobileNo; + data['Naturename'] = this.naturename; + data['PatientID'] = this.patientID; + data['PatientName'] = this.patientName; + data['Project'] = this.project; + data['ProjectID'] = this.projectID; + data['Solution'] = this.solution; + data['Status'] = this.status; + data['StatusAr'] = this.statusAr; + data['StatusEn'] = this.statusEn; + return data; + } +} diff --git a/lib/features/immediate_livecare/immediate_livecare_view_model.dart b/lib/features/immediate_livecare/immediate_livecare_view_model.dart index ffa0b00..90bf9a0 100644 --- a/lib/features/immediate_livecare/immediate_livecare_view_model.dart +++ b/lib/features/immediate_livecare/immediate_livecare_view_model.dart @@ -1,16 +1,26 @@ import 'dart:async'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; +import 'package:get_it/get_it.dart'; +import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/enums.dart'; +import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_repo.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import '../../services/navigation_service.dart'; @@ -42,6 +52,9 @@ class ImmediateLiveCareViewModel extends ChangeNotifier { late ValueNotifier durationNotifier; late Timer timer; + bool isShowNotEligibleDialog = false; + String notEligibleErrorMsg = ""; + initImmediateLiveCare() { _appState = getIt(); immediateLiveCareClinicsList = []; @@ -102,8 +115,80 @@ class ImmediateLiveCareViewModel extends ChangeNotifier { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { liveCareImmediateAppointmentFeesList = apiResponse.data!; + + if ((liveCareImmediateAppointmentFeesList.isCash!)) { + isShowNotEligibleDialog = false; + } else { + if (liveCareImmediateAppointmentFeesList.isInsured! && liveCareImmediateAppointmentFeesList.isEligible!) { + isShowNotEligibleDialog = false; + } else { + if (liveCareImmediateAppointmentFeesList.isInsured! && liveCareImmediateAppointmentFeesList.isEligible!) { + isShowNotEligibleDialog = true; + notEligibleErrorMsg = LocaleKeys.invalidEligibility.tr(context: GetIt.instance().navigatorKey.currentContext!); + } else { + isShowNotEligibleDialog = true; + notEligibleErrorMsg = LocaleKeys.invalidInsurance.tr(context: GetIt.instance().navigatorKey.currentContext!); + } + } + } + + if (isShowNotEligibleDialog) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight(GetIt.instance().navigatorKey.currentContext!, + child: Padding( + padding: EdgeInsets.only( + left: 24.w, + top: 24.h, + right: 24.w, + bottom: 12.h, + ), + child: Utils.getWarningWidget( + loadingText: notEligibleErrorMsg, + confirmText: LocaleKeys.updateInsuranceInfo.tr(context: GetIt.instance().navigatorKey.currentContext!), + cancelText: LocaleKeys.continueCash.tr(context: GetIt.instance().navigatorKey.currentContext!), + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + LoaderBottomSheet.showLoader(); + myAppointmentsViewModel.convertPatientToCash( + projectID: ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat ? 15 : 12, + onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingFeesPleaseWait.tr()); + getLiveCareImmediateAppointmentFees(); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: GetIt.instance().navigatorKey.currentContext!), + GetIt.instance().navigatorKey.currentContext!, + child: Utils.getErrorWidget(loadingText: err.toString()), + callBackFunc: () { + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + }, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + }, + onConfirmTap: () async { + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + Navigator.push( + GetIt.instance().navigatorKey.currentContext!, + CustomPageRoute( + page: InsuranceHomePage(), + ), + ); + }), + ), callBackFunc: () { + // Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + }, isFullScreen: false, isCloseButtonVisible: false, isDismissible: false); + } + notifyListeners(); - if (onSuccess != null) { + if (onSuccess != null && !isShowNotEligibleDialog) { onSuccess(apiResponse); } } diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart index 261bda2..fa1ec5d 100644 --- a/lib/features/insurance/insurance_view_model.dart +++ b/lib/features/insurance/insurance_view_model.dart @@ -18,6 +18,7 @@ class InsuranceViewModel extends ChangeNotifier { bool isInsuranceApprovalsLoading = false; bool isInsuranceExpired = false; + bool isInsuranceActive = false; InsuranceRepo insuranceRepo; ErrorHandlerService errorHandlerService; @@ -79,6 +80,8 @@ class InsuranceViewModel extends ChangeNotifier { (failure) async { isInsuranceLoading = false; isInsuranceDataToBeLoaded = false; + isInsuranceExpired = false; + isInsuranceActive = false; notifyListeners(); }, (apiResponse) { @@ -94,6 +97,9 @@ class InsuranceViewModel extends ChangeNotifier { DateUtil.convertStringToDate(patientInsuranceList.first.cardValidTo), ); + isInsuranceActive = patientInsuranceList.first.isActive ?? false; + // isInsuranceActive = true; + notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart index 22e4859..efb1c06 100644 --- a/lib/features/lab/lab_view_model.dart +++ b/lib/features/lab/lab_view_model.dart @@ -17,7 +17,7 @@ import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_ import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_results/lab_result_details.dart'; -import 'package:hmg_patient_app_new/presentation/labAiAnalysis/lab_ai_analysis_detailed_page.dart'; +import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index ce9e877..0c76c9f 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -73,6 +73,8 @@ abstract class MyAppointmentsRepo { Future>> sendDoctorRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note, String appoDate, String docName, String projectName, String clinicName); Future>>> getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID}); + + Future>> convertPatientToCash({required int projectID}); } class MyAppointmentsRepoImp implements MyAppointmentsRepo { @@ -957,4 +959,36 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { } } + @override + Future> convertPatientToCash({required int projectID}) async { + Map request; + + request = {"ProjectID": projectID}; + + try { + GenericApiModel? apiResponse; + Failure? failure; + await apiClient.post(CONVERT_PATIENT_TO_CASH, onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = (response['MessageStatus'] == 1); + + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: list, + ); + } catch (e) { + failure = DataParsingFailure(e.toString()); + } + }, body: request); + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e) { + return Left(UnknownFailure(e.toString())); + } + } } \ No newline at end of file diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index ce2b7b9..35bf29b 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -1,6 +1,9 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; +import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/appointemnet_filters.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ask_doctor_request_type_response_model.dart'; @@ -10,7 +13,13 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart'; import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; class MyAppointmentsViewModel extends ChangeNotifier { int selectedTabIndex = 0; @@ -73,6 +82,9 @@ class MyAppointmentsViewModel extends ChangeNotifier { GetTamaraInstallmentsDetailsResponseModel? getTamaraInstallmentsDetailsResponseModel; bool isTamaraDetailsLoading = false; + bool isShowNotEligibleDialog = false; + String notEligibleErrorMsg = ""; + MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService, required this.appState}); void onTabChange(int index) { @@ -141,6 +153,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { isTamaraDetailsLoading = true; isAppointmentPatientShareLoading = true; isEyeMeasurementsAppointmentsLoading = true; + isShowNotEligibleDialog = false; notifyListeners(); } @@ -349,7 +362,99 @@ class MyAppointmentsViewModel extends ChangeNotifier { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { patientAppointmentShareResponseModel = apiResponse.data!; + + if ((patientAppointmentShareResponseModel!.isCash!)) { + isShowNotEligibleDialog = false; + } else { + if (patientAppointmentShareResponseModel!.isInsured! && patientAppointmentShareResponseModel!.isEligible!) { + isShowNotEligibleDialog = false; + } else { + if (patientAppointmentShareResponseModel!.isInsured! && patientAppointmentShareResponseModel!.isEligible!) { + isShowNotEligibleDialog = true; + notEligibleErrorMsg = LocaleKeys.invalidEligibility.tr(context: GetIt.instance().navigatorKey.currentContext!); + } else { + isShowNotEligibleDialog = true; + notEligibleErrorMsg = LocaleKeys.invalidInsurance.tr(context: GetIt.instance().navigatorKey.currentContext!); + } + } + } isAppointmentPatientShareLoading = false; + + if (isShowNotEligibleDialog) { + showCommonBottomSheetWithoutHeight(GetIt.instance().navigatorKey.currentContext!, + child: Padding( + padding: EdgeInsets.only( + left: 24.w, + top: 24.h, + right: 24.w, + bottom: 12.h, + ), + child: Utils.getWarningWidget( + loadingText: notEligibleErrorMsg, + confirmText: LocaleKeys.updateInsuranceInfo.tr(context: GetIt.instance().navigatorKey.currentContext!), + cancelText: LocaleKeys.continueCash.tr(context: GetIt.instance().navigatorKey.currentContext!), + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + LoaderBottomSheet.showLoader(); + convertPatientToCash( + projectID: projectID, + onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + setIsPatientAppointmentShareLoading(true); + getPatientShareAppointment(projectID, clinicID, appointmentNo, isLiveCareAppointment); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: GetIt.instance().navigatorKey.currentContext!), + GetIt.instance().navigatorKey.currentContext!, + child: Utils.getErrorWidget(loadingText: err.toString()), + callBackFunc: () { + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + }, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + }, + onConfirmTap: () async { + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + Navigator.push( + GetIt.instance().navigatorKey.currentContext!, + CustomPageRoute( + page: InsuranceHomePage(), + ), + ); + }), + ), callBackFunc: () { + // Navigator.pop(GetIt.instance().navigatorKey.currentContext!); + }, isFullScreen: false, isCloseButtonVisible: false, isDismissible: false); + } + + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + + Future convertPatientToCash({required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await myAppointmentsRepo.convertPatientToCash(projectID: projectID); + + result.fold( + // (failure) async => await errorHandlerService.handleError(failure: failure), + (failure) async { + onError!(failure.message); + }, + (apiResponse) { + if (apiResponse.messageStatus == 2) { + // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + } else if (apiResponse.messageStatus == 1) { notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); @@ -413,7 +518,12 @@ class MyAppointmentsViewModel extends ChangeNotifier { final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel); result.fold( - (failure) async => await errorHandlerService.handleError(failure: failure), + // (failure) async => await errorHandlerService.handleError(failure: failure), + (failure) async { + if(onError != null) { + onError(failure.message); + } + }, (apiResponse) { if (apiResponse.messageStatus == 2) { onError!(apiResponse.errorMessage!); diff --git a/lib/features/prescriptions/prescriptions_repo.dart b/lib/features/prescriptions/prescriptions_repo.dart index dcc9de9..3bfcc7f 100644 --- a/lib/features/prescriptions/prescriptions_repo.dart +++ b/lib/features/prescriptions/prescriptions_repo.dart @@ -188,7 +188,7 @@ class PrescriptionsRepoImp implements PrescriptionsRepo { Map mapDevice = { "AppointmentNo": prescriptionsResponseModel.appointmentNo, "SetupID": prescriptionsResponseModel.setupID, - "EpisodeID": prescriptionsResponseModel.episodeID, + "EpisodeNo": prescriptionsResponseModel.episodeID, "ClinicID": prescriptionsResponseModel.clinicID, "ProjectID": prescriptionsResponseModel.projectID, "DischargeNo": prescriptionsResponseModel.dischargeNo, diff --git a/lib/features/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart index 319e5fc..c0f9c7b 100644 --- a/lib/features/prescriptions/prescriptions_view_model.dart +++ b/lib/features/prescriptions/prescriptions_view_model.dart @@ -153,7 +153,10 @@ class PrescriptionsViewModel extends ChangeNotifier { final result = await prescriptionsRepo.getPatientPrescriptionDetails(prescriptionsResponseModel: prescriptionsResponseModel); result.fold( - (failure) async => await errorHandlerService.handleError(failure: failure), + // (failure) async => await errorHandlerService.handleError(failure: failure), + (failure) async { + onError!(failure.message); + }, (apiResponse) { if (apiResponse.messageStatus == 2) { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); diff --git a/lib/features/radiology/radiology_repo.dart b/lib/features/radiology/radiology_repo.dart index 2af3e0f..5847718 100644 --- a/lib/features/radiology/radiology_repo.dart +++ b/lib/features/radiology/radiology_repo.dart @@ -121,7 +121,7 @@ class RadiologyRepoImp implements RadiologyRepo { Map mapDevice = { "InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? 0 : patientRadiologyResponseModel.invoiceNo, "InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : 0, - "LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo, + // "LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo, "InvoiceLineItemNo": patientRadiologyResponseModel.invoiceLineItemNo, "ProjectID": patientRadiologyResponseModel.projectID!, "InvoiceType": patientRadiologyResponseModel.invoiceType!, diff --git a/lib/features/symptoms_checker/models/resp_models/get_clinic_details_response_model.dart b/lib/features/symptoms_checker/models/resp_models/get_clinic_details_response_model.dart new file mode 100644 index 0000000..2d878c1 --- /dev/null +++ b/lib/features/symptoms_checker/models/resp_models/get_clinic_details_response_model.dart @@ -0,0 +1,25 @@ +class GetClinicDetailsResponseModel { + String? category; + int? clinicID; + bool? isActive; + String? categoryAR; + + GetClinicDetailsResponseModel( + {this.category, this.clinicID, this.isActive, this.categoryAR}); + + GetClinicDetailsResponseModel.fromJson(Map json) { + category = json['Category']; + clinicID = json['ClinicID']; + isActive = json['IsActive']; + categoryAR = json['CategoryAR']; + } + + Map toJson() { + final Map data = new Map(); + data['Category'] = this.category; + data['ClinicID'] = this.clinicID; + data['IsActive'] = this.isActive; + data['CategoryAR'] = this.categoryAR; + return data; + } +} diff --git a/lib/features/symptoms_checker/symptoms_checker_repo.dart b/lib/features/symptoms_checker/symptoms_checker_repo.dart index c0214e1..33bcbd8 100644 --- a/lib/features/symptoms_checker/symptoms_checker_repo.dart +++ b/lib/features/symptoms_checker/symptoms_checker_repo.dart @@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/body_symptom_response_model.dart'; +import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/get_clinic_details_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/risk_and_suggestions_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/symptoms_user_details_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_response_model.dart'; @@ -50,6 +51,11 @@ abstract class SymptomsCheckerRepo { required String userSessionToken, required String sessionId, }); + + Future>>> getClinicDetails({ + required String categoryName, + required String userSessionToken, + }); } class SymptomsCheckerRepoImp implements SymptomsCheckerRepo { @@ -390,4 +396,57 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo { return Left(UnknownFailure(e.toString())); } } + + @override + Future>>> getClinicDetails({ + required String categoryName, + required String userSessionToken, + }) async { + Map headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $userSessionToken', + }; + Map body = {}; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + + await apiClient.get( + "${ApiConsts.getClinicFromCondition}$categoryName", + apiHeaders: headers, + isExternal: true, + isAllowAny: true, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType ?? ServerFailure(error); + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + final clinicDetails; + try { + final list = response['dataDetails']; + clinicDetails = list.map((item) => GetClinicDetailsResponseModel.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus ?? 1, + statusCode: statusCode, + errorMessage: errorMessage, + data: clinicDetails, + ); + } catch (e, stackTrace) { + loggerService.logError("Error parsing GetClinicsByCondition response: $e"); + loggerService.logError("StackTrace: $stackTrace"); + failure = DataParsingFailure(e.toString()); + } + }, + ); + + if (failure != null) return Left(failure!); + if (apiResponse == null) return Left(ServerFailure("Unknown error")); + return Right(apiResponse!); + } catch (e, stackTrace) { + loggerService.logError("Exception in GetClinicsByCondition: $e"); + loggerService.logError("StackTrace: $stackTrace"); + return Left(UnknownFailure(e.toString())); + } + } } diff --git a/lib/features/symptoms_checker/symptoms_checker_view_model.dart b/lib/features/symptoms_checker/symptoms_checker_view_model.dart index 6670670..215b692 100644 --- a/lib/features/symptoms_checker/symptoms_checker_view_model.dart +++ b/lib/features/symptoms_checker/symptoms_checker_view_model.dart @@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/data/organ_mapping_data.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/organ_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/body_symptom_response_model.dart'; +import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/get_clinic_details_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/risk_and_suggestions_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/symptoms_user_details_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_response_model.dart'; @@ -154,6 +155,8 @@ class SymptomsCheckerViewModel extends ChangeNotifier { /// Get the number of triage questions answered int get triageQuestionCount => _triageQuestionCount; + List clinicDetailsList = []; + /// Get choice index for a specific item int? getTriageChoiceForItem(String itemId) { return _selectedTriageChoicesByItemId[itemId]; @@ -1066,6 +1069,43 @@ class SymptomsCheckerViewModel extends ChangeNotifier { ); } + Future getClinicConditionsFromCategory({ + required String categoryName, + Function(dynamic)? onSuccess, + Function(String)? onError, + }) async { + clinicDetailsList.clear(); + notifyListeners(); + + final result = await symptomsCheckerRepo.getClinicDetails( + categoryName: categoryName, + userSessionToken: currentSessionAuthToken, + ); + + result.fold( + (failure) async { + await errorHandlerService.handleError(failure: failure); + if (onError != null) { + onError(failure.toString()); + } + }, + (apiResponse) { + if (apiResponse.messageStatus == 1 && apiResponse.data != null) { + clinicDetailsList = apiResponse.data!; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse.data!); + } + } else { + notifyListeners(); + if (onError != null) { + onError(apiResponse.errorMessage ?? 'Failed to fetch clinic details'); + } + } + }, + ); + } + @override void dispose() { _tooltipTimer?.cancel(); diff --git a/lib/features/todo_section/todo_section_repo.dart b/lib/features/todo_section/todo_section_repo.dart index 76a4438..6d58d80 100644 --- a/lib/features/todo_section/todo_section_repo.dart +++ b/lib/features/todo_section/todo_section_repo.dart @@ -96,6 +96,8 @@ class TodoSectionRepoImp implements TodoSectionRepo { } } + ancillaryOrders.sort((a, b) => b.orderDate!.compareTo(a.orderDate!)); + apiResponse = GenericApiModel>( messageStatus: messageStatus, statusCode: statusCode, diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart index d1c53a0..9658edb 100644 --- a/lib/firebase_options.dart +++ b/lib/firebase_options.dart @@ -45,21 +45,19 @@ class DefaultFirebaseOptions { appId: '1:815750722565:android:62281cd3e5df4063', messagingSenderId: '815750722565', projectId: 'api-project-815750722565', - // databaseURL: - // 'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app', - storageBucket: 'api-project-815750722565.appspot.com', + databaseURL: 'https://api-project-815750722565.firebaseio.com', + storageBucket: 'api-project-815750722565.firebasestorage.app', ); static const FirebaseOptions ios = FirebaseOptions( apiKey: 'AIzaSyDiXnCO00li4V7Ioa2YZ_M4ECxRsu_P9tA', - appId: '1:815750722565:ios:328ec247a81a2ca23c186c', + appId: '1:815750722565:ios:34ec03c09e02e21f3c186c', messagingSenderId: '815750722565', projectId: 'api-project-815750722565', - storageBucket: 'api-project-815750722565.appspot.com', - androidClientId: - '815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com', - iosClientId: - '815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com', - iosBundleId: 'com.HMG.HMG-Smartphone', + databaseURL: 'https://api-project-815750722565.firebaseio.com', + storageBucket: 'api-project-815750722565.firebasestorage.app', + androidClientId: '815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com', + iosBundleId: 'com.cloudsolutions.HMGPatientApp', ); -} + +} \ No newline at end of file diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 7bafadf..3940f9e 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -941,6 +941,7 @@ abstract class LocaleKeys { static const offline = 'offline'; static const videoCall = 'videoCall'; static const liveVideoCallWithHMGDoctors = 'liveVideoCallWithHMGDoctors'; + static const liveAudioCallWithHMGDoctors = 'liveAudioCallWithHMGDoctors'; static const audioCall = 'audioCall'; static const phoneCall = 'phoneCall'; static const livePhoneCallWithHMGDoctors = 'livePhoneCallWithHMGDoctors'; @@ -1563,5 +1564,14 @@ abstract class LocaleKeys { static const noThanksIKnowTheClinic = 'noThanksIKnowTheClinic'; static const unableToSendOTP = 'unableToSendOTP'; static const loadingAIAnalysis = 'loadingAIAnalysis'; + static const symptoms = 'symptoms'; + static const insuranceInActive = 'insuranceInActive'; + static const insuranceInActiveContactSupport = 'insuranceInActiveContactSupport'; + static const updateAppNow = 'updateAppNow'; + static const Dr = 'Dr'; + static const reschedulingAppo = 'reschedulingAppo'; + static const invalidEligibility = 'invalidEligibility'; + static const invalidInsurance = 'invalidInsurance'; + static const continueCash = 'continueCash'; } diff --git a/lib/main.dart b/lib/main.dart index e034cf9..cff0d04 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -76,12 +77,33 @@ Future callAppStateInitializations() async { : "3"); AppState appState = getIt.get(); appState.setDeviceTypeID = deviceTypeId; + + // Pass all uncaught "fatal" errors from the framework to Crashlytics + FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError; + + // Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics + PlatformDispatcher.instance.onError = (error, stack) { + if (!kDebugMode) FirebaseCrashlytics.instance.recordError(error, stack, fatal: true); + return true; + }; } Future callInitializations() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); - await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + + // await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + + try { + // Attempt to get the default app. If it exists, this avoids the error. + await Firebase.app(); + } catch (e) { + // If it doesn't exist, initialize it. + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + } + await AppDependencies.addDependencies(); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); HttpOverrides.global = MyHttpOverrides(); @@ -226,9 +248,16 @@ class MyApp extends StatelessWidget { builder: (context, orientation, deviceType) { // SizeConfig().init(constraints, orientation); return MaterialApp( - title: 'Dr. AlHabib', + // title: 'Dr. AlHabib', + title: 'Dr. AlHabib Beta', builder: (context, mchild) { - return MediaQuery(data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling, alwaysUse24HourFormat: true,), child: mchild!, ); + return MediaQuery( + data: MediaQuery.of(context).copyWith( + textScaler: TextScaler.noScaling, + alwaysUse24HourFormat: true, + ), + child: mchild!, + ); }, showSemanticsDebugger: false, debugShowCheckedModeBanner: false, diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 0e0194b..e5961e3 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -99,6 +99,7 @@ class _AppointmentDetailsPageState extends State { ? () { contactUsViewModel.setSelectedFeedbackType(FeedbackType(id: 1, nameEN: "Complaint for appointment", nameAR: 'شكوى على موعد')); contactUsViewModel.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel); + contactUsViewModel.setIsSendFeedbackTabSelected(true); Navigator.of(context).push( CustomPageRoute( page: FeedbackPage(), @@ -111,9 +112,9 @@ class _AppointmentDetailsPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ AppointmentDoctorCard( - renderWidgetForERDisplay: ((widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) || - (widget.patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || - !Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID)), + // renderWidgetForERDisplay: ((widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) || + renderWidgetForERDisplay: + ((widget.patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || !Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID)), patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, onAskDoctorTap: () async { LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context)); @@ -144,8 +145,6 @@ class _AppointmentDetailsPageState extends State { }); }, onCancelTap: () async { - myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); - LoaderBottomSheet.showLoader(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr(context: context)); await myAppointmentsViewModel.cancelAppointment( patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, @@ -164,6 +163,18 @@ class _AppointmentDetailsPageState extends State { isDismissible: false, isFullScreen: false, ); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err.toString()), + callBackFunc: () {}, + title: "", + isCloseButtonVisible: true, + isDismissible: false, + isFullScreen: false, + ); }); var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", ); setState(() { @@ -532,7 +543,7 @@ class _AppointmentDetailsPageState extends State { LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( context, - child: Utils.getErrorWidget(loadingText: err), + child: Utils.getErrorWidget(loadingText: LocaleKeys.noPrescriptionsForAppointment.tr(context: context)), callBackFunc: () {}, isFullScreen: false, isCloseButtonVisible: true, diff --git a/lib/presentation/appointments/my_doctors_page.dart b/lib/presentation/appointments/my_doctors_page.dart index 3795ce1..fc7798f 100644 --- a/lib/presentation/appointments/my_doctors_page.dart +++ b/lib/presentation/appointments/my_doctors_page.dart @@ -290,6 +290,12 @@ class _MyDoctorsPageState extends State { clinicID: doctor?.clinicID ?? 0, projectID: doctor?.projectID ?? 0, doctorID: doctor?.doctorID ?? 0, + clinicName: doctor?.clinicName, + projectName: doctor?.projectName, + // nationalityFlagURL: doctor?.nationalityFlagURL, + name: doctor?.doctorName, + doctorImageURL: doctor?.doctorImageURL ?? doctor?.doctorImage, + speciality: doctor?.doctorSpeciality )); LoaderBottomSheet.showLoader(); await bookAppointmentsViewModel.getDoctorProfile(onSuccess: (dynamic respData) { diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index f07b9a4..95fc09b 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -155,7 +155,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { myAppointmentsViewModel.getPatientAppointments(true, false); LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () async { - await myAppointmentsViewModel.getPatientAppointmentQueueDetails(); + // await myAppointmentsViewModel.getPatientAppointmentQueueDetails(); Navigator.of(context).pop(); Navigator.pushAndRemoveUntil( context, @@ -163,11 +163,11 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { page: LandingNavigation(), ), (r) => false); - Navigator.of(context).push( - CustomPageRoute( - page: AppointmentQueuePage(), - ), - ); + // Navigator.of(context).push( + // CustomPageRoute( + // page: AppointmentQueuePage(), + // ), + // ); }, isFullScreen: false); }, onError: (error) { diff --git a/lib/presentation/appointments/widgets/appointment_doctor_card.dart b/lib/presentation/appointments/widgets/appointment_doctor_card.dart index 7e43069..9e56053 100644 --- a/lib/presentation/appointments/widgets/appointment_doctor_card.dart +++ b/lib/presentation/appointments/widgets/appointment_doctor_card.dart @@ -183,7 +183,7 @@ class AppointmentDoctorCard extends StatelessWidget { ) : SizedBox.shrink(); } else { - return patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false + return patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? CustomButton( text: LocaleKeys.cancel.tr(), onPressed: () { diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index fa23979..03de833 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -400,30 +400,30 @@ class _BookAppointmentPageState extends State { ), ); }), - SizedBox(height: 16.h), - Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h), - SizedBox(height: 16.h), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h), - SizedBox(width: 12.h), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.pharmaLiveCare.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500), - "".toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), - ], - ), - ], - ), - Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), - ], - ).onPress(() { - openRegionListBottomSheet(context, RegionBottomSheetType.FOR_REGION); - }), + // SizedBox(height: 16.h), + // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h), + // SizedBox(height: 16.h), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Row( + // children: [ + // Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h), + // SizedBox(width: 12.h), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // LocaleKeys.pharmaLiveCare.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500), + // "".toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), + // ], + // ), + // ], + // ), + // Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)), + // ], + // ).onPress(() { + // openRegionListBottomSheet(context, RegionBottomSheetType.FOR_REGION); + // }), ], ), ), diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart index 4992d85..fb6ebe7 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart @@ -110,7 +110,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { children: [ Row( children: [ - Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 32.h, height: 32.h, fit: BoxFit.contain), + Utils.buildSvgWithAssets(icon: getLiveCareTypeIcon(immediateLiveCareVM.liveCareSelectedCallType), width: 32.h, height: 32.h, fit: BoxFit.contain), SizedBox(width: 8.h), getLiveCareType(context, immediateLiveCareVM.liveCareSelectedCallType).toText16(isBold: true), ], @@ -429,6 +429,19 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { // // } // } + String getLiveCareTypeIcon(int callType) { + switch (callType) { + case 1: + return AppAssets.livecare_video; + case 2: + return AppAssets.livecare_audio; + case 3: + return AppAssets.livecare_phone; + default: + return AppAssets.livecare_video; + } + } + String getLiveCareType(BuildContext context, int callType) { switch (callType) { case 1: diff --git a/lib/presentation/book_appointment/livecare/widgets/select_livecare_call_type.dart b/lib/presentation/book_appointment/livecare/widgets/select_livecare_call_type.dart index a1c3f43..e0f6c5c 100644 --- a/lib/presentation/book_appointment/livecare/widgets/select_livecare_call_type.dart +++ b/lib/presentation/book_appointment/livecare/widgets/select_livecare_call_type.dart @@ -22,7 +22,7 @@ class SelectLiveCareCallType extends StatelessWidget { return Column( children: [ checkInOptionCard( - AppAssets.checkin_location_icon, + AppAssets.livecare_video, LocaleKeys.videoCall.tr(context: context), LocaleKeys.liveVideoCallWithHMGDoctors.tr(context: context), ).onPress(() { @@ -31,16 +31,16 @@ class SelectLiveCareCallType extends StatelessWidget { }), SizedBox(height: 16.h), checkInOptionCard( - AppAssets.checkin_location_icon, + AppAssets.livecare_audio, LocaleKeys.audioCall.tr(context: context), - LocaleKeys.liveVideoCallWithHMGDoctors.tr(context: context), + LocaleKeys.liveAudioCallWithHMGDoctors.tr(context: context), ).onPress(() { Navigator.of(context).pop(); immediateLiveCareViewModel.setLiveCareSelectedCallType(2); }), SizedBox(height: 16.h), checkInOptionCard( - AppAssets.checkin_location_icon, + AppAssets.livecare_phone, LocaleKeys.phoneCall.tr(context: context), LocaleKeys.livePhoneCallWithHMGDoctors.tr(context: context), ).onPress(() { diff --git a/lib/presentation/book_appointment/review_appointment_page.dart b/lib/presentation/book_appointment/review_appointment_page.dart index 5b8ba53..035eb22 100644 --- a/lib/presentation/book_appointment/review_appointment_page.dart +++ b/lib/presentation/book_appointment/review_appointment_page.dart @@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart'; @@ -73,7 +74,7 @@ class _ReviewAppointmentPageState extends State { Row( children: [ Image.network( - bookAppointmentsViewModel.selectedDoctor.doctorImageURL!, + bookAppointmentsViewModel.selectedDoctor.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png", width: 50.h, height: 50.h, fit: BoxFit.cover, @@ -83,15 +84,14 @@ class _ReviewAppointmentPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - SizedBox( - width: MediaQuery.of(context).size.width * 0.49, - child: "${bookAppointmentsViewModel.selectedDoctor.doctorTitle} ${bookAppointmentsViewModel.selectedDoctor.name}" - .toString() - .toText16(isBold: true, maxlines: 1), - ), + "${bookAppointmentsViewModel.selectedDoctor.doctorTitle ?? LocaleKeys.Dr.tr(context: context)} ${bookAppointmentsViewModel.selectedDoctor.name}" + .toString() + .toText16(isBold: true, maxlines: 1), + SizedBox(width: 12.w), Image.network( - bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL!, + bookAppointmentsViewModel.selectedDoctor.nationalityFlagURL ?? "https://hmgwebservices.com/Images/flag/SAU.png", width: 20.h, height: 15.h, fit: BoxFit.cover, @@ -242,11 +242,16 @@ class _ReviewAppointmentPageState extends State { LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingAppointmentShare.tr(context: context)); await bookAppointmentsViewModel.getWalkInPatientShareAppointment(onSuccess: (val) { LoaderBottomSheet.hideLoader(); - Navigator.of(context).push( - CustomPageRoute( - page: WaitingAppointmentPaymentPage(), - ), - ); + if (bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax != 0 || + bookAppointmentsViewModel.patientWalkInAppointmentShareResponseModel!.patientShareWithTax != 0.0) { + Navigator.of(context).push( + CustomPageRoute( + page: WaitingAppointmentPaymentPage(), + ), + ); + } else { + initiateBookAppointmentForWalkInNoPatientShare(); + } }, onError: (err) { LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( @@ -259,6 +264,49 @@ class _ReviewAppointmentPageState extends State { }); } + void initiateBookAppointmentForWalkInNoPatientShare() async { + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.bookingWaitingAppointment.tr(context: context)); + await bookAppointmentsViewModel.insertSpecificAppointmentForWalkIn(onSuccess: (val) async { + String appointmentNo = val.data['AppointmentNo'].toString(); + LoaderBottomSheet.hideLoader(); + sendCheckInRequest(bookAppointmentsViewModel.waitingAppointmentNFCCode, appointmentNo, context); + }); + } + + void sendCheckInRequest(String scannedCode, String appointmentNo, BuildContext context) async { + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.processingCheckIn.tr(context: context)); + PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel = PatientAppointmentHistoryResponseModel( + appointmentNo: appointmentNo, + clinicID: bookAppointmentsViewModel.selectedDoctor.clinicID, + projectID: bookAppointmentsViewModel.selectedDoctor.projectID, + ); + await myAppointmentsViewModel.sendCheckInNfcRequest( + patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, + scannedCode: scannedCode, + checkInType: 2, + onSuccess: (apiResponse) { + LoaderBottomSheet.hideLoader(); + myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); + myAppointmentsViewModel.getPatientAppointments(true, false); + showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: apiResponse.data["SuccessMsg"]), callBackFunc: () { + Navigator.of(context).pop(); + Navigator.pushAndRemoveUntil( + context, + CustomPageRoute( + page: LandingNavigation(), + ), + (r) => false); + }, isFullScreen: false); + }, + onError: (error) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.error.tr(context: context), child: Utils.getErrorWidget(loadingText: error), callBackFunc: () { + Navigator.of(context).pop(); + }, isFullScreen: false); + }, + ); + } + void initiateBookAppointment() async { LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: LocaleKeys.bookingYourAppointment.tr(context: context)); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); diff --git a/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart b/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart index ca60e9e..bb347e5 100644 --- a/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart +++ b/lib/presentation/book_appointment/waiting_appointment/waiting_appointment_payment_page.dart @@ -640,6 +640,8 @@ class _WaitingAppointmentPaymentPageState extends State(context, listen: false); medicalFileViewModel = Provider.of(context, listen: false); + appState = getIt.get(); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: Consumer(builder: (context, contactUsVM, child) { @@ -67,11 +73,12 @@ class FeedbackPage extends StatelessWidget { ), ), ), - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - customBorder: BorderRadius.only( - topLeft: Radius.circular(24.h), + contactUsViewModel.isSendFeedbackTabSelected + ? Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + customBorder: BorderRadius.only( + topLeft: Radius.circular(24.h), topRight: Radius.circular(24.h), ), hasShadow: true, @@ -126,7 +133,8 @@ class FeedbackPage extends StatelessWidget { iconColor: AppColors.whiteColor, iconSize: 20.h, ).paddingSymmetrical(24.h, 24.h), - ), + ) + : SizedBox.shrink(), ], ); }), @@ -389,7 +397,99 @@ class FeedbackPage extends StatelessWidget { ], ); } else { - return Container(); + return getIt.get().isAuthenticated + ? Column( + children: [ + SizedBox(height: 24.h), + ListView.builder( + itemCount: contactUsViewModel.isCOCItemsListLoading + ? 4 + : contactUsViewModel.cocItemsList.isEmpty + ? 1 + : contactUsViewModel.cocItemsList.length, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsetsGeometry.zero, + itemBuilder: (context, index) { + return contactUsViewModel.isCOCItemsListLoading + ? LabResultItemView( + onTap: () {}, + labOrder: null, + index: index, + isLoading: true, + ) + : contactUsViewModel.cocItemsList.isNotEmpty + ? AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 500), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + child: Container( + padding: EdgeInsets.all(16.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: true, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppCustomChipWidget( + labelText: appState.isArabic() ? contactUsViewModel.cocItemsList[index].statusAr : contactUsViewModel.cocItemsList[index].status, + // backgroundColor: AppColors.warningColorYellow, + backgroundColor: (contactUsViewModel.cocItemsList[index].statusId == 7 || contactUsViewModel.cocItemsList[index].statusId == 8) + ? AppColors.primaryRedColor + : (contactUsViewModel.cocItemsList[index].statusId == 10 || + contactUsViewModel.cocItemsList[index].statusId == 6 || + contactUsViewModel.cocItemsList[index].statusId == 9) + ? AppColors.successColor + : AppColors.warningColorYellow, + textColor: AppColors.whiteColor, + ), + SizedBox(height: 8.h), + "${LocaleKeys.requestID.tr(context: context)} ${contactUsViewModel.cocItemsList[index].itemID}".toText16(weight: FontWeight.bold), + SizedBox(height: 8.h), + Wrap( + direction: Axis.horizontal, + spacing: 4.h, + runSpacing: 4.h, + children: [ + AppCustomChipWidget( + labelText: contactUsViewModel.cocItemsList[index].date!.split(" ")[0], + icon: AppAssets.calendarGrey, + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), + ), + AppCustomChipWidget( + labelText: contactUsViewModel.cocItemsList[index].formType, + icon: AppAssets.ask_doctor_icon, + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), + ), + ], + ), + SizedBox(height: 8.h), + "${contactUsViewModel.cocItemsList[index].cOCTitle}" + .toText16(weight: FontWeight.bold, fontFamily: Utils.isArabicText(contactUsViewModel.cocItemsList[index].cOCTitle ?? "") ? "GESSTwo" : "Poppins"), + SizedBox(height: 8.h), + "${contactUsViewModel.cocItemsList[index].detail}".toText14( + weight: FontWeight.w500, + color: AppColors.textColorLight, + fontFamily: Utils.isArabicText(contactUsViewModel.cocItemsList[index].detail ?? "") ? "GESSTwo" : "Poppins"), + ], + ), + ).paddingOnly(bottom: 16.h), + ), + ), + ), + ) + : Utils.getNoDataWidget(context); + }), + ], + ) + : Utils.getNoDataWidget(context); } } } diff --git a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart index 999a43e..bbaa5f5 100644 --- a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart +++ b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart @@ -105,7 +105,9 @@ class ErOnlineCheckinHome extends StatelessWidget { ); }); }, - onError: (err) {}); + onError: (err) { + LoaderBottomSheet.hideLoader(); + }); }); }, onCancel: () {}); }); diff --git a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart index 3510197..2645679 100644 --- a/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart +++ b/lib/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_page.dart @@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/features/emergency_services/emergency_servic import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart'; import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; @@ -445,7 +446,14 @@ class _ErOnlineCheckinPaymentPageState extends State showCommonBottomSheetWithoutHeight( context, child: Utils.getSuccessWidget(loadingText: LocaleKeys.erAppointmentBookedSuccess.tr(context: context)), - callBackFunc: () {}, + callBackFunc: () { + Navigator.pushAndRemoveUntil( + context, + CustomPageRoute( + page: LandingNavigation(), + ), + (r) => false); + }, isFullScreen: false, isCloseButtonVisible: true, ); @@ -458,7 +466,14 @@ class _ErOnlineCheckinPaymentPageState extends State showCommonBottomSheetWithoutHeight( context, child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)), - callBackFunc: () {}, + callBackFunc: () { + Navigator.pushAndRemoveUntil( + context, + CustomPageRoute( + page: LandingNavigation(), + ), + (r) => false); + }, isFullScreen: false, isCloseButtonVisible: true, ); diff --git a/lib/presentation/hmg_services/services_page.dart b/lib/presentation/hmg_services/services_page.dart index 9aaf159..f0bf08f 100644 --- a/lib/presentation/hmg_services/services_page.dart +++ b/lib/presentation/hmg_services/services_page.dart @@ -53,14 +53,7 @@ class ServicesPage extends StatelessWidget { late MedicalFileViewModel medicalFileViewModel; late final List hmgServices = [ - HmgServicesComponentModel( - 11, - LocaleKeys.emergencyServices.tr(), - "", - AppAssets.emergency_services_icon, - bgColor: AppColors.primaryRedColor, - true, - route: null, onTap: () async { + HmgServicesComponentModel(11, LocaleKeys.emergencyServices.tr(), "", AppAssets.emergency_services_icon, bgColor: AppColors.primaryRedColor, true, route: null, onTap: () async { if (getIt.get().isAuthenticated) { getIt.get().flushData(); getIt.get().getTransportationOrders( @@ -88,8 +81,7 @@ class ServicesPage extends StatelessWidget { true, route: AppRoutes.bookAppointmentPage, ), - HmgServicesComponentModel( - 5, LocaleKeys.completeCheckup.tr(), "", AppAssets.comprehensiveCheckup, bgColor: AppColors.bgGreenColor, true, route: null, onTap: () async { + HmgServicesComponentModel(5, LocaleKeys.completeCheckup.tr(), "", AppAssets.comprehensiveCheckup, bgColor: AppColors.bgGreenColor, true, route: null, onTap: () async { if (getIt.get().isAuthenticated) { getIt.get().pushPageRoute(AppRoutes.comprehensiveCheckupPage); } else { @@ -141,8 +133,7 @@ class ServicesPage extends StatelessWidget { ); }, ), - HmgServicesComponentModel( - 11, LocaleKeys.eReferralServices.tr(), "", AppAssets.eReferral, bgColor: AppColors.eReferralCardColor, true, route: null, onTap: () async { + HmgServicesComponentModel(11, LocaleKeys.eReferralServices.tr(), "", AppAssets.eReferral, bgColor: AppColors.eReferralCardColor, true, route: null, onTap: () async { if (getIt.get().isAuthenticated) { getIt.get().pushPageRoute(AppRoutes.eReferralPage); } else { @@ -415,19 +406,19 @@ class ServicesPage extends StatelessWidget { ? CustomButton( height: 40.h, icon: AppAssets.recharge_icon, - iconSize: 24.w, - iconColor: AppColors.infoColor, - textColor: AppColors.infoColor, - text: LocaleKeys.recharge.tr(), - borderWidth: 0.w, - fontWeight: FontWeight.w500, - borderColor: Colors.transparent, - backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08), - padding: EdgeInsets.all(8.w), - fontSize: 14.f, - onPressed: () { - Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); - }, + iconSize: 24.w, + iconColor: AppColors.infoColor, + textColor: AppColors.infoColor, + text: LocaleKeys.recharge.tr(), + borderWidth: 0.w, + fontWeight: FontWeight.w500, + borderColor: Colors.transparent, + backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08), + padding: EdgeInsets.all(8.w), + fontSize: 14.f, + onPressed: () { + Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); + }, ) : SizedBox.shrink(), ], @@ -467,60 +458,60 @@ class ServicesPage extends StatelessWidget { getIt.get().isAuthenticated ? Wrap( spacing: -12.h, - // runSpacing: 0.h, - children: [ - Utils.buildImgWithAssets( - icon: AppAssets.babyGirlImg, - height: 32.h, - width: 32.w, - border: 1, - fit: BoxFit.contain, - borderRadius: 50.r, - ), - Utils.buildImgWithAssets( - icon: AppAssets.femaleImg, - height: 32.h, - width: 32.w, - border: 1, - borderRadius: 50.r, - fit: BoxFit.contain, - ), - Utils.buildImgWithAssets( - icon: AppAssets.maleImg, - height: 32.h, - width: 32.w, - border: 1, - borderRadius: 50.r, - fit: BoxFit.contain, - ), - ], + // runSpacing: 0.h, + children: [ + Utils.buildImgWithAssets( + icon: AppAssets.babyGirlImg, + height: 32.h, + width: 32.w, + border: 1, + fit: BoxFit.contain, + borderRadius: 50.r, + ), + Utils.buildImgWithAssets( + icon: AppAssets.femaleImg, + height: 32.h, + width: 32.w, + border: 1, + borderRadius: 50.r, + fit: BoxFit.contain, + ), + Utils.buildImgWithAssets( + icon: AppAssets.maleImg, + height: 32.h, + width: 32.w, + border: 1, + borderRadius: 50.r, + fit: BoxFit.contain, + ), + ], ) : LocaleKeys.loginToViewMedicalFile.tr().toText12(fontWeight: FontWeight.w500, maxLine: 2), Spacer(), getIt.get().isAuthenticated ? CustomButton( height: 40.h, - icon: AppAssets.add_icon, - iconSize: 24.h, - iconColor: AppColors.primaryRedColor, - textColor: AppColors.primaryRedColor, - text: LocaleKeys.addMember.tr(), - borderWidth: 0.w, - fontWeight: FontWeight.w500, - borderColor: Colors.transparent, - backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08), - padding: EdgeInsets.all(8.w), - fontSize: 14.f, - onPressed: () { - DialogService dialogService = getIt.get(); - medicalFileViewModel.clearAuthValues(); - dialogService.showAddFamilyFileSheet( - label: LocaleKeys.addFamilyMember.tr(), - message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(), - onVerificationPress: () { - medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); - }); - }, + icon: AppAssets.add_icon, + iconSize: 24.h, + iconColor: AppColors.primaryRedColor, + textColor: AppColors.primaryRedColor, + text: LocaleKeys.addMember.tr(), + borderWidth: 0.w, + fontWeight: FontWeight.w500, + borderColor: Colors.transparent, + backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08), + padding: EdgeInsets.all(8.w), + fontSize: 14.f, + onPressed: () { + DialogService dialogService = getIt.get(); + medicalFileViewModel.clearAuthValues(); + dialogService.showAddFamilyFileSheet( + label: LocaleKeys.addFamilyMember.tr(), + message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(), + onVerificationPress: () { + medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); + }); + }, ) : SizedBox.shrink(), ], @@ -700,6 +691,58 @@ class ServicesPage extends StatelessWidget { }), ) ], + ), + SizedBox(height: 16.h), + Row( + children: [ + Expanded( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.h, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.privacy_terms, width: 32.w, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.blackColor), + SizedBox(width: 8.w), + Expanded(child: LocaleKeys.termsConditoins.tr().toText14(weight: FontWeight.w500)) + ], + ), + ), + ).onPress(() { + Utils.openWebView( + url: 'https://hmg.com/en/Pages/Terms.aspx', + ); + }), + ), + SizedBox(width: 16.w), + Expanded( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.h, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.privacy_terms, width: 32.w, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.blackColor), + SizedBox(width: 8.w), + Expanded(child: LocaleKeys.privacyPolicy.tr().toText14(weight: FontWeight.w500)) + ], + ), + ), + ).onPress(() { + Utils.openWebView( + url: 'https://hmg.com/en/Pages/Privacy.aspx', + ); + }), + ) + ], ) ], ).paddingSymmetrical(24.w, 0), diff --git a/lib/presentation/home/app_update_page.dart b/lib/presentation/home/app_update_page.dart new file mode 100644 index 0000000..5e6481b --- /dev/null +++ b/lib/presentation/home/app_update_page.dart @@ -0,0 +1,96 @@ +import 'dart:io'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:in_app_update/in_app_update.dart'; +import 'package:lottie/lottie.dart'; + +class AppUpdatePage extends StatelessWidget { + AppUpdatePage({super.key, required this.appUpdateMessage}); + + String appUpdateMessage; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColors.whiteColor, + body: Column( + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.all(24.h), + child: Column( + children: [ + SizedBox(height: 120.h), + Align( + alignment: Alignment.topCenter, + child: Transform.flip( + flipX: getIt.get().isArabic() ? true : false, + child: Lottie.asset(AppAnimations.onboarding_1, + repeat: true, reverse: false, frameRate: FrameRate(60), width: MediaQuery.sizeOf(context).width - 50.w, height: MediaQuery.sizeOf(context).width - 50.w), + ), + ), + SizedBox(height: 50.h), + appUpdateMessage.toText16(weight: FontWeight.w500), + ], + ), + ), + ), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + hasShadow: true, + ), + child: CustomButton( + text: LocaleKeys.updateAppNow.tr(context: context), + onPressed: () { + openAppUpdateLink(); + }, + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, + textColor: AppColors.whiteColor, + borderRadius: 12.r, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 56.h, + ), + ).paddingAll(24.h), + ], + ), + ); + } + + openAppUpdateLink() { + if (Platform.isAndroid) { + // _launchURL("https://play.google.com/store/apps/details?id=com.ejada.hmg"); + InAppUpdate.checkForUpdate().then((info) { + print("checkForUpdate!!!"); + print(info.toString()); + if (info.immediateUpdateAllowed) { + print("Immediate Allowed!!!"); + InAppUpdate.performImmediateUpdate().then((value) {}).catchError((e) => print(e.toString())); + } + }).catchError((e) { + print(e.toString()); + Utils.openWebView( + url: "https://play.google.com/store/apps/details?id=com.ejada.hmg", + ); + }); + } + if (Platform.isIOS) { + Utils.openWebView( + url: "https://itunes.apple.com/app/id733503978", + ); + } + } +} diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index a8a64fa..e8482bf 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -460,7 +460,7 @@ class _LandingPageState extends State { return emergencyServicesVM.patientHasAdvanceERBalance ? Column( children: [ - SizedBox(height: 4.h), + SizedBox(height: 16.h), Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, @@ -490,12 +490,15 @@ class _LandingPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LocaleKeys.youHaveEROnlineCheckInRequest.tr(context: context).toText12(isBold: true), - Utils.buildSvgWithAssets( - icon: AppAssets.forward_arrow_icon_small, - iconColor: AppColors.blackColor, - width: 20.h, - height: 15.h, - fit: BoxFit.contain, + Transform.flip( + flipX: getIt.get().isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon_small, + iconColor: AppColors.blackColor, + width: 20.h, + height: 15.h, + fit: BoxFit.contain, + ), ), ], ), @@ -509,10 +512,10 @@ class _LandingPageState extends State { SizedBox(height: 12.h), ], ) - : SizedBox(height: 12.h); + : SizedBox(height: 0.h); }, ), - SizedBox(height: 24.h), + SizedBox(height: 16.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/presentation/home/widgets/habib_wallet_card.dart b/lib/presentation/home/widgets/habib_wallet_card.dart index 0135983..ed48058 100644 --- a/lib/presentation/home/widgets/habib_wallet_card.dart +++ b/lib/presentation/home/widgets/habib_wallet_card.dart @@ -52,36 +52,36 @@ class HabibWalletCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ LocaleKeys.habibWallet.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2), - Container( - height: 40.h, - width: 40.h, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.textColor, - borderRadius: 8.h, - ), - child: Padding( - padding: EdgeInsets.all(8.h), - child: Utils.buildSvgWithAssets( - icon: AppAssets.show_icon, - width: 12.h, - height: 12.h, - fit: BoxFit.contain, - ), - ), - ), - ], - ), + // Container( + // height: 40.h, + // width: 40.h, + // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + // color: AppColors.textColor, + // borderRadius: 8.h, + // ), + // child: Padding( + // padding: EdgeInsets.all(8.h), + // child: Utils.buildSvgWithAssets( + // icon: AppAssets.show_icon, + // width: 12.h, + // height: 12.h, + // fit: BoxFit.contain, + // ), + // ), + // ), + // ], + // ), SizedBox(height: 4.h), Consumer(builder: (context, habibWalletVM, child) { return Row( children: [ Utils.buildSvgWithAssets( icon: AppAssets.saudi_riyal_icon, - iconColor: AppColors.dividerColor, + iconColor: AppColors.inputLabelTextColor, width: 24.h, height: 24.h, fit: BoxFit.contain, diff --git a/lib/presentation/insurance/widgets/patient_insurance_card.dart b/lib/presentation/insurance/widgets/patient_insurance_card.dart index c9ec790..531341b 100644 --- a/lib/presentation/insurance/widgets/patient_insurance_card.dart +++ b/lib/presentation/insurance/widgets/patient_insurance_card.dart @@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; @@ -16,6 +17,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; class PatientInsuranceCard extends StatelessWidget { PatientInsuranceCard({super.key, required this.insuranceCardDetailsModel, required this.isInsuranceExpired}); @@ -49,19 +51,73 @@ class PatientInsuranceCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - width: MediaQuery.of(context).size.width * 0.45, child: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true)), + width: MediaQuery.of(context).size.width * 0.4, + child: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText18(isBold: true, textOverflow: TextOverflow.clip)), LocaleKeys.policyNumber.tr(namedArgs: {'number': insuranceCardDetailsModel.insurancePolicyNo ?? ''}, context: context).toText12(isBold: true, color: AppColors.lightGrayColor), ], ), AppCustomChipWidget( - icon: isInsuranceExpired ? AppAssets.cancel_circle_icon : AppAssets.insurance_active_icon, - labelText: isInsuranceExpired ? LocaleKeys.insuranceExpired.tr(context: context) : LocaleKeys.insuranceActive.tr(context: context), - iconColor: isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, - textColor: isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, - iconSize: 12, - backgroundColor: isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1), - labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h), - ), + icon: insuranceViewModel.isInsuranceExpired + ? AppAssets.cancel_circle_icon + : insuranceViewModel.isInsuranceActive + ? AppAssets.insurance_active_icon + : AppAssets.alertSquare, + labelText: insuranceViewModel.isInsuranceExpired + ? LocaleKeys.insuranceExpired.tr(context: context) + : insuranceViewModel.isInsuranceActive + ? LocaleKeys.insuranceActive.tr(context: context) + : LocaleKeys.insuranceInActive.tr(context: context), + iconColor: insuranceViewModel.isInsuranceExpired + ? AppColors.primaryRedColor + : insuranceViewModel.isInsuranceActive + ? AppColors.successColor + : AppColors.warningColorYellow, + textColor: insuranceViewModel.isInsuranceExpired + ? AppColors.primaryRedColor + : insuranceViewModel.isInsuranceActive + ? AppColors.successColor + : AppColors.warningColorYellow, + iconSize: 12.w, + deleteIcon: insuranceViewModel.isInsuranceActive ? null : AppAssets.forward_chevron_icon, + deleteIconColor: AppColors.warningColorYellow, + deleteIconHasColor: true, + onChipTap: () { + if (!insuranceViewModel.isInsuranceActive) { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context), + confirmText: LocaleKeys.contactUs.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(context); + }, + onConfirmTap: () async { + launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } + }, + backgroundColor: insuranceViewModel.isInsuranceExpired + ? AppColors.primaryRedColor.withOpacity(0.1) + : insuranceViewModel.isInsuranceActive + ? AppColors.successColor.withOpacity(0.1) + : AppColors.warningColorYellow.withOpacity(0.1), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: insuranceViewModel.isInsuranceActive ? 6.w : 0.w), + ).toShimmer2(isShow: insuranceViewModel.isInsuranceLoading), + // AppCustomChipWidget( + // icon: isInsuranceExpired ? AppAssets.cancel_circle_icon : AppAssets.insurance_active_icon, + // labelText: isInsuranceExpired ? LocaleKeys.insuranceExpired.tr(context: context) : LocaleKeys.insuranceActive.tr(context: context), + // iconColor: isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, + // textColor: isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, + // iconSize: 12, + // backgroundColor: isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1), + // labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h), + // ), ], ), SizedBox(height: 12.h), diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart index a6ee154..4016aff 100644 --- a/lib/presentation/lab/lab_orders_page.dart +++ b/lib/presentation/lab/lab_orders_page.dart @@ -1 +1 @@ -import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { final lavVM = Provider.of(context, listen: false); if (lavVM.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: lavVM.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; lavVM.filterLabReports(value); } } }, child: Consumer( builder: (context, model, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ CustomButton( text: LocaleKeys.byClinic.tr(context: context), onPressed: () { model.setIsSortByClinic(true); }, backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, fontSize: 12, fontWeight: FontWeight.w500, borderRadius: 10, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), SizedBox(width: 8.h), CustomButton( text: LocaleKeys.byHospital.tr(context: context), onPressed: () { model.setIsSortByClinic(false); }, backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, borderColor: model.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, fontSize: 12, fontWeight: FontWeight.w500, borderRadius: 10, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? CustomChipWidget( chipText: selectedFilterText!, chipType: ChipTypeEnum.alert, isSelected: true, ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available model.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (model.patientLabOrdersViewList.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: model.patientLabOrdersViewList.length, itemBuilder: (context, index) { final group = model.patientLabOrdersViewList[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AppCustomChipWidget(labelText: "${group.length} ${LocaleKeys.results.tr(context: context)}"), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Text( model.isSortByClinic ? (group.first.clinicDescription ?? 'Unknown') : (group.first.projectName ?? 'Unknown'), style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis, ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group[index]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), ), AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), ), AppCustomChipWidget( labelText: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), ), ], ), // Row( // children: [ // CustomButton( // text: ("Order No: ".needTranslation + order.orderNo!), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // ], // ), // SizedBox(height: 8.h), // Row( // children: [ // CustomButton( // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // ], // ), SizedBox(height: 12.h), Row( children: [ Expanded(flex: 2, child: SizedBox()), // Expanded( // flex: 1, // child: Container( // height: 40.h, // width: 40.w, // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // color: AppColors.textColor, // borderRadius: 12, // ), // child: Padding( // padding: EdgeInsets.all(12.h), // child: Transform.flip( // flipX: _appState.isArabic(), // child: Utils.buildSvgWithAssets( // icon: AppAssets.forward_arrow_icon_small, // iconColor: AppColors.whiteColor, // fit: BoxFit.contain, // ), // ), // ), // ).onPress(() { // model.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }), // ) Expanded( flex: 2, child: CustomButton( icon: AppAssets.view_report_icon, iconColor: AppColors.primaryRedColor, iconSize: 16.h, text: LocaleKeys.viewResults.tr(context: context), onPressed: () { model.currentlySelectedPatientOrder = order; labProvider.getPatientLabResultByHospital(order); labProvider.getPatientSpecialResult(order); Navigator.of(context).push( CustomPageRoute(page: LabResultByClinic(labOrder: order)), ); }, backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), ) ], ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.length)) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (model.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: model.indexedCharacterForUniqueTest, details: model.uniqueTestsList, labViewModel: model, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file +import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { final lavVM = Provider.of(context, listen: false); if (lavVM.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: lavVM.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; lavVM.filterLabReports(value); } } }, child: Consumer( builder: (context, model, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ CustomButton( text: LocaleKeys.byClinic.tr(context: context), onPressed: () { model.setIsSortByClinic(true); }, backgroundColor: model.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, borderColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), textColor: model.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, fontSize: 12, fontWeight: FontWeight.w500, borderRadius: 10, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), SizedBox(width: 8.h), CustomButton( text: LocaleKeys.byHospital.tr(context: context), onPressed: () { model.setIsSortByClinic(false); }, backgroundColor: model.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, borderColor: model.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, textColor: model.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, fontSize: 12, fontWeight: FontWeight.w500, borderRadius: 10, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? CustomChipWidget( chipText: selectedFilterText!, chipType: ChipTypeEnum.alert, isSelected: true, ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available model.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (model.patientLabOrdersViewList.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: model.patientLabOrdersViewList.length, itemBuilder: (context, index) { final group = model.patientLabOrdersViewList[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AppCustomChipWidget(labelText: "${group.length} ${LocaleKeys.results.tr(context: context)}"), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Text( model.isSortByClinic ? (group.first.clinicDescription ?? 'Unknown') : (group.first.projectName ?? 'Unknown'), style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis, ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group[index]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), ), AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), ), AppCustomChipWidget( labelText: model.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), ), ], ), // Row( // children: [ // CustomButton( // text: ("Order No: ".needTranslation + order.orderNo!), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // ], // ), // SizedBox(height: 8.h), // Row( // children: [ // CustomButton( // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // onPressed: () {}, // backgroundColor: AppColors.greyColor, // borderColor: AppColors.greyColor, // textColor: AppColors.blackColor, // fontSize: 10, // fontWeight: FontWeight.w500, // borderRadius: 8, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 24.h, // ), // ], // ), SizedBox(height: 12.h), Row( children: [ Expanded(flex: 2, child: SizedBox()), // Expanded( // flex: 1, // child: Container( // height: 40.h, // width: 40.w, // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // color: AppColors.textColor, // borderRadius: 12, // ), // child: Padding( // padding: EdgeInsets.all(12.h), // child: Transform.flip( // flipX: _appState.isArabic(), // child: Utils.buildSvgWithAssets( // icon: AppAssets.forward_arrow_icon_small, // iconColor: AppColors.whiteColor, // fit: BoxFit.contain, // ), // ), // ), // ).onPress(() { // model.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }), // ) Expanded( flex: 2, child: CustomButton( icon: AppAssets.view_report_icon, iconColor: AppColors.primaryRedColor, iconSize: 16.h, text: LocaleKeys.viewResults.tr(context: context), onPressed: () { model.currentlySelectedPatientOrder = order; labProvider.getPatientLabResultByHospital(order); labProvider.getPatientSpecialResult(order); Navigator.of(context).push( CustomPageRoute(page: LabResultByClinic(labOrder: order)), ); }, backgroundColor: AppColors.secondaryLightRedColor, borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, fontSize: 14, fontWeight: FontWeight.w500, borderRadius: 12, padding: EdgeInsets.fromLTRB(10, 0, 10, 0), height: 40.h, ), ) ], ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.length)) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (model.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: model.indexedCharacterForUniqueTest, details: model.uniqueTestsList, labViewModel: model, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file diff --git a/lib/presentation/labAiAnalysis/lab_ai_analysis_detailed_page.dart b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart similarity index 97% rename from lib/presentation/labAiAnalysis/lab_ai_analysis_detailed_page.dart rename to lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart index 5d4fe4b..14ff620 100644 --- a/lib/presentation/labAiAnalysis/lab_ai_analysis_detailed_page.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart @@ -14,7 +14,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/expandable_list_widget.dart'; import 'package:provider/provider.dart'; -import '../../features/lab/models/resp_models/ai_overview_labresults_by_ai_model.dart'; +import '../../../features/lab/models/resp_models/ai_overview_labresults_by_ai_model.dart'; class LabAiAnalysisDetailedPage extends StatefulWidget { const LabAiAnalysisDetailedPage({super.key}); @@ -314,6 +314,16 @@ class _LabAiAnalysisDetailedPageState extends State { defaultTrailingIcon: Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, height: 22.h, width: 22.w, iconColor: AppColors.textColor), ), ).paddingSymmetrical(16.w, 0.0), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(Icons.info_outline, color: AppColors.greyTextColor, size: 20.r), + SizedBox(width: 8.w), + Expanded( + child: ("${LocaleKeys.disclaimer.tr()}:${LocaleKeys.thisAboveInfo.tr()}").toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w400), + ), + ], + ).paddingSymmetrical(16.w, 16.h) ], ); }, diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index ddac1bb..2e85099 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -33,6 +33,7 @@ import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_invoices/my_invoices_view_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart'; +import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/active_medication/active_medication_page.dart'; import 'package:hmg_patient_app_new/presentation/allergies/allergies_list_page.dart'; @@ -78,6 +79,7 @@ import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/common_shimmer_widget.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../../features/active_prescriptions/active_prescriptions_view_model.dart'; import '../prescriptions/prescription_detail_page.dart'; @@ -286,14 +288,58 @@ class _MedicalFilePageState extends State { ), Consumer(builder: (context, insuranceVM, child) { return AppCustomChipWidget( - icon: insuranceVM.isInsuranceExpired ? AppAssets.cancel_circle_icon : AppAssets.insurance_active_icon, - labelText: insuranceVM.isInsuranceExpired ? LocaleKeys.insuranceExpired.tr(context: context) : LocaleKeys.insuranceActive.tr(context: context), - iconColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, - textColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor : AppColors.successColor, + icon: insuranceVM.isInsuranceExpired + ? AppAssets.cancel_circle_icon + : insuranceVM.isInsuranceActive + ? AppAssets.insurance_active_icon + : AppAssets.alertSquare, + labelText: insuranceVM.isInsuranceExpired + ? LocaleKeys.insuranceExpired.tr(context: context) + : insuranceVM.isInsuranceActive + ? LocaleKeys.insuranceActive.tr(context: context) + : LocaleKeys.insuranceInActive.tr(context: context), + iconColor: insuranceVM.isInsuranceExpired + ? AppColors.primaryRedColor + : insuranceVM.isInsuranceActive + ? AppColors.successColor + : AppColors.warningColorYellow, + textColor: insuranceVM.isInsuranceExpired + ? AppColors.primaryRedColor + : insuranceVM.isInsuranceActive + ? AppColors.successColor + : AppColors.warningColorYellow, iconSize: 12.w, - backgroundColor: insuranceVM.isInsuranceExpired ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.successColor.withOpacity(0.1), - labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), - ); + deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon, + deleteIconColor: AppColors.warningColorYellow, + deleteIconHasColor: true, + onChipTap: () { + if (!insuranceVM.isInsuranceActive) { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!), + navigationService.navigatorKey.currentContext!, + child: Utils.getWarningWidget( + loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context), + confirmText: LocaleKeys.contactUs.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + navigationService.pop(); + }, + onConfirmTap: () async { + launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } + }, + backgroundColor: insuranceVM.isInsuranceExpired + ? AppColors.primaryRedColor.withOpacity(0.1) + : insuranceVM.isInsuranceActive + ? AppColors.successColor.withOpacity(0.1) + : AppColors.warningColorYellow.withOpacity(0.1), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: insuranceVM.isInsuranceActive ? 6.w : 0.w), + ).toShimmer2(isShow: insuranceVM.isInsuranceLoading); }), ], ), @@ -1176,6 +1222,7 @@ class _MedicalFilePageState extends State { isLargeText: true, iconSize: 36.w, ).onPress(() { + getIt.get().setIsAncillaryOrdersNeedReloading(true); Navigator.of(context).push( CustomPageRoute( page: ToDoPage(), diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart index a3c2667..82150ca 100644 --- a/lib/presentation/profile_settings/profile_settings.dart +++ b/lib/presentation/profile_settings/profile_settings.dart @@ -30,6 +30,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -197,9 +198,11 @@ class ProfileSettingsState extends State { showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.language.tr(context: context), child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false); }, trailingLabel: Utils.appState.isArabic() ? "العربية" : "English"), 1.divider, - actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () {}), - 1.divider, - actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true), + actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () { + openAppSettings(); + }), + // 1.divider, + // actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true), ], ), ), @@ -228,11 +231,11 @@ class ProfileSettingsState extends State { child: Column( children: [ actionItem(AppAssets.call_fill, LocaleKeys.contactUs.tr(context: context), () { - launchUrl(Uri.parse("tel://" + "+966 11 525 9999")); - }, trailingLabel: "011 525 9999"), - 1.divider, - actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"), + launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); + }, trailingLabel: "92 006 6666"), 1.divider, + // actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"), + // 1.divider, actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(context: context), () { if (Platform.isAndroid) { Utils.openWebView( @@ -366,61 +369,66 @@ class FamilyCardWidget extends StatelessWidget { labelText: "Blood: ${appState.getAuthenticatedUser()!.bloodGroup ?? ""}", iconColor: AppColors.primaryRedColor) : SizedBox(), - Selector( - selector: (context, insuranceVM) => ( - isEmpty: insuranceVM.patientInsuranceList.isEmpty, - patientID: insuranceVM.patientInsuranceList.isNotEmpty ? insuranceVM.patientInsuranceList.first.patientID : null, - isLoading: insuranceVM.isInsuranceLoading, - cardValidTo: insuranceVM.patientInsuranceList.isNotEmpty ? insuranceVM.patientInsuranceList.first.cardValidTo : null - ), - builder: (context, data, child) { - if (data.isEmpty) { - return const SizedBox(); - } else if (profile.responseId != data.patientID) { - return SizedBox(); - } - - final isLoading = data.isLoading; - final isExpired = !isLoading && DateTime.now().isAfter(DateUtil.convertStringToDate(data.cardValidTo)); - - final String icon; - final String labelText; - final Color iconColor; - final Color backgroundColor; - - if (isLoading) { - icon = AppAssets.cancel_circle_icon; - labelText = LocaleKeys.insurance.tr(context: context); - iconColor = AppColors.primaryRedColor; - backgroundColor = AppColors.primaryRedColor; - } else if (isExpired) { - icon = AppAssets.cancel_circle_icon; - labelText = LocaleKeys.insuranceExpired.tr(context: context); - iconColor = AppColors.primaryRedColor; - backgroundColor = AppColors.primaryRedColor.withValues(alpha: 0.15); - } else { - icon = AppAssets.insurance_active_icon; - labelText = LocaleKeys.insuranceActive.tr(context: context); - iconColor = AppColors.successColor; - backgroundColor = AppColors.successColor.withValues(alpha: 0.15); - } - - return AppCustomChipWidget( - icon: icon, - labelText: labelText, - iconColor: iconColor, - iconSize: 12.w, - backgroundColor: backgroundColor, - labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 8.w), - // padding: EdgeInsets.zero, - ).toShimmer2(isShow: isLoading); - }, - ) + Consumer(builder: (context, insuranceVM, child) { + return AppCustomChipWidget( + icon: insuranceVM.isInsuranceExpired + ? AppAssets.cancel_circle_icon + : insuranceVM.isInsuranceActive + ? AppAssets.insurance_active_icon + : AppAssets.alertSquare, + labelText: insuranceVM.isInsuranceExpired + ? LocaleKeys.insuranceExpired.tr(context: context) + : insuranceVM.isInsuranceActive + ? LocaleKeys.insuranceActive.tr(context: context) + : LocaleKeys.insuranceInActive.tr(context: context), + iconColor: insuranceVM.isInsuranceExpired + ? AppColors.primaryRedColor + : insuranceVM.isInsuranceActive + ? AppColors.successColor + : AppColors.warningColorYellow, + textColor: insuranceVM.isInsuranceExpired + ? AppColors.primaryRedColor + : insuranceVM.isInsuranceActive + ? AppColors.successColor + : AppColors.warningColorYellow, + iconSize: 12.w, + deleteIcon: insuranceVM.isInsuranceActive ? null : AppAssets.forward_chevron_icon, + deleteIconColor: AppColors.warningColorYellow, + deleteIconHasColor: true, + onChipTap: () { + if (!insuranceVM.isInsuranceActive) { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: LocaleKeys.insuranceInActiveContactSupport.tr(context: context), + confirmText: LocaleKeys.contactUs.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(context); + }, + onConfirmTap: () async { + launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } + }, + backgroundColor: insuranceVM.isInsuranceExpired + ? AppColors.primaryRedColor.withOpacity(0.1) + : insuranceVM.isInsuranceActive + ? AppColors.successColor.withOpacity(0.1) + : AppColors.warningColorYellow.withOpacity(0.1), + labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: insuranceVM.isInsuranceActive ? 6.w : 0.w), + ).toShimmer2(isShow: insuranceVM.isInsuranceLoading); + }), ], ), ), ], - ).paddingOnly(top: 16.h, right: 16.w, left: 16.w, bottom: 0.h), + ).paddingOnly(top: 16.h, right: 16.w, left: 16.w, bottom: 8.h), 1.divider.paddingSymmetrical(16.w, 0.h), _buildActionButton(appState), ], diff --git a/lib/presentation/radiology/radiology_orders_page.dart b/lib/presentation/radiology/radiology_orders_page.dart index f9b94e2..2f42436 100644 --- a/lib/presentation/radiology/radiology_orders_page.dart +++ b/lib/presentation/radiology/radiology_orders_page.dart @@ -310,8 +310,8 @@ class _RadiologyOrdersPageState extends State { ), ), AppCustomChipWidget( - labelText: model.isSortByClinic ? (order.clinicDescription ?? '') : (order.projectName ?? ''), - ), + labelText: model.isSortByClinic ? (order.projectName ?? '') : (order.clinicDescription ?? ''), + ), ], ), SizedBox(height: 12.h), diff --git a/lib/presentation/symptoms_checker/possible_conditions_screen.dart b/lib/presentation/symptoms_checker/possible_conditions_screen.dart index 3d288d7..80c7071 100644 --- a/lib/presentation/symptoms_checker/possible_conditions_screen.dart +++ b/lib/presentation/symptoms_checker/possible_conditions_screen.dart @@ -8,20 +8,32 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/widgets/faculity_selection/facility_type_selection_widget.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/condition_card.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:provider/provider.dart'; import 'package:shimmer/shimmer.dart'; +import '../appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart'; + class PossibleConditionsPage extends StatelessWidget { - const PossibleConditionsPage({super.key}); + PossibleConditionsPage({super.key}); + + late SymptomsCheckerViewModel symptomsCheckerViewModel; + late BookAppointmentsViewModel bookAppointmentsViewModel; + late AppointmentViaRegionViewmodel regionalViewModel; Widget _buildLoadingShimmer() { return ListView.separated( @@ -80,8 +92,20 @@ class PossibleConditionsPage extends StatelessWidget { condition: condition, symptoms: symptoms, onActionPressed: () { - dialogService.showErrorBottomSheet( - message: 'icd10 Code is ${condition.conditionDetails?.icd10Code}. We need to get the clinics mapped against this code.', + LoaderBottomSheet.showLoader(); + symptomsCheckerViewModel.getClinicConditionsFromCategory( + categoryName: (condition.conditionDetails!.category!.name) ?? "Other", + onSuccess: (value) { + LoaderBottomSheet.hideLoader(); + print(symptomsCheckerViewModel.clinicDetailsList.first.clinicID); + initiateBookAppointmentFlow(context); + }, + onError: (err) { + LoaderBottomSheet.hideLoader(); + dialogService.showErrorBottomSheet( + message: err.toString(), + ); + }, ); }, ); @@ -194,6 +218,9 @@ class PossibleConditionsPage extends StatelessWidget { @override Widget build(BuildContext context) { + symptomsCheckerViewModel = context.read(); + bookAppointmentsViewModel = context.read(); + regionalViewModel = context.read(); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( @@ -202,7 +229,6 @@ class PossibleConditionsPage extends StatelessWidget { context: context, onConfirm: () { context.pop(); - final SymptomsCheckerViewModel symptomsCheckerViewModel = context.read(); symptomsCheckerViewModel.reset(); // Clear all symptoms checker data final navigationService = getIt.get(); // navigationService.replaceAllRoutesAndNavigateToLanding(); @@ -230,4 +256,102 @@ class PossibleConditionsPage extends StatelessWidget { ), ); } + + initiateBookAppointmentFlow(BuildContext context) { + bookAppointmentsViewModel.getLocation(); + bookAppointmentsViewModel.setSelectedClinic(GetClinicsListResponseModel( + clinicID: symptomsCheckerViewModel.clinicDetailsList.first.clinicID, + clinicDescription: symptomsCheckerViewModel.clinicDetailsList.first.category, + clinicDescriptionN: symptomsCheckerViewModel.clinicDetailsList.first.categoryAR, + )); + bookAppointmentsViewModel.setIsDoctorsListLoading(true); + + var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; + openRegionListBottomSheet(context, bottomSheetType); + } + + getTitle(AppointmentViaRegionViewmodel data, BuildContext context) { + if (data.selectedRegionId == null) { + return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600); + } else { + return Transform.flip( + flipX: data.isArabic ? true : false, + child: Utils.buildSvgWithAssets( + icon: AppAssets.arrow_back, + iconColor: Color(0xff2B353E), + fit: BoxFit.contain, + ), + ).onPress(() { + data.handleBackPress(); + }); + } + } + + void openRegionListBottomSheet(BuildContext context, RegionBottomSheetType type) { + bookAppointmentsViewModel.setProjectID(null); + + regionalViewModel.flush(); + regionalViewModel.setBottomSheetType(type); + // AppointmentViaRegionViewmodel? viewmodel = null; + showCommonBottomSheetWithoutHeight(context, title: "", titleWidget: Consumer(builder: (_, data, __) => getTitle(data, context)), isDismissible: false, + child: Consumer(builder: (context, data, __) { + return getRegionalSelectionWidget(data, context); + }), callBackFunc: () {}); + } + + Widget getRegionalSelectionWidget(AppointmentViaRegionViewmodel data, BuildContext context) { + if (data.bottomSheetState == AppointmentViaRegionState.REGION_SELECTION) { + return RegionBottomSheetBody(); + } + if (data.bottomSheetState == AppointmentViaRegionState.TYPE_SELECTION) { + bookAppointmentsViewModel.resetFilterList(); + return FacilityTypeSelectionWidget( + selectedRegion: data.selectedRegionId ?? "", + ); + } + if (data.bottomSheetState == AppointmentViaRegionState.HOSPITAL_SELECTION) { + return HospitalBottomSheetBody( + searchText: data.searchController, + displayList: data.displayList, + onFacilityClicked: (value) { + data.setSelectedFacility(value); + data.getDisplayList(); + }, + onHospitalClicked: (hospital) { + regionalViewModel.setHospitalModel(hospital); + if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION) { + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); + regionalViewModel.handleLastStepForRegion(); + } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + regionalViewModel.handleLastStepForClinic(); + } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { + var appointmentsViewModel = Provider.of(context, listen: false); + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); + } + }, + onHospitalSearch: (value) { + data.searchHospitals(value ?? ""); + }, + selectedFacility: data.selectedFacility, + hmcCount: data.hmcCount, + hmgCount: data.hmgCount, + ); + } + if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) { + //if the region screen is opened for the dental clinic then the project id will be in the hospital list as the list is formed form the get project api + var id = ""; + if (data.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { + id = regionalViewModel.selectedHospital?.hospitalList.first.iD?.toString() ?? ""; + } else { + id = regionalViewModel.selectedHospital?.patientDoctorAppointmentList?.first.projectID?.toString() ?? ""; + } + bookAppointmentsViewModel.setProjectID(id); + return SizedBox.shrink(); + } else { + return SizedBox.shrink(); + } + return SizedBox.shrink(); + } } diff --git a/lib/presentation/tele_consultation/zoom/call_screen.dart b/lib/presentation/tele_consultation/zoom/call_screen.dart index 59b5ce4..59be70e 100644 --- a/lib/presentation/tele_consultation/zoom/call_screen.dart +++ b/lib/presentation/tele_consultation/zoom/call_screen.dart @@ -352,43 +352,44 @@ class _CallScreenState extends State { ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); if (data['status'] == RecordingStatus.Start) { if (mySelf != null && !mySelf.isHost!) { - showDialog( - context: context, - builder: (BuildContext context) => AlertDialog( - content: const Text('The session is being recorded.'), - actions: [ - TextButton( - onPressed: () async { - await zoom.acceptRecordingConsent(); - if (context.mounted) { - Navigator.pop(context); - } - ; - }, - child: const Text('accept'), - ), - TextButton( - onPressed: () async { - String currentConsentType = await zoom.getRecordingConsentType(); - if (currentConsentType == ConsentType.ConsentType_Individual) { - await zoom.declineRecordingConsent(); - Navigator.pop(context); - } else { - await zoom.declineRecordingConsent(); - zoom.leaveSession(false); - if (!context.mounted) return; - Navigator.popAndPushNamed( - context, - "Join", - arguments: JoinArguments(args.isJoin, sessionName.value, sessionPassword.value, args.displayName, args.sessionIdleTimeoutMins, args.role), - ); - } - }, - child: const Text('decline'), - ), - ], - ), - ); + await zoom.acceptRecordingConsent(); + // showDialog( + // context: context, + // builder: (BuildContext context) => AlertDialog( + // content: const Text('The session is being recorded.'), + // actions: [ + // TextButton( + // onPressed: () async { + // await zoom.acceptRecordingConsent(); + // if (context.mounted) { + // Navigator.pop(context); + // } + // ; + // }, + // child: const Text('accept'), + // ), + // TextButton( + // onPressed: () async { + // String currentConsentType = await zoom.getRecordingConsentType(); + // if (currentConsentType == ConsentType.ConsentType_Individual) { + // await zoom.declineRecordingConsent(); + // Navigator.pop(context); + // } else { + // await zoom.declineRecordingConsent(); + // zoom.leaveSession(false); + // if (!context.mounted) return; + // Navigator.popAndPushNamed( + // context, + // "Join", + // arguments: JoinArguments(args.isJoin, sessionName.value, sessionPassword.value, args.displayName, args.sessionIdleTimeoutMins, args.role), + // ); + // } + // }, + // child: const Text('decline'), + // ), + // ], + // ), + // ); } isRecordingStarted.value = true; } else { @@ -1745,11 +1746,11 @@ class _CallScreenState extends State { iconSize: circleButtonSize, tooltip: isMuted.value == true ? "Unmute" : "Mute", ), - IconButton( - onPressed: onPressShare, - icon: isSharing.value ? Image.asset("assets/images/png/zoom/share-off@2x.png") : Image.asset("assets/images/png/zoom/share-on@2x.png"), - iconSize: circleButtonSize, - ), + // IconButton( + // onPressed: onPressShare, + // icon: isSharing.value ? Image.asset("assets/images/png/zoom/share-off@2x.png") : Image.asset("assets/images/png/zoom/share-on@2x.png"), + // iconSize: circleButtonSize, + // ), IconButton( onPressed: onPressVideo, iconSize: circleButtonSize, @@ -1771,35 +1772,35 @@ class _CallScreenState extends State { ], ), )), - Container( - margin: const EdgeInsets.only(left: 16, right: 16, bottom: 40, top: 10), - alignment: Alignment.bottomCenter, - child: SizedBox( - height: MediaQuery.of(context).viewInsets.bottom == 0 ? 65 : MediaQuery.of(context).viewInsets.bottom + 18, - child: TextField( - maxLines: 1, - textAlign: TextAlign.left, - style: TextStyle(color: chatTextColor), - cursorColor: chatTextColor, - textAlignVertical: TextAlignVertical.center, - controller: chatMessageController, - decoration: InputDecoration( - contentPadding: const EdgeInsets.only(left: 16, top: 10, bottom: 10, right: 16), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(width: 1, color: chatTextColor), //<-- SEE HERE - ), - hintText: 'Type your message here...', - hintStyle: TextStyle( - fontSize: 14.0, - color: chatTextColor, - ), - ), - onSubmitted: (String str) { - sendChatMessage(str); - }, - ), - ), - ), + // Container( + // margin: const EdgeInsets.only(left: 16, right: 16, bottom: 40, top: 10), + // alignment: Alignment.bottomCenter, + // child: SizedBox( + // height: MediaQuery.of(context).viewInsets.bottom == 0 ? 65 : MediaQuery.of(context).viewInsets.bottom + 18, + // child: TextField( + // maxLines: 1, + // textAlign: TextAlign.left, + // style: TextStyle(color: chatTextColor), + // cursorColor: chatTextColor, + // textAlignVertical: TextAlignVertical.center, + // controller: chatMessageController, + // decoration: InputDecoration( + // contentPadding: const EdgeInsets.only(left: 16, top: 10, bottom: 10, right: 16), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide(width: 1, color: chatTextColor), //<-- SEE HERE + // ), + // hintText: 'Type your message here...', + // hintStyle: TextStyle( + // fontSize: 14.0, + // color: chatTextColor, + // ), + // ), + // onSubmitted: (String str) { + // sendChatMessage(str); + // }, + // ), + // ), + // ), Container( alignment: Alignment.bottomLeft, margin: const EdgeInsets.only(bottom: 120), diff --git a/lib/presentation/todo_section/ancillary_order_payment_page.dart b/lib/presentation/todo_section/ancillary_order_payment_page.dart index fe07186..b34bf21 100644 --- a/lib/presentation/todo_section/ancillary_order_payment_page.dart +++ b/lib/presentation/todo_section/ancillary_order_payment_page.dart @@ -103,7 +103,7 @@ class _AncillaryOrderPaymentPageState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.visaOrMastercard.tr(context: context).toText16(isBold: true).toShimmer2(isShow: todoVM.isProcessingPayment), + Image.asset(AppAssets.mada, width: 50.h, height: 50.h), SizedBox(height: 16.h), LocaleKeys.mada.tr(context: context).toText16(isBold: true).toShimmer2(isShow: todoVM.isProcessingPayment), ], @@ -468,86 +468,43 @@ class _AncillaryOrderPaymentPageState extends State { languageID: appState.isArabic() ? 1 : 2, onSuccess: (response) { LoaderBottomSheet.hideLoader(); - final invoiceNo = response['AncillaryOrderInvoiceList']?[0]?['InvoiceNo']; - _showSuccessDialog(invoiceNo); }, onError: (error) { LoaderBottomSheet.hideLoader(); todoSectionViewModel.setProcessingPayment(false); - Utils.showToast(error); + showCommonBottomSheetWithoutHeight(context, + child: Utils.getErrorWidget(loadingText: error.toString()), isCloseButtonVisible: true, isDismissible: true, isFullScreen: false, callBackFunc: () {}); }, ); } void _showSuccessDialog(dynamic invoiceNo) { todoSectionViewModel.setProcessingPayment(false); - - log("Ancillary order payment successful! Invoice #: $invoiceNo"); - // Show success message and navigate - Utils.showToast("Payment successful! Invoice #: $invoiceNo"); + // Utils.showToast("Payment successful! Invoice #: $invoiceNo"); // Navigate back to home after a short delay - Future.delayed(Duration(seconds: 1), () { - showCommonBottomSheetWithoutHeight( - context, - child: Column( - children: [ - Row( - children: [ - LocaleKeys.hereIsYourInvoiceNumber.tr(context: context).toText14( - color: AppColors.textColorLight, - weight: FontWeight.w500, - ), - SizedBox(width: 4.w), - ("12345").toText16(isBold: true), - ], - ), - SizedBox(height: 24.h), - Row( - children: [ - Expanded( - child: CustomButton( - height: 56.h, - text: LocaleKeys.ok.tr(context: context), - onPressed: () { - Navigator.pushAndRemoveUntil( - context, - CustomPageRoute( - page: LandingNavigation(), - ), - (r) => false); - }, - backgroundColor: AppColors.secondaryLightRedColor, - borderColor: AppColors.secondaryLightRedColor, - textColor: AppColors.primaryRedColor, - ), - ), - ], - ), - ], - ), - // title: LocaleKeys.paymentCompletedSuccessfully.tr(context: context), - titleWidget: Utils.getSuccessWidget(loadingText: LocaleKeys.paymentCompletedSuccessfully.tr(context: context)), - isCloseButtonVisible: false, - isDismissible: false, - isFullScreen: false, - ); + // Future.delayed(Duration(seconds: 1), () { + showCommonBottomSheetWithoutHeight(context, + child: Utils.getSuccessWidget(loadingText: "${LocaleKeys.paymentCompletedSuccessfully.tr(context: context)}, ${LocaleKeys.hereIsYourInvoiceNumber.tr(context: context)}$invoiceNo"), + isCloseButtonVisible: true, + isDismissible: true, + isFullScreen: false, callBackFunc: () { + // Pop until we reach the LandingPage + todoSectionViewModel.setIsAncillaryOrdersNeedReloading(true); + Navigator.pushAndRemoveUntil( + context, + CustomPageRoute( + page: LandingNavigation(), + ), + (r) => false); }); + // }); } _startApplePay() async { - showCommonBottomSheet( - context, - child: Utils.getLoadingWidget(), - callBackFunc: (str) {}, - title: "", - height: ResponsiveExtension.screenHeight * 0.3, - isCloseButtonVisible: false, - isDismissible: false, - isFullScreen: false, - ); + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingApplePayDetails.tr(context: context)); final user = appState.getAuthenticatedUser(); transID = Utils.getAdvancePaymentTransID(widget.projectID, user!.patientId!); @@ -604,7 +561,7 @@ class _AncillaryOrderPaymentPageState extends State { await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest); } catch (error) { log("Apple Pay Insert Request Failed: $error"); - Navigator.of(context).pop(); + LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( context, child: Utils.getErrorWidget(loadingText: LocaleKeys.failedToInitializeApplePay.tr(context: context)), @@ -627,7 +584,7 @@ class _AncillaryOrderPaymentPageState extends State { currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED", onFailed: (failureResult) async { log("failureResult: ${failureResult.message.toString()}"); - Navigator.of(context).pop(); + LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( context, child: Utils.getErrorWidget(loadingText: failureResult.message.toString()), @@ -637,7 +594,7 @@ class _AncillaryOrderPaymentPageState extends State { ); }, onSucceeded: (successResult) async { - Navigator.of(context).pop(); + LoaderBottomSheet.hideLoader(); log("successResult: ${successResult.responseMessage.toString()}"); selectedPaymentMethod = successResult.paymentOption ?? "VISA"; _checkPaymentStatus(); diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index c09fab6..fd16a2d 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -14,6 +14,7 @@ import 'package:hmg_patient_app_new/presentation/health_calculators_and_converts import 'package:hmg_patient_app_new/presentation/health_trackers/add_health_tracker_entry_page.dart'; import 'package:hmg_patient_app_new/presentation/health_trackers/health_tracker_detail_page.dart'; import 'package:hmg_patient_app_new/presentation/health_trackers/health_trackers_page.dart'; +import 'package:hmg_patient_app_new/presentation/home/app_update_page.dart'; import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart'; import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; @@ -61,6 +62,7 @@ class AppRoutes { static const String huaweiHealthExample = '/huaweiHealthExample'; static const String covid19Test = '/covid19Test'; static const String vitalSign = '/vitalSign'; + static const String appUpdate = '/appUpdate'; //appointments static const String bookAppointmentPage = '/bookAppointmentPage'; @@ -123,6 +125,9 @@ class AppRoutes { healthConvertersPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.converter), healthTrackersPage: (context) => HealthTrackersPage(), vitalSign: (context) => VitalSignPage(), + appUpdate: (context) => AppUpdatePage( + appUpdateMessage: '', + ), emergencyServicesPage: (context) => EmergencyServicesPage(), servicesPriceListPage: (context) => ServicesPriceListPage(), addHealthTrackerEntryPage: (context) { diff --git a/lib/widgets/app_language_change.dart b/lib/widgets/app_language_change.dart index e75ff6f..1200c53 100644 --- a/lib/widgets/app_language_change.dart +++ b/lib/widgets/app_language_change.dart @@ -103,7 +103,7 @@ class _AppLanguageChangeState extends State { }, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), - title.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).expanded, + title.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, fontFamily: _value == "ar" ? 'GESSTwo' : 'Poppins').expanded, ], ).paddingOnly(left: 16, right: 16).onPress(() { setState(() { diff --git a/lib/widgets/bottom_navigation/bottom_navigation.dart b/lib/widgets/bottom_navigation/bottom_navigation.dart index bbe8d81..46067df 100644 --- a/lib/widgets/bottom_navigation/bottom_navigation.dart +++ b/lib/widgets/bottom_navigation/bottom_navigation.dart @@ -33,7 +33,7 @@ class BottomNavigation extends StatelessWidget { ), appState.isAuthenticated // ? BottomNavItem(icon: AppAssets.toDoBottom, label: LocaleKeys.todoList.tr(context: context)) - ? BottomNavItem(icon: AppAssets.symptomCheckerBottomIcon, fillIcon: AppAssets.symptomCheckerBottomFillIcon, label: "Symptoms") + ? BottomNavItem(icon: AppAssets.symptomCheckerBottomIcon, fillIcon: AppAssets.symptomCheckerBottomFillIcon, label: LocaleKeys.symptoms.tr(context: context)) : BottomNavItem(icon: AppAssets.news, fillIcon: AppAssets.newsFill, label: LocaleKeys.news.tr()), BottomNavItem(icon: AppAssets.servicesBottom, fillIcon: AppAssets.servicesBottomFill, label: LocaleKeys.services2.tr(context: context)), ]; diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart index fb51f28..515d1f7 100644 --- a/lib/widgets/common_bottom_sheet.dart +++ b/lib/widgets/common_bottom_sheet.dart @@ -183,6 +183,7 @@ void showCommonBottomSheetWithoutHeight( isScrollControlled: true, showDragHandle: false, isDismissible: isDismissible, + enableDrag: isDismissible, backgroundColor: backgroundColor, useSafeArea: useSafeArea, builder: (BuildContext context) { diff --git a/pubspec.yaml b/pubspec.yaml index 19acdf3..01c155b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: hmg_patient_app_new description: "New HMG Patient App" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.0.0+1 +version: 0.0.1+3 environment: sdk: ">=3.6.0 <4.0.0" @@ -67,6 +67,7 @@ dependencies: equatable: ^2.0.7 google_api_availability: ^5.0.1 firebase_analytics: ^11.5.1 + firebase_crashlytics: ^4.3.8 jiffy: ^6.4.3 hijri_gregorian_calendar: ^0.1.1 sms_otp_auto_verify: ^2.2.0 @@ -83,6 +84,7 @@ dependencies: open_filex: ^4.7.0 flutter_swiper_view: ^1.1.8 flutter_callkit_incoming: ^3.0.0 + in_app_update: ^4.2.5 # device_preview: ^1.3.1 location: ^8.0.1