Merge remote-tracking branch 'origin/master' into watch_integration

# Conflicts:
#	android/app/build.gradle.kts
#	android/app/src/main/res/mipmap-hdpi/ic_launcher.png
#	android/app/src/main/res/mipmap-mdpi/ic_launcher.png
#	android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
#	android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
#	android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
#	android/app/src/main2/res/mipmap-hdpi/ic_launcher.png
#	android/app/src/main2/res/mipmap-mdpi/ic_launcher.png
#	android/app/src/main2/res/mipmap-xhdpi/ic_launcher.png
#	android/app/src/main2/res/mipmap-xxhdpi/ic_launcher.png
#	android/app/src/main2/res/mipmap-xxxhdpi/ic_launcher.png
#	android/build/reports/problems/problems-report.html
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/generated/locale_keys.g.dart
#	lib/theme/colors.dart
#	package/device_calendar_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
#	package/device_calendar_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
#	package/device_calendar_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
#	package/device_calendar_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
#	package/device_calendar_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
#	pubspec.yaml
watch_integration
tahaalam 2 weeks ago
commit 151fcf23d1

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

@ -0,0 +1 @@
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -19,22 +19,33 @@ if (keystorePropertiesFile.exists()) {
}
android {
// namespace = "com.ejada.hmg"
namespace = "com.cloudsolutions.HMGPatientApp"
compileSdk = 36
ndkVersion = "28.2.13676358"
// Using NDK 26 for better compatibility with Zoom SDK native libraries
ndkVersion = "27.0.12077973"
// ndkVersion = "25.1.8937393"
sourceSets {
getByName("main") {
jniLibs.srcDirs("src/main/jniLibs")
}
}
defaultConfig {
// applicationId = "com.ejada.hmg"
applicationId = "com.cloudsolutions.HMGPatientApp"
// minSdk = 24
minSdk = 29
targetSdk = 36
minSdk = 26
targetSdk = 35
compileSdk = 36
// targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
multiDexEnabled = true
// Filter to arm64-v8a for better native library compatibility
ndk {
abiFilters += listOf("arm64-v8a", "armeabi-v7a")
}
}
buildFeatures {
@ -85,7 +96,7 @@ android {
}
}
packagingOptions {
packaging {
jniLibs {
pickFirsts += listOf(
"lib/x86/libc++_shared.so",
@ -95,9 +106,16 @@ android {
"**/*.so"
)
useLegacyPackaging = true
// Keep Zoom SDK libraries unstripped to preserve symbols
keepDebugSymbols += listOf(
"*/libzoom_util.so",
"*/libzoom_check.so",
"*/libc++_shared.so"
)
}
resources {
excludes += listOf("META-INF/proguard/androidx-annotations.pro")
excludes.add("lib/*/libc++_shared.so")
}
}
@ -130,9 +148,13 @@ dependencies {
implementation("com.google.code.gson:gson:2.12.0")
// Zoom SDKs
implementation("us.zoom.videosdk:zoomvideosdk-core:1.12.10")
implementation("us.zoom.videosdk:zoomvideosdk-annotation:1.12.10")
implementation("us.zoom.videosdk:zoomvideosdk-videoeffects:1.12.10")
// implementation("us.zoom.videosdk:zoomvideosdk-core:1.12.10")
// implementation("us.zoom.videosdk:zoomvideosdk-annotation:1.12.10")
// implementation("us.zoom.videosdk:zoomvideosdk-videoeffects:1.12.10")
implementation("us.zoom.videosdk:zoomvideosdk-core:2.1.10")
implementation("us.zoom.videosdk:zoomvideosdk-videoeffects:2.1.10")
implementation("us.zoom.videosdk:zoomvideosdk-annotation:2.1.10")
// Networking
implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.11")
@ -193,5 +215,39 @@ dependencies {
implementation("com.whatsapp.otp:whatsapp-otp-android-sdk:0.1.0")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
// implementation(project(":vitalSignEngine"))
}
}
tasks.whenTaskAdded {
if (name.contains("merge") && name.contains("NativeLibs")) {
doLast {
val outputDir = File(project.buildDir, "intermediates/merged_native_libs/release/out/lib")
// Handle both architectures
val abis = listOf("arm64-v8a", "armeabi-v7a")
abis.forEach { abi ->
val targetFile = File(outputDir, "$abi/libc++_shared.so")
val sourceFile = file("src/main/jniLibs/$abi/libc++_shared.so")
if (sourceFile.exists() && targetFile.exists()) {
println("FORCING: Overwriting $abi version with known-good 1.2MB library")
sourceFile.copyTo(targetFile, overwrite = true)
}
}
}
}
}
//tasks.whenTaskAdded {
// if (name.contains("merge") && name.contains("NativeLibs")) {
// doLast {
// val outputDir = File(project.buildDir, "intermediates/merged_native_libs/release/out/lib")
// val targetFile = File(outputDir, "arm64-v8a/libc++_shared.so")
// val sourceFile = file("src/main/jniLibs/arm64-v8a/libc++_shared.so")
//
// if (sourceFile.exists()) {
// println("FORCE REPLACING: Injecting 1.2MB libc++ into APK...")
// sourceFile.copyTo(targetFile, overwrite = true)
// }
// }
// }
//}

@ -52,6 +52,11 @@
*;
}
# Prevent stripping of standard C++ symbols
-keepclassmembers class * {
native <methods>;
}
-dontwarn com.opentok.android.**
-dontwarn com.opentok.otc.**

@ -49,7 +49,7 @@
<uses-permission
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
tools:node="remove" /> <!-- <uses-permission android:name="android.permission.INTERNET" /> -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:node="remove" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
@ -62,7 +62,6 @@
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature
@ -133,6 +132,7 @@
android:screenOrientation="sensorPortrait"
android:showOnLockScreen="true"
android:usesCleartextTraffic="true"
android:extractNativeLibs="true"
tools:replace="android:label">
<!-- <activity-->
<!-- android:name="com.cloud.hmg_patient_app.whatsapp.WhatsAppCodeActivity"-->
@ -148,6 +148,9 @@
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="true" />
<meta-data
android:name="com.google.ar.core"
tools:node="remove" />
<activity
android:name=".MainActivity"
@ -155,7 +158,7 @@
android:enabled="true"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:launchMode="singleInstance"
android:showOnLockScreen="true"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize"

File diff suppressed because one or more lines are too long

@ -0,0 +1,3 @@
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.76629 0.292994C8.94577 0.52652 8.97196 0.843482 8.83323 1.10329C8.24927 2.19693 7.91792 3.4461 7.91792 4.77489C7.91792 9.0867 11.4133 12.5821 15.7251 12.5821C17.0539 12.5821 18.3031 12.2508 19.3967 11.6668C19.6565 11.5281 19.9735 11.5543 20.207 11.7337C20.4406 11.9132 20.5474 12.2128 20.4802 12.4995C19.4056 17.085 15.2909 20.5 10.3769 20.5C4.64589 20.5 0 15.8541 0 10.1232C0 5.20909 3.41505 1.09448 8.0005 0.0198166C8.28726 -0.0473898 8.58681 0.0594678 8.76629 0.292994Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 610 B

@ -1,4 +1,3 @@
<svg height="1792" id="download" width="1792" xmlns="http://www.w3.org/2000/svg">
<path
d="M1344 1344q0-26-19-45t-45-19-45 19-19 45 19 45 45 19 45-19 19-45zm256 0q0-26-19-45t-45-19-45 19-19 45 19 45 45 19 45-19 19-45zm128-224v320q0 40-28 68t-68 28H160q-40 0-68-28t-28-68v-320q0-40 28-68t68-28h465l135 136q58 56 136 56t136-56l136-136h464q40 0 68 28t28 68zm-325-569q17 41-14 70l-448 448q-18 19-45 19t-45-19L403 621q-31-29-14-70 17-39 59-39h256V64q0-26 19-45t45-19h256q26 0 45 19t19 45v448h256q42 0 59 39z"></path>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.73038 1.67378e-07L7.73039 1.67378e-07C9.37341 -9.67694e-06 10.6639 -1.7412e-05 11.6715 0.135446C12.704 0.274261 13.5232 0.564537 14.1668 1.20819C14.8105 1.85183 15.1007 2.67102 15.2396 3.70352C15.375 4.71108 15.375 6.0016 15.375 7.64462V7.7304C15.375 9.37342 15.375 10.6639 15.2396 11.6715C15.1007 12.704 14.8105 13.5232 14.1668 14.1668C13.5232 14.8105 12.704 15.1007 11.6715 15.2396C10.6639 15.375 9.3734 15.375 7.73038 15.375H7.6446C6.00158 15.375 4.71108 15.375 3.70352 15.2396C2.67102 15.1007 1.85183 14.8105 1.20819 14.1668C0.564537 13.5232 0.274261 12.704 0.135446 11.6715C-1.7412e-05 10.6639 -9.67693e-06 9.37341 1.67378e-07 7.73039L1.67378e-07 7.73038L1.67378e-07 7.64462L1.67378e-07 7.64461C-9.67693e-06 6.00159 -1.7412e-05 4.71108 0.135446 3.70352C0.274261 2.67102 0.564537 1.85183 1.20819 1.20819C1.85183 0.564537 2.67102 0.274261 3.70352 0.135446C4.71108 -1.7412e-05 6.00159 -9.67694e-06 7.64461 1.67378e-07L7.64462 1.67378e-07L7.73038 1.67378e-07ZM7.6875 3.1875C8.10171 3.1875 8.4375 3.52329 8.4375 3.9375V6.28379H8.85004L8.86442 6.28376C8.9186 6.28359 9.02672 6.28324 9.12235 6.29699C9.20821 6.30934 9.59436 6.37258 9.77265 6.77369C9.95094 7.1748 9.73916 7.50383 9.6908 7.57583C9.63693 7.65604 9.56422 7.73607 9.5278 7.77617L9.51814 7.78682L9.01431 8.34503C8.84929 8.52797 8.67863 8.71716 8.51617 8.85448C8.33191 9.01023 8.05864 9.1875 7.6875 9.1875C7.31636 9.1875 7.04308 9.01023 6.85883 8.85448C6.69637 8.71716 6.52571 8.52796 6.36069 8.34502L5.85686 7.78682L5.8472 7.77616C5.81077 7.73607 5.73807 7.65603 5.6842 7.57583C5.63584 7.50383 5.42406 7.1748 5.60235 6.77369C5.78064 6.37258 6.16679 6.30934 6.25265 6.29699C6.34828 6.28324 6.4564 6.28359 6.51058 6.28376L6.52496 6.28379H6.9375L6.9375 3.9375C6.9375 3.52329 7.27329 3.1875 7.6875 3.1875ZM4.6875 11.4375C4.6875 11.0233 5.02329 10.6875 5.4375 10.6875H9.9375C10.3517 10.6875 10.6875 11.0233 10.6875 11.4375C10.6875 11.8517 10.3517 12.1875 9.9375 12.1875H5.4375C5.02329 12.1875 4.6875 11.8517 4.6875 11.4375Z" fill="#F43333"/>
</svg>

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -46,7 +46,7 @@
"nationality": "الجنسية",
"neverWait": "لا تنتظر في الطابور أبدًا",
"reminderTitle": "لديك موعد مع الدكتور.",
"appointmentCalendar": "هل ترغب في ضبط تذكير لهذا الموعد في تقويمك؟",
"appointmentCalendar": "هل ترغب في تعيين تذكير لهذا الموعد في التقويم الخاص بك؟",
"appointmentSuccess": "تم حجز الموعد بنجاح",
"docQualifications": "مؤهلات الطبيب",
"pressAgain": "اضغط مرة أخرى للخروج من التطبيق",
@ -58,7 +58,7 @@
"patientShare": "نسبة المريض",
"patientShareWithTax": "نسبة المريض مع الضريبة",
"confirmAppo": "تأكيد الموعد",
"confirmLiveCare": "تأكيد الرعاية الحية",
"confirmLiveCare": "تأكيد ال لايف كير",
"waitingForDoctor": "في انتظار الطبيب",
"appointment": "موعد",
"confirmLater": "تأكيد لاحقًا",
@ -70,20 +70,20 @@
"payNow": "ادفع الآن",
"viewQR": "عرض رمز الاستجابة السريعة",
"instruction": "تعليمات",
"livecare": "الرعاية الحية",
"livecareAppo": "موعد الرعاية الحية",
"livecare": "لايف كير",
"livecareAppo": "موعد لايف كير",
"agreeTo": "أوافق على",
"termsConditoins": "الشروط والأحكام",
"cancelAppoMsg": "هل أنت متأكد أنك تريد إلغاء هذا الموعد؟",
"changePayment": "تغيير طريقة الدفع",
"upcomingNoAction": "لا حاجة لإجراء أي إجراء",
"upcomingNoAction": "لا يتطلب أي إجراء",
"upcomingConfirm": "يرجى تأكيد الموعد لتجنب الإلغاء",
"bookSuccessConfirmMore2412": "ستكون عملية الدفع عبر الإنترنت متاحة قبل 24 ساعة <20><>ن الموعد.",
"upcomingPaymentPending": "سيتم تفعيل الدفع عبر الإنترنت قبل 24 ساعة من موعد الموعد",
"upcomingPaymentNow": "ادفع عبر الإنترنت الآن لتجنب الانتظار الطويل",
"upcomingQR": "استخدم رمز الاستجابة السريعة لتسجيل الوصول في المستشفى",
"upcomingVirtual": "هذا موعد افتراضي، يرجى الالتزام بالتعليمات لتجربة سلسة.",
"upcomingLivecare": "هذا موعد رعاية حية",
"upcomingLivecare": "هذا موعد لايف كير",
"upcomingDetails": "المزيد من التفاصيل",
"reschedule": "إعادة جدولة",
"raise": "رفع",
@ -92,7 +92,7 @@
"reminder": "تذكير",
"location": "المواقع",
"online": "عبر الإنترنت",
"payment": "الالكتروني",
"payment": "الدفع",
"onlinePayment": "عبر الإنترنت",
"onlinePaymentSubtitle": "الدفع",
"cancelNocaps": "إلغاء",
@ -161,7 +161,7 @@
"passQRAppoAttend": "مرر رمز الاستجابة السريعة عبر أجهزة الحضور المتاحة في المستشفى.",
"sitWaitingQR": "اجلس في غرف الانتظار حتى يتم استدعاؤك من قبل الممرضة.",
"attendRegisterCode": "رمز تسجيل الحضور",
"scanQRHospital": "اقترب من لوحة التسجيل عبر الإنترنت في المستشفى وامسح عبر NFC أو رمز الاستجابة السريعة لتسجيل الوصول",
"scanQRHospital": "توجّه إلى لوحة تسجيل الوصول الإلكتروني في المستشفى، وقم بالمسح عبر تقنية NFC أو رمز الاستجابة السريعة (QR) لإتمام تسجيل الوصول.",
"scanNFC": "امسح NFC لتسجيل الوصول",
"sendEmail": "إرسال بريد إلكتروني",
"success": "تم بنجاح",
@ -174,7 +174,7 @@
"arrived": "وصل",
"payNowBookSuccess": "ادفع الآن عبر تطبيق الحبيب",
"payNowBookSuccesstext1": "ادفع الآن باستخدام خدمة الدفع عبر الإنترنت من بوابات الدفع الآمنة",
"payNowBookSuccesstext2": "يمكنك أيضًا الدفع لاحقًا عبر الدفع عبر الإنترنت أو في المستشفى",
"payNowBookSuccesstext2": "يمكنك أيضًا الدفع لاحقًا عبر الدفع الإلكتروني أو في المستشفى.",
"payLater": "ادفع لاحقًا",
"askDocNotAllowed": "هذه الخدمة ستكون متاحة فقط لزيارة الطبيب قبل 15 يومًا",
"moreVerify": "خيارات تحقق إضافية",
@ -246,13 +246,13 @@
"myMedicalFileSubTitle": "جميع سجلاتك الطبية",
"viewMore": "عرض المزيد",
"homeHealthCareService": "خدمة الرعاية الصحية المنزلية",
"onlinePharmacy": "صيدلية عبر الإنترنت",
"onlinePharmacy": "الصيدلية الإلكترونية",
"emergencyService": "خدمة الطوارئ",
"onlinePaymentService": "خدمة الدفع عبر الإنترنت",
"offersAndPackages": "طلب تحويل عبر الإنترنت",
"comprehensiveMedicalCheckup": "فحص طبي شامل",
"hmgService": "خدمة HMG",
"viewAllHabibMedicalService": "عرض جميع خدمات حبيب الطبية",
"viewAllHabibMedicalService": "عرض جميع خدمات الحبيب الطبية",
"viewAll": "عرض الكل",
"view": "عرض",
"contactUs": "اتصل بنا",
@ -263,7 +263,7 @@
"consultation": "استشارة",
"logs": "السجلات",
"textToSpeech": "كيف يمكنني مساعدتك؟",
"locationDialogMessage": "سيساعدك السماح لتطبيق HMG بالوصول إلى موقعك في عرض المستشفيات الأقرب إليك.",
"locationDialogMessage": "السماح لتطبيق HMG بالوصول إلى موقعك سيساعدك في عرض المستشفيات الأقرب إليك.",
"userViewRequester": "يريد المستخدم عرض ملفك الطبي",
"userView": "يمكن للمستخدم عرض ملفك الطبي",
"parking": "موقف السيارات",
@ -288,7 +288,7 @@
"requestA": "طلب",
"noBookedAppointments": "لا توجد مواعيد محجوزة",
"noConfirmedAppointments": "لا توجد مواعيد مؤكدة",
"noArrivedAppointments": "لا توجد مواعيد وصلت",
"noArrivedAppointments": "لا توجد مواعيد تم تسجيل الوصول إليها",
"myAppointmentsList": "المواعيد",
"myAppointments": "مواعيدي",
"radiology": "الأشعة",
@ -358,11 +358,11 @@
"userAgreement": "اتفاقية المستخدم",
"updateSuccessfully": "تم التحديث بنجاح",
"checkVaccineAvailability": "تحقق من توفر اللقاح",
"myVaccinesAvailability": "توفر لقاحاتي",
"myVaccinesAvailability": "توفر اللقاحات الخاصة بي",
"paymentService": "خدمة الدفع",
"paymentOnline": "الخدمة",
"onlineCheckIn": "تسجيل الوصول عبر الإنترنت",
"myBalances": "أرصدةي",
"myBalances": "رصيدي",
"myWallet": "محف<D8AD><D981>تي",
"balanceAmount": "مبلغ المحفظة",
"totalBalance": "إجمالي الرصيد",
@ -383,7 +383,7 @@
"otherAccount": "حساب آخر",
"selectBeneficiary": "اختر المستفيد",
"confirmThePayment": "تأكيد الدفع",
"depositorName": "اسم الوديع",
"depositorName": "اسم مُقدِّم الإيداع",
"mobileNumber": "رقم الجوال",
"phoneNumber": "رقم الهاتف",
"country": "البلد",
@ -410,7 +410,7 @@
"diameter": "القطر",
"remarks": "ملاحظات: ",
"activeMedications": "الأدوية النشطة",
"expDate": "تاريخ انتهاء الصلاحية النشط:",
"expDate": "تاريخ انتهاء الصلاحية:",
"route": "الطريق",
"frequency": "التكرار",
"dailyQuantity": "<22><>لكمية اليومية:",
@ -427,7 +427,7 @@
"doctorResponses": "ردود الطبيب",
"ne_w": "جديد",
"all": "الكل",
"dailyWater": "فحص الماء اليومي",
"dailyWater": "متابعة الماء اليومية",
"questionHere": "أدخل السؤال هنا...",
"viewDoctorResponses": "عرض ردود الطبيب",
"serviceInformationButton": "تسجيل الدخول / التسجيل",
@ -452,7 +452,7 @@
"brands": "العلامات التجارية",
"productDetails": "تفاصيل المنتج",
"medicationRefill": "إعادة تعبئة الدواء",
"pillReminder": "تذكير بالحبوب",
"pillReminder": "تذكير الأدوية",
"shippingAddresses": "عناوين الشحن",
"reachUs": "تواصل معنا",
"ourLocations": "مواقعنا",
@ -472,7 +472,7 @@
"cancelled": "ملغى",
"writeReview": "اكتب تقييمًا",
"shareReview": "شارك التقييم",
"review": " تقييمات",
"review": " التقييمات",
"viewMedicalFile": "عرض التفاصيل",
"viewAllServices": "عرض جميع الخدمات",
"medicalFile": "الملف الطبي",
@ -488,7 +488,7 @@
"services2": "الخدمات",
"cantSeeProfile": "لرؤية ملفك الطبي، يرجى تسجيل الدخول أو التسجيل الآن",
"loginRegisterNow": "تسجيل الدخول أو التسجيل الآن",
"hmgPharmacy": "صيدلية HMG",
"hmgPharmacy": "صيدلية مجموعة الحبيب الطبية",
"ecommerceSolution": "حلول التجارة الإلكترونية",
"comprehensive": "شامل",
"onlineConsulting": "استشارات عبر الإنترنت",
@ -525,7 +525,7 @@
"payOnline": "الدفع عبر الإنترنت",
"cancelOrder": "إلغاء الطلب",
"confirmAddress": "تأكيد العنوان ",
"confirmLocation": "أكيد الموقع ",
"confirmLocation": "أكد الموقع ",
"conditionsHMG": "الشروط والأحكام ",
"conditions": "الشروط والأحكام لكوم",
"confirmDeleteMsg": "هل أنت متأكد! تريد الحذف ",
@ -635,12 +635,12 @@
"infoInsuranceCards": "تتيح لك هذه الخدمة عرض جميع بطاقات التأمين التي تم تسجيلها خلال زياراتك لمجموعة الحبيب الطبية بالإضافة إلى:",
"infoInsuranceCardsPoints": "",
"infoAllergies": "تتيح لك هذه الخدمة عرض جميع أنواع الحساسية المسجلة خلال زياراتك لمجموعة الحبيب الطبية.",
"infoSickLeaves": "تتيح لك هذه الخدمة عرض جميع إجازات المرضى التي تم أخذها في مجموعة الحبيب الطبية بالإضافة إلى:",
"infoSickLeaves": "تتيح لك هذه الخدمة عرض جميع الاجازات المرضيه التي تم أخذها في مجموعة الحبيب الطبية بالإضافة إلى:",
"infoSickLeavePoints": "",
"infoApprovals": "تتيح لك هذه الخدمة عرض جميع طلبات الموافقة التي تم إرسالها إلى شركات التأمين بالإضافة إلى:",
"infoApprovalPoints": "",
"infoMonthReport": "عند تفعيل هذه الخدمة، سيقوم النظام بإرسال تقرير شهري تلقائيًا إلى البريد الإلكتروني المسجل يتضمن العلامات الحيوية والنتائج لآخر الزيارات التي تمت في مجموعة الحبيب الطبية.",
"languageSetting": "لغة الرسائل القصيرة، واتساب، ومكالمات التأكيد",
"languageSetting": "الرسائل القصيرة، واتساب، لغة مكالمات التأكيد",
"alert": "تنبيهات",
"emailAlert": "تنبيه عبر البريد الإلكتروني",
"smsAlert": "تنبيه عبر الرسائل القصيرة",
@ -648,7 +648,7 @@
"emrgName": "اسم جهة الاتصال في حالات الطوارئ",
"emrgNo": "رقم جهة الاتصال في حالات الطوارئ",
"modes": "الأوضاع",
"vibration": "اهتزاز ردود الفعل اللمسية",
"vibration": "اهتزاز عند اللمس",
"blindModes": "أوضاع للمكفوفين جزئيًا",
"invertTheme": "عكس",
"offTheme": "إيقاف",
@ -666,7 +666,7 @@
"findUs": "اعثر علينا",
"liveChat": "دردشة مباشرة",
"service": "خدمة",
"hmgServiceLabel": "خدمة HMG",
"hmgServiceLabel": "خدمة مجموعة الحبيب الطبية",
"healthWeatherIndicators": "مؤشرات الطقس الصحية",
"healthTipsBasedOnCurrentWeather": "نصائح صحية بناءً على الطقس الحالي",
"moreDetails": "المزيد من التفاصيل",
@ -705,7 +705,7 @@
"compliment": "تقدير",
"suggestion": "اقتراح",
"yourFeedback": "تم إرسال ملاحظاتك",
"selectPart": "يرجى اختيار الجزء الذي تشتك<EFBFBD><EFBFBD> منه",
"selectPart": "يرجى اختيار الجزء الذي تشتكي منه",
"number": "رقم",
"notClassified": "غير مصنف",
"selectClinic": "اختر العيادة",
@ -714,13 +714,13 @@
"youCanFind": "يمكنك العثور على ",
"itemInSearch": " عنصر في البحث",
"bloodDonation": "التبرع بالدم",
"bloodDonationInfo": "من خلال هذه الخدمة، يمكنك تسجيل اسمك كمتبرع بالدم <EFBFBD><EFBFBD>يث سيتواصل معك بنك الدم في مجموعة الحبيب الطبية في حالة الحاجة إلى فصيلة الدم.",
"bloodDonationInfo": "من خلال هذه الخدمة، يمكنك تسجيل اسمك كمتبرع بالدم حيث سيتواصل معك بنك الدم في مجموعة الحبيب الطبية في حالة الحاجة إلى فصيلة الدم.",
"bloodInstruction": "أدخل المعلومات المطلوبة، من أجل التسجيل في خدمة التبرع بالدم",
"viewTerms": "لعرض الشروط والأحكام",
"wantConnectHmgNetwork": "عزيزي العميل، لا يوجد وصول إلى الإنترنت، هل ترغب في الاتصال بشبكة HMG لاستخدام تطبيقنا، تأكد من أنك في نطاق شبكة HMG",
"failedToAccessHmgServices": "متصل بشبكة HMG،\n\nلكن فشل في الوصول إلى خدمات HMG",
"wantConnectHmgNetwork": "عزيزي العميل، لا يوجد وصول إلى الإنترنت، هل ترغب في الاتصال بشبكة مجموعة الحبيب الطبية لاستخدام تطبيقنا، تأكد من أنك في نطاق شبكة مجموعة الحبيب الطبية",
"failedToAccessHmgServices": "متصل بشبكة مجموعة الحبيب الطبية،\n\nلكن فشل في الوصول إلى خدمات مجموعة الحبيب الطبية",
"offerAndPackages": "عروض وباقات",
"offerAndPackagesDetails": "تتيح لك هذه الخدمة عرض جميع عروض HMG:",
"offerAndPackagesDetails": "تتيح لك هذه الخدمة عرض جميع عروض مجموعة الحبيب الطبية:",
"invoiceNo": "رقم الفاتورة",
"invoiceDate": "تاريخ الفاتورة",
"specialResult": "نتيجة خاصة",
@ -739,25 +739,25 @@
"excellent": "ممتاز",
"average": "متوسط",
"infoSigns": "تتيح لك هذه الخدمة عرض جميع العلامات الحيوية التي تم قياسها في مجموعة الحبيب الطبية، مثل (الطول، الوزن، مؤشر كتلة الجسم، معدل ضربات القلب، إلخ.) بالإضافة إلى عرض بعض الرسوم البيانية الإحصائية.",
"infoAdvancePayment": "تم تصميم هذه الخدمة بحيث يمكنك إيداع مبلغ مقدم إما في حسابك أو في حساب شخص آخر في مجموعة الحبيب الطبية.",
"infoAdvancePayment": "تم تصميم هذه الخدمة بحيث يمكنك إيداع مبلغ مقدم إما في حسابك أو في حساب شخص آخر، في مجموعة الحبيب الطبية.",
"infoMyBalance": "تتيح لك هذه الخدمة التحقق من رصيدك في جميع الفروع",
"erContant": "تظهر هذه الخدمة أقرب فرع من بين جميع فروع مجموعة الحبيب الطبية بناءً على موقعك الحالي.",
"infoAmbulance": "من خلال هذه الخدمة، يمكنك طلب الإخلاء بواسطة سيارة إسعاف، سواء من المنزل أو إلى المنزل، بالإضافة إلى مجموعة من الخدمات الأخرى",
"infoMyAppointments": "تتيح لك هذه الخدمة رؤية جميع المواعيد التي زرتها في مجموعة الحبيب الطبية، ومن خلال هذه الخدمة:",
"infoTodo": "تم تصميم هذه الخدمة لتمكينك من الحصول على رابط سريع لقائمة المهام التي تحتاج إلى القيام بها",
"infoTodo": "تم تصميم هذه الخدمة لتمكينك من الحصول على رابط سريع لقائمة المهام التي تحتاج القيام بها",
"familyInfo": "من خلال هذه الخدمة، ستتمكن من ربط ملفات عائلتك الطبية بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي.",
"rrtdDetails": "تقدم فريق الاستجابة السريعة خدمة طبية شاملة لجميع أنواع الحالات العاجلة والمستقرة من جميع الأعمار، بما في ذلك البالغين والمرضى الأطفال، وتغطي الخدمة فريق طبي مدرب تدريبًا عاليًا ومجهز تجهيزًا كاملاً قادرًا على تقديم أفضل رعاية طبية في منزل المريض.",
"homeHealthCareText": "تقدم هذه الخدمة مجموعة من خدمات الرعاية الصحية المنزلية، والمتابعة المستمرة والشاملة في أماكن إقامتهم لأولئك الذين لا يمكنهم الوصول إلى المرافق الصحية، مثل (تحليلات المختبر - الأشعة - التطعيمات - العلاج الطبيعي)، إلخ.",
"onlineCheckInAgreement": "تسجيل الوصول عبر الإنترنت مخصص للحال<EFBFBD><EFBFBD>ت التي لا تهدد الحياة. اتصل بالهلال الأحمر (997) أو اذهب إلى أقرب قسم طوارئ إذا كان هناك: \n\nعلامات السكتة الدماغية أو النوبة القلبية \nhالة من النوبات أو الإغماء \nهناك إصابة تهدد الطرف أو الحياة \nصورة لإصابات خطيرة",
"onlineCheckInAgreement": "تسجيل الوصول عبر الإنترنت مخصص للحالات التي لا تهدد الحياة. اتصل بالهلال الأحمر (997) أو اذهب إلى أقرب قسم طوارئ إذا كان هناك: \n\nعلامات السكتة الدماغية أو النوبة القلبية \nhالة من النوبات أو الإغماء \nهناك إصابة تهدد الطرف أو الحياة \nصورة لإصابات خطيرة",
"infoEreferral": "تتيح لك هذه الخدمة تقديم طلب إحالة من أي مقدم رعاية صحية سواء داخل أو خارج المملكة العربية السعودية إلى أي من مستشفيات HMG، عن طريق ملء بعض بيانات المريض وإرفاق التقارير الطبية، علاوة على ذلك يمكنك تتبع حالة الطلب (قيد المعالجة، مقبول أو مرفوض)",
"erConsultation": "تتيح لك هذه الخدمة إجراء استشارة افتراضية عبر الإنترنت عبر مكالمة فيديو مباشرة مع الطبيب من أي مكان وفي أي وقت.",
"myInvoice": "القائمة",
"invoiceList": "فواتيري",
"thisItemIsNotAvailable": "هذا العنصر غير متوفر",
"beforeAfterImages": "صور قبل وبعد",
"clinicAcceptLivecare": "لا حاجة للانتظار أو الزيارة يمكنك الآن الحصول على استشارة طبية عبر مكالمة فيديو (خدمة الرعاية الحية) في اسم العيادة وسيتصل بك الطبيب على الور",
"livecareModalTop": "تقبل هذه العيادة خدمات الرعاية الحية",
"livecarePoint2": "<EFBFBD><EFBFBD>يتصل بك طبيب متخصص",
"clinicAcceptLivecare": "لا حاجة للانتظار أو الزيارة يمكنك الآن الحصول على استشارة طبية عبر مكالمة فيديو (لايف كير) في اسم العيادة وسيتصل بك الطبيب على الفور",
"livecareModalTop": "تقبل هذه العيادة خدمات ال لايف كير",
"livecarePoint2": "سوف يتصل بك طبيب متخصص",
"livecarePoint3": "سيكون لدى الطبيب القدرة على رؤية تاريخ ملفك الطبي الكامل",
"livecarePoint4": "تتوفر خدمة توصيل الأدوية المجانية",
"livecarePoint5": "لا حاجة للزيارة، الخدمة في مكانك",
@ -787,7 +787,7 @@
"enterEmailDesc": "أدخل عنوان بريدك الإلكتروني لإكمال عملية إنشاء ملف طبي",
"enterPhoneDesc": "أدخل رقم هاتفك لتلقي رمز التحقق ",
"pleaseChooseOption": "الرجاء اختيار من الخيارات أدناه لتلقي رمز التحقق OTP",
"prepareToElevate": "هل أنت مستعد لتحسين صحتك ورفاهتك؟",
"prepareToElevate": "هل أنت مستعد لتحسين صحتك ورفاهيتك؟",
"iAcceptTermsConditions": "أوافق على الشروط والأحكام",
"alreadyHaveAccount": "هل لديك حساب بالفعل؟",
"loginNow": "تسجيل الدخول الآن",
@ -804,7 +804,7 @@
"guest": "زائر",
"switchAccount": "تبديل الحساب",
"lastLoginBy": "آخر تسجيل دخول بواسطة",
"allSet": "جاهز! الآن يمكنك تسجيل الدخول باستخدام Face ID / Biometric أو البصمة",
"allSet": "جاهز! الآن يمكنك تسجيل الدخول باستخدام Face ID أو البصمة",
"enableQuickLogin": "تمكين تسجيل الدخول السريع",
"enableMsg": "تمكين تسجيل الدخول السريع سيسمح بالتحقق من خلال Face ID / Biometric الخاص بجهازك الحالي",
"notNow": "ليس الآن",
@ -849,12 +849,12 @@
"searchHospital": "بحث في المستشفى",
"skip": "تخطي",
"getStarted": "ابدأ الآن",
"onboardingHeading1": "حجز المواعيد لم يكن أسهل من قبل",
"onboardingHeading1": "حجز المواعيد لم يكن أسهل من الآن.",
"onboardingBody1": "ببضع نقرات فقط يمكنك استشارة الطبيب الذي تختاره.",
"onboardingHeading2": "الوصول إلى السجل الطبي بين يديك",
"onboardingBody2": "تتبع تاريخك الطبي بما في ذلك الفحوصات المخبرية، الوصفات الطبية، التأمين، وغيرها.",
"hmgHospitals": "مستشفيات HMG",
"hmcMedicalClinic": "مراكز HMC الطبية",
"hmgHospitals": "مستشفيات مجموعة الحبيب الطبية",
"hmcMedicalClinic": "مراكز مجموعة الحبيب الطبية",
"applyFilter": "تطبيق الفلتر",
"facilityAndLocation": "المرفق والموقع",
"regionAndLocation": "المنطقة والمواقع",
@ -874,7 +874,6 @@
"laserClinic": "عيادة الليزر",
"continueString": "يكمل",
"covid_info": "تجري مستشفيات د. سليمان الحبيب فحص فيروس كورونا المستجد وتصدر شهادات السفر على مدار الساعة، طوال أيام الأسبوع، وبسرعة ودقة عالية. يمكن للراغبين في الاستفادة من هذه الخدمة زيارة أحد فروع مستشفيات د. سليمان الحبيب وإجراء فحص كورونا خلال بضع دقائق والحصول على النتائج خلال عدة ساعات خدمة فحص فيروس كورونا Covid 19 بتقنية PCR للكشف عن الفيروس وفقاً لأعلى المعايير العالمية وبأحدث أجهزة RT-PCR عالية الدقة (GeneXpert الأمريكي وغيره)، وهي طرق معتمدة من قبل هيئة الغذاء والدواء وكذلك من قبل المركز السعودي للوقاية من الأمراض المُعدية",
"appointmentDetails": "تفاصيل الموعد",
"checkingDoctorAvailability": "جاري التحقق من توفر الطبيب...",
"cancellingAppointmentPleaseWait": "جاري إلغاء الموعد، يرجى الانتظار...",
@ -924,7 +923,7 @@
"offersFreeMedicineDelivery": "يوفر توصيل مجاني للأدوية لموعد لايف كير",
"dentalChiefComplaints": "الشكاوى الرئيسة للأسنان",
"viewAvailableAppointments": "عرض المواعيد المتاحة",
"doctorProfile": "الملف للطبيب",
"doctorProfile": " ملف الطبيب",
"waitingAppointment": "موعد الانتظار",
"hospitalInformation": "معلومات المستشفى",
"fetchingAppointmentShare": "جاري جلب تفاصيل الموعد...",
@ -960,10 +959,10 @@
"visaOrMastercard": "فيزا أو ماستركارد",
"tamara": "تمارا",
"fetchingApplePayDetails": "جاري جلب تفاصيل Apple Pay، يرجى الانتظار...",
"liveCarePendingRequest": "لايف كير حية معلق",
"liveCarePendingRequest": "طلب لايف كير قيد الانتظار",
"callLiveCareSupport": "اتصل بدعم لايف كير",
"whatIsWaitingAppointment": "ما هو موعد الانتظار؟",
"waitingAppointmentsFeature": "تتيح لك ميزة مواعيد الانتظار حجز موعد أثناء تواجدك داخل مبنى المستشفى، وفي حال عدم توفر فتحة متاحة في جدول الطبيب.",
"waitingAppointmentsFeature": "تتيح لك ميزة مواعيد الانتظار حجز موعد أثناء تواجدك داخل مبنى المستشفى، وفي حال عدم توفر مواعيد متاحة في جدول الطبيب.",
"appointmentWithDoctorConfirmed": "الموعد مع الطبيب مؤكد، ولكن وقت الدخول غير محدد.",
"paymentWithinTenMinutes": "ملاحظة: يجب عليك الدفع خلال 10 دقائق من الحجز، وإلا سيتم إلغاء موعدك تلقائياً",
"liveLocation": "الموقع المباشر",
@ -1233,7 +1232,7 @@
"invalidWeight": "الوزن غير صالح",
"timeToDrinkWater": "حان وقت شرب الماء! 💧",
"stayHydratedDrinkWater": "ابق رطبًا! اشرب {amount} مل من الماء.",
"visitPharmacyOnline": "زيارة الصيدلة على الانترنت",
"visitPharmacyOnline": "زيارة الصيدلية على الانترنت",
"howAreYouFeelingToday": "كيف حالك اليوم؟",
"checkYourSymptomsWithScale": "تحقق من أعراضك باستخدام ذا المقياس",
"checkYourSymptoms": "تحقق من أعراضك",
@ -1241,7 +1240,7 @@
"youHaveEROnlineCheckInRequest": "لديك طلب تسجيل وصول عبر الإنترنت للطوارئ",
"quickLinks": "روابط سريعة",
"viewMedicalFileLandingPage": "عرض الملف الطبي",
"immediateLiveCareRequest": "طلب LiveCare الفوري",
"immediateLiveCareRequest": "طلب لايف كير فوري",
"yourTurnIsAfterPatients": "دورك بعد {count} مريض.",
"dontHaveHHCOrders": "ليس لديك أي أوامر رعاية صحية منزلية حتى الآن.",
"hhcOrders": "أوامر الرعاية الصحية المنزلية",
@ -1257,7 +1256,7 @@
"insuranceActive": "التأمين نشط",
"patientCardID": "رقم بطاقة المريض: {id}",
"noInsuranceApprovals": "لم تحصل على أي موافقات تأمينية حتى الآن.",
"noInsuranceWithHMG": "ليس لديك تأمين مسجل لدى مجموعة حبيب الطبية.",
"noInsuranceWithHMG": "ليس لديك تأمين مسجل لدى مجموعة الحبيب الطبية.",
"referenceRange": "النطاق المرجعي",
"downloadReport": "تنزيل التقرير",
"generatingReport": "جارٍ إنشاء التقرير، يرجى الانتظار...",
@ -1302,12 +1301,12 @@
"updatingMonthlyReportStatus": "جاري تحديث حالة التقرير الشهري...",
"monthlyReportStatusUpdatedSuccessfully": "تم تحديث حالة التقرير الشهري بنجاح",
"whoCanViewMyMedicalFile": "من يمكنه عرض ملفي الطبي؟",
"acceptedYourRequestToBeYourFamilyMember": "{status} طلبك لتكون فردًا من عائلتك",
"acceptedYourRequestToBeYourFamilyMember": "{status} طلب الانضمام الى أفراد عائلتك",
"canViewYourFile": "يمكنه عرض ملفك",
"hasARequestPendingToBeYourFamilyMember": "لديه طلب {status} ليكون فردًا من عائلتك",
"wantsToAddYouAsTheirFamilyMember": "يريد إضافتك كفرد من عائلته",
"rejectedYourRequestToBeYourFamilyMember": "{status} طلبك لتكون فردًا من عائلتك",
"rejectedYourFamilyMemberRequest": "{status} طلب فرد عائلتك",
"wantsToAddYouAsTheirFamilyMember": "يرغب في إضافتك كفرد من أفراد العائلة",
"rejectedYourRequestToBeYourFamilyMember": "{status} طلب الانضمام إلى عائلتك",
"rejectedYourFamilyMemberRequest": "{status} طلب أحد أفراد عائلتك",
"notAvailable": "غير متاح",
"selectAProfile": "الرجاء تحديد ملف تعريف",
"switchFamilyFile": "قم بالتبديل من قائمة الملفات الطبية أدناه",
@ -1386,7 +1385,7 @@
"seekMedicalAdviceDescription": "ليست حالة طوارئ ولكن من الأفضل مراقبة الأعراض.",
"emergencyDescription": "تحتاج إلى استشارة الطبيب في أقرب وقت ممكن قبل فوات الأوان.",
"colorScience": "دلالات الألوان",
"noNeedToVisitDoctor": "لا حاجة لزيرة الطبيب",
"noNeedToVisitDoctor": "لا حاجة لزيارة الطبيب",
"commonSymptom": "الأعراض الشائعة",
"bookAppointment": "احجز موعد",
"notApplicable": "لا ينطبق",
@ -1423,7 +1422,7 @@
"approved": "موافق عليه",
"approvalRejectedPleaseVisitReceptionist": "تم رفض الموافقة - يرجى زيارة موظف الاستقبال",
"sentForApproval": "تم إرساله للموافقة",
"ancillaryOrderDetails": "تفاصيل الطلب المساعد",
"ancillaryOrderDetails": "تفاصيل الطلبات المساندة",
"noProceduresAvailableForSelectedOrder": "لا توجد إجراءات متاحة للطلب المحدد.",
"procedures": "الإجراءات",
"totalAmount": "المبلغ الإجمالي",
@ -1492,7 +1491,6 @@
"yourName": "اسمك",
"ageYears": "العمر (11-120) سنة",
"numberOfRemindersInADay": "عدد التذكيرات في اليوم",
"medications": "الأدوية",
"someRemarksAboutPrescription": "ستجدون هنا بعض الملاحظات حول الوصفة الطبية",
"notifyMeBeforeConsumptionTime": "أبلغني قبل وقت الاستهلاك",
@ -1545,19 +1543,19 @@
"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.",
"ibwAtTargetDescription": "وزنك في النطاق المثالي. حافظ على عاداتك الحالية — نظام غذائي متوازن ونشاط بدني منتظم — للاستمرار على هذا المستوى.",
"ibwBelowTargetDescription": "أنتِ أقل من الوزن المثالي بمقدار {kg} كجم. يُنصح بزيادة الوزن تدريجيًا من خلال فائضٍ بسيط في السعرات الحرارية، وتناول أطعمة غنية بالعناصر الغذائية، مع ممارسة تمارين المقاومة.",
"ibwAboveTargetDescription": "أنتِ أعلى من الوزن المثالي بمقدار {kg} كجم. يُنصح باتباع خفضٍ تدريجي ومستدام للوزن من خلال عجزٍ معتدل في السعرات الحرارية، وزيادة مستوى النشاط البدني، واتباع تغذية متوازنة.",
"ibwCloseToRangeDescription": "وزنك قريب من النطاق المثالي. حافظ على نظام غذائي متوازن ونشاط بدني منتظم، مع اتباع إرشادات شخصية من مختص صحي عند الحاجة.",
"ibwUnderweightDescription": "أنت أقل من الوزن المثالي بمقدار {kg} كجم. ركّز على زيادة السعرات الحرارية من خلال أطعمة غنية بالعناصر الغذائية، وأعط الأولوية للبروتين وتمارين المقاومة لبناء كتلة صحية، مع اتباع إرشادات شخصية من مختص صحي.",
"ibwUnderweightGenericDescription": "يبدو أنكِ أقل من الوزن المثالي. يُنصح بزيادة السعرات الحرارية من خلال أطعمة غنية بالعناصر الغذائية وممارسة تمارين المقاومة؛ مع الحصول على استشارة مختص صحي عند الحاجة.",
"ibwOverweightDescription": "أنت أعلى من الوزن المثالي بمقدار {kg} كجم. يُنصح باتباع استراتيجية تدريجية ومستدامة لفقدان الوزن — من خلال عجزٍ معتدل في السعرات الحرارية، وممارسة نشاط بدني منتظم، وتغذية متوازنة. يُفضّل استشارة مختص صحي قبل إجراء تغييرات كبيرة.",
"ibwOverweightGenericDescription": "يبدو أنك أعلى من الوزن المثالي. يُنصح باتباع عجزٍ تدريجي ومستدام في السعرات الحرارية مع ممارسة النشاط البدني واتباع تغذية متوازنة؛ مع الحصول على استشارة مختص صحي عند الحاجة.",
"dietVeryLowCarbsDescription": "نهج منخفض الكربوهيدرات جدًا (الكيتوني): تقليل الكربوهيدرات إلى الحد الأدنى مع زيادة الدهون وبروتين معتدل. قد يساعد على فقدان الوزن بسرعة وتحسين التحكم في سكر الدم لدى بعض الأشخاص، لكنه قد يكون صعب الاستمرار عليه وقد يسبب نقصًا في بعض العناصر الغذائية. يجب مراقبة الترطيب ، والحصول على استشارة مختص صحي عند استخدامه لفترة طويلة.",
"dietLowCarbsDescription": "خطة منخفضة الكربوهيدرات وعالية البروتين: تقليل الكربوهيدرات مع زيادة البروتين لدعم الشعور بالشبع والحفاظ على الكتلة العضلية. مفيدة لإدارة الوزن وضبط سكر الدم عند موازنتها مع الخضروات والدهون الصحية. احرص على الحصول على كمية كافية من الألياف والعناصر الدقيقة (الفيتامينات والمعادن).",
"dietModerateCarbsDescription": "تناول معتدل للكربوهيدرات مع توازن في البروتين والدهون: يوفر طاقة مستقرة للأنشطة اليومية والتمارين مع قدر من المرونة. مناسب لكثير من الأشخاص الذين يسعون لإدارة وزن مستدامة وتحسين الأداء.",
"dietUSDAGuidelinesDescription": "نمط متوازن مستند إلى (USDA): يركز على الفواكه والخضروات والحبوب الكاملة والبروتينات قليلة الدهن، مع الحد من السكريات المضافة والدهون المشبعة. يُعد إطارًا قائمًا على الأدلة لدعم الصحة العامة، وكفاية العناصر الغذائية، والوقاية من الأمراض المزمنة.",
"dietZoneDietDescription": "حمية الزون (~40٪ كربوهيدرات / 30٪ بروتين / 30٪ دهون): تركز على التوازن الهرموني وضبط الحصص الغذائية. قد تُحسّن تركيب الجسم ومستوى الطاقة لدى بعض الأشخاص، لكنها تتطلب تخطيطًا جيدًا؛ ويُفضّل تخصيصها بالتعاون مع مختص تغذية.",
"contextDependent": "يعتمد السياق",
"calculatedValue": "القيمة المحسوبة",
"calculationFormula": "صيغة الحساب",
@ -1595,5 +1593,9 @@
"whoopwatch": "ساعة Whoop",
"whoophealthapplicationshouldbeinstalledinyourphone": "يجب تثبيت تطبيق Whoop Health على هاتفك",
"whoopwatchshouldbeconnected": "يجب توصيل ساعة Whoop",
"updatetheinformation": "سيتيح ذلك جمع أحدث المعلومات من ساعة آبل الخاصة بك"
"updatetheinformation": "سيتيح ذلك جمع أحدث المعلومات من ساعة آبل الخاصة بك",
"continueCash": "متابعة الدفع نقدًا",
"timeFor": "الوقت",
"hmgPolicies": "سياسات مجموعة الحبيب الطبية",
"darkMode": "المظهر الداكن"
}

@ -92,7 +92,7 @@
"reminder": "Reminder",
"location": "Locations",
"online": "Online",
"payment": "الالكتروني",
"payment": "Payment",
"onlinePayment": "Online",
"onlinePaymentSubtitle": "Payment",
"cancelNocaps": "Cancel",
@ -272,9 +272,9 @@
"appointments": "Appointments",
"all2": "All",
"checkinOption": "Check-In",
"readBarcode": "قراءة الكود",
"showMyPark": "عرض الموقف",
"clearMyData": "امسح البيانات",
"readBarcode": "Read Barcode",
"showMyPark": "Show My Park",
"clearMyData": "Clear My Data",
"floor": "Floor:",
"gate": "Gate:",
"building": "Building:",
@ -357,7 +357,7 @@
"userAgreement": "User Agreement",
"updateSuccessfully": "Update Successfully",
"checkVaccineAvailability": "CHECK VACCINE AVAILABILITY",
"myVaccinesAvailability": "MyVaccinesAvailability",
"myVaccinesAvailability": "My Vaccines Availability",
"paymentService": "Payment Service",
"paymentOnline": "Service",
"onlineCheckIn": "Online Check-In",
@ -393,7 +393,7 @@
"theVerificationCodeExpiresIn": "The Verification Code Expires in",
"pleaseEnterTheVerificationCode": "Please enter the verification code send to",
"eyeMeasurements": "Eye Measurements",
"measurements": "قياسات",
"measurements": "Measurements",
"classes": "Glasses",
"contactLens": "Contact Lens",
"rightEye": "Right Eye",
@ -566,8 +566,8 @@
"transferred": "Transferred",
"riyal": "RIYAL",
"membersince": "MEMBER SINCE",
"identification": "رقم الهوية",
"lakumMobile": "رقم الجوال",
"identification": "Identification Number",
"lakumMobile": "Mobile Number",
"waitinggained": "Waiting gained",
"expired": "Expired",
"willBeExpired": "Will Be Expired",
@ -616,10 +616,10 @@
"bloodType": "Blood Type",
"maritalStatus": "Marital status",
"general": "General",
"profile": "ملفي",
"notifications": "إشعارات",
"profile": "My Profile",
"notifications": "Notifications",
"notificationDetails": "Notification Details",
"notificationDetailsa": "تفاصيل الاشعار",
"notificationDetailsa": "Notification Details",
"infoMyDoctorPoints": "",
"infoMyDoctor": "This service allows you to see all the doctors you have visited in Al Habib Medical Group, and through this service:",
"infoPrescriptions": "This service allows you to view all the medical prescriptions issued by Al Habib Medical Group, and through this service, you can:",
@ -1586,6 +1586,9 @@
"whoopwatch": "Whoop Watch",
"whoophealthapplicationshouldbeinstalledinyourphone": "Whoop Health application should be installed in your phone",
"whoopwatchshouldbeconnected": "Whoop Watch should be connected",
"updatetheinformation": "This will allow to gather the most up to date information from your apple watch"
"updatetheinformation": "This will allow to gather the most up to date information from your apple watch",
"continueCash": "Continue as cash",
"timeFor": "Time For",
"hmgPolicies": "HMG Policies",
"darkMode": "Dark Mode"
}

