diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index cd5030d2..f703aeb8 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -50,6 +50,8 @@
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
tools:node="remove" />
+
+
@@ -92,7 +94,6 @@
-
diff --git a/android/app/src/main2/AndroidManifest.xml b/android/app/src/main2/AndroidManifest.xml
index e07739b9..535bd4ab 100644
--- a/android/app/src/main2/AndroidManifest.xml
+++ b/android/app/src/main2/AndroidManifest.xml
@@ -45,6 +45,7 @@
+
-
diff --git a/assets/fonts/cairo/Cairo-Bold.ttf b/assets/fonts/cairo/Cairo-Bold.ttf
new file mode 100644
index 00000000..041abaf6
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Bold.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.eot b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.eot
new file mode 100644
index 00000000..ed5f0c34
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.eot differ
diff --git a/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.otf b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.otf
new file mode 100644
index 00000000..8bc25fbb
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.otf differ
diff --git a/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.ttf b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.ttf
new file mode 100644
index 00000000..4f026897
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.woff b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.woff
new file mode 100644
index 00000000..91e3d063
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Bold/Cairo-Bold.woff differ
diff --git a/assets/fonts/cairo/Cairo-ExtraBold.ttf b/assets/fonts/cairo/Cairo-ExtraBold.ttf
new file mode 100644
index 00000000..4fc547de
Binary files /dev/null and b/assets/fonts/cairo/Cairo-ExtraBold.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Light.ttf b/assets/fonts/cairo/Cairo-Light.ttf
new file mode 100644
index 00000000..7e0f9427
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Light.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Light/Cairo-Light.eot b/assets/fonts/cairo/Cairo-Light/Cairo-Light.eot
new file mode 100644
index 00000000..d76c5391
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Light/Cairo-Light.eot differ
diff --git a/assets/fonts/cairo/Cairo-Light/Cairo-Light.otf b/assets/fonts/cairo/Cairo-Light/Cairo-Light.otf
new file mode 100644
index 00000000..f8812a9c
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Light/Cairo-Light.otf differ
diff --git a/assets/fonts/cairo/Cairo-Light/Cairo-Light.ttf b/assets/fonts/cairo/Cairo-Light/Cairo-Light.ttf
new file mode 100644
index 00000000..840cbc3e
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Light/Cairo-Light.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Light/Cairo-Light.woff b/assets/fonts/cairo/Cairo-Light/Cairo-Light.woff
new file mode 100644
index 00000000..9534bb4b
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Light/Cairo-Light.woff differ
diff --git a/assets/fonts/cairo/Cairo-Medium.ttf b/assets/fonts/cairo/Cairo-Medium.ttf
new file mode 100644
index 00000000..5b8d0f70
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Medium.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Regular.ttf b/assets/fonts/cairo/Cairo-Regular.ttf
new file mode 100644
index 00000000..36ac46bf
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Regular.ttf differ
diff --git a/assets/fonts/cairo/Cairo-Regular/Cairo-Regular.ttf b/assets/fonts/cairo/Cairo-Regular/Cairo-Regular.ttf
new file mode 100644
index 00000000..3eb09f86
Binary files /dev/null and b/assets/fonts/cairo/Cairo-Regular/Cairo-Regular.ttf differ
diff --git a/assets/fonts/cairo/Cairo-SemiBold.ttf b/assets/fonts/cairo/Cairo-SemiBold.ttf
new file mode 100644
index 00000000..fd01d422
Binary files /dev/null and b/assets/fonts/cairo/Cairo-SemiBold.ttf differ
diff --git a/assets/images/png/full_body_back_female.png b/assets/images/png/full_body_back_female.png
index 9b3aa74d..b1ea5cac 100644
Binary files a/assets/images/png/full_body_back_female.png and b/assets/images/png/full_body_back_female.png differ
diff --git a/assets/images/png/full_body_back_male.png b/assets/images/png/full_body_back_male.png
index 2eda5e8f..73a0b8b3 100644
Binary files a/assets/images/png/full_body_back_male.png and b/assets/images/png/full_body_back_male.png differ
diff --git a/assets/images/png/full_body_front_female.png b/assets/images/png/full_body_front_female.png
index c89608b0..68ce3738 100644
Binary files a/assets/images/png/full_body_front_female.png and b/assets/images/png/full_body_front_female.png differ
diff --git a/assets/images/png/full_body_front_male.png b/assets/images/png/full_body_front_male.png
index d1f34b4e..01e603a4 100644
Binary files a/assets/images/png/full_body_front_male.png and b/assets/images/png/full_body_front_male.png differ
diff --git a/assets/images/svg/add_new_family_icon.svg b/assets/images/svg/add_new_family_icon.svg
new file mode 100644
index 00000000..ad7ee356
--- /dev/null
+++ b/assets/images/svg/add_new_family_icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/images/svg/appointment_rating_icon.svg b/assets/images/svg/appointment_rating_icon.svg
new file mode 100644
index 00000000..83d89feb
--- /dev/null
+++ b/assets/images/svg/appointment_rating_icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/images/svg/calendar_filled_icon.svg b/assets/images/svg/calendar_filled_icon.svg
new file mode 100644
index 00000000..116ce8ef
--- /dev/null
+++ b/assets/images/svg/calendar_filled_icon.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index cd92703c..92f202f0 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -936,7 +936,7 @@
"hospitalInformation": "معلومات المستشفى",
"fetchingAppointmentShare": "جاري جلب تفاصيل الموعد...",
"bookingYourAppointment": "جاري حجز موعدك...",
- "selectLiveCareClinic": "اختر عيادة لايف كير",
+ "selectLiveCareClinic": "عيادة لايف كير",
"checkingForExistingDentalPlan": "جاري التحقق من وجود خطة أسنان حالية، يرجى الانتظار...",
"dentalTreatmentPlan": "خطة علاج الأسنان",
"youHaveExistingTreatmentPlan": "لديك خطة علاج حالية: ",
@@ -1654,8 +1654,40 @@
"twoWaySubtitle": "نقل من الموقع إلى المستشفى والعودة مرة أخرى",
"toHospitalSubtitle": "نقل من موقعك الحالي إلى المستشفى",
"fromHospitalSubtitle": "نقل من المستشفى إلى منزلك",
+ "clinicSchedule": "جدول العيادة",
+ "doctorAddedToFavourite": "تمت إضافة إلى قائمة المفضلة",
+ "doctorRemovedFromFavourite": "تمت إزالة من قائمة الأطباء المفضلين",
+ "addNewFavorite": "إضافة مفضلة جديدة",
+ "favourites": "المفضلة",
+ "pendingAncillaryOrders": "مدفوعات طلبات الاضافية",
+ "liveCarePermissions": "يتطلب لايف كير أذونات الكاميرا والميكروفون وإشعارات، يرجى السماح لها بالمتابعة.",
+ "containsImage": "يحتوي على صورة",
+ "servicesSelected": "الخدمة (الخدمات) المختارة",
+ "selectMedicalFileFromFamily": "اختر ملف طبي من عائلتك",
+ "anyFileFromHMG": "أي ملف طبي نشط من مجموعة حبيب الطبية",
+ "noDistance": "المسافة غير متوفرة",
+ "enterAmount": "يرجى إدخال المبلغ للمتابعة.",
+ "selectHospitalContinue": "يرجى اختيار المستشفى للمتابعة.",
+ "year": "سنة",
+ "notifyPrescription": "أبلغني قبل وقت الاستهلاك",
+ "doctorRatingAppointment": "طبيب\nتصنيف",
+ "ratingSubmitted": "تم إرسال التقييم",
+ "rateTheDoctor": "يرجى تقييم الطبيب",
+ "downloadInvoice": "تحميل الفاتورة",
+ "approvalDetails": "تفاصيل الموافقة",
+ "obese": "سمين",
+ "overWeight": "وزن زائد",
+ "underWeight": "وزن ناقص",
+ "nearestGate": "أقرب بوابة",
+ "RRTDDetails": "فريق الاستجابة السريعة يقوم بتقديم رعاية صحية متكاملة لجميع الحالات الطارئة و المستقرة، الخدمة تشمل جميع الأعمار بما في ذلك حالات الأطفال.",
+ "fromHospitalSubtitle": "نقل من المستشفى إلى منزلك",
"normalMapType": "افتراضي",
"satelliteMapType": "قمر صناعي",
"terrainMapType": "تضاريس",
- "hybridMapType": "هجين"
+ "hybridMapType": "هجين",
+ "openCamera": "افتح الكاميرا",
+ "openGallery": "افتح المعرض",
+ "openFiles": "فتح الملفات",
+ "generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير",
+ "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل."
}
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index 3d633713..384b16d5 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -930,7 +930,7 @@
"hospitalInformation": "Hospital Information",
"fetchingAppointmentShare": "Fetching Appointment Share...",
"bookingYourAppointment": "Booking your appointment...",
- "selectLiveCareClinic": "Select LiveCare Clinic",
+ "selectLiveCareClinic": "LiveCare Clinic",
"checkingForExistingDentalPlan": "Checking for an existing dental plan, Please wait...",
"dentalTreatmentPlan": "Dental treatment plan",
"youHaveExistingTreatmentPlan": "You have an existing treatment plan: ",
@@ -1241,7 +1241,7 @@
"quickLinks": "Quick Links",
"viewMedicalFileLandingPage": "View medical file",
"immediateLiveCareRequest": "Immediate LiveCare Request",
- "yourTurnIsAfterPatients": "Your turn is after {count} patients.",
+ "yourTurnIsAfterPatients": "Your turn is after {count} patients. Please wait for your turn, The doctor will call you shortly.",
"dontHaveHHCOrders": "You don't have any Home Health Care orders yet.",
"hhcOrders": "HHC Orders",
"requestedServices": "Requested Services",
@@ -1309,7 +1309,7 @@
"rejectedYourFamilyMemberRequest": "{status} your family member request",
"notAvailable": "N/A",
"selectAProfile": "Please select a profile",
- "switchFamilyFile": "Switch from the below list of medical file",
+ "switchFamilyFile": "Switch from the below list of medical files",
"medicalFiles": "Medical Files",
"addANewFamilyMember": "Add a new family member",
"viewInvoiceDetails": "View invoice details",
@@ -1646,8 +1646,40 @@
"twoWaySubtitle": "Round trip from location to hospital and back",
"toHospitalSubtitle": "Transfer from your current location to the hospital",
"fromHospitalSubtitle": "Transfer from the hospital back to your home",
+ "clinicSchedule": "Clinic Schedule",
+ "doctorAddedToFavourite": "Added to favorites list",
+ "doctorRemovedFromFavourite": "Removed from favorites list",
+ "favourites": "Favourites",
+ "addNewFavorite": "Add new favourite",
+ "pendingAncillaryOrders": "Pending ancillary orders",
+ "liveCarePermissions": "LiveCare requires Camera, Microphone & Notifications permissions to enable virtual consultation between patient & doctor, Open app settings to allow them.",
+ "containsImage": "Contains Image",
+ "servicesSelected": "Service(s) Selected",
+ "selectMedicalFileFromFamily": "Select a medical file from your family",
+ "anyFileFromHMG": "Any active medical file from HMG",
+ "noDistance": "Distance not available",
+ "enterAmount": "Please enter amount to continue.",
+ "selectHospitalContinue": "Please select hospital to continue.",
+ "year": "Year",
+ "notifyPrescription": "Notify me before the consumption time",
+ "doctorRatingAppointment": "Doctor\nRating",
+ "ratingSubmitted": "Rating Submitted",
+ "rateTheDoctor": "Please rate the doctor",
+ "downloadInvoice": "Download Invoice",
+ "approvalDetails": "Approval Details",
+ "obese": "Obese",
+ "overWeight": "OverWeight",
+ "underWeight": "UnderWeight",
+ "nearestGate": "Nearest Gate",
+ "RRTDDetails": "The Rapid response team provides a comprehensive medical service for all sorts of urgent and stable cases of all ages, including adult and paediatric patients.",
+ "fromHospitalSubtitle": "Transfer from the hospital back to your home",
"normalMapType": "Default",
"satelliteMapType": "Satellite",
"terrainMapType": "Terrain",
- "hybridMapType": "Hybrid"
+ "hybridMapType": "Hybrid",
+ "openCamera": "Open Camera",
+ "openGallery": "Open Gallery",
+ "openFiles": "Open Files",
+ "generateAiAnalysisRadResult": "Generate AI analysis for this result",
+ "grantLocationPermission": "Please grant location permission from app settings to see better results."
}
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index 5fb73a37..b0df11f2 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -233,6 +233,11 @@ class ApiConsts {
static String getAiOverViewLabOrders = "Services/Patients.svc/REST/HMGAI_Lab_Analyze_Orders_API";
static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
+ static String googleCloudStorageARTranslationFileURL = "https://storage.googleapis.com/hmg-patientapp-translations/ar-SA.json";
+ static String googleCloudStorageENTranslationFileURL = "https://storage.googleapis.com/hmg-patientapp-translations/en-US.json";
+
+ static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations";
+
// ************ static values for Api ****************
static final double appVersionID = 20.9;
@@ -450,6 +455,7 @@ var IS_LAST_APPOITMENT_RATED = 'Services/Doctors.svc/REST/IsLastAppoitmentRated_
var GET_APPOINTMENT_DETAILS_BY_NO = 'Services/MobileNotifications.svc/REST/GetAppointmentDetailsByApptNo';
var NEW_RATE_APPOINTMENT_URL = "Services/Doctors.svc/REST/AppointmentsRating_InsertAppointmentRate";
var NEW_RATE_DOCTOR_URL = "Services/Doctors.svc/REST/DoctorsRating_InsertDoctorRate";
+var GET_DOCTORS_RATING_CHECK = "Services/Doctors.svc/REST/GetDoctorsRatingCheck";
//var GET_QR_PARKING = 'Services/SWP.svc/REST/GetQRParkingByID';
@@ -934,6 +940,8 @@ const PROFILE_SETTING = 'Services/Patients.svc/REST/GetPateintInfoForUpdate';
const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo';
+const DOWNLOAD_INVOICE_PDF = 'Services/Notifications.svc/REST/DownloadInvoiceReport';
+
class ApiKeyConstants {
static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng';
}
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index d90cd40c..e4308bd5 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -220,6 +220,7 @@ class AppAssets {
static const String ibw = '$svgBasePath/ibw.svg';
static const String general_health = '$svgBasePath/general_health.svg';
static const String women_health = '$svgBasePath/women_health.svg';
+ static const String add_new_family_icon = '$svgBasePath/add_new_family_icon.svg';
static const String height = '$svgBasePath/height.svg';
static const String weight = '$svgBasePath/weight.svg';
@@ -236,6 +237,7 @@ class AppAssets {
static const String forward_top_nav_icon = '$svgBasePath/forward_top_nav_icon.svg';
static const String back_top_nav_icon = '$svgBasePath/back_top_nav_icon.svg';
static const String bluetooth = '$svgBasePath/bluetooth.svg';
+ static const String calendar_filled_icon = '$svgBasePath/calendar_filled_icon.svg';
//smartwatch
static const String watchActivity = '$svgBasePath/watch_activity.svg';
@@ -354,6 +356,7 @@ class AppAssets {
static const String darkModeIcon = '$svgBasePath/dark_mode_icon.svg';
static const String biometricLockIcon = '$svgBasePath/biometric_lock_icon.svg';
static const String imageIcon = '$svgBasePath/image_icon.svg';
+ static const String appointmentRatingIcon = '$svgBasePath/appointment_rating_icon.svg';
// PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png';
diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart
index 95b154ba..c56c63d4 100644
--- a/lib/core/location_util.dart
+++ b/lib/core/location_util.dart
@@ -99,7 +99,7 @@ class LocationUtils {
title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
navigationService.navigatorKey.currentContext!,
child: Utils.getWarningWidget(
- loadingText: "Please grant location permission from app settings to see better results",
+ loadingText: LocaleKeys.grantLocationPermission.tr(),
isShowActionButtons: true,
onCancelTap: () {
navigationService.pop();
@@ -124,7 +124,7 @@ class LocationUtils {
title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
navigationService.navigatorKey.currentContext!,
child: Utils.getWarningWidget(
- loadingText: "Please grant location permission from app settings to see better results",
+ loadingText: LocaleKeys.grantLocationPermission.tr(),
isShowActionButtons: true,
onCancelTap: () {
navigationService.pop();
@@ -285,7 +285,7 @@ class LocationUtils {
title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
navigationService.navigatorKey.currentContext!,
child: Utils.getWarningWidget(
- loadingText: "Please grant location permission from app settings to see better results",
+ loadingText: LocaleKeys.grantLocationPermission.tr(),
isShowActionButtons: true,
onCancelTap: () {
navigationService.pop();
diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart
index d438d449..e2925c29 100644
--- a/lib/core/utils/push_notification_handler.dart
+++ b/lib/core/utils/push_notification_handler.dart
@@ -396,10 +396,10 @@ class PushNotificationHandler {
final deviceInfo = DeviceInfoPlugin();
final androidInfo = await deviceInfo.androidInfo;
- int sdkInt = androidInfo.version.sdkInt ?? 0;
- if (sdkInt >= 33) {
- await FlutterCallkitIncoming.requestFullIntentPermission();
- }
+ // int sdkInt = androidInfo.version.sdkInt ?? 0;
+ // if (sdkInt >= 33) {
+ // await FlutterCallkitIncoming.requestFullIntentPermission();
+ // }
}
}
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index 18a8d6c8..feca055a 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -355,7 +355,7 @@ class Utils {
repeat: false, reverse: false, frameRate: FrameRate(60), width: width.w, height: height.h, fit: BoxFit.fill),
SizedBox(height: 16.h),
(noDataText ?? LocaleKeys.noDataAvailable.tr())
- .toText14(weight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true)
+ .toText14(isBold: true, color: AppColors.greyTextColor, isCenter: true)
.paddingSymmetrical(64.w, 0.h),
SizedBox(height: 16.h),
callToActionButton
@@ -371,7 +371,7 @@ class Utils {
Lottie.asset(AppAnimations.loadingAnimation,
repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
- (loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor, isCenter: true),
+ (loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor, isCenter: true, isBold: true),
SizedBox(height: 8.h),
],
).center;
@@ -384,7 +384,7 @@ class Utils {
children: [
Lottie.asset(AppAnimations.checkmark, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
- (loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor).paddingSymmetrical(24.h, 0.h),
+ (loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor, isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 8.h),
],
).center;
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 4ea8a17d..5db5b289 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -24,7 +24,7 @@ extension CapExtension on String {
extension EmailValidator on String {
Widget get toWidget => Text(this);
- Widget toText8({Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Text(
+ Widget toText8({bool isEnglishOnly = false, Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Text(
this,
maxLines: maxlines,
overflow: textOverflow,
@@ -34,6 +34,7 @@ extension EmailValidator on String {
fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: 0,
+ fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins',
),
);
@@ -60,7 +61,7 @@ extension EmailValidator on String {
color: color ?? AppColors.blackColor,
letterSpacing: letterSpacing,
decoration: isUnderLine ? TextDecoration.underline : null,
- fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins',
+ fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins',
decorationColor: color ?? AppColors.blackColor),
);
@@ -80,7 +81,7 @@ extension EmailValidator on String {
maxLines: maxlines,
overflow: textOverflow,
style: TextStyle(
- fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins',
+ fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins',
fontSize: 9.f,
fontStyle: fontStyle ?? FontStyle.normal,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
@@ -101,7 +102,7 @@ extension EmailValidator on String {
color: color ?? AppColors.blackColor,
letterSpacing: letterSpacing,
decoration: isUnderLine ? TextDecoration.underline : null,
- fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins',
+ fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins',
),
);
@@ -114,8 +115,7 @@ extension EmailValidator on String {
bool isCenter = false,
double? height,
double? letterSpacing,
- int maxLine = 0, String? fontFamily,
- }) =>
+ int maxLine = 0}) =>
Text(
this,
textAlign: isCenter ? TextAlign.center : textAlignment,
@@ -128,7 +128,7 @@ extension EmailValidator on String {
height: height,
decorationColor: isUnderLine ? AppColors.blackColor : null,
decoration: isUnderLine ? TextDecoration.underline : null,
- fontFamily:fontFamily ??( isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins',
),
);
@@ -211,7 +211,7 @@ extension EmailValidator on String {
height: height,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null,
- fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),
decorationColor: color ?? AppColors.blackColor),
);
@@ -252,14 +252,14 @@ extension EmailValidator on String {
overflow: textOverflow,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
decoration: isUnderLine ? TextDecoration.underline : null,
- fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ fontFamily: fontFamily ?? (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),
decorationColor: decorationColor ?? AppColors.errorColor),
);
Widget toText17({bool isEnglishOnly = false, Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),
);
Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow, bool isEnglishOnly = false,}) => Text(
@@ -267,7 +267,7 @@ extension EmailValidator on String {
textAlign: isCenter ? TextAlign.center : null,
this,
overflow: textOverflow,
- style: TextStyle(fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),),
+ style: TextStyle(fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),),
);
Widget toText19({Color? color, bool isBold = false}) => Text(
@@ -285,11 +285,10 @@ extension EmailValidator on String {
style: TextStyle(fontSize: 20.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
);
- Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines, bool isEnglishOnly = false}) => Text(
+ Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text(
this,
maxLines: maxlines,
- style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.f, letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
- fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins')),
+ style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.f, letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
Widget toText22({Color? color, bool isBold = false, bool isCenter = false}) => Text(
@@ -302,7 +301,7 @@ extension EmailValidator on String {
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),
height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.f, letterSpacing: letterSpacing ?? -1, fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.normal),
);
@@ -310,26 +309,26 @@ extension EmailValidator on String {
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),
height: height ?? 23 / 26, color: color ?? AppColors.blackColor, fontSize: 26.f, letterSpacing: letterSpacing ?? -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
Widget toText28({bool isEnglishOnly = false, Color? color, bool isBold = false, double? height, bool isCenter = false, double? letterSpacing}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.f, letterSpacing: letterSpacing ?? -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),
+ style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.f, letterSpacing: letterSpacing ?? -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),
);
Widget toText32({bool isEnglishOnly = false, FontWeight? weight, Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
+ height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontFamily: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
);
Widget toText44({Color? color, bool isBold = false, bool isEnglishOnly = false,}) => Text(
this,
- style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),),
+ style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins'),),
);
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {
@@ -435,7 +434,7 @@ extension DynamicTextStyleExtension on BuildContext {
String? fontFamily,
bool isLanguageSwitcher = false}) {
AppState appState = getIt.get();
- final family = appState.getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins';
+ final family = appState.getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins';
return TextStyle(
fontFamily: fontFamily ?? family,
fontSize: fontSize,
@@ -466,7 +465,7 @@ class FontUtils {
/// Get the appropriate font family for a specific language
static String getFontFamilyForLanguage(bool isArabic) {
- return isArabic ? 'GESSTwo' : 'Poppins';
+ return isArabic ? 'CairoArabic' : 'Poppins';
}
}
diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart
index de4bec62..41664758 100644
--- a/lib/features/authentication/authentication_repo.dart
+++ b/lib/features/authentication/authentication_repo.dart
@@ -667,6 +667,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future>> getPatientBloodType() async {
+ // Map requestBody = {"PatientType": 1, "PatientTypeID": 1, "TokenID": "@dm!n", "PatientID": 5957754};
Map requestBody = {};
try {
GenericApiModel? apiResponse;
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index c9917d8d..2055deea 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -101,7 +101,10 @@ class AuthenticationViewModel extends ChangeNotifier {
var healthId;
int getDeviceLastLogin = 1;
+ bool isInitialLoginNavigated = false;
+
Future onLoginPressed() async {
+ setIsInitialLoginNavigated(false);
try {
LoaderBottomSheet.showLoader();
//TODO: We will remove this delay
@@ -111,7 +114,7 @@ class AuthenticationViewModel extends ChangeNotifier {
if (data != null) {
await _handleExistingImeiData(data);
} else {
- await _handleNewImeiRegistration();
+ await handleNewImeiRegistration();
}
} catch (e) {
log("Error in onLoginPressed: $e");
@@ -199,6 +202,11 @@ class AuthenticationViewModel extends ChangeNotifier {
}
}
+ setIsInitialLoginNavigated(bool isInitialLoginNavigated) {
+ this.isInitialLoginNavigated = isInitialLoginNavigated;
+ notifyListeners();
+ }
+
void onTermAccepted() {
isTermsAccepted = !isTermsAccepted;
notifyListeners();
@@ -216,7 +224,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
}
- Future selectDeviceImei({required Function(dynamic data) onSuccess, Function(String)? onError}) async {
+ Future selectDeviceImei({bool isNavigate = true, required Function(dynamic data) onSuccess, Function(String)? onError}) async {
// LoadingUtils.showFullScreenLoading();
// String firebaseToken = _appState.deviceToken;
String firebaseToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
@@ -231,7 +239,9 @@ class AuthenticationViewModel extends ChangeNotifier {
// LoadingUtils.hideFullScreenLoader();
// await _errorHandlerService.handleError(failure: failure);
LoaderBottomSheet.hideLoader();
- _navigationService.pushPage(page: LoginScreen());
+ if (isNavigate) {
+ _navigationService.pushPage(page: LoginScreen());
+ }
},
(apiResponse) {
// LoadingUtils.hideFullScreenLoader();
@@ -263,10 +273,13 @@ class AuthenticationViewModel extends ChangeNotifier {
}
}
- Future _handleNewImeiRegistration() async {
- await selectDeviceImei(onSuccess: (dynamic respData) async {
- try {
- if (respData != null) {
+ Future handleNewImeiRegistration({bool isNavigate = true}) async {
+ print("handleNewImeiRegistration called");
+ await selectDeviceImei(
+ isNavigate: isNavigate,
+ onSuccess: (dynamic respData) async {
+ try {
+ if (respData != null) {
dynamic data = await SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
_appState.setSelectDeviceByImeiRespModelElement(data);
LoaderBottomSheet.hideLoader();
@@ -274,19 +287,24 @@ class AuthenticationViewModel extends ChangeNotifier {
// TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData =
// SelectDeviceByImeiRespModelElement.fromJson(respData);
- _navigationService.pushPage(page: SavedLogin());
- // _navigationService.pushPage(page: LoginScreen());
- } else {
- print("print login........");
- LoaderBottomSheet.hideLoader();
- _navigationService.pushPage(page: LoginScreen());
- }
- } catch (e) {
- log("Error processing IMEI registration response: $e");
- LoaderBottomSheet.hideLoader();
- _navigationService.pushPage(page: LoginScreen());
- }
- }, onError: (String error) {
+ if (!isInitialLoginNavigated) {
+ _navigationService.pushPage(page: SavedLogin());
+ }
+ // _navigationService.pushPage(page: LoginScreen());
+ } else {
+ if (isNavigate) {
+ LoaderBottomSheet.hideLoader();
+ _navigationService.pushPage(page: LoginScreen());
+ }
+ }
+ } catch (e) {
+ if (isNavigate) {
+ log("Error processing IMEI registration response: $e");
+ LoaderBottomSheet.hideLoader();
+ _navigationService.pushPage(page: LoginScreen());
+ }
+ }
+ }, onError: (String error) {
LoaderBottomSheet.hideLoader();
_dialogService.showErrorBottomSheet(message: error, onOkPressed: () {});
});
@@ -638,7 +656,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_appState.setUserBloodGroup = activation.patientBlodType ?? "N/A";
// Fetch patient blood type from new API
- await getPatientBloodTypeNew();
+ // await getPatientBloodTypeNew();
}
// _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppAuthToken = activation.authenticationTokenId;
@@ -730,6 +748,8 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future navigateToHomeScreen() async {
+ setIsInitialLoginNavigated(true);
+ getPatientBloodTypeNew();
Navigator.pushAndRemoveUntil(
_navigationService.navigatorKey.currentContext!,
CustomPageRoute(
@@ -1026,7 +1046,9 @@ class AuthenticationViewModel extends ChangeNotifier {
nationalId: _appState.getAuthenticatedUser()!.patientIdentificationNo,
gender: _appState.getAuthenticatedUser()!.gender)
.toJson());
- resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
+ resultEither.fold((failure) async {
+ // await _errorHandlerService.handleError(failure: failure);
+ }, (apiResponse) async {
if (apiResponse.messageStatus == 2) {}
if (apiResponse.messageStatus == 1) {
log("Insert Device Data Success");
@@ -1180,7 +1202,7 @@ class AuthenticationViewModel extends ChangeNotifier {
(apiResponse) {
if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
// Extract blood type from response
- String? bloodType = apiResponse.data['GetPatientBloodType'];
+ String? bloodType = apiResponse.data['GetPatientBloodType'][0]["BloodType"];
if (bloodType != null && bloodType.isNotEmpty) {
_appState.setUserBloodGroup = bloodType;
log("Blood type updated from new API: $bloodType");
diff --git a/lib/features/blood_donation/widgets/hospital_selection.dart b/lib/features/blood_donation/widgets/hospital_selection.dart
index f49b42d6..c7313228 100644
--- a/lib/features/blood_donation/widgets/hospital_selection.dart
+++ b/lib/features/blood_donation/widgets/hospital_selection.dart
@@ -26,7 +26,7 @@ class HospitalBottomSheetBodySelection extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- if(!isHideTitle) LocaleKeys.selectHospital.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.greyTextColor),
+ if(!isHideTitle) LocaleKeys.selectHospital.tr(context: context).toText16(isBold: true, color: AppColors.greyTextColor),
SizedBox(height: 16.h),
SizedBox(
height: MediaQuery.sizeOf(context).height * .4,
@@ -75,7 +75,8 @@ 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.f, color: AppColors.blackColor)),
+ child: (hospital.projectName ?? "").toString().toText16(isBold: true, color: AppColors.blackColor),
+ // Text(hospital.projectName ?? "", style: TextStyle(isBold: true, fontSize: 16.f, color: AppColors.blackColor)),
)
],
);
diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart
index 327afeb0..e43a49d5 100644
--- a/lib/features/book_appointments/book_appointments_view_model.dart
+++ b/lib/features/book_appointments/book_appointments_view_model.dart
@@ -331,6 +331,42 @@ class BookAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
+ void filterDoctors(String query) {
+ if (query.isEmpty) {
+ filteredDoctorList = List.from(doctorsList);
+ _groupDoctorsList();
+ setIsNearestAppointmentSelected(isNearestAppointmentSelected);
+ notifyListeners();
+ return;
+ }
+
+ filteredDoctorList = doctorsList.where((doctor) {
+ final name = (doctor.name ?? '').toLowerCase();
+ final clinicName = (doctor.clinicName ?? '').toLowerCase();
+ final projectName = (doctor.projectName ?? '').toLowerCase();
+ final q = query.toLowerCase();
+ return name.contains(q) || clinicName.contains(q) || projectName.contains(q);
+ }).toList();
+
+ // Re-group filtered list
+ final clinicMap = >{};
+ final hospitalMap = >{};
+
+ for (var doctor in filteredDoctorList) {
+ final clinicKey = (doctor.clinicName ?? 'Unknown').trim();
+ clinicMap.putIfAbsent(clinicKey, () => []).add(doctor);
+
+ final hospitalKey = (doctor.projectName ?? 'Unknown').trim();
+ hospitalMap.putIfAbsent(hospitalKey, () => []).add(doctor);
+ }
+
+ doctorsListByClinic = clinicMap.values.toList();
+ doctorsListByHospital = hospitalMap.values.toList();
+ doctorsListGrouped = isSortByClinic ? doctorsListByClinic : doctorsListByHospital;
+
+ notifyListeners();
+ }
+
void filterClinics(String? query) {
if (query!.isEmpty) {
_filteredClinicsList = List.from(clinicsList);
@@ -821,8 +857,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
initialSlotDuration = apiResponse.data["InitialSlotDuration"];
freeSlotsResponse = apiResponse.data['FreeTimeSlots'];
- isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
- // isWaitingAppointmentAvailable = true;
+ // isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
+ isWaitingAppointmentAvailable = true;
freeSlotsResponse.forEach((element) {
// date = (isLiveCareSchedule != null && isLiveCareSchedule)
diff --git a/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart b/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart
index 75ed1229..a9aa273e 100644
--- a/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart
+++ b/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart
@@ -193,7 +193,7 @@ class DoctorsListResponseModel {
serviceID = json['ServiceID'];
setupID = json['SetupID'];
speciality = json['Speciality'] != null ? json['Speciality'].cast() : [];
- // specialityN = json['SpecialityN'].cast();
+ specialityN = json['SpecialityN'] != null ? json['SpecialityN'].cast() : [];
transactionType = json['TransactionType'];
virtualEmploymentType = json['VirtualEmploymentType'];
workingHours = json['WorkingHours'];
diff --git a/lib/features/hmg_services/models/ui_models/vital_sign_ui_model.dart b/lib/features/hmg_services/models/ui_models/vital_sign_ui_model.dart
index 66f5d77b..90c513c4 100644
--- a/lib/features/hmg_services/models/ui_models/vital_sign_ui_model.dart
+++ b/lib/features/hmg_services/models/ui_models/vital_sign_ui_model.dart
@@ -1,4 +1,6 @@
+import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
/// UI-only helper model for Vital Sign cards.
@@ -49,7 +51,7 @@ class VitalSignUiModel {
}
// Warning for both low and overweight/underweight BMI, since they can indicate potential health issues.
- if (s.contains('low') || s.contains('underweight') || s.contains('overweight')) {
+ if (s.contains('low') || s.contains("OverWeight") || s.contains("وزن زائد") || s.contains("UnderWeight") || s.contains("وزن ناقص")) {
final Color yellowBg = AppColors.highAndLow.withValues(alpha: 0.12);
return VitalSignUiModel(
iconBg: yellowBg,
@@ -96,13 +98,13 @@ class VitalSignUiModel {
final double bmiResult = double.tryParse(bmi.toString()) ?? 0;
if (bmiResult >= 30) {
- bmiStatus = "High";
+ bmiStatus = LocaleKeys.obese.tr();
} else if (bmiResult < 30 && bmiResult >= 25) {
- bmiStatus = "Overweight";
+ bmiStatus = LocaleKeys.overWeight.tr();
} else if (bmiResult < 25 && bmiResult >= 18.5) {
- bmiStatus = "Normal";
+ bmiStatus = LocaleKeys.normal.tr();
} else if (bmiResult < 18.5) {
- bmiStatus = "Underweight";
+ bmiStatus = LocaleKeys.underWeight.tr();
}
// if (bmi == null) return 'N/A';
diff --git a/lib/features/immediate_livecare/immediate_livecare_repo.dart b/lib/features/immediate_livecare/immediate_livecare_repo.dart
index cbce4ea2..8775378b 100644
--- a/lib/features/immediate_livecare/immediate_livecare_repo.dart
+++ b/lib/features/immediate_livecare/immediate_livecare_repo.dart
@@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
+import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart';
@@ -13,6 +14,9 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class ImmediateLiveCareRepo {
Future>>> getLiveCareImmediateClinicsList(int age, int genderID, {Function(dynamic)? onSuccess, Function(String)? onError});
+ Future>>> getLiveCareImmediateClinicSchedule(int age, int genderID, int serviceID,
+ {Function(dynamic)? onSuccess, Function(String)? onError});
+
Future>> getLiveCareImmediateAppointmentFees(int age, int genderID, int serviceID,
{Function(dynamic)? onSuccess, Function(String)? onError});
@@ -203,4 +207,47 @@ class ImmediateLiveCareRepoImp implements ImmediateLiveCareRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>>> getLiveCareImmediateClinicSchedule(int age, int genderID, int serviceID,
+ {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
+ Map mapDevice = {
+ "Age": age,
+ "Gender": genderID,
+ "ServiceID": serviceID,
+ };
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_LIVECARE_CLINIC_TIMING,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ // onError!(error);
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final respObject = response['PatientER_GetClinicsServiceTimingsList'];
+ final liveCareScheduleObj = respObject.map((item) => LiveCareClinicScheduleResponse.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: liveCareScheduleObj,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/immediate_livecare/immediate_livecare_view_model.dart b/lib/features/immediate_livecare/immediate_livecare_view_model.dart
index 46f5a652..6613b481 100644
--- a/lib/features/immediate_livecare/immediate_livecare_view_model.dart
+++ b/lib/features/immediate_livecare/immediate_livecare_view_model.dart
@@ -11,6 +11,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_repo.dart';
+import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_patient_livecare_history_response_model.dart';
@@ -46,6 +47,8 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
List patientLiveCareHistoryList = [];
bool patientHasPendingLiveCareRequest = false;
+ List liveCareClinicScheduleList = [];
+
late AppState _appState;
Duration countdownDuration = Duration(minutes: 1, seconds: 0);
@@ -265,6 +268,33 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
);
}
+ Future getLiveCareImmediateClinicSchedule({int? serviceID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ liveCareClinicScheduleList.clear();
+ notifyListeners();
+
+ final result =
+ await immediateLiveCareRepo.getLiveCareImmediateClinicSchedule(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!, serviceID!);
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ liveCareClinicScheduleList = apiResponse.data!;
+
+ // immediateLiveCareClinicsList.sort((a, b) => b.isOnline!.compareTo(a.isOnline!));
+
+ // isImmediateLiveCareClinicsLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
void startTimer() {
timer = Timer.periodic(const Duration(seconds: 1), (_) => addTime());
notifyListeners();
diff --git a/lib/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart b/lib/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart
new file mode 100644
index 00000000..787167de
--- /dev/null
+++ b/lib/features/immediate_livecare/models/resp_models/get_livecare_clinic_schedule_response_model.dart
@@ -0,0 +1,71 @@
+class LiveCareClinicScheduleResponse {
+ int? iD;
+ int? serviceID;
+ int? dayOfWeek;
+ String? dayOfWeekStr;
+ bool? isActive;
+ String? createdOn;
+ String? createdBy;
+ bool? projectOutSA;
+ String? dayOfWeekStrN;
+ List? shiftTimings;
+
+ LiveCareClinicScheduleResponse({this.iD, this.serviceID, this.dayOfWeek, this.dayOfWeekStr, this.isActive, this.createdOn, this.createdBy, this.projectOutSA, this.dayOfWeekStrN, this.shiftTimings});
+
+ LiveCareClinicScheduleResponse.fromJson(Map json) {
+ iD = json['ID'];
+ serviceID = json['ServiceID'];
+ dayOfWeek = json['DayOfWeek'];
+ dayOfWeekStr = json['DayOfWeekStr'];
+ isActive = json['IsActive'];
+ createdOn = json['CreatedOn'];
+ createdBy = json['CreatedBy'];
+ projectOutSA = json['ProjectOutSA'];
+ dayOfWeekStrN = json['DayOfWeekStrN'];
+ if (json['ShiftTimings'] != null) {
+ shiftTimings = [];
+ json['ShiftTimings'].forEach((v) {
+ shiftTimings!.add(new ShiftTimings.fromJson(v));
+ });
+ }
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ID'] = this.iD;
+ data['ServiceID'] = this.serviceID;
+ data['DayOfWeek'] = this.dayOfWeek;
+ data['DayOfWeekStr'] = this.dayOfWeekStr;
+ data['IsActive'] = this.isActive;
+ data['CreatedOn'] = this.createdOn;
+ data['CreatedBy'] = this.createdBy;
+ data['ProjectOutSA'] = this.projectOutSA;
+ data['DayOfWeekStrN'] = this.dayOfWeekStrN;
+ if (this.shiftTimings != null) {
+ data['ShiftTimings'] = this.shiftTimings!.map((v) => v.toJson()).toList();
+ }
+ return data;
+ }
+}
+
+class ShiftTimings {
+ String? endTime;
+ int? shiftID;
+ String? startTime;
+
+ ShiftTimings({this.endTime, this.shiftID, this.startTime});
+
+ ShiftTimings.fromJson(Map json) {
+ endTime = json['EndTime'];
+ shiftID = json['ShiftID'];
+ startTime = json['StartTime'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['EndTime'] = this.endTime;
+ data['ShiftID'] = this.shiftID;
+ data['StartTime'] = this.startTime;
+ return data;
+ }
+}
diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart
index fb80ca00..6835badb 100644
--- a/lib/features/lab/lab_view_model.dart
+++ b/lib/features/lab/lab_view_model.dart
@@ -848,6 +848,9 @@ class LabViewModel extends ChangeNotifier {
Future getAiOverviewLabOrders({required PatientLabOrdersResponseModel labOrder, required String loadingText}) async {
// LoadingUtils.showFullScreenLoader(loadingText: "Loading and analysing your data,\nPlease be patient and let the AI do the magic. \nPlease be patient, This might take some time.");
// LoadingUtils.showFullScreenLoader(loadingText: loadingText);
+ isLabAIAnalysisNeedsToBeShown = true;
+ notifyListeners();
+
LoaderBottomSheet.showLoader(
loadingText: loadingText,
showCloseButton: true,
@@ -875,26 +878,29 @@ class LabViewModel extends ChangeNotifier {
final result = await labRepo.getPatientAiOverViewLabOrders(results);
result.fold(
(failure) async {
- LoadingUtils.hideFullScreenLoader();
+ LoaderBottomSheet.hideLoader();
if (isLabAIAnalysisNeedsToBeShown) {
await errorHandlerService.handleError(failure: failure);
}
},
(apiResponse) {
- LoadingUtils.hideFullScreenLoader();
+ LoaderBottomSheet.hideLoader();
if (apiResponse.messageStatus == 2) {
} else if (apiResponse.messageStatus == 1) {
if (isLabAIAnalysisNeedsToBeShown) {
labOrdersResponseByAi = apiResponse.data;
navigationService.push(
- MaterialPageRoute(builder: (_) => LabAiAnalysisDetailedPage()),
+ CustomPageRoute(
+ direction: AxisDirection.down,
+ page: LabAiAnalysisDetailedPage(),
+ ),
);
}
}
},
);
- LoadingUtils.hideFullScreenLoader();
+ // LoadingUtils.hideFullScreenLoader();
}
Future getAiOverviewSingleLabResult({required String langId, required LabResult recentLabResult, required String loadingText}) async {
diff --git a/lib/features/my_appointments/models/resp_models/appointment_rated_response_model.dart b/lib/features/my_appointments/models/resp_models/appointment_rated_response_model.dart
new file mode 100644
index 00000000..2096a1e1
--- /dev/null
+++ b/lib/features/my_appointments/models/resp_models/appointment_rated_response_model.dart
@@ -0,0 +1,30 @@
+class AppointmentRatedResponseModel {
+ int? appointmentNo;
+ int? clinicID;
+ int? doctorID;
+ bool? isAllowedToRate;
+ bool? isAppointmentRated;
+ int? projectID;
+
+ AppointmentRatedResponseModel({this.appointmentNo, this.clinicID, this.doctorID, this.isAllowedToRate, this.isAppointmentRated, this.projectID});
+
+ AppointmentRatedResponseModel.fromJson(Map json) {
+ appointmentNo = json['AppointmentNo'];
+ clinicID = json['ClinicID'];
+ doctorID = json['DoctorID'];
+ isAllowedToRate = json['IsAllowedToRate'];
+ isAppointmentRated = json['IsAppointmentRated'];
+ projectID = json['ProjectID'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['AppointmentNo'] = this.appointmentNo;
+ data['ClinicID'] = this.clinicID;
+ data['DoctorID'] = this.doctorID;
+ data['IsAllowedToRate'] = this.isAllowedToRate;
+ data['IsAppointmentRated'] = this.isAppointmentRated;
+ data['ProjectID'] = this.projectID;
+ return data;
+ }
+}
diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart
index 4c7c41e2..45c28c45 100644
--- a/lib/features/my_appointments/my_appointments_repo.dart
+++ b/lib/features/my_appointments/my_appointments_repo.dart
@@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_favorite_doctors_list.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/appointment_rated_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/rate_appointment_resp_model.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/get_tamara_installments_details_response_model.dart';
@@ -81,6 +82,13 @@ abstract class MyAppointmentsRepo {
Future>> convertPatientToCash({required int projectID});
Future>> sendPatientUpdateRequest();
+
+ Future>> getDoctorsRatingCheck({
+ required int doctorID,
+ required int projectID,
+ required int clinicID,
+ required int appointmentNo,
+ });
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@@ -1077,4 +1085,50 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>> getDoctorsRatingCheck({
+ required int doctorID,
+ required int projectID,
+ required int clinicID,
+ required int appointmentNo,
+ }) async {
+ Map mapDevice = {
+ "DoctorID": doctorID,
+ "ProjectID": projectID,
+ "ClinicID": clinicID,
+ "AppointmentNo": appointmentNo,
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_DOCTORS_RATING_CHECK,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ AppointmentRatedResponseModel appointmentRatedResponseModel = AppointmentRatedResponseModel.fromJson(response['DoctorsRatingResponseModel'][0]);
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: appointmentRatedResponseModel,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index a1c48867..6ba27522 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -7,6 +7,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/features/book_appointments/models/resp_models/get_favorite_doctors_list.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/appointemnet_filters.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/appointment_rated_response_model.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/get_tamara_installments_details_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
@@ -87,6 +88,11 @@ class MyAppointmentsViewModel extends ChangeNotifier {
bool isShowNotEligibleDialog = false;
String notEligibleErrorMsg = "";
+ bool isAppointmentAlreadyRated = false;
+
+ AppointmentRatedResponseModel? appointmentRatedResponseModel;
+ bool isAppointmentRatedResponseLoading = false;
+
MyAppointmentsViewModel({required this.myAppointmentsRepo, required this.errorHandlerService, required this.appState});
void onTabChange(int index) {
@@ -670,9 +676,9 @@ class MyAppointmentsViewModel extends ChangeNotifier {
Future getPatientFavouriteDoctors({bool forceRefresh = false, Function(dynamic)? onSuccess, Function(String)? onError}) async {
// If data is already fetched and not forcing refresh, skip API call
- if (isFavouriteDoctorsDataFetched && !forceRefresh) {
- return;
- }
+ // if (isFavouriteDoctorsDataFetched && !forceRefresh) {
+ // return;
+ // }
isPatientFavouriteDoctorsLoading = true;
patientFavouriteDoctorsList.clear();
@@ -995,4 +1001,79 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
+
+ Future getDoctorsRatingCheck({
+ required int doctorID,
+ required int projectID,
+ required int clinicID,
+ required int appointmentNo,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ isAppointmentRatedResponseLoading = true;
+ notifyListeners();
+
+ final result = await myAppointmentsRepo.getDoctorsRatingCheck(
+ doctorID: doctorID,
+ projectID: projectID,
+ clinicID: clinicID,
+ appointmentNo: appointmentNo,
+ );
+
+ result.fold(
+ (failure) async {
+ // await errorHandlerService.handleError(failure: failure);
+ if (onError != null) onError(failure.message);
+ isAppointmentRatedResponseLoading = false;
+ notifyListeners();
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ if (onError != null) onError(apiResponse.errorMessage ?? "Unknown error");
+ isAppointmentRatedResponseLoading = false;
+ notifyListeners();
+ } else if (apiResponse.messageStatus == 1) {
+ appointmentRatedResponseModel = apiResponse.data!;
+ isAppointmentRatedResponseLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse.data);
+ }
+ }
+ },
+ );
+ }
+
+ Future submitDoctorRating(
+ {required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ required int docRate,
+ required String docNote,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError}) async {
+ final result = await myAppointmentsRepo.sendDoctorRate(
+ docRate,
+ patientAppointmentHistoryResponseModel.appointmentNo!,
+ patientAppointmentHistoryResponseModel.projectID!,
+ patientAppointmentHistoryResponseModel.doctorID!,
+ patientAppointmentHistoryResponseModel.clinicID!,
+ docNote,
+ patientAppointmentHistoryResponseModel.appointmentDate!,
+ patientAppointmentHistoryResponseModel.doctorNameObj!,
+ patientAppointmentHistoryResponseModel.projectName!,
+ patientAppointmentHistoryResponseModel.clinicName!);
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError?.call(apiResponse.errorMessage ?? 'Unknown error');
+ } else if (apiResponse.messageStatus == 1) {
+ notifyListeners();
+ if (onSuccess != null) {
+ // onSuccess(apiResponse.data);
+ }
+ }
+ },
+ );
+ }
}
diff --git a/lib/features/my_invoices/my_invoices_repo.dart b/lib/features/my_invoices/my_invoices_repo.dart
index 68eee6e5..79136ba0 100644
--- a/lib/features/my_invoices/my_invoices_repo.dart
+++ b/lib/features/my_invoices/my_invoices_repo.dart
@@ -13,6 +13,8 @@ abstract class MyInvoicesRepo {
Future>> getInvoiceDetails({required num appointmentNo, required num invoiceNo, required int projectID});
Future>> sendInvoiceEmail({required num appointmentNo, required int projectID});
+
+ Future>> downloadInvoice({required String setupId, required int invoiceNo, required int projectID});
}
class MyInvoicesRepoImp implements MyInvoicesRepo {
@@ -138,4 +140,42 @@ class MyInvoicesRepoImp implements MyInvoicesRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future> downloadInvoice({required String setupId, required int invoiceNo, required int projectID}) async {
+ Map mapDevice = {
+ "SetupID": setupId,
+ "ProjectID": projectID,
+ "InvoiceNo": invoiceNo,
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ DOWNLOAD_INVOICE_PDF,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response["InvoiceReportPDFContent"],
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/my_invoices/my_invoices_view_model.dart b/lib/features/my_invoices/my_invoices_view_model.dart
index d51ea086..cd18026c 100644
--- a/lib/features/my_invoices/my_invoices_view_model.dart
+++ b/lib/features/my_invoices/my_invoices_view_model.dart
@@ -26,6 +26,8 @@ class MyInvoicesViewModel extends ChangeNotifier {
TextEditingController filterSearchController = TextEditingController();
String? selectedFilterItem;
+ String? downloadInvoicePDFBase64 = "";
+
MyInvoicesViewModel({required this.myInvoicesRepo, required this.errorHandlerService, required this.navServices});
setInvoicesListLoading() {
@@ -68,7 +70,6 @@ class MyInvoicesViewModel extends ChangeNotifier {
Future getInvoiceDetails({required num appointmentNo, required num invoiceNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myInvoicesRepo.getInvoiceDetails(appointmentNo: appointmentNo, invoiceNo: invoiceNo, projectID: projectID);
-
result.fold(
(failure) async {
isInvoiceDetailsLoading = false;
@@ -93,6 +94,32 @@ class MyInvoicesViewModel extends ChangeNotifier {
);
}
+ Future downloadInvoicePDF({required String setupId, required int invoiceNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await myInvoicesRepo.downloadInvoice(setupId: setupId, invoiceNo: invoiceNo, projectID: projectID);
+
+ result.fold(
+ (failure) async {
+ if (onError != null) {
+ onError(failure.message);
+ }
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ if (apiResponse.data != null && apiResponse.data!.isNotEmpty) {
+ downloadInvoicePDFBase64 = apiResponse.data!;
+ } else {
+ downloadInvoicePDFBase64 = "";
+ }
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
Future sendInvoiceEmail({required num appointmentNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myInvoicesRepo.sendInvoiceEmail(appointmentNo: appointmentNo, projectID: projectID);
diff --git a/lib/features/symptoms_checker/symptoms_checker_repo.dart b/lib/features/symptoms_checker/symptoms_checker_repo.dart
index 33bcbd8f..7fee030b 100644
--- a/lib/features/symptoms_checker/symptoms_checker_repo.dart
+++ b/lib/features/symptoms_checker/symptoms_checker_repo.dart
@@ -54,6 +54,7 @@ abstract class SymptomsCheckerRepo {
Future>>> getClinicDetails({
required String categoryName,
+ required String language,
required String userSessionToken,
});
}
@@ -400,6 +401,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
@override
Future>>> getClinicDetails({
required String categoryName,
+ required String language,
required String userSessionToken,
}) async {
Map headers = {
@@ -413,7 +415,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
Failure? failure;
await apiClient.get(
- "${ApiConsts.getClinicFromCondition}$categoryName",
+ "${ApiConsts.getClinicFromCondition}$categoryName&language=$language",
apiHeaders: headers,
isExternal: true,
isAllowAny: true,
diff --git a/lib/features/symptoms_checker/symptoms_checker_view_model.dart b/lib/features/symptoms_checker/symptoms_checker_view_model.dart
index 215b6921..d06b2538 100644
--- a/lib/features/symptoms_checker/symptoms_checker_view_model.dart
+++ b/lib/features/symptoms_checker/symptoms_checker_view_model.dart
@@ -1079,6 +1079,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
final result = await symptomsCheckerRepo.getClinicDetails(
categoryName: categoryName,
+ language: appState.isArabic() ? 'ar' : 'en',
userSessionToken: currentSessionAuthToken,
);
diff --git a/lib/features/todo_section/todo_section_view_model.dart b/lib/features/todo_section/todo_section_view_model.dart
index 0f6cc873..b14e4ead 100644
--- a/lib/features/todo_section/todo_section_view_model.dart
+++ b/lib/features/todo_section/todo_section_view_model.dart
@@ -13,13 +13,13 @@ class TodoSectionViewModel extends ChangeNotifier {
String? notificationsCount = "0";
initializeTodoSectionViewModel() async {
- if (isAncillaryOrdersNeedReloading) {
- patientAncillaryOrdersList.clear();
- isAncillaryOrdersLoading = true;
+ // if (isAncillaryOrdersNeedReloading) {
+ patientAncillaryOrdersList.clear();
+ isAncillaryOrdersLoading = true;
isAncillaryDetailsProceduresLoading = true;
notificationsCount = "0";
getPatientOnlineAncillaryOrderList();
- }
+ // }
getPatientDashboard();
}
@@ -63,13 +63,14 @@ class TodoSectionViewModel extends ChangeNotifier {
}
Future getPatientOnlineAncillaryOrderList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
- if (!isAncillaryOrdersNeedReloading) {
- return;
- }
+ // if (!isAncillaryOrdersNeedReloading) {
+ // return;
+ // }
patientAncillaryOrdersList.clear();
isAncillaryOrdersLoading = true;
notifyListeners();
+
final result = await todoSectionRepo.getOnlineAncillaryOrderList();
result.fold(
diff --git a/lib/features/translations/custom_asset_loader.dart b/lib/features/translations/custom_asset_loader.dart
new file mode 100644
index 00000000..8cf9e7c9
--- /dev/null
+++ b/lib/features/translations/custom_asset_loader.dart
@@ -0,0 +1,27 @@
+import 'dart:convert';
+import 'dart:io';
+import 'dart:ui';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/services.dart';
+import 'package:path_provider/path_provider.dart';
+
+class RemoteFileLoader extends AssetLoader {
+ @override
+ Future