Merge branch 'refs/heads/master' into fatima

# Conflicts:
#	assets/langs/ar-SA.json
#	lib/generated/locale_keys.g.dart
fatima
Fatimah.Alshammari 5 days ago
commit 46c8fbf0f6

@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgaPetsOq3tqUlswBN
BFUWIIdEg4dcTCGRUKbAEx8ViFygCgYIKoZIzj0DAQehRANCAAS6IKkZ4tCeBlN6
DtXiBekCiIbgHxWk8AWppP0H3mJ+I2s8cIEaquL4/yeLDcHzAHf8tHcYhF/TvggT
nc30yDLv
-----END PRIVATE KEY-----

@ -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"}}]}

@ -1,74 +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"}}]}
"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"
}
}
]
}

@ -18,12 +18,14 @@ if (keystorePropertiesFile.exists()) {
} }
android { android {
namespace = "com.ejada.hmg" // namespace = "com.ejada.hmg"
namespace = "com.cloudsolutions.HMGPatientApp"
compileSdk = 36 compileSdk = 36
ndkVersion = "28.2.13676358" ndkVersion = "28.2.13676358"
defaultConfig { defaultConfig {
applicationId = "com.ejada.hmg" // applicationId = "com.ejada.hmg"
applicationId = "com.cloudsolutions.HMGPatientApp"
// minSdk = 24 // minSdk = 24
minSdk = 26 minSdk = 26
targetSdk = 36 targetSdk = 36

@ -3,9 +3,45 @@
"project_number": "815750722565", "project_number": "815750722565",
"firebase_url": "https://api-project-815750722565.firebaseio.com", "firebase_url": "https://api-project-815750722565.firebaseio.com",
"project_id": "api-project-815750722565", "project_id": "api-project-815750722565",
"storage_bucket": "api-project-815750722565.appspot.com" "storage_bucket": "api-project-815750722565.firebasestorage.app"
}, },
"client": [ "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": { "client_info": {
"mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063",

Binary file not shown.

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="com.ejada.hmg"> package="com.cloudsolutions.HMGPatientApp">
<!-- <!--
io.flutter.app.FlutterApplication is an android.app.Application that io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method. calls FlutterMain.startInitialization(this); in its onCreate method.
@ -129,21 +129,21 @@
android:name=".Application" android:name=".Application"
android:allowBackup="false" android:allowBackup="false"
android:icon="@mipmap/ic_launcher_local" android:icon="@mipmap/ic_launcher_local"
android:label="Dr. Alhabib" android:label="Dr. Alhabib Beta"
android:screenOrientation="sensorPortrait" android:screenOrientation="sensorPortrait"
android:showOnLockScreen="true" android:showOnLockScreen="true"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
tools:replace="android:label"> tools:replace="android:label">
<activity <!-- <activity-->
android:name="com.cloud.hmg_patient_app.whatsapp.WhatsAppCodeActivity" <!-- android:name="com.cloud.hmg_patient_app.whatsapp.WhatsAppCodeActivity"-->
android:exported="true" <!-- android:exported="true"-->
android:enabled="true" <!-- android:enabled="true"-->
android:launchMode="standard" <!-- android:launchMode="standard"-->
> <!-- >-->
<intent-filter> <!-- <intent-filter>-->
<action android:name="com.whatsapp.otp.OTP_RETRIEVED" /> <!-- <action android:name="com.whatsapp.otp.OTP_RETRIEVED" />-->
</intent-filter> <!-- </intent-filter>-->
</activity> <!-- </activity>-->
<meta-data <meta-data
android:name="push_kit_auto_init_enabled" android:name="push_kit_auto_init_enabled"
@ -199,10 +199,10 @@
<!-- </intent-filter> --> <!-- </intent-filter> -->
<!-- </receiver> --> <!-- </receiver> -->
<!-- Geofencing --> <!-- Geofencing -->
<service <!-- <service-->
android:name=".geofence.intent_receivers.GeofenceTransitionsJobIntentService" <!-- android:name=".geofence.intent_receivers.GeofenceTransitionsJobIntentService"-->
android:exported="true" <!-- android:exported="true"-->
android:permission="android.permission.BIND_JOB_SERVICE" /> <!-- android:permission="android.permission.BIND_JOB_SERVICE" />-->
<!-- <receiver--> <!-- <receiver-->
<!-- android:name=".geofence.intent_receivers.GeofenceBroadcastReceiver"--> <!-- android:name=".geofence.intent_receivers.GeofenceBroadcastReceiver"-->

@ -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)
// }
//}

@ -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<out String>,
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()
}
}

@ -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<String, Any>?
Log.d("TAG", "configureFlutterEngine: $args")
println("args")
args?.let {
PenguinView(
mainActivity,
100,
args,
flutterEngine.dartExecutor.binaryMessenger,
activity = mainActivity,
channel
)
}
}
else -> {
result.notImplemented()
}
}
}
}
}

@ -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<Integer> callable = () -> {
SharedPreferences preferences = getPreferences(context);
return preferences.getInt(key, -1);
};
Future<Integer> 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<String> callable = () -> {
SharedPreferences preferences = getPreferences(context);
return preferences.getString(key, defValue);
};
Future<String> 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<Boolean> callable = () -> {
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(key, defValue);
};
Future<Boolean> 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
}
}

@ -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);
}
}
}

@ -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
);
}
}

@ -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;
}
}
}

@ -1,28 +0,0 @@
package com.ejada.hmg.PermissionManager
import android.Manifest
import android.os.Build
object PermissionHelper {
fun getRequiredPermissions(): Array<String> {
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()
}
}

@ -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<out String>, grantResults: IntArray) {
if (this.requestCode == requestCode) {
val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
if (allGranted) {
listener.onPermissionGranted()
} else {
listener.onPermissionDenied()
}
}
}
}

@ -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)
}
}

@ -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");
}

@ -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<ResponseBody> = ApiController.getInstance(mContext)
.apiMethods
.getToken(postToken)
// Enqueue the call for asynchronous execution
purposesCall.enqueue(object : Callback<ResponseBody?> {
override fun onResponse(
call: Call<ResponseBody?>,
response: Response<ResponseBody?>
) {
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<ResponseBody?>, t: Throwable) {
apiTokenCallBack.onGetByRefIDError(t.message)
}
})
} catch (error: Exception) {
apiTokenCallBack.onGetByRefIDError("Exception during API call: $error")
}
}
}