@ -195,11 +195,13 @@ class ApiClientImp implements ApiClient {
}
// body['TokenID'] = "@dm!n";
// body['PatientID'] = 4773715;
// body['PatientID'] = 809289;
// body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0;
// body['SessionID'] = "45786230487560q";
//VIP Patient: 1181868
// body['IdentificationNo'] = "2235558844";
// body['MobileNo'] = "966533147722";
// body['PatientID'] = 809289;
@ -299,14 +301,16 @@ class ApiClientImp implements ApiClient {
} else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
onSuccess(parsed, statusCode,
messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else if (parsed['IsAuthenticated'] == false) {
onFailure(
"User is not Authenticated",
statusCode,
failureType:
UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url),
);
} else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
}
// else if (parsed['IsAuthenticated'] == false) {
// onFailure(
// "User is not Authenticated",
// statusCode,
// failureType:
// UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url),
// );
// }
else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode,
messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);

@ -4,7 +4,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class ApiConsts {
static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
@ -57,7 +57,7 @@ class ApiConsts {
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";
CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId=";
break;
case AppEnvironmentTypeEnum.uat:
baseUrl = "https://uat.hmgwebservices.com/";
@ -69,7 +69,7 @@ class ApiConsts {
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";
CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId=";
break;
case AppEnvironmentTypeEnum.preProd:
baseUrl = "https://webservices.hmg.com/";
@ -81,7 +81,7 @@ class ApiConsts {
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";
CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId=";
break;
case AppEnvironmentTypeEnum.qa:
baseUrl = "https://uat.hmgwebservices.com/";
@ -93,7 +93,7 @@ class ApiConsts {
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";
CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId=";
break;
case AppEnvironmentTypeEnum.staging:
baseUrl = "https://uat.hmgwebservices.com/";
@ -105,7 +105,7 @@ class ApiConsts {
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";
CHAT_URL = "https://chat.hmg.com/geneysChat/Index.aspx?RequestedId=";
break;
}
}
@ -229,7 +229,7 @@ class ApiConsts {
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 = 20.2;
// static final double appVersionID = 50.7;
static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20";
@ -517,8 +517,6 @@ var IS_ALLOW_ASK_DOCTOR = 'Services/Doctors.svc/REST/GetPatientDoctorAppointment
var GET_CALL_REQUEST_TYPE = 'Services/Doctors.svc/REST/GetCallRequestType_LOV';
var ADD_VIDA_REQUEST = 'Services/ER_VirtualCall.svc/REST/PatientER_VidaRequestInseart';
var SEND_CALL_REQUEST = 'Services/Doctors.svc/REST/InsertCallInfo';
var GET_LIVECARE_CLINICS = 'Services/ER_VirtualCall.svc/REST/PatientER_GetClinics';
var GET_LIVECARE_SCHEDULE_CLINICS = 'Services/Doctors.svc/REST/PatientER_GetClinicsHaveSchedule';
@ -916,6 +914,8 @@ var GET_PRESCRIPTION_INSTRUCTIONS_PDF = 'Services/ChatBot_Service.svc/REST/Chatb
const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard';
const SEND_PATIENT_IMMEDIATE_UPDATE_INSURANCE_REQUEST = 'Services/OUTPs.svc/REST/PatientCompanyUpdate';
class ApiKeyConstants {
static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng';
}

@ -346,6 +346,7 @@ class AppAssets {
static const String doctorResponseIcon = '$svgBasePath/doctor_response_icon.svg';
static const String changeLanguageHomePageIcon = '$svgBasePath/change_language_home_page.svg';
static const String aiOverView = '$svgBasePath/ai_overview.svg';
static const String darkModeIcon = '$svgBasePath/dark_mode_icon.svg';
// PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png';

@ -224,7 +224,7 @@ class AppDependencies {
authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()),
);
getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel());
getIt.registerLazySingleton<ProfileSettingsViewModel>(() => ProfileSettingsViewModel(cacheService: getIt<CacheService>()));
getIt.registerLazySingleton<DateRangeSelectorRangeViewModel>(() => DateRangeSelectorRangeViewModel());

@ -1,316 +0,0 @@
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
import 'package:device_calendar/device_calendar.dart';
import 'package:flutter/widgets.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/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/permission_service.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:jiffy/jiffy.dart';
import 'package:manage_calendar_events/manage_calendar_events.dart' as ios;
import 'package:permission_handler/permission_handler.dart';
import 'package:timezone/data/latest.dart' as tzl;
final DeviceCalendarPlugin deviceCalendarPlugin = DeviceCalendarPlugin();
final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin();
class CalendarUtils {
static Completer<CalendarUtils>? _completer;
dynamic get writableCalendars => calendars.firstWhere((c) => !c.isReadOnly!);
dynamic calendars;
CalendarUtils._(this.calendars);
// static Future<CalendarUtils> getInstance() async {
// if (_completer == null) {
// _completer = Completer<CalendarUtils>();
// print(_completer!.isCompleted);
// try {
// final dynamic calendarsResult;
// if (Platform.isIOS) {
// calendarsResult = await _myPlugin.getCalendars();
// if (!_completer!.isCompleted) {
// _completer?.complete(CalendarUtils._(await calendarsResult!));
// }
// } else {
// calendarsResult = await deviceCalendarPlugin.retrieveCalendars();
// if (!_completer!.isCompleted) {
// _completer?.complete(CalendarUtils._(await calendarsResult.data!));
// }
// }
// } on Exception catch (e) {
// if (!_completer!.isCompleted) {
// _completer!.completeError(e);
// }
// }
// }
// return _completer!.future;
// }
static Future<CalendarUtils> getInstance() async {
tzl.initializeTimeZones();
if (_completer != null) {
return _completer!.future;
}
_completer = Completer<CalendarUtils>();
try {
final dynamic calendarsResult;
if (Platform.isIOS) {
calendarsResult = await _myPlugin.getCalendars();
_completer!.complete(CalendarUtils._(calendarsResult));
} else {
calendarsResult = await deviceCalendarPlugin.retrieveCalendars();
_completer!.complete(CalendarUtils._(calendarsResult.data));
}
} catch (e) {
_completer!.completeError(e);
}
return _completer!.future;
}
Future createOrUpdateEvents({List<DateTime>? scheduleList, String? title, String? description, List<DateTime>? scheduleDateTime, List<DayOfWeek>? daysOfWeek}) async {
tzl.initializeTimeZones();
List<Event> events = [];
Location _currentLocation;
if (DateTime.now().timeZoneName == "+04")
_currentLocation = getLocation('Asia/Dubai');
else
_currentLocation = getLocation('Asia/Riyadh');
scheduleDateTime!.forEach((element) {
RecurrenceRule recurrenceRule = RecurrenceRule(
// RecurrenceFrequency.Daily,
// daysOfWeek: daysOfWeek,
// endDate: element,
until: element, frequency: Frequency.daily,
);
//added byAamir Tz Time
Event event = Event(writableCalendars!.id,
recurrenceRule: recurrenceRule,
start: TZDateTime.from(element, _currentLocation),
end: TZDateTime.from(element.add(Duration(minutes: 30)), _currentLocation),
title: title,
description: description);
events.add(event);
});
events.forEach((element) {
deviceCalendarPlugin.createOrUpdateEvent(element);
});
}
Future createOrUpdateEvent({required String title, required String description, required String location, DateTime? scheduleDateTime, String? eventId}) async {
RecurrenceRule recurrenceRule = RecurrenceRule(
// RecurrenceFrequency.Daily,
// daysOfWeek: daysOfWeek,
// endDate: scheduleDateTime,
until: scheduleDateTime, frequency: Frequency.daily,
);
Location _currentLocation;
// if (DateTime.now().timeZoneName == "+04")
// _currentLocation = getLocation('Asia/Dubai');
// else
_currentLocation = getLocation('Asia/Riyadh');
TZDateTime scheduleDateTimeUTZ = TZDateTime.from(scheduleDateTime!, _currentLocation);
print("writableCalendars-name: " + writableCalendars.name);
print("writableCalendars-Id: " + writableCalendars.id);
print("writableCalendarsToString: " + writableCalendars.toString());
print("writableCalendarsToString: " + writableCalendars!.id!);
Event event = Event(
writableCalendars!.id,
start: scheduleDateTimeUTZ,
end: scheduleDateTimeUTZ.add(Duration(minutes: 30)),
title: title,
description: description,
);
ios.CalendarEvent iosCalEvent =
ios.CalendarEvent(location: location, startDate: scheduleDateTimeUTZ, endDate: scheduleDateTimeUTZ.add(Duration(minutes: 30)), title: title, description: description, isAllDay: false);
if (Platform.isAndroid) {
Result<bool> result = await deviceCalendarPlugin.hasPermissions();
print(result);
await deviceCalendarPlugin.createOrUpdateEvent(event).catchError((e) {
print("catchError " + e.toString());
}).whenComplete(() {
print("whenComplete Calender ID " + eventId!);
});
} else {
await _myPlugin.createEvent(calendarId: writableCalendars.id!, event: iosCalEvent).catchError((e) {
print("catchError " + e.toString());
}).whenComplete(() {
print("whenComplete Calender ID iOS " + eventId!);
});
}
}
deleteEvent(String _calendarId, String _eventId) async {
if (Platform.isIOS) {
await _myPlugin.deleteEvent(calendarId: _calendarId, eventId: _eventId);
} else {
await deviceCalendarPlugin.deleteEvent(_calendarId, _eventId);
}
}
Future retrieveEvents(
String calendarId,
RetrieveEventsParams retrieveEventsParams,
) async {
if (Platform.isIOS) {
return await _myPlugin.getEvents(calendarId: calendarId);
} else {
return await deviceCalendarPlugin.retrieveEvents(calendarId, retrieveEventsParams);
}
}
Future createCalendar(
String calendarName, {
Color? calendarColor,
String? localAccountName,
}) async {
return await deviceCalendarPlugin.createCalendar(calendarName, calendarColor: calendarColor, localAccountName: localAccountName);
}
}
Future<Map<Permission, PermissionStatus>> requestPermissions() async {
var permissionResults = [Permission.calendarFullAccess].request();
return permissionResults;
}
showReminderBottomSheet(BuildContext context, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
{required Function() onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool isMultiAllowed = false}) async {
if (Platform.isAndroid) {
if (await PermissionService.isCalendarPermissionEnabled()) {
_showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
} else {
// Utils.showPermissionConsentDialog(context, TranslationBase.of(context).calendarPermission, () async {
// if (await Permission.calendarFullAccess.request().isGranted) {
// _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
// onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
// }
// });
}
} else {
if (await Permission.calendarWriteOnly.request().isGranted) {
if (await Permission.calendarFullAccess.request().isGranted) {
_showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted,
onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed);
}
}
}
}
Future<void> _showReminderBottomSheet(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
{required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async {
showCommonBottomSheetWithoutHeight(providedContext, title: "Set the timer of reminder", child: PrescriptionReminderView(
setReminder: (int value) async {
if (!isMultiAllowed!) {
if (onMultiDateSuccess == null) {
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
await calendarUtils.createOrUpdateEvent(
title: title ?? "You have appointment with Dr. $doctorName",
description: description ?? "At $appoDateFormatted $appoTimeFormatted",
scheduleDateTime: dateTime,
eventId: eventId,
location: '');
onSuccess();
}
} else {
onMultiDateSuccess!(value);
}
},
), callBackFunc: () {}, isFullScreen: false);
}
setCalender(BuildContext context,
{required String eventId, required int selectedMinutes, int? frequencyNumber, required int days, required String orderDate, required String itemDescriptionN, required String route}) async {
DateTime actualDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0);
frequencyNumber ??= 2; //Some time frequency number is null so by default will be 2
int remainingDays = days - (Jiffy.parseFromDateTime(DateTime.now()).diff(Jiffy.parseFromDateTime(DateUtil.convertStringToDate(orderDate)), unit: Unit.day) as int);
if (remainingDays.isNegative) {
getIt.get<DialogService>().showErrorBottomSheet(message: "Prescription date has been already passed you can not add a reminder for this prescription.");
return;
}
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
try {
for (int i = 0; i < remainingDays; i++) {
//event for number of days.
for (int j = 0; j < frequencyNumber; j++) {
// event for number of times per day.
if (j != 0) {
actualDate.add(new Duration(hours: 8)); // 8 hours addition for daily dose.
}
//Time subtraction from actual reminder time. like before 30, or 1 hour.
actualDate = Jiffy.parseFromDateTime(actualDate).subtract(minutes: selectedMinutes).dateTime;
calendarUtils.createOrUpdateEvent(
title: "$itemDescriptionN} Prescription Reminder",
description: "$itemDescriptionN $frequencyNumber $route ",
scheduleDateTime: actualDate,
eventId: eventId + (i.toString() + j.toString()),
location: '', //event id with varitions
);
print("Creating event #$j for day $i$actualDate");
actualDate = DateTime(actualDate.year, actualDate.month, actualDate.day, 8, 0);
}
actualDate = Jiffy.parseFromDateTime(actualDate).add(days: 1).dateTime;
}
} catch (ex) {
getIt.get<DialogService>().showErrorBottomSheet(message: "catch:$ex");
}
}
Future<void> checkAndRemove(hasReminder, {bool delete = false, String itemDescriptionN = ""}) async {
final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin();
CalendarUtils calendarUtils = await CalendarUtils.getInstance();
DateTime startEventsDate = Jiffy.parseFromDateTime(DateTime.now()).subtract(days: 30).dateTime;
DateTime endEventsDate = Jiffy.parseFromDateTime(DateTime.now()).add(days: 120).dateTime;
RetrieveEventsParams params = RetrieveEventsParams(startDate: startEventsDate, endDate: endEventsDate);
if (calendarUtils.calendars != null) {
if (Platform.isAndroid) {
await processEvents(calendarUtils.calendars, calendarUtils, params, delete, itemDescriptionN, hasReminder);
} else {
List<ios.Calendar>? iosCalendars = await _myPlugin.getCalendars();
if (iosCalendars != null) {
await processEvents(iosCalendars.map((cal) => Calendar(id: cal.id, name: cal.name, accountName: cal.accountName)).toList(), calendarUtils, params, delete, itemDescriptionN, hasReminder);
}
}
}
}
Future<void> processEvents(List<Calendar> calendars, calendarUtils, params, delete, String itemDescriptionN, hasReminder) async {
for (var calendar in calendars) {
Result<UnmodifiableListView<Event>> events = await calendarUtils.retrieveEvents(calendar.id!, params);
for (var event in events.data!) {
if (event.title!.contains(itemDescriptionN)) {
if (delete) {
await calendarUtils.deleteEvent(calendar, event);
// AppToast.showSuccessToast(message: TranslationBase.of(context).reminderCancelSuccess);
hasReminder = false;
} else {
hasReminder = false;
// setState(() {
// hasReminder = true;
// });
}
}
}
}
}

@ -51,7 +51,7 @@ class CalenderUtilsNew {
startDate: scheduleDateTime!,
endDate: scheduleDateTime!.add(Duration(minutes: 30)),
// reminderMinutes: reminderMinutes, // TODO : NEED TO CONFIRM THIS FROM TAHA
reminderMinutes: reminderMinutes, // TODO : NEED TO CONFIRM THIS FROM TAHA
);
return eventResult.isNotEmpty;
// }

@ -504,7 +504,7 @@ class DateUtil {
}
static convertISODateToJsonDate(String isoDate) {
return "/Date(" + DateFormat('mm-dd-yyy').parse(isoDate).millisecondsSinceEpoch.toString() + ")/";
return "/Date(" + DateFormat('mm-dd-yyy', "en-US").parse(isoDate).millisecondsSinceEpoch.toString() + ")/";
}
static String getDay(DayOfWeek dayOfWeek) {

@ -398,7 +398,7 @@ class PushNotificationHandler {
int sdkInt = androidInfo.version.sdkInt ?? 0;
if (sdkInt >= 33) {
// await FlutterCallkitIncoming.requestFullIntentPermission();
await FlutterCallkitIncoming.requestFullIntentPermission();
}
}
}

@ -664,10 +664,12 @@ class Utils {
double width = 24,
double height = 24,
BoxFit fit = BoxFit.cover,
bool applyThemeColor = true,
}) {
final Color? resolvedColor = iconColor ?? (applyThemeColor && AppColors.isDarkMode ? AppColors.textColor : null);
return SvgPicture.asset(
icon,
colorFilter: iconColor != null ? ColorFilter.mode(isDisabled ? iconColor.withOpacity(0.5) : iconColor, BlendMode.srcIn) : null,
colorFilter: resolvedColor != null ? ColorFilter.mode(isDisabled ? resolvedColor.withOpacity(0.5) : resolvedColor, BlendMode.srcIn) : null,
width: width,
height: height,
fit: fit,
@ -801,11 +803,13 @@ class Utils {
double? fontSize,
double? letterSpacing,
FontWeight? fontWeight,
Color iconColor = AppColors.textColor,
Color textColor = AppColors.blackColor,
Color? iconColor,
Color? textColor,
bool isSaudiCurrency = true,
bool isExpanded = true,
}) {
final resolvedIconColor = iconColor ?? AppColors.textColor;
final resolvedTextColor = textColor ?? AppColors.blackColor;
return RichText(
maxLines: 1,
text: TextSpan(
@ -813,13 +817,13 @@ class Utils {
WidgetSpan(
alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,
child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: iconColor),
child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: resolvedIconColor),
),
TextSpan(
// text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount),
text: " ${habibWalletAmount.toStringAsFixed(2)}",
style: TextStyle(
color: textColor,
color: resolvedTextColor,
fontSize: fontSize ?? 32.f,
letterSpacing: letterSpacing ?? -4,
fontFamily: "Poppins",
@ -860,7 +864,7 @@ class Utils {
static String getAppointmentTransID(int projectID, int clinicID, int appoNo, {bool isAddMilliseconds = true}) {
String currentMillis = DateTime.now().millisecondsSinceEpoch.toString();
return '$projectID-$clinicID-$appoNo${isAddMilliseconds ? '-${currentMillis.substring(currentMillis.length - 5, currentMillis.length)}' : ""}';
return '$projectID-$clinicID-$appoNo${isAddMilliseconds ? '-${currentMillis.substring(currentMillis.length - 5, currentMillis.length)}${currentMillis.substring(currentMillis.length - 5, currentMillis.length)}' : ""}';
}
static String getAdvancePaymentTransID(int projectID, int fileNumber) {

@ -235,7 +235,7 @@ extension EmailValidator on String {
TextOverflow? textOverflow,
String? fontFamily,
double? letterSpacing = -0.4,
Color decorationColor = AppColors.errorColor}) =>
Color? decorationColor}) =>
Text(
this,
maxLines: maxlines,
@ -250,7 +250,7 @@ extension EmailValidator on String {
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null,
fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get<AppState>().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
decorationColor: decorationColor),
decorationColor: decorationColor ?? AppColors.errorColor),
);
Widget toText17({bool isEnglishOnly = false, Color? color, bool isBold = false, bool isCenter = false}) => Text(

@ -28,10 +28,10 @@ extension WidgetExtensions on Widget {
Widget toShimmer({bool isShow = true, bool isTransparent = false}) => isShow
? Shimmer.fromColors(
baseColor: Color(0xffb9bebe),
highlightColor: Colors.white,
baseColor: AppColors.shimmerBaseColor,
highlightColor: AppColors.shimmerHighlightColor,
child: Container(
color: isTransparent ? Colors.transparent : Colors.white.withOpacity(0.3),
color: isTransparent ? Colors.transparent : AppColors.whiteColor.withOpacity(0.3),
child: this,
),
)
@ -41,14 +41,14 @@ extension WidgetExtensions on Widget {
Widget toShimmer2({bool isShow = true, double radius = 20, double? width, double? height}) => isShow
? Shimmer.fromColors(
baseColor: const Color(0xffe8eff0),
highlightColor: Colors.white,
baseColor: AppColors.shimmerBaseColor,
highlightColor: AppColors.shimmerHighlightColor,
child: ClipRRect(
borderRadius: BorderRadius.circular(radius),
child: Container(
width: width,
height: height,
color: Colors.white,
color: AppColors.whiteColor,
child: this,
),
),
@ -69,7 +69,7 @@ extension WidgetExtensions on Widget {
return Container(
padding: disablePadding ? EdgeInsets.zero : const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14),
decoration: BoxDecoration(
color: Colors.white,
color: AppColors.whiteColor,
borderRadius: BorderRadius.circular(radius),
boxShadow: [
BoxShadow(
@ -161,15 +161,17 @@ extension SmoothContainerExtension on ShapeBorder {
smoothness: 1,
side: side ?? BorderSide.none,
),
shadows: hasShadow
? [
BoxShadow(
color: const Color(0xff000000).withOpacity(.05),
blurRadius: 32,
offset: const Offset(0, 0),
)
]
: [],
shadows:
// hasShadow
// ? [
// BoxShadow(
// color: const Color(0xff000000).withOpacity(.05),
// blurRadius: 32,
// offset: const Offset(0, 0),
// )
// ]
// :
[],
);
}
}

@ -67,7 +67,7 @@ class AskDoctorViewModel extends ChangeNotifier {
(failure) async {
isDoctorResponsesLoading = false;
notifyListeners();
await errorHandlerService.handleError(failure: failure);
// await errorHandlerService.handleError(failure: failure);
if (onError != null) {
onError(failure.toString());
}

@ -44,6 +44,7 @@ import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
import '../insurance/insurance_view_model.dart';
import 'models/request_models/get_user_mobile_device_data.dart';
import 'models/request_models/insert_patient_mobile_deviceinfo.dart';
import 'models/request_models/patient_insert_device_imei_request.dart';
@ -629,11 +630,12 @@ class AuthenticationViewModel extends ChangeNotifier {
// medicalVm.getAllPendingRecordsByResponseId();
}
await clearDefaultInputValues();
myAppointmentsVM.setIsAppointmentDataToBeLoaded(true);
getIt.get<InsuranceViewModel>().setIsInsuranceDataToBeLoaded(true);
if (isUserAgreedBefore) {
LoaderBottomSheet.hideLoader();
navigateToHomeScreen();
} else {
myAppointmentsVM.setIsAppointmentDataToBeLoaded(true);
LoaderBottomSheet.hideLoader();
navigateToHomeScreen();
//Agreement page not designed yet so we are navigating to home screen directly
@ -833,8 +835,8 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future<void> onRegistrationComplete() async {
// LoaderBottomSheet.showLoader();
LoadingUtils.showFullScreenLoader(loadingText: "Setting up your medical file.\nMay take a moment.");
LoaderBottomSheet.showLoader();
// LoadingUtils.showFullScreenLoader(loadingText: "Setting up your medical file.\nMay take a moment.");
var request = RequestUtils.getUserSignupCompletionRequest(fullName: nameController.text, emailAddress: emailController.text, gender: genderType, maritalStatus: maritalStatus);
final resultEither = await _authenticationRepo.registerUser(registrationPayloadDataModelRequest: request);
@ -1031,7 +1033,8 @@ class AuthenticationViewModel extends ChangeNotifier {
label: LocaleKeys.notice.tr(),
onOkPressed: () {
_dialogService.showPhoneNumberPickerSheet(
label: "Where would you like to receive OTP?",
// label: "Where would you like to receive OTP?",
label: LocaleKeys.receiveOtpToast.tr(),
message: "Please select from the below options to receive OTP.",
onSMSPress: () {
checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms);

@ -75,7 +75,7 @@ class HospitalBottomSheetBodySelection extends StatelessWidget {
children: [
Utils.buildSvgWithAssets(icon: AppAssets.hmg).paddingOnly(right: 10),
Expanded(
child: Text(hospital.projectName ?? "", style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16, color: AppColors.blackColor)),
child: Text(hospital.projectName ?? "", style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16.f, color: AppColors.blackColor)),
)
],
);

@ -464,7 +464,11 @@ class BookAppointmentsViewModel extends ChangeNotifier {
final result = await bookAppointmentsRepo.getLiveCareScheduleClinics(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
isClinicsListLoading = false;
notifyListeners();
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
@ -688,6 +692,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
result.fold(
(failure) async {
print(failure);
if (onError != null) {
onError(failure.message);
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {

@ -153,7 +153,7 @@ class ContactUsViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
liveChatProjectsList = apiResponse.data!;
liveChatProjectsList.sort((a, b) => b.distanceInKilometers.compareTo(a.distanceInKilometers));
liveChatProjectsList.sort((a, b) => a.distanceInKilometers.compareTo(b.distanceInKilometers));
isLiveChatProjectsListLoading = false;
notifyListeners();
if (onSuccess != null) {

@ -183,7 +183,7 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@override
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList() async {
Map<String, dynamic> request = {};
Map<String, dynamic> request = {'IsOnlineCheckIn': false, 'IsAdvancePayment': false, 'IsForER': true};
try {
GenericApiModel<List<HospitalsModel>>? apiResponse;

@ -40,7 +40,7 @@ class VitalSignUiModel {
}
if (s.contains('high')) {
return const VitalSignUiModel(
return VitalSignUiModel(
iconBg: AppColors.chipSecondaryLightRedColor,
iconFg: AppColors.primaryRedColor,
chipBg: AppColors.chipSecondaryLightRedColor,

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

@ -174,13 +174,21 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
},
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(),
),
);
//Call the API to attempt updating patient insurance
LoaderBottomSheet.showLoader();
myAppointmentsViewModel.sendPatientUpdateRequest(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
getLiveCareImmediateAppointmentFees();
}, onError: (err) {
LoaderBottomSheet.hideLoader();
Navigator.push(
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
CustomPageRoute(
page: InsuranceHomePage(),
),
);
});
}),
), callBackFunc: () {
// Navigator.pop(GetIt.instance<NavigationService>().navigatorKey.currentContext!);

@ -52,7 +52,7 @@ class InsuranceApprovalResponseModel {
String? eApprovalRemarks;
bool? isEmailSentOnDelayApproval;
int? eAuthorizationID;
InsuranceApprovalDetails? apporvalDetails;
List<InsuranceApprovalDetails>? apporvalDetails = [];
String? approvalStatusDescption;
String? clinicName;
String? clinicNameN;
@ -217,7 +217,9 @@ class InsuranceApprovalResponseModel {
isEmailSentOnDelayApproval = json['IsEmailSentOnDelayApproval'];
eAuthorizationID = json['EAuthorizationID'];
if (json['ApporvalDetails'] != null && json['ApporvalDetails'].length != 0) {
apporvalDetails = InsuranceApprovalDetails.fromJson(json['ApporvalDetails'][0]);
json['ApporvalDetails'].forEach((v) {
apporvalDetails!.add(InsuranceApprovalDetails.fromJson(v));
});
}
approvalStatusDescption = json['ApprovalStatusDescption'];
clinicName = json['ClinicName'];
@ -302,9 +304,9 @@ class InsuranceApprovalResponseModel {
data['EApprovalRemarks'] = this.eApprovalRemarks;
data['IsEmailSentOnDelayApproval'] = this.isEmailSentOnDelayApproval;
data['EAuthorizationID'] = this.eAuthorizationID;
if (this.apporvalDetails != null) {
data['ApporvalDetails'] = this.apporvalDetails!.toJson;
}
// if (this.apporvalDetails != null) {
// data['ApporvalDetails'] = this.apporvalDetails!.toJson;
// }
data['ApprovalStatusDescption'] = this.approvalStatusDescption;
data['ClinicName'] = this.clinicName;
data['ClinicNameN'] = this.clinicNameN;

@ -232,7 +232,7 @@ class LabRepoImp implements LabRepo {
"DoctorID": labOrder.doctorID!,
"OrderNo": labOrder.orderNo!,
"InvoiceType": labOrder.invoiceType!,
"SetupID": labOrder.setupID!,
"SetupID": labOrder.setupID ?? "",
"IsDownload": true,
'ClinicName': labOrder.clinicDescription,
'DateofBirth': Utils.appState.getAuthenticatedUser()!.dateofBirth,
@ -249,7 +249,8 @@ class LabRepoImp implements LabRepo {
GenericApiModel<String>? apiResponse;
Failure? failure;
await apiClient.post(
Utils.isVidaPlusProject(int.parse(labOrder.projectID!)) ? SEND_LAB_RESULT_EMAIL : SEND_LAB_RESULT_EMAIL_NEW,
// Utils.isVidaPlusProject(int.parse(labOrder.projectID!)) ? SEND_LAB_RESULT_EMAIL : SEND_LAB_RESULT_EMAIL_NEW,
SEND_LAB_RESULT_EMAIL_NEW,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;

@ -205,14 +205,36 @@ class LabViewModel extends ChangeNotifier {
}
filterLabReports(String query) {
final clinicMap = <String, List<PatientLabOrdersResponseModel>>{};
final hospitalMap = <String, List<PatientLabOrdersResponseModel>>{};
if (query.isEmpty) {
filteredLabOrders = List.from(patientLabOrders); // reset
// filteredLabOrders = List.from(patientLabOrders); // reset
for (var order in patientLabOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
}
patientLabOrdersByClinic = clinicMap.values.toList();
patientLabOrdersByHospital = hospitalMap.values.toList();
patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital;
} else {
filteredLabOrders = patientLabOrders.where((order) {
final descriptions = order.testDetails?.map((d) => d.description?.toLowerCase()).toList() ?? [];
return descriptions.any((desc) => desc != null && desc.contains(query.toLowerCase()));
}).toList();
patientLabOrders = filteredLabOrders;
// patientLabOrders = filteredLabOrders;
for (var order in filteredLabOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
}
patientLabOrdersByClinic = clinicMap.values.toList();
patientLabOrdersByHospital = hospitalMap.values.toList();
patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital;
}
notifyListeners();
}
@ -505,7 +527,10 @@ class LabViewModel extends ChangeNotifier {
rangeEnd = 100.0;
break;
default:
throw ArgumentError('Invalid flag: $flag');
rangeStart = 40.0;
rangeEnd = 59.0;
break;
// throw ArgumentError('Invalid flag: $flag');
}
// Clamp input value to 0-100 and map it to the range bounds

@ -27,6 +27,7 @@ class LabResult {
num? resultTypeID;
String? packageShortDescription;
int? testId;
String? testShortDescription;
LabResult(
{this.description,
@ -54,6 +55,7 @@ class LabResult {
this.criticalLow,
this.referenceLow,
this.testId,
this.testShortDescription,
});
LabResult.fromJson(Map<String, dynamic> json) {
@ -85,6 +87,7 @@ class LabResult {
packageShortDescription = json['PackageShortDescription'];
resultTypeID = json['ResultTypeID'];
testId = json['TestID'];
testShortDescription = json['TestShortDescription'];
}
Map<String, dynamic> toJson() {
@ -114,6 +117,7 @@ class LabResult {
data['CriticalLow'] = this.criticalLow;
data['ReferenceLow'] = this.referenceLow;
data['TestID'] = this.testId;
data['TestShortDescription'] = this.testShortDescription;
return data;
}

@ -41,7 +41,7 @@ class MedicalFileViewModel extends ChangeNotifier {
List<SickLeaveList> patientSickLeavesViewList = [];
bool isSickLeavesSortByClinic = true;
bool isSickLeavesDataNeedsReloading = true;
// bool isSickLeavesDataNeedsReloading = true;
List<GetAllergiesResponseModel> patientAllergiesList = [];
@ -164,7 +164,7 @@ class MedicalFileViewModel extends ChangeNotifier {
}
setIsPatientSickLeaveListLoading(bool val) {
if (val && isSickLeavesDataNeedsReloading) {
// if (val && isSickLeavesDataNeedsReloading) {
patientSickLeaveList.clear();
patientSickLeavesByClinic.clear();
patientSickLeavesByHospital.clear();
@ -172,7 +172,7 @@ class MedicalFileViewModel extends ChangeNotifier {
patientSickLeavePDFBase64 = "";
isSickLeavesSortByClinic = true;
isPatientSickLeaveListLoading = val;
}
// }
notifyListeners();
}
@ -268,11 +268,13 @@ class MedicalFileViewModel extends ChangeNotifier {
}
Future<void> getPatientSickLeaveList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
if (!isSickLeavesDataNeedsReloading) {
return;
}
// if (!isSickLeavesDataNeedsReloading) {
// return;
// }
patientSickLeaveList.clear();
notifyListeners();
final result = await medicalFileRepo.getPatientSickLeavesList();
result.fold(
@ -314,7 +316,7 @@ class MedicalFileViewModel extends ChangeNotifier {
}
}
patientSickLeavesViewList = patientSickLeavesByClinic;
isSickLeavesDataNeedsReloading = false;
// isSickLeavesDataNeedsReloading = false;
notifyListeners();
if (onSuccess != null) {
@ -353,6 +355,11 @@ class MedicalFileViewModel extends ChangeNotifier {
Future<void> getPatientMedicalReportList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
patientMedicalReportList.clear();
patientMedicalReportRequestedList.clear();
patientMedicalReportReadyList.clear();
patientMedicalReportCancelledList.clear();
notifyListeners();
final result = await medicalFileRepo.getPatientMedicalReportsList();
result.fold(

@ -122,7 +122,7 @@ class PatientSickLeavesResponseModel {
patientName = json['PatientName'];
projectName = json['ProjectName'];
qR = json['QR'];
speciality = json['Speciality'].cast<String>();
// speciality = json['Speciality'].cast<String>();
startDate = json['StartDate'];
status = json['Status'];
strRequestDate = json['StrRequestDate'];

@ -20,7 +20,8 @@ import 'models/req_model/appointment_rate_req_model.dart';
import 'models/resp_models/appointment_details_resp_model.dart';
abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments({required bool isActiveAppointment, required bool isArrivedAppointments, bool isForEyeMeasurement = false});
Future<Either<Failure, GenericApiModel<List<PatientAppointmentHistoryResponseModel>>>> getPatientAppointments(
{required bool isActiveAppointment, required bool isArrivedAppointments, bool isForEyeMeasurement = false});
Future<Either<Failure, GenericApiModel<PatientAppointmentShareResponseModel>>> getPatientShareAppointment(
{required int projectID, required int clinicID, required String appointmentNo, required bool isLiveCareAppointment});
@ -67,14 +68,16 @@ abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<AppointmentDetails>>> getAppointmentDetails(int appointmentID, int projectID);
Future<Either<Failure, GenericApiModel<void>>> sendAppointmentRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note);
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<dynamic>>> convertPatientToCash({required int projectID});
Future<Either<Failure, GenericApiModel<dynamic>>> sendPatientUpdateRequest();
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@ -194,9 +197,7 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
"AppointmentNo": appointmentNo,
"PaymentMethodName": paymentMethodName,
"PaymentAmount": payedAmount == 0 ? "0" : payedAmount.toString(),
"PaymentDate": payedAmount == 0 ? "" : "/Date(${DateTime
.now()
.millisecondsSinceEpoch})/",
"PaymentDate": payedAmount == 0 ? "" : "/Date(${DateTime.now().millisecondsSinceEpoch})/",
"PaymentReferenceNumber": payedAmount == 0 ? "" : paymentReference,
"ProjectID": projectID,
"PatientID": patientID,
@ -865,10 +866,8 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
}
}
@override
Future<Either<Failure, GenericApiModel<void>>> sendAppointmentRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note) async {
Future<Either<Failure, GenericApiModel<void>>> sendAppointmentRate(int rate, int appointmentNo, int projectID, int doctorID, int clinicID, String note) async {
AppointmentRate appointmentRate = AppointmentRate();
appointmentRate.rate = rate;
appointmentRate.appointmentNo = appointmentNo;
@ -879,7 +878,6 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
appointmentRate.createdBy = 2;
appointmentRate.editedBy = 2;
try {
GenericApiModel<bool>? apiResponse;
Failure? failure;
@ -908,7 +906,8 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
}
@override
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) async {
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) async {
Map<String, dynamic> request;
request = {
@ -991,4 +990,35 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
}
@override
Future<Either<Failure, GenericApiModel>> sendPatientUpdateRequest() async {
Map<String, dynamic> request = {};
try {
GenericApiModel<bool>? apiResponse;
Failure? failure;
await apiClient.post(SEND_PATIENT_IMMEDIATE_UPDATE_INSURANCE_REQUEST, 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()));
}
}
}

@ -54,9 +54,6 @@ class MyAppointmentsViewModel extends ChangeNotifier {
List<PatientQueueDetails> patientQueueDetailsList = [];
late PatientQueueDetails currentPatientQueueDetails;
List<PatientAppointmentHistoryResponseModel> patientAppointmentsHistoryList = [];
List<PatientAppointmentHistoryResponseModel> filteredAppointmentList = [];
@ -344,10 +341,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, bool isLiveCareAppointment,
{Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientShareAppointment(
projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo, isLiveCareAppointment: isLiveCareAppointment);
Future<void> getPatientShareAppointment(int projectID, int clinicID, String appointmentNo, bool isLiveCareAppointment, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.getPatientShareAppointment(projectID: projectID, clinicID: clinicID, appointmentNo: appointmentNo, isLiveCareAppointment: isLiveCareAppointment);
result.fold(
(failure) async {
@ -421,13 +416,23 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
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(),
),
);
//Call the API to attempt updating patient insurance
LoaderBottomSheet.showLoader();
sendPatientUpdateRequest(onSuccess: (val) {
LoaderBottomSheet.hideLoader();
setIsPatientAppointmentShareLoading(true);
getPatientShareAppointment(projectID, clinicID, appointmentNo, isLiveCareAppointment);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
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!);
@ -443,6 +448,27 @@ class MyAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> sendPatientUpdateRequest({Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.sendPatientUpdateRequest();
result.fold(
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
onError!(failure.message);
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> convertPatientToCash({required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.convertPatientToCash(projectID: projectID);
@ -465,13 +491,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future<void> addAdvanceNumberRequest(
{required String advanceNumber,
required String paymentReference,
required String appointmentNo,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result =
await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
{required String advanceNumber, required String paymentReference, required String appointmentNo, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -489,14 +510,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future<void> generateAppointmentQR(
{required int clinicID,
required int projectID,
required String appointmentNo,
required int isFollowUp,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result =
await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);
{required int clinicID, required int projectID, required String appointmentNo, required int isFollowUp, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -513,14 +528,13 @@ class MyAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> cancelAppointment(
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
Future<void> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold(
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
if(onError != null) {
if (onError != null) {
onError(failure.message);
}
},
@ -538,8 +552,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> confirmAppointment(
{required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
Future<void> confirmAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.confirmAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold(
@ -600,8 +613,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
required int checkInType,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await myAppointmentsRepo.sendCheckInNfcRequest(
patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, scannedCode: scannedCode, checkInType: checkInType);
final result = await myAppointmentsRepo.sendCheckInNfcRequest(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, scannedCode: scannedCode, checkInType: checkInType);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -647,12 +659,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
}
Future<void> insertLiveCareVIDARequest(
{required clientRequestID,
required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await myAppointmentsRepo.insertLiveCareVIDARequest(
clientRequestID: clientRequestID, patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
{required clientRequestID, required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.insertLiveCareVIDARequest(clientRequestID: clientRequestID, patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
@ -783,7 +791,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
final result = await myAppointmentsRepo.getTamaraInstallmentsDetails();
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
isTamaraDetailsLoading = false;
notifyListeners();
},
(apiResponse) {
getTamaraInstallmentsDetailsResponseModel = apiResponse.data!;
isTamaraDetailsLoading = false;
@ -928,5 +940,4 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
}

@ -13,10 +13,10 @@ class GetInvoicesListResponseModel {
String? doctorName;
String? doctorNameN;
String? clinicName;
double? decimalDoctorRate;
num? decimalDoctorRate;
String? doctorImageURL;
int? doctorRate;
int? patientNumber;
num? doctorRate;
num? patientNumber;
String? projectName;
GetInvoicesListResponseModel(

@ -43,7 +43,7 @@ class MyInvoicesViewModel extends ChangeNotifier {
} else if (apiResponse.messageStatus == 1) {
allInvoicesList = apiResponse.data!;
isInvoicesListLoading = false;
allInvoicesList.sort((a, b) => b.appointmentDate!.compareTo(a.appointmentDate!));
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);

@ -1,8 +1,36 @@
import 'package:flutter/foundation.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class ProfileSettingsViewModel extends ChangeNotifier {
static const String _darkModeKey = 'is_dark_mode';
void notify(){
final CacheService _cacheService;
bool _isDarkMode = false;
bool get isDarkMode => _isDarkMode;
ProfileSettingsViewModel({required CacheService cacheService})
: _cacheService = cacheService;
/// Call once at app startup (before the first frame) to restore the
/// persisted dark-mode preference.
void loadDarkMode() {
final saved = _cacheService.getBool(key: _darkModeKey);
_isDarkMode = saved ?? false;
AppColors.isDarkMode = _isDarkMode;
// No notifyListeners() here we are called before build.
}
void toggleDarkMode(bool value) {
_isDarkMode = value;
AppColors.isDarkMode = value;
_cacheService.saveBool(key: _darkModeKey, value: value);
notifyListeners();
}
void notify() {
notifyListeners();
}
}

@ -188,14 +188,16 @@ class RadiologyRepoImp implements RadiologyRepo {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
final radOrders;
List<PatientRadiologyResponseModel> radOrders = [];
try {
if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) {
final list = response['FinalRadiologyList'];
radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientRadiologyResponseModel>();
} else {
final list = response['FinalRadiologyListAPI'];
radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientRadiologyResponseModel>();
if (response['FinalRadiologyListAPI'] != null && response['FinalRadiologyListAPI'].length != 0) {
final list = response['FinalRadiologyListAPI'];
radOrders = list.map((item) => PatientRadiologyResponseModel.fromJson(item as Map<String, dynamic>)).toList().cast<PatientRadiologyResponseModel>();
}
}
apiResponse = GenericApiModel<List<PatientRadiologyResponseModel>>(

@ -67,6 +67,19 @@ class RadiologyViewModel extends ChangeNotifier {
patientRadiologyOrders = apiResponse.data!;
filteredRadiologyOrders = List.from(patientRadiologyOrders);
tempRadiologyOrders = [...patientRadiologyOrders];
final clinicMap = <String, List<PatientRadiologyResponseModel>>{};
final hospitalMap = <String, List<PatientRadiologyResponseModel>>{};
for (var order in patientRadiologyOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
}
patientRadiologyOrdersByClinic = clinicMap.values.toList();
patientRadiologyOrdersByHospital = hospitalMap.values.toList();
patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital;
isRadiologyOrdersLoading = false;
filterSuggestions();
notifyListeners();
@ -168,9 +181,31 @@ class RadiologyViewModel extends ChangeNotifier {
filterRadiologyReports(String query) {
if (query.isEmpty) {
patientRadiologyOrders = tempRadiologyOrders; // reset
final clinicMap = <String, List<PatientRadiologyResponseModel>>{};
final hospitalMap = <String, List<PatientRadiologyResponseModel>>{};
for (var order in patientRadiologyOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
}
patientRadiologyOrdersByClinic = clinicMap.values.toList();
patientRadiologyOrdersByHospital = hospitalMap.values.toList();
patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital;
} else {
filteredRadiologyOrders = filteredRadiologyOrders.where((desc) => desc.description!.toLowerCase().contains(query.toLowerCase())).toList();
patientRadiologyOrders = filteredRadiologyOrders;
filteredRadiologyOrders = filteredRadiologyOrders.where((desc) => (desc.description ?? "").toLowerCase().contains(query.toLowerCase())).toList();
final clinicMap = <String, List<PatientRadiologyResponseModel>>{};
final hospitalMap = <String, List<PatientRadiologyResponseModel>>{};
for (var order in filteredRadiologyOrders) {
final clinicKey = (order.clinicDescription ?? 'Unknown').trim();
clinicMap.putIfAbsent(clinicKey, () => []).add(order);
final hospitalKey = (order.projectName ?? order.projectID ?? 'Unknown').toString().trim();
hospitalMap.putIfAbsent(hospitalKey, () => []).add(order);
}
patientRadiologyOrdersByClinic = clinicMap.values.toList();
patientRadiologyOrdersByHospital = hospitalMap.values.toList();
patientRadiologyOrdersViewList = isSortByClinic ? patientRadiologyOrdersByClinic : patientRadiologyOrdersByHospital;
}
notifyListeners();
}

@ -1587,5 +1587,8 @@ abstract class LocaleKeys {
static const whoophealthapplicationshouldbeinstalledinyourphone = 'whoophealthapplicationshouldbeinstalledinyourphone';
static const whoopwatchshouldbeconnected = 'whoopwatchshouldbeconnected';
static const updatetheinformation = 'updatetheinformation';
static const timeFor = 'timeFor';
static const hmgPolicies = 'hmgPolicies';
static const darkMode = 'darkMode';
}

@ -62,6 +62,9 @@ Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
getIt.get<LoggerService>().logInfo("Firebase backgroundMessageHandler Main!!!");
}
// flutter3_32 pub run easy_localization:generate -O ./lib/generated -f keys -o locale_keys.g.dart --source-dir ./assets/langs
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
@ -108,6 +111,9 @@ Future<void> callInitializations() async {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
HttpOverrides.global = MyHttpOverrides();
await callAppStateInitializations();
// Restore persisted dark-mode preference before the first frame.
getIt.get<ProfileSettingsViewModel>().loadDarkMode();
}
void main() async {
@ -247,27 +253,35 @@ class MyApp extends StatelessWidget {
return Sizer(
builder: (context, orientation, deviceType) {
// SizeConfig().init(constraints, orientation);
return MaterialApp(
// title: 'Dr. AlHabib',
title: 'Dr. AlHabib Beta',
builder: (context, mchild) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.noScaling,
alwaysUse24HourFormat: true,
),
child: mchild!,
return Consumer<ProfileSettingsViewModel>(
builder: (context, profileVm, _) {
final isArabic = EasyLocalization.of(context)?.locale.languageCode == "ar";
return MaterialApp(
key: ValueKey('app_theme_${profileVm.isDarkMode}'),
// title: 'Dr. AlHabib',
title: 'Dr. AlHabib Beta',
builder: (context, mchild) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.noScaling,
alwaysUse24HourFormat: true,
),
child: mchild!,
);
},
showSemanticsDebugger: false,
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
initialRoute: AppRoutes.initialRoute,
routes: AppRoutes.routes,
theme: AppTheme.getTheme(isArabic),
darkTheme: AppTheme.getDarkTheme(isArabic),
themeMode: profileVm.isDarkMode ? ThemeMode.dark : ThemeMode.light,
navigatorKey: getIt.get<NavigationService>().navigatorKey,
);
},
showSemanticsDebugger: false,
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
initialRoute: AppRoutes.initialRoute,
routes: AppRoutes.routes,
theme: AppTheme.getTheme(EasyLocalization.of(context)?.locale.languageCode == "ar"),
navigatorKey: getIt.get<NavigationService>().navigatorKey,
);
},
);

@ -2,11 +2,11 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:flutter/cupertino.dart';
import '../../core/app_assets.dart';
import '../../core/utils/calendar_utils.dart';
import '../../features/active_prescriptions/active_prescriptions_view_model.dart';
import '../../features/active_prescriptions/models/active_prescriptions_response_model.dart';
import '../../generated/locale_keys.g.dart';
@ -34,7 +34,6 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
List<ActivePrescriptionsResponseModel> selectedDayMeds = [];
ActivePrescriptionsViewModel? activePreVM;
Map<String, bool> medReminderStatus = {};
String _buildMedKey(ActivePrescriptionsResponseModel med) {
@ -172,7 +171,7 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
offset: const Offset(0, -4),
child: Text(
_getSuffix(selectedDate.day),
style: const TextStyle(
style: TextStyle(
fontSize: 12,
color: AppColors.textColor,
fontWeight: FontWeight.w500,
@ -182,7 +181,7 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
),
TextSpan(
text: " ${DateFormat.MMMM().format(selectedDate)}",
style: const TextStyle(
style: TextStyle(
color: AppColors.textColor,
fontSize: 16,
fontWeight: FontWeight.w500,
@ -279,7 +278,7 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
),
],
).paddingOnly(left: 16, right: 16),
const Divider(
Divider(
color: AppColors.greyColor),
GestureDetector(
onTap: () => showDoseDialog(med),
@ -331,7 +330,7 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
],
).paddingAll(16),
),
const Divider(
Divider(
color: AppColors.greyColor),
_buildButtons(),
],
@ -393,16 +392,16 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
children: [
AppCustomChipWidget(
labelText:
LocaleKeys.route.tr(namedArgs: {'route': med.route ?? ''})),
LocaleKeys.route.tr(namedArgs: {LocaleKeys.route.tr(): med.route ?? ''})),
AppCustomChipWidget(
labelText:
LocaleKeys.frequency.tr(namedArgs: {'frequency': med.frequency ?? ''})),
LocaleKeys.frequency.tr(namedArgs: {LocaleKeys.frequency.tr(): med.frequency ?? ''})),
AppCustomChipWidget(
labelText:
LocaleKeys.instruction.tr(namedArgs: {'instruction': med.doseDailyQuantity?.toString() ?? ''})),
LocaleKeys.instruction.tr(namedArgs: {LocaleKeys.instruction.tr(): med.doseDailyQuantity?.toString() ?? ''})),
AppCustomChipWidget(
labelText:
LocaleKeys.duration.tr(namedArgs: {'days': med.days.toString() ?? ''})),
LocaleKeys.duration.tr(namedArgs: {LocaleKeys.days.tr(): med.days.toString() ?? ''})),
],
),
],
@ -658,7 +657,7 @@ class _ActiveMedicationPageState extends State<ActiveMedicationPage> {
builder: (_) => Container(
width: double.infinity,
height: 460.h,
decoration: const BoxDecoration(
decoration: BoxDecoration(
color: AppColors.bottomSheetBgColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
@ -773,6 +772,8 @@ class _ReminderTimerDialogState extends State<ReminderTimerDialog> {
String bigTimeText = "00:00";
bool showPicker = false;
CalenderUtilsNew calender = CalenderUtilsNew.instance;
final List<List<String>> presetTimes = [
["06:00 AM", "07:00 AM", "08:00 AM", "09:00 AM"], // Morning
["12:00 PM", "01:00 PM", "02:00 PM", "03:00 PM"], // Noon
@ -813,7 +814,7 @@ class _ReminderTimerDialogState extends State<ReminderTimerDialog> {
text: TextSpan(
children: [
TextSpan(
text: "Time for ",
text: LocaleKeys.timeFor.tr(),
style: TextStyle(
fontSize: 18.f,
fontWeight: FontWeight.bold,
@ -842,7 +843,7 @@ class _ReminderTimerDialogState extends State<ReminderTimerDialog> {
),
),
TextSpan(
text: " reminder",
text: LocaleKeys.reminder.tr(),
style: TextStyle(
fontSize: 18.f,
fontWeight: FontWeight.bold,
@ -972,16 +973,28 @@ class _ReminderTimerDialogState extends State<ReminderTimerDialog> {
if (isPM && hour != 12) hour += 12;
if (!isPM && hour == 12) hour = 0;
int totalMinutes = hour * 60 + minute;
await setCalender(
context,
eventId: widget.med.itemId.toString(),
selectedMinutes: totalMinutes,
await calender.createMultipleEvents(
reminderMinutes: totalMinutes,
frequencyNumber: widget.frequencyNumber,
days: widget.med.days ?? 1,
orderDate: widget.med.orderDate ?? "",
itemDescriptionN: widget.med.itemDescription ?? "",
route: widget.med.route ?? "",
onFailure: (errorMessage) {},
prescriptionNumber: widget.med.itemId.toString()
);
// await setCalender(
// context,
// eventId: widget.med.itemId.toString(),
// selectedMinutes: totalMinutes,
// frequencyNumber: widget.frequencyNumber,
// days: widget.med.days ?? 1,
// orderDate: widget.med.orderDate ?? "",
// itemDescriptionN: widget.med.itemDescription ?? "",
// route: widget.med.route ?? "",
// );
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(LocaleKeys.reminderAddedToCalendar.tr())),
);

@ -56,7 +56,7 @@ class AllergiesListPage extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.allergy_info_icon, width: 36.w, height: 36.h, fit: BoxFit.contain).toShimmer2(isShow: true),
Utils.buildSvgWithAssets(icon: AppAssets.allergy_info_icon, width: 36.w, height: 36.h, fit: BoxFit.contain, applyThemeColor: false).toShimmer2(isShow: true),
SizedBox(width: 16.h),
Expanded(
child: Column(
@ -100,7 +100,7 @@ class AllergiesListPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.allergy_info_icon, width: 36.w, height: 36.h, fit: BoxFit.contain),
Utils.buildSvgWithAssets(icon: AppAssets.allergy_info_icon, width: 36.w, height: 36.h, fit: BoxFit.contain, applyThemeColor: false),
SizedBox(height: 16.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,

@ -241,13 +241,13 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
},
backgroundColor: AppColors.successColor,
borderColor: AppColors.successColor,
textColor: AppColors.whiteColor,
textColor: Colors.white,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
height: 40.h,
icon: AppAssets.confirm_appointment_icon,
iconColor: AppColors.whiteColor,
iconColor: Colors.white,
iconSize: 16.h,
)
: SizedBox.shrink())
@ -305,16 +305,16 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
}
},
text: LocaleKeys.getDirections.tr(context: context),
backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
backgroundColor: AppColors.bookAppointment.withValues(alpha: 0.8),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.01),
textColor: AppColors.whiteColor,
textColor: Colors.white,
fontSize: 14.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.directions_icon,
iconColor: AppColors.whiteColor,
iconColor: Colors.white,
iconSize: 14.h,
).paddingAll(12.h),
),
@ -353,7 +353,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h),
Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h, applyThemeColor: false),
SizedBox(width: 8.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -841,15 +841,15 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
},
backgroundColor: AppColors.successColor,
borderColor: AppColors.successColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
textColor: Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 50.h,
icon: AppAssets.add_icon,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
iconColor: Colors.white,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.h)
: SizedBox.shrink()
: CustomButton(
@ -860,14 +860,14 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction),
borderColor:
AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: widget.patientAppointmentHistoryResponseModel.nextAction == 15 ? AppColors.textColor : AppColors.whiteColor,
textColor: widget.patientAppointmentHistoryResponseModel.nextAction == 15 ? AppColors.textColor : Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 56.h,
icon: AppointmentType.getNextActionIcon(widget.patientAppointmentHistoryResponseModel.nextAction),
iconColor: AppColors.whiteColor,
iconColor: Colors.white,
iconSize: 18.h,
).paddingSymmetrical(16.h, 24.h),
],
@ -904,7 +904,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
textColor: Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,

@ -318,6 +318,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
applyThemeColor: false
).paddingSymmetrical(24.h, 0.h).onPress(() {
// payfortVM.setIsApplePayConfigurationLoading(true);
if (Utils.havePrivilege(103)) {

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -34,6 +36,13 @@ class _MyDoctorsPageState extends State<MyDoctorsPage> {
int? expandedIndex;
final Map<int, GlobalKey> _groupKeys = {};
@override
void initState() {
scheduleMicrotask(() {
myAppointmentsViewModel.getPatientMyDoctors();
});
super.initState();
}
@override
Widget build(BuildContext context) {

@ -96,10 +96,10 @@ class AppointmentCard extends StatelessWidget {
children: [
AppCustomChipWidget(
icon: isLoading ? AppAssets.walkin_appointment_icon : (isLiveCare ? AppAssets.small_livecare_icon : AppAssets.walkin_appointment_icon),
iconColor: isLoading ? AppColors.textColor : (isLiveCare ? AppColors.whiteColor : AppColors.textColor),
iconColor: isLoading ? AppColors.textColor : (isLiveCare ? Colors.white : AppColors.textColor),
labelText: isLoading ? LocaleKeys.walkin.tr(context: context) : (isLiveCare ? LocaleKeys.livecare.tr(context: context) : LocaleKeys.walkin.tr(context: context)),
backgroundColor: isLoading ? AppColors.greyColor : (isLiveCare ? AppColors.successColor : AppColors.greyColor),
textColor: isLoading ? AppColors.textColor : (isLiveCare ? AppColors.whiteColor : AppColors.textColor),
textColor: isLoading ? AppColors.textColor : (isLiveCare ? Colors.white : AppColors.textColor),
).toShimmer2(isShow: isLoading),
AppCustomChipWidget(
labelText:
@ -145,7 +145,7 @@ class AppointmentCard extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h),
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, iconColor: AppColors.ratingColorYellow),
SizedBox(height: 2.h),
(isFoldable || isTablet)
? "${patientAppointmentHistoryResponseModel.decimalDoctorRate}".toText9(isBold: true, color: AppColors.textColor)

@ -68,9 +68,9 @@ class AppointmentDoctorCard extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h),
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, iconColor: AppColors.ratingColorYellow),
SizedBox(height: 2.h),
"${patientAppointmentHistoryResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor),
"${patientAppointmentHistoryResponseModel.decimalDoctorRate ?? 0.0}".toText11(isBold: true, color: AppColors.textColor),
],
),
).circle(100),
@ -115,13 +115,13 @@ class AppointmentDoctorCard extends StatelessWidget {
icon: !patientAppointmentHistoryResponseModel.isLiveCareAppointment!
? AppAssets.walkin_appointment_icon
: AppAssets.small_livecare_icon,
iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor,
iconColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white,
labelText: patientAppointmentHistoryResponseModel.isLiveCareAppointment!
? LocaleKeys.livecare.tr(context: context)
: LocaleKeys.walkin.tr(context: context),
backgroundColor:
!patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.greyColor : AppColors.successColor,
textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : AppColors.whiteColor,
textColor: !patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? AppColors.textColor : Colors.white,
),
],
),

@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/ask_doctor/models/ask_doctor_appointments_list.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/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';

@ -56,6 +56,7 @@ class HospitalListItem extends StatelessWidget {
children: [
Utils.buildSvgWithAssets(
icon: (hospitalData?.isHMC == true) ? AppAssets.hmc : AppAssets.hmg,
applyThemeColor: false,
).paddingOnly(right: 10),
Expanded(
child: Text(

@ -63,6 +63,7 @@ class RegionListItem extends StatelessWidget {
iconSize: 14.h,
icon: svgPath,
iconHasColor: false,
applyThemeColor: false,
richText: RichText(
text: TextSpan(
text: count,

@ -1,13 +1,21 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils;
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart' show RegionListItem;
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../widgets/common_bottom_sheet.dart';
@ -30,13 +38,52 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
} else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) {
myAppointmentsViewModel.getMappedDoctors(onError: (err) {
Navigator.pop(context);
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
if (myAppointmentsViewModel.selectedClinic.clinicID == 23) {
showCommonBottomSheetWithoutHeight(
context,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
("For booking appointments in the Physiotherapy clinic, please contact: 920066666").toText16(color: AppColors.blackColor),
SizedBox(height: 16.h),
CustomButton(
height: 40.h,
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
text: LocaleKeys.callNow.tr(),
textColor: AppColors.whiteColor,
iconColor: AppColors.whiteColor,
onPressed: () {
launchUrl(
Uri.parse("tel://920066666"),
);
},
icon: AppAssets.call),
],
).center,
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} else {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
// showCommonBottomSheetWithoutHeight(
// context,
// child: Utils.getErrorWidget(loadingText: err),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
});
}
});
@ -52,8 +99,8 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
if (myAppointmentsVM.isRegionListLoading) {
return Container(
height: MediaQuery.of(context).size.height * 0.3,
decoration: const BoxDecoration(
color: Colors.white,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Center(

@ -109,7 +109,7 @@ class AskDoctorAppointmentCard extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h),
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, applyThemeColor: false),
SizedBox(height: 2.h),
"${askDoctorAppointmentHistoryList.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor),
],
@ -171,7 +171,18 @@ class AskDoctorAppointmentCard extends StatelessWidget {
child: AskDoctorRequestTypeSelect(
askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList,
myAppointmentsViewModel: myAppointmentsViewModel,
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel()
patientAppointmentHistoryResponseModel: PatientAppointmentHistoryResponseModel(
appointmentNo: askDoctorAppointmentHistoryList.appointmentNo,
doctorID: askDoctorAppointmentHistoryList.doctorID!,
doctorName: askDoctorAppointmentHistoryList.doctorName!,
doctorTitle: askDoctorAppointmentHistoryList.doctorTitle!,
doctorImageURL: askDoctorAppointmentHistoryList.doctorImageURL!,
clinicID: askDoctorAppointmentHistoryList.clinicID!,
clinicName: askDoctorAppointmentHistoryList.clinicName!,
projectID: askDoctorAppointmentHistoryList.projectID!,
projectName: askDoctorAppointmentHistoryList.projectName!,
appointmentDate: askDoctorAppointmentHistoryList.appointmentDate!,
),
// myAppointmentsVM.patientAppointmentsHistoryList[index],
),
callBackFunc: () {},

@ -116,7 +116,7 @@ class LoginScreenState extends State<LoginScreen> {
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: context.dynamicTextStyle(color: Colors.black, fontSize: 14.f, height: 26 / 16, fontWeight: FontWeight.w500),
style: context.dynamicTextStyle(color: AppColors.textColor, fontSize: 14.f, height: 26 / 16, fontWeight: FontWeight.w500),
children: <TextSpan>[
TextSpan(text: LocaleKeys.dontHaveAccount.tr(context: context), style: context.dynamicTextStyle()),
TextSpan(text: " "),
@ -188,7 +188,8 @@ class LoginScreenState extends State<LoginScreen> {
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,
textColor: AppColors.whiteColor,
textColor: Colors.white,
iconColor: Colors.white,
icon: AppAssets.message,
),
),
@ -217,11 +218,12 @@ class LoginScreenState extends State<LoginScreen> {
await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp);
}
},
backgroundColor: Colors.white,
borderColor: AppColors.borderOnlyColor,
backgroundColor: AppColors.whiteColor,
borderColor: AppColors.textColor,
textColor: AppColors.textColor,
icon: AppAssets.whatsapp,
iconColor: null,
applyThemeColor: false,
),
),
],

@ -85,7 +85,7 @@ class _RegisterNew extends State<RegisterNew> {
Directionality(
textDirection: Directionality.of(context),
child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)),
decoration: BoxDecoration(color: AppColors.whiteColor, borderRadius: BorderRadius.circular(24)),
padding: EdgeInsets.symmetric(horizontal: 16.h),
child: Column(
children: [

@ -76,7 +76,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
LocaleKeys.personalDetailsVerification.tr(context: context).toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2),
SizedBox(height: 24.h),
Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)),
decoration: BoxDecoration(color: AppColors.whiteColor, borderRadius: BorderRadius.circular(24)),
padding: EdgeInsets.only(left: 16.h, right: 16.h),
child: Column(
children: [

@ -251,10 +251,11 @@ class _SavedLogin extends State<SavedLogin> {
}
},
backgroundColor: AppColors.whiteColor,
borderColor: Color(0xFF2E3039),
textColor: Color(0xFF2E3039),
borderColor: AppColors.textColor,
textColor: AppColors.textColor,
borderWidth: 2.w,
padding: EdgeInsets.fromLTRB(0, 14.h, 0, 14.h),
applyThemeColor: false,
),
const Spacer(flex: 2),
// OR divider

@ -230,7 +230,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.search_by_clinic_icon, width: 40.h, height: 40.h),
Utils.buildSvgWithAssets(icon: AppAssets.search_by_clinic_icon, width: 40.h, height: 40.h, applyThemeColor: false),
SizedBox(width: 12.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -262,7 +262,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.search_by_doctor_icon, width: 40.h, height: 40.h),
Utils.buildSvgWithAssets(icon: AppAssets.search_by_doctor_icon, width: 40.h, height: 40.h, applyThemeColor: false),
SizedBox(width: 12.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -292,7 +292,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h),
Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h, applyThemeColor: false),
SizedBox(width: 12.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -336,9 +336,9 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.search_by_clinic_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.h),
Column(
Utils.buildSvgWithAssets(icon: AppAssets.search_by_clinic_icon, width: 40.h, height: 40.h, applyThemeColor: false),
SizedBox(width: 12.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.immediateConsultation.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
@ -378,9 +378,9 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.search_by_doctor_icon, width: 40.h, height: 40.h),
SizedBox(width: 12.h),
Column(
Utils.buildSvgWithAssets(icon: AppAssets.search_by_doctor_icon, width: 40.h, height: 40.h, applyThemeColor: false),
SizedBox(width: 12.h),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.scheduledConsultation.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
@ -400,30 +400,6 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
),
);
}),
// SizedBox(height: 16.h),
// Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.1), height: 1.h),
// SizedBox(height: 16.h),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Row(
// children: [
// Utils.buildSvgWithAssets(icon: AppAssets.search_by_region_icon, width: 40.h, height: 40.h),
// SizedBox(width: 12.h),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// LocaleKeys.pharmaLiveCare.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
// "".toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
// ],
// ),
// ],
// ),
// Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon, iconColor: AppColors.textColor, width: 40.h, height: 40.h)),
// ],
// ).onPress(() {
// openRegionListBottomSheet(context, RegionBottomSheetType.FOR_REGION);
// }),
],
),
),

@ -159,7 +159,7 @@ class DoctorsFilters extends StatelessWidget{
Spacer(),
DecoratedBox(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
color: AppColors.whiteColor,
customBorder: BorderRadius.only(topLeft: Radius.circular(24.h), topRight: Radius.circular(24.h)) ,
),

@ -41,7 +41,7 @@ class DoctorProfilePage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.h),
// SizedBox(height: 24.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -106,6 +106,7 @@ class DoctorProfilePage extends StatelessWidget {
width: 48.w,
height: 48.h,
fit: BoxFit.contain,
applyThemeColor: false
),
SizedBox(height: 16.h),
"Ratings".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
@ -132,6 +133,7 @@ class DoctorProfilePage extends StatelessWidget {
width: 48.w,
height: 48.h,
fit: BoxFit.contain,
applyThemeColor: false
),
SizedBox(height: 16.h),
"Reviews".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
@ -172,6 +174,10 @@ class DoctorProfilePage extends StatelessWidget {
child: CustomButton(
text: LocaleKeys.viewAvailableAppointments.tr(),
onPressed: () async {
bookAppointmentsViewModel.selectedDoctor.speciality = bookAppointmentsViewModel.doctorsProfileResponseModel.specialty;
bookAppointmentsViewModel.selectedDoctor.specialityN = bookAppointmentsViewModel.doctorsProfileResponseModel.specialty;
bookAppointmentsViewModel.selectedDoctor.name = bookAppointmentsViewModel.doctorsProfileResponseModel.doctorName;
bookAppointmentsViewModel.selectedDoctor.name = bookAppointmentsViewModel.doctorsProfileResponseModel.doctorName;
LoaderBottomSheet.showLoader();
bookAppointmentsViewModel.isLiveCareSchedule
? await bookAppointmentsViewModel.getLiveCareDoctorFreeSlots(
@ -223,14 +229,14 @@ class DoctorProfilePage extends StatelessWidget {
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
textColor: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50.h,
icon: AppAssets.calendar,
iconColor: AppColors.whiteColor,
iconColor: Colors.white,
iconSize: 20.h,
).paddingSymmetrical(24.h, 24.h),
),

@ -84,7 +84,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} ${LocaleKeys.yearsOld.tr(context: context)}"),
AppCustomChipWidget(
labelText:
"${LocaleKeys.clinic.tr()}: ${(appState.isArabic() ? immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceNameN : immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceName)!}"),
"${LocaleKeys.clinic.tr()}: ${(appState.isArabic() ? immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceNameN : immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceName) ?? ""}"),
],
),
],
@ -110,7 +110,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: getLiveCareTypeIcon(immediateLiveCareVM.liveCareSelectedCallType), width: 32.h, height: 32.h, fit: BoxFit.contain),
Utils.buildSvgWithAssets(icon: getLiveCareTypeIcon(immediateLiveCareVM.liveCareSelectedCallType), width: 32.h, height: 32.h, fit: BoxFit.contain, applyThemeColor: false),
SizedBox(width: 8.h),
getLiveCareType(context, immediateLiveCareVM.liveCareSelectedCallType).toText16(isBold: true),
],

@ -292,6 +292,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
applyThemeColor: false
).paddingSymmetrical(24.h, 0.h).onPress(() {
// payfortVM.setIsApplePayConfigurationLoading(true);
if (Utils.havePrivilege(103)) {

@ -117,7 +117,7 @@ class _ImmediateLiveCarePendingRequestPageState extends State<ImmediateLiveCareP
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
labelText: immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus,
labelText: immediateLiveCareViewModel.patientLiveCareHistoryList.isNotEmpty ? immediateLiveCareViewModel.patientLiveCareHistoryList[0].stringCallStatus : "",
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.20),
textColor: AppColors.alertColor,
),

@ -116,7 +116,7 @@ class _SelectImmediateLiveCareClinicPageState extends State<SelectImmediateLiveC
onImmediateLiveCareClinicSelected(GetLiveCareClinicListResponseModel liveCareClinic) {
//TODO: add implementation to show clinic schedule
if (liveCareClinic.isOnline == 1) {
// if (liveCareClinic.isOnline == 1) {
showCommonBottomSheetWithoutHeight(context, child: SelectLiveCareCallType(immediateLiveCareViewModel: immediateLiveCareViewModel), callBackFunc: () async {
if (immediateLiveCareViewModel.liveCareSelectedCallType != 0) {
immediateLiveCareViewModel.setImmediateLiveCareSelectedClinic(liveCareClinic);
@ -130,17 +130,24 @@ class _SelectImmediateLiveCareClinicPageState extends State<SelectImmediateLiveC
);
}, onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}
}, title: LocaleKeys.selectLiveCareCallType.tr(), isCloseButtonVisible: true, isFullScreen: false);
} else {
showCommonBottomSheetWithoutHeight(context,
child: Utils.getErrorWidget(
loadingText: "The selected clinic is only available between ${liveCareClinic.shiftTimings!.first.startTime} & ${liveCareClinic.shiftTimings!.first.endTime} hours."),
callBackFunc: () {},
title: "",
isCloseButtonVisible: true,
isFullScreen: false);
}
// } else {
// showCommonBottomSheetWithoutHeight(context,
// child: Utils.getErrorWidget(
// loadingText: "The selected clinic is only available between ${liveCareClinic.shiftTimings!.first.startTime} & ${liveCareClinic.shiftTimings!.first.endTime} hours."),
// callBackFunc: () {},
// title: "",
// isCloseButtonVisible: true,
// isFullScreen: false);
// }
}
}

@ -61,7 +61,7 @@ class SelectLiveCareCallType extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill),
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill, applyThemeColor: false),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,

@ -225,8 +225,8 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16,
textColor: Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),

@ -144,7 +144,14 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: bookAppointmentsVM.isClinicsListLoading ? 5 : bookAppointmentsVM.liveCareClinicsList.length,
itemCount: bookAppointmentsVM.isClinicsListLoading
? 5
: bookAppointmentsVM.liveCareClinicsList.isNotEmpty
? bookAppointmentsVM.liveCareClinicsList.length
: 1,
// bookAppointmentsVM.isClinicsListLoading ? 5 : bookAppointmentsVM.liveCareClinicsList.length,
itemBuilder: (context, index) {
return bookAppointmentsVM.isClinicsListLoading
? ClinicCard(
@ -163,14 +170,16 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: ClinicCard(
bookAppointmentsVM: bookAppointmentsVM,
liveCareClinicsResponseModel: bookAppointmentsVM.liveCareClinicsList[index],
clinicsListResponseModel: GetClinicsListResponseModel(),
isLoading: bookAppointmentsVM.isClinicsListLoading,
).onPress(() {
onLiveCareClinicSelected(bookAppointmentsVM.liveCareClinicsList[index]);
}),
child: bookAppointmentsVM.liveCareClinicsList.isNotEmpty
? ClinicCard(
bookAppointmentsVM: bookAppointmentsVM,
liveCareClinicsResponseModel: bookAppointmentsVM.liveCareClinicsList[index],
clinicsListResponseModel: GetClinicsListResponseModel(),
isLoading: bookAppointmentsVM.isClinicsListLoading,
).onPress(() {
onLiveCareClinicSelected(bookAppointmentsVM.liveCareClinicsList[index]);
})
: Utils.getNoDataWidget(context),
),
),
),

@ -313,6 +313,7 @@ class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymen
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
applyThemeColor: false
).paddingSymmetrical(24.h, 0.h).onPress(() {
// payfortVM.setIsApplePayConfigurationLoading(true);
if (Utils.havePrivilege(103)) {
@ -484,6 +485,7 @@ class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymen
});
});
} else {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),

@ -262,7 +262,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
textColor: Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 10.r,
@ -344,7 +344,7 @@ class TimeSlotChip extends StatelessWidget {
? Container(
padding: EdgeInsets.symmetric(horizontal: 14.h, vertical: 8.h),
decoration: ShapeDecoration(
color: isSelected ? AppColors.warningColorYellow : AppColors.whiteColor,
color: isSelected ? AppColors.warningColorYellow : AppColors.textColor,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.circular(8.h),
smoothness: 1,
@ -367,8 +367,8 @@ class TimeSlotChip extends StatelessWidget {
),
),
child: label.toText12(
color: isSelected ? AppColors.primaryRedColor : Colors.black87,
fontWeight: FontWeight.w500,
color: isSelected ? AppColors.primaryRedColor : AppColors.textColor,
fontWeight: FontWeight.w500,
),
),
);

@ -34,7 +34,7 @@ class ClinicCard extends StatelessWidget {
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Utils.buildSvgWithAssets(icon: "assets/images/clinicIcons/${clinicsListResponseModel.clinicID ?? 1}.svg", width: 24.w, height: 24.h, fit: BoxFit.contain).toShimmer2(isShow: isLoading),
(clinicsListResponseModel.isLiveCareClinicAndOnline ?? true)
? Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 32.w, height: 32.h, fit: BoxFit.contain).toShimmer2(isShow: isLoading)
? Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 32.w, height: 32.h, fit: BoxFit.contain, applyThemeColor: false).toShimmer2(isShow: isLoading)
: SizedBox.shrink(),
],
),

@ -15,6 +15,8 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:lottie/lottie.dart';
import 'package:url_launcher/url_launcher.dart';
class DoctorCard extends StatelessWidget {
const DoctorCard({
@ -72,7 +74,7 @@ class DoctorCard extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h),
Utils.buildSvgWithAssets(icon: AppAssets.rating_icon, width: 15.w, height: 15.h, applyThemeColor: false),
SizedBox(height: 2.h),
"${isLoading ? 4.78 : doctorsListResponseModel.decimalDoctorRate}".toText11(isBold: true, color: AppColors.textColor),
],
@ -198,13 +200,52 @@ class DoctorCard extends StatelessWidget {
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
if (bookAppointmentsViewModel.selectedClinic.clinicID == 23) {
showCommonBottomSheetWithoutHeight(
context,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
("For booking appointments in the Physiotherapy clinic, please contact: 920066666").toText16(color: AppColors.blackColor),
SizedBox(height: 16.h),
CustomButton(
height: 40.h,
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
text: LocaleKeys.callNow.tr(),
textColor: AppColors.whiteColor,
iconColor: AppColors.whiteColor,
onPressed: () {
launchUrl(
Uri.parse("tel://920066666"),
);
},
icon: AppAssets.call),
],
).center,
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} else {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
// showCommonBottomSheetWithoutHeight(
// context,
// child: Utils.getErrorWidget(loadingText: err),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
});
},
backgroundColor: Color(0xffFEE9EA),

@ -69,13 +69,13 @@ class DoctorRatingDetails extends StatelessWidget {
Container(
width: 100.0,
margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0),
child: Text(LocaleKeys.excellent.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))),
child: Text(LocaleKeys.excellent.tr(context: context), style: TextStyle(fontSize: 13.0, color: AppColors.textColor, fontWeight: FontWeight.w600))),
getRatingLine(bookAppointmentsVM.doctorDetailsList[0].ratio, Colors.green[700]!),
],
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)),
child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
),
],
),
@ -89,13 +89,13 @@ class DoctorRatingDetails extends StatelessWidget {
Container(
width: 100.0,
margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0),
child: Text(LocaleKeys.vGood.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))),
child: Text(LocaleKeys.vGood.tr(context: context), style: TextStyle(fontSize: 13.0, color: AppColors.textColor, fontWeight: FontWeight.w600))),
getRatingLine(bookAppointmentsVM.doctorDetailsList[1].ratio, Color(0xffB7B723)),
],
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)),
child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
),
],
),
@ -109,13 +109,13 @@ class DoctorRatingDetails extends StatelessWidget {
Container(
width: 100.0,
margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0),
child: Text(LocaleKeys.good.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))),
child: Text(LocaleKeys.good.tr(context: context), style: TextStyle(fontSize: 13.0, color: AppColors.textColor, fontWeight: FontWeight.w600))),
getRatingLine(bookAppointmentsVM.doctorDetailsList[2].ratio, Color(0xffEBA727)),
],
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)),
child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
),
],
),
@ -129,13 +129,13 @@ class DoctorRatingDetails extends StatelessWidget {
Container(
width: 100.0,
margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0),
child: Text(LocaleKeys.average.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))),
child: Text(LocaleKeys.average.tr(context: context), style: TextStyle(fontSize: 13.0, color: AppColors.textColor, fontWeight: FontWeight.w600))),
getRatingLine(bookAppointmentsVM.doctorDetailsList[3].ratio, Color(0xffEB7227)),
],
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)),
child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
),
],
),
@ -150,13 +150,13 @@ class DoctorRatingDetails extends StatelessWidget {
Container(
width: 100.0,
margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0),
child: Text(LocaleKeys.average.tr(context: context), style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))),
child: Text(LocaleKeys.average.tr(context: context), style: TextStyle(fontSize: 13.0, color: AppColors.textColor, fontWeight: FontWeight.w600))),
getRatingLine(bookAppointmentsVM.doctorDetailsList[4].ratio, Color(0xffE20C0C)),
],
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)),
child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
),
],
),

