diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0e1749d6..fef05b1a 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -39,7 +39,6 @@
-
@@ -52,7 +51,7 @@
-
+
diff --git a/assets/images/png/ambulance_section.png b/assets/images/png/ambulance_section.png
new file mode 100644
index 00000000..62ca1716
Binary files /dev/null and b/assets/images/png/ambulance_section.png differ
diff --git a/assets/images/png/female_bmi.png b/assets/images/png/female_bmi.png
new file mode 100644
index 00000000..437f1dc1
Binary files /dev/null and b/assets/images/png/female_bmi.png differ
diff --git a/assets/images/png/rrt_section.png b/assets/images/png/rrt_section.png
new file mode 100644
index 00000000..b28d5993
Binary files /dev/null and b/assets/images/png/rrt_section.png differ
diff --git a/assets/images/svg/bfc.svg b/assets/images/svg/bfc.svg
new file mode 100644
index 00000000..a6d2ef3a
--- /dev/null
+++ b/assets/images/svg/bfc.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/bmi1.svg b/assets/images/svg/bmi1.svg
new file mode 100644
index 00000000..c957dc8e
--- /dev/null
+++ b/assets/images/svg/bmi1.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/bmr1.svg b/assets/images/svg/bmr1.svg
new file mode 100644
index 00000000..7e403a81
--- /dev/null
+++ b/assets/images/svg/bmr1.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/cloudy_weather.svg b/assets/images/svg/cloudy_weather.svg
new file mode 100644
index 00000000..bc7d54bf
--- /dev/null
+++ b/assets/images/svg/cloudy_weather.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/images/svg/cloudyweather.svg b/assets/images/svg/cloudyweather.svg
new file mode 100644
index 00000000..6f8ebb47
--- /dev/null
+++ b/assets/images/svg/cloudyweather.svg
@@ -0,0 +1,49 @@
+
+
+
diff --git a/assets/images/svg/ddc.svg b/assets/images/svg/ddc.svg
new file mode 100644
index 00000000..f671baf8
--- /dev/null
+++ b/assets/images/svg/ddc.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/document.svg b/assets/images/svg/document.svg
new file mode 100644
index 00000000..5073ead5
--- /dev/null
+++ b/assets/images/svg/document.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/evening.svg b/assets/images/svg/evening.svg
new file mode 100644
index 00000000..7932d78d
--- /dev/null
+++ b/assets/images/svg/evening.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/images/svg/ibwc.svg b/assets/images/svg/ibwc.svg
new file mode 100644
index 00000000..acfba187
--- /dev/null
+++ b/assets/images/svg/ibwc.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/location_unavailable_filled.svg b/assets/images/svg/location_unavailable_filled.svg
new file mode 100644
index 00000000..8bc315c1
--- /dev/null
+++ b/assets/images/svg/location_unavailable_filled.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/location_unavailable_filled_background.svg b/assets/images/svg/location_unavailable_filled_background.svg
new file mode 100644
index 00000000..cb3fa768
--- /dev/null
+++ b/assets/images/svg/location_unavailable_filled_background.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/svg/morning.svg b/assets/images/svg/morning.svg
new file mode 100644
index 00000000..0f0d9904
--- /dev/null
+++ b/assets/images/svg/morning.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/images/svg/op.svg b/assets/images/svg/op.svg
new file mode 100644
index 00000000..ff400de8
--- /dev/null
+++ b/assets/images/svg/op.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/images/svg/report.svg b/assets/images/svg/report.svg
new file mode 100644
index 00000000..b5ca54b1
--- /dev/null
+++ b/assets/images/svg/report.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/images/svg/sucess.svg b/assets/images/svg/sucess.svg
new file mode 100644
index 00000000..6df93d5e
--- /dev/null
+++ b/assets/images/svg/sucess.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/svg/whitecalender.svg b/assets/images/svg/whitecalender.svg
new file mode 100644
index 00000000..ff400de8
--- /dev/null
+++ b/assets/images/svg/whitecalender.svg
@@ -0,0 +1,8 @@
+
diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 08adc616..72199078 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -2,18 +2,18 @@
"english": "الإنجليزية",
"arabic": "العربية",
"login": "تسجيل الدخول",
- "noDataAvailable": "لا توجد بيانات متاحة",
+ "noDataAvailable": "لا توجد طلبات",
"noRatingAvailable": "لا يوجد تقييم متاح",
"doctorDoesNotHaveRating": "لم يحصل هذا الطبيب على أي تقييمات بعد.",
"confirm": "تأكيد",
- "loadingText": "جاري التحميل، يرجى الانتظار...",
+ "loadingText": "يرجى الانتظار…",
"kilometerUnit": "كم",
"dashboardScreenToolbarTitle": "الرئيسية",
"settings": "الإعدادات",
"language": "لغة التطبيق",
"lanEnglish": "الإنجليزية",
"lanArabic": "العربية",
- "cancel": "إلغاء",
+ "cancel": "لا",
"done": "تم",
"replay2": "إعادة التشغيل",
"home": "الرئيسية",
@@ -40,7 +40,7 @@
"noResultFound": "لم يتم العثور على نتائج",
"noSearchResultFound": "لم يتم العثور على نتائج",
"pleaseEnterProductName": "يرجى إدخال اسم المنتج",
- "bookNow": "احجز الآن",
+ "bookNow": "حجز موعد",
"docInfo": "معلومات الطبيب",
"appoInfo": "معلومات الموعد",
"availableAppo": "المواعيد المتاحة",
@@ -68,8 +68,8 @@
"appoActions": "إجراءات الموعد",
"date": "التاريخ",
"time": "الوقت",
- "pendingPayment": "معلق للدفع",
- "payNow": "ادفع الآن",
+ "pendingPayment": "إتمام الدفع",
+ "payNow": "الدفع",
"viewQR": "عرض رمز الاستجابة السريعة",
"instruction": "تعليمات",
"livecare": "لايف كير",
@@ -81,8 +81,10 @@
"upcomingNoAction": "لا يتطلب أي إجراء",
"upcomingConfirm": "يرجى تأكيد الموعد لتجنب الإلغاء",
"bookSuccessConfirmMore2412": "ستكون عملية الدفع عبر الإنترنت متاحة قبل 24 ساعة ��ن الموعد.",
- "upcomingPaymentPending": "سيتم تفعيل الدفع عبر الإنترنت قبل 24 ساعة من موعد الموعد",
- "upcomingPaymentNow": "ادفع عبر الإنترنت الآن لتجنب الانتظار الطويل",
+ "upcomingPaymentPending": "سيتم تفعيل الدفع عبر الإنترنت قبل 24 ساعة من وقت الموعد",
+ "upcomingPaymentNow": "الدفع الإلكتروني لتجنب الانتظار",
+ "timeUntilAppointment": "الوقت المتبقي حتى الموعد",
+ "appointmentTimePassed": "انتهى وقت الموعد",
"upcomingQR": "استخدم رمز الاستجابة السريعة لتسجيل الوصول في المستشفى",
"upcomingVirtual": "هذا موعد افتراضي، يرجى الالتزام بالتعليمات لتجربة سلسة.",
"upcomingLivecare": "هذا موعد لايف كير",
@@ -91,15 +93,15 @@
"raise": "رفع",
"complaint": "شكوى",
"add": "إضافة",
- "reminder": "تذكير",
+ "reminder": "حفظ",
"location": "المواقع",
- "online": "عبر الإنترنت",
+ "online": "متصل",
"payment": "الدفع",
"onlinePayment": "عبر الإنترنت",
"onlinePaymentSubtitle": "الدفع",
- "cancelNocaps": "إلغاء",
- "setReminder": "ضبط تذكير",
- "nationalIdNumber": "رقم الهوية الوطنية",
+ "cancelNocaps": "الاحتفاظ بالموعد",
+ "setReminder": "تذكير",
+ "nationalIdNumber": "رقم الهوية / الإقام",
"medicalFileNumber": "رقم الملف الطبي",
"loginregister": "تسجيل الدخول / التسجيل",
"poweredBy": "مدعوم من",
@@ -112,7 +114,7 @@
"yes": "نعم",
"no": "لا",
"logintyperadio": "اختر من الخيارات أدناه لتسجيل الدخول إلى ملفك الطبي.",
- "registernow": "سجل الآن",
+ "registernow": "تسجيل",
"nationalID": "أدخل رقم الهوية",
"nationalId": "الهوية الوطنية",
"fileNo": "رقم الملف",
@@ -121,10 +123,10 @@
"forgotFileNoTitle": "نسيت الملف الطبي",
"enterNationalId": "يرجى إدخال رقم الهاتف المحمول ورقم الهوية",
"profileInfo": "يرجى إدخال معلومات الملف الشخصي",
- "submit": "إرسال",
+ "submit": "تحديث",
"forgotDesc": "أدخل رقم الهاتف المحمول لاستلام رقم الملف الطبي عبر الرسائل القصيرة",
- "dob": "تاريخ الميلاد:",
- "hijriDate": "الت��ريخ الهجري",
+ "dob": "تاريخ الميلاد",
+ "hijriDate": "التاريخ الهجري",
"gregorianDate": "التاريخ الميلادي",
"verifyLoginWith": "يرجى اختيار واحدة من الخيارات التالية للتحقق",
"registerUser": "تسجيل",
@@ -171,12 +173,12 @@
"emailSentError": "خطأ في إرسال البريد الإلكتروني",
"close": "إغلاق",
"closeIt": "أغلق",
- "booked": "محجوز",
+ "booked": "تم الحجز",
"confirmed": "مؤكد",
- "arrived": "وصل",
+ "arrived": " تم الوصول",
"payNowBookSuccess": "ادفع الآن عبر تطبيق الحبيب",
"payNowBookSuccesstext1": "ادفع الآن باستخدام خدمة الدفع عبر الإنترنت من بوابات الدفع الآمنة",
- "payNowBookSuccesstext2": "يمكنك أيضًا الدفع لاحقًا عبر الدفع الإلكتروني أو في المستشفى.",
+ "payNowBookSuccesstext2": "يمكنك أيضًا الدفع لاحقًا عبر الدفع الإلكت§روني أو في المستشفى.",
"payLater": "ادفع لاحقًا",
"askDocNotAllowed": "هذه الخدمة ستكون متاحة فقط لزيارة الطبيب قبل 15 يومًا",
"moreVerify": "خيارات تحقق إضافية",
@@ -196,6 +198,7 @@
"enterEmail": "يرجى إدخال البريد الإلكتروني",
"family": "عائلتي",
"familyTitle": "ملفات عائلتي",
+ "familyTitle2": "ملفات العائلة",
"myFamily": "عائلتي",
"addNewMember": "إضافة فرد جديد للعائلة",
"sentRequests": "الطلبات المرسلة",
@@ -214,9 +217,9 @@
"heightUnit": "وحدة الطول",
"weightUnit": "وحدة الوزن",
"unit": "الوحدة",
- "request": "طلب",
+ "request": "الطلبات",
"memberName": "اسم العضو",
- "switchLogin": "تبديل",
+ "switchLogin": "عرض",
"removeMember": "إزالة",
"allowView": "السماح",
"rejectView": "رفض",
@@ -269,12 +272,13 @@
"userViewRequester": "يريد المستخدم عرض ملفك الطبي",
"userView": "يمكن للمستخدم عرض ملفك الطبي",
"parking": "موقف السيارات",
+ "parking2": " المواقف",
"alhabiServices": "خدمة HMG",
"parkingTitle": "خدمة السيارة، خدمة السيارة، خدمة لحفظ معلومات الموقف، العودة إليها لاحقًا، 1- من خلال النقر على (قراءة الرمز)، حفظ بيانات الموقف. 2- من خلال النقر على زر (عرض موقف سيارتي)، يظهر لك موقع السيارة في خرائط Google. 3- قراءة موضع آخر بالضغط على زر مسح بيانات الموضع.",
"parkingDescription": "خدمة المواقف هي لك لمسح موقع السيارة حتى تتمكن من العثور عليها بسهولة عند مغادرتك. انقر على زر (مسح الموقف) لحفظ موقع الموقف، ثم سيظهر زر (عرض موقفي) لإظهار الطريق إلى الموقف. إذا كنت ترغب في إعادة مسح موقف السيارة QR فقط انقر على (مسح بياناتي).",
"appointments": "المواعيد",
"all2": "الكل",
- "checkinOption": "تسجيل الوصول",
+ "checkinOption": "تسجيل الحضور",
"readBarcode": "قراءة الكود",
"showMyPark": "عرض الموقف",
"clearMyData": "امسح البيانات",
@@ -287,7 +291,7 @@
"locationa": "الموقع",
"callNow": "اتصل الآن",
"ambulancerequest": "طلب إسعاف",
- "requestA": "طلب",
+ "requestA": "الطلبات",
"noBookedAppointments": "لا توجد مواعيد محجوزة",
"noConfirmedAppointments": "لا توجد مواعيد مؤكدة",
"noArrivedAppointments": "لا توجد مواعيد تم تسجيل الوصول إليها",
@@ -296,10 +300,10 @@
"radiology": "الأشعة",
"radiologySubtitle": "النتيجة",
"lab": "المختبر",
- "labSubtitle": "النتائج",
+ "labSubtitle": "نتائج",
"medicines": "الأدوية",
"medicinesSubtitle": "الوصفات",
- "vitalSigns": "علامات حيوية",
+ "vitalSigns": "العلامات الحيوية",
"vitalSignsSubTitle": "التقارير",
"vitalSignNormal": "طبيعي",
"vitalSignLow": "منخفض",
@@ -307,13 +311,16 @@
"vitalSignObese": "بدين",
"vitalSignOverweight": "زيادة الوزن",
"vitalSignUnderweight": "نقص الوزن",
+ "vitalSignSkinny": "نحيف جداً",
"myMedical": "نشط",
"myMedicalSubtitle": "الأدوية",
"myDoctor": "أطبائي",
"myDoctorSubtitle": "القائمة",
+ "myDoctorSubtitle2": "قائمة",
"eye": "العين",
"eyeSubtitle": "القياس",
"insurance": "التأمين",
+ "insurance2": "تأمين",
"insuranceSubtitle": "البطاقة",
"updateInsurance": "تحديث",
"updateInsuranceSubtitle": "التأمين",
@@ -323,11 +330,12 @@
"allergiesSubtitle": "القائمة",
"myVaccines": "لقاحاتي",
"myVaccinesSubtitle": "القائمة",
- "medical": "طبي",
+ "medical": "الطبي",
"medicalSubtitle": "التقرير",
"monthly": "شهري",
"monthlySubtitle": "التقرير",
"sick": "مريض",
+ "sick2": "المرضية",
"sickSubtitle": "الإجازات",
"myBalance": "رصيدي",
"myBalanceSubtitle": "الرصيد",
@@ -341,13 +349,13 @@
"askYourSubtitle": "طبيبك",
"internet": "الإنترنت",
"internetSubtitle": "الاقتران",
- "chatbot": "الدرد��ة الآلية",
+ "chatbot": "الدردشة الآلية",
"chatbotSubtitle": "",
"timeLine": "الخط الزمني",
"labOrders": "طلبات المختبر",
"billNo": "رقم الفاتورة:",
"prescriptions": "الوصفات",
- "history": "التاريخ",
+ "history": "سجل الطلبات",
"orderNo": "رقم الطلب",
"orderDetails": "تفاصيل الطلب",
"deliveryDriverTrack": "تتبع السائق",
@@ -393,7 +401,7 @@
"confirmThePayment": "تأكيد الدفع",
"depositorName": "اسم مُقدِّم الإيداع",
"mobileNumber": "رقم الجوال",
- "phoneNumber": "رقم الهاتف",
+ "phoneNumber": "رقم الجوال",
"country": "البلد",
"ok": "حسنا",
"averageWaitingTime": "متوسط وقت الانتظار:",
@@ -402,7 +410,7 @@
"waterConsumedInMonth": "الماء المستهلك في شهر",
"theVerificationCodeExpiresIn": "ينتهي رمز التحقق في",
"pleaseEnterTheVerificationCode": "يرجى إدخال رمز التحقق المرسل إلى",
- "eyeMeasurements": "قياسات العين",
+ "eyeMeasurements": "فحوصات النظر",
"measurements": "قياسات",
"classes": "نظارات",
"contactLens": "عدسات لاصقة",
@@ -429,7 +437,7 @@
"startDay": "يوم البدء",
"endDay": "يوم الانتهاء",
"days": "أيام ",
- "pleaseVerify": "يرجى التحقق ",
+ "pleaseVerify": "إضافة",
"scheduleTime": "وقت الجدولة",
"askDoctor": "اسأل الطبيب",
"doctorResponses": "ردود الطبيب",
@@ -449,7 +457,7 @@
"infoRadiology": "تتيح لك هذه الخدمة عرض تقارير وصور الأشعة في مجموعة الحبيب الطبية بالإضافة إلى إرسال التقرير عبر البريد الإلكتروني.",
"noReviewsAvailable": "لا توجد تقييمات متاحة",
"noLocationAvailable": "لا توجد مواقع متاحة",
- "orders": "الطلبات",
+ "orders": "سجل الطلبات",
"lakum": "لكم",
"lakumMsg": "لا توجد تفاصيل عن النقاط",
"lakumPoint": "نقطة",
@@ -481,7 +489,7 @@
"shareReview": "شارك التقييم",
"review": " التقييمات",
"viewMedicalFile": "عرض التفاصيل",
- "viewAllServices": "عرض جميع الخدمات",
+ "viewAllServices": "جميع الخدمات",
"medicalFile": "الملف الطبي",
"verified": "تم التحقق",
"checkup": "فحص",
@@ -490,9 +498,11 @@
"refferalTitle": "إحالة إلكترونية",
"refferalSubTitle": "الخدمة",
"healthCare": "الرعاية الصحية",
- "emergency": "حالة طوارئ",
+ "emergency": "طوارئ",
+ "emergency2": "الطوارئ",
"erservices": "خدمات الطوارئ",
"services2": "الخدمات",
+ "services3": "خدمات",
"cantSeeProfile": "لرؤية ملفك الطبي، يرجى تسجيل الدخول أو التسجيل الآن",
"loginRegisterNow": "تسجيل الدخول أو التسجيل الآن",
"hmgPharmacy": "صيدلية الحبيب",
@@ -597,7 +607,7 @@
"selectGender": "اختر الجنس",
"iAmA": "أنا ...",
"selectAge": "اختر عمرك",
- "select": "اختر",
+ "select": "تأكيد الموعد",
"iAm": "أنا",
"yearsOld": "سنوات",
"dragPoint": "اسحب النقطة لتغيير عمرك",
@@ -670,8 +680,8 @@
"noOffersAvailable": "لا توجد عروض متاحة!",
"accessibility": "وضع الوصول",
"orderStatus": "حالة الطلب",
- "findUs": "اعثر علينا",
- "liveChat": "دردشة مباشرة",
+ "findUs": "فروعنا",
+ "liveChat": "محادثة مباشرة",
"service": "خدمة",
"hmgServiceLabel": "خدمة مجموعة الحبيب الطبية",
"healthWeatherIndicators": "مؤشرات الطقس الصحية",
@@ -685,8 +695,8 @@
"duration": "المدة",
"cm": "سم",
"ft": "قدم",
- "kg": "كجم",
- "lb": "رطل",
+ "kg": "كغ",
+ "lb": "باوند",
"birthDate": "تاريخ الميلاد",
"dateOfBirth": "تاريخ الميلاد",
"mass": "الكتلة",
@@ -701,12 +711,12 @@
"bikini": "بيكيني",
"totalMinutes": "إجمالي الدقائق",
"feedback": "رأيك يهمنا",
- "likeToHear": "نود سماع ملاحظاتك، ومخاوفك بشأن خدمات الرعاية الصحية وتجربة الخدمات الإلكترونية. يرجى استخدام النموذج أدناه",
+ "likeToHear": "يسعدنا سماع رأيك. شاركنا تجربتك أو أي ملاحظات حول خدماتنا الطبية أو الالكترونية عبر النموذج أدناه",
"emptySubject": "يرجى إدخال الموضوع",
"emptyMessage": "يرجى إدخال الرسالة",
- "selectAttachment": "اختر المرفق",
- "complainAppo": "شكوى بخصوص الموعد",
- "complainAppoAlt": "شكوى بدون موعد",
+ "selectAttachment": "اختر الملف",
+ "complainAppo": "شكوى مع وجود موعد",
+ "complainAppoAlt": "شكوى بدون وجود موعد",
"messageType": "نوع الرسالة",
"feedbackType": "نوع الرسالة",
"compliment": "تقدير",
@@ -759,13 +769,14 @@
"infoTodo": "تم تصميم هذه الخدمة لتمكينك من الحصول على رابط سريع لقائمة المهام التي تحتاج القيام بها",
"familyInfo": "من خلال هذه الخدمة، ستتمكن من ربط ملفات عائلتك الطبية بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي.",
"rrtdDetails": "تقدم فريق الاستجابة السريعة خدمة طبية شاملة لجميع أنواع الحالات العاجلة والمستقرة من جميع الأعمار، بما في ذلك البالغين والمرضى الأطفال، وتغطي الخدمة فريق طبي مدرب تدريبًا عاليًا ومجهز تجهيزًا كاملاً قادرًا على تقديم أفضل رعاية طبية في منزل المريض.",
- "homeHealthCareText": "تقدم هذه الخدمة مجموعة من خدمات الرعاية الصحية المنزلية، والمتابعة المستمرة والشاملة في أماكن إقامتهم لأولئك الذين لا يمكنهم الوصول إلى المرافق الصحية، مثل (تحليلات المختبر - الأشعة - التطعيمات - العلاج الطبيعي)، إلخ.",
+ "homeHealthCareText": "أعلى معايير الرعاية و الخدمات الطبية في راحة منزلك",
"onlineCheckInAgreement": "تسجيل الوصول عبر الإنترنت مخصص للحالات التي لا تهدد الحياة. اتصل بالهلال الأحمر (997) أو اذهب إلى أقرب قسم طوارئ إذا كان هناك: \n\nعلامات السكتة الدماغية أو النوبة القلبية \nhالة من النوبات أو الإغماء \nهناك إصابة تهدد الطرف أو الحياة \nصورة لإصابات خطيرة",
"infoEreferral": "تتيح لك هذه الخدمة تقديم طلب إحالة من أي مقدم رعاية صحية سواء داخل أو خارج المملكة العربية السعودية إلى أي من مستشفيات HMG، عن طريق ملء بعض بيانات المريض وإرفاق التقارير الطبية، علاوة على ذلك يمكنك تتبع حالة الطلب (قيد المعالجة، مقبول أو مرفوض)",
"erConsultation": "تتيح لك هذه الخدمة إجراء استشارة افتراضية عبر الإنترنت عبر مكالمة فيديو مباشرة مع الطبيب من أي مكان وفي أي وقت.",
"myInvoice": "القائمة",
"invoiceList": "فواتيري",
- "allInvoices": "كل الفواتير",
+ "invoiceList2": "فواتيري",
+ "allInvoices": "الكل",
"hospitals": "المستشفيات",
"clinics": "العيادات",
"doctors": "الأطباء",
@@ -790,47 +801,49 @@
"continuePlan": "متابعة خطة العلاج؟",
"aboutApp": "حول التطبيق",
"dontHaveAccount": "ليس لديك حساب؟",
- "loginOrRegister": "تسجيل الدخول أو التسجيل",
+ "loginOrRegister": "تسجيل الدخول / إنشاء حساب",
"myFiles": "ملفاتي",
"resultsPending": "النتائج معلقة",
"resultsAvailable": "النتائج متاحة",
- "viewReport": "عرض التقرير",
+ "viewReport": "التفاصيل",
"checkAvailability": "التحقق من التوفر",
"readInstructions": "قراءة التعليمات",
"searchLabReport": "ابحث عن تقرير المختبر",
- "prescriptionDeliveryError": "هذه العيادة لا تدعم إعادة التعبئة والتسليم.",
- "receiveOtpToast": "أين تود تلقي رمز التحقق OTP؟",
- "enterPhoneNumber": "أدخل رقم الهاتف",
+ "prescriptionDeliveryError": "خدمة الصرف والتوصيل غير متاحة",
+ "receiveOtpToast": "رمز التحقق",
+ "enterPhoneNumber": "إدخال رقم الجوال",
"enterEmailDesc": "أدخل عنوان بريدك الإلكتروني لإكمال عملية إنشاء ملف طبي",
- "enterPhoneDesc": "أدخل رقم هاتفك لتلقي رمز التحقق ",
- "pleaseChooseOption": "الرجاء اختيار من الخيارات أدناه لتلقي رمز التحقق OTP",
- "prepareToElevate": "هل أنت مستعد لتحسين صحتك ورفاهيتك؟",
- "iAcceptTermsConditions": "أوافق على الشروط والأحكام",
- "alreadyHaveAccount": "هل لديك حساب بالفعل؟",
- "loginNow": "تسجيل الدخول الآن",
- "notice": "إشعار",
+ "enterPhoneDesc": "أدخل رقم جوالك لاستلام رمز التحقق ",
+ "pleaseChooseOption": "اين ترغب في استلام رمز التحقق؟",
+ "prepareToElevate": "رعايتك الصحية تبدأ من هنا",
+ "iAcceptTermsConditions": "الموافقة على الشروط والأحكام",
+ "alreadyHaveAccount": "لديك حساب؟",
+ "loginNow": "تسجيل الدخول",
+ "notice": "تنبيه",
"oR": "أو",
- "sendOTPWHATSAPP": "أرسل لي OTP عبر واتساب",
- "sendOTPSMS": "أرسل لي OTP عبر الرسائل القصيرة",
+ "sendOTPWHATSAPP": "واتساب",
+ "sendOTPSMS": "رسالة نصية",
"fullName": "الاسم الكامل",
"married": "متزوج",
"uae": "الإمارات العربية المتحدة",
"malE": "ذكر",
"loginBy": "تسجيل الدخول بواسطة",
- "loginByOTP": "تسجيل الدخول بواسطة OTP",
+ "loginByOTP": "تسجيل الدخول بواسطة رمزالتحقق",
"guest": "زائر",
"switchAccount": "تبديل الحساب",
"lastLoginBy": "آخر تسجيل دخول بواسطة",
- "allSet": "جاهز! الآن يمكنك تسجيل الدخول باستخدام Face ID أو البصمة",
- "enableQuickLogin": "تمكين تسجيل الدخول السريع",
+ "allSet": "الآن يمكنك تسجيل الدخول باستخدام بصمة الوجه أو البصمة",
+ "quickLogin": "الدخول السريع",
+ "enableQuickLogin": "تسجيل الدخول السريع",
+ "enableQuickLoginBtn": " تفعيل الدخول السريع",
"enableMsg": "تمكين تسجيل الدخول السريع سيسمح بالتحقق من خلال Face ID / Biometric الخاص بجهازك الحالي",
"notNow": "ليس الآن",
"pendingActivation": "في انتظار التنشيط",
"awaitingApproval": "انتظر القبول",
- "news": "أخبار",
+ "news": "الأخبار",
"ready": "جاهز",
"enterValidNationalId": "رقم الهوية أو رقم الملف غير صحيح",
- "enterValidPhoneNumber": "الرجاء إدخال رقم هاتف صالح",
+ "enterValidPhoneNumber": "الرجاء ادخال رقم الهاتف",
"cannotEnterSaudiOrUAENumber": "لا يمكنك إدخال أرقام هواتف السعودية (00966) أو الإمارات (00971) عند اختيار دولة 'أخرى'",
"medicalCentersWithCount": "{count} مراكز طبية",
"medicalCenters": "مراكز طبية",
@@ -841,15 +854,15 @@
"selectHospitalSubTitle": "يرجى اختيار المستشفى للموعد",
"iAcceptThe": "أوافق على",
"personalDetailsVerification": "التحقق من التفاصيل الشخصية",
- "otpVerification": "التحقق من OTP",
- "weHaveSendOTP": "لقد أرسلنا OTP إلى",
+ "otpVerification": "رمز التحقق",
+ "weHaveSendOTP": "تم ارسال رمز التحقق الى",
"via": "عبر",
"forRegistrationVerification": "للتحقق من التسجيل",
- "didntReceiveIt": "لم تستلمه؟",
+ "didntReceiveIt": "لم يصلك الرمز؟",
"resendOTP": "إعادة إرسال",
- "resendIn": "إعادة الإرسال في",
- "pleaseEnterAnationalID": "يرجى إدخال رقم الهوية الوطنية",
- "pleaseEnterAFileNumber": "يرجى إدخال رقم الملف",
+ "resendIn": "إعادة الإرسال خلال",
+ "pleaseEnterAnationalID": "تسجيل الدخول برقم الهوية او الاقامة",
+ "pleaseEnterAFileNumber": "يرجى إدخال / رقم الملف",
"pleaseEnterAValidEmail": "يرجى إدخال بريد إلكتروني صالح",
"pleaseEnterFullName": "يرجى إدخال الاسم الكامل",
"pleaseAcceptTermsConditions": "يرجى قبول الشروط والأحكام",
@@ -871,27 +884,28 @@
"onboardingBody1": "ببضع نقرات فقط يمكنك استشارة الطبيب الذي تختاره.",
"onboardingHeading2": "الوصول إلى السجل الطبي بين يديك",
"onboardingBody2": "تتبع تاريخك الطبي بما في ذلك الفحوصات المخبرية، الوصفات الطبية، التأمين، وغيرها.",
- "hmgHospitals": "مستشفيات الحبيب",
- "hmcMedicalClinic": "مراكز مجموعة الحبيب الطبية",
- "applyFilter": "تطبيق الفلتر",
- "facilityAndLocation": "المرفق والموقع",
- "regionAndLocation": "المنطقة والمواقع",
- "clearAllFilters": "مسح جميع الفلاتر",
- "filters": "فلاتر",
+ "hmgHospitals": "المستشفيات",
+ "hmcMedicalClinic": "المراكز الطبية",
+ "applyFilter": "تطبيق",
+ "facilityAndLocation": "المنشآت",
+ "regionAndLocation": "المنطقة",
+ "clearAllFilters": "اعادة تعيين",
+ "filters": "تحديد البحث",
"searchClinic": "بحث عن عيادة",
- "normal": "عادي",
+ "normal": "طبيعي",
"attention": "انتباه",
- "monitor": "مراقبة",
+ "monitor": "يتطلب متابعة",
"noSpecialResult": "لا توجد نتائج خاصة",
"setTheDateRange": "تعيين النطاق الزمني",
- "historyFlowchart": "مخطط تدفق التاريخ",
+ "selectDate": "اختر التاريخ",
+ "historyFlowchart": "السجل التاريخي",
"to": "إلى",
"startDate": "تاريخ البدء",
"endDate": "تاريخ الانتهاء",
- "walkin": "زيارة بدون موعد",
+ "walkin": "موعد",
"laserClinic": "عيادة الليزر",
"continueString": "يكمل",
- "covid_info": "تجري مستشفيات د. سليمان الحبيب فحص فيروس كورونا المستجد وتصدر شهادات السفر على مدار الساعة، طوال أيام الأسبوع، وبسرعة ودقة عالية. يمكن للراغبين في الاستفادة من هذه الخدمة زيارة أحد فروع مستشفيات د. سليمان الحبيب وإجراء فحص كورونا خلال بضع دقائق والحصول على النتائج خلال عدة ساعات خدمة فحص فيروس كورونا Covid 19 بتقنية PCR للكشف عن الفيروس وفقاً لأعلى المعايير العالمية وبأحدث أجهزة RT-PCR عالية الدقة (GeneXpert الأمريكي وغيره)، وهي طرق معتمدة من قبل هيئة الغذاء والدواء وكذلك من قبل المركز السعودي للوقاية من الأمراض المُعدية",
+ "covid_info": "تجري مستشفيات د. سليمان الحبيب فحص فيروس كورونا المستجد وتصدر شهادات السفر على مدار الساعة، طوال أيام الأسبوع، وبسرعة ودقة عالية. يمكن للراغبين في الاستفادة من هذه الخدمة زيارة أحد فروع مستشفيات د. سليمان الحبيب وإجراء فحص كورونا خلال بضع دقائق والحصول على النتائج خلال عدة ساعات خدمة فحص فيروس كورونا Covid 19 بتقنية PCR للكشف عن الفيروس وفقاً لأعلى المعايير العالمية وبأحدث أجهزة RT-PCR عالية الدقة (GeneXpert الأمريكي وغيره)، وهي طرق معتمدة من قبل هيئة الغذاء والدواء وكذلك من قبل المركز السعودي للوقاية من الأمراض المُعدية",
"appointmentDetails": "تفاصيل الموعد",
"checkingDoctorAvailability": "جاري التحقق من توفر الطبيب...",
"cancellingAppointmentPleaseWait": "جاري إلغاء الموعد، يرجى الانتظار...",
@@ -899,8 +913,8 @@
"notConfirmed": "غير مؤكد",
"appointmentStatus": "حالة الموعد",
"doctorWillCallYou": "سيتصل بك الطبيب عندما يقترب موعدك.",
- "getDirections": "الحصول على الاتجاهات",
- "notifyMeBeforeAppointment": "أبلغني قبل الموعد",
+ "getDirections": "الاتجاهات",
+ "notifyMeBeforeAppointment": "تنبيهي قبل الموعد",
"fetchingLabResults": "جاري جلب نتائج المختبر...",
"fetchingRadiologyResults": "جاري جلب نتائج الأشعة...",
"fetchingAppointmentPrescriptions": "جاري جلب وصفات الموعد...",
@@ -908,21 +922,21 @@
"amountBeforeTax": "المبلغ قبل الضريبة",
"rebookAppointment": "إعادة حجز الموعد",
"fetchingDoctorSchedulePleaseWait": "جاري جلب جدول الطبيب، يرجى الانتظار...",
- "pickADate": "اختر تاريخاً",
+ "pickADate": "اختيار الوقت والتاريخ",
"confirmingAppointmentPleaseWait": "جاري تأكيد الموعد، يرجى الانتظار...",
"appointmentConfirmedSuccessfully": "تم تأكيد الموعد بنجاح",
"appointmentPayment": "دفع الموعد",
"checkingPaymentStatusPleaseWait": "جاري التحقق من حالة الدفع، يرجى الانتظار...",
"paymentFailedPleaseTryAgain": "فشل الدفع! يرجى المحاولة مرة أخرى.",
"appointmentCheckIn": "تسجيل حضور الموعد",
- "insuranceExpiredOrInactive": "التأمين منتهي الصلاحية أو غير نشط",
- "totalAmountToPay": "المبلغ الإجمالي المستحق",
- "vat15": "ضريبة القيمة المضافة 15%",
+ "insuranceExpiredOrInactive": "التأمين غير ساري (منتهي او غير مفعل)",
+ "totalAmountToPay": "المبلغ الإجمالي",
+ "vat15": "ضريبة القيمة المضافة (15%)",
"general": "عام",
"liveCare": "لايف كير",
- "recentVisits": "الزيارات الأخيرة",
+ "recentVisits": "قائمة الزيارات",
"favouriteDoctors": "الأطباء المفضلون",
- "searchByClinic": "البحث حسب العيادة",
+ "searchByClinic": "العيادة",
"tapToSelectClinic": "انقر لاختيار العيادة",
"searchByDoctor": "البحث حسب الطبيب",
"tapToSelect": "انقر للاختيار",
@@ -931,8 +945,8 @@
"immediateConsultation": "استشارة فورية",
"scheduledConsultation": "استشارة مجدولة",
"pharmaLiveCare": "لايف كير الصيدلية",
- "notSureHelpMeChooseClinic": "غير متأكد؟ ساعدني في اختيار عيادة!",
- "mentionYourSymptomsAndFindDoctors": "اذكر أعراضك واعثر على قائمة الأطباء وفقاً لذلك",
+ "notSureHelpMeChooseClinic": "هل تريد مساعدة في اختيار العياة؟",
+ "mentionYourSymptomsAndFindDoctors": "أدخل حالتك الصحية للحصول على قائمة الأطباء",
"immediateService": "خدمة فورية",
"noNeedToWaitGetMedicalConsultation": "لا حاجة للانتظار، ستحصل على استشارة طبية فورية عبر مكالمة فيديو",
"noVisitRequired": "لا حاجة للزيارة",
@@ -941,7 +955,7 @@
"freeMedicineDelivery": "توصيل مجاني للأدوية",
"offersFreeMedicineDelivery": "يوفر توصيل مجاني للأدوية لموعد لايف كير",
"dentalChiefComplaints": "الشكاوى الرئيسة للأسنان",
- "viewAvailableAppointments": "عرض المواعيد المتاحة",
+ "viewAvailableAppointments": "المواعيد المتاحة",
"doctorProfile": " ملف الطبيب",
"waitingAppointment": "موعد الانتظار",
"hospitalInformation": "معلومات المستشفى",
@@ -958,22 +972,22 @@
"viewNearestAppos": "عرض أقرب المواعيد المتاحة",
"noDoctorFound": "لم يتم العثور على طبيب مطابق للمعايير المحددة...",
"yesPleasImInAHurry": "نعم من فضلك، أنا في عجلة من أمري",
- "fetchingFeesPleaseWait": "جاري جلب الرسوم، يرجى الانتظار...",
+ "fetchingFeesPleaseWait": "يرجى الانتظار...",
"noThanksPhysicalVisit": "لا، شكراً. أفضل الزيارة الشخصية",
"offline": "غير متصل",
"videoCall": "مكالمة فيديو",
- "liveVideoCallWithHMGDoctors": "مكالمة فيديو مباشرة مع أطباء مجموعة الحبيب الطبية",
- "liveAudioCallWithHMGDoctors": "مكالمة صوتية مباشرة مع أطباء مجموعة الحبيب الطبية",
+ "liveVideoCallWithHMGDoctors": "مكالمة فيديو مباشرة مع مختص",
+ "liveAudioCallWithHMGDoctors": "مكالمة صوتية مباشرة مع مختص",
"audioCall": "مكالمة صوتية",
"phoneCall": "مكالمة هاتفية",
- "livePhoneCallWithHMGDoctors": "مكالمة هاتفية مباشرة مع أطباء مجموعة الحبيب الطبية",
- "reviewLiveCareRequest": "مراجعة طلب لايف كير",
- "selectedLiveCareType": "نوع لايف كير المحدد",
- "selectLiveCareCallType": "اختر نوع مكالمة لايف كير",
+ "livePhoneCallWithHMGDoctors": "مكالمة هاتفية مباشرة مع مختص",
+ "reviewLiveCareRequest": "تفاصيل الطلب",
+ "selectedLiveCareType": "نوع الطلب",
+ "selectLiveCareCallType": "نوع مكالمة لايف كير",
"confirmingLiveCareRequest": "جاري تأكيد طلب لايف كير، يرجى الانتظار...",
"unknownErrorOccurred": "حدث خطأ غير معروف...",
"liveCarePermissionsMessage": "يتطلب لايف كير أذونات الكاميرا والميكروفون والموقع والإشعارات لتمكين الاستشارة الافتراضية بين المريض والطبيب، يرجى السماح بهذه الأذونات للمتابعة.",
- "liveCarePayment": "دفع لايف كير",
+ "liveCarePayment": "الدفع",
"mada": "مدى",
"visaOrMastercard": "فيزا أو ماستركارد",
"tamara": "تمارا",
@@ -995,8 +1009,8 @@
"processingCheckIn": "جاري معالجة تسجيل الحضور...",
"bookingWaitingAppointment": "جاري حجز موعد الانتظار، يرجى الانتظار...",
"enterValidIDorIqama": "يرجى إدخال رقم هوية وطنية أو رقم ملف صالح",
- "selectAppointment": "حدد الموعد",
- "rebookSameDoctor": "أعد الحجز مع نفس الطبيب",
+ "selectAppointment": "اختر الموعد",
+ "rebookSameDoctor": "حجز موعد",
"queueing": "قائمة الانتظار",
"inQueue": "في قائمة الانتظار",
"yourTurn": "دورك",
@@ -1017,7 +1031,7 @@
"upcoming": "القادمة",
"completed": "المكتملة",
"noAppointmentsYet": "ليس لديك أي مواعيد بعد.",
- "viewProfile": "عرض الملف الشخصي",
+ "viewProfile": "الملف الشخصي",
"choosePreferredHospitalForService": "اختر المستشفى المفضل لديك للخدمة",
"noHospitalsFound": "لم يتم العثور على مستشفيات",
"cancelOrderConfirmation": "هل أنت متأكد أنك تريد إلغاء هذا الطلب؟",
@@ -1035,9 +1049,9 @@
"noServicesAvailable": "لا توجد خدمات متاحة",
"selectAService": "اختر خدمة",
"comprehensiveCheckup": "الفحص الشامل",
- "viewNearestHMGLocations": "عرض أقرب مواقع مجموعة الحبيب الطبية",
+ "viewNearestHMGLocations": "عرض أقرب فرع",
"provideFeedbackOnServices": "قدم ملاحظاتك على خدماتنا",
- "liveChatWithHMG": "خيار الدردشة المباشرة مع مجموعة الحبيب الطبية",
+ "liveChatWithHMG": "حدث مباشرة مع الموظف",
"send": "إرسال",
"status": "الحالة",
"sendingFeedback": "جاري إرسال الملاحظات...",
@@ -1085,11 +1099,11 @@
"hereIsYourReferralNumber": "هذا هو رقم الإحالة الخاص بك #: ",
"searchEReferral": "البحث عن إحالة إلكترونية",
"enterRequiredInfoToSearch": "يرجى إدخال المعلومات المطلوبة للبحث عن إحالة إلكترونية",
- "selectPickupDirection": "اختر اتجاه الاستلام",
+ "selectPickupDirection": "اختر الاتجاه",
"selectDirection": "اختر الاتجاه",
"toHospital": "إلى المستشفى",
"fromHospital": "من المستشفى",
- "selectWay": "اختر الطريقة",
+ "selectWay": "الاتجاهات",
"oneWay": "اتجاه واحد",
"twoWay": "اتجاهين",
"selectPickupDetails": "اختر تفاصيل الاستلام",
@@ -1097,16 +1111,16 @@
"selectDetails": "اختر التفاصيل",
"work": "العمل",
"pick": "استلام",
- "insideTheHome": "داخل المنزل",
+ "insideTheHome": "من المنزل",
"haveAnyAppointment": "هل لديك أي موعد",
- "amountPaidAtHospital": "سيتم دفع المبلغ في المستشفى",
- "submitRequest": "إرسال الطلب",
- "enterPickupLocationManually": "أدخل موقع الاستلام يدوياً",
+ "amountPaidAtHospital": "الدفع عند الوصول للمستشفى",
+ "submitRequest": "تأكيد الطلب",
+ "enterPickupLocationManually": "تحديد موقع الاستلام",
"enterPickupLocation": "أدخل موقع الاستلام",
- "trackingDetails": "تفاصيل التتبع",
+ "trackingDetails": "استدعاء سيارة إسعاف",
"cancelRequest": "إلغاء الطلب",
"shareLocationWhatsapp": "مشاركة موقعك المباشر على واتساب",
- "pleaseWaitForCall": "يرجى انتظار المكالمة",
+ "pleaseWaitForCall": "سنتصل بك قريبًا لتأكيد الطلب",
"toHospitalLower": "إلى المستشفى",
"contact": "اتصال",
"failed": "فشل",
@@ -1115,7 +1129,7 @@
"onTheWayToHospital": " في الطريق إلى المستشفى",
"arrivedAtHospital": "وصل إلى المستشفى",
"orderCancel": "إلغاء الطلب",
- "emergencyCheckIn": "تسجيل الطوارئ الإلكتروني",
+ "emergencyCheckIn": "تسجيل الوصول في الطواريء",
"erOnlineCheckInDescription": "تتيح هذه الخدمة للمرضى تسجيل موعد الطوارئ قبل الوصول.",
"erOnlineCheckInSuccess": "تم تسجيل وصول الطوارئ بنجاح. الرجاء التوجه إلى منطقة الانتظار.",
"erOnlineCheckInError": "حدث خطأ غير متوقع أثناء عملية التسجيل. يرجى التواصل مع الدعم.",
@@ -1131,35 +1145,42 @@
"allFacilities": "جميع المرافق",
"selectLocation": "اختر الموقع",
"pleaseSelectTheLocation": "يرجى اختيار الموقع",
- "viewLocationGoogleMaps": "عرض الموقع على خرائط جوجل",
+ "viewLocationGoogleMaps": "الاتجاهات",
"callAmbulance": "استدعاء سيارة إسعاف",
"requestAmbulanceInEmergency": "طلب سيارة إسعاف في حالة الطوارئ من المنزل أو المستشفى",
- "confirmation": "تأكيد",
- "areYouSureYouWantToCallAmbulance": "هل أنت متأكد أنك تريد استدعاء سيارة إسعاف؟",
- "getDetailsOfNearestBranch": "احصل على تفاصيل أقرب فرع بما في ذلك الاتجاهات",
- "areYouSureYouWantToCallRRT": "هل أنت متأكد أنك تريد استدعاء فريق الاستجابة السريعة (RRT)؟",
+ "confirmation": "استمرار",
+ "areYouSureYouWantToCallAmbulance": "هل تود تأكيد طلب سيارة الإسعاف؟",
+ "getDetailsOfNearestBranch": "الحصول على تفاصيل أقرب مركز طوارئ والاتجاهات إليه",
+ "areYouSureYouWantToCallRRT": "هل تريد استدعاء فريق الاستجابة السريعة؟",
"priorERCheckInToSkipLine": "تسجيل الوصول المسبق في الطوارئ لتجاوز الطابور والدفع في الاستقبال.",
- "areYouSureYouWantToMakeERCheckIn": "هل أنت متأكد أنك تريد إجراء تسجيل وصول الطوارئ؟",
- "checkingYourERAppointmentStatus": "جاري التحقق من حالة موعد الطوارئ الخاص بك...",
+ "areYouSureYouWantToMakeERCheckIn": "هل تريد إجراء تسجيل وصول الطوارئ؟",
+ "checkingYourERAppointmentStatus": "يرجى الانتظار…",
"transportOptions": "خيارات النقل",
- "selectHospitalForAdvancePayment": "يرجى اختيار المستشفى الذي ترغب في دفع مبلغ مقدم له.",
- "recharge": "إعادة الشحن",
+ "selectHospitalForAdvancePayment": "يرجى تحديد المستشفى أولاً.",
+ "recharge": "شحن المحفظة",
"activityLevel": "مستوى النشاط",
"selectActivityLevel": "حدد مستوى النشاط",
+ "almostInactive": "غير نشط تقريبًا (بدون تمارين)",
+ "lightlyActive": "نشاط خفيف",
+ "lightlyActive13Days": "نشاط خفيف (١-٣) أيام في الأسبوع",
+ "superActive": "نشاط مكثف (تمارين شاقة جدًا)",
"caloriesPerDay": "السعرات الحرارية في اليوم الواحد",
"dietType": "نوع النظام الغذائي",
"selectDietType": "حدد نوع النظام الغذائي",
"bodyFrameSize": "حجم إطار الجسم",
"selectBodyFrameSize": "حدد حجم إطار الجسم",
+ "bodyFrameSmall": "صغير (الأصابع متداخلة)",
+ "bodyFrameMedium": "متوسط (الأصابع متلامسة)",
+ "bodyFrameLarge": "كبير (الأصابع لا تتلامس)",
"averageCycleLength": "متوسط طول الدورة الشهرية (عادةً 28 يومًا)",
"averageLutealPhase": "متوسط طول المرحلة الأصفرية (عادةً 14 يومًا)",
- "convert": "يتحول",
+ "convert": "تحويل الوحدات",
"calculate": "احسب",
- "healthCalculators": "حاسبات الصحة",
- "healthConverters": "محولات الصحة",
+ "healthCalculators": "الحاسبات الصحية",
+ "healthConverters": "تحويل الوحدات",
"generalHealth": "الصحة العامة",
"relatedToBMICalories": "متعلق بمؤشر كتلة الجسم والسعرات الحرارية ودهون الجسم وما إلى ذلك للبقاء على اطلاع دائم بصحتك.",
- "selectCalculator": "اختر الآلة الحاسبة",
+ "selectCalculator": "اختر الحاسبة",
"womensHealth": "صحة المرأة",
"relatedToPeriodsOvulation": "متعلق بالدورة الشهرية والإباضة والحمل ومواضيع أخرى.",
"bloodSugar": "سكر الدم",
@@ -1168,14 +1189,22 @@
"monitorCholesterolLevels": "راقب مستويات الكوليسترول، وقيّم مخاطر صحة القلب، واتخذ خطوات استباقية للرفاهية.",
"triglyceridesFatBlood": "الدهون الثلاثية في الدم",
"understandTriglyceridesImpact": "افهم تأثير الدهون الثلاثية على صحة القلب مع رؤى مخصصة وتوصيات الخبراء.",
- "bmiCalculator": "حاسبة\nمؤشر كتلة الجسم",
- "caloriesCalculator": "حاسبة\nالسعرات الحرارية",
- "bmrCalculator": "حاسبة\nمعدل الأيض الأساسي",
- "idealBodyWeight": "الوزن المثالي\nللجسم",
- "bodyFatCalculator": "حاسبة\nدهون الجسم",
+ "bmiCalculator": "مؤشر\nكتلة الجسم",
+ "caloriesCalculator": "السعرات \nالحرارية",
+ "bmrCalculator": "معدل \nالايض",
+ "idealBodyWeight": "الوزن\n المثالي",
+ "bodyFatCalculator": "دهون\n الجسم",
"carbsProteinFat": "الكربوهيدرات\nالبروتين والدهون",
"ovulationPeriod": "فترة\nالإباضة",
"deliveryDueDate": "تاريخ الولادة\nالمتوقع",
+ "bmiCalculatorDesc": "احسب مؤشر كتلة جسمك لفهم نطاق وزنك الصحي.",
+ "caloriesCalculatorDesc": "اكتشف عدد السعرات الحرارية التي تحتاجها يومياً للحفاظ على الوزن أو فقدانه.",
+ "bmrCalculatorDesc": "حدد معدل الأيض الأساسي ومتطلباتك اليومية من الطاقة.",
+ "idealBodyWeightDesc": "اكتشف وزنك المثالي بناءً على الطول والعمر وبنية الجسم.",
+ "bodyFatCalculatorDesc": "قدّر نسبة دهون جسمك لتتبع أهداف اللياقة والصحة.",
+ "carbsProteinFatDesc": "وازن بين العناصر الغذائية مع النسب الصحيحة من الكربوهيدرات والبروتين والدهون.",
+ "ovulationPeriodDesc": "تتبع فترة خصوبتك وخطط للحمل بدقة.",
+ "deliveryDueDateDesc": "احسب تاريخ ولادتك المتوقع وراقب مراحل الحمل.",
"low": "منخفض",
"preDiabetic": "ما قبل السكري",
"high": "مرتفع",
@@ -1209,30 +1238,30 @@
"bookAppointment": "حجز\nموعد",
"completeCheckup": "الفحص الشامل",
"indoorNavigation": "الملاحة الداخلية",
- "eReferralServices": "خدمات الإحالة الإلكترونية",
+ "eReferralServices": "الاحالة",
"bloodDonation": "التبرع بالدم",
"dailyWaterMonitor": "مراقب الماء اليومي",
"fetchingYourWaterIntakeDetails": "جاري جلب تفاصيل استهلاك الماء الخاص بك.",
"healthCalculatorsServices": "حاسبات\nالصحة",
"healthConvertersServices": "محولات\nالصحة",
"smartWatchesServices": "الساعات\nالذكية",
- "exploreServices": "استكشف الخدمات",
- "medicalAndCareServices": "الخدمات الطبية والرعاية",
+ "exploreServices": "قائمة الخدمات",
+ "medicalAndCareServices": "خدمات الرعاية الطبية",
"hmgServices": "خدمات مجموعة الحبيب الطبية",
"personalServices": "الخدمات الشخصية",
"habibWallet": "محفظة الحبيب",
+ "habibWallet2": "المحفظة",
"loginToViewWalletBalance": "سجل الدخول لعرض رصيد محفظتك",
- "recharge": "إعادة الشحن",
"loginToViewMedicalFile": "سجل الدخول لعرض ملفك الطبي",
"addMember": "إضافة عضو",
"addFamilyMember": "إضافة فرد من العائلة",
- "pleaseFillBelowFieldToAddNewFamilyMember": "يرجى ملء الحقل أدناه لإضافة فرد جديد من العائلة إلى ملفك الشخصي",
- "healthTools": "أدوات الصحة",
+ "pleaseFillBelowFieldToAddNewFamilyMember": "أدخل البيانات أدناه لإضافة فرد جديد إلى عائلتك",
+ "healthTools": "الادوات الصحية",
"supportServices": "خدمات الدعم",
"virtualTour": "جولة افتراضية",
"carParking": "موقف السيارات",
"latestNews": "آخر الأخبار",
- "hmgContact": "اتصل بمجموعة الحبيب الطبية",
+ "hmgContact": "تواصل معنا",
"durationCannotExceed90": "لا يجوز أن تتجاوز المدة 90 دقيقة",
"unexpectedError": "حدث خطأ غير متوقع",
"gettingAmbulanceTransportOption": "جاري الحصول على خيارات نقل الإسعاف",
@@ -1251,10 +1280,10 @@
"invalidWeight": "الوزن غير صالح",
"timeToDrinkWater": "حان وقت شرب الماء! 💧",
"stayHydratedDrinkWater": "ابق رطبًا! اشرب {amount} مل من الماء.",
- "visitPharmacyOnline": "زيارة الصيدلية على الانترنت",
+ "visitPharmacyOnline": "الصيدلية الالكترونية",
"howAreYouFeelingToday": "كيف حالك اليوم؟",
- "checkYourSymptomsWithScale": "تحقق من أعراضك باستخدام ذا المقياس",
- "checkYourSymptoms": "تحقق من أعراضك",
+ "checkYourSymptomsWithScale": "قيّم حالتك الصحية واحصل على التوجيه الطبي المناسب",
+ "checkYourSymptoms": "مدقق الأعراض",
"noUpcomingAppointmentPleaseBook": "ليس لديك أي مواعيد قادمة. يرجى حجز موعد",
"youHaveEROnlineCheckInRequest": "لديك طلب تسجيل وصول عبر الإنترنت للطوارئ",
"quickLinks": "روابط سريعة",
@@ -1266,8 +1295,8 @@
"requestedServices": "الخدمات المطلوبة",
"selectServices": "اختر الخدمات",
"selectedServices": "الخدمات المختارة",
- "createNewRequest": "إنشاء طلب جديد",
- "youHaveNoPendingRequests": "ليس لديك أي طلبات معلقة.",
+ "createNewRequest": "طلب جديد",
+ "youHaveNoPendingRequests": "ليس لديك أي طلبات",
"noInsuranceDataFound": "لم يتم العثور على بيانات التأمين...",
"noInsuranceUpdateRequest": "لم يتم العثور على أي طلبات لتحديث بيانات التأمين.",
"policyNumberInsurancePage": "الوثيقة: {number}",
@@ -1277,9 +1306,9 @@
"noInsuranceApprovals": "لم تحصل على أي موافقات تأمينية حتى الآن.",
"noInsuranceWithHMG": "ليس لديك تأمين مسجل لدى مجموعة الحبيب الطبية.",
"referenceRange": "النطاق المرجعي",
- "downloadReport": "تنزيل التقرير",
+ "downloadReport": "تحميل",
"generatingReport": "جارٍ إنشاء التقرير، يرجى الانتظار...",
- "noLabResults": "ليس لديك أي نتائج مختبرية حتى الآن.",
+ "noLabResults": "لا يوجد نتائج",
"labResultDetails": "تفاصيل نتائج المختبر",
"resultOf": "نتيجة",
"whatIsThisResult": "ما هي هذه النتيجة؟",
@@ -1289,29 +1318,30 @@
"results": "نتائج",
"viewResults": "عرض النتائج",
"rebook": "إعادة الحجز",
- "noOphthalmologyAppointments": "لم يتم العثور على أي مواعيد في قسم طب العيون...",
- "noVitalSignsRecordedYet": "لا توجد علامات حيوية مسجلة بعد",
- "appointmentsAndVisits": "المواعيد والزيارات",
+ "noOphthalmologyAppointments": "لم يتم العثور على أي مواعيد",
+ "noVitalSignsRecordedYet": "لا توجد علامات حيوية",
+ "appointmentsAndVisits": "المواعيد",
"labAndRadiology": "المختبر والأشعة",
"activeMedicationsAndPrescriptions": "الوصفات الطبية",
"allPrescriptions": "جميع الوصفات",
"allMedications": "جميع الأدوية",
- "youDontHaveAnyPrescriptionsYet": "ليس لديك أي وصفات طبية بعد.",
- "youDontHaveAnyCompletedVisitsYet": "ليس لديك أي زيارات مكتملة بعد",
- "others": "أخرى",
+ "youDontHaveAnyPrescriptionsYet": "ليس لديك أي وصفات طبية",
+ "youDontHaveAnyCompletedVisitsYet": "ليس لديك أي زيارات مكتملة",
+ "others": "خدمات أخرى",
"allergyInfo": "معلومات الحساسية",
"vaccineInfo": "معلومات اللقاحات",
"updateInsuranceInfo": "تحديث التأمين",
- "myInvoicesList": "قائمة فواتيري",
- "ancillaryOrdersList": "قائمة الطلبات المساعدة",
- "youDontHaveAnySickLeavesYet": "ليس لديك أي إجازات مرضية بعد.",
+ "myInvoicesList": "و الفواتير",
+ "ancillaryOrdersList": "الخدمات الطبية المساندة",
+ "youDontHaveAnySickLeavesYet": "ليس لديك أي إجازات مرضية",
"medicalReports": "التقارير الطبية",
"sickLeaveReport": "تقرير الإجازة المرضية",
"weightTracker": "متتبع الوزن",
"askYourDoctor": "اسأل طبيبك",
"internetPairing": "الاقتران بالإنترنت",
"requested": "مطلوب",
- "youDontHaveAnyMedicalReportsYet": "ليس لديك أي تقارير طبية بعد.",
+ "readyToDownload": "جاهز للتحميل",
+ "youDontHaveAnyMedicalReportsYet": "ليس لديك أي تقارير طبية",
"requestMedicalReport": "طلب تقرير طبي",
"youDoNotHaveAnyAppointmentsToRequestMedicalReport": "ليس لديك أي مواعيد لطلب تقرير طبي.",
"areYouSureYouWantToRequestMedicalReport": "هل أنت متأكد أنك تريد طلب تقرير طبي لهذا الموعد؟",
@@ -1330,7 +1360,7 @@
"selectAProfile": "الرجاء تحديد ملف تعريف",
"switchFamilyFile": "قم بالتبديل من قائمة الملفات الطبية أدناه",
"medicalFiles": "الملفات الطبية",
- "addANewFamilyMember": "إضافة فرد جديد من العائلة",
+ "addANewFamilyMember": "إضافة فرد جديد",
"viewInvoiceDetails": "عرض تفاصيل الفاتورة",
"outPatient": "مريض خارجي",
"invoiceDetails": "تفاصيل الفاتورة",
@@ -1346,18 +1376,18 @@
"parkingDate": "التاريخ: {date}",
"parkedSince": "متوقف منذ: {time}",
"resetDirection": "إعادة تعيين الاتجاه",
- "noPrescriptionOrdersYet": "ليس لديك أي طلبات وصفات طبية حتى الآن.",
+ "noPrescriptionOrdersYet": "ليس لديك أي طلبات.",
"fetchingPrescriptionPDFPleaseWait": "جاري جلب ملف الوصفة الطبية، يرجى الانتظار...",
"ratingValue": "التقييم: {rating}",
"downloadPrescription": "تحميل الوصفة الطبية",
"fetchingPrescriptionDetails": "جاري جلب تفاصيل الوصفة الطبية...",
"switchBackFamilyFile": "العودة إلى ملف العائلة",
- "profileAndSettings": "الملف الشخصي والإعدادات",
+ "profileAndSettings": "الإعدادات",
"quickActions": "إجراءات سريعة",
"notificationsSettings": "إعدادات الإشعارات",
"touchIDFaceIDServices": "خدمات Touch ID / Face ID",
"personalInformation": "المعلومات الشخصية",
- "updateEmailAddress": "تحديث عنوان البريد الإلكتروني",
+ "updateEmailAddress": "عنوان البريد الالكتروني",
"helpAndSupport": "المساعدة والدعم",
"permissionsProfile": "الأذونات",
"privacyPolicy": "سياسة الخصوصية",
@@ -1378,9 +1408,9 @@
"previous": "سابق",
"selectedOrgans": "الهيئات المختارة",
"noOrgansSelected": "لم يتم تحديد أي أعضاء بعد",
- "organSelector": "محدد الأعضاء",
+ "organSelector": "حدد موقع الألم",
"noPredictionsAvailable": "لا توجد تنبؤات متاحة",
- "areYouSureYouWantToRestartOrganSelection": "هل أنت متأكد أنك تريد إعادة تشغيل اختيار الأعضاء؟",
+ "areYouSureYouWantToRestartOrganSelection": "هل تريد الخروج؟",
"possibleConditions": "الحالات المحتملة",
"pleaseSelectAtLeastOneRiskBeforeProceeding": "يرجى اختيار عامل خطر واحد على الأقل قبل المتابعة",
"aboveYouSeeCommonRiskFactors": "أعلاه ترى عوامل الخطر الأكثر شيوعًا. على الرغم من أن /diagnosis قد تعيد أسئلة حول عوامل الخطر، ",
@@ -1393,10 +1423,10 @@
"failedToLoadImage": "فشل تحميل الصورة",
"typeNotification": "النوع",
"pleaseSelectAtLeastOneOptionBeforeProceeding": "يرجى اختيار خيار واحد على الأقل قبل المتابعة",
- "suggestions": "الاقتراحات",
+ "suggestions": "التوصيات",
"pleaseGoBackAndSelectOrgansFirst": "يرجى العودة واختيار الأعضاء أولاً",
"symptomsSelector": "محدد الأعراض",
- "possibleSymptomsRelatedTo": "الأعراض المحتملة المتعلقة بـ",
+ "possibleSymptomsRelatedTo": "أعراض مرتبطة بـ",
"suggestionAIListDescription": "هذه قائمة بالأعراض المقترحة من قبل الذكاء الاصطناعي، بناءً على المعلومات التي تم جمعها حتى الآن خلال المقابلة",
"analyzing": "جاري التحليل...",
"seekMedicalAdvice": "اطلب المشورة الطبية",
@@ -1406,23 +1436,23 @@
"colorScience": "دلالات الألوان",
"noNeedToVisitDoctor": "لا حاجة لزيارة الطبيب",
"commonSymptom": "الأعراض الشائعة",
- "bookAppointment": "احجز موعد",
+ "bookAppointment": "حجز موعد",
"notApplicable": "لا ينطبق",
"emergencyTriage": "طوارئ",
"emergencyEvidenceDetected": "تم اكتشاف دليل طوارئ. يرجى طلب العناية الطبية.",
"noQuestionItemsAvailable": "لا توجد عناصر أسئلة متاحة",
"pleaseAnswerAllQuestionsBeforeProceeding": "يرجى الإجابة على جميع الأسئلة قبل المتابعة",
"triage": "الفرز",
- "areYouSureYouWantToExitProgress": "هل أنت متأكد أنك تريد الخروج؟ سيتم فقدان تقدمك.",
+ "areYouSureYouWantToExitProgress": "هل تود الخروج؟ ستفقد تقدمك الحالي.",
"noQuestionAvailable": "لا يوجد سؤال متاح",
- "possibleSymptom": "عرض محتمل: ",
- "symptomsCheckerFindingScore": "- درجة نتائج فاحص الأعراض",
+ "possibleSymptom": "تشخيص محتمل",
+ "symptomsCheckerFindingScore": "نسبة التطابق",
"notSet": "غير محدد",
"years": "سنوات",
- "symptomsChecker": "فاحص الأعراض",
+ "symptomsChecker": "مدقق الاعراض",
"helloIsYourInformationUpToDate": "مرحباً {name}، هل معلوماتك محدثة؟",
"noEditAll": "لا، تعديل الكل",
- "yesItIs": "نعم، إنها كذلك",
+ "yesItIs": "نعم",
"age": "العمر",
"youDontHaveAnyAncillaryOrdersYet": "ليس لديك أي طلبات مساعدة بعد.",
"invoiceWithNumber": "الفاتورة: {invoiceNo}",
@@ -1448,14 +1478,16 @@
"covered": "مغطى",
"vatPercent": "ضريبة القيمة المضافة (15%)",
"proceedToPayment": "المتابعة للدفع",
- "supportedSmartWatches": "الساعات الذكية المدعومة",
+ "supportedSmartWatches": "كيف تعمل؟",
"pleaseMakeSureSamsungWatchConnected": "يرجى التأكد من أن ساعة Samsung الخاصة بك متصلة بهاتفك، ومتزامنة ومحدثة بشكل نشط.",
"beforeSyncingDataFollowInstructions": "قبل مزامنة البيانات، يرجى التأكد من اتباع التعليمات بشكل صحيح.",
"viewWatchInstructions": "عرض تعليمات الساعة",
"healthConnectAppNotInstalled": "يبدو أنه ليس لديك تطبيق Health Connect مثبتًا. يرجى تثبيته من متجر Play لمزامنة بيانات صحتك.",
- "setTimerOfReminder": "ضبط مؤقت التذكير",
+ "setTimerOfReminder": "تنبيهي قبل الموعد",
"youHaveAppointmentWithDr": "لديك موعد مع د. ",
"hours": "ساعات",
+ "minutes": "دقائق",
+ "seconds": "ثواني",
"secs": "ثواني",
"noAllergiesDataFound": "لم يتم العثور على بيانات الحساسية...",
"heartRateDescription": "معدل ضربات قلبك يشير إلى عدد المرات التي ينبض فيها قلبك في الدقيقة",
@@ -1465,6 +1497,7 @@
"distanceDescription": "المسافة المقطوعة على مدار اليوم",
"overview": "نظرة عامة",
"details": "التفاصيل",
+ "details2": "تفاصيل",
"healthy": "صحي",
"warning": "تحذير",
"vitalSignDetails": "تفاصيل العلامات الحيوية",
@@ -1515,7 +1548,7 @@
"notifyMeBeforeConsumptionTime": "أبلغني قبل وقت الاستهلاك",
"noMedicationsToday": "لا أدوية اليوم",
"reminders": "تذكيرات",
- "reminderAddedToCalendar": "تمت إضافة تذكير إلى التقويم ✅",
+ "reminderAddedToCalendar": "تمت إضافة تذكير إلى التقويم ",
"errorWhileSettingCalendar": "حدث خطأ أثناء ضبط التقويم:{error}",
"instructions": "التعليمات",
"requests": "الطلبات",
@@ -1527,28 +1560,28 @@
"pleaseVisitRoomForVitalSigns": "يرجى زيارة الغرفة {roomNumber} لقياس العلامات الحيوية",
"pleaseVisitRoomToTheDoctor": "يرجى زيارة الغرفة {roomNumber} لمقابلة الطبيب",
"erOnlineCheckInRequest": "طلب تسجيل الوصول عبر الإنترنت لقسم الطوارئ",
- "indoor": "داخلي",
- "navigation": "الملاحة",
- "health": "الصحة",
+ "indoor": "خريطة",
+ "thehospital": "المستشفى",
+ "health": " الصحية",
"calculators": "الحاسبات",
- "converters": "المحولات",
- "guide": "الدليل",
- "liveCareServiceDesc": "احصل على استشارة طبية من طبيب متخصص عبر مكالمة فيديو",
+ "converters": "محول الوحدات",
+ "guide": "دليل",
+ "liveCareServiceDesc": "احصل على استشارة طبية من طبيب مختص عبر مكالمة فيديو",
"bloodGroup": "فصيلة الدم: {bloodType}",
"medicalServices": "الخدمات الطبية",
- "insuranceAndPayments": "التأمين والمدفوعات",
+ "insuranceAndPayments": "التأمين و الفواتير",
"trackerAndOthers": "المتتبع وأخرى",
"bmi": "مؤشر كتلة الجسم",
- "yesPleaseINeedHelp": "نعم، من فضلك أريد المساعدة",
+ "yesPleaseINeedHelp": "نعم، احتاج مساعدة",
"aiOverView": "AI ملخص",
- "generateAiAnalysis": "قم بإجراء تحليل لهذا الطلب AI",
- "aiAnalysis": "AI تحليل",
- "prediction": "تنبؤ",
- "prevention": "وقاية",
- "disclaimer": "تنصل",
- "thisAboveInfo": "المعلومات المذكورة أعلاه مُولّدة بواسطة AI بناءً على نتائج تحاليلك المخبرية، وهي لأغراض إعلامية فقط. لا ينبغي اعتبارها تشخيصًا طبيًا أو خطة علاجية. استشر طبيبك دائمًا للحصول على نصيحة طبية مُخصصة قبل اتخاذ أي قرارات تتعلق بصحتك.",
+ "generateAiAnalysis": "تحليل الذكاء الاصطناعي",
+ "aiAnalysis": "تحليل الذكاء الاصطناعي",
+ "prediction": "التوقعات",
+ "prevention": "الوقاية",
+ "disclaimer": "إخلاء مسؤولية",
+ "thisAboveInfo": "تم تحليل نتائج المختبرهذه بواسطة الذكاء الاصطناعي، وهي لا تُعدّ نصيحة طبية. استشر طبيبك المختص للتشخيص والعلاج.",
"aiDisclaimer": "سيتم مشاركة بيانات نتائج تحاليلك المخبرية بشكل آمن مع خدمة الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في تقديم رؤى صحية مُخصصة. هل ترغب في المتابعة؟",
- "consent": "موافقة",
+ "consent": "تحليل الذكاء الاصطناعي",
"bmiNormalDescription": "مؤشر كتلة جسمك ضمن المعدل الصحي. استمر في اتباع نظام غذائي متوازن، وممارسة النشاط البدني بانتظام، وإجراء الفحوصات الدورية للحفاظ على صحة جيدة. راقب أي تغييرات ملحوظة مع مرور الوقت.",
"bmiUnderweightDescription": "يشير مؤشر كتلة الجسم إلى أنك تعاني من نقص الوزن. لذا، يُنصح بزيادة السعرات الحرارية المتناولة من خلال تناول الأطعمة الغنية بالعناصر الغذائية، وممارسة تمارين المقاومة لبناء العضلات، واستشارة أخصائي رعاية صحية للتحقق من وجود أسباب كامنة.",
"bmiOverweightDescription": "يشير مؤشر كتلة الجسم إلى زيادة الوزن. لذا، يُنصح بالسعي إلى إنقاص الوزن تدريجياً وبشكل مستدام من خلال تقليل السعرات الحرارية بشكل معتدل، وممارسة النشاط البدني بانتظام، واختيار الأطعمة الصحية. استشر طبيبك قبل إجراء أي تغييرات جذرية في نمط حياتك.",
@@ -1587,10 +1620,10 @@
"servicePriceListRights": "يحق للمريض الحصول على متابعة مجانية في غضون 14 يومًا من الزيارة الأولى",
"serviceName": "اسم الخدمة",
"noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.",
- "noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.",
+ "noThanksIKnowTheClinic": "لا، شكراً",
"unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة",
- "loadingAIAnalysis": "نقوم بتحليل نتائجك، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.",
- "symptoms": "أعراض",
+ "loadingAIAnalysis": "جارٍ تحليل النتائج بواسطة الذكاء الاصطناعي، يرجى الانتظار...",
+ "symptoms": "مدقق الاعراض",
"insuranceInActive": "التأمين غير نشط",
"insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.",
"updateAppNow": "تحديث التطبيق الآن",
@@ -1616,23 +1649,22 @@
"continueCash": "متابعة الدفع نقدًا",
"timeFor": "الوقت",
"hmgPolicies": "سياسات مجموعة الحبيب الطبية",
- "darkMode": "المظهر الداكن",
+ "darkMode": "الوضع الداكن",
"featureComingSoonDescription": "هذه الميزة ستتوفر قريباً. نحن نعمل جاهدين لإضافة ميزات أكثر تميزاً إلى التطبيق. انتظرونا لمتابعة التحديثات.",
- "generateAiAnalysisResult": "قم بإجراء تحليل لهذا المختبر AI",
+ "generateAiAnalysisResult": "تحليل النتائج بالذكاء الاصطناعي",
"ratings": "التقييمات",
- "hmgPharmacyText": "صيدلية الحبيب، المتجر الصيدلاني الإلكتروني المتكامل الذي تقدمه لكم مجموعة خدمات الدكتور سليمان الحبيب الطبية.",
+ "hmgPharmacyText": "وجهتك الالكترونية الشاملة للأدوية ومنتجات العناية بالصحة",
"insuranceRequestSubmittedSuccessfully": "تم إرسال طلب تحديث بيانات التأمين بنجاح. سيتم إعلامك بمجرد الانتهاء.",
"updatingEmailAddress": "جارٍ تحديث عنوان البريد الإلكتروني، يرجى الانتظار...",
"verifyInsurance": "التحقق من التأمين",
- "tests": "تحليل",
+ "tests": "تحاليل",
"calendarPermissionAlert": "يرجى منح إذن الوصول إلى التقويم من إعدادات التطبيق لضبط تذكير تناول الدواء.",
- "sortByNearestLocation": "فرز حسب الأقرب إلى موقعك",
+ "sortByNearestLocation": "حسب الأقرب الى موقعك",
"giveLocationPermissionForNearestList": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق لعرض أقرب المواقع.",
"sortByLocation": "الترتيب حسب الموقع",
- "timeForFirstReminder": "وقت التذكير الأول",
- "reminderRemovalNote": "يمكنك إزالتها من التقويم الخاص بك لاحقاً عن طريق إيقاف تشغيل التذكير",
+ "timeForFirstReminder": "اضافةتذكير",
+ "reminderRemovalNote": "يمكنك إلغاء التذكير لاحقاً من التقويم.",
"communicationLanguage": "لغة التواصل",
-
"cmcServiceHeader": "فحص صحي شامل: تشخيص متقدم، معلومات صحية مفصلة",
"cmcServiceDescription": "احصل على معلومات تفصيلية عن صحتك من خلال خدمات التشخيص المتقدمة لدينا. افهم جسمك بشكل أفضل لمستقبل صحي.",
"eReferralServiceHeader": "نظام الإحالة الإلكترونية في مستشفى حبيب: تبسيط عملية إحالة المرضى",
@@ -1650,19 +1682,19 @@
"emergencyServiceHeader": "تسجيل الوصول إلى قسم الطوارئ، أسرع من أي وقت مضى. اتصل بالإسعاف / فريق الاستجابة السريعة على الفور",
"emergencyServiceDescription": "هل تواجه حالة طبية طارئة؟ سيارات الإسعاف وفرق الاستجابة السريعة لدينا جاهزة على مدار الساعة. بالإضافة إلى ذلك، يمكنك تسجيل دخولك إلى قسم الطوارئ بسرعة لتلقي رعاية أسرع.",
"homeHealthCareServiceHeader": "صحتك، في أبهى صورها. رعاية فائقة الجودة، تصلك إلى عتبة دارك.",
- "homeHealthCareServiceDescription": "نقدم لكم رعاية صحية عالية الجودة تصلكم إلى عتبة منزلكم. ممرضات ذوات خبرة يقدمون رعاية حانية في راحة منزلكم.",
+ "homeHealthCareServiceDescription": "نقدم لكم رعاية صحية عالية الجودة تصلكم إلى عتبة منزلكم. ممرضات ذوات خبرةممرضات ذوات خبرة يقدمون لكم الرعاية اللازمة.",
"profileOnlyText": "الملف الشخصي",
- "information": "معلومة",
+ "information": "معلومات الطبيب",
"noFavouriteDoctors": "ليس لديك أي قائمة مفضلة حتى الآن",
"addDoctors": "إضافة الأطباء",
"favouriteList": "قائمة المفضلة",
"later": "لاحقاً",
"cancelAppointmentConfirmMessage": "هل أنت متأكد من رغبتك في إلغاء هذا الموعد؟",
- "acknowledged": "معترف به",
+ "acknowledged": "إغلاق",
"searchLabResults": "بحث نتائج المختبر",
"callForAssistance": "اتصل للحصول على المساعدة الفورية",
"oneWaySubtitle": "نقل من الموقع إلى المستشفى",
- "twoWaySubtitle": "نقل من الموقع إلى المستشفى والعودة مرة أخرى",
+ "twoWaySubtitle": "نقل من الموقع إلى المستشفى والعودة",
"toHospitalSubtitle": "نقل من موقعك الحالي إلى المستشفى",
"fromHospitalSubtitle": "نقل من المستشفى إلى منزلك",
"clinicSchedule": "جدول العيادة",
@@ -1673,18 +1705,18 @@
"pendingAncillaryOrders": "مدفوعات طلبات الاضافية",
"liveCarePermissions": "يتطلب لايف كير أذونات الكاميرا والميكروفون وإشعارات، يرجى السماح لها بالمتابعة.",
"containsImage": "يحتوي على صورة",
- "servicesSelected": "الخدمة (الخدمات) المختارة",
+ "servicesSelected": "الخدمة / الخدمات",
"selectMedicalFileFromFamily": "اختر ملف طبي من عائلتك",
"anyFileFromHMG": "أي ملف طبي نشط من مجموعة حبيب الطبية",
"noDistance": "المسافة غير متوفرة",
"enterAmount": "يرجى إدخال المبلغ للمتابعة.",
"selectHospitalContinue": "يرجى اختيار المستشفى للمتابعة.",
"year": "سنة",
- "notifyPrescription": "أبلغني قبل وقت الاستهلاك",
+ "notifyPrescription": "تنبيه قبل موعد الجرعة",
"doctorRatingAppointment": "طبيب\nتصنيف",
"ratingSubmitted": "تم إرسال التقييم",
"rateTheDoctor": "يرجى تقييم الطبيب",
- "downloadInvoice": "تحميل الفاتورة",
+ "downloadInvoice": "تحميل",
"approvalDetails": "تفاصيل الموافقة",
"obese": "سمين",
"overWeight": "وزن زائد",
@@ -1699,7 +1731,7 @@
"openCamera": "افتح الكاميرا",
"openGallery": "افتح المعرض",
"openFiles": "فتح الملفات",
- "generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير",
+ "generateAiAnalysisRadResult": "النتيجة بالذكاء الاصطناعي",
"grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل.",
"NoBookedAppointments": "لا توجد مواعيد محجوزة",
"aiDisclaimerRad": "سيتم مشاركة بيانات نتائج الأشعة الخاصة بك بشكل آمن مع محلل الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في توفير رؤى صحية مخصصة. هل ترغب في المتابعة؟",
@@ -1720,5 +1752,47 @@
"aiDisclaimerRad": "سيتم مشاركة بيانات نتائج الأشعة الخاصة بك بشكل آمن مع محلل الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في توفير رؤى صحية مخصصة. هل ترغب في المتابعة؟",
"sendingAskDrRequest": "جارٍ إرسال الطلب...",
"askDrRequestSentSuccess": "تم إرسال الطلب بنجاح، وسيتواصل معك الطبيب قريباً.",
- "onlineCheckIn24HoursOnly": "لا تتوفر خدمة تسجيل الوصول عبر الإنترنت إلا خلال 4 ساعات من موعد الحجز.لا تتوفر خدمة تسجيل الوصول عبر الإنترنت إلا خلال 4 ساعات من موعد الحجز."
+ "onlineCheckIn24HoursOnly": "لا تتوفر خدمة تسجيل الوصول عبر الإنترنت إلا خلال 4 ساعات من موعد الحجز.لا تتوفر خدمة تسجيل الوصول عبر الإنترنت إلا خلال 4 ساعات من موعد الحجز.",
+ "searchFor": "بحث عن",
+ "m": "متر",
+ "inch": "انش",
+ "updateEmailAddressTitle": "أدخل البريد الإلكتروني الجديد: ",
+ "enterNewNewContactNumber": "الرجاء اضافة رقم اتصال في حالة الطوارئ: ",
+ "nationalIdFileNumber": "رقم الهوية / الإقامة / الملف",
+ "finda": "البحث عن",
+ "errorFetchingData": "حدث خطأ أثناء تحميل البيانات",
+ "negative": "سلبي",
+ "calculateCaloriesBasedOnFactors": "حساب السعرات الحرارية اليومية بناءً على عدة عوامل مثل الطول، الوزن، العمر، الجنس، والنشاط البدني اليومي.",
+ "conformationCall": "سنتصل بك قريبًا لتأكيد الطلب",
+ "radiologyLabResults": "نتائج الأشعة",
+ "disclaimerRadiology": "تم تحليل نتائج الأشعة هذه بواسطة الذكاء الاصطناعي، وهي لا تُعدّ نصيحة طبية. استشر طبيبك المختص للتشخيص والعلاج.",
+ "enterIdentificationNumberWithNoStar": "أدخل رقم الهوية",
+ "enterReferralNumber": "أدخل رقم الإحالة",
+ "referralNumber": "رقم الإحالة",
+ "phoneHint": "5xxxxxxxx",
+ "selectSearchCriteria": "اختر معيار البحث",
+ "selectCriteria": "اختيار المعيار",
+ "locationServicesDisabled": "حالة الطقس غير متوفرة لتعطيل خدمات الموقع. يرجى تفعيل خدمات الموقع لتتمكن من رؤية معلومات الطقس.",
+ "selectDateTimeKey": "اختيار",
+ "medicalKey": "الطبية",
+ "doctors2": "أطباء",
+ "illurgyInfomation": "الحساسية",
+ "vaccineInfomation": "التطعيمات",
+ "approvals1": "موافقات",
+ "convertBloodcholesterolInfo":"حول قيمة كوليسترول الدم بين ملجم/ديسيلتر و مليمول/لتر",
+ "carbsAlert": "حساب نسب المغذيات (الكربوهيدرات ،البروتين والدهون) بالسعرات الحرارية والقرامات وفقا لنسب محددة مسبقا",
+ "bodyFatAlert": "يحسب بناءً على الحجم",
+ "ibwAlert": "حساب الوزن المثالي بناءً على الطول، الوزن، وبنية الجسم",
+ "glucoseAlert":"تغيير وحدات القياس بين مليجرام لكل ديسيلتر و ملي مول لكل لتر",
+ "selectBloodGroup": "اختر الفصيلة",
+ "routePrescription": "طريقة الاستخدام",
+ "noNearestER": "لا يوجد طوارئ قريب منك",
+ "loginToUseServiceLiveCare": "تحتاج إلى تسجيل الدخول لاستخدام هذه الخدمة",
+ "mldl": "مليجرام لكل ديسيلتر",
+ "mmol": "ملي مول لكل لتر",
+ "triglycerideInfo": "تغيير وحدات القياس بين مليجرام لكل ديسيلتر و ملي مول لكل لتر",
+ "selectSmartWatch": "تعيين",
+ "selectBloodDonationCity": "اختر المدينة",
+ "selectBloodDonationGender": "اختر الجنس",
+ "selectBloodType": "اختر الفصيلة"
}
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index 18484fc1..27373b5f 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -6,7 +6,7 @@
"noRatingAvailable": "No Rating Available",
"doctorDoesNotHaveRating": "This doctor does not have any ratings yet.",
"confirm": "Confirm",
- "loadingText": "Loading, please wait...",
+ "loadingText": "Please wait...",
"kilometerUnit": "KM",
"dashboardScreenToolbarTitle": "Home",
"settings": "Settings",
@@ -21,7 +21,7 @@
"mySchedule": "My Schedule",
"logout": "Logout",
"respirationRate": "Respiration Rate",
- "bookAppo": "Book Appointment",
+ "bookAppo": "New Appointment",
"searchBy": "Search By:",
"clinic": "Clinic",
"byClinic": "By Clinic",
@@ -40,7 +40,7 @@
"noResultFound": "No Result Found",
"noSearchResultFound": "No Result Found",
"pleaseEnterProductName": "Please Enter Product Name",
- "bookNow": "Book Now",
+ "bookNow": "New Appointment",
"docInfo": "Doctor Information",
"appoInfo": "Appointment Information",
"availableAppo": "Available Appointments",
@@ -69,7 +69,7 @@
"date": "Date",
"time": "Time",
"pendingPayment": "Pending for payment",
- "payNow": "Pay Now",
+ "payNow": "Payment",
"viewQR": "View QR Code",
"instruction": "Instructions",
"livecare": "LiveCare",
@@ -99,7 +99,7 @@
"onlinePaymentSubtitle": "Payment",
"cancelNocaps": "Cancel",
"setReminder": "Set Reminder",
- "nationalIdNumber": "National ID Number",
+ "nationalIdNumber": "National ID / Iqama",
"medicalFileNumber": "Medical File Number",
"loginregister": "Login / Register",
"poweredBy": "Powered by",
@@ -112,7 +112,7 @@
"yes": "Yes",
"no": "No",
"logintyperadio": " Choose from the below options to login to your medical file.",
- "registernow": "Register Now",
+ "registernow": "Register",
"nationalID": "Enter the Identification Number",
"nationalId": "National ID",
"fileNo": "File Number",
@@ -123,7 +123,7 @@
"profileInfo": "Please enter profile information",
"submit": "Submit",
"forgotDesc": "Enter the mobile number to receive the Medical File Number via SMS",
- "dob": "Birth Date:",
+ "dob": "Birth Date",
"hijriDate": "Hijri Date",
"gregorianDate": "Gregorian Date",
"verifyLoginWith": "Please choose one of the following options to verify",
@@ -196,6 +196,7 @@
"enterEmail": "Please Enter Email",
"family": "My Family",
"familyTitle": "My Family Files",
+ "familyTitle2": "My Family Files",
"addNewMember": "Add Family Member",
"sentRequests": "Sent Requests",
"recievedRequests": "Recieved Requests",
@@ -268,6 +269,7 @@
"userViewRequester": "User Wants to View Your Medical File",
"userView": "User Can View Your Medical File",
"parking": "Parking",
+ "parking2": "Parking",
"alhabiServices": "HMG Service",
"parkingTitle": "Car service, car service, service to save parking information, return to it later, 1- By clicking on (Read the code), save the parking data. 2- By clicking on the button (view my car park), it shows you the car’s location in Google Maps. 3- Read another position by pressing the Clear Position Data button.",
"parkingDescription": "Parking service is for you to scan the car location so you can find it easy on you way out. click on (scan parking) button to save the parking location, then (show my park) button will appear to show you the way for the parking. if you want to rescan parking QR just click on (Clear My Data).",
@@ -306,10 +308,12 @@
"vitalSignObese": "Obese",
"vitalSignOverweight": "Overweight",
"vitalSignUnderweight": "Underweight",
+ "vitalSignSkinny": "Underweight",
"myMedical": "Active",
"myMedicalSubtitle": "Medications",
"myDoctor": "My Doctors",
"myDoctorSubtitle": "List",
+ "myDoctorSubtitle2": "List",
"eye": "Eye",
"eyeSubtitle": "Measurement",
"insurance": "Insurance",
@@ -327,6 +331,7 @@
"monthly": "Monthly",
"monthlySubtitle": "Report",
"sick": "Sick",
+ "sick2": "Sick",
"sickSubtitle": "Leaves",
"myBalance": "My Balance",
"myBalanceSubtitle": "Credit",
@@ -438,7 +443,7 @@
"serviceInformation": "Service Information",
"homeHealthCare": "Home Health Care",
"noAppointmentAvailable": "No Available Appointments",
- "homeHealthCareText": "This service provides a set of home health care services, continuous and comprehensive follow-up in their places of residence for those who cannot access health facilities, such as (laboratory analyzes - radiology - vaccinations - physical therapy), etc.",
+ "homeHealthCareText": "Clinical excellence and specialized care in the comfort of your home",
"loginRegister": "Login/Register",
"orderLog": "Order Log",
"infoLab": "This service allows you to view the results of all laboratory tests performed in Al Habib Medical Group as well as sending the report via e-mail.",
@@ -484,8 +489,10 @@
"refferalSubTitle": "Service",
"healthCare": "Health Care",
"emergency": "Emergency",
+ "emergency2": "Emergency",
"erservices": "Emergency",
"services2": "Services",
+ "services3": "Services",
"cantSeeProfile": "To view your medical profile, please log in or register now",
"loginRegisterNow": "Login or Register Now",
"hmgPharmacy": "HMG Pharmacy",
@@ -694,11 +701,11 @@
"bikini": "Bikini",
"totalMinutes": "Total Minutes",
"feedback": "Feedback",
- "likeToHear": "We would love to hear the feedback, concerns on healthcare services and eServices experience. Please use the below form",
+ "likeToHear": "We would love to hear your feedback. If you have any concerns about healthcare services or eServices experience, please let us in the form below.",
"emptySubject": "Please enter the subject",
"emptyMessage": "Please enter message",
"selectAttachment": "Select Attachment",
- "complainAppo": "Complaint for appointment",
+ "complainAppo": "Complaint with appointment",
"complainAppoAlt": "Complaint without appointment",
"messageType": "Message Type",
"feedbackType": "Feedback Type",
@@ -757,6 +764,7 @@
"erConsultation": "This service allows you to make an online virtual consultation via video call directly with the doctor from anywhere at any time.",
"myInvoice": "List",
"invoiceList": "My Invoice",
+ "invoiceList2": "My Invoice",
"allInvoices": "All Invoices",
"hospitals": "Hospitals",
"clinics": "Clinics",
@@ -769,7 +777,7 @@
"livecarePoint2": "A Specialized doctor will contact you",
"livecarePoint3": "A Doctor will be able to see your full medical file history",
"livecarePoint4": "Free Medicine Delivery Available",
- "livecarePoint5": "No need to visit the service is in your place",
+ "livecarePoint5": "Consult our specialists remotely and manage your health whenever and wherever you are.",
"bookImmediateLivecare": "I accept to get the service immediately",
"bookVideoLivecare2": "I don't need to visit the clinic",
"noThankyou": "No Thanks",
@@ -783,11 +791,11 @@
"aboutApp": "About the app",
"aboutPoints": "Online Appointment Booking & rescheduling, Insurance approval status, Find A doctor, Ask your doctor, Medical prescriptions, Lab results, Hospitals contact numbers, Doctor profiles, Hospitals locations, Pharmacies Locations, Hospital's Virtual Tour, Official Social Media, Vaccines Schedule, Health Calculators, Other Services",
"termsConditions": "These Online Services Terms of Use (Service Terms) govern certain online services provided by Dr Sulaiman Al Habib Medical Services Group Company (HMG, we, us, our)...",
- "receiveOtpToast": "Where would you like to receive OTP?",
+ "receiveOtpToast": "OTP",
"enterPhoneNumber": "Enter Phone Number",
"enterEmailDesc": "Enter your email address to complete the process of creating a medical file",
"enterPhoneDesc": "Enter your phone number to receive OTP verification code",
- "pleaseChooseOption": "Please select from the below options to receive OTP",
+ "pleaseChooseOption": "Please select an option below to receive your OTP.",
"dontHaveAccount": "Don't have an account?",
"loginOrRegister": "Login or Register",
"myFiles": "My Files",
@@ -798,14 +806,14 @@
"readInstructions": "Read Instructions",
"searchLabReport": "Search Lab Report",
"prescriptionDeliveryError": "This clinic doesn't support refill",
- "prepareToElevate": "Prepared to elevate your health and well-being?",
+ "prepareToElevate": "Your wellness journey starts here.",
"iAcceptTermsConditions": "I Accept the Terms and Conditions",
"alreadyHaveAccount": "Already have an account?",
"loginNow": "Login Now",
"notice": "Notice",
"oR": "OR",
- "sendOTPWHATSAPP": "Send me OTP on Whatsapp",
- "sendOTPSMS": "Send me OTP on SMS",
+ "sendOTPWHATSAPP": "Whatsapp",
+ "sendOTPSMS": "SMS",
"fullName": "Full Name",
"married": "Married",
"uae": "United Arab Emirates",
@@ -814,8 +822,10 @@
"loginByOTP": "Login By OTP",
"guest": "Guest",
"switchAccount": "Switch Account",
- "allSet": "All Set! Now you can login with Face ID or Biometric",
+ "allSet": "Now you can login with Face ID or Biometric",
+ "quickLogin": "Quick Login",
"enableQuickLogin": "Enable Quick Login",
+ "enableQuickLoginBtn": "Enable Quick Login",
"enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric",
"notNow": "Not Now",
"pendingActivation": "Pending Activation",
@@ -841,7 +851,7 @@
"didntReceiveIt": "Didn't receive it?",
"resendOTP": "Resend",
"resendIn": "resend in",
- "pleaseEnterAnationalID": "Please enter a national ID",
+ "pleaseEnterAnationalID": "ID or Iqama number is required",
"pleaseEnterAFileNumber": "Please enter a file number",
"pleaseEnterAValidEmail": "Please enter a valid email",
"pleaseEnterFullName": "Please enter full name",
@@ -870,6 +880,7 @@
"monitor": "Monitor",
"noSpecialResult": "No Special Results",
"setTheDateRange": "Set The Date Range",
+ "selectDate": "Select Date",
"historyFlowchart": "History FlowChart",
"to": "to",
"startDate" : "Start Date",
@@ -882,7 +893,7 @@
"clearAllFilters": "Clear all filters",
"filters": "Filters",
"searchClinic": "Search Clinic",
- "walkin": "Walk In",
+ "walkin": "Booked",
"continueString": "Continue",
"laserClinic": "Laser Clinic",
"covid_info" :"Dr. Sulaiman Al Habib hospitals are conducting a test for the emerging corona virus and issuing travel certificates 24/7 in a short time and with high accuracy. Those wishing to benefit from this service can visit one of Dr. Sulaiman Al Habib branches to conduct a corona test within few minutes, and obtain the result within several hours. Corona Virus Covid 19 testing service with PCR technology to detect the virus according to the highest international standards and with the latest high-precision RT-PCR devices (American GeneXpert and others), That is approved by the Food and Drug Authority as well as by the Saudi Center for Infectious Diseases Prevention.",
@@ -910,7 +921,7 @@
"paymentFailedPleaseTryAgain": "Payment Failed! Please try again.",
"appointmentCheckIn": "Appointment check in",
"insuranceExpiredOrInactive": "Insurance expired or inactive",
- "totalAmountToPay": "Total amount to pay",
+ "totalAmountToPay": "Total Amount",
"vat15": "VAT 15%",
"general": "General",
"liveCare": "LiveCare",
@@ -925,15 +936,15 @@
"immediateConsultation": "Immediate Consultation",
"scheduledConsultation": "Scheduled Consultation",
"pharmaLiveCare": "Pharma LiveCare",
- "notSureHelpMeChooseClinic": "Not sure? help me choose a clinic!",
- "mentionYourSymptomsAndFindDoctors": "Mention your symptoms and find the list of doctors accordingly",
+ "notSureHelpMeChooseClinic": "Need help choosing a clinic?",
+ "mentionYourSymptomsAndFindDoctors": "Tell us your symptoms, and we’ll recommend the best-suited specialists for your care",
"immediateService": "Immediate service",
"noNeedToWaitGetMedicalConsultation": "No need to wait, you will get medical consultation immediately via video call",
"noVisitRequired": "No visit required",
- "doctorWillContact": "Doctor will contact",
- "specialisedDoctorWillContactYou": "A specialised doctor will contact you and will be able to view your medical history",
+ "doctorWillContact": "Doctor will contact you",
+ "specialisedDoctorWillContactYou": "A specialized doctor will contact you and will be able to view your medical history",
"freeMedicineDelivery": "Free medicine delivery",
- "offersFreeMedicineDelivery": "Offers free medicine delivery for the LiveCare appointment",
+ "offersFreeMedicineDelivery": "Receive free medicine delivery with your LiveCare appointment.",
"dentalChiefComplaints": "Dental Chief Complaints",
"viewAvailableAppointments": "View available appointments",
"doctorProfile": "Doctor Profile",
@@ -952,22 +963,22 @@
"viewNearestAppos": "View nearest available appointments",
"noDoctorFound": "No Doctor found for selected criteria...",
"yesPleasImInAHurry": "Yes please, I am in a hurry",
- "fetchingFeesPleaseWait": "Fetching fees, Please wait...",
+ "fetchingFeesPleaseWait": "Please wait...",
"noThanksPhysicalVisit": "No, Thanks. I would like a physical visit",
"offline": "Offline",
"videoCall": "Video Call",
- "liveVideoCallWithHMGDoctors": "Live Video Call with HMG Doctors",
- "liveAudioCallWithHMGDoctors": "Live Audio Call with HMG Doctors",
+ "liveVideoCallWithHMGDoctors": "Live video call with a specialist",
+ "liveAudioCallWithHMGDoctors": "Live audio call with a specialist",
"audioCall": "Audio Call",
"phoneCall": "Phone Call",
- "livePhoneCallWithHMGDoctors": "Live Phone Call with HMG Doctors",
- "reviewLiveCareRequest": "Review LiveCare Request",
- "selectedLiveCareType": "Selected LiveCare Type",
- "selectLiveCareCallType": "Select LiveCare call type",
+ "livePhoneCallWithHMGDoctors": "Live phone call with a specialist",
+ "reviewLiveCareRequest": "LiveCare Request Details",
+ "selectedLiveCareType": "LiveCare Type",
+ "selectLiveCareCallType": "LiveCare Call Type",
"confirmingLiveCareRequest": "Confirming LiveCare request, Please wait...",
"unknownErrorOccurred": "Unknown error occurred...",
"liveCarePermissionsMessage": "LiveCare requires Camera, Microphone, Location & Notifications permissions to enable virtual consultation between patient & doctor, Please allow these to proceed.",
- "liveCarePayment": "LiveCare Payment",
+ "liveCarePayment": "Payment",
"mada": "Mada",
"visaOrMastercard": "Visa or Mastercard",
"tamara": "Tamara",
@@ -990,7 +1001,7 @@
"bookingWaitingAppointment": "Booking Waiting Appointment, Please wait...",
"enterValidIDorIqama": "Please enter a valid national ID or file number",
"selectAppointment": "Select Appointment",
- "rebookSameDoctor": "Rebook with same doctor",
+ "rebookSameDoctor": "New Appointment",
"queueing": "Queueing",
"inQueue": "In Queue",
"yourTurn": "Your Turn",
@@ -1051,7 +1062,7 @@
"insuranceDocument": "Insurance Document",
"selectBranch": "Select Branch",
"patientInformation": "Patient information",
- "patientLocation": "Where the patient located",
+ "patientLocation": "Select the location of the patient",
"identificationNumber": "Identification Number",
"enterIdentificationNumber": "Enter Identification Number*",
"patientName": "Patient Name*",
@@ -1079,7 +1090,7 @@
"hereIsYourReferralNumber": "Here is your Referral #: ",
"searchEReferral": "Search E-Referral",
"enterRequiredInfoToSearch": "Please enter the required information to search for an e-referral",
- "selectPickupDirection": "Select Pickup Direction",
+ "selectPickupDirection": "Pickup Direction",
"selectDirection": "Select Direction",
"toHospital": "To Hospital",
"fromHospital": "From Hospital",
@@ -1090,9 +1101,9 @@
"pleaseSelectDetailsOfPickup": " Please select the details of pickup",
"selectDetails": "Select Details",
"work": "Work",
- "pick": "Pick",
- "insideTheHome": "Inside the home",
- "haveAnyAppointment": "Have any appointment",
+ "pick": "Pick up",
+ "insideTheHome": "From your home/Selected location",
+ "haveAnyAppointment": "Select if you have any appointment?",
"amountPaidAtHospital": "Amount will be paid at the hospital",
"submitRequest": "Submit Request",
"enterPickupLocationManually": "Enter Pickup Location Manually",
@@ -1125,26 +1136,33 @@
"allFacilities": "All Facilities",
"selectLocation": "Select Location",
"pleaseSelectTheLocation": "Please select the location",
- "viewLocationGoogleMaps": "View Location on Google Maps",
+ "viewLocationGoogleMaps": "Get Directions on Google Maps",
"callAmbulance": "Call Ambulance",
- "requestAmbulanceInEmergency": "Request an ambulance in emergency from home or hospital",
+ "requestAmbulanceInEmergency": "Request an ambulance for immediate assistance in cases of emergency.",
"confirmation": "Confirmation",
"areYouSureYouWantToCallAmbulance": "Are you sure you want to call an ambulance?",
- "getDetailsOfNearestBranch": "Get the details of nearest branch including directions",
+ "getDetailsOfNearestBranch": "Find the nearest ER and get directions.",
"areYouSureYouWantToCallRRT": "Are you sure you want to call Rapid Response Team (RRT)?",
- "priorERCheckInToSkipLine": "Prior ER Check-In to skip the line & payment at the reception.",
- "areYouSureYouWantToMakeERCheckIn": "Are you sure you want to make ER Check-In?",
- "checkingYourERAppointmentStatus": "Checking your ER Appointment status...",
+ "priorERCheckInToSkipLine": "Check in before you arrive to the ER to skip the line & payment at reception.",
+ "areYouSureYouWantToMakeERCheckIn": "Are you sure you want to request an online ER check-in?",
+ "checkingYourERAppointmentStatus": "Please Wait...",
"transportOptions": "Transport Options",
"selectHospitalForAdvancePayment": "Please select the hospital you want to make an advance payment for.",
- "recharge": "Recharge",
+ "recharge": "Add Funds",
"activityLevel": "Activity Level",
"selectActivityLevel": "Select Activity Level",
+ "almostInactive": "Almost Inactive (no exercise)",
+ "lightlyActive": "Lightly active",
+ "lightlyActive13Days": "Lightly active (1-3) days per week",
+ "superActive": "Super active (very hard exercise)",
"caloriesPerDay": "Calories Per Day",
"dietType": "Diet Type",
"selectDietType": "Select Diet Type",
"bodyFrameSize": "Body Frame Size",
"selectBodyFrameSize": "Select Body Frame Size",
+ "bodyFrameSmall": "Small (fingers overlaps)",
+ "bodyFrameMedium": "Medium (fingers touch)",
+ "bodyFrameLarge": "Large (fingers don't touch)",
"averageCycleLength": "Average Cycle Length (Usually 28 days)",
"averageLutealPhase": "Average Luteal Phase Length(Usually 14 days)",
"convert": "Convert",
@@ -1162,14 +1180,22 @@
"monitorCholesterolLevels": "Monitor cholesterol levels, assess heart health risks, and take proactive steps for well-being.",
"triglyceridesFatBlood": "Triglycerides Fat Blood",
"understandTriglyceridesImpact": "Understand triglycerides' impact on heart health with personalized insights and expert recommendations.",
- "bmiCalculator": "BMI\nCalculator",
- "caloriesCalculator": "Calories\nCalculator",
- "bmrCalculator": "BMR\nCalculator",
- "idealBodyWeight": "Ideal Body\nWeight",
- "bodyFatCalculator": "Body Fat\nCalculator",
- "carbsProteinFat": "Carbs\nProtein & Fat",
- "ovulationPeriod": "Ovulation\nPeriod",
- "deliveryDueDate": "Delivery\nDue Date",
+ "bmiCalculator": "BMI Calculator",
+ "bmiCalculatorDesc": "Calculate your body mass index to understand your healthy weight range.",
+ "caloriesCalculator": "Calories Calculator",
+ "caloriesCalculatorDesc": "Find out how many calories you need daily to maintain or lose weight.",
+ "bmrCalculator": "BMR Calculator",
+ "bmrCalculatorDesc": "Determine your basal metabolic rate and daily energy requirements.",
+ "idealBodyWeight": "Ideal Body Weight",
+ "idealBodyWeightDesc": "Discover your ideal weight based on height, age, and body structure.",
+ "bodyFatCalculator": "Body Fat Calculator",
+ "bodyFatCalculatorDesc": "Estimate your body fat percentage to track fitness and health goals.",
+ "carbsProteinFat": "Carbs Protein & Fat",
+ "carbsProteinFatDesc": "Balance your macros with the right carbs, protein, and fat ratios.",
+ "ovulationPeriod": "Ovulation Period",
+ "ovulationPeriodDesc": "Track your fertile window and plan for conception with accuracy.",
+ "deliveryDueDate": "Delivery Due Date",
+ "deliveryDueDateDesc": "Calculate your expected delivery date and monitor pregnancy milestones.",
"low": "Low",
"preDiabetic": "Pre-diabetic",
"high": "High",
@@ -1200,7 +1226,7 @@
"healthTrackers": "Health Trackers",
"monitorBloodPressureLevels": "Monitor your blood pressure levels, track systolic and diastolic readings, and maintain a healthy heart.",
"trackWeightProgress": "Track your weight progress, set goals, and maintain a healthy body mass for overall wellness.",
- "bookAppointment": "Book\nAppointment",
+ "bookAppointment": "New\nAppointment",
"completeCheckup": "Complete Checkup",
"indoorNavigation": "Indoor Navigation",
"eReferralServices": "E-Referral Services",
@@ -1210,10 +1236,11 @@
"healthConvertersServices": "Health\nConverters",
"smartWatchesServices": "Smart\nWatches",
"exploreServices": "Explore Services",
- "medicalAndCareServices": "Medical & Care Services",
+ "medicalAndCareServices": "Medical & Healthcare Services",
"hmgServices": "HMG Services",
"personalServices": "Personal Services",
- "habibWallet": "Habib Wallet",
+ "habibWallet": "HMG Wallet",
+ "habibWallet2": "Habib Wallet",
"loginToViewWalletBalance": "Login to view your wallet balance",
"loginToViewMedicalFile": "Login to view your medical file",
"addMember": "Add Member",
@@ -1245,8 +1272,8 @@
"stayHydratedDrinkWater": "Stay hydrated! Drink {amount}ml of water.",
"visitPharmacyOnline": "Visit Pharmacy Online",
"howAreYouFeelingToday": "How are you feeling today?",
- "checkYourSymptomsWithScale": "Check your symptoms with this scale",
- "checkYourSymptoms": "Check your symptoms",
+ "checkYourSymptomsWithScale": "Evaluate your symptoms and find the right care",
+ "checkYourSymptoms": "Symptom Checker",
"noUpcomingAppointmentPleaseBook": "You do not have any upcoming appointment. Please book an appointment",
"youHaveEROnlineCheckInRequest": "You have ER Online Check-In Request",
"quickLinks": "Quick Links",
@@ -1258,9 +1285,9 @@
"requestedServices": "Requested Services",
"selectServices": "Select Services",
"selectedServices": "Selected Services",
- "createNewRequest": "Create new request",
- "youHaveNoPendingRequests": "You have no pending requests.",
- "noInsuranceDataFound": "No insurance data found...",
+ "createNewRequest": "New Request",
+ "youHaveNoPendingRequests": "You have no pending requests",
+ "noInsuranceinsurance2DataFound": "No insurance data found...",
"noInsuranceUpdateRequest": "No insurance update requests found.",
"policyNumberInsurancePage": "Policy: {number}",
"insuranceExpired": "Insurance Expired",
@@ -1278,7 +1305,7 @@
"lastTested": "Last Tested",
"byVisit": "By Visit",
"byTest": "By Test",
- "results": "results",
+ "results": "Results",
"viewResults": "View Results",
"rebook": "Rebook",
"noOphthalmologyAppointments": "No Ophthalmology appointments found...",
@@ -1293,7 +1320,7 @@
"others": "Others",
"allergyInfo": "Allergy Info",
"vaccineInfo": "Vaccine Info",
- "updateInsuranceInfo": "Update Insurance",
+ "updateInsuranceInfo": "Insurance Update",
"myInvoicesList": "My Invoices List",
"ancillaryOrdersList": "Ancillary Orders List",
"youDontHaveAnySickLeavesYet": "You don't have any sick leaves yet.",
@@ -1303,6 +1330,7 @@
"askYourDoctor": "Ask Your Doctor",
"internetPairing": "Internet Pairing",
"requested": "Requested",
+ "readyToDownload": "Ready to download",
"youDontHaveAnyMedicalReportsYet": "You don't have any medical reports yet.",
"requestMedicalReport": "Request medical report",
"youDoNotHaveAnyAppointmentsToRequestMedicalReport": "You do not have any appointments to request a medical report.",
@@ -1344,7 +1372,7 @@
"downloadPrescription": "Download Prescription",
"fetchingPrescriptionDetails": "Fetching prescription details...",
"switchBackFamilyFile": "Switch Back To Family File",
- "profileAndSettings": "Profile & Settings",
+ "profileAndSettings": "Settings",
"quickActions": "Quick Actions",
"notificationsSettings": "Notifications Settings",
"touchIDFaceIDServices": "Touch ID / Face ID Services",
@@ -1448,6 +1476,8 @@
"setTimerOfReminder": "Set the timer of reminder",
"youHaveAppointmentWithDr": "You have appointment with Dr. ",
"hours": "Hours",
+ "minutes": "Minutes",
+ "seconds": "Seconds",
"secs": "Secs",
"noAllergiesDataFound": "No allergies data found...",
"heartRateDescription": "Your heart rate indicates how many times your heart beats per minute",
@@ -1457,6 +1487,7 @@
"distanceDescription": "Distance covered throughout the day",
"overview": "Overview",
"details": "Details",
+ "details2": "Details",
"healthy": "Healthy",
"warning": "Warning",
"vitalSignDetails": "Vital Sign Details",
@@ -1469,7 +1500,7 @@
"heightDescription": "Height is measured in centimeters and is used to calculate BMI and dosage recommendations.",
"weightDescription": "Weight helps track overall health, nutrition, and changes over time.",
"bloodPressureDescription": "Blood pressure reflects the force of blood against artery walls. It is shown as systolic/diastolic.",
- "temperatureDescription": "Body temperature reflects how hot your body is and may change with infection or inflammation.",
+ "temperatureDescription": "Body temperature is a vital sign that indicates how warm the body is. It may increase in response to immune triggers like infection or inflammation",
"heartRateDescriptionVital": "Heart rate refers to the number of heart beats per minute.",
"respiratoryRateDescription": "Respiratory rate is the number of breaths taken per minute.",
"bmiAdvice": "Maintain a balanced diet and regular activity. If your BMI is high or low, consider consulting your doctor.",
@@ -1509,7 +1540,7 @@
"route": "Route",
"frequency": "Frequency",
"reminders": "Reminders",
- "reminderAddedToCalendar": "Reminder added to calendar ✅",
+ "reminderAddedToCalendar": "Reminder added to calendar",
"errorWhileSettingCalendar": "Error while setting calendar: {error}",
"instructions": "Instructions",
"requests": "Requests",
@@ -1522,18 +1553,18 @@
"pleaseVisitRoomToTheDoctor": "Please visit Room {roomNumber} to the Doctor",
"erOnlineCheckInRequest": "ER Online Check-In Request",
"indoor": "Indoor",
- "navigation": "Navigation",
+ "thehospital": "Navigation",
"health": "Health",
"calculators": "Calculators",
"converters": "Converters",
"guide": "Guide",
- "liveCareServiceDesc": "Get medical advice with a specialist doctor Via a video call",
+ "liveCareServiceDesc": "Get medical advice from a specialist doctor via video call",
"bloodGroup": "Blood: {bloodType}",
"medicalServices": "Medical Services",
"insuranceAndPayments": "Insurance & Payments",
"trackerAndOthers": "Tracker & Others",
"bmi": "BMI",
- "yesPleaseINeedHelp": "Yes, Please I need help",
+ "yesPleaseINeedHelp": "Yes, Please",
"confirmYourLocation": "Confirm Your Location",
"confirmYourLocationDesc": "Please confirm your present location to view appropriate directions.",
"insideHospital": "I am inside the hospital",
@@ -1543,7 +1574,7 @@
"servicePriceListRights": "The patient has the right to a free follow-up within 14 days of initial visit",
"serviceName": "Service Name",
"noFreeSlot": "No free slot available for the selected date. Please select another date or check back later.",
- "noThanksIKnowTheClinic": "No, Thanks. I Know the clinic",
+ "noThanksIKnowTheClinic": "No, Thanks",
"unableToSendOTP": "Unable to send Verification OTP",
"aiOverView": "AI Overview",
"generateAiAnalysis": "Generate AI analysis for this order",
@@ -1551,7 +1582,7 @@
"prediction": "Prediction",
"prevention": "Prevention",
"disclaimer": "Disclaimer",
- "thisAboveInfo": "The above information is generated by AI based on your lab results and is intended for informational purposes only. It should not be considered a medical diagnosis or treatment plan. Always consult with your healthcare provider for personalized medical advice and before making any health-related decisions.",
+ "thisAboveInfo": "This Lab result was analyzed by AI, and it is not medical advice. Consult your healthcare provider for diagnosis and treatment.",
"aiDisclaimer": "Your lab result data will be securely shared with our AI Analyzer for analysis. This helps provide personalized health insights. Do you want to proceed?",
"consent": "Consent",
"bmiNormalDescription": "Your BMI is within the healthy range. Continue a balanced diet, regular physical activity, and routine checkups to maintain good health. Monitor any significant changes over time.",
@@ -1613,13 +1644,13 @@
"darkMode": "Dark Mode",
"generateAiAnalysisResult": "Generate AI analysis for this result",
"ratings": "Ratings",
- "hmgPharmacyText": "Al Habib Pharmacy, the complete online Pharmaceutical store brought to you by Dr. Sulaiman Al Habib Medical Services Group.",
+ "hmgPharmacyText": "Online pharmacy for a complete health shopping experience",
"insuranceRequestSubmittedSuccessfully": "Your insurance update request has been successfully submitted. You will be notified once completed.",
"updatingEmailAddress": "Updating email address, Please wait...",
"verifyInsurance": "Verify Insurance",
"tests": "tests",
"calendarPermissionAlert": "Please grant calendar access permission from app settings to set medication reminder.",
- "timeForFirstReminder": "Time for 1st reminder",
+ "timeForFirstReminder": "Add Reminder",
"reminderRemovalNote": "You can remove it from your calendar later by switching off the reminder",
"sortByLocation": "Sort by location",
"sortByNearestLocation": "Sort by nearest to your location",
@@ -1639,22 +1670,22 @@
"smartWatchServiceDescription": "Seamlessly connect your smartwatch to our health app for effortless data tracking and personalized insights.",
"liveChatServiceHeader": "24/7 Expert\nAssistance",
"liveChatServiceDescription": "Need help ? Our live chat connects you with expert support for any questions about features, settings, or troubleshooting.",
- "emergencyServiceHeader": "ER Check-in, Faster Than Ever. Call ambulance / Rapid Response Team instantly",
- "emergencyServiceDescription": "In a medical emergency? Our ambulances and rapid response teams are on standby 24/7. Plus, quick ER check-in for faster care.",
- "homeHealthCareServiceHeader": "Your Health, Elevated. Premium care, delivered to your doorstep.",
- "homeHealthCareServiceDescription": "We bring quality healthcare to your doorstep. Experienced nurses providing compassionate care in the comfort of your home.",
+ "emergencyServiceHeader": "Emergency Care, Faster than Ever.",
+ "emergencyServiceDescription": "Facing a medical emergency? Our ambulances are on standby 24/7 for your immediate assistance.",
+ "homeHealthCareServiceHeader": "Premium care, delivered right to your doorstep",
+ "homeHealthCareServiceDescription": "We provide the highest degree of patient care at home in a value-oriented, efficient, and professional manner.",
"profileOnlyText": "Profile",
"information": "Information",
- "noFavouriteDoctors": "You don't have any favourite list yet",
+ "noFavouriteDoctors": "You don't have any favorite list yet",
"addDoctors": "Add Doctors",
- "favouriteList": "Favourite List",
+ "favouriteList": "Favorite List",
"later": "Later",
"cancelAppointmentConfirmMessage": "Are you sure you want to cancel this appointment?",
"acknowledged": "Acknowledged",
"searchLabResults": "Search lab results",
"callForAssistance": "Call for immediate assistance",
"oneWaySubtitle": "Pickup from location to hospital",
- "twoWaySubtitle": "Round trip from location to hospital and back",
+ "twoWaySubtitle": "Round trip from location to hospital",
"toHospitalSubtitle": "Transfer from your current location to the hospital",
"fromHospitalSubtitle": "Transfer from the hospital back to your home",
"clinicSchedule": "Clinic Schedule",
@@ -1682,7 +1713,7 @@
"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.",
+ "RRTDDetails": "Comprehensive medical services for stable and urgent cases, available for all ages.",
"fromHospitalSubtitle": "Transfer from the hospital back to your home",
"normalMapType": "Default",
"satelliteMapType": "Satellite",
@@ -1712,5 +1743,48 @@
"aiDisclaimerRad": "Your radiology result data will be securely shared with our AI Analyzer for analysis. This helps provide personalized health insights. Do you want to proceed?",
"sendingAskDrRequest": "Sending Request...",
"askDrRequestSentSuccess": "Request has been sent successfully, The doctor will get back to you soon.",
- "onlineCheckIn24HoursOnly": "Online Check-In is only available within 4 hours of the appointment time."
+ "onlineCheckIn24HoursOnly": "Online Check-In is only available within 4 hours of the appointment time.",
+ "searchFor": "Search For",
+ "m": "m",
+"inch": "in",
+ "updateEmailAddressTitle": "Enter the new email address to be updated: ",
+ "enterNewNewContactNumber": "Enter the new emergency contact number to be updated: ",
+ "nationalIdFileNumber": "National ID/File Number",
+ "finda": "Find a",
+ "calculateCaloriesBasedOnFactors": "Calculates daily calorie intake based on several factors including: height, weight, age, gender and daily physical activity.",
+ "insurance2": "Insurance",
+ "conformationCall": "You will receive a call from HMG for confirmation ",
+ "radiologyLabResults": "Radiology Results",
+ "disclaimerRadiology": "This radiology result was analyzed by AI, and it is not medical advice. Consult your healthcare provider for diagnosis and treatment.",
+ "enterIdentificationNumberWithNoStar": "Enter Identification Number",
+ "enterReferralNumber": "Enter Referral Number",
+ "referralNumber": "Referral Number",
+ "phoneHint": "5xxxxxxxx",
+ "selectSearchCriteria": "Select the Search Criteria",
+ "selectCriteria": "Select Criteria",
+ "locationServicesDisabled": "Weather is unavailable because location services are disabled. Please enable location services to see the weather information.",
+ "selectDateTimeKey": "Select",
+ "carbsAlert":"Calculate carbohydrate based protein and fat ration in calories and grams according to a pre set ratio.",
+ "bodyFatAlert": "Estimate the total body fat based on the size.",
+ "ibwAlert": "Calculates the ideal body weight based on height, weight and body size.",
+ "glucoseAlert":"Convert blood glucose values between mg/dL and mmol/L. (1 mmol/L ≈ 18.0182 mg/dL)",
+ "selectBloodGroup": "Select Blood Group",
+ "routePrescription": "Route",
+ "noNearestER": "No nearest Er Around you",
+ "loginToUseServiceLiveCare": "Log In to Use This Service",
+ "medicalKey": "Medical",
+ "convertBloodcholesterolInfo": "Convert blood cholesterol values between mg/dL and mmol/L. ",
+ "mldl": "مليجرام لكل ديسيلتر",
+ "mmol": "ملي مول لكل لتر",
+ "triglycerideInfo": "Convert triglyceride values between mg/dL and mmol/L.",
+ "selectSmartWatch": "Select",
+ "selectBloodDonationCity": "Select City",
+ "selectBloodDonationGender": "Select Gender",
+ "selectBloodType": "Select Blood Type",
+ "doctors2": "Doctor",
+ "illurgyInfomation": "Allergy",
+ "vaccineInfomation": "Vaccine",
+ "approvals1": "Approvals"
}
+
+
diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart
index 374ac9d1..3c71281c 100644
--- a/lib/core/api/api_client.dart
+++ b/lib/core/api/api_client.dart
@@ -172,6 +172,7 @@ class ApiClientImp implements ApiClient {
// body['VersionID'] = ApiConsts.appVersionID.toString();
if (!isExternal) {
body['VersionID'] = ApiConsts.appVersionID.toString();
+ if(!isRCService)
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index bf9144fa..ff39fa70 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -189,6 +189,7 @@ class ApiConsts {
static final createEReferral = "Services/Patients.svc/REST/CreateEReferral";
static final getEReferrals = "Services/Patients.svc/REST/GetEReferrals";
+
//WATER CONSUMPTION
static String h2oGetUserProgress = "Services/H2ORemainder.svc/REST/H2O_GetUserProgress";
static String h2oInsertUserActivity = "Services/H2ORemainder.svc/REST/H2O_InsertUserActivity";
@@ -205,6 +206,9 @@ class ApiConsts {
static String updateDiabeticResult = 'Services/Patients.svc/REST/Patient_UpdateDiabtecResult';
static String deactivateDiabeticStatus = 'Services/Patients.svc/REST/Patient_DeactivateDiabeticStatus';
static String sendAverageBloodSugarReport = 'Services/Notifications.svc/REST/SendAverageBloodSugarReport';
+ static String averageBloodSugarReportDownload = 'Services/Notifications.svc/REST/SendAverageBloodSugarReportDownload';
+ static String averageWeightReportDownload = 'Services/Notifications.svc/REST/SendAverageBodyWeightReportDownload';
+ static String averageBloodPressureReportDownload = 'Services/Notifications.svc/REST/SendAverageBloodPressureReportDownload';
// Blood Pressure
static String getBloodPressureResultAverage = 'Services/Patients.svc/REST/Patient_GetBloodPressureResultAverage';
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 44ca3b10..107e06d1 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -17,6 +17,9 @@ class AppAssets {
static const String email = '$svgBasePath/email.svg';
static const String globe = '$svgBasePath/globe.svg';
static const String globeOther = '$svgBasePath/globe_other.svg';
+ static const String document = '$svgBasePath/document.svg';
+ static const String report = '$svgBasePath/report.svg';
+ static const String sucess = '$svgBasePath/sucess.svg';
// static const String globeOther = '$svgBasePath/globe_other.svg';
static const String cancel = '$svgBasePath/cancel.svg';
@@ -119,6 +122,8 @@ class AppAssets {
static const String search_by_region_icon = '$svgBasePath/search_by_region_icon.svg';
static const String location_red = '$svgBasePath/location_red.svg';
static const String location_unavailable = '$svgBasePath/location_unavailable.svg';
+ static const String location_unavailable_filled = '$svgBasePath/location_unavailable_filled.svg';
+ static const String location_unavailable_filled_background = '$svgBasePath/location_unavailable_filled_background.svg';
static const String livecare_clinic_icon = '$svgBasePath/livecare_clinic_icon.svg';
static const String immediate_service_icon = '$svgBasePath/immediate_service_icon.svg';
static const String no_visit_icon = '$svgBasePath/no_visit_icon.svg';
@@ -363,6 +368,14 @@ class AppAssets {
static const String files = '$svgBasePath/files.svg';
static const String online_checkin_icon = '$svgBasePath/online_checkin_icon.svg';
+ //Health Calculators
+ static const String bodyfatcalc = '$svgBasePath/bfc.svg';
+ static const String duedatecalc = '$svgBasePath/ddc.svg';
+ static const String idealbodyweightcacl = '$svgBasePath/ibwc.svg';
+ static const String ovluationperiod = '$svgBasePath/op.svg';
+ static const String bmicalc = '$svgBasePath/bmi1.svg';
+ static const String bmrcalc = '$svgBasePath/bmr1.svg';
+
// PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png';
static const String liveCareService = '$pngBasePath/livecare_service.png';
@@ -391,7 +404,7 @@ class AppAssets {
static const String lockIcon = '$pngBasePath/lock-icon.png';
static const String dummyUser = '$pngBasePath/dummy_user.png';
static const String comprehensiveCheckupEn = '$pngBasePath/cc_en.png';
- static const String comprehensiveCheckupAr = '$pngBasePath/cc_er.png';
+ static const String comprehensiveCheckupAr = '$pngBasePath/cc_ar.png';
static const String maleIcon = '$pngBasePath/male_icon.png';
static const String femaleIcon = '$pngBasePath/female_icon.png';
@@ -400,7 +413,13 @@ class AppAssets {
static const String fullBodyFrontFemale = '$pngBasePath/full_body_front_female.png';
static const String fullBodyBackFemale = '$pngBasePath/full_body_back_female.png';
static const String bmiFullBody = '$pngBasePath/bmi_image_1.png';
+ static const String bmiFullBodyFemale = '$pngBasePath/female_bmi.png';
static const String defaultMEP = '$pngBasePath/default_MEP.png';
+
+
+
+ static const String ambulance_section = '$pngBasePath/ambulance_section.png';
+ static const String rrt_section = '$pngBasePath/rrt_section.png';
}
class AppAnimations {
diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart
index 85fe9cb2..21f93eed 100644
--- a/lib/core/app_state.dart
+++ b/lib/core/app_state.dart
@@ -94,24 +94,33 @@ class AppState {
String? get getProfileImageData => _profileImageData;
set setProfileImageData(String? value) {
+ // Clear old data first
+ if (_profileImageData != null && _profileImageData != value) {
+ print('🔄 Replacing profile image: old data length=${_profileImageData!.length}, new data length=${value?.length ?? 0}');
+ }
+
+ // Set new value directly WITHOUT caching
_profileImageData = value;
- // Persist to cache
+
if (value != null && value.isNotEmpty) {
- cacheService.saveString(key: _profileImageKey, value: value);
+ print('✅ Profile image set (length: ${value.length}) - NO CACHE');
} else {
- cacheService.remove(key: _profileImageKey);
+ print('🗑️ Profile image cleared - NO CACHE');
}
}
- /// Load profile image from cache on app initialization
+ /// Load profile image from cache on app initialization - DISABLED
void _loadProfileImageFromCache() {
- _profileImageData = cacheService.getString(key: _profileImageKey);
+ // DO NOT LOAD FROM CACHE - always fetch fresh from API
+ _profileImageData = null;
+ print('📂 Profile image cache disabled - will fetch from API');
}
- /// Clear profile image from cache (e.g., on logout)
+ /// Clear profile image data (e.g., on logout or user switch)
void clearProfileImageCache() {
+ print('🧹 Clearing profile image data (was: ${_profileImageData != null ? "${_profileImageData!.length} chars" : "null"})');
_profileImageData = null;
- cacheService.remove(key: _profileImageKey);
+ print('✅ Profile image data cleared - NO CACHE');
}
SelectDeviceByImeiRespModelElement? _selectDeviceByImeiRespModelElement;
diff --git a/lib/core/cache_consts.dart b/lib/core/cache_consts.dart
index c1e06aa3..c829adbf 100644
--- a/lib/core/cache_consts.dart
+++ b/lib/core/cache_consts.dart
@@ -78,5 +78,6 @@ class CacheConst {
static const String isMonthlyReportEnabled = 'is-monthly-report-enabled';
static const String zoomRoomID = 'zoom-room-id';
+ static const String callTypeID = 'call-type-id';
static String isAppOpenedFromCall = "is_app_opened_from_call";
}
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index 3b7253db..3b9eefc0 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -64,6 +64,8 @@ import 'package:hmg_patient_app_new/features/todo_section/todo_section_repo.dart
import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart';
import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_repo.dart';
import 'package:hmg_patient_app_new/features/water_monitor/water_monitor_view_model.dart';
+import 'package:hmg_patient_app_new/features/weather/weather_repo.dart';
+import 'package:hmg_patient_app_new/features/weather/weather_view_model.dart';
import 'package:hmg_patient_app_new/features/health_trackers/health_trackers_view_model.dart';
import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
@@ -74,6 +76,7 @@ import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/services/notification_service.dart';
+import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart';
import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart';
import 'package:local_auth/local_auth.dart';
import 'package:logger/web.dart';
@@ -131,7 +134,6 @@ class AppDependencies {
navigationService: getIt(),
));
-
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
getIt.registerLazySingleton(() => NotificationServiceImp(
flutterLocalNotificationsPlugin: flutterLocalNotificationsPlugin,
@@ -164,13 +166,18 @@ class AppDependencies {
getIt.registerLazySingleton(() => SymptomsCheckerRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => BloodDonationRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => WaterMonitorRepoImp(loggerService: getIt(), apiClient: getIt()));
+ getIt.registerLazySingleton(() => WeatherRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => MyInvoicesRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => HealthTrackersRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => MonthlyReportRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => ActivePrescriptionsRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => TermsConditionsRepoImp(loggerService: getIt(), apiClient: getIt()));
- getIt.registerFactory(() => TermsConditionsViewModel(termsConditionsRepo: getIt(), errorHandlerService: getIt(),
- ),);
+ getIt.registerFactory(
+ () => TermsConditionsViewModel(
+ termsConditionsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ),
+ );
getIt.registerLazySingleton(() => MonthlyReportsRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => QrParkingRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => NotificationsRepoImp(loggerService: getIt(), apiClient: getIt()));
@@ -230,10 +237,10 @@ class AppDependencies {
);
getIt.registerLazySingleton(() => ProfileSettingsViewModel(
- cacheService: getIt(),
- profileSettingsRepo: getIt(),
- errorHandlerService: getIt(),
- ));
+ cacheService: getIt(),
+ profileSettingsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ));
getIt.registerLazySingleton(() => DateRangeSelectorRangeViewModel());
@@ -299,6 +306,8 @@ class AppDependencies {
getIt.registerLazySingleton(() => WaterMonitorViewModel(waterMonitorRepo: getIt(), errorHandlerService: getIt()));
+ getIt.registerLazySingleton(() => WeatherMonitorViewModel(weatherRepo: getIt(), errorHandlerService: getIt(), locationUtils: getIt()));
+
//commenting this because its already define there was on run time error because of this.
getIt.registerLazySingleton(() => MyInvoicesViewModel(myInvoicesRepo: getIt(), errorHandlerService: getIt(), navServices: getIt()));
@@ -307,22 +316,12 @@ class AppDependencies {
getIt.registerLazySingleton(() => NotificationsViewModel(notificationsRepo: getIt(), errorHandlerService: getIt()));
getIt.registerLazySingleton(() => HealthTrackersViewModel(healthTrackersRepo: getIt(), errorHandlerService: getIt()));
- getIt.registerLazySingleton(
- () => ActivePrescriptionsViewModel(
- errorHandlerService: getIt(),
- activePrescriptionsRepo: getIt()
- ),
- );
- getIt.registerFactory(
- () => QrParkingViewModel(
- qrParkingRepo: getIt(),
- errorHandlerService: getIt(),
- cacheService: getIt(),
- ),
- );
+ getIt.registerLazySingleton(() => ActivePrescriptionsViewModel(errorHandlerService: getIt(), activePrescriptionsRepo: getIt()));
+ getIt.registerFactory(() => QrParkingViewModel(qrParkingRepo: getIt(), errorHandlerService: getIt(), cacheService: getIt()));
getIt.registerLazySingleton(() => AskDoctorViewModel(askDoctorRepo: getIt(), errorHandlerService: getIt()));
getIt.registerLazySingleton(() => ServicesPriceListViewModel(servicesPriceListRepo: getIt(), errorHandlerService: getIt()));
+ getIt.registerLazySingleton(() => DateRangCalenderModel(appState: getIt(), navigationService: getIt(), dialogService: getIt()));
}
}
diff --git a/lib/core/enums.dart b/lib/core/enums.dart
index 8bb8330c..4ac919e7 100644
--- a/lib/core/enums.dart
+++ b/lib/core/enums.dart
@@ -5,8 +5,11 @@
// unverified,
// }
+import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
enum AuthMethodTypesEnum { sms, whatsApp, fingerPrint, faceID, moreOptions }
@@ -20,6 +23,17 @@ enum SelectionTypeEnum { dropdown, calendar, search, time }
enum GenderTypeEnum { male, female }
+extension GenderTypeEnumExtension on GenderTypeEnum {
+ String get displayName {
+ switch (this) {
+ case GenderTypeEnum.male:
+ return LocaleKeys.malE.tr();
+ case GenderTypeEnum.female:
+ return LocaleKeys.femaleGender.tr();
+ }
+ }
+}
+
enum MaritalStatusTypeEnum { single, married, divorced, widowed }
enum ChipTypeEnum { success, error, alert, info, warning, lightBg, primaryRed }
@@ -58,17 +72,17 @@ extension HealthCalculatorExtenshion on HealthCalculatorsTypeEnum {
bool isArabic = appState.getLanguageID() == 1 ? true : false;
switch (this) {
case HealthCalculatorsTypeEnum.bmi:
- return isArabic ? "حاسبة مؤشر كتلة الجسم" : "BMI Calculator";
+ return isArabic ? "مؤشر كتلة الجسم" : "BMI Calculator";
case HealthCalculatorsTypeEnum.calories:
- return isArabic ? "حاسبة السعرات الحرارية" : "Calories Calculator";
+ return isArabic ? "السعرات الحرارية" : "Calories Calculator";
case HealthCalculatorsTypeEnum.bmr:
- return isArabic ? "حاسبة معدل الأيض الأساسي" : "BMR Calculator";
+ return isArabic ? "معدل الايض" : "BMR Calculator";
case HealthCalculatorsTypeEnum.idealBodyWeight:
- return isArabic ? "الوزن المثالي للجسم" : "Ideal Body Weight Calculator";
+ return isArabic ? "الوزن المثالي" : "Ideal Body Weight Calculator";
case HealthCalculatorsTypeEnum.bodyFat:
- return isArabic ? "حاسبة الدهون في الجسم" : "Body Fat Calculator";
+ return isArabic ? "دهون الجسم" : "Body Fat Calculator";
case HealthCalculatorsTypeEnum.crabsProteinFat:
- return isArabic ? "حاسبة البروتين والدهون في سرطان البحر" : "Crabs Protein & Fat Calculator";
+ return isArabic ? "حاسبة المغذيات" : "Crabs Protein & Fat Calculator";
case HealthCalculatorsTypeEnum.ovulation:
return isArabic ? "فترة الإباضة" : "Ovulation Period";
case HealthCalculatorsTypeEnum.deliveryDueDate:
@@ -80,6 +94,22 @@ extension HealthCalculatorExtenshion on HealthCalculatorsTypeEnum {
case HealthCalculatorsTypeEnum.triglycerides:
return isArabic ? "الدهون الثلاثية في الدم" : "Triglycerides Fat Blood";
}
+ }
+
+ String get title {
+ AppState appState = getIt.get();
+ bool isArabic = appState.getLanguageID() == 1 ? true : false;
+ switch (this) {
+ case HealthCalculatorsTypeEnum.crabsProteinFat:
+ return isArabic ? "نتيجة المغذيات" : "Nutrient Results";
+ case HealthCalculatorsTypeEnum.calories:
+ return isArabic ? "سعراتك الحرارية" : "Calories";
+
+ case HealthCalculatorsTypeEnum.calories:
+ return isArabic ? "مؤشر كتلة الجسم" : "BMI";
+ default:
+ return "Your ${this.name.toCamelCase}";
+ }
}
static LoginTypeEnum? fromValue(int value) {
diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart
index c56c63d4..52a2e93d 100644
--- a/lib/core/location_util.dart
+++ b/lib/core/location_util.dart
@@ -89,7 +89,7 @@ class LocationUtils {
}
}
- LocationPermission permissionGranted = await Geolocator.checkPermission();
+ LocationPermission permissionGranted = await Geolocator.checkPermission();
if (permissionGranted == LocationPermission.denied) {
permissionGranted = await Geolocator.requestPermission();
if (permissionGranted != LocationPermission.whileInUse && permissionGranted != LocationPermission.always) {
@@ -257,6 +257,30 @@ class LocationUtils {
appState.userLong = locationData.longitude;
}
+ Future isLocationPermissionEnabled() async {
+ if (Platform.isIOS || (await isGMSDevice ?? true)) {
+ return await _isGMSLocationPermissionEnabled();
+ } else {
+ return await _isHMSLocationPermissionEnabled();
+ }
+ }
+
+ Future _isGMSLocationPermissionEnabled() async {
+ bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
+ if (!serviceEnabled) return false;
+
+ LocationPermission permission = await Geolocator.checkPermission();
+ return permission == LocationPermission.whileInUse || permission == LocationPermission.always;
+ }
+
+ Future _isHMSLocationPermissionEnabled() async {
+ bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
+ if (!serviceEnabled) return false;
+
+ LocationPermission permission = await Geolocator.checkPermission();
+ return permission == LocationPermission.whileInUse || permission == LocationPermission.always;
+ }
+
void getHMSLocation({VoidCallback? onFailure, Function(LatLng p1)? onSuccess, VoidCallback? onLocationDeniedForever}) async {
try {
var location = Location();
diff --git a/lib/core/utils/calender_utils_new.dart b/lib/core/utils/calender_utils_new.dart
index 6f043e26..bbf69119 100644
--- a/lib/core/utils/calender_utils_new.dart
+++ b/lib/core/utils/calender_utils_new.dart
@@ -16,33 +16,64 @@ class CalenderUtilsNew {
final DeviceCalendar calender = DeviceCalendar.instance;
List writableCalender = [];
- CalenderUtilsNew._instance() {
- getCalenders();
- }
+ /// Completer to ensure getCalenders() only runs once at a time
+ Completer? _calendarInitCompleter;
+
+ CalenderUtilsNew._instance();
static final CalenderUtilsNew instance = CalenderUtilsNew._instance();
- Future getCalenders() async {
+ /// Ensures calendars are loaded exactly once. Safe to call multiple times —
+ /// subsequent calls await the same future.
+ Future ensureCalendarsLoaded() async {
+ if (writableCalender.isNotEmpty) return;
+ if (_calendarInitCompleter != null) {
+ // Already in progress — just wait for it
+ return _calendarInitCompleter!.future;
+ }
+ _calendarInitCompleter = Completer();
+ try {
+ await _loadCalendars();
+ _calendarInitCompleter!.complete();
+ } catch (e) {
+ _calendarInitCompleter!.completeError(e);
+ _calendarInitCompleter = null; // Allow retry on failure
+ rethrow;
+ }
+ }
+
+ Future _loadCalendars() async {
+ print("the get calenders is called");
CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions();
if (result != CalendarPermissionStatus.granted) {
- // await DeviceCalendar.instance.requestPermissions();
- showCommonBottomSheetWithoutHeight(
- title: LocaleKeys.notice.tr(context: GetIt.instance().navigatorKey.currentContext!),
- GetIt.instance().navigatorKey.currentContext!,
- child: Utils.getWarningWidget(
- loadingText: LocaleKeys.calendarPermissionAlert.tr(),
- isShowActionButtons: true,
- onCancelTap: () {
- GetIt.instance().pop();
- },
- onConfirmTap: () async {
- GetIt.instance().pop();
- openAppSettings();
- }),
- callBackFunc: () {},
- isFullScreen: false,
- isCloseButtonVisible: true,
- );
+ await DeviceCalendar.instance.requestPermissions();
+ result = await DeviceCalendar.instance.hasPermissions();
+ // if (result != CalendarPermissionStatus.granted) {
+ // print("the permission is not granted");
+ // showCommonBottomSheetWithoutHeight(
+ // title: LocaleKeys.notice.tr(context: GetIt
+ // .instance()
+ // .navigatorKey
+ // .currentContext!),
+ // GetIt
+ // .instance()
+ // .navigatorKey
+ // .currentContext!,
+ // child: Utils.getWarningWidget(
+ // loadingText: LocaleKeys.calendarPermissionAlert.tr(),
+ // isShowActionButtons: true,
+ // onCancelTap: () {
+ // GetIt.instance().pop();
+ // },
+ // onConfirmTap: () async {
+ // GetIt.instance().pop();
+ // openAppSettings();
+ // }),
+ // callBackFunc: () {},
+ // isFullScreen: false,
+ // isCloseButtonVisible: true,
+ // );
+ // }
}
var calenders = await calender.listCalendars();
calenders.forEach((calender) {
@@ -52,21 +83,13 @@ class CalenderUtilsNew {
});
}
- FutureOr createOrUpdateEvent(
- {required String title,
- required String description,
- required String location,
- DateTime? scheduleDateTime,
- String? eventId,
- int? reminderMinutes}) async {
- if (writableCalender.isEmpty) {
- await getCalenders();
- }
+ FutureOr createOrUpdateEvent({required String title, required String description, required String location, DateTime? scheduleDateTime, String? eventId, int? reminderMinutes}) async {
+ await ensureCalendarsLoaded();
var writableCalendars = writableCalender.first;
String eventResult = "";
- CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions();
- if (result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions();
- print(result);
+ // CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions();
+ // if (result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions();
+ // print(result);
// String eventId = await getEventIdIfEventExist(title!.split("#").last);
// if (eventId.isEmpty) {
@@ -93,19 +116,19 @@ class CalenderUtilsNew {
// return eventId.isNotEmpty;
}
- FutureOr createMultipleEvents(
- {required int reminderMinutes,
- int? frequencyNumber,
- required int days,
- required String orderDate,
- required String itemDescriptionN,
- required String route,
- Function(String)? onFailure,
- String? prescriptionNumber,
- DateTime? scheduleDateTime,
- }) async {
+ FutureOr createMultipleEvents({
+ required int reminderMinutes,
+ int? frequencyNumber,
+ required int days,
+ required String orderDate,
+ required String itemDescriptionN,
+ required String route,
+ Function(String)? onFailure,
+ String? prescriptionNumber,
+ DateTime? scheduleDateTime,
+ }) async {
DateTime currentDay = DateTime.now();
- DateTime actualDate = scheduleDateTime??DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0);
+ DateTime actualDate = scheduleDateTime ?? DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0);
print("the frequency is $frequencyNumber");
frequencyNumber ??= 2; //Some time frequency number is null so by default will be 2
int interval = calculateIntervalAsPerFrequency(frequencyNumber);
@@ -152,9 +175,7 @@ class CalenderUtilsNew {
}
FutureOr checkIfEventExist(String admissionId) async {
- if (writableCalender.isEmpty) {
- await getCalenders();
- }
+ await ensureCalendarsLoaded();
List events = await getEvents();
if (events.isEmpty) return false;
for (var event in events) {
@@ -167,7 +188,7 @@ class CalenderUtilsNew {
FutureOr getEventIdIfEventExist(String admissionId) async {
if (writableCalender.isEmpty) {
- await getCalenders();
+ await ensureCalendarsLoaded();
}
List events = await getEvents();
if (events.isEmpty) return "";
@@ -180,7 +201,7 @@ class CalenderUtilsNew {
FutureOr checkAndRemove({required String id}) async {
if (writableCalender.isEmpty) {
- await getCalenders();
+ await ensureCalendarsLoaded();
}
List events = await getEvents();
if (events.isEmpty) return false;
@@ -197,7 +218,7 @@ class CalenderUtilsNew {
FutureOr checkAndRemoveMultipleItems({required String id}) async {
if (writableCalender.isEmpty) {
- await getCalenders();
+ await ensureCalendarsLoaded();
}
List events = await getEvents();
if (events.isEmpty) return false;
diff --git a/lib/core/utils/date_util.dart b/lib/core/utils/date_util.dart
index 6c4e7bec..5aa48b07 100644
--- a/lib/core/utils/date_util.dart
+++ b/lib/core/utils/date_util.dart
@@ -599,6 +599,17 @@ class DateUtil {
return '${hours} hr ${minutes} min';
}
+
+ /// Parses an ISO 8601 date string that may have more than 6 fractional-second digits.
+ /// e.g. '2026-04-12T12:07:35.4226413' → truncates to 6 digits before parsing.
+ static DateTime? parseISODate(String? date) {
+ if (date == null || date.isEmpty) return null;
+ final truncated = date.replaceFirstMapped(
+ RegExp(r'(\.\d{6})\d+'),
+ (m) => m.group(1)!,
+ );
+ return DateTime.tryParse(truncated);
+ }
}
extension OnlyDate on DateTime {
diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart
index e2925c29..c82c608d 100644
--- a/lib/core/utils/push_notification_handler.dart
+++ b/lib/core/utils/push_notification_handler.dart
@@ -9,17 +9,27 @@ import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_callkit_incoming/entities/android_params.dart';
+import 'package:flutter_callkit_incoming/entities/call_event.dart';
import 'package:flutter_callkit_incoming/entities/call_kit_params.dart';
import 'package:flutter_callkit_incoming/entities/ios_params.dart';
import 'package:flutter_callkit_incoming/entities/notification_params.dart';
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
import 'package:flutter_ios_voip_kit_karmm/call_state_type.dart';
import 'package:flutter_ios_voip_kit_karmm/flutter_ios_voip_kit.dart';
+import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/core/api/api_client.dart';
+import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:uuid/uuid.dart';
+// Global tracking variables for call state
+bool _isCallInProgress = false;
+String? _currentCallId;
+Timer? _callTimeoutTimer;
+String? _currentSessionId; // Store session ID for API call
+
// |--> Push Notification Background
@pragma('vm:entry-point')
Future backgroundMessageHandler(dynamic message) async {
@@ -39,30 +49,37 @@ callPage(String sessionID, String token) async {}
_incomingCall(Map data) async {
print('the value of the _incomingCall remote message is $data');
- // LandingPage.incomingCallData = IncomingCallData.fromJson(data);
- // var dataItem = await AppSharedPreferences().getObject('call_data');
- // if(dataItem != null ) return; // to stop repeated attempt to invoke the call
- // if (LandingPage.isOpenCallPage == false) {
- // LandingPage.isOpenCallPage = true;
+ // Check if there's already a call in progress to prevent duplicates
+ if (_isCallInProgress && _currentCallId != null) {
+ print('⚠️ Call already in progress (ID: $_currentCallId), ignoring duplicate notification');
+ return;
+ }
String roomID = data['session_id'] ?? '';
+ String callTypeID = data['AppointmentNo'] ?? '';
- // GetIt.instance().saveString(key: CacheConst.zoomRoomID, value: roomID);
- // GetIt.instance().saveBool(key: CacheConst.isAppOpenedFromCall, value: true);
+ // Generate unique call ID
+ var _currentUuid = Uuid().v4();
+ _currentCallId = _currentUuid;
+ _isCallInProgress = true;
+ _currentSessionId = roomID; // Store session ID for decline API call
+
+ print('📞 Starting new call with ID: $_currentCallId, Session: $_currentSessionId');
- Utils.saveStringFromPrefs(CacheConst.zoomRoomID, roomID);
- Utils.saveBoolFromPrefs(CacheConst.isAppOpenedFromCall, true);
+ await Utils.saveStringFromPrefs(CacheConst.zoomRoomID, roomID);
+ await Utils.saveStringFromPrefs(CacheConst.callTypeID, callTypeID);
+ await Utils.saveBoolFromPrefs(CacheConst.isAppOpenedFromCall, true);
WidgetsFlutterBinding.ensureInitialized();
- var _currentUuid = Uuid().v4();
+ int callKitType = callTypeID == '2' ? 0 : 1;
+
CallKitParams callKitParams = CallKitParams(
id: _currentUuid,
nameCaller: "Dr Al Habib",
appName: 'Dr Al Habib',
avatar: 'https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG',
- // handle: LandingPage.incomingCallData.name,
- type: 1,
+ type: callKitType,
textAccept: 'Accept',
textDecline: 'Decline',
missedCallNotification: NotificationParams(
@@ -78,7 +95,11 @@ _incomingCall(Map data) async {
callbackText: 'Hang Up',
),
duration: 30000,
- extra: {'userId': '1a2b3c4d'},
+ extra: {
+ 'userId': '1a2b3c4d',
+ 'callTypeID': callTypeID,
+ 'roomID': roomID,
+ },
headers: {'apiKey': 'Abc@123!', 'platform': 'flutter'},
android: const AndroidParams(
isImportant: true,
@@ -87,10 +108,10 @@ _incomingCall(Map data) async {
isShowLogo: false,
logoUrl: "https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG",
ringtonePath: 'system_ringtone_default',
- backgroundColor: '#ED1C2B',
+ backgroundColor: '#2E3039',
backgroundUrl: 'https://saudipedia.com/en/saudipediaen/uploads/images/2024/08/02/97358.jpg',
actionColor: '#4CAF50',
- textColor: '#000000',
+ textColor: '#FFFFFF',
incomingCallNotificationChannelName: "Incoming Call",
missedCallNotificationChannelName: "Missed Call",
isShowCallID: false),
@@ -111,12 +132,89 @@ _incomingCall(Map data) async {
ringtonePath: 'system_ringtone_default',
),
);
+
FlutterCallkitIncoming.unsilenceEvents();
await FlutterCallkitIncoming.showCallkitIncoming(callKitParams);
+ // Start 60-second timeout timer to auto-dismiss call
+ _callTimeoutTimer?.cancel(); // Cancel any existing timer
+ _callTimeoutTimer = Timer(Duration(seconds: 40), () async {
+ print('⏱️ Call timeout (60 seconds) - auto dismissing call notification');
+ await _endCallAndCleanup(_currentUuid);
+ });
+
await Future.delayed(Duration(milliseconds: 500));
}
+// Helper method to end call and cleanup
+Future _endCallAndCleanup(String callId, {bool isDeclined = false}) async {
+ try {
+ print('🧹 Cleaning up call: $callId');
+
+ // If call was declined, update session status via API
+ if (isDeclined && _currentSessionId != null && _currentSessionId!.isNotEmpty) {
+ await _updateSessionStatus(_currentSessionId!, 3, 'Patient');
+ }
+
+ // End the specific call
+ await FlutterCallkitIncoming.endCall(callId);
+
+ // Clear all calls to ensure clean state
+ await FlutterCallkitIncoming.endAllCalls();
+
+ // Reset tracking flags
+ _isCallInProgress = false;
+ _currentCallId = null;
+ _currentSessionId = null;
+
+ // Cancel timer
+ _callTimeoutTimer?.cancel();
+ _callTimeoutTimer = null;
+
+ // Clear cache
+ await Utils.saveBoolFromPrefs(CacheConst.isAppOpenedFromCall, false);
+ await Utils.saveStringFromPrefs(CacheConst.zoomRoomID, '');
+ await Utils.saveStringFromPrefs(CacheConst.callTypeID, '');
+
+ print('✅ Call and push notification cleanup completed successfully');
+ } catch (e) {
+ print('❌ Error during call cleanup: $e');
+ // Force reset flags even if there's an error
+ _isCallInProgress = false;
+ _currentCallId = null;
+ _currentSessionId = null;
+ _callTimeoutTimer?.cancel();
+ _callTimeoutTimer = null;
+ }
+}
+
+// Helper method to update session status via API
+Future _updateSessionStatus(String sessionId, int sessionStatus, String sessionEndedBy) async {
+ try {
+
+ final apiClient = getIt.get();
+
+ Map requestBody = {
+ "Open_SessionID": sessionId,
+ "SessionStatus": sessionStatus,
+ "SessionEndedBy": sessionEndedBy
+ };
+
+ await apiClient.post(
+ CHANGE_PATIENT_ER_SESSION,
+ body: requestBody,
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ print('✅ Session status updated successfully: $response');
+ },
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ print('❌ Failed to update session status: $error');
+ },
+ );
+ } catch (e) {
+ print('❌ Exception updating session status: $e');
+ }
+}
+
Future openCallPage(BuildContext context) async {
try {
// if (incomingCallData!.background == "0") {
@@ -282,6 +380,10 @@ class PushNotificationHandler {
try {
print('🎈 example: onDidRejectIncomingCall $uuid - $callerId');
timeOutTimer.cancel();
+ // Cleanup on reject with API call
+ if (_currentCallId != null) {
+ await _endCallAndCleanup(_currentCallId!, isDeclined: true);
+ }
} catch (err) {}
};
@@ -292,6 +394,12 @@ class PushNotificationHandler {
print('🎈 example: onDidAcceptIncomingCall $uuid - $callerId');
await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
await voIPKit.callConnected();
+
+ // Cleanup on accept - cancel timer and reset flags
+ _callTimeoutTimer?.cancel();
+ _callTimeoutTimer = null;
+ _isCallInProgress = false;
+ _currentCallId = null;
await Future.delayed(Duration(seconds: 2)).then((val) async {
await voIPKit.endCall();
});
diff --git a/lib/core/utils/request_utils.dart b/lib/core/utils/request_utils.dart
index bb947398..4d4ae4b5 100644
--- a/lib/core/utils/request_utils.dart
+++ b/lib/core/utils/request_utils.dart
@@ -1,7 +1,6 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
-import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
@@ -12,6 +11,7 @@ import 'package:hmg_patient_app_new/features/authentication/models/request_model
import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart';
import 'package:hmg_patient_app_new/features/common/models/commong_authanticated_req_model.dart';
import 'package:hmg_patient_app_new/features/common/models/family_file_request.dart';
+import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart';
class RequestUtils {
static dynamic getPatientAuthenticationRequest({
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index bc4b82c0..615641b5 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -820,6 +820,28 @@ class Utils {
// return Image.asset(icon, width: width, height: height, fit: fit, );
}
+ static Widget buildImgWithAssetsWithBorderRadius({
+ required String icon,
+ Color? iconColor,
+ bool isDisabled = false,
+ double? width,
+ double? height,
+ BoxFit fit = BoxFit.cover,
+ double? border,
+ double? borderRadius,
+ }) {
+ final iconH = height ?? 24.h;
+ final iconW = width ?? 24.w;
+ return Container(
+ width: iconW, height: iconH,
+ decoration: BoxDecoration(
+ border: border != null ? Border.all(color: AppColors.whiteColor, width: border) : null,
+ borderRadius: borderRadius != null ? BorderRadius.circular(borderRadius ?? 12.r) : null,
+ image: DecorationImage(image: AssetImage(icon,), fit: fit)
+ ),
+ );
+ }
+
/// Widget to build an SVG from network
static Widget buildImgWithNetwork({
required String url,
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 5db5b289..7a71b345 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -322,8 +322,10 @@ extension EmailValidator on String {
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: getIt.get().getLanguageCode() == "ar" ? 'CairoArabic' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
+
+ height: getIt.get().getLanguageCode() == "ar" ? 1.2 : 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(
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index 45c2d620..eb922652 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -6,7 +6,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:get_it/get_it.dart';
-import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
@@ -42,6 +41,7 @@ import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
+import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
@@ -152,10 +152,12 @@ class AuthenticationViewModel extends ChangeNotifier {
void onDobChange(String? date) {
if (calenderType == CalenderEnum.hijri) {
- var hijriDate = HijriGregConverter.gregorianToHijri(DateTime.parse(date!));
+ // Use DateRangCalenderModel for accurate Umm al-Qura conversion
+ final calendarModel = DateRangCalenderModel(appState: _appState, navigationService: _errorHandlerService, dialogService: _dialogService);
+ var hijriDate = calendarModel.gregorianToHijri(DateTime.parse(date!));
DateTime hijriDateTimeForController = DateTime(hijriDate.year, hijriDate.month, hijriDate.day);
dob = Utils.formatDateForApi(date);
- dobController.text = Utils.formatHijriDateToDisplay(hijriDateTimeForController.toIso8601String()); // Or directly hijriDate.toString() if that's what your formatter expects
+ dobController.text = Utils.formatHijriDateToDisplay(hijriDateTimeForController.toIso8601String());
} else {
dobController.text = Utils.formatDateToDisplay(date!);
dob = Utils.formatDateForApi(date);
@@ -897,7 +899,13 @@ class AuthenticationViewModel extends ChangeNotifier {
}
final resultEither = await _authenticationRepo.checkPatientForRegistration(commonAuthanticatedRequest: nRequest);
- resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
+ resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure, onUnHandledFailure: (failur) {
+
+ LoaderBottomSheet.hideLoader();
+ _dialogService.showExceptionBottomSheet(message: failur.message, onOkPressed: () {
+ _navigationService.pop();
+ });
+ }), (apiResponse) async {
checkUserStatusForRegistration(response: apiResponse.data, request: request);
});
}
@@ -907,6 +915,7 @@ class AuthenticationViewModel extends ChangeNotifier {
// 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);
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async {
if (apiResponse.data is String) {
@@ -926,6 +935,8 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pushAndRemoveUntil(CustomPageRoute(page: LandingNavigation()), (r) => false);
_navigationService.push(CustomPageRoute(page: LoginScreen()));
});
+ } else {
+ print("=========");
}
}
});
@@ -1109,7 +1120,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_dialogService.showPhoneNumberPickerSheet(
// label: "Where would you like to receive OTP?",
label: LocaleKeys.receiveOtpToast.tr(),
- message: "Please select from the below options to receive OTP.",
+ message: _appState.isArabic() ? "يرجى الاختيار من الخيارات أدناه لاستلام رمز التحقق." "Please select from the below options to receive OTP.",
onSMSPress: () {
checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms);
},
@@ -1240,6 +1251,12 @@ class AuthenticationViewModel extends ChangeNotifier {
try {
log("Fetching profile image for patient ID: $patientID");
+
+ // IMPORTANT: Clear old cache BEFORE fetching new image
+ // This ensures old data is removed immediately
+ _appState.clearProfileImageCache();
+ log("🧹 Cleared profile image cache before fetch");
+
final profileSettingsRepo = GetIt.instance();
final result = await profileSettingsRepo.getProfileImage(patientID: patientID);
@@ -1247,6 +1264,8 @@ class AuthenticationViewModel extends ChangeNotifier {
(failure) {
// Silently fail - profile image is optional
log("Failed to fetch profile image: ${failure.message}");
+ // Ensure cache is cleared even on failure
+ _appState.setProfileImageData = null;
},
(apiResponse) {
if (apiResponse.data != null && apiResponse.data['Patient_GetProfileImageDataList'] != null) {
@@ -1254,21 +1273,26 @@ class AuthenticationViewModel extends ChangeNotifier {
if (imageList is List && imageList.isNotEmpty) {
String? imageData = imageList[0]['ImageData'];
if (imageData != null && imageData.isNotEmpty) {
+ // Set new profile image data - this will update cache and notify all listeners
_appState.setProfileImageData = imageData;
- log("✅ Profile image loaded and cached successfully");
+ log("✅ Profile image loaded and cached successfully for patient: $patientID");
} else {
- log("⚠️ Profile image data is empty");
+ log("⚠️ Profile image data is empty for patient: $patientID");
+ _appState.setProfileImageData = null;
}
} else {
- log("⚠️ Profile image list is empty");
+ log("⚠️ Profile image list is empty for patient: $patientID");
+ _appState.setProfileImageData = null;
}
} else {
- log("⚠️ No profile image data in response");
+ log("⚠️ No profile image data in response for patient: $patientID");
+ _appState.setProfileImageData = null;
}
},
);
} catch (e) {
log("❌ Error fetching profile image: $e");
+ _appState.setProfileImageData = null;
}
}
}
diff --git a/lib/features/authentication/widgets/otp_verification_screen.dart b/lib/features/authentication/widgets/otp_verification_screen.dart
index 9e80dbb9..b3b5e3eb 100644
--- a/lib/features/authentication/widgets/otp_verification_screen.dart
+++ b/lib/features/authentication/widgets/otp_verification_screen.dart
@@ -558,9 +558,9 @@ class _OTPVerificationScreenState extends State {
LocaleKeys.via.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
(widget.isFormFamilyFile ? LoginTypeEnum.sms.displayName : authVM.loginTypeEnum.displayName)
.toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4),
- appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true
- ? LocaleKeys.forRegistrationVerification.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
- : LocaleKeys.forLoginVerification.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
+ // appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true
+ // ? LocaleKeys.forRegistrationVerification.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
+ // : LocaleKeys.forLoginVerification.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
],
),
diff --git a/lib/features/emergency_services/emergency_services_repo.dart b/lib/features/emergency_services/emergency_services_repo.dart
index 10c5541a..582c4a58 100644
--- a/lib/features/emergency_services/emergency_services_repo.dart
+++ b/lib/features/emergency_services/emergency_services_repo.dart
@@ -183,7 +183,7 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@override
Future>>> getProjectList() async {
- Map request = {'IsOnlineCheckIn': true, 'IsAdvancePayment': false, 'IsForER': true};
+ Map request = {"IsEROnlineCheckIn":true,'IsOnlineCheckIn': false, 'IsAdvancePayment': false, 'IsForER': true};
try {
GenericApiModel>? apiResponse;
diff --git a/lib/features/emergency_services/emergency_services_view_model.dart b/lib/features/emergency_services/emergency_services_view_model.dart
index c8a16455..83d2a564 100644
--- a/lib/features/emergency_services/emergency_services_view_model.dart
+++ b/lib/features/emergency_services/emergency_services_view_model.dart
@@ -54,6 +54,7 @@ import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
import 'package:hmg_patient_app_new/widgets/order_tracking/order_tracking_state.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:huawei_map/huawei_map.dart' as HMSCameraServices;
+import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../location/GeocodeResponse.dart';
@@ -274,7 +275,6 @@ class EmergencyServicesViewModel extends ChangeNotifier {
void navigateTOAmbulancePage() {
placeValueInController();
- getProjects();
flushData();
selectedFacility = FacilitySelection.ALL;
@@ -282,6 +282,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
locationUtils!.getLocation(
isShowConfirmDialog: true,
onSuccess: (position) {
+ getProjects();
updateBottomSheetState(BottomSheetType.FIXED);
navServices.push(
CustomPageRoute(page: CallAmbulancePage(), direction: AxisDirection.down),
@@ -310,17 +311,21 @@ class EmergencyServicesViewModel extends ChangeNotifier {
}
void updateBottomSheetState(BottomSheetType sheetType) {
- if (sheetType == BottomSheetType.EXPANDED && selectedHospital == null) {
- dialogService.showErrorBottomSheet(message: LocaleKeys.selectHospital.tr());
- return;
- }
+ // if (sheetType == BottomSheetType.EXPANDED && selectedHospital == null) {
+ // dialogService.showErrorBottomSheet(message: LocaleKeys.selectHospital.tr());
+ // return;
+ // }
bottomSheetType = sheetType;
- if (sheetType == BottomSheetType.EXPANDED) {
- clearAppointmentData();
- }
+ // if (sheetType == BottomSheetType.FIXED) {
+ // clearAppointmentData();
+ // }
notifyListeners();
}
+ void showError(String message) {
+ dialogService.showErrorBottomSheet(message: message);
+ }
+
void setIsGMSAvailable(bool value) {
notifyListeners();
}
@@ -732,6 +737,10 @@ class EmergencyServicesViewModel extends ChangeNotifier {
}
FutureOr submitAmbulanceRequest(GeocodeResult? result, PlaceDetails? place, PlacePrediction? placePrediction) async {
+ if (false == haveAnAppointment && null == selectedHospital) {
+ dialogService.showErrorBottomSheet(message: LocaleKeys.selectHospital.tr());
+ return;
+ }
PatientER_RC request = createRequest(result, place, placePrediction);
navServices.push(CustomPageRoute(page: RequestingServicesPage()));
@@ -802,19 +811,19 @@ class EmergencyServicesViewModel extends ChangeNotifier {
request.patientERTransportationMethod = selectedTransportOption;
transportationDetails.pickupUrgency = 1;
switch (callingPlace) {
- case AmbulanceCallingPlace.FROM_HOSPITAL:
- transportationDetails.dropoffLatitude = selectedHospital!.latitude;
- transportationDetails.dropoffLongitude = selectedHospital!.longitude;
- transportationDetails.dropoffLocationName = selectedHospital!.name;
+ case AmbulanceCallingPlace.TO_HOSPITAL:
+ transportationDetails.dropoffLatitude = selectedHospital?.latitude;
+ transportationDetails.dropoffLongitude = selectedHospital?.longitude;
+ transportationDetails.dropoffLocationName = selectedHospital?.name;
transportationDetails.pickupLatitude = ((result?.geometry.location.lat) ?? place?.lat)?.toStringAsFixed(6);
transportationDetails.pickupLongitude = ((result?.geometry.location.lng) ?? place?.lng)?.toStringAsFixed(6);
transportationDetails.pickupLocationName = result?.formattedAddress ?? placePrediction?.description;
transportationDetails.direction = 1;
break;
- case AmbulanceCallingPlace.TO_HOSPITAL:
- transportationDetails.pickupLatitude = selectedHospital!.latitude;
- transportationDetails.pickupLongitude = selectedHospital!.longitude;
- transportationDetails.pickupLocationName = selectedHospital!.name;
+ case AmbulanceCallingPlace.FROM_HOSPITAL:
+ transportationDetails.pickupLatitude = selectedHospital?.latitude;
+ transportationDetails.pickupLongitude = selectedHospital?.longitude;
+ transportationDetails.pickupLocationName = selectedHospital?.name;
transportationDetails.dropoffLatitude = ((result?.geometry.location.lat) ?? place?.lat)?.toStringAsFixed(6);
transportationDetails.dropoffLongitude = ((result?.geometry.location.lng) ?? place?.lng)?.toStringAsFixed(6);
transportationDetails.dropoffLocationName = result?.formattedAddress ?? placePrediction?.description;
@@ -986,19 +995,47 @@ class EmergencyServicesViewModel extends ChangeNotifier {
this.currentlyDisplayedOrder = currentlyDisplayedOrder;
switch (currentlyDisplayedOrder) {
case OrderDislpay.ALL:
- orderDisplayList = allOrders;
+ orderDisplayList = List.from(allOrders);
break;
case OrderDislpay.RRT:
- orderDisplayList = ordersRRT?.completedOrders ?? [];
+ orderDisplayList = List.from(ordersRRT?.completedOrders ?? []);
break;
case OrderDislpay.AMBULANCE:
- orderDisplayList = ambulanceOrders ?? [];
+ orderDisplayList = List.from(ambulanceOrders ?? []);
break;
}
+
+ orderDisplayList = _sortOrdersByDate(orderDisplayList);
notifyListeners();
}
- void openRRT() {
+ List _sortOrdersByDate(List list) {
+ list.sort((a, b) {
+ final int? dateA = _parseCreatedDate(a)?.millisecondsSinceEpoch;
+ final int? dateB = _parseCreatedDate(b)?.millisecondsSinceEpoch;
+ print("the dateA is $dateA and dateB is $dateB");
+ if (dateA == null && dateB == null) return 0;
+ if (dateA == null) return 1;
+ if (dateB == null) return -1;
+ return dateB.compareTo(dateA);
+ });
+ return list;
+ }
+
+ DateTime? _parseCreatedDate(dynamic order) {
+ final String? raw = _getCreatedDate(order);
+
+
+ return DateTime.tryParse(raw??"");
+ }
+
+ String? _getCreatedDate(dynamic order) {
+ if (order is AmbulanceRequestOrdersModel) return order.created;
+ if (order is GetCMCAllOrdersResponseModel) return order.created;
+ return null;
+ }
+
+ void openRRT(BuildContext context) {
if (appState.isAuthenticated) {
if (agreedToTermsAndCondition == false) {
dialogService.showErrorBottomSheet(
@@ -1032,6 +1069,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
return;
}
placeValueInController();
+ context.read().placeValueInController();
locationUtils!.getLocation(
isShowConfirmDialog: true,
onSuccess: (position) async {
diff --git a/lib/features/health_trackers/health_trackers_repo.dart b/lib/features/health_trackers/health_trackers_repo.dart
index 2a64fc46..52bc40f6 100644
--- a/lib/features/health_trackers/health_trackers_repo.dart
+++ b/lib/features/health_trackers/health_trackers_repo.dart
@@ -15,6 +15,9 @@ abstract class HealthTrackersRepo {
/// Get blood sugar results (week, month, year).
Future>> getDiabeticResults();
+ Future>> downloadBloodSugarReport();
+ Future>> downloadWeightReport();
+ Future>> downloadBloodPressureReport();
/// Add new blood sugar result.
Future>> addDiabeticResult({
@@ -211,6 +214,114 @@ class HealthTrackersRepoImp implements HealthTrackersRepo {
}
}
+ @override
+ Future>> downloadBloodSugarReport() async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ await apiClient.post(
+ ApiConsts.averageBloodSugarReportDownload,
+ body: {},
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ dynamic pdf = response['ReportPDFContent'];
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: pdf,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+
+ @override
+ Future>> downloadWeightReport() async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ await apiClient.post(
+ ApiConsts.averageWeightReportDownload,
+ body: {},
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ dynamic pdf = response['ReportPDFContent'];
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: pdf,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+ @override
+ Future>> downloadBloodPressureReport() async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ await apiClient.post(
+ ApiConsts.averageBloodPressureReportDownload,
+ body: {},
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ dynamic pdf = response['ReportPDFContent'];
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: pdf,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
@override
Future>> addDiabeticResult({
required String bloodSugarDateChart,
diff --git a/lib/features/health_trackers/health_trackers_view_model.dart b/lib/features/health_trackers/health_trackers_view_model.dart
index ab54f595..6b16fdc3 100644
--- a/lib/features/health_trackers/health_trackers_view_model.dart
+++ b/lib/features/health_trackers/health_trackers_view_model.dart
@@ -1,6 +1,10 @@
import 'dart:developer';
+import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
+import 'package:hmg_patient_app_new/core/app_state.dart';
+import 'package:hmg_patient_app_new/core/dependencies.dart';
+import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/health_trackers/health_trackers_repo.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/blood_pressure/blood_pressure_result.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/blood_pressure/month_blood_pressure_result_average.dart';
@@ -14,7 +18,9 @@ import 'package:hmg_patient_app_new/features/health_trackers/models/weight/month
import 'package:hmg_patient_app_new/features/health_trackers/models/weight/week_weight_measurement_result_average.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/weight/weight_measurement_result.dart';
import 'package:hmg_patient_app_new/features/health_trackers/models/weight/year_weight_measurement_result_average.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
class HealthTrackersViewModel extends ChangeNotifier {
HealthTrackersRepo healthTrackersRepo;
@@ -28,13 +34,25 @@ class HealthTrackersViewModel extends ChangeNotifier {
String? get errorMessage => _errorMessage;
- List get durationFilters => ["Week", "Month", "Year"];
+ final List durationFiltersEn = ["Week", "Month", "Year"];
+ final List durationFiltersAr = ["أسبوع", "شهر", "سنة"];
+
+ List get durationFilters => getIt.get().isArabic() ? durationFiltersAr : durationFiltersEn;
String _selectedDuration = "Week";
bool _isGraphView = true;
String get selectedDurationFilter => _selectedDuration;
+ // Get the localized display value for the selected duration
+ String get selectedDurationFilterDisplay {
+ final index = durationFiltersEn.indexOf(_selectedDuration);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? durationFiltersAr[index] : durationFiltersEn[index];
+ }
+ return _selectedDuration;
+ }
+
bool get isGraphView => _isGraphView;
final List bloodSugarUnit = ['mg/dlt', 'mol/L'];
@@ -72,6 +90,10 @@ class HealthTrackersViewModel extends ChangeNotifier {
"آخر",
];
+ List getBloodSugarTimeList(){
+ return getIt.get().isArabic()?bloodSugarMeasureTimeArList:bloodSugarMeasureTimeEnList;
+ }
+
// Setters with notification
void setBloodSugarMeasureTime(String duration) async {
_selectedBloodSugarMeasureTime = duration;
@@ -80,7 +102,15 @@ class HealthTrackersViewModel extends ChangeNotifier {
// Setters with notification
void setFilterDuration(String duration) async {
- _selectedDuration = duration;
+ // Map Arabic values to English keys
+ if (getIt.get().isArabic()) {
+ final index = durationFiltersAr.indexOf(duration);
+ if (index >= 0 && index < durationFiltersEn.length) {
+ _selectedDuration = durationFiltersEn[index];
+ }
+ } else {
+ _selectedDuration = duration;
+ }
notifyListeners();
}
@@ -97,26 +127,73 @@ class HealthTrackersViewModel extends ChangeNotifier {
// ==================== WEIGHT FORM FIELDS ====================
final List weightUnits = ['kg', 'lb'];
+ final List weightUnitsEn = ['kg', 'lb'];
+ final List weightUnitsAr = ['كجم', 'رطل'];
+
String _selectedWeightUnit = 'kg';
String get selectedWeightUnit => _selectedWeightUnit;
+ List getWeightUnitsList() {
+ return getIt.get().isArabic() ? weightUnitsAr : weightUnitsEn;
+ }
+
void setWeightUnit(String unit) {
- _selectedWeightUnit = unit;
+ // Map Arabic values to English keys
+ if (getIt.get().isArabic()) {
+ final index = weightUnitsAr.indexOf(unit);
+ if (index >= 0 && index < weightUnitsEn.length) {
+ _selectedWeightUnit = weightUnitsEn[index];
+ }
+ } else {
+ _selectedWeightUnit = unit;
+ }
notifyListeners();
}
+ // Get the localized display value for the selected weight unit
+ String get selectedWeightUnitDisplay {
+ final index = weightUnitsEn.indexOf(_selectedWeightUnit);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? weightUnitsAr[index] : weightUnitsEn[index];
+ }
+ return _selectedWeightUnit;
+ }
+
// ==================== BLOOD PRESSURE FORM FIELDS ====================
- final List measuredArmList = ['Left Arm', 'Right Arm'];
+ final List measuredArmListEn = ['Left Arm', 'Right Arm'];
+ final List measuredArmListAr = ['الذراع الأيسر', 'الذراع الأيمن'];
+
String _selectedMeasuredArm = '';
String get selectedMeasuredArm => _selectedMeasuredArm;
+ List getMeasuredArmList() {
+ return getIt.get().isArabic() ? measuredArmListAr : measuredArmListEn;
+ }
+
void setMeasuredArm(String arm) {
- _selectedMeasuredArm = arm;
+ // Map Arabic values to English keys
+ if (getIt.get().isArabic()) {
+ final index = measuredArmListAr.indexOf(arm);
+ if (index >= 0 && index < measuredArmListEn.length) {
+ _selectedMeasuredArm = measuredArmListEn[index];
+ }
+ } else {
+ _selectedMeasuredArm = arm;
+ }
notifyListeners();
}
+ // Get the localized display value for the selected measured arm
+ String get selectedMeasuredArmDisplay {
+ final index = measuredArmListEn.indexOf(_selectedMeasuredArm);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? measuredArmListAr[index] : measuredArmListEn[index];
+ }
+ return _selectedMeasuredArm;
+ }
+
// Text Controllers
TextEditingController weightController = TextEditingController();
TextEditingController bloodSugarController = TextEditingController();
@@ -425,6 +502,91 @@ class HealthTrackersViewModel extends ChangeNotifier {
}
}
+
+ Future downloadBloodSugerReport({
+ Function(String)? onSuccess,
+ }) async {
+ LoaderBottomSheet.showLoader(loadingText: LocaleKeys.generatingReport.tr());
+ try {
+ final result = await healthTrackersRepo.downloadBloodSugarReport();
+ LoaderBottomSheet.hideLoader();
+ bool success = false;
+
+ result.fold(
+ (failure) {
+ errorHandlerService.handleError(failure: failure);
+ },
+ (apiModel) {
+ success = true;
+ if (onSuccess != null) onSuccess(apiModel.data??"");
+ },
+ );
+
+ notifyListeners();
+
+ return success;
+ } catch (e) {
+ log('Error in sendWeightReportByEmail: $e');
+ return false;
+ }
+ }
+
+ Future downloadBloodPressureReport({
+ Function(String)? onSuccess,
+ }) async {
+ LoaderBottomSheet.showLoader(loadingText: LocaleKeys.generatingReport.tr());
+ try {
+ final result = await healthTrackersRepo.downloadBloodPressureReport();
+ LoaderBottomSheet.hideLoader();
+ bool success = false;
+
+ result.fold(
+ (failure) {
+ errorHandlerService.handleError(failure: failure);
+ },
+ (apiModel) {
+ success = true;
+ if (onSuccess != null) onSuccess(apiModel.data??"");
+ },
+ );
+
+ notifyListeners();
+
+ return success;
+ } catch (e) {
+ log('Error in sendWeightReportByEmail: $e');
+ return false;
+ }
+ }
+ Future downloadWeightReport({
+ Function(String)? onSuccess,
+ }) async {
+ LoaderBottomSheet.showLoader(loadingText: LocaleKeys.generatingReport.tr());
+ try {
+ final result = await healthTrackersRepo.downloadWeightReport();
+ LoaderBottomSheet.hideLoader();
+ bool success = false;
+
+ result.fold(
+ (failure) {
+ errorHandlerService.handleError(failure: failure);
+ },
+ (apiModel) {
+ success = true;
+ if (onSuccess != null) onSuccess(apiModel.data??"");
+ },
+ );
+
+ notifyListeners();
+
+ return success;
+ } catch (e) {
+ log('Error in sendWeightReportByEmail: $e');
+ return false;
+ }
+ }
+
+
// ==================== BLOOD PRESSURE TRACKING METHODS ====================
/// Fetch blood pressure averages and results
@@ -857,33 +1019,35 @@ class HealthTrackersViewModel extends ChangeNotifier {
// Validation method
String? _validateBloodSugarEntry(String dateTime) {
+ final isArabic = getIt.get().isArabic();
+
// Validate blood sugar value
if (bloodSugarController.text.trim().isEmpty) {
- return "Please enter blood sugar value";
+ return isArabic ? "الرجاء إدخال مستوى سكر الدم" : "Please enter blood sugar value";
}
final bloodSugarValue = double.tryParse(bloodSugarController.text.trim());
if (bloodSugarValue == null) {
- return "Please enter a valid number";
+ return isArabic ? "الرجاء إدخال رقم صحيح" : "Please enter a valid number";
}
if (bloodSugarValue <= 0) {
- return "Blood sugar value must be greater than 0";
+ return isArabic ? "يجب أن يكون مستوى سكر الدم أكبر من 0" : "Blood sugar value must be greater than 0";
}
// Validate reasonable range (typical ranges)
if (bloodSugarValue > 1000) {
- return "Blood sugar value seems too high. Please check and enter again";
+ return isArabic ? "مستوى سكر الدم يبدو مرتفع جداً. يرجى التحقق وإدخالها مرة أخرى" : "Blood sugar value seems too high. Please check and enter again";
}
// Validate date time
if (dateTime.trim().isEmpty) {
- return "Please select date and time";
+ return isArabic ? "الرجاء اختيار التاريخ والوقت" : "Please select date and time";
}
// Validate measure time
if (_selectedBloodSugarMeasureTime.isEmpty) {
- return "Please select when the measurement was taken";
+ return isArabic ? "الرجاء اختيار وقت القياس" : "Please select when the measurement was taken";
}
return null; // No errors
@@ -896,6 +1060,8 @@ class HealthTrackersViewModel extends ChangeNotifier {
Function()? onSuccess,
Function(String error)? onFailure,
}) async {
+ final isArabic = getIt.get().isArabic();
+
// Validate
final validationError = _validateBloodSugarEntry(dateTime);
if (validationError != null) {
@@ -930,13 +1096,13 @@ class HealthTrackersViewModel extends ChangeNotifier {
notifyListeners();
if (onSuccess != null) onSuccess();
} else {
- _errorMessage = "Failed to save blood sugar entry. Please try again";
+ _errorMessage = isArabic ? "فشل حفظ قراءة سكر الدم. يرجى المحاولة مرة أخرى" : "Failed to save blood sugar entry. Please try again";
notifyListeners();
if (onFailure != null) onFailure(_errorMessage!);
}
} catch (e) {
log('Error in saveBloodSugarEntry: $e');
- _errorMessage = "An error occurred. Please try again";
+ _errorMessage = isArabic ? "حدث خطأ. يرجى المحاولة مرة أخرى" : "An error occurred. Please try again";
isLoading = false;
notifyListeners();
if (onFailure != null) onFailure(_errorMessage!);
@@ -947,21 +1113,23 @@ class HealthTrackersViewModel extends ChangeNotifier {
// Validate weight entry before saving
String? _validateWeightEntry(String dateTime) {
+ final isArabic = getIt.get().isArabic();
+
// Validate weight value
final weightValue = weightController.text.trim();
if (weightValue.isEmpty) {
- return "Please enter weight value";
+ return isArabic ? "الرجاء إدخال قيمة الوزن" : "Please enter weight value";
}
// Check if it's a valid number
final parsedValue = double.tryParse(weightValue);
if (parsedValue == null || parsedValue <= 0) {
- return "Please enter a valid weight value";
+ return isArabic ? "الرجاء إدخال قيمة وزن صحيحة" : "Please enter a valid weight value";
}
// Validate date time
if (dateTime.trim().isEmpty) {
- return "Please select date and time";
+ return isArabic ? "الرجاء تحديد التاريخ والوقت" : "Please select date and time";
}
return null; // No errors
@@ -973,6 +1141,8 @@ class HealthTrackersViewModel extends ChangeNotifier {
Function()? onSuccess,
Function(String error)? onFailure,
}) async {
+ final isArabic = getIt.get().isArabic();
+
// Validate
final validationError = _validateWeightEntry(dateTime);
if (validationError != null) {
@@ -1005,13 +1175,13 @@ class HealthTrackersViewModel extends ChangeNotifier {
notifyListeners();
if (onSuccess != null) onSuccess();
} else {
- _errorMessage = "Failed to save weight entry. Please try again";
+ _errorMessage = isArabic ? "فشل حفظ قراءة الوزن. يرجى المحاولة مرة أخرى" : "Failed to save weight entry. Please try again";
notifyListeners();
if (onFailure != null) onFailure(_errorMessage!);
}
} catch (e) {
log('Error in saveWeightEntry: $e');
- _errorMessage = "An error occurred. Please try again";
+ _errorMessage = isArabic ? "حدث خطأ. يرجى المحاولة مرة أخرى" : "An error occurred. Please try again";
isLoading = false;
notifyListeners();
if (onFailure != null) onFailure(_errorMessage!);
@@ -1022,34 +1192,36 @@ class HealthTrackersViewModel extends ChangeNotifier {
// Validate blood pressure entry before saving
String? _validateBloodPressureEntry(String dateTime) {
+ final isArabic = getIt.get().isArabic();
+
// Validate systolic value
final systolicValue = systolicController.text.trim();
if (systolicValue.isEmpty) {
- return "Please enter systolic value";
+ return isArabic ? "الرجاء إدخال القيمة الانقباضية" : "Please enter systolic value";
}
final parsedSystolic = int.tryParse(systolicValue);
if (parsedSystolic == null || parsedSystolic <= 0) {
- return "Please enter a valid systolic value";
+ return isArabic ? "الرجاء إدخال قيمة صحيحة للضغط الانقباضي" : "Please enter a valid systolic value";
}
// Validate diastolic value
final diastolicValue = diastolicController.text.trim();
if (diastolicValue.isEmpty) {
- return "Please enter diastolic value";
+ return isArabic ? "الرجاء إدخال قيمة الضغط الانبساطي" : "Please enter diastolic value";
}
final parsedDiastolic = int.tryParse(diastolicValue);
if (parsedDiastolic == null || parsedDiastolic <= 0) {
- return "Please enter a valid diastolic value";
+ return isArabic ? "الرجاء إدخال قيمة صحيحة للضغط الانبساطي" : "Please enter a valid diastolic value";
}
// Validate arm selection
if (_selectedMeasuredArm.isEmpty) {
- return "Please select measured arm";
+ return isArabic ? "الرجاء اختيار الذراع المقاسة" : "Please select measured arm";
}
// Validate date time
if (dateTime.trim().isEmpty) {
- return "Please select date and time";
+ return isArabic ? "الرجاء تحديد التاريخ والوقت" : "Please select date and time";
}
return null; // No errors
@@ -1061,6 +1233,8 @@ class HealthTrackersViewModel extends ChangeNotifier {
Function()? onSuccess,
Function(String error)? onFailure,
}) async {
+ final isArabic = getIt.get().isArabic();
+
// Validate
final validationError = _validateBloodPressureEntry(dateTime);
if (validationError != null) {
@@ -1076,7 +1250,7 @@ class HealthTrackersViewModel extends ChangeNotifier {
try {
// Get measured arm index (0 = Left Arm, 1 = Right Arm)
- final measuredArmIndex = measuredArmList.indexOf(_selectedMeasuredArm);
+ final measuredArmIndex = measuredArmListEn.indexOf(_selectedMeasuredArm);
// Call API
final success = await addOrUpdateBloodPressureResult(
@@ -1097,13 +1271,13 @@ class HealthTrackersViewModel extends ChangeNotifier {
notifyListeners();
if (onSuccess != null) onSuccess();
} else {
- _errorMessage = "Failed to save blood pressure entry. Please try again";
+ _errorMessage = isArabic ? "فشل حفظ قراءة ضغط الدم. يرجى المحاولة مرة أخرى" : "Failed to save blood pressure entry. Please try again";
notifyListeners();
if (onFailure != null) onFailure(_errorMessage!);
}
} catch (e) {
log('Error in saveBloodPressureEntry: $e');
- _errorMessage = "An error occurred. Please try again";
+ _errorMessage = isArabic ? "حدث خطأ. يرجى المحاولة مرة أخرى" : "An error occurred. Please try again";
isLoading = false;
notifyListeners();
if (onFailure != null) onFailure(_errorMessage!);
@@ -1118,4 +1292,30 @@ class HealthTrackersViewModel extends ChangeNotifier {
diastolicController.dispose();
super.dispose();
}
+
+ Future downloadReport(HealthTrackerTypeEnum trackerType, {required Function(dynamic report) onSuccess}) async {
+ switch (trackerType) {
+ case HealthTrackerTypeEnum.bloodSugar:
+ await downloadBloodSugerReport(
+ onSuccess : (value){
+ onSuccess(value);
+ }
+ );
+ break;
+ case HealthTrackerTypeEnum.bloodPressure:
+ await downloadBloodPressureReport(
+ onSuccess : (value){
+ onSuccess(value);
+ }
+ );
+ break;
+ case HealthTrackerTypeEnum.weightTracker:
+ await downloadWeightReport(
+ onSuccess : (value){
+ onSuccess(value);
+ }
+ );
+ break;
+ }
+ }
}
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 ea0782bd..6fb24066 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
@@ -11,6 +11,7 @@ enum VitalSignStatus {
obese,
overweight,
underweight,
+ skinny,
}
/// UI-only helper model for Vital Sign cards.
@@ -34,8 +35,9 @@ class VitalSignUiModel {
///
/// Rules:
/// - Height is always blue.
- /// - High, Obese, Overweight => red scheme.
- /// - Low, Underweight => yellow scheme.
+ /// - High, Obese => red scheme.
+ /// - Overweight => orange scheme.
+ /// - Low, Underweight, Skinny => yellow scheme.
/// - Otherwise => green scheme (Normal).
static VitalSignUiModel scheme({required VitalSignStatus? status, required String label}) {
final l = label.toLowerCase();
@@ -50,10 +52,8 @@ class VitalSignUiModel {
);
}
- // High, Obese, Overweight => red scheme (health concerns)
- if (status == VitalSignStatus.high ||
- status == VitalSignStatus.obese ||
- status == VitalSignStatus.overweight) {
+ // High, Obese => red scheme (health concerns)
+ if (status == VitalSignStatus.high || status == VitalSignStatus.obese) {
return VitalSignUiModel(
iconBg: AppColors.chipSecondaryLightRedColor,
iconFg: AppColors.primaryRedColor,
@@ -62,8 +62,20 @@ class VitalSignUiModel {
);
}
- // Low, Underweight => yellow scheme (warning)
- if (status == VitalSignStatus.low || status == VitalSignStatus.underweight) {
+ // Overweight => orange scheme (warning)
+ if (status == VitalSignStatus.overweight) {
+ return VitalSignUiModel(
+ iconBg: AppColors.warningColorYellow.withValues(alpha: 0.12),
+ iconFg: AppColors.warningColorYellow,
+ chipBg: AppColors.warningColorYellow.withValues(alpha: 0.12),
+ chipFg: AppColors.warningColorYellow,
+ );
+ }
+
+ // Low, Underweight, Skinny => yellow scheme (warning)
+ if (status == VitalSignStatus.low ||
+ status == VitalSignStatus.underweight ||
+ status == VitalSignStatus.skinny) {
final Color yellowBg = AppColors.highAndLow.withValues(alpha: 0.12);
return VitalSignUiModel(
iconBg: yellowBg,
@@ -98,6 +110,8 @@ class VitalSignUiModel {
return LocaleKeys.vitalSignOverweight.tr();
case VitalSignStatus.underweight:
return LocaleKeys.vitalSignUnderweight.tr();
+ case VitalSignStatus.skinny:
+ return LocaleKeys.vitalSignSkinny.tr();
}
}
@@ -131,22 +145,30 @@ class VitalSignUiModel {
return null;
}
- // BMI >= 25 (Overweight or Obese) => High
- if (bmiResult >= 25) {
- return VitalSignStatus.high;
+ // BMI >= 30 (Obese) => Red
+ if (bmiResult >= 30) {
+ return VitalSignStatus.obese;
+ }
+ // BMI >= 25 (Overweight) => Orange
+ else if (bmiResult >= 25) {
+ return VitalSignStatus.overweight;
}
- // BMI >= 18.5 and < 25 => Normal
+ // BMI >= 18.5 (Normal) => Green
else if (bmiResult >= 18.5) {
return VitalSignStatus.normal;
}
- // BMI < 18.5 (Underweight) => Low
+ // BMI >= 16 (Underweight) => Yellow
+ else if (bmiResult >= 16) {
+ return VitalSignStatus.underweight;
+ }
+ // BMI < 16 (Skinny/Severely underweight) => Yellow
else {
- return VitalSignStatus.low;
+ return VitalSignStatus.skinny;
}
}
/// Weight status based on BMI with detailed classification
- /// Returns: Obese, Overweight, Normal, Underweight
+ /// Returns: Obese, Overweight, Normal, Underweight, Skinny
static VitalSignStatus? weightStatus(dynamic bmi) {
// Return null if BMI is not available or is 0
final double bmiResult = double.tryParse(bmi.toString()) ?? 0;
@@ -155,15 +177,26 @@ class VitalSignUiModel {
return null;
}
+ // BMI >= 30 (Obese) => Red
if (bmiResult >= 30) {
return VitalSignStatus.obese;
- } else if (bmiResult >= 25) {
+ }
+ // BMI >= 25 (Overweight) => Orange
+ else if (bmiResult >= 25) {
return VitalSignStatus.overweight;
- } else if (bmiResult >= 18.5) {
+ }
+ // BMI >= 18.5 (Normal) => Green
+ else if (bmiResult >= 18.5) {
return VitalSignStatus.normal;
- } else {
+ }
+ // BMI >= 16 (Underweight) => Yellow
+ else if (bmiResult >= 16) {
return VitalSignStatus.underweight;
}
+ // BMI < 16 (Skinny/Severely underweight) => Yellow
+ else {
+ return VitalSignStatus.skinny;
+ }
}
}
diff --git a/lib/features/immediate_livecare/immediate_livecare_view_model.dart b/lib/features/immediate_livecare/immediate_livecare_view_model.dart
index 6613b481..e61292d6 100644
--- a/lib/features/immediate_livecare/immediate_livecare_view_model.dart
+++ b/lib/features/immediate_livecare/immediate_livecare_view_model.dart
@@ -39,6 +39,7 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
MyAppointmentsViewModel myAppointmentsViewModel;
List immediateLiveCareClinicsList = [];
+ List mainLiveCareClinicList = [];
bool isImmediateLiveCareClinicsLoading = false;
int liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone
late GetLiveCareClinicListResponseModel immediateLiveCareSelectedClinic;
@@ -61,6 +62,7 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
initImmediateLiveCare() {
_appState = getIt();
immediateLiveCareClinicsList = [];
+ mainLiveCareClinicList = [];
isImmediateLiveCareClinicsLoading = true;
liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone
immediateLiveCareSelectedClinic = GetLiveCareClinicListResponseModel();
@@ -90,9 +92,11 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
- immediateLiveCareClinicsList = apiResponse.data!;
+ mainLiveCareClinicList = apiResponse.data!;
- immediateLiveCareClinicsList.sort((a, b) => b.isOnline!.compareTo(a.isOnline!));
+ mainLiveCareClinicList.sort((a, b) => b.isOnline!.compareTo(a.isOnline!));
+ immediateLiveCareClinicsList.clear();
+ immediateLiveCareClinicsList.addAll(mainLiveCareClinicList);
isImmediateLiveCareClinicsLoading = false;
notifyListeners();
@@ -103,6 +107,18 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
},
);
}
+ void filterClinic(String query){
+ if(query.isEmpty){
+ immediateLiveCareClinicsList.clear();
+ immediateLiveCareClinicsList.addAll(mainLiveCareClinicList);
+ }else{
+
+ // bool isArabic = getIt.get().isArabic();
+ immediateLiveCareClinicsList = mainLiveCareClinicList.where((clinic) => clinic.serviceName!.toLowerCase().contains(query.toLowerCase()) || clinic.serviceNameN!.toLowerCase().contains(query.toLowerCase()
+ )).toList();
+ }
+ notifyListeners();
+ }
Future getLiveCareImmediateAppointmentFees({Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result =
diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart
index 28210d39..621ebe4c 100644
--- a/lib/features/insurance/insurance_view_model.dart
+++ b/lib/features/insurance/insurance_view_model.dart
@@ -191,6 +191,7 @@ class InsuranceViewModel extends ChangeNotifier {
notifyListeners();
},
(apiResponse) {
+ patientInsuranceApprovalsList =[];
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
diff --git a/lib/features/location/location_view_model.dart b/lib/features/location/location_view_model.dart
index 5b0eef6d..460eb0f1 100644
--- a/lib/features/location/location_view_model.dart
+++ b/lib/features/location/location_view_model.dart
@@ -18,7 +18,6 @@ class LocationViewModel extends ChangeNotifier {
final ErrorHandlerService errorHandlerService;
LocationViewModel({required this.locationRepo, required this.errorHandlerService}) {
- placeValueInController();
}
List predictions = [];
@@ -31,7 +30,9 @@ class LocationViewModel extends ChangeNotifier {
Completer? gmsController;
Completer? hmsController;
-
+ get isGMSAvailable {
+ return getIt.get().isGMSAvailable;
+ }
HMSCameraServices.CameraPosition getHMSLocation() {
return HMSCameraServices.CameraPosition(target: HMSCameraServices.LatLng(getIt().userLat, getIt().userLong), zoom: 18);
}
@@ -43,7 +44,7 @@ class LocationViewModel extends ChangeNotifier {
}
void placeValueInController() async {
- if (await getIt().isGMSAvailable) {
+ if (isGMSAvailable) {
gmsController = Completer();
} else {
hmsController = Completer();
diff --git a/lib/features/medical_file/medical_file_view_model.dart b/lib/features/medical_file/medical_file_view_model.dart
index 05f82208..8b7ce7c3 100644
--- a/lib/features/medical_file/medical_file_view_model.dart
+++ b/lib/features/medical_file/medical_file_view_model.dart
@@ -41,6 +41,7 @@ class MedicalFileViewModel extends ChangeNotifier {
List patientSickLeavesViewList = [];
bool isSickLeavesSortByClinic = true;
+
// bool isSickLeavesDataNeedsReloading = true;
List patientAllergiesList = [];
@@ -165,13 +166,13 @@ class MedicalFileViewModel extends ChangeNotifier {
setIsPatientSickLeaveListLoading(bool val) {
// if (val && isSickLeavesDataNeedsReloading) {
- patientSickLeaveList.clear();
- patientSickLeavesByClinic.clear();
- patientSickLeavesByHospital.clear();
- patientSickLeavesViewList.clear();
- patientSickLeavePDFBase64 = "";
- isSickLeavesSortByClinic = true;
- isPatientSickLeaveListLoading = val;
+ patientSickLeaveList.clear();
+ patientSickLeavesByClinic.clear();
+ patientSickLeavesByHospital.clear();
+ patientSickLeavesViewList.clear();
+ patientSickLeavePDFBase64 = "";
+ isSickLeavesSortByClinic = true;
+ isPatientSickLeaveListLoading = val;
// }
notifyListeners();
}
@@ -456,6 +457,7 @@ class MedicalFileViewModel extends ChangeNotifier {
patientIdenficationNumber: currentUser.patientIdentificationNo,
emaiLAddress: currentUser.emailAddress,
genderDescription: currentUser.genderDescription,
+ patientImageData: _appState.getProfileImageData, // Set main user's profile image
);
// Clear and start fresh with current user
@@ -499,6 +501,7 @@ class MedicalFileViewModel extends ChangeNotifier {
genderDescription: element.genderDescription,
genderImage: element.genderImage,
emaiLAddress: element.emaiLAddress,
+ patientImageData: element.patientImageData, // Include profile image data
);
if (isPending) {
@@ -774,4 +777,41 @@ class MedicalFileViewModel extends ChangeNotifier {
},
);
}
+
+ /// Update family member's profile image in cached family files
+ void updateFamilyMemberProfileImage(int patientID, String imageData) {
+ try {
+ bool updated = false;
+
+ // Update in patientFamilyFiles list
+ for (var i = 0; i < patientFamilyFiles.length; i++) {
+ if (patientFamilyFiles[i].patientId == patientID ||
+ patientFamilyFiles[i].responseId == patientID) {
+ patientFamilyFiles[i].patientImageData = imageData;
+ updated = true;
+ print("✅ Updated profile image for family member in patientFamilyFiles (index: $i, patientID: $patientID)");
+ break;
+ }
+ }
+
+ // Update in pendingFamilyFiles list if exists
+ for (var i = 0; i < pendingFamilyFiles.length; i++) {
+ if (pendingFamilyFiles[i].patientId == patientID ||
+ pendingFamilyFiles[i].responseId == patientID) {
+ pendingFamilyFiles[i].patientImageData = imageData;
+ print("✅ Updated profile image for pending family member (index: $i, patientID: $patientID)");
+ break;
+ }
+ }
+
+ if (updated) {
+ // Notify listeners to update UI
+ notifyListeners();
+ } else {
+ print("⚠️ Family member not found in cache for patientID: $patientID");
+ }
+ } catch (e) {
+ print("❌ Error updating family member profile image in cache: $e");
+ }
+ }
}
diff --git a/lib/features/medical_file/models/family_file_response_model.dart b/lib/features/medical_file/models/family_file_response_model.dart
index f4aa557d..59aa2bd2 100644
--- a/lib/features/medical_file/models/family_file_response_model.dart
+++ b/lib/features/medical_file/models/family_file_response_model.dart
@@ -25,6 +25,7 @@ class FamilyFileResponseModelLists {
String? statusDescription;
bool? isSuperUser = false;
bool? isRequestFromMySide;
+ String? patientImageData;
FamilyFileResponseModelLists(
{this.id,
@@ -50,7 +51,8 @@ class FamilyFileResponseModelLists {
this.patientName,
this.statusDescription,
this.isSuperUser,
- this.isRequestFromMySide});
+ this.isRequestFromMySide,
+ this.patientImageData});
factory FamilyFileResponseModelLists.fromRawJson(String str) => FamilyFileResponseModelLists.fromJson(json.decode(str));
@@ -81,6 +83,7 @@ class FamilyFileResponseModelLists {
statusDescription: json["StatusDescription"],
isSuperUser: json["isSuperUser"] ?? false,
isRequestFromMySide: json["isRequestFromMySide"] ?? false,
+ patientImageData: json["PatientImageData"],
);
Map toJson() => {
@@ -108,5 +111,6 @@ class FamilyFileResponseModelLists {
"StatusDescription": statusDescription,
"isSuperUser": isSuperUser,
"isRequestFromMySide": isRequestFromMySide,
+ "PatientImageData": patientImageData,
};
}
diff --git a/lib/features/my_appointments/models/reminder_type.dart b/lib/features/my_appointments/models/reminder_type.dart
new file mode 100644
index 00000000..f13f20a0
--- /dev/null
+++ b/lib/features/my_appointments/models/reminder_type.dart
@@ -0,0 +1,50 @@
+/// Enum to define different types of reminders
+enum ReminderType {
+ /// Reminder for appointment schedule
+ appointment,
+
+ /// Reminder for payment due
+ payment,
+
+ /// Reminder for check-in
+ checkIn,
+}
+
+extension ReminderTypeExtension on ReminderType {
+ /// Get display name for the reminder type
+ String get displayName {
+ switch (this) {
+ case ReminderType.appointment:
+ return 'Appointment Reminder';
+ case ReminderType.payment:
+ return 'Payment Reminder';
+ case ReminderType.checkIn:
+ return 'Check-In Reminder';
+ }
+ }
+
+ /// Get description for the reminder type
+ String get description {
+ switch (this) {
+ case ReminderType.appointment:
+ return 'Appointment scheduled reminder';
+ case ReminderType.payment:
+ return 'Payment due reminder';
+ case ReminderType.checkIn:
+ return 'Check-in reminder';
+ }
+ }
+
+ /// Get event ID prefix for calendar events
+ String get eventIdPrefix {
+ switch (this) {
+ case ReminderType.appointment:
+ return 'APPT';
+ case ReminderType.payment:
+ return 'PAY';
+ case ReminderType.checkIn:
+ return 'CHKIN';
+ }
+ }
+}
+
diff --git a/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart b/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart
index cea2e64b..420c0482 100644
--- a/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart
+++ b/lib/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart
@@ -75,6 +75,7 @@ class PatientAppointmentHistoryResponseModel {
num? patientShareWithTax;
num? patientTaxAmount;
String? doctorNationalityFlagURL;
+ bool? isClinicReBookingAllowed;
PatientAppointmentHistoryResponseModel({
this.setupID,
@@ -152,6 +153,7 @@ class PatientAppointmentHistoryResponseModel {
this.patientShareWithTax,
this.patientTaxAmount,
this.doctorNationalityFlagURL,
+ this.isClinicReBookingAllowed,
});
PatientAppointmentHistoryResponseModel.fromJson(Map json) {
@@ -241,6 +243,7 @@ class PatientAppointmentHistoryResponseModel {
patientShareWithTax = json['PatientShareWithTax'];
patientTaxAmount = json['PatientTaxAmount'];
doctorNationalityFlagURL = json['DoctorNationalityFlagURL'];
+ isClinicReBookingAllowed = json['IsClinicReBookingAllowed'];
}
Map toJson() {
@@ -313,6 +316,7 @@ class PatientAppointmentHistoryResponseModel {
data['RemaniningHoursTocanPay'] = this.remaniningHoursTocanPay;
data['SMSButtonVisable'] = this.sMSButtonVisable;
data['ServiceID'] = this.serviceID;
+ data['IsClinicReBookingAllowed'] = this.isClinicReBookingAllowed;
return data;
}
}
diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart
index d4669767..541e8878 100644
--- a/lib/features/my_appointments/my_appointments_repo.dart
+++ b/lib/features/my_appointments/my_appointments_repo.dart
@@ -847,7 +847,7 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
// final queueList = list.map((item) => PatientQueueDetails.fromJson(item as Map)).toList().cast();
final queueList = PatientQueueDetails.fromJson(queueData);
- queueList.patientQueueData!.isClinicConfigured = 1;
+ // queueList.patientQueueData!.isClinicConfigured = 1;
apiResponse = GenericApiModel(
messageStatus: messageStatus,
diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index 73f8d331..942a51e6 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -2,11 +2,13 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
+import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/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/reminder_type.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';
@@ -19,6 +21,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
@@ -1109,4 +1112,409 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
+
+ /// Creates a reminder for the appointment
+ /// Shows a bottom sheet to select reminder time and creates calendar event
+ /// [reminderType] specifies the type of reminder (appointment, payment, or check-in)
+ /// For payment and check-in reminders, shows only 1, 2, 3 hours before appointment
+ /// Automatically removes previous reminders when creating a new one
+ Future createReminder({
+ required BuildContext context,
+ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ ReminderType reminderType = ReminderType.appointment,
+ Function(bool)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ try {
+ CalenderUtilsNew calender = CalenderUtilsNew.instance;
+ DateTime endDate = DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate);
+
+ // Generate title and description based on reminder type
+ String title;
+ String description;
+ String eventIdPrefix = reminderType.eventIdPrefix;
+
+ switch (reminderType) {
+ case ReminderType.appointment:
+ title = "Appointment with ${patientAppointmentHistoryResponseModel.doctorNameObj}";
+ description = "${patientAppointmentHistoryResponseModel.doctorNameObj} will be having an appointment on ${patientAppointmentHistoryResponseModel.appointmentDate}";
+ break;
+ case ReminderType.payment:
+ title = "Payment Due for Appointment #${patientAppointmentHistoryResponseModel.appointmentNo}";
+ description = "Payment reminder for appointment with ${patientAppointmentHistoryResponseModel.doctorNameObj} at ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ case ReminderType.checkIn:
+ title = "Check-In Reminder for Appointment #${patientAppointmentHistoryResponseModel.appointmentNo}";
+ description = "Don't forget to check in for your appointment with ${patientAppointmentHistoryResponseModel.doctorNameObj}";
+ break;
+ }
+
+ // For payment and check-in, remove existing reminders first
+ if (reminderType == ReminderType.payment || reminderType == ReminderType.checkIn) {
+ // Remove all existing reminder types
+ await _removeAllRemindersForAppointment(patientAppointmentHistoryResponseModel);
+ }
+
+ // For payment and check-in reminders, use custom hour-based options
+ if (reminderType == ReminderType.payment || reminderType == ReminderType.checkIn) {
+ _showHourBasedReminderSheet(
+ context: context,
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ title: title,
+ description: description,
+ eventIdPrefix: eventIdPrefix,
+ endDate: endDate,
+ onSuccess: onSuccess,
+ onError: onError,
+ );
+ } else {
+ // For appointment reminders, use the standard reminder sheet with all options
+ BottomSheetUtils().showReminderBottomSheet(
+ context,
+ endDate,
+ patientAppointmentHistoryResponseModel.doctorNameObj ?? "",
+ "${patientAppointmentHistoryResponseModel.appointmentNo}",
+ "",
+ "",
+ title: title,
+ description: description,
+ onSuccess: () {
+ setAppointmentReminder(true, patientAppointmentHistoryResponseModel);
+ if (onSuccess != null) {
+ onSuccess(true);
+ }
+ },
+ isMultiAllowed: true,
+ onMultiDateSuccess: (int selectedIndex) async {
+ String eventTitle;
+ String eventDescription;
+
+ switch (reminderType) {
+ case ReminderType.appointment:
+ eventTitle = "Appointment Reminder with ${patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${patientAppointmentHistoryResponseModel.appointmentNo}";
+ eventDescription = "Appointment Reminder with ${patientAppointmentHistoryResponseModel.doctorNameObj} in ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ case ReminderType.payment:
+ eventTitle = "Payment Due Reminder for Appointment #${patientAppointmentHistoryResponseModel.appointmentNo} with ${patientAppointmentHistoryResponseModel.doctorNameObj}";
+ eventDescription = "Payment reminder for ${patientAppointmentHistoryResponseModel.doctorNameObj} at ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ case ReminderType.checkIn:
+ eventTitle = "Check-In Reminder for Appointment #${patientAppointmentHistoryResponseModel.appointmentNo} with ${patientAppointmentHistoryResponseModel.doctorNameObj}";
+ eventDescription = "Check-in reminder for appointment with ${patientAppointmentHistoryResponseModel.doctorNameObj} at ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ }
+
+ bool isEventAddedOrRemoved = await calender.createOrUpdateEvent(
+ title: eventTitle,
+ description: eventDescription,
+ scheduleDateTime: DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate),
+ eventId: "${eventIdPrefix}_${patientAppointmentHistoryResponseModel.appointmentNo}",
+ location: patientAppointmentHistoryResponseModel.projectName ?? '',
+ reminderMinutes: selectedIndex,
+ );
+
+ setAppointmentReminder(isEventAddedOrRemoved, patientAppointmentHistoryResponseModel);
+
+ if (onSuccess != null) {
+ onSuccess(isEventAddedOrRemoved);
+ }
+ },
+ );
+ }
+ } catch (e) {
+ if (onError != null) {
+ onError(e.toString());
+ }
+ }
+ }
+
+ /// Removes all reminder types for an appointment (internal helper)
+ Future _removeAllRemindersForAppointment(PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel) async {
+ CalenderUtilsNew calender = CalenderUtilsNew.instance;
+
+ // Remove all possible reminder types
+ for (var type in ReminderType.values) {
+ try {
+ await calender.checkAndRemove(
+ id: "${type.eventIdPrefix}_${patientAppointmentHistoryResponseModel.appointmentNo}",
+ );
+ } catch (e) {
+ // Ignore errors if reminder doesn't exist
+ debugPrint("No existing ${type.displayName} to remove");
+ }
+ }
+ }
+
+ /// Shows hour-based reminder selection for payment and check-in reminders
+ void _showHourBasedReminderSheet({
+ required BuildContext context,
+ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ required ReminderType reminderType,
+ required String title,
+ required String description,
+ required String eventIdPrefix,
+ required DateTime endDate,
+ Function(bool)? onSuccess,
+ Function(String)? onError,
+ }) {
+ showCommonBottomSheetWithoutHeight(
+ context,
+ title: "Select Reminder Time",
+ child: Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Center(
+ child: Text(
+ "When would you like to be reminded?",
+ style: TextStyle(
+ fontSize: 14.f,
+ color: AppColors.greyTextColor,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ SizedBox(height: 24.h),
+ _buildHourOption(
+ context: context,
+ hours: 1,
+ icon: Icons.alarm,
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ title: title,
+ description: description,
+ eventIdPrefix: eventIdPrefix,
+ endDate: endDate,
+ onSuccess: onSuccess,
+ onError: onError,
+ ),
+ SizedBox(height: 12.h),
+ _buildHourOption(
+ context: context,
+ hours: 2,
+ icon: Icons.alarm,
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ title: title,
+ description: description,
+ eventIdPrefix: eventIdPrefix,
+ endDate: endDate,
+ onSuccess: onSuccess,
+ onError: onError,
+ ),
+ SizedBox(height: 12.h),
+ _buildHourOption(
+ context: context,
+ hours: 3,
+ icon: Icons.alarm,
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ title: title,
+ description: description,
+ eventIdPrefix: eventIdPrefix,
+ endDate: endDate,
+ onSuccess: onSuccess,
+ onError: onError,
+ ),
+ ],
+ ),
+ ),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ }
+
+ /// Builds an hour option button for payment/check-in reminders
+ Widget _buildHourOption({
+ required BuildContext context,
+ required int hours,
+ required IconData icon,
+ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ required ReminderType reminderType,
+ required String title,
+ required String description,
+ required String eventIdPrefix,
+ required DateTime endDate,
+ Function(bool)? onSuccess,
+ Function(String)? onError,
+ }) {
+ return GestureDetector(
+ onTap: () async {
+ Navigator.of(context).pop(); // Close the selection sheet
+
+ // Create reminder with selected hours (converted to minutes)
+ await _createReminderWithHours(
+ hours: hours,
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ title: title,
+ description: description,
+ eventIdPrefix: eventIdPrefix,
+ endDate: endDate,
+ onSuccess: onSuccess,
+ onError: onError,
+ );
+ },
+ child: Container(
+ padding: EdgeInsets.all(16.h),
+ decoration: BoxDecoration(
+ color: AppColors.whiteColor,
+ border: Border.all(color: AppColors.borderOnlyColor),
+ borderRadius: BorderRadius.circular(12.r),
+ ),
+ child: Row(
+ children: [
+ Container(
+ padding: EdgeInsets.all(12.h),
+ decoration: BoxDecoration(
+ color: AppColors.primaryRedColor.withAlpha(26),
+ borderRadius: BorderRadius.circular(8.r),
+ ),
+ child: Icon(
+ icon,
+ color: AppColors.primaryRedColor,
+ size: 24.h,
+ ),
+ ),
+ SizedBox(width: 12.w),
+ Expanded(
+ child: Text(
+ "$hours ${hours == 1 ? 'Hour' : 'Hours'} Before Appointment",
+ style: TextStyle(
+ fontSize: 16.f,
+ fontWeight: FontWeight.w600,
+ color: AppColors.textColor,
+ ),
+ ),
+ ),
+ Icon(
+ Icons.arrow_forward_ios,
+ size: 16.h,
+ color: AppColors.greyTextColor,
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ /// Creates reminder with specific hours before appointment
+ Future _createReminderWithHours({
+ required int hours,
+ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ required ReminderType reminderType,
+ required String title,
+ required String description,
+ required String eventIdPrefix,
+ required DateTime endDate,
+ Function(bool)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ try {
+ CalenderUtilsNew calender = CalenderUtilsNew.instance;
+
+ // Convert hours to minutes
+ int reminderMinutes = hours * 60;
+
+ String eventTitle;
+ String eventDescription;
+
+ switch (reminderType) {
+ case ReminderType.appointment:
+ eventTitle = "Appointment Reminder with ${patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${patientAppointmentHistoryResponseModel.appointmentNo}";
+ eventDescription = "Appointment Reminder with ${patientAppointmentHistoryResponseModel.doctorNameObj} in ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ case ReminderType.payment:
+ eventTitle = "Payment Due - $hours ${hours == 1 ? 'hour' : 'hours'} before Appointment #${patientAppointmentHistoryResponseModel.appointmentNo}";
+ eventDescription = "Payment reminder for ${patientAppointmentHistoryResponseModel.doctorNameObj} at ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ case ReminderType.checkIn:
+ eventTitle = "Check-In Now - $hours ${hours == 1 ? 'hour' : 'hours'} before Appointment #${patientAppointmentHistoryResponseModel.appointmentNo}";
+ eventDescription = "Check-in reminder for appointment with ${patientAppointmentHistoryResponseModel.doctorNameObj} at ${patientAppointmentHistoryResponseModel.projectName}";
+ break;
+ }
+
+ bool isEventAddedOrRemoved = await calender.createOrUpdateEvent(
+ title: eventTitle,
+ description: eventDescription,
+ scheduleDateTime: DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate),
+ eventId: "${eventIdPrefix}_${patientAppointmentHistoryResponseModel.appointmentNo}",
+ location: patientAppointmentHistoryResponseModel.projectName ?? '',
+ reminderMinutes: reminderMinutes,
+ );
+
+ setAppointmentReminder(isEventAddedOrRemoved, patientAppointmentHistoryResponseModel);
+
+ if (onSuccess != null) {
+ onSuccess(isEventAddedOrRemoved);
+ }
+ } catch (e) {
+ if (onError != null) {
+ onError(e.toString());
+ }
+ }
+ }
+
+ /// Deletes the reminder for the appointment
+ /// Removes the calendar event associated with the appointment
+ /// [reminderType] specifies the type of reminder to delete (appointment, payment, or check-in)
+ Future deleteReminder({
+ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ ReminderType reminderType = ReminderType.appointment,
+ Function(bool)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ try {
+ CalenderUtilsNew calender = CalenderUtilsNew.instance;
+ String eventIdPrefix = reminderType.eventIdPrefix;
+
+ bool isEventRemoved = await calender.checkAndRemove(
+ id: "${eventIdPrefix}_${patientAppointmentHistoryResponseModel.appointmentNo}",
+ );
+
+ // Update the reminder status (inverted because we're removing)
+ setAppointmentReminder(!isEventRemoved, patientAppointmentHistoryResponseModel);
+
+ if (onSuccess != null) {
+ onSuccess(isEventRemoved);
+ }
+ } catch (e) {
+ if (onError != null) {
+ onError(e.toString());
+ }
+ }
+ }
+
+ /// Toggle reminder for an appointment
+ /// Creates or deletes reminder based on the current state
+ /// [reminderType] specifies the type of reminder (appointment, payment, or check-in)
+ Future toggleReminder({
+ required BuildContext context,
+ required bool shouldCreateReminder,
+ required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel,
+ required ReminderType reminderType ,
+ Function(bool)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ if (shouldCreateReminder) {
+ await createReminder(
+ context: context,
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ onSuccess: onSuccess,
+ onError: onError,
+ );
+ } else {
+ await deleteReminder(
+ patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
+ reminderType: reminderType,
+ onSuccess: onSuccess,
+ onError: onError,
+ );
+ }
+ }
}
diff --git a/lib/features/my_invoices/my_invoices_view_model.dart b/lib/features/my_invoices/my_invoices_view_model.dart
index cd18026c..631efd5b 100644
--- a/lib/features/my_invoices/my_invoices_view_model.dart
+++ b/lib/features/my_invoices/my_invoices_view_model.dart
@@ -52,6 +52,8 @@ class MyInvoicesViewModel extends ChangeNotifier {
notifyListeners();
},
(apiResponse) {
+ _originalInvoicesList =[];
+ allInvoicesList =[];
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
diff --git a/lib/features/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart
index b9c29072..c374b3e2 100644
--- a/lib/features/prescriptions/prescriptions_view_model.dart
+++ b/lib/features/prescriptions/prescriptions_view_model.dart
@@ -20,6 +20,7 @@ import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:permission_handler/permission_handler.dart';
+import 'package:provider/provider.dart';
class PrescriptionsViewModel extends ChangeNotifier {
bool isPrescriptionsOrdersLoading = false;
@@ -255,7 +256,9 @@ class PrescriptionsViewModel extends ChangeNotifier {
);
}
- void initiatePrescriptionDelivery() async {
+ void initiatePrescriptionDelivery(BuildContext context) async {
+ context.read().placeValueInController();
+
getIt.get().getLocation(
isShowConfirmDialog: true,
onSuccess: (position) async {
@@ -303,6 +306,23 @@ class PrescriptionsViewModel extends ChangeNotifier {
} else if (apiResponse.messageStatus == 1) {
isPrescriptionsDeliveryOrdersLoading = false;
prescriptionsOrderList = apiResponse.data!;
+
+ // Sort by created date (newest first)
+ prescriptionsOrderList.sort((a, b) {
+ try {
+ if (a.created == null && b.created == null) return 0;
+ if (a.created == null) return 1;
+ if (b.created == null) return -1;
+
+ DateTime dateA = DateTime.parse(a.created!);
+ DateTime dateB = DateTime.parse(b.created!);
+ return dateB.compareTo(dateA); // Descending order (newest first)
+ } catch (e) {
+ print('Error parsing date for sorting: $e');
+ return 0;
+ }
+ });
+
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
diff --git a/lib/features/profile_settings/profile_settings_repo.dart b/lib/features/profile_settings/profile_settings_repo.dart
index d86bd7fd..113a52c0 100644
--- a/lib/features/profile_settings/profile_settings_repo.dart
+++ b/lib/features/profile_settings/profile_settings_repo.dart
@@ -151,7 +151,7 @@ class ProfileSettingsRepoImp implements ProfileSettingsRepo {
}
@override
- Future>> getProfileImage({
+ Future>> getProfileImage({
required int patientID,
}) async {
final Map body = {
diff --git a/lib/features/profile_settings/profile_settings_view_model.dart b/lib/features/profile_settings/profile_settings_view_model.dart
index 77960569..5d2f58d4 100644
--- a/lib/features/profile_settings/profile_settings_view_model.dart
+++ b/lib/features/profile_settings/profile_settings_view_model.dart
@@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
+import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/models/get_patient_info_response_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@@ -188,19 +189,15 @@ class ProfileSettingsViewModel extends ChangeNotifier {
Function(String)? onError,
bool forceRefresh = false, // Add flag to force refresh
}) async {
- // Skip API call if image is already loaded and not forcing refresh
- if (!forceRefresh && GetIt.instance().getProfileImageData != null) {
- // Use cached data
- profileImageData = GetIt.instance().getProfileImageData;
- if (onSuccess != null) {
- onSuccess(profileImageData);
- }
- return;
- }
+ print('🌐 Fetching profile image from API for patient: $patientID (forceRefresh: $forceRefresh)');
+
+ // IMPORTANT: Always clear old data BEFORE fetching
+ // Do NOT use cached data - always fetch fresh from API
+ profileImageData = null;
isProfileImageLoading = true;
profileImageError = null;
- notifyListeners();
+ notifyListeners(); // Notify to show loading state
final result = await profileSettingsRepo.getProfileImage(patientID: patientID);
@@ -208,6 +205,11 @@ class ProfileSettingsViewModel extends ChangeNotifier {
(failure) {
isProfileImageLoading = false;
profileImageError = failure.message;
+ print('❌ Failed to fetch profile image: ${failure.message}');
+
+ // Ensure data is cleared on failure
+ profileImageData = null;
+
notifyListeners();
if (onError != null) {
onError(failure.message);
@@ -215,43 +217,48 @@ class ProfileSettingsViewModel extends ChangeNotifier {
},
(response) {
isProfileImageLoading = false;
+
// Extract image data from response
if (response.data != null && response.data['Patient_GetProfileImageDataList'] != null) {
var imageList = response.data['Patient_GetProfileImageDataList'];
if (imageList is List && imageList.isNotEmpty) {
- profileImageData = imageList[0]['PatientsProfileImageData'];
- // Store in AppState for global access
- GetIt.instance().setProfileImageData = profileImageData;
+ profileImageData = imageList[0]['ImageData'];
+
+ if (profileImageData != null && profileImageData!.isNotEmpty) {
+ // ONLY store in ViewModel - AppState will be updated separately by auth flow
+ print('✅ Profile image loaded from API (length: ${profileImageData!.length})');
+ } else {
+ profileImageData = null;
+ print('⚠️ Profile image data is empty in API response');
+ }
} else {
profileImageData = null;
- GetIt.instance().setProfileImageData = null;
+ print('⚠️ Profile image list is empty in API response');
}
} else {
profileImageData = null;
- GetIt.instance().setProfileImageData = null;
+ print('⚠️ No profile image data in API response');
}
- notifyListeners();
+
+ notifyListeners(); // Notify to update UI with new/null data
onSuccess?.call(response.data);
},
);
}
- /// Clear cached profile image data
+ /// Clear profile image data from ViewModel
void clearProfileImageCache() {
+ print('🧹 Clearing profile image from ViewModel');
profileImageData = null;
- GetIt.instance().setProfileImageData = null;
notifyListeners();
}
- /// Sync profile image data from AppState
+ /// Sync profile image data from AppState - DISABLED
+ /// Profile Settings screen uses only ViewModel data from API
void syncProfileImageFromAppState() {
- final appStateImageData = GetIt.instance().getProfileImageData;
- if (appStateImageData != null && appStateImageData.isNotEmpty) {
- if (profileImageData != appStateImageData) {
- profileImageData = appStateImageData;
- notifyListeners();
- }
- }
+ // DO NOTHING - Profile Settings uses only direct API data
+ // No syncing from AppState to avoid stale cache issues
+ print('⚠️ syncProfileImageFromAppState called but disabled - use API data only');
}
Future uploadProfileImage({
@@ -286,6 +293,16 @@ class ProfileSettingsViewModel extends ChangeNotifier {
profileImageData = imageData;
// Store in AppState for global access
GetIt.instance().setProfileImageData = imageData;
+
+ // Update the family files cache with the new profile image
+ try {
+ final medicalFileViewModel = GetIt.instance.get();
+ medicalFileViewModel.updateFamilyMemberProfileImage(patientID, imageData);
+ print("✅ Updated profile image in family files cache for patient: $patientID");
+ } catch (e) {
+ print("⚠️ Could not update family files cache: $e");
+ }
+
notifyListeners();
onSuccess?.call(response.data);
},
diff --git a/lib/features/radiology/models/resp_models/radiology_ai_analysis_response_model.dart b/lib/features/radiology/models/resp_models/radiology_ai_analysis_response_model.dart
index e838f187..3f523428 100644
--- a/lib/features/radiology/models/resp_models/radiology_ai_analysis_response_model.dart
+++ b/lib/features/radiology/models/resp_models/radiology_ai_analysis_response_model.dart
@@ -2,9 +2,19 @@ import 'dart:convert';
class RadiologyAiAnalysisResponse {
String? summary;
+ String? labResults;
+ String? aiPredictions;
+ String? riskFactors;
+ String? prevention;
+ int? languageId;
RadiologyAiAnalysisResponse({
this.summary,
+ this.labResults,
+ this.aiPredictions,
+ this.riskFactors,
+ this.prevention,
+ this.languageId,
});
factory RadiologyAiAnalysisResponse.fromRawJson(String str) => RadiologyAiAnalysisResponse.fromJson(json.decode(str));
@@ -12,11 +22,20 @@ class RadiologyAiAnalysisResponse {
String toRawJson() => json.encode(toJson());
factory RadiologyAiAnalysisResponse.fromJson(Map json) => RadiologyAiAnalysisResponse(
- summary: json["summary"],
- );
+ summary: json["summary"],
+ labResults: json["lab_results"],
+ aiPredictions: json["ai_predictions"],
+ riskFactors: json["riskFactors"],
+ prevention: json["prevention"],
+ languageId: json["language_id"],
+ );
Map toJson() => {
- "summary": summary,
- };
+ "summary": summary,
+ "lab_results": labResults,
+ "ai_predictions": aiPredictions,
+ "riskFactors": riskFactors,
+ "prevention": prevention,
+ "language_id": languageId,
+ };
}
-
diff --git a/lib/features/radiology/radiology_repo.dart b/lib/features/radiology/radiology_repo.dart
index 30b078ef..7374b247 100644
--- a/lib/features/radiology/radiology_repo.dart
+++ b/lib/features/radiology/radiology_repo.dart
@@ -42,7 +42,7 @@ class RadiologyRepoImp implements RadiologyRepo {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
- final radOrders;
+ List radOrders = [];
try {
if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) {
final list = response['FinalRadiologyList'];
@@ -52,10 +52,18 @@ class RadiologyRepoImp implements RadiologyRepo {
.cast();
} else {
final list = response['FinalRadiologyListAPI'];
- radOrders = list
- .map((item) => PatientRadiologyResponseModel.fromJson(item as Map))
- .toList()
- .cast();
+ if(list != null && list.length != 0) {
+ radOrders = list
+ .map((item) => PatientRadiologyResponseModel.fromJson(item as Map))
+ .toList()
+ .cast();
+ }
+ }
+
+ // Check if radOrders is empty and set failure
+ if (radOrders.isEmpty) {
+ failure = ServerFailure(errorMessage ?? "No radiology orders found");
+ return;
}
apiResponse = GenericApiModel>(
@@ -203,6 +211,12 @@ class RadiologyRepoImp implements RadiologyRepo {
}
}
+ // Check if radOrders is empty and set failure
+ if (radOrders.isEmpty) {
+ failure = ServerFailure(errorMessage ?? "No radiology orders found for this appointment");
+ return;
+ }
+
apiResponse = GenericApiModel>(
messageStatus: messageStatus,
statusCode: statusCode,
diff --git a/lib/features/radiology/radiology_view_model.dart b/lib/features/radiology/radiology_view_model.dart
index 7386a5a0..cf795a1d 100644
--- a/lib/features/radiology/radiology_view_model.dart
+++ b/lib/features/radiology/radiology_view_model.dart
@@ -1,12 +1,10 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
-import 'package:hmg_patient_app_new/core/app_state.dart';
-import 'package:hmg_patient_app_new/core/dependencies.dart';
-import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/radiology_ai_analysis_response_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/radiology/radiology_ai_analysis_detailed_page.dart';
import 'package:hmg_patient_app_new/presentation/radiology/radiology_result_page.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
@@ -216,12 +214,11 @@ class RadiologyViewModel extends ChangeNotifier {
void setIsRadiologyAIAnalysisNeedsToBeShown(bool value) {
isRadiologyAIAnalysisNeedsToBeShown = value;
- notifyListeners();
}
void closeRadiologyAIAnalysis() {
radiologyAiAnalysisResponse = null;
- notifyListeners();
+
}
Future getRadiologyAiAnalysis({required String reportData, required String loadingText, required int langId}) async {
@@ -229,7 +226,6 @@ class RadiologyViewModel extends ChangeNotifier {
loadingText: loadingText,
showCloseButton: true,
onCloseTap: () {
- setIsRadiologyAIAnalysisNeedsToBeShown(false);
},
);
@@ -248,6 +244,10 @@ class RadiologyViewModel extends ChangeNotifier {
if (isRadiologyAIAnalysisNeedsToBeShown) {
radiologyAiAnalysisResponse = apiResponse.data;
notifyListeners();
+ // Navigate to detailed page
+ navigationService.push(
+ CustomPageRoute(direction: AxisDirection.down, page: RadiologyAiAnalysisDetailedPage()),
+ );
}
}
},
diff --git a/lib/features/water_monitor/water_monitor_view_model.dart b/lib/features/water_monitor/water_monitor_view_model.dart
index 1ef2ef65..5234a559 100644
--- a/lib/features/water_monitor/water_monitor_view_model.dart
+++ b/lib/features/water_monitor/water_monitor_view_model.dart
@@ -40,7 +40,20 @@ class WaterMonitorViewModel extends ChangeNotifier {
// Units
final List heightUnits = ['cm', 'm', 'ft', 'in'];
+ final List heightUnitsEn = ['cm', 'm', 'ft', 'in'];
+ final List heightUnitsAr = ['سم', 'م', 'قدم', 'بوصة'];
+
final List weightUnits = ['kg', 'lb'];
+ final List weightUnitsEn = ['kg', 'lb'];
+ final List weightUnitsAr = ['كجم', 'رطل'];
+
+ List getHeightUnitsList() {
+ return getIt.get().isArabic() ? heightUnitsAr : heightUnitsEn;
+ }
+
+ List getWeightUnitsList() {
+ return getIt.get().isArabic() ? weightUnitsAr : weightUnitsEn;
+ }
// Selected values
String _selectedHeightUnit = 'cm';
@@ -62,8 +75,26 @@ class WaterMonitorViewModel extends ChangeNotifier {
String get selectedHeightUnit => _selectedHeightUnit;
+ // Get the localized display value for the selected height unit
+ String get selectedHeightUnitDisplay {
+ final index = heightUnitsEn.indexOf(_selectedHeightUnit);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? heightUnitsAr[index] : heightUnitsEn[index];
+ }
+ return _selectedHeightUnit;
+ }
+
String get selectedWeightUnit => _selectedWeightUnit;
+ // Get the localized display value for the selected weight unit
+ String get selectedWeightUnitDisplay {
+ final index = weightUnitsEn.indexOf(_selectedWeightUnit);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? weightUnitsAr[index] : weightUnitsEn[index];
+ }
+ return _selectedWeightUnit;
+ }
+
String get selectedActivityLevel => _selectedActivityLevel;
String get selectedNumberOfReminders => _selectedNumberOfReminders;
@@ -75,17 +106,75 @@ class WaterMonitorViewModel extends ChangeNotifier {
bool get isGraphView => _isGraphView;
// Activity level options
- List get activityLevels =>
- ["Almost Inactive (no exercise)", "Lightly active", "Lightly active (1-3) days per week", "Super active (very hard exercise)"];
+ final List activityLevelsEn = [
+ "Almost Inactive (no exercise)",
+ "Lightly active",
+ "Lightly active (1-3) days per week",
+ "Super active (very hard exercise)"
+ ];
+
+ final List activityLevelsAr = [
+ "غير نشط تقريباً (بدون تمرين)",
+ "نشط قليلاً",
+ "نشط قليلاً (1-3) أيام في الأسبوع",
+ "نشط جداً (تمرين شاق جداً)"
+ ];
+
+ List get activityLevels => getIt.get().isArabic() ? activityLevelsAr : activityLevelsEn;
+
+ // Get the localized display value for the selected activity level
+ String get selectedActivityLevelDisplay {
+ final index = activityLevelsEn.indexOf(_selectedActivityLevel);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? activityLevelsAr[index] : activityLevelsEn[index];
+ }
+ return _selectedActivityLevel;
+ }
// Reminder options
- List get reminderOptions => ["1 Time", "2 Time", "3 Time", "4 Time", "5 Time", "6 Time"];
+ final List reminderOptionsEn = ["1 Time", "2 Time", "3 Time", "4 Time", "5 Time", "6 Time"];
+ final List reminderOptionsAr = ["مرة واحدة", "مرتين", "3 مرات", "4 مرات", "5 مرات", "6 مرات"];
+
+ List get reminderOptions => getIt.get().isArabic() ? reminderOptionsAr : reminderOptionsEn;
+
+ // Get the localized display value for the selected number of reminders
+ String get selectedNumberOfRemindersDisplay {
+ final index = reminderOptionsEn.indexOf(_selectedNumberOfReminders);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? reminderOptionsAr[index] : reminderOptionsEn[index];
+ }
+ return _selectedNumberOfReminders;
+ }
// Gender options
- List get genderOptions => ["Male", "Female"];
+ final List genderOptionsEn = ["Male", "Female"];
+ final List genderOptionsAr = ["ذكر", "أنثى"];
+
+ List get genderOptions => getIt.get().isArabic() ? genderOptionsAr : genderOptionsEn;
+
+ // Get the localized display value for the selected gender
+ String get selectedGenderDisplay {
+ final index = genderOptionsEn.indexOf(_selectedGender);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? genderOptionsAr[index] : genderOptionsEn[index];
+ }
+ return _selectedGender;
+ }
+
+ // Duration Options
+ final List durationFiltersEn = ["Daily", "Weekly", "Monthly"];
+ final List durationFiltersAr = ["يومي", "أسبوعي", "شهري"];
-//Duration Options
- List get durationFilters => ["Daily", "Weekly", "Monthly"];
+ List get durationFilters => getIt.get().isArabic() ? durationFiltersAr : durationFiltersEn;
+
+ // Get the localized display value for the selected duration
+ String get selectedDurationFilterDisplay {
+ final index = durationFiltersEn.indexOf(_selectedDuration);
+ if (index >= 0) {
+ return getIt.get().isArabic() ? durationFiltersAr[index] : durationFiltersEn[index];
+ }
+ return _selectedDuration;
+ }
// Network/data
final AppState _appState = GetIt.instance();
@@ -503,7 +592,15 @@ class WaterMonitorViewModel extends ChangeNotifier {
// Setters with notification
void setFilterDuration(String duration) async {
- _selectedDuration = duration;
+ // Map Arabic values to English keys
+ if (getIt.get().isArabic()) {
+ final index = durationFiltersAr.indexOf(duration);
+ if (index >= 0 && index < durationFiltersEn.length) {
+ _selectedDuration = durationFiltersEn[index];
+ }
+ } else {
+ _selectedDuration = duration;
+ }
notifyListeners();
// Fetch new progress data when duration filter changes
await fetchUserProgressForMonitoring();
@@ -517,27 +614,67 @@ class WaterMonitorViewModel extends ChangeNotifier {
// Setters with notification
void setGender(String gender) {
- _selectedGender = gender;
+ // Map Arabic values to English keys
+ if (getIt.get().isArabic()) {
+ final index = genderOptionsAr.indexOf(gender);
+ if (index >= 0 && index < genderOptionsEn.length) {
+ _selectedGender = genderOptionsEn[index];
+ }
+ } else {
+ _selectedGender = gender;
+ }
notifyListeners();
}
void setHeightUnit(String unit) {
- _selectedHeightUnit = unit;
+ // Map Arabic values to English keys
+ if (getIt.get