@ -1,376 +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<String, Any>,
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)
}
/**
* 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<String, Any?> = 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<Double>?) {
TODO("Not yet implemented")
}
override fun onLocationMessage(locationMessage: LocationMessage?) {
TODO("Not yet implemented")
}
}

@ -3,9 +3,45 @@
"project_number": "815750722565", "project_number": "815750722565",
"firebase_url": "https://api-project-815750722565.firebaseio.com", "firebase_url": "https://api-project-815750722565.firebaseio.com",
"project_id": "api-project-815750722565", "project_id": "api-project-815750722565",
"storage_bucket": "api-project-815750722565.appspot.com" "storage_bucket": "api-project-815750722565.firebasestorage.app"
}, },
"client": [ "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": { "client_info": {
"mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063",

@ -19,6 +19,9 @@ pluginManagement {
plugins { plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("dev.flutter.flutter-plugin-loader") version "1.0.0"
// id("com.android.application") version "8.9.3" apply false // 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("com.android.application") version "8.9.3" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false
} }

@ -1,767 +1 @@
{ {"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":[]}
"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": []
}

@ -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": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 224 KiB

@ -0,0 +1,19 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.4375 0.9375C14.5976 0.9375 14.7363 1.04846 14.7715 1.20465L14.9472 1.98451C15.0671 2.51701 15.483 2.93285 16.0155 3.05281L16.7954 3.22848C16.9515 3.26366 17.0625 3.40239 17.0625 3.5625C17.0625 3.72261 16.9515 3.86134 16.7954 3.89652L16.0155 4.07219C15.483 4.19215 15.0671 4.60799 14.9472 5.14049L14.7715 5.92035C14.7363 6.07654 14.5976 6.1875 14.4375 6.1875C14.2774 6.1875 14.1387 6.07654 14.1035 5.92035L13.9278 5.14049C13.8079 4.60799 13.392 4.19215 12.8595 4.07219L12.0796 3.89652C11.9235 3.86134 11.8125 3.72261 11.8125 3.5625C11.8125 3.40239 11.9235 3.26366 12.0796 3.22848L12.8595 3.05281C13.392 2.93285 13.8079 2.51701 13.9278 1.98451L14.1035 1.20465C14.1387 1.04846 14.2774 0.9375 14.4375 0.9375Z" fill="url(#paint0_linear_9523_4592)"/>
<path d="M9 1.6875C9.31066 1.6875 9.5625 1.93934 9.5625 2.25C9.5625 3.75456 10.3204 5.3062 11.5071 6.49288C12.6938 7.67956 14.2454 8.4375 15.75 8.4375C16.0607 8.4375 16.3125 8.68934 16.3125 9C16.3125 9.31066 16.0607 9.5625 15.75 9.5625C14.2454 9.5625 12.6938 10.3204 11.5071 11.5071C10.3204 12.6938 9.5625 14.2454 9.5625 15.75C9.5625 16.0607 9.31066 16.3125 9 16.3125C8.68934 16.3125 8.4375 16.0607 8.4375 15.75C8.4375 14.2454 7.67956 12.6938 6.49288 11.5071C5.3062 10.3204 3.75456 9.5625 2.25 9.5625C1.93934 9.5625 1.6875 9.31066 1.6875 9C1.6875 8.68934 1.93934 8.4375 2.25 8.4375C3.75456 8.4375 5.3062 7.67956 6.49288 6.49288C7.67956 5.3062 8.4375 3.75456 8.4375 2.25C8.4375 1.93934 8.68934 1.6875 9 1.6875Z" fill="url(#paint1_linear_9523_4592)"/>
<path d="M3.89652 12.0796C3.86134 11.9235 3.72261 11.8125 3.5625 11.8125C3.40239 11.8125 3.26366 11.9235 3.22848 12.0796L3.05281 12.8595C2.93285 13.392 2.51701 13.8079 1.98451 13.9278L1.20465 14.1035C1.04846 14.1387 0.9375 14.2774 0.9375 14.4375C0.9375 14.5976 1.04846 14.7363 1.20465 14.7715L1.98451 14.9472C2.51701 15.0671 2.93285 15.483 3.05281 16.0155L3.22848 16.7954C3.26366 16.9515 3.40239 17.0625 3.5625 17.0625C3.72261 17.0625 3.86134 16.9515 3.89652 16.7954L4.07219 16.0155C4.19215 15.483 4.60799 15.0671 5.14049 14.9472L5.92035 14.7715C6.07654 14.7363 6.1875 14.5976 6.1875 14.4375C6.1875 14.2774 6.07654 14.1387 5.92035 14.1035L5.14049 13.9278C4.60799 13.8079 4.19215 13.392 4.07219 12.8595L3.89652 12.0796Z" fill="url(#paint2_linear_9523_4592)"/>
<defs>
<linearGradient id="paint0_linear_9523_4592" x1="9" y1="0.9375" x2="9" y2="17.0625" gradientUnits="userSpaceOnUse">
<stop stop-color="#8A38F5"/>
<stop offset="1" stop-color="#E20BBB"/>
</linearGradient>
<linearGradient id="paint1_linear_9523_4592" x1="9" y1="0.9375" x2="9" y2="17.0625" gradientUnits="userSpaceOnUse">
<stop stop-color="#8A38F5"/>
<stop offset="1" stop-color="#E20BBB"/>
</linearGradient>
<linearGradient id="paint2_linear_9523_4592" x1="9" y1="0.9375" x2="9" y2="17.0625" gradientUnits="userSpaceOnUse">
<stop stop-color="#8A38F5"/>
<stop offset="1" stop-color="#E20BBB"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.03901 1.3125L8.961 1.3125C7.31466 1.31249 6.02729 1.31249 5.0234 1.43396C4.00096 1.55768 3.18715 1.81548 2.54214 2.39599C1.88865 2.98413 1.59058 3.73922 1.4491 4.68627C1.31247 5.60088 1.31249 6.769 1.3125 8.24081L1.3125 9.75917C1.31249 11.231 1.31247 12.3991 1.4491 13.3137C1.59058 14.2608 1.88865 15.0159 2.54214 15.604C3.18715 16.1845 4.00096 16.4423 5.0234 16.566C6.02729 16.6875 7.31465 16.6875 8.96099 16.6875H9.03901C10.6854 16.6875 11.9727 16.6875 12.9766 16.566C13.999 16.4423 14.8129 16.1845 15.4579 15.604C16.1114 15.0159 16.4094 14.2608 16.5509 13.3137C16.6875 12.3991 16.6875 11.231 16.6875 9.75919V8.24081C16.6875 6.76899 16.6875 5.60087 16.5509 4.68627C16.4094 3.73922 16.1114 2.98413 15.4579 2.39599C14.8129 1.81548 13.999 1.55768 12.9766 1.43396C11.9727 1.31249 10.6853 1.31249 9.03901 1.3125ZM12.5625 4.5C12.5625 4.18934 12.3107 3.9375 12 3.9375C11.6893 3.9375 11.4375 4.18934 11.4375 4.5L11.4375 5.4375H10.5C10.1893 5.4375 9.9375 5.68934 9.9375 6C9.9375 6.31066 10.1893 6.5625 10.5 6.5625H11.4375V7.5C11.4375 7.81066 11.6893 8.0625 12 8.0625C12.3107 8.0625 12.5625 7.81066 12.5625 7.5V6.5625H13.5C13.8107 6.5625 14.0625 6.31066 14.0625 6C14.0625 5.68934 13.8107 5.4375 13.5 5.4375H12.5625L12.5625 4.5ZM9.9375 13.125C9.9375 12.8143 10.1893 12.5625 10.5 12.5625L13.5 12.5625C13.8107 12.5625 14.0625 12.8143 14.0625 13.125C14.0625 13.4357 13.8107 13.6875 13.5 13.6875L10.5 13.6875C10.1893 13.6875 9.9375 13.4357 9.9375 13.125ZM10.5 10.3125C10.1893 10.3125 9.9375 10.5643 9.9375 10.875C9.9375 11.1857 10.1893 11.4375 10.5 11.4375L13.5 11.4375C13.8107 11.4375 14.0625 11.1857 14.0625 10.875C14.0625 10.5643 13.8107 10.3125 13.5 10.3125L10.5 10.3125ZM7.89775 10.1023C8.11742 10.3219 8.11742 10.6781 7.89775 10.8977L6.983 11.8125L7.89775 12.7273C8.11742 12.9469 8.11742 13.3031 7.89775 13.5227C7.67808 13.7424 7.32192 13.7424 7.10225 13.5227L6.1875 12.608L5.27275 13.5227C5.05308 13.7424 4.69692 13.7424 4.47725 13.5227C4.25758 13.3031 4.25758 12.9469 4.47725 12.7273L5.392 11.8125L4.47725 10.8977C4.25758 10.6781 4.25758 10.3219 4.47725 10.1023C4.69692 9.88258 5.05308 9.88258 5.27275 10.1023L6.1875 11.017L7.10225 10.1023C7.32192 9.88258 7.67808 9.88258 7.89775 10.1023ZM4.5 5.4375C4.18934 5.4375 3.9375 5.68934 3.9375 6C3.9375 6.31066 4.18934 6.5625 4.5 6.5625L7.5 6.5625C7.81066 6.5625 8.0625 6.31066 8.0625 6C8.0625 5.68934 7.81066 5.4375 7.5 5.4375L4.5 5.4375Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.56265 5.25C9.56265 4.93934 9.31081 4.6875 9.00015 4.6875C8.68949 4.6875 8.43765 4.93934 8.43765 5.25L8.43765 6.75C8.43765 7.06066 8.68949 7.3125 9.00015 7.3125C9.31081 7.3125 9.56265 7.06066 9.56265 6.75V5.25Z" fill="#2E3039"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.9988 0.9375C7.73784 0.9375 6.71271 1.36345 5.81862 1.82666C5.54843 1.96664 5.29743 2.1051 5.05759 2.23741C4.47075 2.56113 3.95062 2.84805 3.37945 3.03029L3.36037 3.03638C3.02491 3.14341 2.74681 3.23213 2.53612 3.3147C2.33781 3.39241 2.10212 3.4989 1.9349 3.68475C1.78469 3.85169 1.70752 4.0391 1.65635 4.21837C1.6099 4.38111 1.57434 4.57846 1.53625 4.78983L1.53211 4.81279C0.603657 9.96205 2.6339 14.8403 7.59174 16.7384L7.61642 16.7479C8.10374 16.9345 8.43795 17.0625 9.00126 17.0625C9.56458 17.0625 9.89877 16.9345 10.3861 16.7479L10.4107 16.7384C15.3684 14.8402 17.3966 9.96183 16.4679 4.81275L16.4638 4.78975C16.4257 4.57837 16.3901 4.38099 16.3437 4.21825C16.2925 4.03897 16.2153 3.85153 16.065 3.68458C15.8978 3.49874 15.6621 3.39228 15.4638 3.31459C15.2531 3.23206 14.975 3.14338 14.6395 3.0364L14.6205 3.03033C14.049 2.84808 13.5285 2.56109 12.9412 2.23732C12.7012 2.10503 12.4501 1.96659 12.1799 1.82665C11.2853 1.36346 10.2598 0.9375 8.9988 0.9375ZM5.69431 3.17268C5.91405 3.05144 6.12837 2.9332 6.33612 2.82557C7.16979 2.39367 8.00392 2.0625 8.9988 2.0625C9.99375 2.0625 10.8283 2.39372 11.6626 2.82567C11.8704 2.9333 12.0848 3.05153 12.3047 3.17275C12.9278 3.51634 13.5945 3.88397 14.2787 4.10215C14.638 4.21674 14.8809 4.29449 15.0535 4.3621C15.1671 4.4066 15.2164 4.43472 15.2324 4.44405C15.2383 4.45602 15.2486 4.48074 15.2619 4.52707C15.291 4.62916 15.3171 4.77013 15.3608 5.01244C16.2166 9.75713 14.3493 14.0257 10.0085 15.6878C9.5102 15.8786 9.34656 15.9375 9.00125 15.9375C8.65594 15.9375 8.49229 15.8786 7.99399 15.6878C3.65273 14.0257 1.78378 9.75694 2.63926 5.01241C2.68294 4.77015 2.70902 4.62921 2.73815 4.52713C2.75137 4.48082 2.7617 4.45611 2.76765 4.44414C2.78356 4.4348 2.83295 4.40667 2.94657 4.36215C3.11916 4.29452 3.36205 4.21672 3.72141 4.10206C4.40531 3.88385 5.0716 3.51625 5.69431 3.17268ZM15.2282 4.43645C15.2272 4.43489 15.2267 4.43428 15.2267 4.43436C15.2267 4.43441 15.2269 4.43474 15.2273 4.43527C15.2275 4.43559 15.2278 4.43599 15.2282 4.43645Z" fill="#2E3039"/>
<path d="M2.77331 4.43444C2.77332 4.43453 2.77283 4.43532 2.7718 4.43654M3.37945 3.03029C3.95062 2.84805 4.47075 2.56113 5.05759 2.23741C5.29743 2.1051 5.54843 1.96664 5.81862 1.82666C6.71271 1.36345 7.73784 0.9375 8.9988 0.9375C10.2598 0.9375 11.2853 1.36346 12.1799 1.82665C12.4501 1.96659 12.7012 2.10503 12.9412 2.23732C13.5285 2.56109 14.049 2.84808 14.6205 3.03033L14.6395 3.0364C14.975 3.14338 15.2531 3.23206 15.4638 3.31459C15.6621 3.39228 15.8978 3.49874 16.065 3.68458C16.2153 3.85153 16.2925 4.03897 16.3437 4.21825C16.3901 4.38099 16.4257 4.57837 16.4638 4.78975L16.4679 4.81275C17.3966 9.96183 15.3684 14.8402 10.4107 16.7384L10.3861 16.7479C9.89877 16.9345 9.56458 17.0625 9.00126 17.0625C8.43795 17.0625 8.10374 16.9345 7.61642 16.7479L7.59174 16.7384C2.6339 14.8403 0.603657 9.96205 1.53211 4.81279L1.53625 4.78983C1.57434 4.57846 1.6099 4.38111 1.65635 4.21837C1.70752 4.0391 1.78469 3.85169 1.9349 3.68475C2.10212 3.4989 2.33781 3.39241 2.53612 3.3147C2.74681 3.23213 3.02491 3.14341 3.36037 3.03638L3.37945 3.03029ZM3.37945 3.03029L3.55043 3.56618M5.69431 3.17268C5.91405 3.05144 6.12837 2.9332 6.33612 2.82557C7.16979 2.39367 8.00392 2.0625 8.9988 2.0625C9.99375 2.0625 10.8283 2.39372 11.6626 2.82567C11.8704 2.9333 12.0848 3.05153 12.3047 3.17275C12.9278 3.51634 13.5945 3.88397 14.2787 4.10215C14.638 4.21674 14.8809 4.29449 15.0535 4.3621C15.1671 4.4066 15.2164 4.43472 15.2324 4.44405C15.2383 4.45602 15.2486 4.48074 15.2619 4.52707C15.291 4.62916 15.3171 4.77013 15.3608 5.01244C16.2166 9.75713 14.3493 14.0257 10.0085 15.6878C9.5102 15.8786 9.34656 15.9375 9.00125 15.9375C8.65594 15.9375 8.49229 15.8786 7.99399 15.6878C3.65273 14.0257 1.78378 9.75694 2.63926 5.01241C2.68294 4.77015 2.70902 4.62921 2.73815 4.52713C2.75137 4.48082 2.7617 4.45611 2.76765 4.44414C2.78356 4.4348 2.83295 4.40667 2.94657 4.36215C3.11916 4.29452 3.36205 4.21672 3.72141 4.10206C4.40531 3.88385 5.0716 3.51625 5.69431 3.17268ZM15.2282 4.43645C15.2272 4.43489 15.2267 4.43428 15.2267 4.43436C15.2267 4.43441 15.2269 4.43474 15.2273 4.43527C15.2275 4.43559 15.2278 4.43599 15.2282 4.43645ZM9.56265 5.25C9.56265 4.93934 9.31081 4.6875 9.00015 4.6875C8.68949 4.6875 8.43765 4.93934 8.43765 5.25L8.43765 6.75C8.43765 7.06066 8.68949 7.3125 9.00015 7.3125C9.31081 7.3125 9.56265 7.06066 9.56265 6.75V5.25Z" stroke="#2E3039" stroke-width="0.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.9922 16C10.9922 15.4477 11.4399 15 11.9922 15H12.0012C12.5535 15 13.0012 15.4477 13.0012 16C13.0012 16.5523 12.5535 17 12.0012 17H11.9922C11.4399 17 10.9922 16.5523 10.9922 16Z" fill="#ED1C2B"/>
<path d="M11.25 13C11.25 13.4142 11.5858 13.75 12 13.75C12.4142 13.75 12.75 13.4142 12.75 13L12.75 9C12.75 8.58579 12.4142 8.25 12 8.25C11.5858 8.25 11.25 8.58579 11.25 9L11.25 13Z" fill="#ED1C2B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.362 2.015C11.4264 1.66167 12.5736 1.66167 13.638 2.015C14.6981 2.36687 15.5304 3.20141 16.3665 4.37395C17.1999 5.5426 18.1208 7.17206 19.3078 9.2725L19.3544 9.35496C20.5417 11.4557 21.4625 13.0851 22.0364 14.4065C22.613 15.7343 22.9002 16.8807 22.6711 17.9821C22.4403 19.0911 21.8714 20.0995 21.0428 20.8617C20.2162 21.622 19.0907 21.9428 17.6736 22.0968C16.2645 22.25 14.4212 22.25 12.0488 22.25H11.9513C9.57882 22.25 7.73554 22.25 6.32642 22.0968C4.90927 21.9428 3.78379 21.622 2.95722 20.8617C2.12862 20.0995 1.55968 19.0911 1.32895 17.9821C1.0998 16.8807 1.387 15.7343 1.96365 14.4065C2.53752 13.0851 3.45835 11.4557 4.64558 9.35495L4.69218 9.2725C5.87921 7.17207 6.80008 5.5426 7.63347 4.37395C8.46963 3.20141 9.30194 2.36687 10.362 2.015ZM13.1655 3.43862C12.4078 3.18713 11.5922 3.18713 10.8345 3.43862C10.2386 3.63645 9.63943 4.1445 8.85474 5.24486C8.07275 6.34143 7.18998 7.90144 5.97466 10.0519C4.75941 12.2023 3.87825 13.7635 3.33951 15.004C2.79983 16.2467 2.66463 17.0379 2.7975 17.6766C2.96511 18.4821 3.37754 19.2102 3.97272 19.7577C4.44016 20.1877 5.16852 20.4621 6.48854 20.6056C7.80696 20.7489 9.56861 20.75 12 20.75C14.4314 20.75 16.193 20.7489 17.5115 20.6056C18.8315 20.4621 19.5599 20.1877 20.0273 19.7577C20.6225 19.2102 21.0349 18.4821 21.2025 17.6766C21.3354 17.0379 21.2002 16.2467 20.6605 15.004C20.1218 13.7635 19.2406 12.2023 18.0254 10.0519C16.81 7.90144 15.9273 6.34143 15.1453 5.24486C14.3606 4.1445 13.7615 3.63645 13.1655 3.43862Z" fill="#ED1C2B"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.729492 7.0013C0.729492 10.4646 3.53704 13.2721 7.00033 13.2721C10.4636 13.2721 13.2712 10.4646 13.2712 7.0013C13.2712 3.53802 10.4636 0.730469 7.00033 0.730469C3.53704 0.730469 0.729492 3.53802 0.729492 7.0013ZM6.81476 6.43387C6.95887 6.45324 7.15822 6.50511 7.32738 6.67427C7.49654 6.84343 7.5484 7.04278 7.56778 7.18689C7.58383 7.30627 7.58374 7.44509 7.58367 7.56168L7.58366 9.91799C7.58366 10.2402 7.32249 10.5013 7.00033 10.5013C6.67816 10.5013 6.41699 10.2402 6.41699 9.91799L6.41699 7.58466C6.09483 7.58466 5.83366 7.32349 5.83366 7.00132C5.83366 6.67916 6.09483 6.41799 6.41699 6.41799L6.43997 6.41798C6.55656 6.41791 6.69537 6.41782 6.81476 6.43387ZM6.99767 4.08464C6.67694 4.08464 6.41694 4.3458 6.41694 4.66797C6.41694 4.99014 6.67694 5.2513 6.99767 5.2513H7.00288C7.32361 5.2513 7.58361 4.99014 7.58361 4.66797C7.58361 4.3458 7.32361 4.08464 7.00288 4.08464H6.99767Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="8" fill="#EFEFF0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.312 9.93059C23.9686 9.74998 22.2479 9.74999 20.0572 9.75H19.9428C17.7521 9.74999 16.0314 9.74998 14.688 9.93059C13.3114 10.1157 12.2191 10.5027 11.3609 11.3609C10.5027 12.2191 10.1157 13.3114 9.93059 14.688C9.74998 16.0314 9.74999 17.7521 9.75 19.9428V20.0572C9.74999 22.2479 9.74998 23.9686 9.93059 25.312C10.1157 26.6886 10.5027 27.7809 11.3609 28.6391C12.2191 29.4973 13.3114 29.8843 14.688 30.0694C16.0314 30.25 17.7521 30.25 19.9428 30.25H19.9428H20.0572H20.0572C22.2479 30.25 23.9686 30.25 25.312 30.0694C26.6886 29.8843 27.7809 29.4973 28.6391 28.6391C29.4973 27.7809 29.8843 26.6886 30.0694 25.312C30.25 23.9686 30.25 22.2479 30.25 20.0572V20.0572V19.9428V19.9428C30.25 17.7521 30.25 16.0314 30.0694 14.688C29.8843 13.3114 29.4973 12.2191 28.6391 11.3609C27.7809 10.5027 26.6886 10.1157 25.312 9.93059ZM20.75 16C20.75 15.5858 20.4142 15.25 20 15.25C19.5858 15.25 19.25 15.5858 19.25 16L19.25 24C19.25 24.4142 19.5858 24.75 20 24.75C20.4142 24.75 20.75 24.4142 20.75 24L20.75 16ZM17.75 18C17.75 17.5858 17.4142 17.25 17 17.25C16.5858 17.25 16.25 17.5858 16.25 18L16.25 22C16.25 22.4142 16.5858 22.75 17 22.75C17.4142 22.75 17.75 22.4142 17.75 22L17.75 18ZM23.75 18C23.75 17.5858 23.4142 17.25 23 17.25C22.5858 17.25 22.25 17.5858 22.25 18L22.25 22C22.25 22.4142 22.5858 22.75 23 22.75C23.4142 22.75 23.75 22.4142 23.75 22L23.75 18ZM14.75 19C14.75 18.5858 14.4142 18.25 14 18.25C13.5858 18.25 13.25 18.5858 13.25 19L13.25 21C13.25 21.4142 13.5858 21.75 14 21.75C14.4142 21.75 14.75 21.4142 14.75 21V19ZM26.75 19C26.75 18.5858 26.4142 18.25 26 18.25C25.5858 18.25 25.25 18.5858 25.25 19L25.25 21C25.25 21.4142 25.5858 21.75 26 21.75C26.4142 21.75 26.75 21.4142 26.75 21V19Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="8" fill="#EFEFF0"/>
<path d="M13.3173 9.28657C13.8839 9.40369 14.3352 9.78443 14.6156 10.2875L15.5088 11.8899C15.8379 12.4801 16.1147 12.9768 16.2955 13.4086C16.4873 13.8666 16.6013 14.3182 16.5492 14.8176C16.4971 15.317 16.2925 15.7354 16.0103 16.144C15.7443 16.5292 15.3709 16.958 14.9272 17.4677L13.6142 18.9759C13.3789 19.2461 13.2612 19.3812 13.2505 19.5501C13.2397 19.719 13.3362 19.8633 13.529 20.1518C15.1726 22.6109 17.3877 24.8268 19.8488 26.4718C20.1374 26.6647 20.2816 26.7611 20.4505 26.7503C20.6194 26.7396 20.7546 26.6219 21.0248 26.3866L22.5331 25.0736C23.0427 24.6299 23.4716 24.2565 23.8568 23.9905C24.2653 23.7083 24.6838 23.5036 25.1831 23.4516C25.6825 23.3995 26.1342 23.5134 26.5922 23.7052C27.0239 23.886 27.5206 24.1629 28.1107 24.4918L29.7133 25.3851C30.2163 25.6655 30.5971 26.1168 30.7142 26.6835C30.8325 27.2561 30.658 27.8316 30.2724 28.3047C28.8735 30.021 26.6322 31.1139 24.281 30.6396C22.8358 30.348 21.4098 29.8623 19.6851 28.8732C16.2197 26.8858 13.1126 23.777 11.1276 20.3157C10.1384 18.591 9.65272 17.165 9.36118 15.7197C8.88688 13.3685 9.97971 11.1272 11.6961 9.72833C12.1691 9.34279 12.7447 9.16822 13.3173 9.28657Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="8" fill="#EFEFF0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.072 11H16.928C15.3393 11 14.0461 10.9999 13.0263 11.1371C11.9623 11.2801 11.0474 11.5887 10.318 12.318C9.58869 13.0474 9.28011 13.9623 9.13706 15.0263C8.99995 16.0461 8.99997 17.3393 9 18.9279V21.072C8.99997 22.6607 8.99995 23.9539 9.13706 24.9737C9.28011 26.0377 9.58869 26.9527 10.318 27.682C11.0474 28.4113 11.9623 28.7199 13.0263 28.8629C14.0462 29.0001 15.3393 29 16.928 29H18.072C19.6607 29 20.9538 29.0001 21.9737 28.8629C23.0377 28.7199 23.9527 28.4113 24.682 27.682C25.3875 26.9764 25.6993 26.0972 25.8484 25.0773C26.3063 25.4374 26.7206 25.7408 27.0944 25.9666C27.7947 26.3896 28.6822 26.7439 29.5929 26.2925C30.4895 25.848 30.7673 24.9371 30.8829 24.1198C30.9991 23.2982 30.9991 22.1926 30.999 20.8645V19.1382C30.9991 17.8101 30.9991 16.7045 30.8829 15.8828C30.7673 15.0655 30.4895 14.1546 29.5929 13.7102C28.6822 13.2587 27.7947 13.613 27.0944 14.0361C26.7207 14.2619 26.3066 14.5651 25.8488 14.925C25.6998 13.9042 25.3881 13.0241 24.682 12.318C23.9527 11.5887 23.0377 11.2801 21.9737 11.1371C20.9539 10.9999 19.6607 11 18.072 11ZM25.9943 17.3825C26 17.8628 26 18.3777 26 18.928V21.072C26 21.6233 26 22.1391 25.9943 22.6201C26.9515 23.4089 27.6126 23.943 28.1285 24.2547C28.3999 24.4186 28.5637 24.4778 28.6531 24.4955C28.6728 24.4994 28.6863 24.5007 28.6942 24.5012C28.6982 24.5014 28.7027 24.5013 28.7027 24.5013L28.7047 24.5005C28.7064 24.4997 28.7078 24.4988 28.7087 24.4982C28.7101 24.4972 28.7108 24.4966 28.7108 24.4966C28.7136 24.4936 28.7286 24.4774 28.7499 24.4358C28.7977 24.3422 28.8567 24.1641 28.9026 23.8397C28.9966 23.1754 28.999 22.2135 28.999 20.7832V19.2194C28.999 17.7892 28.9966 16.8273 28.9026 16.1629C28.8567 15.8385 28.7977 15.6604 28.7499 15.5669C28.7286 15.5252 28.714 15.5095 28.7112 15.5065C28.7112 15.5065 28.709 15.5043 28.7047 15.5021L28.7032 15.5014C28.7032 15.5014 28.6982 15.5013 28.6942 15.5015C28.6863 15.5019 28.6728 15.5032 28.6531 15.5071C28.5637 15.5248 28.3999 15.584 28.1285 15.748C27.6126 16.0597 26.9515 16.5938 25.9943 17.3825ZM18 16C18 15.4477 18.4477 15 19 15L21 15C21.5523 15 22 15.4477 22 16C22 16.5523 21.5523 17 21 17L19 17C18.4477 17 18 16.5523 18 16Z" fill="#2E3039"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@ -945,6 +945,7 @@
"offline": "غير متصل", "offline": "غير متصل",
"videoCall": "مكالمة فيديو", "videoCall": "مكالمة فيديو",
"liveVideoCallWithHMGDoctors": "مكالمة فيديو مباشرة مع أطباء مجموعة الحبيب الطبية", "liveVideoCallWithHMGDoctors": "مكالمة فيديو مباشرة مع أطباء مجموعة الحبيب الطبية",
"liveAudioCallWithHMGDoctors": "مكالمة صوتية مباشرة مع أطباء مجموعة الحبيب الطبية",
"audioCall": "مكالمة صوتية", "audioCall": "مكالمة صوتية",
"phoneCall": "مكالمة هاتفية", "phoneCall": "مكالمة هاتفية",
"livePhoneCallWithHMGDoctors": "مكالمة هاتفية مباشرة مع أطباء مجموعة الحبيب الطبية", "livePhoneCallWithHMGDoctors": "مكالمة هاتفية مباشرة مع أطباء مجموعة الحبيب الطبية",
@ -1522,7 +1523,64 @@
"trackerAndOthers": "المتتبع وأخرى", "trackerAndOthers": "المتتبع وأخرى",
"bmi": "مؤشر كتلة الجسم", "bmi": "مؤشر كتلة الجسم",
"yesPleaseINeedHelp": "نعم، من فضلك أريد المساعدة", "yesPleaseINeedHelp": "نعم، من فضلك أريد المساعدة",
"noThanksIKnowTheClinic": "لا شكراً، أعرف العيادة", "aiOverView": "AI ملخص",
"generateAiAnalysis": "قم بإجراء تحليل لهذا الطلب AI",
"aiAnalysis": "AI تحليل",
"prediction": "تنبؤ",
"prevention": "وقاية",
"disclaimer": "تنصل",
"thisAboveInfo": "المعلومات المذكورة أعلاه مُولّدة بواسطة AI بناءً على نتائج تحاليلك المخبرية، وهي لأغراض إعلامية فقط. لا ينبغي اعتبارها تشخيصًا طبيًا أو خطة علاجية. استشر طبيبك دائمًا للحصول على نصيحة طبية مُخصصة قبل اتخاذ أي قرارات تتعلق بصحتك.",
"aiDisclaimer": "سيتم مشاركة بيانات نتائج تحاليلك المخبرية بشكل آمن مع خدمة الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في تقديم رؤى صحية مُخصصة. هل ترغب في المتابعة؟",
"consent": "موافقة",
"bmiNormalDescription": "مؤشر كتلة جسمك ضمن المعدل الصحي. استمر في اتباع نظام غذائي متوازن، وممارسة النشاط البدني بانتظام، وإجراء الفحوصات الدورية للحفاظ على صحة جيدة. راقب أي تغييرات ملحوظة مع مرور الوقت.",
"bmiUnderweightDescription": "يشير مؤشر كتلة الجسم إلى أنك تعاني من نقص الوزن. لذا، يُنصح بزيادة السعرات الحرارية المتناولة من خلال تناول الأطعمة الغنية بالعناصر الغذائية، وممارسة تمارين المقاومة لبناء العضلات، واستشارة أخصائي رعاية صحية للتحقق من وجود أسباب كامنة.",
"bmiOverweightDescription": "يشير مؤشر كتلة الجسم إلى زيادة الوزن. لذا، يُنصح بالسعي إلى إنقاص الوزن تدريجياً وبشكل مستدام من خلال تقليل السعرات الحرارية بشكل معتدل، وممارسة النشاط البدني بانتظام، واختيار الأطعمة الصحية. استشر طبيبك قبل إجراء أي تغييرات جذرية في نمط حياتك.",
"caloriesMaintenanceDescription": "السعرات الحرارية اليومية المُقدَّرة للحفاظ على وزنك الحالي بناءً على مستوى نشاطك ومعدل الأيض لديك. استخدم هذه الكمية كخط أساس: زدها قليلاً لزيادة الكتلة العضلية، أو قللها قليلاً لإنقاص الوزن تدريجياً. تابع تقدمك وعدّل الخطة كل أسبوعين إلى أربعة أسابيع.",
"caloriesModerateDeficitDescription": "نظام غذائي معتدل لتقليل السعرات الحرارية مصمم لإنقاص الوزن بشكل ثابت ومستدام (عادةً من 0.25 إلى 0.5 كيلوغرام أسبوعيًا). يُنصح بدمجه مع تمارين المقاومة وتناول كمية كافية من البروتين للحفاظ على الكتلة العضلية. تجنب التخفيضات الحادة في السعرات الحرارية واستشر طبيبًا مختصًا إذا كنت تعاني من أي حالة صحية.",
"caloriesAggressiveDeficitDescription": "يؤدي خفض السعرات الحرارية بشكل كبير إلى فقدان الوزن بشكل أسرع، ولكنه قد يصعب الاستمرار عليه ويزيد من خطر نقص العناصر الغذائية والإرهاق وفقدان الكتلة العضلية. لا يُنصح باتباعه على المدى الطويل؛ استشر طبيبًا أو أخصائي تغذية قبل الاستمرار.",
"bodyFatEssentialDescription": "نسبة الدهون في جسمك ضمن النطاق الأساسي/الرياضي. هذا المستوى شائع لدى الرياضيين ويشير إلى انخفاض نسبة الدهون في الجسم. مع أن هذا قد يكون مثاليًا للأداء، تأكد من الحفاظ على تغذية سليمة ووظائف هرمونية متوازنة. استشر طبيبًا إذا شعرت بالتعب، أو واجهت مشاكل هرمونية، أو أي مخاوف صحية أخرى.",
"bodyFatFitnessDescription": "نسبة الدهون في جسمك ضمن النطاق الصحي. وهذا يدل على مستوى صحي من الدهون في الجسم يرتبط بلياقة بدنية جيدة. حافظ على نمط حياتك الحالي، بما في ذلك ممارسة الرياضة بانتظام واتباع نظام غذائي متوازن، للحفاظ على هذا المستوى الصحي.",
"bodyFatAverageDescription": "نسبة الدهون في جسمك ضمن المعدل الطبيعي/المقبول، وهي نسبة تُعتبر صحية لعموم الناس. لتحسين تكوين جسمك، يُنصح بممارسة تمارين القوة، وتمارين القلب والأوعية الدموية، واتباع نظام غذائي متوازن. ركّز على التغييرات التدريجية والمستدامة للحفاظ على صحتك على المدى الطويل.",
"bodyFatObeseDescription": "نسبة الدهون في جسمك أعلى من المعدل الصحي الموصى به. قد يزيد هذا من المخاطر الصحية، بما في ذلك أمراض القلب والأوعية الدموية، والسكري، ومشاكل المفاصل. يُنصح باستشارة طبيب أو أخصائي تغذية معتمد لوضع خطة علاجية شخصية تشمل التغذية المتوازنة، والنشاط البدني المنتظم، وتعديلات نمط الحياة لتحقيق إدارة مستدامة للوزن.",
"bmrNormalDescription": "معدل الأيض الأساسي لديك ضمن النطاق المتوقع لحالتك. معدل الأيض الأساسي هو الطاقة التي يحتاجها جسمك في حالة الراحة للحفاظ على وظائفه الحيوية (التنفس، الدورة الدموية، درجة الحرارة). استخدم هذه القيمة كأساس لتقدير إجمالي احتياجاتك اليومية من الطاقة من خلال تطبيق مُعامل النشاط. حافظ على نظام غذائي متوازن وممارسة النشاط البدني بانتظام لدعم صحة التمثيل الغذائي.",
"bmrLowDescription": "معدل الأيض الأساسي لديك أقل من المعدل الطبيعي لحالتك. تشمل الأسباب المحتملة انخفاض كتلة العضلات، أو تراجع التمثيل الغذائي المرتبط بالتقدم في السن، أو التكيف الأيضي الناتج عن تقييد السعرات الحرارية لفترة طويلة. يُنصح بالتركيز على تمارين المقاومة لبناء العضلات والحفاظ عليها، والتأكد من تناول كميات كافية من البروتين والمغذيات الدقيقة، واستشارة أخصائي رعاية صحية إذا كان هذا الأمر غير متوقع.",
"bmrHighDescription": "معدل الأيض الأساسي لديك أعلى من المتوسط \u200B\u200Bبالنسبة لحالتك. قد يعكس هذا زيادة في كتلة العضلات، أو صغر السن، أو ارتفاع معدل الأيض لديك بشكل طبيعي، مما يعني أنك تحرق طاقة أكبر أثناء الراحة. استخدم هذه المعلومات لتحديد احتياجاتك من السعرات الحرارية: احتياجات أعلى للحفاظ على الوزن أو بناء العضلات، ونقص معتدل في السعرات الحرارية لإنقاص الوزن. استشر طبيبك إذا لاحظت أي تغيرات سريعة غير مبررة.",
"ibwAtTargetDescription": "Your weight is at the ideal target. Maintain your current habits — balanced diet and regular activity — to keep this.",
"ibwBelowTargetDescription": "You are below the ideal weight by {kg} kg. Aim to gradually increase weight with a modest calorie surplus, nutrient-dense foods, and resistance training.",
"ibwAboveTargetDescription": "You are above the ideal weight by {kg} kg. Aim for a gradual, sustainable weight reduction through a moderate calorie deficit, increased activity, and balanced nutrition.",
"ibwCloseToRangeDescription": "Your weight is close to the ideal range. Maintain a balanced diet and regular activity; follow personalized advice from a healthcare professional if needed.",
"ibwUnderweightDescription": "You are below the ideal weight by {kg} kg. Focus on increasing calorie intake with nutrient-dense foods, prioritize protein and resistance training to build healthy mass, and consider consulting a healthcare professional.",
"ibwUnderweightGenericDescription": "You appear underweight compared to the ideal. Consider increasing calorie intake with nutrient-dense foods and resistance training; seek professional guidance if needed.",
"ibwOverweightDescription": "You are above the ideal weight by {kg} kg. Aim for a gradual, sustainable weight loss strategy — moderate calorie deficit, regular physical activity, and balanced nutrition. Consult a professional before major changes.",
"ibwOverweightGenericDescription": "You appear above the ideal weight. Consider a gradual, sustainable calorie deficit combined with activity and balanced nutrition; consult a professional if needed.",
"dietVeryLowCarbsDescription": "Very lowcarb (ketogenic) approach: minimal carbohydrates, higher fat and moderate protein. May support rapid weight loss and improved blood sugar control for some, but can be hard to sustain and may cause nutrient gaps. Monitor hydration/electrolytes and consult a professional for longterm use.",
"dietLowCarbsDescription": "Lowcarb, higherprotein plan: reduced carbohydrates with increased protein to support satiety and muscle maintenance. Helpful for weight management and glycemic control when balanced with vegetables and healthy fats. Ensure adequate fiber and micronutrients.",
"dietModerateCarbsDescription": "Moderate carbohydrate intake with balanced protein and fats: provides steady energy for daily activity and exercise while allowing flexibility. Suitable for many people aiming for sustainable weight management and performance.",
"dietUSDAGuidelinesDescription": "USDAbased balanced pattern: emphasizes fruits, vegetables, whole grains, lean proteins, and limited added sugars and saturated fats. Evidencebased framework for general health, nutrient adequacy, and chronic disease prevention.",
"dietZoneDietDescription": "Zone Diet (~40% carbs / 30% protein / 30% fat): emphasizes hormonal balance and portion control. May improve body composition and energy for some, but requires planning; personalize with a nutrition professional.",
"contextDependent": "يعتمد السياق",
"calculatedValue": "القيمة المحسوبة",
"calculationFormula": "صيغة الحساب",
"confirmYourLocation": "قم بتأكيد موقعك",
"confirmYourLocationDesc": "يرجى تأكيد موقعك الحالي لعرض الاتجاهات المناسبة.",
"insideHospital": "أنا داخل المستشفى",
"outsideHospital": "أنا خارج المستشفى",
"servicePriceList": "قائمة أسعار الخدمات",
"servicePriceListDesc": "توضح قائمة أسعار الخدمات أدناه رسوم الخدمات الصحية المقدمة للمرضى بنظام الدفع النقدي. أما فيما يتعلق بالخدمات المشمولة بالتأمين، فسيتم تطبيق التغطية التأمينية والتحقق من الأهلية واحتساب نسب التحمل وفقًا لشروط وثيقة التأمين وجدول المنافع المعتمد لكل شركة تأمين.",
"servicePriceListRights": "يحق للمريض الحصول على متابعة مجانية في غضون 14 يومًا من الزيارة الأولى",
"serviceName": "اسم الخدمة",
"noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.",
"noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.",
"unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة", "unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة",
"loadingAIAnalysis": "جارٍ تحليل نتائج المختبر، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.",
"symptoms": "أعراض",
"insuranceInActive": "التأمين غير نشط",
"insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.",
"updateAppNow": "تحديث التطبيق الآن",
"Dr": "الدكتور.",
"reschedulingAppo": "إعادة جدولة الموعد، يرجى الانتظار...",
"invalidEligibility": "لا يمكنك إجراء الدفع عبر الإنترنت لأنك غير مؤهل لاستخدام الخدمة المقدمة.",
"invalidInsurance": "لا يمكنك إجراء الدفع عبر الإنترنت لأنه ليس لديك تأمين صالح.",
"continueCash": "تواصل نقدا",
"timeFor": "الوقت" "timeFor": "الوقت"
} }

@ -937,6 +937,7 @@
"offline": "Offline", "offline": "Offline",
"videoCall": "Video Call", "videoCall": "Video Call",
"liveVideoCallWithHMGDoctors": "Live Video Call with HMG Doctors", "liveVideoCallWithHMGDoctors": "Live Video Call with HMG Doctors",
"liveAudioCallWithHMGDoctors": "Live Audio Call with HMG Doctors",
"audioCall": "Audio Call", "audioCall": "Audio Call",
"phoneCall": "Phone Call", "phoneCall": "Phone Call",
"livePhoneCallWithHMGDoctors": "Live Phone Call with HMG Doctors", "livePhoneCallWithHMGDoctors": "Live Phone Call with HMG Doctors",
@ -1439,7 +1440,6 @@
"healthy": "Healthy", "healthy": "Healthy",
"warning": "Warning", "warning": "Warning",
"vitalSignDetails": "Vital Sign Details", "vitalSignDetails": "Vital Sign Details",
"resultOf": "Result of {date}",
"resultOfNoDate": "Result of --", "resultOfNoDate": "Result of --",
"referenceRangeBetween": "Reference range: {low} {high} {unit}", "referenceRangeBetween": "Reference range: {low} {high} {unit}",
"referenceRangeMin": "Reference range: ≥ {low} {unit}", "referenceRangeMin": "Reference range: ≥ {low} {unit}",
@ -1475,7 +1475,6 @@
"remindersSet": "Reminders Set!", "remindersSet": "Reminders Set!",
"dailyWaterRemindersScheduledAt": "Daily water reminders scheduled at:", "dailyWaterRemindersScheduledAt": "Daily water reminders scheduled at:",
"waterConsumption": "Water Consumption", "waterConsumption": "Water Consumption",
"selectActivityLevel": "Select Activity Level",
"selectNumberOfReminders": "Select Number of Reminders", "selectNumberOfReminders": "Select Number of Reminders",
"h2oSettings": "H20 Settings", "h2oSettings": "H20 Settings",
"settingsSavedSuccessfully": "Settings saved successfully", "settingsSavedSuccessfully": "Settings saved successfully",
@ -1515,6 +1514,63 @@
"trackerAndOthers": "Tracker & Others", "trackerAndOthers": "Tracker & Others",
"bmi": "BMI", "bmi": "BMI",
"yesPleaseINeedHelp": "Yes, Please I need help", "yesPleaseINeedHelp": "Yes, Please I need help",
"confirmYourLocation": "Confirm Your Location",
"confirmYourLocationDesc": "Please confirm your present location to view appropriate directions.",
"insideHospital": "I am inside the hospital",
"outsideHospital": "I am outside the hospital",
"servicePriceList": "Services Price List",
"servicePriceListDesc": "Below is the services price list outline the healthcare services fees for cash payments, where the insurance coverage, eligibility, and co-payment deductions will be processed in accordance with the insurance policy terms and the table of benefits of each insurance providers:",
"servicePriceListRights": "The patient has the right to a free follow-up within 14 days of initial visit",
"serviceName": "Service Name",
"noFreeSlot": "No free slot available for the selected date. Please select another date or check back later.",
"noThanksIKnowTheClinic": "No, Thanks. I Know the clinic", "noThanksIKnowTheClinic": "No, Thanks. I Know the clinic",
"unableToSendOTP": "Unable to send Verification OTP" "unableToSendOTP": "Unable to send Verification OTP",
"aiOverView": "AI Overview",
"generateAiAnalysis": "Generate AI analysis for this order",
"aiAnalysis": "AI Analysis",
"prediction": "Prediction",
"prevention": "Prevention",
"disclaimer": "Disclaimer",
"thisAboveInfo": "The above information is generated by AI based on your lab results and is intended for informational purposes only. It should not be considered a medical diagnosis or treatment plan. Always consult with your healthcare provider for personalized medical advice and before making any health-related decisions.",
"aiDisclaimer": "Your lab result data will be securely shared with our AI Analyzer for analysis. This helps provide personalized health insights. Do you want to proceed?",
"consent": "Consent",
"bmiNormalDescription": "Your BMI is within the healthy range. Continue a balanced diet, regular physical activity, and routine checkups to maintain good health. Monitor any significant changes over time.",
"bmiUnderweightDescription": "BMI suggests you are underweight. Consider increasing calorie intake with nutrient-dense foods, include resistance training to build muscle, and consult a healthcare professional to check for underlying causes.",
"bmiOverweightDescription": "BMI indicates overweight. Aim for gradual, sustainable weight loss through a modest calorie deficit, regular physical activity, and healthier food choices. Seek medical advice before major lifestyle changes.",
"caloriesMaintenanceDescription": "Estimated daily calories to maintain your current weight given your activity level and metabolism. Use this as a baseline: increase slightly for muscle gain, or create a small deficit for gradual weight loss. Track progress and adjust every 24 weeks.",
"caloriesModerateDeficitDescription": "A moderate calorie reduction designed for steady, sustainable weight loss (typically 0.250.5 kg per week). Combine with resistance training and adequate protein to preserve muscle. Avoid extreme cuts and consult a professional if you have medical conditions.",
"caloriesAggressiveDeficitDescription": "A large calorie reduction that may produce faster weight loss but can be hard to sustain and increase risk of nutrient deficiencies, fatigue, or muscle loss. Not recommended long-term; seek guidance from a healthcare or nutrition professional before continuing.",
"bodyFatEssentialDescription": "Your body fat percentage is in the essential/athletic range. This level is typical for athletes and indicates very low body fat. While this may be optimal for performance, ensure you maintain adequate nutrition and hormone function. Consult a healthcare professional if you experience fatigue, hormonal issues, or other health concerns.",
"bodyFatFitnessDescription": "Your body fat percentage is in the fitness range. This indicates a healthy level of body fat associated with good physical conditioning. Maintain your current lifestyle habits including regular exercise and balanced nutrition to sustain this healthy range.",
"bodyFatAverageDescription": "Your body fat percentage is in the average/acceptable range. This is considered a healthy range for general population. To improve body composition, consider incorporating strength training, cardiovascular exercise, and a balanced diet. Focus on gradual, sustainable changes for long-term health.",
"bodyFatObeseDescription": "Your body fat percentage is above the recommended healthy range. This may increase health risks including cardiovascular disease, diabetes, and joint problems. Consider consulting a healthcare provider or registered dietitian to develop a personalized plan that includes balanced nutrition, regular physical activity, and lifestyle modifications for sustainable weight management.",
"bmrNormalDescription": "Your Basal Metabolic Rate (BMR) is within the expected range for your profile. BMR is the energy your body needs at rest to maintain vital functions (breathing, circulation, temperature). Use this value as the baseline for estimating total daily energy needs by applying an activity multiplier. Maintain a balanced diet and regular physical activity to support metabolic health.",
"bmrLowDescription": "Your BMR is lower than typical for your profile. Possible causes include lower lean muscle mass, age-related metabolic decline, or metabolic adaptation from prolonged calorie restriction. Consider focusing on resistance training to build/maintain muscle, ensure adequate protein and micronutrient intake, and consult a healthcare professional if this is unexpected.",
"bmrHighDescription": "Your BMR is higher than average for your profile. This can reflect greater lean mass, younger age, or a naturally higher metabolic rate, meaning you burn more energy at rest. Use this information to tailor calorie targets: higher needs for maintenance or muscle gain, moderate deficit for weight loss. Seek medical advice if you notice rapid unexplained changes.",
"ibwAtTargetDescription": "Your weight is at the ideal target. Maintain your current habits — balanced diet and regular activity — to keep this.",
"ibwBelowTargetDescription": "You are below the ideal weight by {kg} kg. Aim to gradually increase weight with a modest calorie surplus, nutrient-dense foods, and resistance training.",
"ibwAboveTargetDescription": "You are above the ideal weight by {kg} kg. Aim for a gradual, sustainable weight reduction through a moderate calorie deficit, increased activity, and balanced nutrition.",
"ibwCloseToRangeDescription": "Your weight is close to the ideal range. Maintain a balanced diet and regular activity; follow personalized advice from a healthcare professional if needed.",
"ibwUnderweightDescription": "You are below the ideal weight by {kg} kg. Focus on increasing calorie intake with nutrient-dense foods, prioritize protein and resistance training to build healthy mass, and consider consulting a healthcare professional.",
"ibwUnderweightGenericDescription": "You appear underweight compared to the ideal. Consider increasing calorie intake with nutrient-dense foods and resistance training; seek professional guidance if needed.",
"ibwOverweightDescription": "You are above the ideal weight by {kg} kg. Aim for a gradual, sustainable weight loss strategy — moderate calorie deficit, regular physical activity, and balanced nutrition. Consult a professional before major changes.",
"ibwOverweightGenericDescription": "You appear above the ideal weight. Consider a gradual, sustainable calorie deficit combined with activity and balanced nutrition; consult a professional if needed.",
"dietVeryLowCarbsDescription": "Very lowcarb (ketogenic) approach: minimal carbohydrates, higher fat and moderate protein. May support rapid weight loss and improved blood sugar control for some, but can be hard to sustain and may cause nutrient gaps. Monitor hydration/electrolytes and consult a professional for longterm use.",
"dietLowCarbsDescription": "Lowcarb, higherprotein plan: reduced carbohydrates with increased protein to support satiety and muscle maintenance. Helpful for weight management and glycemic control when balanced with vegetables and healthy fats. Ensure adequate fiber and micronutrients.",
"dietModerateCarbsDescription": "Moderate carbohydrate intake with balanced protein and fats: provides steady energy for daily activity and exercise while allowing flexibility. Suitable for many people aiming for sustainable weight management and performance.",
"dietUSDAGuidelinesDescription": "USDAbased balanced pattern: emphasizes fruits, vegetables, whole grains, lean proteins, and limited added sugars and saturated fats. Evidencebased framework for general health, nutrient adequacy, and chronic disease prevention.",
"dietZoneDietDescription": "Zone Diet (~40% carbs / 30% protein / 30% fat): emphasizes hormonal balance and portion control. May improve body composition and energy for some, but requires planning; personalize with a nutrition professional.",
"contextDependent": "Context Dependent",
"calculatedValue": "Calculated Value",
"calculationFormula": "Calculation Formula",
"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"
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,73 +0,0 @@
// import 'dart:convert';
// import 'dart:io';
//
// void main() async {
// final file = File('assets/json/body_symptoms_data.json');
// final content = await file.readAsString();
//
// print('File size: ${content.length} characters');
//
// // Split into two parts
// final parts = content.split('export const SymptomsData = [');
// if (parts.length != 2) {
// print('ERROR: Could not split file properly');
// exit(1);
// }
//
// print('Split into ${parts.length} parts');
//
// // Process BodySymptomsData
// var bodyPart = parts[0]
// .replaceAll('export const BodySymptomsData = ', '')
// .trim()
// .replaceAll(RegExp(r';$'), '');
//
// print('Parsing body symptoms...');
// Map<String, dynamic> bodySymptomsData;
// try {
// bodySymptomsData = json.decode(bodyPart);
// print('✅ Body symptoms parsed: ${bodySymptomsData.length} body parts');
// } catch (e) {
// print('❌ Error parsing body symptoms: $e');
// exit(1);
// }
//
// // Process SymptomsData
// print('Processing symptoms data...');
// var symptomsPart = parts[1]
// .trim()
// .replaceAll(RegExp(r'\];$'), '')
// .replaceAllMapped(RegExp(r'\n(\s*)id:'), (m) => '\n${m.group(1)}"id":')
// .replaceAllMapped(RegExp(r'\n(\s*)type:'), (m) => '\n${m.group(1)}"type":')
// .replaceAllMapped(RegExp(r'\n(\s*)name:'), (m) => '\n${m.group(1)}"name":')
// .replaceAllMapped(RegExp(r'\n(\s*)common_name:'), (m) => '\n${m.group(1)}"common_name":');
//
// print('Parsing symptoms...');
// List<dynamic> symptomsData;
// try {
// symptomsData = json.decode('[$symptomsPart]');
// print('✅ Symptoms parsed: ${symptomsData.length} symptoms');
// } catch (e) {
// print('❌ Error parsing symptoms: $e');
// print('First 1000 chars:');
// print('[$symptomsPart]'.substring(0, 1000));
// exit(1);
// }
//
// // Create final JSON
// print('Creating final JSON structure...');
// final jsonStructure = {
// 'bodySymptoms': bodySymptomsData,
// 'symptoms': symptomsData,
// };
//
// // Write to file
// print('Writing to file...');
// final encoder = JsonEncoder.withIndent(' ');
// await file.writeAsString(encoder.convert(jsonStructure));
//
// print('\n✅ SUCCESS! File converted to proper JSON');
// print('✅ Body parts: ${bodySymptomsData.length}');
// print('✅ Symptoms: ${symptomsData.length}');
// }
//

@ -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"}}}}}}

@ -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"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

@ -2,10 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CLIENT_ID</key>
<string>815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt</string>
<key>ANDROID_CLIENT_ID</key> <key>ANDROID_CLIENT_ID</key>
<string>815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com</string> <string>815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com</string>
<key>API_KEY</key> <key>API_KEY</key>
@ -15,11 +11,11 @@
<key>PLIST_VERSION</key> <key>PLIST_VERSION</key>
<string>1</string> <string>1</string>
<key>BUNDLE_ID</key> <key>BUNDLE_ID</key>
<string>com.HMG.HMG-Smartphone</string> <string>com.cloudsolutions.HMGPatientApp</string>
<key>PROJECT_ID</key> <key>PROJECT_ID</key>
<string>api-project-815750722565</string> <string>api-project-815750722565</string>
<key>STORAGE_BUCKET</key> <key>STORAGE_BUCKET</key>
<string>api-project-815750722565.appspot.com</string> <string>api-project-815750722565.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key> <key>IS_ADS_ENABLED</key>
<false></false> <false></false>
<key>IS_ANALYTICS_ENABLED</key> <key>IS_ANALYTICS_ENABLED</key>
@ -31,7 +27,7 @@
<key>IS_SIGNIN_ENABLED</key> <key>IS_SIGNIN_ENABLED</key>
<true></true> <true></true>
<key>GOOGLE_APP_ID</key> <key>GOOGLE_APP_ID</key>
<string>1:815750722565:ios:328ec247a81a2ca23c186c</string> <string>1:815750722565:ios:34ec03c09e02e21f3c186c</string>
<key>DATABASE_URL</key> <key>DATABASE_URL</key>
<string>https://api-project-815750722565.firebaseio.com</string> <string>https://api-project-815750722565.firebaseio.com</string>
</dict> </dict>

@ -18,12 +18,14 @@
61243B562EC5FA3700D46FA0 /* PenguinNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */; }; 61243B562EC5FA3700D46FA0 /* PenguinNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */; };
61243B572EC5FA3700D46FA0 /* PenguinViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */; }; 61243B572EC5FA3700D46FA0 /* PenguinViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
766D8CB62EC60BE600D05E07 /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 766D8CB32EC60BE600D05E07 /* Penguin.xcframework */; }; 765A5A8C2F35CD8B0003FF7D /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A802F35CD730003FF7D /* Penguin.xcframework */; };
766D8CB72EC60BE600D05E07 /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 766D8CB32EC60BE600D05E07 /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 765A5A8D2F35CD8B0003FF7D /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A802F35CD730003FF7D /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
766D8CB82EC60BE600D05E07 /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 766D8CB42EC60BE600D05E07 /* PenNavUI.xcframework */; }; 765A5A8E2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */; };
766D8CB92EC60BE600D05E07 /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 766D8CB42EC60BE600D05E07 /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 765A5A8F2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
766D8CBA2EC60BE600D05E07 /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 766D8CB52EC60BE600D05E07 /* PenguinINRenderer.xcframework */; }; 765A5A902F35CD8B0003FF7D /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */; };
766D8CBB2EC60BE600D05E07 /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 766D8CB52EC60BE600D05E07 /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 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 */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@ -41,15 +43,15 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = { 765A5A922F35CD8B0003FF7D /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase; isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
766D8CB72EC60BE600D05E07 /* Penguin.xcframework in Embed Frameworks */, 765A5A8F2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Embed Frameworks */,
766D8CBB2EC60BE600D05E07 /* PenguinINRenderer.xcframework in Embed Frameworks */, 765A5A8D2F35CD8B0003FF7D /* Penguin.xcframework in Embed Frameworks */,
766D8CB92EC60BE600D05E07 /* PenNavUI.xcframework in Embed Frameworks */, 765A5A912F35CD8B0003FF7D /* PenNavUI.xcframework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -73,10 +75,12 @@
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; 7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
766D8CB32EC60BE600D05E07 /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = "<group>"; }; 765A5A802F35CD730003FF7D /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Penguin.xcframework; sourceTree = "<group>"; };
766D8CB42EC60BE600D05E07 /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = "<group>"; }; 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenguinINRenderer.xcframework; sourceTree = "<group>"; };
766D8CB52EC60BE600D05E07 /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = "<group>"; }; 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = PenNavUI.xcframework; sourceTree = "<group>"; };
769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; }; 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; };
76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ring_30Sec.caf; sourceTree = "<group>"; };
76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ring_30Sec.mp3; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; }; 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 = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
@ -95,9 +99,9 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
766D8CB62EC60BE600D05E07 /* Penguin.xcframework in Frameworks */, 765A5A8C2F35CD8B0003FF7D /* Penguin.xcframework in Frameworks */,
766D8CBA2EC60BE600D05E07 /* PenguinINRenderer.xcframework in Frameworks */, 765A5A902F35CD8B0003FF7D /* PenNavUI.xcframework in Frameworks */,
766D8CB82EC60BE600D05E07 /* PenNavUI.xcframework in Frameworks */, 765A5A8E2F35CD8B0003FF7D /* PenguinINRenderer.xcframework in Frameworks */,
DE1EF78253E64BE86845D2CC /* Pods_Runner.framework in Frameworks */, DE1EF78253E64BE86845D2CC /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -136,9 +140,9 @@
766D8CB22EC60BE600D05E07 /* Frameworks */ = { 766D8CB22EC60BE600D05E07 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
766D8CB32EC60BE600D05E07 /* Penguin.xcframework */, 765A5A802F35CD730003FF7D /* Penguin.xcframework */,
766D8CB52EC60BE600D05E07 /* PenguinINRenderer.xcframework */, 765A5A812F35CD730003FF7D /* PenguinINRenderer.xcframework */,
766D8CB42EC60BE600D05E07 /* PenNavUI.xcframework */, 765A5A822F35CD730003FF7D /* PenNavUI.xcframework */,
D562310E31D1DDEFA02A6C12 /* Pods_Runner.framework */, D562310E31D1DDEFA02A6C12 /* Pods_Runner.framework */,
); );
name = Frameworks; name = Frameworks;
@ -189,6 +193,8 @@
97C146F01CF9000F007C117D /* Runner */ = { 97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */,
76AA18AD2F3B2A4D00DC8DFC /* ring_30Sec.mp3 */,
61243B412EC5FA3700D46FA0 /* Helper */, 61243B412EC5FA3700D46FA0 /* Helper */,
61243B472EC5FA3700D46FA0 /* Penguin */, 61243B472EC5FA3700D46FA0 /* Penguin */,
769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */, 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */,
@ -235,10 +241,10 @@
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
8372B02399CDF54531650AD4 /* [CP] Embed Pods Frameworks */, 8372B02399CDF54531650AD4 /* [CP] Embed Pods Frameworks */,
81DE7C26F41956799E954FCE /* [CP] Copy Pods Resources */, 81DE7C26F41956799E954FCE /* [CP] Copy Pods Resources */,
765A5A922F35CD8B0003FF7D /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
); );
buildRules = ( buildRules = (
); );
@ -300,6 +306,8 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
76AA18AE2F3B2A4D00DC8DFC /* ring_30Sec.caf in Resources */,
76AA18AF2F3B2A4D00DC8DFC /* ring_30Sec.mp3 in Resources */,
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */, 478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */,
@ -515,7 +523,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2; CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -524,8 +532,8 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.0; MARKETING_VERSION = 0.0.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.HMGPatientApp;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -701,7 +709,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2; CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -710,8 +718,8 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.0; MARKETING_VERSION = 0.0.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.HMGPatientApp;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -730,7 +738,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2; CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 3A359E86ZF; DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -739,8 +747,8 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.0; MARKETING_VERSION = 0.0.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.HMGPatientApp;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