@ -122,12 +122,12 @@ class LiveChatPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
("${appState.isArabic() ? contactUsVM.liveChatProjectsList[index].projectNameN! : contactUsVM.liveChatProjectsList[index].projectName!}\n${contactUsVM.liveChatProjectsList[index].distanceInKilometers!} KM")
.toText14(isBold: true, color: contactUsVM.selectedLiveChatProjectIndex == index ? AppColors.whiteColor : AppColors.textColor),
.toText14(isBold: true, color: contactUsVM.selectedLiveChatProjectIndex == index ? Colors.white : AppColors.textColor),
Transform.flip(
flipX: getIt.get<AppState>().isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small,
iconColor: contactUsVM.selectedLiveChatProjectIndex == index ? AppColors.whiteColor : AppColors.textColor,
iconColor: contactUsVM.selectedLiveChatProjectIndex == index ? Colors.white : AppColors.textColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
@ -235,8 +235,8 @@ class LiveChatPage extends StatelessWidget {
},
backgroundColor: contactUsVM.selectedLiveChatProjectIndex == -1 ? AppColors.greyColor : AppColors.primaryRedColor,
borderColor: contactUsVM.selectedLiveChatProjectIndex == -1 ? AppColors.greyColor : AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16,
textColor: Colors.white,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),

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

Loading…
Cancel
Save