@ -109,7 +109,7 @@
"size" : "83.5x83.5" "size" : "83.5x83.5"
}, },
{ {
"filename" : "icon 1.jpg", "filename" : "icon.jpg",
"idiom" : "ios-marketing", "idiom" : "ios-marketing",
"scale" : "1x", "scale" : "1x",
"size" : "1024x1024" "size" : "1024x1024"

@ -2,10 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CLIENT_ID</key>
<string>815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt</string>
<key>ANDROID_CLIENT_ID</key> <key>ANDROID_CLIENT_ID</key>
<string>815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com</string> <string>815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com</string>
<key>API_KEY</key> <key>API_KEY</key>
@ -15,24 +11,24 @@
<key>PLIST_VERSION</key> <key>PLIST_VERSION</key>
<string>1</string> <string>1</string>
<key>BUNDLE_ID</key> <key>BUNDLE_ID</key>
<string>com.HMG.HMG-Smartphone</string> <string>com.cloudsolutions.HMGPatientApp</string>
<key>PROJECT_ID</key> <key>PROJECT_ID</key>
<string>api-project-815750722565</string> <string>api-project-815750722565</string>
<key>STORAGE_BUCKET</key> <key>STORAGE_BUCKET</key>
<string>api-project-815750722565.appspot.com</string> <string>api-project-815750722565.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key> <key>IS_ADS_ENABLED</key>
<false/> <false></false>
<key>IS_ANALYTICS_ENABLED</key> <key>IS_ANALYTICS_ENABLED</key>
<false/> <false></false>
<key>IS_APPINVITE_ENABLED</key> <key>IS_APPINVITE_ENABLED</key>
<true/> <true></true>
<key>IS_GCM_ENABLED</key> <key>IS_GCM_ENABLED</key>
<true/> <true></true>
<key>IS_SIGNIN_ENABLED</key> <key>IS_SIGNIN_ENABLED</key>
<true/> <true></true>
<key>GOOGLE_APP_ID</key> <key>GOOGLE_APP_ID</key>
<string>1:815750722565:ios:328ec247a81a2ca23c186c</string> <string>1:815750722565:ios:34ec03c09e02e21f3c186c</string>
<key>DATABASE_URL</key> <key>DATABASE_URL</key>
<string>https://api-project-815750722565.firebaseio.com</string> <string>https://api-project-815750722565.firebaseio.com</string>
</dict> </dict>
</plist> </plist>

@ -13,7 +13,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Dr. Alhabib</string> <string>Dr. Alhabib Beta</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>

@ -309,22 +309,13 @@ class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitia
PenNavUIManager.shared.eventsDelegate = self PenNavUIManager.shared.eventsDelegate = self
// print("====== after onPenNavSuccess navigate =========")
// PenNavUIManager.shared.navigate(to: "3-1")
print("====== after eventsDelegate onPenNavSuccess =========")
PenNavUIManager.shared.navigate(to: "108")
// Present the Penguin UI on top of the Flutter view controller // Present the Penguin UI on top of the Flutter view controller
print("====== after onPenNavSuccess present =========")
PenNavUIManager.shared.present(root: controller, view: _view) PenNavUIManager.shared.present(root: controller, view: _view)
print("====== after present onPenNavSuccess =========") print("====== after present onPenNavSuccess =========")
print(model?.clinicID) print(model?.clinicID)
@ -347,11 +338,21 @@ class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitia
let clientID = self.model?.clientID, !clientID.isEmpty else { let clientID = self.model?.clientID, !clientID.isEmpty else {
print("Error: Config Client ID is nil or empty") print("Error: Config Clinic ID is nil or empty")
return return
} }
print("====== after onPenNavSuccess navigate =========")
// PenNavUIManager.shared.navigate(to: "3-1") { success, error in
PenNavUIManager.shared.navigate(to: clinicID) { success, error in
if success {
print("Nav Success")
} else {
print("Nav Error")
}
}
@ -373,20 +374,20 @@ class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitia
guard let token = token else { // guard let token = token else {
//
print("Token is nil") // print("Token is nil")
//
return // return
//
} // }
//
print("Token Generated") // print("Token Generated")
//
print(token); // print(token);
//
// self?.handleNavigation(clinicID: clinicID, token: token) { success, errorMessage in // self?.handleNavigation(clinicID: clinicID, token: token) { success, errorMessage in
// //
// if success { // if success {
@ -425,7 +426,8 @@ class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitia
PenNavUIManager.shared.setToken(token: token) PenNavUIManager.shared.setToken(token: token)
PenNavUIManager.shared.navigate(to: clinicID) // PenNavUIManager.shared.navigate(to: clinicID)
PenNavUIManager.shared.navigate(to: "3-1")
completion(true,nil) completion(true,nil)

Binary file not shown.

Binary file not shown.

@ -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/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.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/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/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/analytics/analytics_service.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/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../exceptions/api_failure.dart'; import '../exceptions/api_failure.dart';
@ -36,6 +38,7 @@ abstract class ApiClient {
required Function(dynamic response, int statusCode) onSuccess, required Function(dynamic response, int statusCode) onSuccess,
required Function(String error, int statusCode) onFailure, required Function(String error, int statusCode) onFailure,
Map<String, dynamic>? queryParams, Map<String, dynamic>? queryParams,
Map<String, String> apiHeaders,
bool isAllowAny, bool isAllowAny,
bool isExternal, bool isExternal,
bool isRCService, bool isRCService,
@ -181,14 +184,30 @@ class ApiClientImp implements ApiClient {
body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken; body[_appState.isAuthenticated ? 'TokenID' : 'LogInTokenID'] = _appState.appAuthToken;
} }
if (url.contains("HMGAI_Lab_Analyze_Orders_API")) {
url = "https://uat.hmgwebservices.com/Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API";
body['TokenID'] = "@dm!n";
}
if (url.contains("HMGAI_Lab_Analyzer_API")) {
url = "https://uat.hmgwebservices.com/Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
body['TokenID'] = "@dm!n";
}
// body['TokenID'] = "@dm!n"; // body['TokenID'] = "@dm!n";
// body['PatientID'] = 4768663; // body['PatientID'] = 4773715;
// body['PatientTypeID'] = 1; // body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0; // body['PatientOutSA'] = 0;
// body['SessionID'] = "45786230487560q"; // body['SessionID'] = "45786230487560q";
// body['IdentificationNo'] = "2235558844";
// body['MobileNo'] = "966533147722";
// body['PatientID'] = 809289;
} }
// body['IsNewFlutterApp'] = true; if(!url.contains("/paymentApi")) {
body['IsNewFlutterApp'] = true;
}
body.removeWhere((key, value) => value == null); body.removeWhere((key, value) => value == null);
} }
@ -208,7 +227,8 @@ class ApiClientImp implements ApiClient {
// Handle body encoding based on isBodyPlainText flag // Handle body encoding based on isBodyPlainText flag
final dynamic requestBody = isBodyPlainText ? body : json.encode(body); final dynamic requestBody = isBodyPlainText ? body : json.encode(body);
debugPrint("uri: ${Uri.parse(url.trim())}"); 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 response = await http.post(Uri.parse(url.trim()), body: requestBody, headers: headers);
final int statusCode = response.statusCode; final int statusCode = response.statusCode;
// log("response.body: ${response.body}"); // log("response.body: ${response.body}");
@ -233,8 +253,16 @@ class ApiClientImp implements ApiClient {
} else { } else {
if (parsed['ErrorType'] == 4) { if (parsed['ErrorType'] == 4) {
//TODO : handle app update //TODO : handle app update
onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, // onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode,
failureType: AppUpdateFailure("parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']")); // 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); logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
} }
if (parsed['ErrorType'] == 2) { if (parsed['ErrorType'] == 2) {
@ -354,6 +382,7 @@ class ApiClientImp implements ApiClient {
{required Function(dynamic response, int statusCode) onSuccess, {required Function(dynamic response, int statusCode) onSuccess,
required Function(String error, int statusCode) onFailure, required Function(String error, int statusCode) onFailure,
Map<String, dynamic>? queryParams, Map<String, dynamic>? queryParams,
Map<String, String>? apiHeaders,
bool isAllowAny = false, bool isAllowAny = false,
bool isExternal = false, bool isExternal = false,
bool isRCService = false}) async { bool isRCService = false}) async {
@ -378,7 +407,7 @@ class ApiClientImp implements ApiClient {
if (await Utils.checkConnection(bypassConnectionCheck: true)) { if (await Utils.checkConnection(bypassConnectionCheck: true)) {
final response = await http.get( final response = await http.get(
Uri.parse(url.trim()), 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; final int statusCode = response.statusCode;
// print("statusCode :$statusCode"); // print("statusCode :$statusCode");

@ -1,6 +1,242 @@
import 'package:amazon_payfort/amazon_payfort.dart'; import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:hmg_patient_app_new/core/enums.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 // PACKAGES and OFFERS
var EXA_CART_API_BASE_URL = 'https://mdlaboratories.com/offersdiscounts'; var EXA_CART_API_BASE_URL = 'https://mdlaboratories.com/offersdiscounts';
// var EXA_CART_API_BASE_URL = 'http://10.200.101.75:9000'; // var EXA_CART_API_BASE_URL = 'http://10.200.101.75:9000';
@ -380,6 +616,8 @@ var GET_PATIENT_SICK_LEAVE = 'Services/Patients.svc/REST/GetPatientSickLeave';
var GET_PATIENT_SICK_LEAVE_STATUS = 'Services/Patients.svc/REST/GetPatientSickLeave_Status'; var GET_PATIENT_SICK_LEAVE_STATUS = 'Services/Patients.svc/REST/GetPatientSickLeave_Status';
var GET_SERVICES_PRICE_LIST = 'Services/OUTPs.svc/REST/GetServicesPriceList';
var SendSickLeaveEmail = 'Services/Notifications.svc/REST/SendSickLeaveEmail'; var SendSickLeaveEmail = 'Services/Notifications.svc/REST/SendSickLeaveEmail';
var GET_PATIENT_AdVANCE_BALANCE_AMOUNT = 'Services/Patients.svc/REST/GetPatientAdvanceBalanceAmount'; var GET_PATIENT_AdVANCE_BALANCE_AMOUNT = 'Services/Patients.svc/REST/GetPatientAdvanceBalanceAmount';
@ -678,239 +916,6 @@ var GET_PRESCRIPTION_INSTRUCTIONS_PDF = 'Services/ChatBot_Service.svc/REST/Chatb
const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard'; const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard';
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';
//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 values for Api ****************
static final double appVersionID = 50.3;
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 { class ApiKeyConstants {
static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng'; static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng';
} }

@ -251,6 +251,10 @@ class AppAssets {
static const String alertSquare = '$svgBasePath/alert-square.svg'; static const String alertSquare = '$svgBasePath/alert-square.svg';
static const String arrowRight = '$svgBasePath/arrow-right.svg'; static const String arrowRight = '$svgBasePath/arrow-right.svg';
static const String tickIcon = '$svgBasePath/tick.svg'; static const String tickIcon = '$svgBasePath/tick.svg';
static const String guradIcon = '$svgBasePath/guard_icon.svg';
static const String calculatorIcon = '$svgBasePath/calculator_icon.svg';
static const String informationIcon = '$svgBasePath/information-circle.svg';
static const String highCautionIcon = '$svgBasePath/high_caution.svg';
// Symptoms Checker // Symptoms Checker
static const String calendarGrey = '$svgBasePath/calendar-grey.svg'; static const String calendarGrey = '$svgBasePath/calendar-grey.svg';
@ -291,6 +295,10 @@ class AppAssets {
static const String bulb = '$svgBasePath/bulb.svg'; static const String bulb = '$svgBasePath/bulb.svg';
static const String switchBtn = '$svgBasePath/switch.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 //Health Trackers
static const String bloodPressureIcon = '$svgBasePath/blood_pressure_icon.svg'; static const String bloodPressureIcon = '$svgBasePath/blood_pressure_icon.svg';
static const String bloodSugarOnlyIcon = '$svgBasePath/blood_sugar_only_icon.svg'; static const String bloodSugarOnlyIcon = '$svgBasePath/blood_sugar_only_icon.svg';
@ -322,6 +330,7 @@ class AppAssets {
static const String doctorResponseIcon = '$svgBasePath/doctor_response_icon.svg'; static const String doctorResponseIcon = '$svgBasePath/doctor_response_icon.svg';
static const String changeLanguageHomePageIcon = '$svgBasePath/change_language_home_page.svg'; static const String changeLanguageHomePageIcon = '$svgBasePath/change_language_home_page.svg';
static const String aiOverView = '$svgBasePath/ai_overview.svg';
// PNGS // // PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png'; static const String hmgLogo = '$pngBasePath/hmg_logo.png';
@ -346,8 +355,10 @@ class AppAssets {
static const String maleIcon = '$pngBasePath/male_icon.png'; static const String maleIcon = '$pngBasePath/male_icon.png';
static const String femaleIcon = '$pngBasePath/female_icon.png'; static const String femaleIcon = '$pngBasePath/female_icon.png';
static const String fullBodyFront = '$pngBasePath/full_body_front.png'; static const String fullBodyFrontMale = '$pngBasePath/full_body_front_male.png';
static const String fullBodyBack = '$pngBasePath/full_body_back.png'; static const String fullBodyBackMale = '$pngBasePath/full_body_back_male.png';
static const String fullBodyFrontFemale = '$pngBasePath/full_body_front_female.png';
static const String fullBodyBackFemale = '$pngBasePath/full_body_back_female.png';
static const String bmiFullBody = '$pngBasePath/bmi_image_1.png'; static const String bmiFullBody = '$pngBasePath/bmi_image_1.png';
} }

@ -54,6 +54,8 @@ import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_v
import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart'; import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart'; import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart'; import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/features/services_price_list/services_price_list_repo.dart';
import 'package:hmg_patient_app_new/features/services_price_list/services_price_list_view_model.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_repo.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_repo.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
@ -169,6 +171,7 @@ class AppDependencies {
getIt.registerLazySingleton<QrParkingRepo>(() => QrParkingRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); getIt.registerLazySingleton<QrParkingRepo>(() => QrParkingRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<NotificationsRepo>(() => NotificationsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); getIt.registerLazySingleton<NotificationsRepo>(() => NotificationsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<AskDoctorRepo>(() => AskDoctorRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); getIt.registerLazySingleton<AskDoctorRepo>(() => AskDoctorRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<ServicesPriceListRepo>(() => ServicesPriceListRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
// ViewModels // ViewModels
// Global/shared VMs LazySingleton // Global/shared VMs LazySingleton
@ -311,5 +314,6 @@ class AppDependencies {
getIt.registerLazySingleton<AskDoctorViewModel>(() => AskDoctorViewModel(askDoctorRepo: getIt(), errorHandlerService: getIt())); getIt.registerLazySingleton<AskDoctorViewModel>(() => AskDoctorViewModel(askDoctorRepo: getIt(), errorHandlerService: getIt()));
getIt.registerLazySingleton<ServicesPriceListViewModel>(() => ServicesPriceListViewModel(servicesPriceListRepo: getIt(), errorHandlerService: getIt()));
} }
} }

@ -110,7 +110,7 @@ class DateUtil {
} }
static String formatDateToTime(DateTime date) { static String formatDateToTime(DateTime date) {
return DateFormat('hh:mm a').format(date); return DateFormat('hh:mm a', "en-US").format(date);
} }
static String yearMonthDay(DateTime dateTime) { static String yearMonthDay(DateTime dateTime) {
@ -487,7 +487,9 @@ class DateUtil {
} }
static String getFormattedDate(DateTime dateTime, String formattedString) { static String getFormattedDate(DateTime dateTime, String formattedString) {
return DateFormat(formattedString).format(dateTime); String formattedDate = DateFormat(formattedString, "en-US").format(dateTime);
print(formattedDate);
return formattedDate;
} }
static convertISODateToJsonDate(String isoDate) { static convertISODateToJsonDate(String isoDate) {

@ -38,7 +38,7 @@ class LoadingUtils {
child: Material( child: Material(
child: Center( child: Center(
child: isSuccessDialog ? Utils.getSuccessWidget(loadingText: loadingText) : Utils.getLoadingWidget(loadingText: loadingText), child: isSuccessDialog ? Utils.getSuccessWidget(loadingText: loadingText) : Utils.getLoadingWidget(loadingText: loadingText),
), ).paddingSymmetrical(24.w, 0),
), ),
); );
}).then((value) { }).then((value) {

@ -12,13 +12,17 @@ class PenguinMethodChannel {
try { try {
await _channel.invokeMethod('launchPenguin', { await _channel.invokeMethod('launchPenguin', {
"storyboardName": storyboardName, "storyboardName": storyboardName,
"baseURL": "https://penguinuat.hmg.com",
// "dataURL": "https://hmg.nav.penguinin.com", // UAT URLs
// "positionURL": "https://hmg.nav.penguinin.com", // "baseURL": "https://penguinuat.hmg.com",
// "dataURL": "https://hmg-v33.local.penguinin.com", // "dataURL": "https://penguinuat.hmg.com",
// "positionURL": "https://hmg-v33.local.penguinin.com", // "positionURL": "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", "dataServiceName": "api",
"positionServiceName": "pe", "positionServiceName": "pe",
"clientID": "HMG", "clientID": "HMG",

@ -95,7 +95,7 @@ _incomingCall(Map<String, dynamic> data) async {
missedCallNotificationChannelName: "Missed Call", missedCallNotificationChannelName: "Missed Call",
isShowCallID: false), isShowCallID: false),
ios: IOSParams( ios: IOSParams(
iconName: 'Meena Health', iconName: 'CallKitLogo',
handleType: 'generic', handleType: 'generic',
supportsVideo: true, supportsVideo: true,
maximumCallGroups: 2, maximumCallGroups: 2,
@ -372,6 +372,14 @@ class PushNotificationHandler {
} }
}); });
if (Platform.isIOS) {
FirebaseMessaging.instance.getAPNSToken().then((String? token) {
print("Push Notification getAPNSToken: ${token!}");
}).catchError((err) {
print("Push Notification getAPNSToken ERR: ${err.toString()}");
});
}
FirebaseMessaging.instance.getToken().then((String? token) { FirebaseMessaging.instance.getToken().then((String? token) {
print("Push Notification getToken: ${token!}"); print("Push Notification getToken: ${token!}");
onToken(token!); onToken(token!);

@ -210,8 +210,8 @@ class RequestUtils {
List<String> names = fullName != null ? fullName.split(" ") : []; List<String> names = fullName != null ? fullName.split(" ") : [];
var dob = appState.getUserRegistrationPayload.dob; var dob = appState.getUserRegistrationPayload.dob;
final DateFormat dateFormat1 = DateFormat('MM/dd/yyyy'); final DateFormat dateFormat1 = DateFormat('MM/dd/yyyy', "en-US");
final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy'); final DateFormat dateFormat2 = DateFormat('dd/MM/yyyy', "en-US");
DateTime gregorianDate = dateFormat2.parse(dob!); DateTime gregorianDate = dateFormat2.parse(dob!);
HijriGregDate hijriDate = HijriGregConverter.gregorianToHijri(gregorianDate); HijriGregDate hijriDate = HijriGregConverter.gregorianToHijri(gregorianDate);
String? date = "${hijriDate.day}/${hijriDate.month}/${hijriDate.year}"; String? date = "${hijriDate.day}/${hijriDate.month}/${hijriDate.year}";

@ -128,7 +128,7 @@ class Utils {
static String convertStringToDateTime(String dateTimeString) { static String convertStringToDateTime(String dateTimeString) {
String timeString = dateTimeString; String timeString = dateTimeString;
// Parse the time string using DateFormat // Parse the time string using DateFormat
DateFormat format = DateFormat.Hms(); // 'Hms' = 'HH:mm:ss' DateFormat format = DateFormat.Hms(["en-US"]); // 'Hms' = 'HH:mm:ss'
DateTime time = format.parse(timeString); DateTime time = format.parse(timeString);
DateTime now = DateTime.now(); DateTime now = DateTime.now();
@ -408,6 +408,8 @@ class Utils {
Widget? bodyWidget, Widget? bodyWidget,
Function? onConfirmTap, Function? onConfirmTap,
Function? onCancelTap, Function? onCancelTap,
String? cancelText,
String? confirmText,
}) { }) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -425,7 +427,7 @@ class Utils {
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.cancel.tr(), text: cancelText ?? LocaleKeys.cancel.tr(),
onPressed: () { onPressed: () {
if (onCancelTap != null) { if (onCancelTap != null) {
onCancelTap(); onCancelTap();
@ -434,14 +436,14 @@ class Utils {
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
icon: AppAssets.cancel, // icon: AppAssets.cancel,
iconColor: AppColors.whiteColor, // iconColor: AppColors.whiteColor,
), ),
), ),
SizedBox(width: 8.h), SizedBox(width: 8.h),
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.confirm.tr(), text: confirmText ?? LocaleKeys.confirm.tr(),
onPressed: () async { onPressed: () async {
if (onConfirmTap != null) { if (onConfirmTap != null) {
onConfirmTap(); onConfirmTap();
@ -450,7 +452,7 @@ class Utils {
backgroundColor: AppColors.bgGreenColor, backgroundColor: AppColors.bgGreenColor,
borderColor: AppColors.bgGreenColor, borderColor: AppColors.bgGreenColor,
textColor: Colors.white, textColor: Colors.white,
icon: AppAssets.confirm, // icon: AppAssets.confirm,
), ),
), ),
], ],
@ -987,4 +989,23 @@ class Utils {
return isAllowed; 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 = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
const persian = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
String result = input;
for (int i = 0; i < 10; i++) {
result = result.replaceAll(arabic[i], english[i]);
result = result.replaceAll(persian[i], english[i]);
}
return result;
}
} }

@ -23,8 +23,7 @@ extension CapExtension on String {
extension EmailValidator on String { extension EmailValidator on String {
Widget get toWidget => Text(this); Widget get toWidget => Text(this);
Widget toText8({Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Widget toText8({Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Text(
Text(
this, this,
maxLines: maxlines, maxLines: maxlines,
overflow: textOverflow, overflow: textOverflow,
@ -38,7 +37,8 @@ extension EmailValidator on String {
); );
Widget toText10( Widget toText10(
{Color? color, {bool isEnglishOnly = false,
Color? color,
FontWeight? weight, FontWeight? weight,
bool isBold = false, bool isBold = false,
bool isUnderLine = false, bool isUnderLine = false,
@ -59,19 +59,20 @@ extension EmailValidator on String {
color: color ?? AppColors.blackColor, color: color ?? AppColors.blackColor,
letterSpacing: letterSpacing, letterSpacing: letterSpacing,
decoration: isUnderLine ? TextDecoration.underline : null, decoration: isUnderLine ? TextDecoration.underline : null,
fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins',
decorationColor: color ?? AppColors.blackColor), decorationColor: color ?? AppColors.blackColor),
); );
Widget toText9( Widget toText9(
{Color? color, {Color? color,
FontWeight? weight, FontWeight? weight,
bool isBold = false, bool isBold = false,
bool isUnderLine = false, bool isUnderLine = false,
bool isCenter = false, bool isCenter = false,
int? maxlines, int? maxlines,
FontStyle? fontStyle, FontStyle? fontStyle,
TextOverflow? textOverflow, TextOverflow? textOverflow,
double letterSpacing = 0}) => double letterSpacing = 0}) =>
Text( Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
@ -87,15 +88,7 @@ extension EmailValidator on String {
decorationColor: color ?? AppColors.blackColor), decorationColor: color ?? AppColors.blackColor),
); );
Widget toText11( Widget toText11({Color? color, FontWeight? weight, bool isUnderLine = false, bool isCenter = false, bool isBold = false, int maxLine = 0, double letterSpacing = 0}) => Text(
{Color? color,
FontWeight? weight,
bool isUnderLine = false,
bool isCenter = false,
bool isBold = false,
int maxLine = 0,
double letterSpacing = 0}) =>
Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null, maxLines: (maxLine > 0) ? maxLine : null,
@ -110,7 +103,7 @@ extension EmailValidator on String {
); );
Widget toText12( Widget toText12(
{Color? color, {bool isEnglishOnly = false, Color? color,
bool isUnderLine = false, bool isUnderLine = false,
TextAlign textAlignment = TextAlign.start, TextAlign textAlignment = TextAlign.start,
bool isBold = false, bool isBold = false,
@ -131,6 +124,7 @@ extension EmailValidator on String {
height: height, height: height,
decorationColor: isUnderLine ? AppColors.blackColor : null, decorationColor: isUnderLine ? AppColors.blackColor : null,
decoration: isUnderLine ? TextDecoration.underline : null, decoration: isUnderLine ? TextDecoration.underline : null,
fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins',
), ),
); );
@ -176,15 +170,7 @@ extension EmailValidator on String {
), ),
); );
Widget toText13( Widget toText13({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0, FontWeight? weight, double? letterSpacing = 0}) => Text(
{Color? color,
bool isUnderLine = false,
bool isBold = false,
bool isCenter = false,
int maxLine = 0,
FontWeight? weight,
double? letterSpacing = 0}) =>
Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
maxLines: (maxLine > 0) ? maxLine : null, maxLines: (maxLine > 0) ? maxLine : null,
@ -197,6 +183,7 @@ extension EmailValidator on String {
); );
Widget toText14({ Widget toText14({
bool isEnglishOnly = false,
Color? color, Color? color,
bool isUnderLine = false, bool isUnderLine = false,
bool isBold = false, bool isBold = false,
@ -205,6 +192,7 @@ extension EmailValidator on String {
int? maxlines, int? maxlines,
double? letterSpacing = 0, double? letterSpacing = 0,
double? height, double? height,
String? fontFamily,
TextOverflow? textOverflow, TextOverflow? textOverflow,
}) => }) =>
Text( Text(
@ -219,18 +207,11 @@ extension EmailValidator on String {
height: height, height: height,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null, decoration: isUnderLine ? TextDecoration.underline : null,
fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
decorationColor: color ?? AppColors.blackColor), decorationColor: color ?? AppColors.blackColor),
); );
Widget toText15( Widget toText15({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, FontWeight? weight, int? maxlines, double? letterSpacing = -1}) => Text(
{Color? color,
bool isUnderLine = false,
bool isBold = false,
bool isCenter = false,
FontWeight? weight,
int? maxlines,
double? letterSpacing = -1}) =>
Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
maxLines: maxlines, maxLines: maxlines,
@ -242,8 +223,7 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null), decoration: isUnderLine ? TextDecoration.underline : null),
); );
Widget toText16( Widget toText16({bool isEnglishOnly = false, Color? color,
{Color? color,
bool isUnderLine = false, bool isUnderLine = false,
bool isBold = false, bool isBold = false,
bool isCenter = false, bool isCenter = false,
@ -252,12 +232,14 @@ extension EmailValidator on String {
TextAlign? textAlign, TextAlign? textAlign,
FontWeight? weight, FontWeight? weight,
TextOverflow? textOverflow, TextOverflow? textOverflow,
String? fontFamily,
double? letterSpacing = -0.4, double? letterSpacing = -0.4,
Color decorationColor = AppColors.errorColor}) => Color decorationColor = AppColors.errorColor}) =>
Text( Text(
this, this,
maxLines: maxlines, maxLines: maxlines,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? textAlign ?? TextAlign.center : null,
// locale: Locale('en', 'US'),
style: TextStyle( style: TextStyle(
color: color ?? AppColors.blackColor, color: color ?? AppColors.blackColor,
fontSize: 16.f, fontSize: 16.f,
@ -266,14 +248,14 @@ extension EmailValidator on String {
overflow: textOverflow, overflow: textOverflow,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null, decoration: isUnderLine ? TextDecoration.underline : null,
fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
decorationColor: decorationColor), decorationColor: decorationColor),
); );
Widget toText17({Color? color, bool isBold = false, bool isCenter = false}) => Text( Widget toText17({bool isEnglishOnly = false, Color? color, bool isBold = false, bool isCenter = false}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
style: TextStyle( style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
); );
Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow}) => Text( Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow}) => Text(
@ -281,17 +263,12 @@ extension EmailValidator on String {
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
this, this,
overflow: textOverflow, overflow: textOverflow,
style: TextStyle( style: TextStyle(fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
fontSize: 18.f,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: -0.4),
); );
Widget toText19({Color? color, bool isBold = false}) => Text( Widget toText19({Color? color, bool isBold = false}) => Text(
this, this,
style: TextStyle( style: TextStyle(fontSize: 19.f, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4),
fontSize: 19.f, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4),
); );
Widget toText20({ Widget toText20({
@ -301,86 +278,51 @@ extension EmailValidator on String {
}) => }) =>
Text( Text(
this, this,
style: TextStyle( style: TextStyle(fontSize: 20.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
fontSize: 20.f,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: -0.4),
); );
Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text( Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text(
this, this,
maxLines: maxlines, maxLines: maxlines,
style: TextStyle( style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.f, letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
color: color ?? AppColors.blackColor,
fontSize: 21.f,
letterSpacing: -1,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
); );
Widget toText22({Color? color, bool isBold = false, bool isCenter = false}) => Text( Widget toText22({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
style: TextStyle( style: TextStyle(height: 1, color: color ?? AppColors.blackColor, fontSize: 22.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
height: 1,
color: color ?? AppColors.blackColor,
fontSize: 22.f,
letterSpacing: -1,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
); );
Widget toText24({Color? color, bool isBold = false, bool isCenter = false, FontWeight? fontWeight, double? letterSpacing}) => Text( Widget toText24({Color? color, bool isBold = false, bool isCenter = false, FontWeight? fontWeight, double? letterSpacing}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
style: TextStyle( style: TextStyle(
height: 23 / 24, height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.f, letterSpacing: letterSpacing ?? -1, fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.normal),
color: color ?? AppColors.blackColor,
fontSize: 24.f,
letterSpacing: letterSpacing ?? -1,
fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.normal),
); );
Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false, FontWeight? weight, double? letterSpacing}) => Text( Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false, FontWeight? weight, double? letterSpacing}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
style: TextStyle( style: TextStyle(
height: height ?? 23 / 26, height: height ?? 23 / 26, color: color ?? AppColors.blackColor, fontSize: 26.f, letterSpacing: letterSpacing ?? -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
color: color ?? AppColors.blackColor,
fontSize: 26.f,
letterSpacing: letterSpacing ?? -1,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
); );
Widget toText28({Color? color, bool isBold = false, double? height, bool isCenter = false, double? letterSpacing}) => Text( Widget toText28({bool isEnglishOnly = false, Color? color, bool isBold = false, double? height, bool isCenter = false, double? letterSpacing}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
style: TextStyle( style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.f, letterSpacing: letterSpacing ?? -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
height: height ?? 23 / 28,
color: color ?? AppColors.blackColor,
fontSize: 28.f,
letterSpacing: letterSpacing ?? -1,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
); );
Widget toText32({FontWeight? weight, Color? color, bool isBold = false, bool isCenter = false}) => Text( Widget toText32({bool isEnglishOnly = false, FontWeight? weight, Color? color, bool isBold = false, bool isCenter = false}) => Text(
this, this,
textAlign: isCenter ? TextAlign.center : null, textAlign: isCenter ? TextAlign.center : null,
style: TextStyle( style: TextStyle(
height: 32 / 32, height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontFamily: isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
color: color ?? AppColors.blackColor,
fontSize: 32.f,
letterSpacing: -1,
fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
); );
Widget toText44({Color? color, bool isBold = false}) => Text( Widget toText44({Color? color, bool isBold = false}) => Text(
this, this,
style: TextStyle( style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
height: 32 / 32,
color: color ?? AppColors.blackColor,
fontSize: 44.f,
letterSpacing: -1,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
); );
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) { Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {
@ -416,9 +358,7 @@ extension EmailValidator on String {
} }
bool isValidEmail() { bool isValidEmail() {
return RegExp( return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this);
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
.hasMatch(this);
} }
String toFormattedDate() { String toFormattedDate() {
@ -485,11 +425,12 @@ extension DynamicTextStyleExtension on BuildContext {
Locale? locale, Locale? locale,
TextBaseline? textBaseline, TextBaseline? textBaseline,
FontStyle? fontStyle, FontStyle? fontStyle,
String? fontFamily,
bool isLanguageSwitcher = false}) { bool isLanguageSwitcher = false}) {
AppState appState = getIt.get<AppState>(); AppState appState = getIt.get<AppState>();
final family = appState.getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'; final family = appState.getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins';
return TextStyle( return TextStyle(
fontFamily: family, fontFamily: fontFamily ?? family,
fontSize: fontSize, fontSize: fontSize,
fontWeight: fontWeight, fontWeight: fontWeight,
color: color, color: color,

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle; import 'package:flutter/services.dart' show rootBundle;
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart'; import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.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/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart'; import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
@ -74,6 +75,7 @@ class AuthenticationViewModel extends ChangeNotifier {
dobController = TextEditingController(), dobController = TextEditingController(),
nameController = TextEditingController(), nameController = TextEditingController(),
emailController = TextEditingController(); emailController = TextEditingController();
CountryEnum selectedCountrySignup = CountryEnum.saudiArabia; CountryEnum selectedCountrySignup = CountryEnum.saudiArabia;
MaritalStatusTypeEnum? maritalStatus; MaritalStatusTypeEnum? maritalStatus;
GenderTypeEnum? genderType; GenderTypeEnum? genderType;
@ -279,9 +281,10 @@ class AuthenticationViewModel extends ChangeNotifier {
loginTypeEnum = otpTypeEnum == OTPTypeEnum.sms ? LoginTypeEnum.sms : LoginTypeEnum.whatsapp; loginTypeEnum = otpTypeEnum == OTPTypeEnum.sms ? LoginTypeEnum.sms : LoginTypeEnum.whatsapp;
if (phoneNumberController.text.isEmpty) { // if (phoneNumberController.text.isEmpty) {
phoneNumberController.text = "504278212"; // phoneNumberController.text = "504278212";
} // }
bool isValidated = ValidationUtils.isValidatePhoneAndId(phoneNumber: phoneNumberController.text, nationalId: nationalIdController.text); bool isValidated = ValidationUtils.isValidatePhoneAndId(phoneNumber: phoneNumberController.text, nationalId: nationalIdController.text);
if (!isValidated) { if (!isValidated) {
@ -404,7 +407,6 @@ class AuthenticationViewModel extends ChangeNotifier {
return; return;
} }
patientShareRequestID = apiResponse.data['PatientShareRequestID']; patientShareRequestID = apiResponse.data['PatientShareRequestID'];
print("PatientShareRequestID ==============: $patientShareRequestID");
_appState.setFamilyFileTokenID = apiResponse.data['LogInTokenID']; _appState.setFamilyFileTokenID = apiResponse.data['LogInTokenID'];
} }
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
@ -580,9 +582,13 @@ class AuthenticationViewModel extends ChangeNotifier {
MedicalFileViewModel medicalVm = getIt<MedicalFileViewModel>(); MedicalFileViewModel medicalVm = getIt<MedicalFileViewModel>();
if (!_appState.getIsChildLoggedIn) { if (!_appState.getIsChildLoggedIn) {
await medicalVm.getFamilyFiles(status: 0); await medicalVm.getFamilyFiles(status: 0);
if (isFormFamilyFile) {
await medicalVm.getAllPendingRecordsByResponseId();
_navigationService.pushAndReplace(AppRoutes.medicalFilePage);
} else {
_navigationService.replaceAllRoutesAndNavigateToLanding();
}
// await medicalVm.getAllPendingRecordsByResponseId(); // await medicalVm.getAllPendingRecordsByResponseId();
// _navigationService.replaceAllRoutesAndNavigateToLanding();
_navigationService.popUntilNamed(AppRoutes.landingScreen);
} }
} else { } else {
if (activation.list != null && activation.list!.isNotEmpty) { if (activation.list != null && activation.list!.isNotEmpty) {
@ -742,7 +748,12 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> onWrongActivationCode({String? message}) async { Future<void> onWrongActivationCode({String? message}) async {
otpScreenNotifier.value = true; otpScreenNotifier.value = true;
await _dialogService.showErrorBottomSheet(message: message ?? "Something went wrong. ", onOkPressed: () {}); await _dialogService.showErrorBottomSheet(
message: message ?? "Something went wrong. ",
onOkPressed: () {
LoaderBottomSheet.hideLoader();
_navigationService.pushAndReplace(AppRoutes.loginScreen);
});
} }
loginWithFingerPrintFace(Function success) async { loginWithFingerPrintFace(Function success) async {
@ -836,7 +847,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} else { } else {
LoadingUtils.hideFullScreenLoader(); LoadingUtils.hideFullScreenLoader();
if (apiResponse.data["MessageStatus"] == 1) { 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. //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. await clearDefaultInputValues(); // This will Clear All Default Values Of User.
Future.delayed(Duration(seconds: 1), () { Future.delayed(Duration(seconds: 1), () {
@ -1045,6 +1056,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
Future<void> getServicePrivilege() async { Future<void> getServicePrivilege() async {
ApiConsts.setBackendURLs();
final resultEither = await _authenticationRepo.getServicePrivilege(); final resultEither = await _authenticationRepo.getServicePrivilege();
List<ListPrivilege> privilegeModelList = []; List<ListPrivilege> privilegeModelList = [];
List<VidaPlusProjectListModel> vidaPlusProjectListModel = []; List<VidaPlusProjectListModel> vidaPlusProjectListModel = [];
@ -1052,7 +1064,10 @@ class AuthenticationViewModel extends ChangeNotifier {
List<ProjectDetailListModel> projectDetailListModel = []; List<ProjectDetailListModel> projectDetailListModel = [];
resultEither.fold( resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure), // (failure) async => await _errorHandlerService.handleError(failure: failure),
(failure) async {
print(failure.message);
},
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty");

@ -185,7 +185,7 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
body: mapDevice, body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) { onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType; failure = failureType;
onError!(error); // onError!(error);
}, },
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {

@ -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/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_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/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 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'models/resp_models/get_livecare_clinics_response_model.dart'; import 'models/resp_models/get_livecare_clinics_response_model.dart';
@ -103,6 +104,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
String selectedAppointmentDate = ""; String selectedAppointmentDate = "";
String selectedAppointmentTime = ""; String selectedAppointmentTime = "";
String selectedAppointmentDisplayDate = "";
dynamic freeSlotsResponse; dynamic freeSlotsResponse;
@ -385,9 +387,10 @@ class BookAppointmentsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
setSelectedAppointmentDateTime(String date, String time) { setSelectedAppointmentDateTime(String date, String time, String displayDate) {
selectedAppointmentDate = date; selectedAppointmentDate = date;
selectedAppointmentTime = time; selectedAppointmentTime = time;
selectedAppointmentDisplayDate = displayDate;
notifyListeners(); notifyListeners();
} }
@ -581,7 +584,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
result.fold( result.fold(
(failure) async { (failure) async {
onError?.call(LocaleKeys.noDoctorFound.tr()); onError?.call(selectedClinic.clinicID == 23 ? failure.message : LocaleKeys.noDoctorFound.tr());
}, },
(apiResponse) async { (apiResponse) async {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
@ -721,7 +724,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
Future<void> getLiveCareDoctorFreeSlots({bool isBookingForLiveCare = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getLiveCareDoctorFreeSlots({bool isBookingForLiveCare = false, Function(dynamic)? onSuccess, Function(String)? onError}) async {
docFreeSlots.clear(); docFreeSlots.clear();
DateTime date; DateTime date;
final DateFormat formatter = DateFormat('HH:mm'); final DateFormat formatter = DateFormat('HH:mm', "en-US");
final DateFormat dateFormatter = DateFormat('yyyy-MM-dd'); final DateFormat dateFormatter = DateFormat('yyyy-MM-dd');
Map<DateTime, List> _eventsParsed; Map<DateTime, List> _eventsParsed;
@ -806,6 +809,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
result.fold( result.fold(
(failure) async { (failure) async {
print(failure); print(failure);
onError!(failure.message);
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
@ -835,16 +839,11 @@ class BookAppointmentsViewModel extends ChangeNotifier {
appointmentDate: apiResponse.data["SameClinicApptList"][0]['AppointmentDate'], appointmentDate: apiResponse.data["SameClinicApptList"][0]['AppointmentDate'],
); );
showCommonBottomSheet(navigationService.navigatorKey.currentContext!, LoaderBottomSheet.showLoader(
child: Utils.getLoadingWidget(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr()), loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!),
callBackFunc: (str) {}, );
title: "",
height: ResponsiveExtension.screenHeight * 0.3,
isCloseButtonVisible: false,
isDismissible: false,
isFullScreen: false);
await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async {
navigationService.pop(); LoaderBottomSheet.hideLoader();
Future.delayed(Duration(milliseconds: 50)).then((value) async {}); Future.delayed(Duration(milliseconds: 50)).then((value) async {});
LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: LocaleKeys.bookingYourAppointment.tr()); LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: LocaleKeys.bookingYourAppointment.tr());
await insertSpecificAppointment( await insertSpecificAppointment(

@ -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/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_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_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/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
@ -17,6 +18,8 @@ abstract class ContactUsRepo {
Future<Either<Failure, GenericApiModel<String>>> getChatRequestID({required String name, required String mobileNo, required String workGroup}); Future<Either<Failure, GenericApiModel<String>>> getChatRequestID({required String name, required String mobileNo, required String workGroup});
Future<Either<Failure, GenericApiModel<dynamic>>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment}); Future<Either<Failure, GenericApiModel<dynamic>>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment});
Future<Either<Failure, GenericApiModel<List<COCItem>>>> getStatusForCOC(String identificationNo, String mobileNo, {Function(dynamic)? onSuccess, Function(String)? onError});
} }
class ContactUsRepoImp implements ContactUsRepo { class ContactUsRepoImp implements ContactUsRepo {
@ -181,4 +184,44 @@ class ContactUsRepoImp implements ContactUsRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<List<COCItem>>>> getStatusForCOC(String identificationNo, String mobileNo, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
Map<String, dynamic> body = {};
body['IdentificationNo'] = identificationNo;
body['MobileNo'] = mobileNo;
body['Searching_type'] = 1;
try {
GenericApiModel<List<COCItem>>? 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<String, dynamic>)).toList().cast<COCItem>();
apiResponse = GenericApiModel<List<COCItem>>(
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()));
}
}
} }

@ -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/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_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_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/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
@ -33,6 +34,9 @@ class ContactUsViewModel extends ChangeNotifier {
List<String> feedbackAttachmentList = []; List<String> feedbackAttachmentList = [];
List<COCItem> cocItemsList = [];
bool isCOCItemsListLoading = false;
PatientAppointmentHistoryResponseModel? patientFeedbackSelectedAppointment; PatientAppointmentHistoryResponseModel? patientFeedbackSelectedAppointment;
List<FeedbackType> feedbackTypeList = [ List<FeedbackType> feedbackTypeList = [
@ -52,10 +56,12 @@ class ContactUsViewModel extends ChangeNotifier {
isHMGLocationsListLoading = true; isHMGLocationsListLoading = true;
isHMGHospitalsListSelected = true; isHMGHospitalsListSelected = true;
isLiveChatProjectsListLoading = true; isLiveChatProjectsListLoading = true;
isCOCItemsListLoading = true;
hmgHospitalsLocationsList.clear(); hmgHospitalsLocationsList.clear();
hmgPharmacyLocationsList.clear(); hmgPharmacyLocationsList.clear();
liveChatProjectsList.clear(); liveChatProjectsList.clear();
feedbackAttachmentList.clear(); feedbackAttachmentList.clear();
cocItemsList.clear();
selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'); selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد');
setPatientFeedbackSelectedAppointment(null); setPatientFeedbackSelectedAppointment(null);
getHMGLocations(); getHMGLocations();
@ -74,6 +80,9 @@ class ContactUsViewModel extends ChangeNotifier {
setIsSendFeedbackTabSelected(bool isSelected) { setIsSendFeedbackTabSelected(bool isSelected) {
isSendFeedbackTabSelected = isSelected; isSendFeedbackTabSelected = isSelected;
if (!isSelected) {
getStatusForCOC(identificationNo: appState.getAuthenticatedUser()!.patientIdentificationNo!, mobileNo: "966${Utils.getPhoneNumberWithoutZero(appState.getAuthenticatedUser()!.mobileNumber!)}");
}
notifyListeners(); notifyListeners();
} }
@ -223,4 +232,38 @@ class ContactUsViewModel extends ChangeNotifier {
}, },
); );
} }
Future<void> 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);
}
}
},
);
}
} }

@ -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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
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;
}
}

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.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/enums.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_repo.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_repo.dart';
@ -17,6 +18,7 @@ import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get
import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/search_e_referral_resp_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/search_e_referral_resp_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/vital_sign_respo_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/vital_sign_respo_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/services/error_handler_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/services/navigation_service.dart';
@ -31,8 +33,7 @@ class HmgServicesViewModel extends ChangeNotifier {
final ErrorHandlerService errorHandlerService; final ErrorHandlerService errorHandlerService;
final NavigationService navigationService; final NavigationService navigationService;
HmgServicesViewModel( HmgServicesViewModel({required this.bookAppointmentsRepo, required this.hmgServicesRepo, required this.errorHandlerService, required this.navigationService});
{required this.bookAppointmentsRepo, required this.hmgServicesRepo, required this.errorHandlerService, required this.navigationService});
bool isCmcOrdersLoading = false; bool isCmcOrdersLoading = false;
bool isCmcServicesLoading = false; bool isCmcServicesLoading = false;
@ -55,9 +56,11 @@ class HmgServicesViewModel extends ChangeNotifier {
// Vital Sign PageView Controller // Vital Sign PageView Controller
PageController _vitalSignPageController = PageController(); PageController _vitalSignPageController = PageController();
PageController get vitalSignPageController => _vitalSignPageController; PageController get vitalSignPageController => _vitalSignPageController;
int _vitalSignCurrentPage = 0; int _vitalSignCurrentPage = 0;
int get vitalSignCurrentPage => _vitalSignCurrentPage; int get vitalSignCurrentPage => _vitalSignCurrentPage;
void setVitalSignCurrentPage(int page) { void setVitalSignCurrentPage(int page) {
@ -65,7 +68,6 @@ class HmgServicesViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
// HHC specific lists // HHC specific lists
List<GetCMCAllOrdersResponseModel> hhcOrdersList = []; List<GetCMCAllOrdersResponseModel> hhcOrdersList = [];
List<GetCMCServicesResponseModel> hhcServicesList = []; List<GetCMCServicesResponseModel> hhcServicesList = [];
@ -82,9 +84,8 @@ class HmgServicesViewModel extends ChangeNotifier {
List<SearchEReferralResponseModel> searchReferralList = []; List<SearchEReferralResponseModel> searchReferralList = [];
List<Covid19GetTestProceduresResp> covidTestProcedureList = []; List<Covid19GetTestProceduresResp> covidTestProcedureList = [];
Covid19GetPaymentInfo? covidPaymentInfo; Covid19GetPaymentInfo? covidPaymentInfo;
Future<void> getOrdersList() async {}
Future<void> getOrdersList() async {}
// HHC multiple services selection // HHC multiple services selection
List<GetCMCServicesResponseModel> selectedHhcServices = []; List<GetCMCServicesResponseModel> selectedHhcServices = [];
@ -792,22 +793,20 @@ class HmgServicesViewModel extends ChangeNotifier {
}, },
); );
} }
List<CovidQuestionnaireModel> getQuestionsFromJson() { List<CovidQuestionnaireModel> getQuestionsFromJson() {
final String questionsJson = '''[ { "id": 1, "questionEN": "Is the test intended for travel?", "questionAR": "هل تجري التحليل بغرض السفر؟", "ans": 2 }, { "id": 2, "questionEN": "Coming from outside KSA within last 2 weeks?", "questionAR": "هل قدمت من خارج المملكة خلال الأسبوعين الماضيين؟", "ans": 2 }, { "id": 3, "questionEN": "Do you currently have fever?", "questionAR": "هل تعاني حاليا من حرارة؟", "ans": 2 }, { "id": 4, "questionEN": "Did you have fever in last 2 weeks?", "questionAR": "هل عانيت من حرارة في الأسبوعين الماضيين؟", "ans": 2 }, { "id": 5, "questionEN": "Do you have a sore throat?", "questionAR": "هل لديك التهاب في الحلق؟", "ans": 2 }, { "id": 6, "questionEN": "Do you have a runny nose?", "questionAR": "هل لديك سيلان بالأنف؟" }, { "id": 7, "questionEN": "Do you have a cough?", "questionAR": "هل لديك سعال؟", "ans": 2 }, { "id": 8, "questionEN": "Do you have shortness of breath?", "questionAR": "هل تعاني من ضيق في التنفس؟", "ans": 2 }, { "id": 9, "questionEN": "Do you have nausea?", "questionAR": "هل تعاني من غثيان؟", "ans": 2 }, { "id": 10, "questionEN": "Do you have vomiting?", "questionAR": "هل تعاني من القيء؟", "ans": 2 }, { "id": 11, "questionEN": "Do you have a headache?", "questionAR": "هل تعاني من صداع في الرأس؟", "ans": 2 }, { "id": 12, "questionEN": "Do you have muscle pain?", "questionAR": "هل تعانين من آلام عضلية؟", "ans": 2 }, { "id": 13, "questionEN": "Do you have joint pain?", "questionAR": "هل تعاني من آلام المفاصل؟", "ans": 2 }, { "id": 14, "questionEN": "Do you have diarrhea?", "questionAR": "هل لديك اسهال؟", "ans": 2 } ]'''; final String questionsJson =
'''[ { "id": 1, "questionEN": "Is the test intended for travel?", "questionAR": "هل تجري التحليل بغرض السفر؟", "ans": 2 }, { "id": 2, "questionEN": "Coming from outside KSA within last 2 weeks?", "questionAR": "هل قدمت من خارج المملكة خلال الأسبوعين الماضيين؟", "ans": 2 }, { "id": 3, "questionEN": "Do you currently have fever?", "questionAR": "هل تعاني حاليا من حرارة؟", "ans": 2 }, { "id": 4, "questionEN": "Did you have fever in last 2 weeks?", "questionAR": "هل عانيت من حرارة في الأسبوعين الماضيين؟", "ans": 2 }, { "id": 5, "questionEN": "Do you have a sore throat?", "questionAR": "هل لديك التهاب في الحلق؟", "ans": 2 }, { "id": 6, "questionEN": "Do you have a runny nose?", "questionAR": "هل لديك سيلان بالأنف؟" }, { "id": 7, "questionEN": "Do you have a cough?", "questionAR": "هل لديك سعال؟", "ans": 2 }, { "id": 8, "questionEN": "Do you have shortness of breath?", "questionAR": "هل تعاني من ضيق في التنفس؟", "ans": 2 }, { "id": 9, "questionEN": "Do you have nausea?", "questionAR": "هل تعاني من غثيان؟", "ans": 2 }, { "id": 10, "questionEN": "Do you have vomiting?", "questionAR": "هل تعاني من القيء؟", "ans": 2 }, { "id": 11, "questionEN": "Do you have a headache?", "questionAR": "هل تعاني من صداع في الرأس؟", "ans": 2 }, { "id": 12, "questionEN": "Do you have muscle pain?", "questionAR": "هل تعانين من آلام عضلية؟", "ans": 2 }, { "id": 13, "questionEN": "Do you have joint pain?", "questionAR": "هل تعاني من آلام المفاصل؟", "ans": 2 }, { "id": 14, "questionEN": "Do you have diarrhea?", "questionAR": "هل لديك اسهال؟", "ans": 2 } ]''';
try { try {
final parsed = json.decode(questionsJson) as List<dynamic>; final parsed = json.decode(questionsJson) as List<dynamic>;
return parsed return parsed.map((e) => CovidQuestionnaireModel.fromJson(Map<String, dynamic>.from(e))).toList();
.map((e) => CovidQuestionnaireModel.fromJson(Map<String, dynamic>.from(e)))
.toList();
} catch (_) { } catch (_) {
return <CovidQuestionnaireModel>[]; return <CovidQuestionnaireModel>[];
} }
} }
Future<void> getCovidProcedureList({ Future<void> getCovidProcedureList({
Function(dynamic)? onSuccess, Function(dynamic)? onSuccess,
Function(String)? onError, Function(String)? onError,
}) async { }) async {
@ -816,14 +815,14 @@ class HmgServicesViewModel extends ChangeNotifier {
final result = await hmgServicesRepo.getCovidTestProcedures(); final result = await hmgServicesRepo.getCovidTestProcedures();
result.fold( result.fold(
(failure) async { (failure) async {
notifyListeners(); notifyListeners();
await errorHandlerService.handleError(failure: failure); await errorHandlerService.handleError(failure: failure);
if (onError != null) { if (onError != null) {
onError(failure.toString()); onError(failure.toString());
} }
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 1) { if (apiResponse.messageStatus == 1) {
covidTestProcedureList = apiResponse.data ?? []; covidTestProcedureList = apiResponse.data ?? [];
notifyListeners(); notifyListeners();
@ -840,7 +839,6 @@ class HmgServicesViewModel extends ChangeNotifier {
); );
} }
Future<void> getPaymentInfo({ Future<void> getPaymentInfo({
String? procedureID, String? procedureID,
int? projectID, int? projectID,
@ -852,14 +850,14 @@ class HmgServicesViewModel extends ChangeNotifier {
final result = await hmgServicesRepo.getCovidPaymentInfo(procedureID!, projectID!); final result = await hmgServicesRepo.getCovidPaymentInfo(procedureID!, projectID!);
result.fold( result.fold(
(failure) async { (failure) async {
notifyListeners(); notifyListeners();
await errorHandlerService.handleError(failure: failure); await errorHandlerService.handleError(failure: failure);
if (onError != null) { if (onError != null) {
onError(failure.toString()); onError(failure.toString());
} }
}, },
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 1) { if (apiResponse.messageStatus == 1) {
covidPaymentInfo = apiResponse.data; covidPaymentInfo = apiResponse.data;
notifyListeners(); notifyListeners();
@ -900,6 +898,8 @@ class HmgServicesViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 1) { if (apiResponse.messageStatus == 1) {
vitalSignList = apiResponse.data ?? []; vitalSignList = apiResponse.data ?? [];
hasVitalSignDataLoaded = true; hasVitalSignDataLoaded = true;
getIt.get<SymptomsCheckerViewModel>().setSelectedHeight(vitalSignList.first.heightCm);
getIt.get<SymptomsCheckerViewModel>().setSelectedWeight(vitalSignList.first.weightKg);
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);

@ -97,7 +97,7 @@ class HospitalSelectionBottomSheetViewModel extends ChangeNotifier {
initPenguinSDK(hospital.iD, clinicID: clinicID); initPenguinSDK(hospital.iD, clinicID: clinicID);
} }
initPenguinSDK(int projectID, {String clinicID = "1"}) async { initPenguinSDK(int projectID, {String clinicID = ""}) async {
NavigationClinicDetails data = NavigationClinicDetails(); NavigationClinicDetails data = NavigationClinicDetails();
data.projectId = projectID.toString(); data.projectId = projectID.toString();
data.clinicId = clinicID; data.clinicId = clinicID;

@ -1,16 +1,26 @@
import 'dart:async'; import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.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/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.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/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/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/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_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_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/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/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/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'; import '../../services/navigation_service.dart';
@ -42,6 +52,9 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
late ValueNotifier<Duration> durationNotifier; late ValueNotifier<Duration> durationNotifier;
late Timer timer; late Timer timer;
bool isShowNotEligibleDialog = false;
String notEligibleErrorMsg = "";
initImmediateLiveCare() { initImmediateLiveCare() {
_appState = getIt<AppState>(); _appState = getIt<AppState>();
immediateLiveCareClinicsList = []; immediateLiveCareClinicsList = [];
@ -102,8 +115,80 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
liveCareImmediateAppointmentFeesList = apiResponse.data!; 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<NavigationService>().navigatorKey.currentContext!);
} else {
isShowNotEligibleDialog = true;
notEligibleErrorMsg = LocaleKeys.invalidInsurance.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!);
}
}
}
if (isShowNotEligibleDialog) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(GetIt.instance<NavigationService>().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<NavigationService>().navigatorKey.currentContext!),
cancelText: LocaleKeys.continueCash.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
isShowActionButtons: true,
onCancelTap: () {
Navigator.pop(GetIt.instance<NavigationService>().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<NavigationService>().navigatorKey.currentContext!),
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
onConfirmTap: () async {
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
Navigator.push(
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
CustomPageRoute(
page: InsuranceHomePage(),
),
);
}),
), callBackFunc: () {
// Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
}, isFullScreen: false, isCloseButtonVisible: false, isDismissible: false);
}
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null && !isShowNotEligibleDialog) {
onSuccess(apiResponse); onSuccess(apiResponse);
} }
} }

@ -18,6 +18,7 @@ class InsuranceViewModel extends ChangeNotifier {
bool isInsuranceApprovalsLoading = false; bool isInsuranceApprovalsLoading = false;
bool isInsuranceExpired = false; bool isInsuranceExpired = false;
bool isInsuranceActive = false;
InsuranceRepo insuranceRepo; InsuranceRepo insuranceRepo;
ErrorHandlerService errorHandlerService; ErrorHandlerService errorHandlerService;
@ -79,6 +80,8 @@ class InsuranceViewModel extends ChangeNotifier {
(failure) async { (failure) async {
isInsuranceLoading = false; isInsuranceLoading = false;
isInsuranceDataToBeLoaded = false; isInsuranceDataToBeLoaded = false;
isInsuranceExpired = false;
isInsuranceActive = false;
notifyListeners(); notifyListeners();
}, },
(apiResponse) { (apiResponse) {
@ -94,6 +97,9 @@ class InsuranceViewModel extends ChangeNotifier {
DateUtil.convertStringToDate(patientInsuranceList.first.cardValidTo), DateUtil.convertStringToDate(patientInsuranceList.first.cardValidTo),
); );
isInsuranceActive = patientInsuranceList.first.isActive ?? false;
// isInsuranceActive = true;
notifyListeners(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);

@ -5,6 +5,8 @@ import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/ai_overview_labresults_by_ai_model.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_order_response_by_ai_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/features/lab/models/resp_models/patient_lab_orders_response_model.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_special_result.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_special_result.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
@ -13,6 +15,7 @@ import 'models/resp_models/lab_result.dart' show LabResult;
abstract class LabRepo { abstract class LabRepo {
Future<Either<Failure, GenericApiModel<List<PatientLabOrdersResponseModel>>>> getPatientLabOrders(); Future<Either<Failure, GenericApiModel<List<PatientLabOrdersResponseModel>>>> getPatientLabOrders();
Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResults(PatientLabOrdersResponseModel laborder, bool isVidaPlus, String procedureName); Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResults(PatientLabOrdersResponseModel laborder, bool isVidaPlus, String procedureName);
Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResultsByHospitals(PatientLabOrdersResponseModel laborder, bool isVidaPlus); Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResultsByHospitals(PatientLabOrdersResponseModel laborder, bool isVidaPlus);
@ -22,6 +25,10 @@ abstract class LabRepo {
Future<Either<Failure, GenericApiModel<String>>> getLabResultReportPDF({required PatientLabOrdersResponseModel labOrder}); Future<Either<Failure, GenericApiModel<String>>> getLabResultReportPDF({required PatientLabOrdersResponseModel labOrder});
Future<Either<Failure, GenericApiModel<dynamic>>> getLabResultsByAppointmentNo({required num appointmentNo, required num projectID, required num clinicID}); Future<Either<Failure, GenericApiModel<dynamic>>> getLabResultsByAppointmentNo({required num appointmentNo, required num projectID, required num clinicID});
Future<Either<Failure, GenericApiModel<LabOrdersResponseByAi>>> getPatientAiOverViewLabOrders(var payload);
Future<Either<Failure, GenericApiModel<LabOrderResponseByAi>>> getPatientAiOverViewLabOrder(var payload);
} }
class LabRepoImp implements LabRepo { class LabRepoImp implements LabRepo {
@ -71,10 +78,7 @@ class LabRepoImp implements LabRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResults( Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResults(PatientLabOrdersResponseModel laborder, bool isVidaPlus, String procedureName) async {
PatientLabOrdersResponseModel laborder, bool isVidaPlus, String procedureName
) async {
Map<String, dynamic> request = Map(); Map<String, dynamic> request = Map();
request['InvoiceNo_VP'] = isVidaPlus ? laborder!.invoiceNo : "0"; request['InvoiceNo_VP'] = isVidaPlus ? laborder!.invoiceNo : "0";
request['InvoiceNo'] = isVidaPlus ? "0" : laborder!.invoiceNo; request['InvoiceNo'] = isVidaPlus ? "0" : laborder!.invoiceNo;
@ -100,10 +104,7 @@ class LabRepoImp implements LabRepo {
throw Exception("lab list is empty"); throw Exception("lab list is empty");
} }
final labOrders = list final labOrders = list.map((item) => LabResult.fromJson(item as Map<String, dynamic>)).toList().cast<LabResult>();
.map((item) => LabResult.fromJson(item as Map<String, dynamic>))
.toList()
.cast<LabResult>();
apiResponse = GenericApiModel<List<LabResult>>( apiResponse = GenericApiModel<List<LabResult>>(
messageStatus: messageStatus, messageStatus: messageStatus,
@ -125,9 +126,7 @@ class LabRepoImp implements LabRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<LabResult>>>> Future<Either<Failure, GenericApiModel<List<LabResult>>>> getPatientLabResultsByHospitals(PatientLabOrdersResponseModel laborder, bool isVidaPlus) async {
getPatientLabResultsByHospitals(
PatientLabOrdersResponseModel laborder, bool isVidaPlus) async {
Map<String, dynamic> request = Map(); Map<String, dynamic> request = Map();
request['InvoiceNo_VP'] = isVidaPlus ? laborder!.invoiceNo : "0"; request['InvoiceNo_VP'] = isVidaPlus ? laborder!.invoiceNo : "0";
request['InvoiceNo'] = isVidaPlus ? "0" : laborder!.invoiceNo; request['InvoiceNo'] = isVidaPlus ? "0" : laborder!.invoiceNo;
@ -175,9 +174,7 @@ class LabRepoImp implements LabRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<List<PatientLabSpecialResult>>>> Future<Either<Failure, GenericApiModel<List<PatientLabSpecialResult>>>> getSpecialLabResult(PatientLabOrdersResponseModel laborder, bool isVidaPlus) async {
getSpecialLabResult(
PatientLabOrdersResponseModel laborder, bool isVidaPlus) async {
Map<String, dynamic> request = Map(); Map<String, dynamic> request = Map();
request['InvoiceNo_VP'] = isVidaPlus ? laborder!.invoiceNo : "0"; request['InvoiceNo_VP'] = isVidaPlus ? laborder!.invoiceNo : "0";
request['InvoiceNo'] = isVidaPlus ? "0" : laborder!.invoiceNo; request['InvoiceNo'] = isVidaPlus ? "0" : laborder!.invoiceNo;
@ -203,11 +200,7 @@ class LabRepoImp implements LabRepo {
throw Exception("lab list is empty"); throw Exception("lab list is empty");
} }
final labOrders = list final labOrders = list.map((item) => PatientLabSpecialResult.fromJson(item as Map<String, dynamic>)).toList().cast<PatientLabSpecialResult>();
.map((item) => PatientLabSpecialResult.fromJson(
item as Map<String, dynamic>))
.toList()
.cast<PatientLabSpecialResult>();
apiResponse = GenericApiModel<List<PatientLabSpecialResult>>( apiResponse = GenericApiModel<List<PatientLabSpecialResult>>(
messageStatus: messageStatus, messageStatus: messageStatus,
@ -318,4 +311,76 @@ class LabRepoImp implements LabRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<LabOrderResponseByAi>>> getPatientAiOverViewLabOrder(var labOrder) async {
try {
GenericApiModel<LabOrderResponseByAi>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.getAiOverViewLabOrder,
body: labOrder,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
var res;
if (response["analysis_result"] != null) {
res = response["analysis_result"];
}
apiResponse = GenericApiModel<LabOrderResponseByAi>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: LabOrderResponseByAi.fromJson(res),
);
} 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()));
}
}
@override
Future<Either<Failure, GenericApiModel<LabOrdersResponseByAi>>> getPatientAiOverViewLabOrders(var labOrder) async {
try {
GenericApiModel<LabOrdersResponseByAi>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.getAiOverViewLabOrders,
body: {"lab_results": labOrder},
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
var res;
if (response["lab_analysis_result"] != null) {
res = response["lab_analysis_result"];
}
apiResponse = GenericApiModel<LabOrdersResponseByAi>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: LabOrdersResponseByAi.fromJson(res),
);
} 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()));
}
}
} }

@ -1,16 +1,24 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart'; import 'package:hmg_patient_app_new/core/common_models/data_points.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/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils; import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils;
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart'; import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/models/ai_overview_labresult_model_payload.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/ai_overview_labresults_by_ai_model.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/lab_result.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/lab_result.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_order_response_by_ai_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/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_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/lab/lab_results/lab_result_details.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/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_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/theme/colors.dart';
@ -53,20 +61,7 @@ class LabViewModel extends ChangeNotifier {
List<LabResult> mainLabResults = []; List<LabResult> mainLabResults = [];
List<DataPoint> mainGraphPoints = []; List<DataPoint> mainGraphPoints = [];
List<DataPoint> filteredGraphValues = []; List<DataPoint> filteredGraphValues = [];
List months = [ List months = ['Jan', 'Feb', 'Mar', 'April', 'May', 'Jun', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
'Jan',
'Feb',
'Mar',
'April',
'May',
'Jun',
'July',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
late List<String> _labSuggestionsList = []; late List<String> _labSuggestionsList = [];
@ -86,22 +81,22 @@ class LabViewModel extends ChangeNotifier {
List<List<PatientLabOrdersResponseModel>> patientLabOrdersByHospital = []; List<List<PatientLabOrdersResponseModel>> patientLabOrdersByHospital = [];
List<List<PatientLabOrdersResponseModel>> patientLabOrdersViewList = []; List<List<PatientLabOrdersResponseModel>> patientLabOrdersViewList = [];
LabViewModel( LabOrderResponseByAi? labOrderResponseByAi;
{required this.labRepo, LabOrdersResponseByAi? labOrdersResponseByAi;
required this.errorHandlerService,
required this.navigationService}); LabViewModel({required this.labRepo, required this.errorHandlerService, required this.navigationService});
initLabProvider() { initLabProvider() {
// if (isLabNeedToLoad) { // if (isLabNeedToLoad) {
patientLabOrders.clear(); patientLabOrders.clear();
filteredLabOrders.clear(); filteredLabOrders.clear();
labOrderTests.clear(); labOrderTests.clear();
isLabOrdersLoading = true; isLabOrdersLoading = true;
isLabResultsLoading = true; isLabResultsLoading = true;
patientLabOrdersByClinic.clear(); patientLabOrdersByClinic.clear();
patientLabOrdersByHospital.clear(); patientLabOrdersByHospital.clear();
patientLabOrdersViewList.clear(); patientLabOrdersViewList.clear();
getPatientLabOrders(); getPatientLabOrders();
// } // }
notifyListeners(); notifyListeners();
} }
@ -133,13 +128,13 @@ class LabViewModel extends ChangeNotifier {
final result = await labRepo.getPatientLabOrders(); final result = await labRepo.getPatientLabOrders();
result.fold( result.fold(
(failure) async { (failure) async {
isLabOrdersLoading = false; isLabOrdersLoading = false;
isLabResultsLoading = false; isLabResultsLoading = false;
notifyListeners(); notifyListeners();
}, },
// => await errorHandler_service.handleError(failure: failure), // => await errorHandler_service.handleError(failure: failure),
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
@ -203,11 +198,7 @@ class LabViewModel extends ChangeNotifier {
} }
filterSuggestions() { filterSuggestions() {
final List<String> labels = patientLabOrders final List<String> labels = patientLabOrders.expand((order) => order.testDetails ?? []).map((detail) => detail.description).whereType<String>().toList();
.expand((order) => order.testDetails ?? [])
.map((detail) => detail.description)
.whereType<String>()
.toList();
_labSuggestionsList = labels.toSet().toList(); _labSuggestionsList = labels.toSet().toList();
notifyListeners(); notifyListeners();
@ -322,14 +313,12 @@ class LabViewModel extends ChangeNotifier {
); );
} }
Future<void> getPatientLabResultByHospital( Future<void> getPatientLabResultByHospital(PatientLabOrdersResponseModel laborder) async {
PatientLabOrdersResponseModel laborder) async {
isLabResultByHospitalLoading = true; isLabResultByHospitalLoading = true;
notifyListeners(); notifyListeners();
mainLabResultsByHospitals.clear(); mainLabResultsByHospitals.clear();
final result = await labRepo.getPatientLabResultsByHospitals(laborder, final result = await labRepo.getPatientLabResultsByHospitals(laborder, Utils.isVidaPlusProject(int.parse(laborder.projectID ?? "0")));
Utils.isVidaPlusProject(int.parse(laborder.projectID ?? "0")));
result.fold( result.fold(
(failure) async { (failure) async {
@ -353,12 +342,9 @@ class LabViewModel extends ChangeNotifier {
mainLabResults.clear(); mainLabResults.clear();
filteredGraphValues.clear(); filteredGraphValues.clear();
maxY = double.negativeInfinity; maxY = double.negativeInfinity;
minY = double.infinity; minY = double.infinity;
maxX = double.infinity; maxX = double.infinity;
final result = await labRepo.getPatientLabResults( final result = await labRepo.getPatientLabResults(laborder, Utils.isVidaPlusProject(int.parse(laborder.projectID ?? "0")), procedureName);
laborder,
Utils.isVidaPlusProject(int.parse(laborder.projectID ?? "0")),
procedureName);
result.fold( result.fold(
(failure) async { (failure) async {
@ -372,7 +358,6 @@ class LabViewModel extends ChangeNotifier {
var recentThree = sort(apiResponse.data!); var recentThree = sort(apiResponse.data!);
mainLabResults = recentThree; mainLabResults = recentThree;
double highRefrenceValue = double.negativeInfinity; double highRefrenceValue = double.negativeInfinity;
String? flagForHighReferenceRange; String? flagForHighReferenceRange;
double lowRefenceValue = double.infinity; double lowRefenceValue = double.infinity;
@ -380,11 +365,10 @@ class LabViewModel extends ChangeNotifier {
recentThree.reversed.forEach((element) { recentThree.reversed.forEach((element) {
try { try {
var dateTime = var dateTime = DateUtil.convertStringToDate(element.verifiedOnDateTime!);
DateUtil.convertStringToDate(element.verifiedOnDateTime!);
var resultValue = double.parse(element.resultValue!); var resultValue = double.parse(element.resultValue!);
var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag??""); var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag ?? "");
if (resultValue>maxY) { if (resultValue > maxY) {
maxY = resultValue; maxY = resultValue;
maxX = maxY; maxX = maxY;
} }
@ -401,14 +385,13 @@ class LabViewModel extends ChangeNotifier {
} }
filteredGraphValues.add(DataPoint( filteredGraphValues.add(DataPoint(
value: transformedValue, value: transformedValue,
actualValue:element.resultValue!, actualValue: element.resultValue!,
label: formatDateAsMMYY(dateTime), label: formatDateAsMMYY(dateTime),
unitOfMeasurement: element.uOM, unitOfMeasurement: element.uOM,
displayTime: resultDate(dateTime), displayTime: resultDate(dateTime),
time: DateUtil.convertStringToDate(element.verifiedOnDateTime), time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "", referenceValue: element.calculatedResultFlag ?? "",
)); ));
} catch (e) {} } catch (e) {}
}); });
@ -417,6 +400,10 @@ class LabViewModel extends ChangeNotifier {
lowRefenceValue = minY; lowRefenceValue = minY;
} }
if (minY > lowRefenceValue) {
minY = lowRefenceValue - 25;
}
this.flagForHighReferenceRange = flagForHighReferenceRange; this.flagForHighReferenceRange = flagForHighReferenceRange;
this.flagForLowReferenceRange = flagForLowReferenceRange; this.flagForLowReferenceRange = flagForLowReferenceRange;
highTransformedReferenceValue = double.parse(transformValueInRange(highRefrenceValue, flagForHighReferenceRange ?? "").toStringAsFixed(1)); highTransformedReferenceValue = double.parse(transformValueInRange(highRefrenceValue, flagForHighReferenceRange ?? "").toStringAsFixed(1));
@ -424,7 +411,7 @@ class LabViewModel extends ChangeNotifier {
this.highRefrenceValue = double.parse(highRefrenceValue.toStringAsFixed(1)); this.highRefrenceValue = double.parse(highRefrenceValue.toStringAsFixed(1));
this.lowRefenceValue = double.parse(lowRefenceValue.toStringAsFixed(1)); this.lowRefenceValue = double.parse(lowRefenceValue.toStringAsFixed(1));
if(maxY< highRefrenceValue) { if (maxY < highRefrenceValue) {
maxY = highRefrenceValue; maxY = highRefrenceValue;
} }
maxY += 25; maxY += 25;
@ -434,7 +421,9 @@ class LabViewModel extends ChangeNotifier {
checkIfGraphShouldBeDisplayed(recentResult); checkIfGraphShouldBeDisplayed(recentResult);
recentResult.verifiedOn = resultDate(DateUtil.convertStringToDate(recentResult.verifiedOnDateTime!)); recentResult.verifiedOn = resultDate(DateUtil.convertStringToDate(recentResult.verifiedOnDateTime!));
// filteredGraphValues = [filteredGraphValues.first]; // filteredGraphValues = [filteredGraphValues.first];
navigationService.push(MaterialPageRoute( labOrderResponseByAi = null;
navigationService.push(
MaterialPageRoute(
builder: (_) => LabResultDetails(recentLabResult: recentResult, testDescription: testDescription), builder: (_) => LabResultDetails(recentLabResult: recentResult, testDescription: testDescription),
), ),
); );
@ -444,14 +433,13 @@ class LabViewModel extends ChangeNotifier {
); );
} }
void checkIfGraphShouldBeDisplayed(LabResult recentResult){ void checkIfGraphShouldBeDisplayed(LabResult recentResult) {
shouldShowGraph = recentResult.checkIfGraphShouldBeDisplayed(); shouldShowGraph = recentResult.checkIfGraphShouldBeDisplayed();
isGraphVisible = shouldShowGraph; isGraphVisible = shouldShowGraph;
notifyListeners(); notifyListeners();
} }
Future<void> getPatientSpecialResult( Future<void> getPatientSpecialResult(PatientLabOrdersResponseModel laborder) async {
PatientLabOrdersResponseModel laborder) async {
isSpecialResultsLoading = true; isSpecialResultsLoading = true;
labSpecialResult = ""; labSpecialResult = "";
notifyListeners(); notifyListeners();
@ -473,8 +461,7 @@ class LabViewModel extends ChangeNotifier {
StringBuffer htmlbuffer = StringBuffer(""); StringBuffer htmlbuffer = StringBuffer("");
apiResponse.data?.forEach((element) { apiResponse.data?.forEach((element) {
if(element.resultDataHTML != null && element.resultDataHTML?.isNotEmpty == true) if (element.resultDataHTML != null && element.resultDataHTML?.isNotEmpty == true) htmlbuffer.write("${element.resultDataHTML} <br/> <br/>");
htmlbuffer.write("${element.resultDataHTML} <br/> <br/>");
}); });
labSpecialResult = htmlbuffer.toString(); labSpecialResult = htmlbuffer.toString();
@ -486,10 +473,8 @@ class LabViewModel extends ChangeNotifier {
); );
} }
String resultDate(DateTime date){ String resultDate(DateTime date) {
return '${date.day} ${months[date.month - 1]},${date.year}';
return '${date.day} ${months[date.month-1]},${date.year}';
} }
double transformValueInRange(double inputValue, String flag) { double transformValueInRange(double inputValue, String flag) {
@ -497,7 +482,7 @@ class LabViewModel extends ChangeNotifier {
double rangeStart, rangeEnd; double rangeStart, rangeEnd;
switch (flag) { switch (flag) {
case'LCL': case 'LCL':
case 'CL': case 'CL':
rangeStart = 0.0; rangeStart = 0.0;
rangeEnd = 19.0; rangeEnd = 19.0;
@ -534,16 +519,17 @@ class LabViewModel extends ChangeNotifier {
debugPrint("the transformed value is $transformedValue"); debugPrint("the transformed value is $transformedValue");
return transformedValue; return transformedValue;
} }
void getSelectedDateRange(DateTime? start, DateTime? end) { void getSelectedDateRange(DateTime? start, DateTime? end) {
maxY = double.negativeInfinity; maxY = double.negativeInfinity;
if(start == null && end == null) { if (start == null && end == null) {
mainLabResults.forEach((element) { mainLabResults.forEach((element) {
final time = DateUtil.convertStringToDate(element.verifiedOnDateTime!); final time = DateUtil.convertStringToDate(element.verifiedOnDateTime!);
try{ try {
var resultValue = double.parse(element.resultValue!); var resultValue = double.parse(element.resultValue!);
var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag??""); var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag ?? "");
if (resultValue > maxY) { if (resultValue > maxY) {
maxY = resultValue; maxY = resultValue;
} }
@ -552,54 +538,43 @@ class LabViewModel extends ChangeNotifier {
actualValue: element.resultValue!, actualValue: element.resultValue!,
label: formatDateAsMMYY(time), label: formatDateAsMMYY(time),
unitOfMeasurement: element.uOM, unitOfMeasurement: element.uOM,
displayTime: resultDate(time), displayTime: resultDate(time),
time: DateUtil.convertStringToDate(element.verifiedOnDateTime), time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "", referenceValue: element.calculatedResultFlag ?? "",
)); ));
}catch(e){ } catch (e) {}
}
}); });
} else {
}else {
filteredGraphValues.clear(); filteredGraphValues.clear();
mainLabResults.forEach((element) { mainLabResults.forEach((element) {
try { try {
var dateTime = var dateTime = DateUtil.convertStringToDate(element.verifiedOnDateTime!);
DateUtil.convertStringToDate(element.verifiedOnDateTime!);
var resultValue = double.parse(element.resultValue!); var resultValue = double.parse(element.resultValue!);
var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag??""); var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag ?? "");
if (resultValue > maxY) { if (resultValue > maxY) {
maxY = resultValue; maxY = resultValue;
} }
if (start != null && end == null) { if (start != null && end == null) {
if (dateTime.isAtSameMomentAs(start)) { if (dateTime.isAtSameMomentAs(start)) {
filteredGraphValues.add(DataPoint( filteredGraphValues.add(DataPoint(
value: transformedValue, value: transformedValue,
actualValue: element.resultValue!, actualValue: element.resultValue!,
unitOfMeasurement: element.uOM, unitOfMeasurement: element.uOM,
label: formatDateAsMMYY(dateTime), label: formatDateAsMMYY(dateTime),
displayTime: resultDate(dateTime), displayTime: resultDate(dateTime),
time: time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "")); referenceValue: element.calculatedResultFlag ?? ""));
} }
} else if (start != null && end != null) { } else if (start != null && end != null) {
if ((dateTime.isAfter(start)) && (dateTime.isBefore(end))) { if ((dateTime.isAfter(start)) && (dateTime.isBefore(end))) {
filteredGraphValues.add(DataPoint( filteredGraphValues.add(DataPoint(
value: transformedValue, value: transformedValue,
actualValue: element.resultValue!, actualValue: element.resultValue!,
label: formatDateAsMMYY(dateTime), label: formatDateAsMMYY(dateTime),
unitOfMeasurement: element.uOM, unitOfMeasurement: element.uOM,
displayTime: resultDate(dateTime), displayTime: resultDate(dateTime),
time: time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "")); referenceValue: element.calculatedResultFlag ?? ""));
} }
} }
@ -608,16 +583,13 @@ class LabViewModel extends ChangeNotifier {
} }
filteredGraphValues = sortFilteredList(filteredGraphValues).reversed.toList(); filteredGraphValues = sortFilteredList(filteredGraphValues).reversed.toList();
notifyListeners(); notifyListeners();
} }
String formatDateAsMMYY(DateTime date) { String formatDateAsMMYY(DateTime date) {
return '${months[date.month - 1]}, ${date.year}';
return '${months[date.month-1]}, ${date.year}';
} }
List<LabResult> sortByFlagAndValue(List<LabResult> original) { List<LabResult> sortByFlagAndValue(List<LabResult> original) {
const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH']; const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
@ -651,7 +623,6 @@ class LabViewModel extends ChangeNotifier {
} }
List<LabResult> sort(List<LabResult> original) { List<LabResult> sort(List<LabResult> original) {
final copy = List<LabResult>.from(original); final copy = List<LabResult>.from(original);
copy.sort((a, b) { copy.sort((a, b) {
final aDate = DateUtil.convertStringToDate(a.verifiedOnDateTime); final aDate = DateUtil.convertStringToDate(a.verifiedOnDateTime);
@ -666,8 +637,6 @@ class LabViewModel extends ChangeNotifier {
} }
List<DataPoint> sortFilteredList(List<DataPoint> original) { List<DataPoint> sortFilteredList(List<DataPoint> original) {
final copy = List<DataPoint>.from(original); final copy = List<DataPoint>.from(original);
copy.sort((a, b) { copy.sort((a, b) {
final aDate = a.time; final aDate = a.time;
@ -702,7 +671,7 @@ class LabViewModel extends ChangeNotifier {
} }
} }
String getFormattedDate(DateTime date){ String getFormattedDate(DateTime date) {
return DateFormat('EEEE, dd MMMM. yyyy').format(date); return DateFormat('EEEE, dd MMMM. yyyy').format(date);
} }
@ -716,7 +685,7 @@ class LabViewModel extends ChangeNotifier {
case 'N': case 'N':
return AppAssets.ic_normal_result; return AppAssets.ic_normal_result;
case 'H': case 'H':
return AppAssets.ic_low_result; return AppAssets.ic_low_result;
case 'CH': case 'CH':
case 'HCH': case 'HCH':
return AppAssets.ic_critical_low_result; return AppAssets.ic_critical_low_result;
@ -758,8 +727,81 @@ class LabViewModel extends ChangeNotifier {
} }
} }
alterGraphVisibility(){ alterGraphVisibility() {
isGraphVisible = !isGraphVisible; isGraphVisible = !isGraphVisible;
notifyListeners(); notifyListeners();
} }
Future<void> getAiOverviewLabOrders({required PatientLabOrdersResponseModel labOrder, required String loadingText}) async {
// LoadingUtils.showFullScreenLoader(loadingText: "Loading and analysing your data,\nPlease be patient and let the AI do the magic. \nPlease be patient, This might take some time.");
LoadingUtils.showFullScreenLoader(loadingText: loadingText);
List<Map<String, dynamic>> results = [];
Map<String, dynamic> orderData = {"order_date": labOrder.orderDate ?? "", "clinic": labOrder.clinicDescription ?? "", "doctor": labOrder.doctorName ?? "", "results": []};
List<Map<String, dynamic>> testResults = [];
if (labOrder.testDetails != null && labOrder.testDetails!.isNotEmpty) {
for (var testDetail in labOrder.testDetails!) {
LabResult? matchingResult =
mainLabResultsByHospitals.firstWhere((labResult) => labResult.testCode == testDetail.testCode || labResult.description == testDetail.description, orElse: () => LabResult());
testResults.add({
"test_name": testDetail.description ?? "",
"result_value": matchingResult.resultValue ?? "",
"reference_range": matchingResult.referanceRange ?? "",
"unit": matchingResult.uOM ?? "",
"flag": matchingResult.calculatedResultFlag ?? "N"
});
}
}
orderData["results"] = testResults;
results.add(orderData);
final result = await labRepo.getPatientAiOverViewLabOrders(results);
result.fold(
(failure) async {
LoadingUtils.hideFullScreenLoader();
await errorHandlerService.handleError(failure: failure);
},
(apiResponse) {
LoadingUtils.hideFullScreenLoader();
if (apiResponse.messageStatus == 2) {
} else if (apiResponse.messageStatus == 1) {
labOrdersResponseByAi = apiResponse.data;
navigationService.push(
MaterialPageRoute(builder: (_) => LabAiAnalysisDetailedPage()),
);
}
},
);
LoadingUtils.hideFullScreenLoader();
}
Future<void> getAiOverviewSingleLabResult({required String langId, required LabResult recentLabResult, required String loadingText}) async {
LoaderBottomSheet.showLoader(loadingText: loadingText);
List<Map<String, dynamic>> results = [];
results.add({
"Description": recentLabResult.description ?? '',
"ResultValue": recentLabResult.resultValue ?? '',
"CalculatedResultFlag": recentLabResult.calculatedResultFlag ?? '',
"UOM": recentLabResult.uOM ?? '',
"ReferanceRange": recentLabResult.referanceRange ?? '',
});
var payload = {"patient_id": currentlySelectedPatientOrder!.patientID, "language_id": langId, "lab_results": results};
final result = await labRepo.getPatientAiOverViewLabOrder(payload);
result.fold(
(failure) async {
LoaderBottomSheet.hideLoader();
await errorHandlerService.handleError(failure: failure);
},
(apiResponse) {
LoaderBottomSheet.hideLoader();
if (apiResponse.messageStatus == 2) {
} else if (apiResponse.messageStatus == 1) {
labOrderResponseByAi = apiResponse.data;
notifyListeners();
}
},
);
LoaderBottomSheet.hideLoader();
}
} }

@ -0,0 +1,69 @@
import 'dart:convert';
class AiLabOrdersOverView {
String? orderDate;
String? clinic;
String? doctor;
List<Result>? results;
AiLabOrdersOverView({
this.orderDate,
this.clinic,
this.doctor,
this.results,
});
factory AiLabOrdersOverView.fromRawJson(String str) => AiLabOrdersOverView.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AiLabOrdersOverView.fromJson(Map<String, dynamic> json) => AiLabOrdersOverView(
orderDate: json["order_date"] == null ? null : json["order_date"],
clinic: json["clinic"],
doctor: json["doctor"],
results: json["results"] == null ? [] : List<Result>.from(json["results"]!.map((x) => Result.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"order_date": orderDate,
"clinic": clinic,
"doctor": doctor,
"results": results == null ? [] : List<dynamic>.from(results!.map((x) => x.toJson())),
};
}
class Result {
String? testName;
String? resultValue;
String? referenceRange;
String? unit;
String? flag;
Result({
this.testName,
this.resultValue,
this.referenceRange,
this.unit,
this.flag,
});
factory Result.fromRawJson(String str) => Result.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Result.fromJson(Map<String, dynamic> json) => Result(
testName: json["test_name"],
resultValue: json["result_value"],
referenceRange: json["reference_range"],
unit: json["unit"],
flag: json["flag"],
);
Map<String, dynamic> toJson() => {
"test_name": testName,
"result_value": resultValue,
"reference_range": referenceRange,
"unit": unit,
"flag": flag,
};
}

@ -0,0 +1,177 @@
import 'dart:convert';
class LabOrdersResponseByAi {
Analysis? analysis;
String? patientId;
int? totalOrders;
int? totalResults;
LabOrdersResponseByAi({
this.analysis,
this.patientId,
this.totalOrders,
this.totalResults,
});
factory LabOrdersResponseByAi.fromRawJson(String str) => LabOrdersResponseByAi.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory LabOrdersResponseByAi.fromJson(Map<String, dynamic> json) => LabOrdersResponseByAi(
analysis: json["analysis"] == null ? null : Analysis.fromJson(json["analysis"]),
patientId: json["patient_id"],
totalOrders: json["total_orders"],
totalResults: json["total_results"],
);
Map<String, dynamic> toJson() => {
"analysis": analysis?.toJson(),
"patient_id": patientId,
"total_orders": totalOrders,
"total_results": totalResults,
};
}
class Analysis {
List<AiGeneratedAttribute>? aiGeneratedAttributes;
List<String>? aiPredictions;
List<AiRecommendation>? aiRecommendations;
List<String>? prevention;
String? rawMessage;
List<RiskFactor>? riskFactors;
List<dynamic>? suggestedDoctors;
String? summary;
Analysis({
this.aiGeneratedAttributes,
this.aiPredictions,
this.aiRecommendations,
this.prevention,
this.rawMessage,
this.riskFactors,
this.suggestedDoctors,
this.summary,
});
factory Analysis.fromRawJson(String str) => Analysis.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Analysis.fromJson(Map<String, dynamic> json) => Analysis(
aiGeneratedAttributes: json["ai_generated_attributes"] == null ? [] : List<AiGeneratedAttribute>.from(json["ai_generated_attributes"]!.map((x) => AiGeneratedAttribute.fromJson(x))),
aiPredictions: json["ai_predictions"] == null ? [] : List<String>.from(json["ai_predictions"]!.map((x) => x)),
aiRecommendations: json["ai_recommendations"] == null ? [] : List<AiRecommendation>.from(json["ai_recommendations"]!.map((x) => AiRecommendation.fromJson(x))),
prevention: json["prevention"] == null ? [] : List<String>.from(json["prevention"]!.map((x) => x)),
rawMessage: json["raw_message"],
riskFactors: json["riskFactors"] == null ? [] : List<RiskFactor>.from(json["riskFactors"]!.map((x) => RiskFactor.fromJson(x))),
suggestedDoctors: json["suggested_doctors"] == null ? [] : List<dynamic>.from(json["suggested_doctors"]!.map((x) => x)),
summary: json["summary"],
);
Map<String, dynamic> toJson() => {
"ai_generated_attributes": aiGeneratedAttributes == null ? [] : List<dynamic>.from(aiGeneratedAttributes!.map((x) => x.toJson())),
"ai_predictions": aiPredictions == null ? [] : List<dynamic>.from(aiPredictions!.map((x) => x)),
"ai_recommendations": aiRecommendations == null ? [] : List<dynamic>.from(aiRecommendations!.map((x) => x.toJson())),
"prevention": prevention == null ? [] : List<dynamic>.from(prevention!.map((x) => x)),
"raw_message": rawMessage,
"riskFactors": riskFactors == null ? [] : List<dynamic>.from(riskFactors!.map((x) => x.toJson())),
"suggested_doctors": suggestedDoctors == null ? [] : List<dynamic>.from(suggestedDoctors!.map((x) => x)),
"summary": summary,
};
}
class AiGeneratedAttribute {
String? calculatedResultFlag;
String? description;
String? referanceRange;
String? resultValue;
String? testShortDescription;
String? uom;
String? calculationFormula;
AiGeneratedAttribute({
this.calculatedResultFlag,
this.description,
this.referanceRange,
this.resultValue,
this.testShortDescription,
this.uom,
this.calculationFormula,
});
factory AiGeneratedAttribute.fromRawJson(String str) => AiGeneratedAttribute.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AiGeneratedAttribute.fromJson(Map<String, dynamic> json) => AiGeneratedAttribute(
calculatedResultFlag: json["CalculatedResultFlag"],
description: json["Description"],
referanceRange: json["ReferanceRange"],
resultValue: json["ResultValue"],
testShortDescription: json["TestShortDescription"],
uom: json["UOM"],
calculationFormula: json["calculationFormula"],
);
Map<String, dynamic> toJson() => {
"CalculatedResultFlag": calculatedResultFlag,
"Description": description,
"ReferanceRange": referanceRange,
"ResultValue": resultValue,
"TestShortDescription": testShortDescription,
"UOM": uom,
"calculationFormula": calculationFormula,
};
}
class AiRecommendation {
String? priority;
String? recommendation;
AiRecommendation({
this.priority,
this.recommendation,
});
factory AiRecommendation.fromRawJson(String str) => AiRecommendation.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AiRecommendation.fromJson(Map<String, dynamic> json) => AiRecommendation(
priority: json["priority"],
recommendation: json["recommendation"],
);
Map<String, dynamic> toJson() => {
"priority": priority,
"recommendation": recommendation,
};
}
class RiskFactor {
String? description;
String? factor;
String? risk;
RiskFactor({
this.description,
this.factor,
this.risk,
});
factory RiskFactor.fromRawJson(String str) => RiskFactor.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory RiskFactor.fromJson(Map<String, dynamic> json) => RiskFactor(
description: json["description"],
factor: json["factor"],
risk: json["risk"],
);
Map<String, dynamic> toJson() => {
"description": description,
"factor": factor,
"risk": risk,
};
}

@ -26,6 +26,7 @@ class LabResult {
String? referenceLow; String? referenceLow;
num? resultTypeID; num? resultTypeID;
String? packageShortDescription; String? packageShortDescription;
int? testId;
LabResult( LabResult(
{this.description, {this.description,
@ -52,6 +53,7 @@ class LabResult {
this.referenceHigh, this.referenceHigh,
this.criticalLow, this.criticalLow,
this.referenceLow, this.referenceLow,
this.testId,
}); });
LabResult.fromJson(Map<String, dynamic> json) { LabResult.fromJson(Map<String, dynamic> json) {
@ -82,6 +84,7 @@ class LabResult {
referenceLow = json['ReferenceLow']; referenceLow = json['ReferenceLow'];
packageShortDescription = json['PackageShortDescription']; packageShortDescription = json['PackageShortDescription'];
resultTypeID = json['ResultTypeID']; resultTypeID = json['ResultTypeID'];
testId = json['TestID'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -110,6 +113,7 @@ class LabResult {
data['ReferenceHigh'] = this.referenceHigh; data['ReferenceHigh'] = this.referenceHigh;
data['CriticalLow'] = this.criticalLow; data['CriticalLow'] = this.criticalLow;
data['ReferenceLow'] = this.referenceLow; data['ReferenceLow'] = this.referenceLow;
data['TestID'] = this.testId;
return data; return data;
} }

@ -0,0 +1,145 @@
import 'dart:convert';
class LabOrderResponseByAi {
String? summary;
List<AiGeneratedAttribute>? aiGeneratedAttributes;
List<String>? aiPredictions;
List<AiRecommendation>? aiRecommendations;
List<RiskFactor>? riskFactors;
List<String>? prevention;
List<dynamic>? suggestedDoctors;
String? rawMessage;
LabOrderResponseByAi({
this.summary,
this.aiGeneratedAttributes,
this.aiPredictions,
this.aiRecommendations,
this.riskFactors,
this.prevention,
this.suggestedDoctors,
this.rawMessage,
});
factory LabOrderResponseByAi.fromRawJson(String str) => LabOrderResponseByAi.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory LabOrderResponseByAi.fromJson(Map<String, dynamic> json) => LabOrderResponseByAi(
summary: json["summary"],
aiGeneratedAttributes: json["ai_generated_attributes"] == null ? [] : List<AiGeneratedAttribute>.from(json["ai_generated_attributes"]!.map((x) => AiGeneratedAttribute.fromJson(x))),
aiPredictions: json["ai_predictions"] == null ? [] : List<String>.from(json["ai_predictions"]!.map((x) => x)),
aiRecommendations: json["ai_recommendations"] == null ? [] : List<AiRecommendation>.from(json["ai_recommendations"]!.map((x) => AiRecommendation.fromJson(x))),
riskFactors: json["riskFactors"] == null ? [] : List<RiskFactor>.from(json["riskFactors"]!.map((x) => RiskFactor.fromJson(x))),
prevention: json["prevention"] == null ? [] : List<String>.from(json["prevention"]!.map((x) => x)),
suggestedDoctors: json["suggested_doctors"] == null ? [] : List<dynamic>.from(json["suggested_doctors"]!.map((x) => x)),
rawMessage: json["raw_message"],
);
Map<String, dynamic> toJson() => {
"summary": summary,
"ai_generated_attributes": aiGeneratedAttributes == null ? [] : List<dynamic>.from(aiGeneratedAttributes!.map((x) => x.toJson())),
"ai_predictions": aiPredictions == null ? [] : List<dynamic>.from(aiPredictions!.map((x) => x)),
"ai_recommendations": aiRecommendations == null ? [] : List<dynamic>.from(aiRecommendations!.map((x) => x.toJson())),
"riskFactors": riskFactors == null ? [] : List<dynamic>.from(riskFactors!.map((x) => x.toJson())),
"prevention": prevention == null ? [] : List<dynamic>.from(prevention!.map((x) => x)),
"suggested_doctors": suggestedDoctors == null ? [] : List<dynamic>.from(suggestedDoctors!.map((x) => x)),
"raw_message": rawMessage,
};
}
class AiGeneratedAttribute {
String? description;
String? resultValue;
String? referanceRange;
String? calculatedResultFlag;
String? uom;
String? calculationFormula;
String? testShortDescription;
AiGeneratedAttribute({
this.description,
this.resultValue,
this.referanceRange,
this.calculatedResultFlag,
this.uom,
this.calculationFormula,
this.testShortDescription,
});
factory AiGeneratedAttribute.fromRawJson(String str) => AiGeneratedAttribute.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AiGeneratedAttribute.fromJson(Map<String, dynamic> json) => AiGeneratedAttribute(
description: json["Description"],
resultValue: json["ResultValue"],
referanceRange: json["ReferanceRange"],
calculatedResultFlag: json["CalculatedResultFlag"],
uom: json["UOM"],
calculationFormula: json["calculationFormula"],
testShortDescription: json["TestShortDescription"],
);
Map<String, dynamic> toJson() => {
"Description": description,
"ResultValue": resultValue,
"ReferanceRange": referanceRange,
"CalculatedResultFlag": calculatedResultFlag,
"UOM": uom,
"calculationFormula": calculationFormula,
"TestShortDescription": testShortDescription,
};
}
class AiRecommendation {
String? recommendation;
String? priority;
AiRecommendation({
this.recommendation,
this.priority,
});
factory AiRecommendation.fromRawJson(String str) => AiRecommendation.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AiRecommendation.fromJson(Map<String, dynamic> json) => AiRecommendation(
recommendation: json["recommendation"],
priority: json["priority"],
);
Map<String, dynamic> toJson() => {
"recommendation": recommendation,
"priority": priority,
};
}
class RiskFactor {
String? factor;
String? risk;
String? description;
RiskFactor({
this.factor,
this.risk,
this.description,
});
factory RiskFactor.fromRawJson(String str) => RiskFactor.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory RiskFactor.fromJson(Map<String, dynamic> json) => RiskFactor(
factor: json["factor"],
risk: json["risk"],
description: json["description"],
);
Map<String, dynamic> toJson() => {
"factor": factor,
"risk": risk,
"description": description,
};
}

@ -439,11 +439,10 @@ class MedicalFileViewModel extends ChangeNotifier {
); );
// Clear and start fresh with current user // Clear and start fresh with current user
patientFamilyFiles.clear(); final List<FamilyFileResponseModelLists> newPatientFamilyFiles = [currentUserFamilyFile];
patientFamilyFiles.add(currentUserFamilyFile);
final List<FamilyFileResponseModelLists> activeFamilyFiles = []; final List<FamilyFileResponseModelLists> activeFamilyFiles = [];
final List<FamilyFileResponseModelLists> pendingFamilyFiles = []; final List<FamilyFileResponseModelLists> newPendingFamilyFiles = [];
for (var element in apiResponse.data!) { for (var element in apiResponse.data!) {
if (element.status == null) { if (element.status == null) {
@ -484,7 +483,7 @@ class MedicalFileViewModel extends ChangeNotifier {
if (isPending) { if (isPending) {
familyFile.isRequestFromMySide = true; familyFile.isRequestFromMySide = true;
pendingFamilyFiles.add(familyFile); newPendingFamilyFiles.add(familyFile);
} }
if (isActive) { if (isActive) {
activeFamilyFiles.add(familyFile); activeFamilyFiles.add(familyFile);
@ -492,13 +491,14 @@ class MedicalFileViewModel extends ChangeNotifier {
} }
for (var activeFile in activeFamilyFiles) { for (var activeFile in activeFamilyFiles) {
if (!patientFamilyFiles.any((e) => e.responseId == activeFile.responseId)) { if (!newPatientFamilyFiles.any((e) => e.responseId == activeFile.responseId)) {
patientFamilyFiles.add(activeFile); newPatientFamilyFiles.add(activeFile);
} }
} }
this.pendingFamilyFiles.clear(); // Assign new list instances
this.pendingFamilyFiles.addAll(pendingFamilyFiles); patientFamilyFiles = newPatientFamilyFiles;
pendingFamilyFiles = newPendingFamilyFiles;
} }
notifyListeners(); notifyListeners();
@ -553,7 +553,9 @@ class MedicalFileViewModel extends ChangeNotifier {
} }
} }
// pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.responseId == element.responseId))); // pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.responseId == element.responseId)));
pendingFamilyFiles.addAll(tempPendingFamilyFiles.where((element) => !pendingFamilyFiles.any((e) => e.patientId == element.patientId))); final existingIds = pendingFamilyFiles.map((e) => e.patientId).toSet();
final newItems = tempPendingFamilyFiles.where((element) => !existingIds.contains(element.patientId)).toList();
pendingFamilyFiles = [...pendingFamilyFiles, ...newItems];
} }
notifyListeners(); notifyListeners();
} }
@ -589,7 +591,7 @@ class MedicalFileViewModel extends ChangeNotifier {
onUnHandledFailure: (failure) { onUnHandledFailure: (failure) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
_dialogService.showErrorBottomSheet( _dialogService.showErrorBottomSheet(
message: failure.message!, message: failure.message,
onOkPressed: () { onOkPressed: () {
navigationService.pop(); navigationService.pop();
}); });
@ -663,7 +665,7 @@ class MedicalFileViewModel extends ChangeNotifier {
navigationService.pop(); navigationService.pop();
}); });
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
patientFamilyFiles.removeWhere((element) => element.id == id); patientFamilyFiles = patientFamilyFiles.where((element) => element.id != id).toList();
getFamilyFiles(); getFamilyFiles();
getAllPendingRecordsByResponseId(); getAllPendingRecordsByResponseId();
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -741,11 +743,12 @@ class MedicalFileViewModel extends ChangeNotifier {
// moveProfile.status = 3; // moveProfile.status = 3;
// moveProfile.statusDescription = "Approved"; // moveProfile.statusDescription = "Approved";
// patientFamilyFiles.add(moveProfile); // patientFamilyFiles.add(moveProfile);
pendingFamilyFiles.removeWhere((element) => element.id == id); pendingFamilyFiles = pendingFamilyFiles.where((element) => element.id != id).toList();
//TODO: Call Api Here To Load Family Members //TODO: Call Api Here To Load Family Members
getFamilyFiles(status: 0); getFamilyFiles(status: 0);
getAllPendingRecordsByResponseId(); getAllPendingRecordsByResponseId();
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
notifyListeners();
// onFamilyFileTabChange(0); // onFamilyFileTabChange(0);
} }
}, },

@ -73,6 +73,8 @@ abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<void>>> sendDoctorRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note, String appoDate, String docName, String projectName, String clinicName); Future<Either<Failure, GenericApiModel<void>>> sendDoctorRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note, String appoDate, String docName, String projectName, String clinicName);
Future<Either<Failure, GenericApiModel<List<PatientQueueDetails>>>> getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID}); Future<Either<Failure, GenericApiModel<List<PatientQueueDetails>>>> getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID});
Future<Either<Failure, GenericApiModel<dynamic>>> convertPatientToCash({required int projectID});
} }
class MyAppointmentsRepoImp implements MyAppointmentsRepo { class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@ -957,4 +959,36 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
} }
} }
@override
Future<Either<Failure, GenericApiModel>> convertPatientToCash({required int projectID}) async {
Map<String, dynamic> request;
request = {"ProjectID": projectID};
try {
GenericApiModel<bool>? 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<bool>(
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()));
}
}
} }

@ -1,6 +1,9 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.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/app_state.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.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/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/appointemnet_filters.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ask_doctor_request_type_response_model.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/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/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/utils/appointment_type.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/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 { class MyAppointmentsViewModel extends ChangeNotifier {
int selectedTabIndex = 0; int selectedTabIndex = 0;
@ -73,6 +82,9 @@ class MyAppointmentsViewModel extends ChangeNotifier {
GetTamaraInstallmentsDetailsResponseModel? getTamaraInstallmentsDetailsResponseModel; GetTamaraInstallmentsDetailsResponseModel? getTamaraInstallmentsDetailsResponseModel;
bool isTamaraDetailsLoading = false; bool isTamaraDetailsLoading = false;
bool isShowNotEligibleDialog = false;
String notEligibleErrorMsg = "";
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService, required this.appState}); MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService, required this.appState});
void onTabChange(int index) { void onTabChange(int index) {
@ -141,6 +153,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
isTamaraDetailsLoading = true; isTamaraDetailsLoading = true;
isAppointmentPatientShareLoading = true; isAppointmentPatientShareLoading = true;
isEyeMeasurementsAppointmentsLoading = true; isEyeMeasurementsAppointmentsLoading = true;
isShowNotEligibleDialog = false;
notifyListeners(); notifyListeners();
} }
@ -349,7 +362,99 @@ class MyAppointmentsViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) { } else if (apiResponse.messageStatus == 1) {
patientAppointmentShareResponseModel = apiResponse.data!; 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<NavigationService>().navigatorKey.currentContext!);
} else {
isShowNotEligibleDialog = true;
notEligibleErrorMsg = LocaleKeys.invalidInsurance.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!);
}
}
}
isAppointmentPatientShareLoading = false; isAppointmentPatientShareLoading = false;
if (isShowNotEligibleDialog) {
showCommonBottomSheetWithoutHeight(GetIt.instance<NavigationService>().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<NavigationService>().navigatorKey.currentContext!),
cancelText: LocaleKeys.continueCash.tr(context: GetIt.instance<NavigationService>().navigatorKey.currentContext!),
isShowActionButtons: true,
onCancelTap: () {
Navigator.pop(GetIt.instance<NavigationService>().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<NavigationService>().navigatorKey.currentContext!),
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
onConfirmTap: () async {
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
Navigator.push(
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
CustomPageRoute(
page: InsuranceHomePage(),
),
);
}),
), callBackFunc: () {
// Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);
}, isFullScreen: false, isCloseButtonVisible: false, isDismissible: false);
}
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> 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(); notifyListeners();
if (onSuccess != null) { if (onSuccess != null) {
onSuccess(apiResponse); onSuccess(apiResponse);
@ -413,7 +518,12 @@ class MyAppointmentsViewModel extends ChangeNotifier {
final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel); final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold( 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) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
onError!(apiResponse.errorMessage!); onError!(apiResponse.errorMessage!);
@ -510,7 +620,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
} }
Future<void> getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async {
if (!isAppointmentDataToBeLoaded) return; // if (!isAppointmentDataToBeLoaded) return;
isPatientMyDoctorsLoading = true; isPatientMyDoctorsLoading = true;
notifyListeners(); notifyListeners();

@ -188,13 +188,13 @@ class PrescriptionsRepoImp implements PrescriptionsRepo {
Map<String, dynamic> mapDevice = { Map<String, dynamic> mapDevice = {
"AppointmentNo": prescriptionsResponseModel.appointmentNo, "AppointmentNo": prescriptionsResponseModel.appointmentNo,
"SetupID": prescriptionsResponseModel.setupID, "SetupID": prescriptionsResponseModel.setupID,
"EpisodeID": prescriptionsResponseModel.episodeID, "EpisodeNo": prescriptionsResponseModel.episodeID,
"ClinicID": prescriptionsResponseModel.clinicID, "ClinicID": prescriptionsResponseModel.clinicID,
"ProjectID": prescriptionsResponseModel.projectID, "ProjectID": prescriptionsResponseModel.projectID,
"DischargeNo": prescriptionsResponseModel.dischargeNo, "DischargeNo": prescriptionsResponseModel.dischargeNo,
"IsDownload": true, "IsDownload": true,
// "To": Utils.appState.getAuthenticatedUser()!.emailAddress, "To": Utils.appState.getAuthenticatedUser()!.emailAddress,
"To": "amjad.haroon@cloudsolutions.com.sa", // "To": "amjad.haroon@cloudsolutions.com.sa",
"ClinicName": prescriptionsResponseModel.clinicDescription, "ClinicName": prescriptionsResponseModel.clinicDescription,
"DoctorName": prescriptionsResponseModel.doctorName, "DoctorName": prescriptionsResponseModel.doctorName,
}; };

@ -54,7 +54,7 @@ class PrescriptionsViewModel extends ChangeNotifier {
PrescriptionsViewModel({required this.prescriptionsRepo, required this.errorHandlerService, required this.navServices}); PrescriptionsViewModel({required this.prescriptionsRepo, required this.errorHandlerService, required this.navServices});
initPrescriptionsViewModel() { initPrescriptionsViewModel() {
if (isPrescriptionsDataNeedsReloading) { // if (isPrescriptionsDataNeedsReloading) {
patientPrescriptionOrders.clear(); patientPrescriptionOrders.clear();
patientPrescriptionOrdersByClinic.clear(); patientPrescriptionOrdersByClinic.clear();
patientPrescriptionOrdersByHospital.clear(); patientPrescriptionOrdersByHospital.clear();
@ -62,7 +62,7 @@ class PrescriptionsViewModel extends ChangeNotifier {
prescriptionsOrderList.clear(); prescriptionsOrderList.clear();
isPrescriptionsOrdersLoading = true; isPrescriptionsOrdersLoading = true;
getPatientPrescriptionOrders(); getPatientPrescriptionOrders();
} // }
isSortByClinic = true; isSortByClinic = true;
isPrescriptionsDeliveryOrdersLoading = true; isPrescriptionsDeliveryOrdersLoading = true;
notifyListeners(); notifyListeners();
@ -102,9 +102,9 @@ class PrescriptionsViewModel extends ChangeNotifier {
} }
Future<void> getPatientPrescriptionOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientPrescriptionOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async {
if (!isPrescriptionsDataNeedsReloading) { // if (!isPrescriptionsDataNeedsReloading) {
return; // return;
} // }
final result = await prescriptionsRepo.getPatientPrescriptionOrders(patientId: "1231755"); final result = await prescriptionsRepo.getPatientPrescriptionOrders(patientId: "1231755");
@ -153,7 +153,10 @@ class PrescriptionsViewModel extends ChangeNotifier {
final result = await prescriptionsRepo.getPatientPrescriptionDetails(prescriptionsResponseModel: prescriptionsResponseModel); final result = await prescriptionsRepo.getPatientPrescriptionDetails(prescriptionsResponseModel: prescriptionsResponseModel);
result.fold( result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure), // (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
onError!(failure.message);
},
(apiResponse) { (apiResponse) {
if (apiResponse.messageStatus == 2) { if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});

@ -121,7 +121,7 @@ class RadiologyRepoImp implements RadiologyRepo {
Map<String, dynamic> mapDevice = { Map<String, dynamic> mapDevice = {
"InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? 0 : patientRadiologyResponseModel.invoiceNo, "InvoiceNo": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? 0 : patientRadiologyResponseModel.invoiceNo,
"InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : 0, "InvoiceNo_VP": Utils.isVidaPlusProject(patientRadiologyResponseModel.projectID!) ? patientRadiologyResponseModel.invoiceNo : 0,
"LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo, // "LineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
"InvoiceLineItemNo": patientRadiologyResponseModel.invoiceLineItemNo, "InvoiceLineItemNo": patientRadiologyResponseModel.invoiceLineItemNo,
"ProjectID": patientRadiologyResponseModel.projectID!, "ProjectID": patientRadiologyResponseModel.projectID!,
"InvoiceType": patientRadiologyResponseModel.invoiceType!, "InvoiceType": patientRadiologyResponseModel.invoiceType!,

@ -0,0 +1,54 @@
class ServicesPriceListResponseModel {
int? createdBy;
String? createdOn;
int? editedBy;
String? editedOn;
int? id;
bool? isEnabled;
String? nameAR;
String? nameEN;
num? price;
int? rowID;
ServicesPriceListResponseModel({
this.createdBy,
this.createdOn,
this.editedBy,
this.editedOn,
this.id,
this.isEnabled,
this.nameAR,
this.nameEN,
this.price,
this.rowID,
});
ServicesPriceListResponseModel.fromJson(Map<String, dynamic> json) {
createdBy = json['CreatedBy'];
createdOn = json['CreatedOn'];
editedBy = json['EditedBy'];
editedOn = json['EditedOn'];
id = json['ID'];
isEnabled = json['IsEnabled'];
nameAR = json['NameAR'];
nameEN = json['NameEN'];
price = json['Price'];
rowID = json['RowID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['CreatedBy'] = createdBy;
data['CreatedOn'] = createdOn;
data['EditedBy'] = editedBy;
data['EditedOn'] = editedOn;
data['ID'] = id;
data['IsEnabled'] = isEnabled;
data['NameAR'] = nameAR;
data['NameEN'] = nameEN;
data['Price'] = price;
data['RowID'] = rowID;
return data;
}
}

@ -0,0 +1,80 @@
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
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/services_price_list/models/resp_models/services_price_list_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class ServicesPriceListRepo {
Future<Either<Failure, GenericApiModel<List<ServicesPriceListResponseModel>>>> getServicesPriceList({
String searchKey = "",
int pageIndex = 0,
int pageSize = 0,
});
}
class ServicesPriceListRepoImp implements ServicesPriceListRepo {
final ApiClient apiClient;
final LoggerService loggerService;
ServicesPriceListRepoImp({required this.loggerService, required this.apiClient});
@override
Future<Either<Failure, GenericApiModel<List<ServicesPriceListResponseModel>>>> getServicesPriceList({
String searchKey = "",
int pageIndex = 0,
int pageSize = 0,
}) async {
Map<String, dynamic> mapDevice = {
"ID": 1,
"SearchKey": searchKey,
"PageIndex": pageIndex,
"PageSize": pageSize,
"RowCount": 0,
"TokenID": "@dm!n"
};
try {
GenericApiModel<List<ServicesPriceListResponseModel>>? apiResponse;
Failure? failure;
await apiClient.post(
GET_SERVICES_PRICE_LIST,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['getServicesPriceList'];
if (list == null || list.isEmpty) {
throw Exception("Services price list is empty");
}
final servicesList = list
.map((item) => ServicesPriceListResponseModel.fromJson(item as Map<String, dynamic>))
.toList()
.cast<ServicesPriceListResponseModel>();
apiResponse = GenericApiModel<List<ServicesPriceListResponseModel>>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: servicesList,
);
} 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()));
}
}
}

@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/features/services_price_list/models/resp_models/services_price_list_response_model.dart';
import 'package:hmg_patient_app_new/features/services_price_list/services_price_list_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
class ServicesPriceListViewModel extends ChangeNotifier {
bool isServicesPriceListLoading = false;
ServicesPriceListRepo servicesPriceListRepo;
ErrorHandlerService errorHandlerService;
List<ServicesPriceListResponseModel> servicesPriceList = [];
List<ServicesPriceListResponseModel> filteredServicesPriceList = [];
String searchKey = "";
ServicesPriceListViewModel({
required this.servicesPriceListRepo,
required this.errorHandlerService,
});
initServicesPriceListProvider() {
servicesPriceList.clear();
filteredServicesPriceList.clear();
isServicesPriceListLoading = true;
getServicesPriceList();
notifyListeners();
}
setIsServicesPriceListLoading(bool val) {
isServicesPriceListLoading = val;
notifyListeners();
}
setSearchKey(String val) {
searchKey = val;
filterServicesList(val);
}
void filterServicesList(String query) {
if (query.isEmpty) {
filteredServicesPriceList = List.from(servicesPriceList);
} else {
filteredServicesPriceList = servicesPriceList.where((service) {
final nameEN = service.nameEN?.toLowerCase() ?? '';
final nameAR = service.nameAR?.toLowerCase() ?? '';
final searchLower = query.toLowerCase();
return nameEN.contains(searchLower) || nameAR.contains(searchLower);
}).toList();
}
notifyListeners();
}
Future<void> getServicesPriceList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await servicesPriceListRepo.getServicesPriceList(
searchKey: searchKey,
);
result.fold(
(failure) async {
isServicesPriceListLoading = false;
notifyListeners();
if (onError != null) {
onError(failure.toString());
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
isServicesPriceListLoading = false;
notifyListeners();
if (onError != null) {
onError(apiResponse.errorMessage ?? "Error loading services price list");
}
} else if (apiResponse.messageStatus == 1) {
servicesPriceList = apiResponse.data!;
servicesPriceList.removeWhere((element) => element.isEnabled == false);
filteredServicesPriceList = List.from(servicesPriceList);
isServicesPriceListLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
}

@ -1,9 +1,11 @@
import 'dart:developer';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/organ_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/organ_model.dart';
class OrganData { class OrganData {
// ==================== FRONT VIEW ==================== // ==================== FRONT VIEW ====================
static const List<OrganModel> frontViewOrgans = [ static const List<OrganModel> frontViewOrgansForMale = [
// ========== HEAD & FACE ========== // ========== HEAD & FACE ==========
OrganModel( OrganModel(
id: 'head', id: 'head',
@ -307,9 +309,313 @@ class OrganData {
position: OrganPosition(x: 0.57, y: 0.91), position: OrganPosition(x: 0.57, y: 0.91),
), ),
]; ];
static const List<OrganModel> frontViewOrgansForFemale = [
// ========== HEAD & FACE ==========
OrganModel(
id: 'head',
name: 'whole_head',
nameAr: 'الرأس_كامل',
description: 'Head',
descriptionAr: 'الرأس',
bodyView: BodyView.front,
position: OrganPosition(x: 0.54, y: 0.05),
),
OrganModel(
id: 'left_eye',
name: 'eyes',
nameAr: 'العيون',
description: 'Left Eye',
descriptionAr: 'العين اليسرى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.49, y: 0.095),
),
OrganModel(
id: 'right_eye',
name: 'eyes',
nameAr: 'العيون',
description: 'Right Eye',
descriptionAr: 'العين اليمنى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.6, y: 0.095),
),
OrganModel(
id: 'nose_mouth',
name: 'oral_cavity',
nameAr: 'تجويف_الفم',
description: 'Nose/Mouth',
descriptionAr: 'الأنف/الفم',
bodyView: BodyView.front,
position: OrganPosition(x: 0.54, y: 0.12),
),
// ========== NECK ==========
OrganModel(
id: 'throat',
name: 'neck_or_throat',
nameAr: 'الرقبة_أو_الحلق',
description: 'Throat',
descriptionAr: 'الحلق',
bodyView: BodyView.front,
position: OrganPosition(x: 0.54, y: 0.17),
),
// ========== SHOULDERS ==========
OrganModel(
id: 'left_shoulder',
name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Left Shoulder',
descriptionAr: 'الكتف الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.29, y: 0.22),
),
OrganModel(
id: 'right_shoulder',
name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Right Shoulder',
descriptionAr: 'الكتف الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.75, y: 0.22),
),
// ========== CHEST ==========
OrganModel(
id: 'left_chest',
name: 'chest',
nameAr: 'الصدر',
description: 'Left Chest',
descriptionAr: 'الصدر الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.4, y: 0.22),
),
OrganModel(
id: 'center_chest',
name: 'chest',
nameAr: 'الصدر',
description: 'Center Chest',
descriptionAr: 'وسط الصدر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.52, y: 0.25),
),
OrganModel(
id: 'right_chest',
name: 'chest',
nameAr: 'الصدر',
description: 'Right Chest',
descriptionAr: 'الصدر الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.65, y: 0.22),
),
// ========== RIBS ==========
OrganModel(
id: 'left_ribs',
name: 'chest',
nameAr: 'الصدر',
description: 'Left Ribs',
descriptionAr: 'الأضلاع اليسرى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.38, y: 0.35),
),
OrganModel(
id: 'right_ribs',
name: 'chest',
nameAr: 'الصدر',
description: 'Right Ribs',
descriptionAr: 'الأضلاع اليمنى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.64, y: 0.35),
),
// ========== ABDOMEN ==========
OrganModel(
id: 'upper_abdomen',
name: 'upper_abdomen',
nameAr: 'البطن_العلوي',
description: 'Upper Abdomen',
descriptionAr: 'أعلى البطن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.51, y: 0.31),
),
OrganModel(
id: 'navel',
name: 'mid_abdomen',
nameAr: 'البطن_الأوسط',
description: 'Navel',
descriptionAr: 'السرة',
bodyView: BodyView.front,
position: OrganPosition(x: 0.51, y: 0.38),
),
OrganModel(
id: 'lower_abdomen',
name: 'lower_abdomen',
nameAr: 'البطن_السفلي',
description: 'Lower Abdomen',
descriptionAr: 'أسفل البطن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.51, y: 0.44),
),
// ========== PELVIS ==========
OrganModel(
id: 'left_groin',
name: 'sexual_organs',
nameAr: 'الأعضاء_التناسلية',
description: 'Left Groin',
descriptionAr: 'الفخذ الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.42, y: 0.49),
),
OrganModel(
id: 'right_groin',
name: 'sexual_organs',
nameAr: 'الأعضاء_التناسلية',
description: 'Right Groin',
descriptionAr: 'الفخذ الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.59, y: 0.49),
),
// ========== LEFT ARM ==========
OrganModel(
id: 'left_elbow',
name: 'elbow',
nameAr: 'الكوع',
description: 'Left Elbow',
descriptionAr: 'الكوع الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.24, y: 0.35),
),
OrganModel(
id: 'left_forearm',
name: 'forearm',
nameAr: 'الساعد',
description: 'Left Forearm',
descriptionAr: 'الساعد الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.24, y: 0.43),
),
OrganModel(
id: 'left_wrist',
name: 'hand',
nameAr: 'اليد',
description: 'Left Wrist',
descriptionAr: 'المعصم الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.17, y: 0.49),
),
// ========== RIGHT ARM ==========
OrganModel(
id: 'right_elbow',
name: 'elbow',
nameAr: 'الكوع',
description: 'Right Elbow',
descriptionAr: 'الكوع الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.76, y: 0.35),
),
OrganModel(
id: 'right_forearm',
name: 'forearm',
nameAr: 'الساعد',
description: 'Right Forearm',
descriptionAr: 'الساعد الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.76, y: 0.43),
),
OrganModel(
id: 'right_wrist',
name: 'hand',
nameAr: 'اليد',
description: 'Right Wrist',
descriptionAr: 'المعصم الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.83, y: 0.5),
),
// ========== LEFT LEG ==========
OrganModel(
id: 'left_thigh',
name: 'thigh',
nameAr: 'الفخذ',
description: 'Left Thigh',
descriptionAr: 'الفخذ الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.4, y: 0.60),
),
OrganModel(
id: 'left_knee',
name: 'knee',
nameAr: 'الركبة',
description: 'Left Knee',
descriptionAr: 'الركبة اليسرى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.4, y: 0.72),
),
OrganModel(
id: 'left_shin',
name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Left Shin',
descriptionAr: 'الساق اليسرى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.41, y: 0.82),
),
OrganModel(
id: 'left_ankle',
name: 'foot',
nameAr: 'القدم',
description: 'Left Ankle',
descriptionAr: 'الكاحل الأيسر',
bodyView: BodyView.front,
position: OrganPosition(x: 0.43, y: 0.91),
),
// ========== RIGHT LEG ==========
OrganModel(
id: 'right_thigh',
name: 'thigh',
nameAr: 'الفخذ',
description: 'Right Thigh',
descriptionAr: 'الفخذ الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.65, y: 0.60),
),
OrganModel(
id: 'right_knee',
name: 'knee',
nameAr: 'الركبة',
description: 'Right Knee',
descriptionAr: 'الركبة اليمنى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.6, y: 0.72),
),
OrganModel(
id: 'right_shin',
name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Right Shin',
descriptionAr: 'الساق اليمنى',
bodyView: BodyView.front,
position: OrganPosition(x: 0.59, y: 0.82),
),
OrganModel(
id: 'right_ankle',
name: 'foot',
nameAr: 'القدم',
description: 'Right Ankle',
descriptionAr: 'الكاحل الأيمن',
bodyView: BodyView.front,
position: OrganPosition(x: 0.57, y: 0.91),
),
];
// ==================== BACK VIEW ==================== // ==================== BACK VIEW ====================
static const List<OrganModel> backViewOrgans = [ static const List<OrganModel> backViewOrgansForMale = [
// ========== HEAD & NECK ========== // ========== HEAD & NECK ==========
OrganModel( OrganModel(
id: 'back_of_head', id: 'back_of_head',
@ -504,19 +810,232 @@ class OrganData {
position: OrganPosition(x: 0.57, y: 0.79), position: OrganPosition(x: 0.57, y: 0.79),
), ),
]; ];
static const List<OrganModel> backViewOrgansForFemale = [
// ========== HEAD & NECK ==========
OrganModel(
id: 'back_of_head',
name: 'whole_head',
nameAr: 'الرأس_كامل',
description: 'Back of Head',
descriptionAr: 'مؤخرة الرأس',
bodyView: BodyView.back,
position: OrganPosition(x: 0.48, y: 0.055),
),
OrganModel(
id: 'neck_back',
name: 'nape_of_neck',
nameAr: 'مؤخرة_الرقبة',
description: 'Neck',
descriptionAr: 'الرقبة',
bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.14),
),
// ========== SHOULDERS ==========
OrganModel(
id: 'left_shoulder_back',
name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Left Shoulder',
descriptionAr: 'الكتف الأيسر',
bodyView: BodyView.back,
position: OrganPosition(x: 0.3, y: 0.2),
),
OrganModel(
id: 'right_shoulder_back',
name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Right Shoulder',
descriptionAr: 'الكتف الأيمن',
bodyView: BodyView.back,
position: OrganPosition(x: 0.69, y: 0.2),
),
// ========== UPPER BACK ==========
OrganModel(
id: 'upper_spine',
name: 'back',
nameAr: 'الظهر',
description: 'Upper Spine',
descriptionAr: 'العمود الفقري العلوي',
bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.23),
),
OrganModel(
id: 'left_upper_back',
name: 'back',
nameAr: 'الظهر',
description: 'Left Upper Back',
descriptionAr: 'أعلى الظهر الأيسر',
bodyView: BodyView.back,
position: OrganPosition(x: 0.38, y: 0.28),
),
OrganModel(
id: 'right_upper_back',
name: 'back',
nameAr: 'الظهر',
description: 'Right Upper Back',
descriptionAr: 'أعلى الظهر الأيمن',
bodyView: BodyView.back,
position: OrganPosition(x: 0.62, y: 0.28),
),
// ========== MID BACK ==========
OrganModel(
id: 'mid_spine',
name: 'back',
nameAr: 'الظهر',
description: 'Mid Spine',
descriptionAr: 'العمود الفقري الأوسط',
bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.35),
),
OrganModel(
id: 'left_mid_back',
name: 'back',
nameAr: 'الظهر',
description: 'Left Mid Back',
descriptionAr: 'وسط الظهر الأيسر',
bodyView: BodyView.back,
position: OrganPosition(x: 0.38, y: 0.35),
),
OrganModel(
id: 'right_mid_back',
name: 'back',
nameAr: 'الظهر',
description: 'Right Mid Back',
descriptionAr: 'وسط الظهر الأيمن',
bodyView: BodyView.back,
position: OrganPosition(x: 0.62, y: 0.35),
),
// ========== LOWER BACK ==========
OrganModel(
id: 'lower_spine',
name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Lower Back',
descriptionAr: 'أسفل الظهر',
bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.43),
),
OrganModel(
id: 'left_lower_back',
name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Left Lower Back',
descriptionAr: 'أسفل الظهر الأيسر',
bodyView: BodyView.back,
position: OrganPosition(x: 0.36, y: 0.43),
),
OrganModel(
id: 'right_lower_back',
name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Right Lower Back',
descriptionAr: 'أسفل الظهر الأيمن',
bodyView: BodyView.back,
position: OrganPosition(x: 0.65, y: 0.43),
),
// ========== GLUTES ==========
OrganModel(
id: 'sacrum',
name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Sacrum',
descriptionAr: 'العجز',
bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.5),
),
OrganModel(
id: 'left_glute',
name: 'buttocks',
nameAr: 'الأرداف',
description: 'Left Glute',
descriptionAr: 'الأرداف اليسرى',
bodyView: BodyView.back,
position: OrganPosition(x: 0.36, y: 0.52),
),
OrganModel(
id: 'right_glute',
name: 'buttocks',
nameAr: 'الأرداف',
description: 'Right Glute',
descriptionAr: 'الأرداف اليمنى',
bodyView: BodyView.back,
position: OrganPosition(x: 0.61, y: 0.52),
),
// ========== LEGS ==========
OrganModel(
id: 'left_hamstring',
name: 'thigh',
nameAr: 'الفخذ',
description: 'Left Hamstring',
descriptionAr: 'عضلة الفخذ الخلفية اليسرى',
bodyView: BodyView.back,
position: OrganPosition(x: 0.41, y: 0.62),
),
OrganModel(
id: 'right_hamstring',
name: 'thigh',
nameAr: 'الفخذ',
description: 'Right Hamstring',
descriptionAr: 'عضلة الفخذ الخلفية اليمنى',
bodyView: BodyView.back,
position: OrganPosition(x: 0.62, y: 0.62),
),
OrganModel(
id: 'left_calf',
name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Left Calf',
descriptionAr: 'ربلة الساق اليسرى',
bodyView: BodyView.back,
position: OrganPosition(x: 0.43, y: 0.79),
),
OrganModel(
id: 'right_calf',
name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Right Calf',
descriptionAr: 'ربلة الساق اليمنى',
bodyView: BodyView.back,
position: OrganPosition(x: 0.57, y: 0.79),
),
];
// Helper methods // Helper methods
static List<OrganModel> getOrgansForView(BodyView view) { // Accept genderKey (e.g., 'male' / 'female' or Arabic 'ذكر' / 'أنثى') to return gender-specific organ sets
return view == BodyView.front ? frontViewOrgans : backViewOrgans; static List<OrganModel> getOrgansForView(BodyView view, {String? genderKey}) {
final bool isFemale = genderKey != null && (genderKey.toLowerCase() == 'female' || genderKey == 'أنثى' || genderKey == '2');
if (view == BodyView.front) {
return isFemale ? frontViewOrgansForFemale : frontViewOrgansForMale;
} else {
return isFemale ? backViewOrgansForFemale : backViewOrgansForMale;
}
} }
static List<OrganModel> getAllOrgans() { /// Return all organs (front + back) for the selected gender.
return [...frontViewOrgans, ...backViewOrgans]; /// If genderKey is null, default to male to preserve previous behavior.
static List<OrganModel> getAllOrgans({String? genderKey}) {
final bool isFemale = genderKey != null && (genderKey.toLowerCase() == 'female' || genderKey == 'أنثى' || genderKey == '2');
if (isFemale) {
return [...frontViewOrgansForFemale, ...backViewOrgansForFemale];
}
// default: male
return [...frontViewOrgansForMale, ...backViewOrgansForMale];
} }
static OrganModel? getOrganById(String id) { /// Find organ by id within the organs of the selected gender (or male if not specified)
static OrganModel? getOrganById(String id, {String? genderKey}) {
try { try {
return getAllOrgans().firstWhere((organ) => organ.id == id); return getAllOrgans(genderKey: genderKey).firstWhere((organ) => organ.id == id);
} catch (e) { } catch (e) {
return null; return null;
} }

@ -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<String, dynamic> json) {
category = json['Category'];
clinicID = json['ClinicID'];
isActive = json['IsActive'];
categoryAR = json['CategoryAR'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Category'] = this.category;
data['ClinicID'] = this.clinicID;
data['IsActive'] = this.isActive;
data['CategoryAR'] = this.categoryAR;
return data;
}
}

@ -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/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.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/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/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/symptoms_user_details_response_model.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/models/resp_models/triage_response_model.dart';
@ -50,6 +51,11 @@ abstract class SymptomsCheckerRepo {
required String userSessionToken, required String userSessionToken,
required String sessionId, required String sessionId,
}); });
Future<Either<Failure, GenericApiModel<List<GetClinicDetailsResponseModel>>>> getClinicDetails({
required String categoryName,
required String userSessionToken,
});
} }
class SymptomsCheckerRepoImp implements SymptomsCheckerRepo { class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
@ -390,4 +396,57 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel<List<GetClinicDetailsResponseModel>>>> getClinicDetails({
required String categoryName,
required String userSessionToken,
}) async {
Map<String, String> headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer $userSessionToken',
};
Map<String, dynamic> body = {};
try {
GenericApiModel<List<GetClinicDetailsResponseModel>>? 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<String, dynamic>)).toList().cast<GetClinicDetailsResponseModel>();
apiResponse = GenericApiModel<List<GetClinicDetailsResponseModel>>(
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()));
}
}
} }

@ -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/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/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/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/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/symptoms_user_details_response_model.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/models/resp_models/triage_response_model.dart';
@ -84,9 +85,9 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
String? _selectedGender; String? _selectedGender;
DateTime? _dateOfBirth; DateTime? _dateOfBirth;
int? _selectedAge; int? _selectedAge;
double _selectedHeight = 170; num _selectedHeight = 170;
bool _isHeightCm = true; bool _isHeightCm = true;
double _selectedWeight = 60; num _selectedWeight = 60;
bool _isWeightKg = true; bool _isWeightKg = true;
// Getters // Getters
@ -104,11 +105,25 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
int? get selectedAge => _selectedAge; int? get selectedAge => _selectedAge;
double? get selectedHeight => _selectedHeight; setSelectedAge(int age) {
_selectedAge = age;
}
setSelectedHeight(num height) {
_selectedHeight = height;
notifyListeners();
}
setSelectedWeight(num weight) {
_selectedWeight = weight;
notifyListeners();
}
num? get selectedHeight => _selectedHeight;
bool get isHeightCm => _isHeightCm; bool get isHeightCm => _isHeightCm;
double? get selectedWeight => _selectedWeight; num? get selectedWeight => _selectedWeight;
bool get isWeightKg => _isWeightKg; bool get isWeightKg => _isWeightKg;
@ -140,6 +155,8 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Get the number of triage questions answered /// Get the number of triage questions answered
int get triageQuestionCount => _triageQuestionCount; int get triageQuestionCount => _triageQuestionCount;
List<GetClinicDetailsResponseModel> clinicDetailsList = [];
/// Get choice index for a specific item /// Get choice index for a specific item
int? getTriageChoiceForItem(String itemId) { int? getTriageChoiceForItem(String itemId) {
return _selectedTriageChoicesByItemId[itemId]; return _selectedTriageChoicesByItemId[itemId];
@ -161,14 +178,11 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
/// Get organs for current view /// Get organs for current view
List<OrganModel> get currentOrgans => OrganData.getOrgansForView(_currentView); List<OrganModel> get currentOrgans => OrganData.getOrgansForView(_currentView, genderKey: _selectedGender);
/// Get all selected organs from both views /// Get all selected organs from both views (for the selected gender)
List<OrganModel> get selectedOrgans { List<OrganModel> get selectedOrgans {
final allOrgans = [ final allOrgans = OrganData.getAllOrgans(genderKey: _selectedGender);
...OrganData.frontViewOrgans,
...OrganData.backViewOrgans,
];
return allOrgans.where((organ) => _selectedOrganIds.contains(organ.id)).toList(); return allOrgans.where((organ) => _selectedOrganIds.contains(organ.id)).toList();
} }
@ -1055,6 +1069,43 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
); );
} }
Future<void> 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 @override
void dispose() { void dispose() {
_tooltipTimer?.cancel(); _tooltipTimer?.cancel();

@ -96,6 +96,8 @@ class TodoSectionRepoImp implements TodoSectionRepo {
} }
} }
ancillaryOrders.sort((a, b) => b.orderDate!.compareTo(a.orderDate!));
apiResponse = GenericApiModel<List<AncillaryOrderItem>>( apiResponse = GenericApiModel<List<AncillaryOrderItem>>(
messageStatus: messageStatus, messageStatus: messageStatus,
statusCode: statusCode, statusCode: statusCode,

@ -45,21 +45,19 @@ class DefaultFirebaseOptions {
appId: '1:815750722565:android:62281cd3e5df4063', appId: '1:815750722565:android:62281cd3e5df4063',
messagingSenderId: '815750722565', messagingSenderId: '815750722565',
projectId: 'api-project-815750722565', projectId: 'api-project-815750722565',
// databaseURL: databaseURL: 'https://api-project-815750722565.firebaseio.com',
// 'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app', storageBucket: 'api-project-815750722565.firebasestorage.app',
storageBucket: 'api-project-815750722565.appspot.com',
); );
static const FirebaseOptions ios = FirebaseOptions( static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyDiXnCO00li4V7Ioa2YZ_M4ECxRsu_P9tA', apiKey: 'AIzaSyDiXnCO00li4V7Ioa2YZ_M4ECxRsu_P9tA',
appId: '1:815750722565:ios:328ec247a81a2ca23c186c', appId: '1:815750722565:ios:34ec03c09e02e21f3c186c',
messagingSenderId: '815750722565', messagingSenderId: '815750722565',
projectId: 'api-project-815750722565', projectId: 'api-project-815750722565',
storageBucket: 'api-project-815750722565.appspot.com', databaseURL: 'https://api-project-815750722565.firebaseio.com',
androidClientId: storageBucket: 'api-project-815750722565.firebasestorage.app',
'815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com', androidClientId: '815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com',
iosClientId: iosBundleId: 'com.cloudsolutions.HMGPatientApp',
'815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com',
iosBundleId: 'com.HMG.HMG-Smartphone',
); );
}
}

@ -941,6 +941,7 @@ abstract class LocaleKeys {
static const offline = 'offline'; static const offline = 'offline';
static const videoCall = 'videoCall'; static const videoCall = 'videoCall';
static const liveVideoCallWithHMGDoctors = 'liveVideoCallWithHMGDoctors'; static const liveVideoCallWithHMGDoctors = 'liveVideoCallWithHMGDoctors';
static const liveAudioCallWithHMGDoctors = 'liveAudioCallWithHMGDoctors';
static const audioCall = 'audioCall'; static const audioCall = 'audioCall';
static const phoneCall = 'phoneCall'; static const phoneCall = 'phoneCall';
static const livePhoneCallWithHMGDoctors = 'livePhoneCallWithHMGDoctors'; static const livePhoneCallWithHMGDoctors = 'livePhoneCallWithHMGDoctors';
@ -1513,8 +1514,65 @@ abstract class LocaleKeys {
static const trackerAndOthers = 'trackerAndOthers'; static const trackerAndOthers = 'trackerAndOthers';
static const bmi = 'bmi'; static const bmi = 'bmi';
static const yesPleaseINeedHelp = 'yesPleaseINeedHelp'; static const yesPleaseINeedHelp = 'yesPleaseINeedHelp';
static const aiOverView = 'aiOverView';
static const generateAiAnalysis = 'generateAiAnalysis';
static const aiAnalysis = 'aiAnalysis';
static const prediction = 'prediction';
static const prevention = 'prevention';
static const disclaimer = 'disclaimer';
static const thisAboveInfo = 'thisAboveInfo';
static const aiDisclaimer = 'aiDisclaimer';
static const consent = 'consent';
static const bmiNormalDescription = 'bmiNormalDescription';
static const bmiUnderweightDescription = 'bmiUnderweightDescription';
static const bmiOverweightDescription = 'bmiOverweightDescription';
static const caloriesMaintenanceDescription = 'caloriesMaintenanceDescription';
static const caloriesModerateDeficitDescription = 'caloriesModerateDeficitDescription';
static const caloriesAggressiveDeficitDescription = 'caloriesAggressiveDeficitDescription';
static const bodyFatEssentialDescription = 'bodyFatEssentialDescription';
static const bodyFatFitnessDescription = 'bodyFatFitnessDescription';
static const bodyFatAverageDescription = 'bodyFatAverageDescription';
static const bodyFatObeseDescription = 'bodyFatObeseDescription';
static const bmrNormalDescription = 'bmrNormalDescription';
static const bmrLowDescription = 'bmrLowDescription';
static const bmrHighDescription = 'bmrHighDescription';
static const ibwAtTargetDescription = 'ibwAtTargetDescription';
static const ibwBelowTargetDescription = 'ibwBelowTargetDescription';
static const ibwAboveTargetDescription = 'ibwAboveTargetDescription';
static const ibwCloseToRangeDescription = 'ibwCloseToRangeDescription';
static const ibwUnderweightDescription = 'ibwUnderweightDescription';
static const ibwUnderweightGenericDescription = 'ibwUnderweightGenericDescription';
static const ibwOverweightDescription = 'ibwOverweightDescription';
static const ibwOverweightGenericDescription = 'ibwOverweightGenericDescription';
static const dietVeryLowCarbsDescription = 'dietVeryLowCarbsDescription';
static const dietLowCarbsDescription = 'dietLowCarbsDescription';
static const dietModerateCarbsDescription = 'dietModerateCarbsDescription';
static const dietUSDAGuidelinesDescription = 'dietUSDAGuidelinesDescription';
static const dietZoneDietDescription = 'dietZoneDietDescription';
static const contextDependent = 'contextDependent';
static const calculatedValue = 'calculatedValue';
static const calculationFormula = 'calculationFormula';
static const confirmYourLocation = 'confirmYourLocation';
static const confirmYourLocationDesc = 'confirmYourLocationDesc';
static const insideHospital = 'insideHospital';
static const outsideHospital = 'outsideHospital';
static const servicePriceList = 'servicePriceList';
static const servicePriceListDesc = 'servicePriceListDesc';
static const servicePriceListRights = 'servicePriceListRights';
static const serviceName = 'serviceName';
static const noFreeSlot = 'noFreeSlot';
static const noThanksIKnowTheClinic = 'noThanksIKnowTheClinic'; static const noThanksIKnowTheClinic = 'noThanksIKnowTheClinic';
static const unableToSendOTP = 'unableToSendOTP'; static const unableToSendOTP = 'unableToSendOTP';
static const timeFor = 'Time for'; 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';
static const timeFor = 'Time for';
} }

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -36,6 +37,7 @@ import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_mo
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart'; import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_model.dart';
import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_view_model.dart'; import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart'; import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/features/services_price_list/services_price_list_view_model.dart';
import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart'; import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart';
@ -75,12 +77,33 @@ Future<void> callAppStateInitializations() async {
: "3"); : "3");
AppState appState = getIt.get<AppState>(); AppState appState = getIt.get<AppState>();
appState.setDeviceTypeID = deviceTypeId; 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<void> callInitializations() async { Future<void> callInitializations() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.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(); await AppDependencies.addDependencies();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
HttpOverrides.global = MyHttpOverrides(); HttpOverrides.global = MyHttpOverrides();
@ -202,6 +225,9 @@ void main() async {
), ),
ChangeNotifierProvider<AskDoctorViewModel>( ChangeNotifierProvider<AskDoctorViewModel>(
create: (_) => getIt.get<AskDoctorViewModel>(), create: (_) => getIt.get<AskDoctorViewModel>(),
),
ChangeNotifierProvider<ServicesPriceListViewModel>(
create: (_) => getIt.get<ServicesPriceListViewModel>(),
) )
], child: MyApp()), ], child: MyApp()),
), // Wrap your app ), // Wrap your app
@ -222,9 +248,16 @@ class MyApp extends StatelessWidget {
builder: (context, orientation, deviceType) { builder: (context, orientation, deviceType) {
// SizeConfig().init(constraints, orientation); // SizeConfig().init(constraints, orientation);
return MaterialApp( return MaterialApp(
title: 'Dr. AlHabib', // title: 'Dr. AlHabib',
title: 'Dr. AlHabib Beta',
builder: (context, mchild) { builder: (context, mchild) {
return MediaQuery(data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling), child: mchild!); return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.noScaling,
alwaysUse24HourFormat: true,
),
child: mchild!,
);
}, },
showSemanticsDebugger: false, showSemanticsDebugger: false,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -8,6 +9,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/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart'; import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/penguin_method_channel.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -16,6 +18,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/book_appointments
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart'; import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart';
import 'package:hmg_patient_app_new/features/contact_us/models/feedback_type.dart'; import 'package:hmg_patient_app_new/features/contact_us/models/feedback_type.dart';
import 'package:hmg_patient_app_new/features/hospital/AppPermission.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_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/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/features/my_appointments/my_appointments_view_model.dart';
@ -38,7 +41,8 @@ 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/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.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 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:maps_launcher/maps_launcher.dart'; import 'package:map_launcher/map_launcher.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../medical_file/widgets/medical_file_card.dart'; import '../medical_file/widgets/medical_file_card.dart';
@ -95,6 +99,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
? () { ? () {
contactUsViewModel.setSelectedFeedbackType(FeedbackType(id: 1, nameEN: "Complaint for appointment", nameAR: 'شكوى على موعد')); contactUsViewModel.setSelectedFeedbackType(FeedbackType(id: 1, nameEN: "Complaint for appointment", nameAR: 'شكوى على موعد'));
contactUsViewModel.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel); contactUsViewModel.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel);
contactUsViewModel.setIsSendFeedbackTabSelected(true);
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: FeedbackPage(), page: FeedbackPage(),
@ -107,9 +112,9 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppointmentDoctorCard( AppointmentDoctorCard(
renderWidgetForERDisplay: ((widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) || // renderWidgetForERDisplay: ((widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) ||
(widget.patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || renderWidgetForERDisplay:
!Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID)), ((widget.patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || !Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID)),
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onAskDoctorTap: () async { onAskDoctorTap: () async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context)); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context));
@ -140,8 +145,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
}); });
}, },
onCancelTap: () async { onCancelTap: () async {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr(context: context)); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr(context: context));
await myAppointmentsViewModel.cancelAppointment( await myAppointmentsViewModel.cancelAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
@ -160,6 +163,18 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isDismissible: false, isDismissible: false,
isFullScreen: 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}", ); var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", );
setState(() { setState(() {
@ -187,15 +202,57 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.appointmentStatus.tr(context: context).toText16(isBold: true), Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.appointmentStatus.tr(context: context).toText16(isBold: true),
SizedBox(height: 4.h),
(!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
? LocaleKeys.notConfirmed.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: LocaleKeys.confirmed.tr(context: context).toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
],
),
((!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel) && widget.patientAppointmentHistoryResponseModel.nextAction != 10)
? CustomButton(
text: LocaleKeys.confirm.tr(),
onPressed: () async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingAppointmentPleaseWait.tr(context: context));
await myAppointmentsViewModel.confirmAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onSuccess: (apiResponse) {
LoaderBottomSheet.hideLoader();
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false);
showCommonBottomSheetWithoutHeight(
title: "",
context,
child: Utils.getSuccessWidget(loadingText: LocaleKeys.appointmentConfirmedSuccessfully.tr(context: context)),
callBackFunc: () {
Navigator.of(context).pop();
},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
backgroundColor: AppColors.successColor,
borderColor: AppColors.successColor,
textColor: AppColors.whiteColor,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
height: 40.h,
icon: AppAssets.confirm_appointment_icon,
iconColor: AppColors.whiteColor,
iconSize: 16.h,
)
: SizedBox.shrink())
], ],
), ),
SizedBox(height: 4.h),
(!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
? LocaleKeys.notConfirmed.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: LocaleKeys.confirmed.tr(context: context).toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h),
//TODO Add countdown timer in case of LiveCare Appointment //TODO Add countdown timer in case of LiveCare Appointment
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false
? Row( ? Row(
@ -228,9 +285,24 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
child: SizedBox( child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785, width: MediaQuery.of(context).size.width * 0.785,
child: CustomButton( child: CustomButton(
onPressed: () { onPressed: () async {
MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!), if (widget.patientAppointmentHistoryResponseModel.projectID == 130 || widget.patientAppointmentHistoryResponseModel.projectID == 120) {
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName); showDirectionsBottomSheet();
} else {
await MapLauncher.showMarker(
mapType: MapType.google,
coords: Coords(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!)),
title: widget.patientAppointmentHistoryResponseModel.projectName ?? "Habib Hospital",
).catchError((err) {
MapLauncher.showMarker(
mapType: Platform.isIOS ? MapType.apple : MapType.google,
coords: Coords(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!)),
title: widget.patientAppointmentHistoryResponseModel.projectName ?? "Habib Hospital",
);
});
}
}, },
text: LocaleKeys.getDirections.tr(context: context), text: LocaleKeys.getDirections.tr(context: context),
backgroundColor: AppColors.textColor.withValues(alpha: 0.8), backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
@ -471,7 +543,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getErrorWidget(loadingText: err), child: Utils.getErrorWidget(loadingText: LocaleKeys.noPrescriptionsForAppointment.tr(context: context)),
callBackFunc: () {}, callBackFunc: () {},
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,
@ -807,6 +879,89 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
); );
} }
void showDirectionsBottomSheet() {
showCommonBottomSheetWithoutHeight(
context,
title: "",
isDismissible: true,
isCloseButtonVisible: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.confirmYourLocation.tr(context: context).toText28(color: AppColors.textColor, isBold: true, height: 1.5),
SizedBox(height: 4.h),
LocaleKeys.confirmYourLocationDesc.tr(context: context).toText12(
color: AppColors.greyTextColor,
fontWeight: FontWeight.w500,
),
SizedBox(height: 24.h),
CustomButton(
text: LocaleKeys.insideHospital.tr(context: context),
onPressed: () {
Navigator.pop(context);
initPenguinSDK(widget.patientAppointmentHistoryResponseModel.projectID == 130 ? 1 : (widget.patientAppointmentHistoryResponseModel.projectID == 120 ? 3 : -1),
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID.toString());
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 56.h,
),
SizedBox(height: 8.h),
CustomButton(
text: LocaleKeys.outsideHospital.tr(context: context),
onPressed: () async {
Navigator.pop(context);
await MapLauncher.showMarker(
mapType: MapType.google,
coords: Coords(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!), double.parse(widget.patientAppointmentHistoryResponseModel.longitude!)),
title: widget.patientAppointmentHistoryResponseModel.projectName ?? "Habib Hospital",
).catchError((err) {
MapLauncher.showMarker(
mapType: Platform.isIOS ? MapType.apple : MapType.google,
coords: Coords(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!), double.parse(widget.patientAppointmentHistoryResponseModel.longitude!)),
title: widget.patientAppointmentHistoryResponseModel.projectName ?? "Habib Hospital",
);
});
},
backgroundColor: AppColors.chipSecondaryLightRedColor,
borderColor: AppColors.chipSecondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 56.h,
),
],
).paddingSymmetrical(24.w, 20.h),
callBackFunc: () {},
);
}
initPenguinSDK(int projectID, {String clinicID = ""}) async {
NavigationClinicDetails data = NavigationClinicDetails();
data.projectId = projectID.toString();
data.clinicId = clinicID;
// data.clinicId = "1";
final bool permited = await AppPermission.askPenguinPermissions();
if (!permited) {
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.bluetooth,
Permission.bluetoothConnect,
Permission.bluetoothScan,
Permission.activityRecognition,
].request().whenComplete(() {
PenguinMethodChannel().launch("penguin", getIt.get<AppState>().isArabic() ? "ar" : "en", getIt.get<AppState>().getAuthenticatedUser()?.patientId?.toString() ?? "", true, details: data);
});
}
}
openDoctorScheduleCalendar() async { openDoctorScheduleCalendar() async {
DoctorsListResponseModel doctor = DoctorsListResponseModel( DoctorsListResponseModel doctor = DoctorsListResponseModel(
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID, clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,

@ -491,6 +491,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onSuccess: (apiResponse) { onSuccess: (apiResponse) {
Future.delayed(Duration(milliseconds: 500), () { Future.delayed(Duration(milliseconds: 500), () {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.initAppointmentsViewModel(); myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
@ -511,6 +512,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!, isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!,
onSuccess: (apiResponse) { onSuccess: (apiResponse) {
Future.delayed(Duration(milliseconds: 500), () { Future.delayed(Duration(milliseconds: 500), () {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.initAppointmentsViewModel(); myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save