Merge branch 'master' into dev_aamir

# Conflicts:
#	lib/presentation/profile_settings/profile_settings.dart
pull/166/head
aamir-csol 2 months ago
commit 2bbfe1f131

@ -1,3 +1,11 @@
# Translation prompt & Command
Read the context for both files & generate translations strings in the en-US.json & ar-SA.json files for the strings containing "needTranslation". Also replace the strings in the dart with the generated Strings. Also do not remove existing properties & do no generate duplicate strings in the json files
flutter3_32 pub run easy_localization:generate -O ./lib/generated -f keys -o locale_keys.g.dart --source-dir ./assets/langs
# HMG Patient App # HMG Patient App
A comprehensive Flutter-based mobile application for HMG (Habib Medical Group) patients, A comprehensive Flutter-based mobile application for HMG (Habib Medical Group) patients,

@ -0,0 +1,3 @@
<svg width="15" height="23" viewBox="0 0 15 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.32806 22.32C7.33606 22.32 6.34406 22.2 5.35206 21.96C4.37606 21.736 3.48006 21.36 2.66406 20.832C1.86406 20.304 1.21606 19.616 0.720063 18.768C0.240063 17.92 6.25104e-05 16.88 6.25104e-05 15.648C6.25104e-05 14.4 0.248063 13.248 0.744063 12.192C1.25606 11.12 1.96806 10.168 2.88006 9.336C3.80806 8.488 4.90406 7.784 6.16806 7.224C7.43206 6.664 8.81606 6.264 10.3201 6.024L10.9921 8.688C9.68006 8.928 8.51206 9.256 7.48806 9.672C6.48006 10.088 5.62406 10.584 4.92006 11.16C4.23206 11.736 3.71206 12.368 3.36006 13.056C3.00806 13.76 2.83206 14.512 2.83206 15.312C2.83206 15.952 2.94406 16.504 3.16806 16.968C3.40806 17.448 3.72006 17.848 4.10406 18.168C4.48806 18.488 4.92006 18.744 5.40006 18.936C5.88006 19.128 6.37606 19.264 6.88806 19.344C7.40006 19.44 7.88006 19.488 8.32806 19.488C9.33606 19.488 10.3041 19.392 11.2321 19.2C12.1601 19.024 12.9841 18.784 13.7041 18.48L14.5201 21.024C14.1361 21.216 13.6081 21.408 12.9361 21.6C12.2641 21.808 11.5281 21.976 10.7281 22.104C9.92806 22.248 9.12806 22.32 8.32806 22.32ZM3.86406 9.24C3.27206 9.048 2.72806 8.744 2.23206 8.328C1.75206 7.912 1.36806 7.4 1.08006 6.792C0.792063 6.184 0.648063 5.512 0.648063 4.776C0.648063 3.768 0.904063 2.912 1.41606 2.208C1.92806 1.488 2.59206 0.943998 3.40806 0.575998C4.24006 0.191998 5.13606 -1.90735e-06 6.09606 -1.90735e-06C6.56006 -1.90735e-06 7.00806 0.0319982 7.44006 0.0959983C7.87206 0.159998 8.30406 0.255998 8.73606 0.383997L8.25606 3.072C7.92006 2.992 7.57606 2.928 7.22406 2.88C6.87206 2.832 6.56006 2.808 6.28806 2.808C5.72806 2.808 5.23206 2.896 4.80006 3.072C4.38406 3.248 4.05606 3.496 3.81606 3.816C3.59206 4.136 3.48006 4.512 3.48006 4.944C3.48006 5.312 3.58406 5.656 3.79206 5.976C4.01606 6.28 4.29606 6.544 4.63206 6.768C4.98406 6.992 5.35206 7.168 5.73606 7.296C6.13606 7.424 6.50406 7.496 6.84006 7.512L3.86406 9.24Z" fill="#2B353E"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -0,0 +1,5 @@
<svg width="24" height="22" viewBox="0 0 24 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="7" cy="7" r="7" fill="#0B85F7" fill-opacity="0.75"/>
<circle cx="17" cy="7" r="7" fill="#18C273" fill-opacity="0.75"/>
<circle cx="12" cy="15" r="7" fill="#ED1C2B" fill-opacity="0.75"/>
</svg>

After

Width:  |  Height:  |  Size: 301 B

@ -0,0 +1,3 @@
<svg width="12" height="21" viewBox="0 0 12 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.72994 2.25V9.24H10.3499V11.49H2.72994V18.69H11.2499V20.94H-5.83827e-05V2.02656e-06H11.2499V2.25H2.72994Z" fill="#2B353E"/>
</svg>

After

Width:  |  Height:  |  Size: 242 B

@ -1377,6 +1377,18 @@
"suggestions": "الاقتراحات", "suggestions": "الاقتراحات",
"pleaseGoBackAndSelectOrgansFirst": "يرجى العودة واختيار الأعضاء أولاً", "pleaseGoBackAndSelectOrgansFirst": "يرجى العودة واختيار الأعضاء أولاً",
"symptomsSelector": "محدد الأعراض", "symptomsSelector": "محدد الأعراض",
"possibleSymptomsRelatedTo": "الأعراض المحتملة المتعلقة بـ",
"suggestionAIListDescription": "هذه قائمة بالأعراض المقترحة من قبل الذكاء الاصطناعي، بناءً على المعلومات التي تم جمعها حتى الآن خلال المقابلة",
"analyzing": "جاري التحليل...",
"seekMedicalAdvice": "اطلب المشورة الطبية",
"monitorDescription": "لا حاجة لطلب المشورة الطبية. فقط حافظ على روتين صحي.",
"seekMedicalAdviceDescription": "ليست حالة طوارئ ولكن من الأفضل مراقبة الأعراض.",
"emergencyDescription": "تحتاج إلى استشارة الطبيب في أقرب وقت ممكن قبل فوات الأوان.",
"colorScience": "دلالات الألوان",
"noNeedToVisitDoctor": "لا حاجة لزي<D8B2><D98A>رة الطبيب",
"commonSymptom": "الأعراض الشائعة",
"bookAppointment": "احجز موعد",
"notApplicable": "لا ينطبق",
"emergencyTriage": "طوارئ", "emergencyTriage": "طوارئ",
"emergencyEvidenceDetected": "تم اكتشاف دليل طوارئ. يرجى طلب العناية الطبية.", "emergencyEvidenceDetected": "تم اكتشاف دليل طوارئ. يرجى طلب العناية الطبية.",
"noQuestionItemsAvailable": "لا توجد عناصر أسئلة متاحة", "noQuestionItemsAvailable": "لا توجد عناصر أسئلة متاحة",
@ -1499,5 +1511,20 @@
"selectTime": "حدد الوقت", "selectTime": "حدد الوقت",
"pleaseWaitYouWillBeCalledForVitalSigns": "يرجى الانتظار! سيتم استدعاؤك لقياس العلامات الحيوية", "pleaseWaitYouWillBeCalledForVitalSigns": "يرجى الانتظار! سيتم استدعاؤك لقياس العلامات الحيوية",
"pleaseVisitRoomForVitalSigns": "يرجى زيارة الغرفة {roomNumber} لقياس العلامات الحيوية", "pleaseVisitRoomForVitalSigns": "يرجى زيارة الغرفة {roomNumber} لقياس العلامات الحيوية",
"pleaseVisitRoomToTheDoctor": "يرجى زيارة الغرفة {roomNumber} لمقابلة الطبيب" "pleaseVisitRoomToTheDoctor": "يرجى زيارة الغرفة {roomNumber} لمقابلة الطبيب",
"erOnlineCheckInRequest": "طلب تسجيل الوصول عبر الإنترنت لقسم الطوارئ",
"indoor": "داخلي",
"navigation": "الملاحة",
"health": "الصحة",
"calculators": "الحاسبات",
"converters": "المحولات",
"guide": "الدليل",
"liveCareServiceDesc": "احصل على استشارة طبية من طبيب متخصص عبر مكالمة فيديو",
"bloodGroup": "فصيلة الدم: {bloodType}",
"medicalServices": "الخدمات الطبية",
"insuranceAndPayments": "التأمين والمدفوعات",
"trackerAndOthers": "المتتبع وأخرى",
"bmi": "مؤشر كتلة الجسم"
} }

@ -1367,6 +1367,18 @@
"suggestions": "Suggestions", "suggestions": "Suggestions",
"pleaseGoBackAndSelectOrgansFirst": "Please go back and select organs first", "pleaseGoBackAndSelectOrgansFirst": "Please go back and select organs first",
"symptomsSelector": "Symptoms Selector", "symptomsSelector": "Symptoms Selector",
"possibleSymptomsRelatedTo": "Possible symptoms related to",
"suggestionAIListDescription": "This is a list of symptoms suggested by our AI, based on the information gathered so far during the interview",
"analyzing": "Analyzing...",
"seekMedicalAdvice": "Seek Medical Advice",
"monitorDescription": "No need to seek medical advice. Just keep healthy routine.",
"seekMedicalAdviceDescription": "Not emergency but better to monitor the symptoms.",
"emergencyDescription": "Need to consult doctor as soon as possible before getting too late.",
"colorScience": "Color Science",
"noNeedToVisitDoctor": "No need to visit doctor",
"commonSymptom": "Common Symptom",
"bookAppointment": "Book Appointment",
"notApplicable": "Not Applicable",
"emergencyTriage": "Emergency", "emergencyTriage": "Emergency",
"emergencyEvidenceDetected": "Emergency evidence detected. Please seek medical attention.", "emergencyEvidenceDetected": "Emergency evidence detected. Please seek medical attention.",
"noQuestionItemsAvailable": "No question items available", "noQuestionItemsAvailable": "No question items available",
@ -1490,5 +1502,20 @@
"selectTime": "Select Time", "selectTime": "Select Time",
"pleaseWaitYouWillBeCalledForVitalSigns": "Please wait! you will be called for vital signs", "pleaseWaitYouWillBeCalledForVitalSigns": "Please wait! you will be called for vital signs",
"pleaseVisitRoomForVitalSigns": "Please visit Room {roomNumber} for vital signs", "pleaseVisitRoomForVitalSigns": "Please visit Room {roomNumber} for vital signs",
"pleaseVisitRoomToTheDoctor": "Please visit Room {roomNumber} to the Doctor" "pleaseVisitRoomToTheDoctor": "Please visit Room {roomNumber} to the Doctor",
"erOnlineCheckInRequest": "ER Online Check-In Request",
"indoor": "Indoor",
"navigation": "Navigation",
"health": "Health",
"calculators": "Calculators",
"converters": "Converters",
"guide": "Guide",
"liveCareServiceDesc": "Get medical advice with a specialist doctor Via a video call",
"bloodGroup": "Blood: {bloodType}",
"medicalServices": "Medical Services",
"insuranceAndPayments": "Insurance & Payments",
"trackerAndOthers": "Tracker & Others",
"bmi": "BMI"
} }

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

@ -189,6 +189,8 @@ class ApiClientImp implements ApiClient {
// body['SessionID'] = "45786230487560q"; // body['SessionID'] = "45786230487560q";
} }
// body['IsNewFlutterApp'] = true;
body.removeWhere((key, value) => value == null); body.removeWhere((key, value) => value == null);
} }

@ -841,7 +841,7 @@ class ApiConsts {
static final String getRiskFactors = '$symptomsCheckerApi/GetRiskFactors'; static final String getRiskFactors = '$symptomsCheckerApi/GetRiskFactors';
static final String getSuggestions = '$symptomsCheckerApi/GetSuggestion'; static final String getSuggestions = '$symptomsCheckerApi/GetSuggestion';
static final String diagnosis = '$symptomsCheckerApi/GetDiagnosis'; static final String diagnosis = '$symptomsCheckerApi/GetDiagnosis';
static final String explain = '$symptomsCheckerApi/explain'; static final String explain = '$symptomsCheckerApi/ExplainDiagnosisResult';
//E-REFERRAL SERVICES //E-REFERRAL SERVICES
static final getAllRelationshipTypes = "Services/Patients.svc/REST/GetAllRelationshipTypes"; static final getAllRelationshipTypes = "Services/Patients.svc/REST/GetAllRelationshipTypes";

@ -254,6 +254,7 @@ class AppAssets {
static const String homeBorderedIcon = '$svgBasePath/home_bordered.svg'; static const String homeBorderedIcon = '$svgBasePath/home_bordered.svg';
static const String symptomCheckerIcon = '$svgBasePath/symptom_checker_icon.svg'; static const String symptomCheckerIcon = '$svgBasePath/symptom_checker_icon.svg';
static const String symptomCheckerBottomIcon = '$svgBasePath/symptom_bottom_icon.svg'; static const String symptomCheckerBottomIcon = '$svgBasePath/symptom_bottom_icon.svg';
static const String coloredDotsIcon = '$svgBasePath/colored_dots_icon.svg';
// Water Monitor // Water Monitor
static const String waterBottle = '$svgBasePath/water_bottle.svg'; static const String waterBottle = '$svgBasePath/water_bottle.svg';
@ -306,6 +307,9 @@ class AppAssets {
static const String bloodPressure = '$svgBasePath/blood_pressure.svg'; static const String bloodPressure = '$svgBasePath/blood_pressure.svg';
static const String temperature = '$svgBasePath/temperature.svg'; static const String temperature = '$svgBasePath/temperature.svg';
static const String arLangIcon = '$svgBasePath/ar_lang_icon.svg';
static const String enLangIcon = '$svgBasePath/en_lang_icon.svg';
// PNGS // // PNGS //
static const String hmgLogo = '$pngBasePath/hmg_logo.png'; static const String hmgLogo = '$pngBasePath/hmg_logo.png';
static const String liveCareService = '$pngBasePath/livecare_service.png'; static const String liveCareService = '$pngBasePath/livecare_service.png';
@ -353,4 +357,3 @@ class AppAnimations {
static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json'; static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json';
static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json'; static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json';
} }

@ -311,3 +311,150 @@ extension ServiceTypeEnumExt on ServiceTypeEnum {
enum PossibleConditionsSeverityEnum { seekMedicalAdvice, monitorOnly, emergency } enum PossibleConditionsSeverityEnum { seekMedicalAdvice, monitorOnly, emergency }
enum HealthTrackerTypeEnum { bloodSugar, bloodPressure, weightTracker } enum HealthTrackerTypeEnum { bloodSugar, bloodPressure, weightTracker }
// Severity Enum
enum SeverityEnum { mild, moderate, severe }
extension SeverityEnumExtension on SeverityEnum {
int get toInt {
switch (this) {
case SeverityEnum.mild:
return 0;
case SeverityEnum.moderate:
return 1;
case SeverityEnum.severe:
return 2;
}
}
String get displayName {
AppState appState = getIt.get<AppState>();
bool isArabic = appState.getLanguageID() == 1 ? true : false;
switch (this) {
case SeverityEnum.mild:
return isArabic ? 'خفيف' : 'Mild';
case SeverityEnum.moderate:
return isArabic ? 'متوسط' : 'Moderate';
case SeverityEnum.severe:
return isArabic ? 'شديد' : 'Severe';
}
}
static SeverityEnum? fromInt(int value) {
switch (value) {
case 0:
return SeverityEnum.mild;
case 1:
return SeverityEnum.moderate;
case 2:
return SeverityEnum.severe;
default:
return null;
}
}
}
// Triage Level Enum
enum TriageLevelEnum { emergencyAmbulance, emergency, consultation24, consultation, selfCare }
extension TriageLevelEnumExtension on TriageLevelEnum {
int get toInt {
switch (this) {
case TriageLevelEnum.emergencyAmbulance:
return 0;
case TriageLevelEnum.emergency:
return 1;
case TriageLevelEnum.consultation24:
return 2;
case TriageLevelEnum.consultation:
return 3;
case TriageLevelEnum.selfCare:
return 4;
}
}
String get displayName {
AppState appState = getIt.get<AppState>();
bool isArabic = appState.getLanguageID() == 1 ? true : false;
switch (this) {
case TriageLevelEnum.emergencyAmbulance:
return isArabic ? 'طوارئ - إسعاف' : 'Emergency - Ambulance';
case TriageLevelEnum.emergency:
return isArabic ? 'طوارئ' : 'Emergency';
case TriageLevelEnum.consultation24:
return isArabic ? 'استشارة خلال 24 ساعة' : 'Consultation within 24 hours';
case TriageLevelEnum.consultation:
return isArabic ? 'استشارة' : 'Consultation';
case TriageLevelEnum.selfCare:
return isArabic ? 'رعاية ذاتية' : 'Self Care';
}
}
static TriageLevelEnum? fromInt(int value) {
switch (value) {
case 0:
return TriageLevelEnum.emergencyAmbulance;
case 1:
return TriageLevelEnum.emergency;
case 2:
return TriageLevelEnum.consultation24;
case 3:
return TriageLevelEnum.consultation;
case 4:
return TriageLevelEnum.selfCare;
default:
return null;
}
}
}
// Question Type Enum
enum QuestionTypeEnum { single, groupSingle, groupMultiple, duration }
extension QuestionTypeEnumExtension on QuestionTypeEnum {
int get toInt {
switch (this) {
case QuestionTypeEnum.single:
return 0;
case QuestionTypeEnum.groupSingle:
return 1;
case QuestionTypeEnum.groupMultiple:
return 2;
case QuestionTypeEnum.duration:
return 3;
}
}
String get displayName {
AppState appState = getIt.get<AppState>();
bool isArabic = appState.getLanguageID() == 1 ? true : false;
switch (this) {
case QuestionTypeEnum.single:
return isArabic ? 'سؤال واحد' : 'Single';
case QuestionTypeEnum.groupSingle:
return isArabic ? 'مجموعة - اختيار واحد' : 'Group Single';
case QuestionTypeEnum.groupMultiple:
return isArabic ? 'مجموعة - اختيار متعدد' : 'Group Multiple';
case QuestionTypeEnum.duration:
return isArabic ? 'المدة' : 'Duration';
}
}
static QuestionTypeEnum? fromInt(int value) {
switch (value) {
case 0:
return QuestionTypeEnum.single;
case 1:
return QuestionTypeEnum.groupSingle;
case 2:
return QuestionTypeEnum.groupMultiple;
case 3:
return QuestionTypeEnum.duration;
default:
return null;
}
}
}

@ -814,7 +814,8 @@ class Utils {
child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: iconColor), child: Utils.buildSvgWithAssets(icon: AppAssets.saudi_riyal_icon, width: iconSize.h, height: iconSize.h, iconColor: iconColor),
), ),
TextSpan( TextSpan(
text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount), // text: NumberFormat.currency(locale: 'en_US', symbol: " ", decimalDigits: 0).format(habibWalletAmount),
text: " ${habibWalletAmount.toStringAsFixed(2)}",
style: TextStyle( style: TextStyle(
color: textColor, color: textColor,
fontSize: fontSize ?? 32.f, fontSize: fontSize ?? 32.f,

@ -571,7 +571,7 @@ class AuthenticationViewModel extends ChangeNotifier {
MedicalFileViewModel medicalVm = getIt<MedicalFileViewModel>(); MedicalFileViewModel medicalVm = getIt<MedicalFileViewModel>();
if (!_appState.getIsChildLoggedIn) { if (!_appState.getIsChildLoggedIn) {
await medicalVm.getFamilyFiles(status: 0); await medicalVm.getFamilyFiles(status: 0);
await medicalVm.getAllPendingRecordsByResponseId(); // await medicalVm.getAllPendingRecordsByResponseId();
_navigationService.replaceAllRoutesAndNavigateToLanding(); _navigationService.replaceAllRoutesAndNavigateToLanding();
} }
} else { } else {
@ -610,7 +610,7 @@ class AuthenticationViewModel extends ChangeNotifier {
MedicalFileViewModel medicalVm = getIt<MedicalFileViewModel>(); MedicalFileViewModel medicalVm = getIt<MedicalFileViewModel>();
insertPatientIMEIData(loginTypeEnum.toInt); insertPatientIMEIData(loginTypeEnum.toInt);
medicalVm.getFamilyFiles(status: 0); //TODO: Remove status: 1 by Aamir Need to Discuss With Sultan medicalVm.getFamilyFiles(status: 0); //TODO: Remove status: 1 by Aamir Need to Discuss With Sultan
medicalVm.getAllPendingRecordsByResponseId(); // medicalVm.getAllPendingRecordsByResponseId();
} }
await clearDefaultInputValues(); await clearDefaultInputValues();
if (isUserAgreedBefore) { if (isUserAgreedBefore) {

@ -545,20 +545,20 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 10.h),
LocaleKeys.otpVerification.tr().toText24(isBold: true), LocaleKeys.otpVerification.tr(context: context).toText24(isBold: true),
SizedBox(height: 20.h), SizedBox(height: 20.h),
Wrap( Wrap(
spacing: 2.h, spacing: 2.h,
runSpacing: 2.h, runSpacing: 2.h,
children: [ children: [
LocaleKeys.weHaveSendOTP.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4), LocaleKeys.weHaveSendOTP.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
_getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true), _getMaskedPhoneNumber().toText15(color: AppColors.inputLabelTextColor, isBold: true),
LocaleKeys.via.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4), LocaleKeys.via.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
(widget.isFormFamilyFile ? LoginTypeEnum.sms.displayName : authVM.loginTypeEnum.displayName) (widget.isFormFamilyFile ? LoginTypeEnum.sms.displayName : authVM.loginTypeEnum.displayName)
.toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4), .toText15(color: AppColors.inputLabelTextColor, isBold: true, letterSpacing: -0.4),
appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true appState.getUserRegistrationPayload.isRegister != null && appState.getUserRegistrationPayload.isRegister == true
? LocaleKeys.forRegistrationVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4) ? LocaleKeys.forRegistrationVerification.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4)
: LocaleKeys.forLoginVerification.tr().toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4), : LocaleKeys.forLoginVerification.tr(context: context).toText15(color: AppColors.inputLabelTextColor, letterSpacing: -0.4),
], ],
), ),
@ -590,7 +590,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
LocaleKeys.didntReceiveIt.tr().toText16(color: AppColors.inputLabelTextColor), LocaleKeys.didntReceiveIt.tr(context: context).toText16(color: AppColors.inputLabelTextColor),
SizedBox(width: 5.h), SizedBox(width: 5.h),
if (_resendTime > 0) if (_resendTime > 0)
Builder( Builder(
@ -599,7 +599,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
final seconds = (_resendTime % 60).toString().padLeft(2, '0'); final seconds = (_resendTime % 60).toString().padLeft(2, '0');
return Row( return Row(
children: [ children: [
LocaleKeys.resendIn.tr().toText16(color: AppColors.inputLabelTextColor), LocaleKeys.resendIn.tr(context: context).toText16(color: AppColors.inputLabelTextColor),
SizedBox(width: 2.h), SizedBox(width: 2.h),
' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor) ' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor)
], ],
@ -609,7 +609,7 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
else else
GestureDetector( GestureDetector(
onTap: _resendOtp, onTap: _resendOtp,
child: LocaleKeys.resendOTP.tr().toText16(color: AppColors.primaryRedColor), child: LocaleKeys.resendOTP.tr(context: context).toText16(color: AppColors.primaryRedColor),
), ),
], ],
), ),

@ -45,9 +45,7 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
initImmediateLiveCare() { initImmediateLiveCare() {
_appState = getIt<AppState>(); _appState = getIt<AppState>();
immediateLiveCareClinicsList = []; immediateLiveCareClinicsList = [];
patientLiveCareHistoryList = [];
isImmediateLiveCareClinicsLoading = true; isImmediateLiveCareClinicsLoading = true;
patientHasPendingLiveCareRequest = false;
liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone
immediateLiveCareSelectedClinic = GetLiveCareClinicListResponseModel(); immediateLiveCareSelectedClinic = GetLiveCareClinicListResponseModel();
liveCareImmediateAppointmentFeesList = LiveCareImmediateAppointmentFeesList(); liveCareImmediateAppointmentFeesList = LiveCareImmediateAppointmentFeesList();
@ -136,6 +134,10 @@ class ImmediateLiveCareViewModel extends ChangeNotifier {
} }
Future<void> getPatientLiveCareHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientLiveCareHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async {
patientLiveCareHistoryList = [];
patientHasPendingLiveCareRequest = false;
notifyListeners();
final result = await immediateLiveCareRepo.getPatientLiveCareHistory(); final result = await immediateLiveCareRepo.getPatientLiveCareHistory();
result.fold( result.fold(

@ -220,6 +220,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
} }
Future<void> getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
isPatientHasQueueAppointment = false;
if (!isAppointmentDataToBeLoaded) return; if (!isAppointmentDataToBeLoaded) return;
filteredAppointmentList.clear(); filteredAppointmentList.clear();
@ -727,6 +728,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
Future<void> getPatientAppointmentQueueDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async { Future<void> getPatientAppointmentQueueDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async {
//TODO: Discuss With Haroon, Is the User Has no data it return No Element Bad State; //TODO: Discuss With Haroon, Is the User Has no data it return No Element Bad State;
isPatientHasQueueAppointment = false;
isAppointmentQueueDetailsLoading = true; isAppointmentQueueDetailsLoading = true;
notifyListeners(); notifyListeners();
final result = await myAppointmentsRepo.getPatientAppointmentQueueDetails( final result = await myAppointmentsRepo.getPatientAppointmentQueueDetails(

@ -8,28 +8,36 @@ class OrganData {
OrganModel( OrganModel(
id: 'head', id: 'head',
name: 'whole_head', name: 'whole_head',
nameAr: 'الرأس_كامل',
description: 'Head', description: 'Head',
descriptionAr: 'الرأس',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.50, y: 0.03), position: OrganPosition(x: 0.50, y: 0.03),
), ),
OrganModel( OrganModel(
id: 'left_eye', id: 'left_eye',
name: 'eyes', name: 'eyes',
nameAr: 'العيون',
description: 'Left Eye', description: 'Left Eye',
descriptionAr: 'العين اليسرى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.43, y: 0.07), position: OrganPosition(x: 0.43, y: 0.07),
), ),
OrganModel( OrganModel(
id: 'right_eye', id: 'right_eye',
name: 'eyes', name: 'eyes',
nameAr: 'العيون',
description: 'Right Eye', description: 'Right Eye',
descriptionAr: 'العين اليمنى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.57, y: 0.07), position: OrganPosition(x: 0.57, y: 0.07),
), ),
OrganModel( OrganModel(
id: 'nose_mouth', id: 'nose_mouth',
name: 'oral_cavity', name: 'oral_cavity',
nameAr: 'تجويف_الفم',
description: 'Nose/Mouth', description: 'Nose/Mouth',
descriptionAr: 'الأنف/الفم',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.50, y: 0.09), position: OrganPosition(x: 0.50, y: 0.09),
), ),
@ -38,7 +46,9 @@ class OrganData {
OrganModel( OrganModel(
id: 'throat', id: 'throat',
name: 'neck_or_throat', name: 'neck_or_throat',
nameAr: 'الرقبة_أو_الحلق',
description: 'Throat', description: 'Throat',
descriptionAr: 'الحلق',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.50, y: 0.15), position: OrganPosition(x: 0.50, y: 0.15),
), ),
@ -47,14 +57,18 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_shoulder', id: 'left_shoulder',
name: 'upper_arm', name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Left Shoulder', description: 'Left Shoulder',
descriptionAr: 'الكتف الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.22, y: 0.22), position: OrganPosition(x: 0.22, y: 0.22),
), ),
OrganModel( OrganModel(
id: 'right_shoulder', id: 'right_shoulder',
name: 'upper_arm', name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Right Shoulder', description: 'Right Shoulder',
descriptionAr: 'الكتف الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.8, y: 0.22), position: OrganPosition(x: 0.8, y: 0.22),
), ),
@ -63,21 +77,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_chest', id: 'left_chest',
name: 'chest', name: 'chest',
nameAr: 'الصدر',
description: 'Left Chest', description: 'Left Chest',
descriptionAr: 'الصدر الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.38, y: 0.22), position: OrganPosition(x: 0.38, y: 0.22),
), ),
OrganModel( OrganModel(
id: 'center_chest', id: 'center_chest',
name: 'chest', name: 'chest',
nameAr: 'الصدر',
description: 'Center Chest', description: 'Center Chest',
descriptionAr: 'وسط الصدر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.52, y: 0.25), position: OrganPosition(x: 0.52, y: 0.25),
), ),
OrganModel( OrganModel(
id: 'right_chest', id: 'right_chest',
name: 'chest', name: 'chest',
nameAr: 'الصدر',
description: 'Right Chest', description: 'Right Chest',
descriptionAr: 'الصدر الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.65, y: 0.22), position: OrganPosition(x: 0.65, y: 0.22),
), ),
@ -86,14 +106,18 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_ribs', id: 'left_ribs',
name: 'chest', name: 'chest',
nameAr: 'الصدر',
description: 'Left Ribs', description: 'Left Ribs',
descriptionAr: 'الأضلاع اليسرى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.38, y: 0.35), position: OrganPosition(x: 0.38, y: 0.35),
), ),
OrganModel( OrganModel(
id: 'right_ribs', id: 'right_ribs',
name: 'chest', name: 'chest',
nameAr: 'الصدر',
description: 'Right Ribs', description: 'Right Ribs',
descriptionAr: 'الأضلاع اليمنى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.64, y: 0.35), position: OrganPosition(x: 0.64, y: 0.35),
), ),
@ -102,21 +126,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'upper_abdomen', id: 'upper_abdomen',
name: 'upper_abdomen', name: 'upper_abdomen',
nameAr: 'البطن_العلوي',
description: 'Upper Abdomen', description: 'Upper Abdomen',
descriptionAr: 'أعلى البطن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.51, y: 0.31), position: OrganPosition(x: 0.51, y: 0.31),
), ),
OrganModel( OrganModel(
id: 'navel', id: 'navel',
name: 'mid_abdomen', name: 'mid_abdomen',
nameAr: 'البطن_الأوسط',
description: 'Navel', description: 'Navel',
descriptionAr: 'السرة',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.51, y: 0.38), position: OrganPosition(x: 0.51, y: 0.38),
), ),
OrganModel( OrganModel(
id: 'lower_abdomen', id: 'lower_abdomen',
name: 'lower_abdomen', name: 'lower_abdomen',
nameAr: 'البطن_السفلي',
description: 'Lower Abdomen', description: 'Lower Abdomen',
descriptionAr: 'أسفل البطن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.51, y: 0.44), position: OrganPosition(x: 0.51, y: 0.44),
), ),
@ -125,14 +155,18 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_groin', id: 'left_groin',
name: 'sexual_organs', name: 'sexual_organs',
nameAr: 'الأعضاء_التناسلية',
description: 'Left Groin', description: 'Left Groin',
descriptionAr: 'الفخذ الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.42, y: 0.49), position: OrganPosition(x: 0.42, y: 0.49),
), ),
OrganModel( OrganModel(
id: 'right_groin', id: 'right_groin',
name: 'sexual_organs', name: 'sexual_organs',
nameAr: 'الأعضاء_التناسلية',
description: 'Right Groin', description: 'Right Groin',
descriptionAr: 'الفخذ الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.59, y: 0.49), position: OrganPosition(x: 0.59, y: 0.49),
), ),
@ -142,21 +176,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_elbow', id: 'left_elbow',
name: 'elbow', name: 'elbow',
nameAr: 'الكوع',
description: 'Left Elbow', description: 'Left Elbow',
descriptionAr: 'الكوع الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.21, y: 0.35), position: OrganPosition(x: 0.21, y: 0.35),
), ),
OrganModel( OrganModel(
id: 'left_forearm', id: 'left_forearm',
name: 'forearm', name: 'forearm',
nameAr: 'الساعد',
description: 'Left Forearm', description: 'Left Forearm',
descriptionAr: 'الساعد الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.19, y: 0.43), position: OrganPosition(x: 0.19, y: 0.43),
), ),
OrganModel( OrganModel(
id: 'left_wrist', id: 'left_wrist',
name: 'hand', name: 'hand',
nameAr: 'اليد',
description: 'Left Wrist', description: 'Left Wrist',
descriptionAr: 'المعصم الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.14, y: 0.5), position: OrganPosition(x: 0.14, y: 0.5),
), ),
@ -166,21 +206,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'right_elbow', id: 'right_elbow',
name: 'elbow', name: 'elbow',
nameAr: 'الكوع',
description: 'Right Elbow', description: 'Right Elbow',
descriptionAr: 'الكوع الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.79, y: 0.35), position: OrganPosition(x: 0.79, y: 0.35),
), ),
OrganModel( OrganModel(
id: 'right_forearm', id: 'right_forearm',
name: 'forearm', name: 'forearm',
nameAr: 'الساعد',
description: 'Right Forearm', description: 'Right Forearm',
descriptionAr: 'الساعد الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.81, y: 0.43), position: OrganPosition(x: 0.81, y: 0.43),
), ),
OrganModel( OrganModel(
id: 'right_wrist', id: 'right_wrist',
name: 'hand', name: 'hand',
nameAr: 'اليد',
description: 'Right Wrist', description: 'Right Wrist',
descriptionAr: 'المعصم الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.85, y: 0.5), position: OrganPosition(x: 0.85, y: 0.5),
), ),
@ -189,28 +235,36 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_thigh', id: 'left_thigh',
name: 'thigh', name: 'thigh',
nameAr: 'الفخذ',
description: 'Left Thigh', description: 'Left Thigh',
descriptionAr: 'الفخذ الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.4, y: 0.60), position: OrganPosition(x: 0.4, y: 0.60),
), ),
OrganModel( OrganModel(
id: 'left_knee', id: 'left_knee',
name: 'knee', name: 'knee',
nameAr: 'الركبة',
description: 'Left Knee', description: 'Left Knee',
descriptionAr: 'الركبة اليسرى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.4, y: 0.72), position: OrganPosition(x: 0.4, y: 0.72),
), ),
OrganModel( OrganModel(
id: 'left_shin', id: 'left_shin',
name: 'lower_leg', name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Left Shin', description: 'Left Shin',
descriptionAr: 'الساق اليسرى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.41, y: 0.82), position: OrganPosition(x: 0.41, y: 0.82),
), ),
OrganModel( OrganModel(
id: 'left_ankle', id: 'left_ankle',
name: 'foot', name: 'foot',
nameAr: 'القدم',
description: 'Left Ankle', description: 'Left Ankle',
descriptionAr: 'الكاحل الأيسر',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.43, y: 0.91), position: OrganPosition(x: 0.43, y: 0.91),
), ),
@ -219,28 +273,36 @@ class OrganData {
OrganModel( OrganModel(
id: 'right_thigh', id: 'right_thigh',
name: 'thigh', name: 'thigh',
nameAr: 'الفخذ',
description: 'Right Thigh', description: 'Right Thigh',
descriptionAr: 'الفخذ الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.65, y: 0.60), position: OrganPosition(x: 0.65, y: 0.60),
), ),
OrganModel( OrganModel(
id: 'right_knee', id: 'right_knee',
name: 'knee', name: 'knee',
nameAr: 'الركبة',
description: 'Right Knee', description: 'Right Knee',
descriptionAr: 'الركبة اليمنى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.6, y: 0.72), position: OrganPosition(x: 0.6, y: 0.72),
), ),
OrganModel( OrganModel(
id: 'right_shin', id: 'right_shin',
name: 'lower_leg', name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Right Shin', description: 'Right Shin',
descriptionAr: 'الساق اليمنى',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.57, y: 0.82), position: OrganPosition(x: 0.57, y: 0.82),
), ),
OrganModel( OrganModel(
id: 'right_ankle', id: 'right_ankle',
name: 'foot', name: 'foot',
nameAr: 'القدم',
description: 'Right Ankle', description: 'Right Ankle',
descriptionAr: 'الكاحل الأيمن',
bodyView: BodyView.front, bodyView: BodyView.front,
position: OrganPosition(x: 0.57, y: 0.91), position: OrganPosition(x: 0.57, y: 0.91),
), ),
@ -252,14 +314,18 @@ class OrganData {
OrganModel( OrganModel(
id: 'back_of_head', id: 'back_of_head',
name: 'whole_head', name: 'whole_head',
nameAr: 'الرأس_كامل',
description: 'Back of Head', description: 'Back of Head',
descriptionAr: 'مؤخرة الرأس',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.04), position: OrganPosition(x: 0.50, y: 0.04),
), ),
OrganModel( OrganModel(
id: 'neck_back', id: 'neck_back',
name: 'nape_of_neck', name: 'nape_of_neck',
nameAr: 'مؤخرة_الرقبة',
description: 'Neck', description: 'Neck',
descriptionAr: 'الرقبة',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.14), position: OrganPosition(x: 0.50, y: 0.14),
), ),
@ -268,14 +334,18 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_shoulder_back', id: 'left_shoulder_back',
name: 'upper_arm', name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Left Shoulder', description: 'Left Shoulder',
descriptionAr: 'الكتف الأيسر',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.33, y: 0.19), position: OrganPosition(x: 0.33, y: 0.19),
), ),
OrganModel( OrganModel(
id: 'right_shoulder_back', id: 'right_shoulder_back',
name: 'upper_arm', name: 'upper_arm',
nameAr: 'الذراع_العلوي',
description: 'Right Shoulder', description: 'Right Shoulder',
descriptionAr: 'الكتف الأيمن',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.67, y: 0.19), position: OrganPosition(x: 0.67, y: 0.19),
), ),
@ -284,21 +354,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'upper_spine', id: 'upper_spine',
name: 'back', name: 'back',
nameAr: 'الظهر',
description: 'Upper Spine', description: 'Upper Spine',
descriptionAr: 'العمود الفقري العلوي',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.23), position: OrganPosition(x: 0.50, y: 0.23),
), ),
OrganModel( OrganModel(
id: 'left_upper_back', id: 'left_upper_back',
name: 'back', name: 'back',
nameAr: 'الظهر',
description: 'Left Upper Back', description: 'Left Upper Back',
descriptionAr: 'أعلى الظهر الأيسر',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.38, y: 0.28), position: OrganPosition(x: 0.38, y: 0.28),
), ),
OrganModel( OrganModel(
id: 'right_upper_back', id: 'right_upper_back',
name: 'back', name: 'back',
nameAr: 'الظهر',
description: 'Right Upper Back', description: 'Right Upper Back',
descriptionAr: 'أعلى الظهر الأيمن',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.62, y: 0.28), position: OrganPosition(x: 0.62, y: 0.28),
), ),
@ -307,21 +383,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'mid_spine', id: 'mid_spine',
name: 'back', name: 'back',
nameAr: 'الظهر',
description: 'Mid Spine', description: 'Mid Spine',
descriptionAr: 'العمود الفقري الأوسط',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.35), position: OrganPosition(x: 0.50, y: 0.35),
), ),
OrganModel( OrganModel(
id: 'left_mid_back', id: 'left_mid_back',
name: 'back', name: 'back',
nameAr: 'الظهر',
description: 'Left Mid Back', description: 'Left Mid Back',
descriptionAr: 'وسط الظهر الأيسر',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.38, y: 0.35), position: OrganPosition(x: 0.38, y: 0.35),
), ),
OrganModel( OrganModel(
id: 'right_mid_back', id: 'right_mid_back',
name: 'back', name: 'back',
nameAr: 'الظهر',
description: 'Right Mid Back', description: 'Right Mid Back',
descriptionAr: 'وسط الظهر الأيمن',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.62, y: 0.35), position: OrganPosition(x: 0.62, y: 0.35),
), ),
@ -330,21 +412,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'lower_spine', id: 'lower_spine',
name: 'lower_back', name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Lower Back', description: 'Lower Back',
descriptionAr: 'أسفل الظهر',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.43), position: OrganPosition(x: 0.50, y: 0.43),
), ),
OrganModel( OrganModel(
id: 'left_lower_back', id: 'left_lower_back',
name: 'lower_back', name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Left Lower Back', description: 'Left Lower Back',
descriptionAr: 'أسفل الظهر الأيسر',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.40, y: 0.43), position: OrganPosition(x: 0.40, y: 0.43),
), ),
OrganModel( OrganModel(
id: 'right_lower_back', id: 'right_lower_back',
name: 'lower_back', name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Right Lower Back', description: 'Right Lower Back',
descriptionAr: 'أسفل الظهر الأيمن',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.60, y: 0.43), position: OrganPosition(x: 0.60, y: 0.43),
), ),
@ -353,21 +441,27 @@ class OrganData {
OrganModel( OrganModel(
id: 'sacrum', id: 'sacrum',
name: 'lower_back', name: 'lower_back',
nameAr: 'أسفل_الظهر',
description: 'Sacrum', description: 'Sacrum',
descriptionAr: 'العجز',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.50, y: 0.52), position: OrganPosition(x: 0.50, y: 0.52),
), ),
OrganModel( OrganModel(
id: 'left_glute', id: 'left_glute',
name: 'buttocks', name: 'buttocks',
nameAr: 'الأرداف',
description: 'Left Glute', description: 'Left Glute',
descriptionAr: 'الأرداف اليسرى',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.45, y: 0.56), position: OrganPosition(x: 0.45, y: 0.56),
), ),
OrganModel( OrganModel(
id: 'right_glute', id: 'right_glute',
name: 'buttocks', name: 'buttocks',
nameAr: 'الأرداف',
description: 'Right Glute', description: 'Right Glute',
descriptionAr: 'الأرداف اليمنى',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.55, y: 0.56), position: OrganPosition(x: 0.55, y: 0.56),
), ),
@ -376,28 +470,36 @@ class OrganData {
OrganModel( OrganModel(
id: 'left_hamstring', id: 'left_hamstring',
name: 'thigh', name: 'thigh',
nameAr: 'الفخذ',
description: 'Left Hamstring', description: 'Left Hamstring',
descriptionAr: 'عضلة الفخذ الخلفية اليسرى',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.43, y: 0.65), position: OrganPosition(x: 0.43, y: 0.65),
), ),
OrganModel( OrganModel(
id: 'right_hamstring', id: 'right_hamstring',
name: 'thigh', name: 'thigh',
nameAr: 'الفخذ',
description: 'Right Hamstring', description: 'Right Hamstring',
descriptionAr: 'عضلة الفخذ الخلفية اليمنى',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.57, y: 0.65), position: OrganPosition(x: 0.57, y: 0.65),
), ),
OrganModel( OrganModel(
id: 'left_calf', id: 'left_calf',
name: 'lower_leg', name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Left Calf', description: 'Left Calf',
descriptionAr: 'ربلة الساق اليسرى',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.43, y: 0.79), position: OrganPosition(x: 0.43, y: 0.79),
), ),
OrganModel( OrganModel(
id: 'right_calf', id: 'right_calf',
name: 'lower_leg', name: 'lower_leg',
nameAr: 'الساق_السفلي',
description: 'Right Calf', description: 'Right Calf',
descriptionAr: 'ربلة الساق اليمنى',
bodyView: BodyView.back, bodyView: BodyView.back,
position: OrganPosition(x: 0.57, y: 0.79), position: OrganPosition(x: 0.57, y: 0.79),
), ),

@ -1,97 +1,97 @@
import 'package:flutter/material.dart'; // import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; // import 'package:hmg_patient_app_new/core/enums.dart';
//
class ConditionsModel { // class ConditionsModel {
final IconData icon; // final IconData icon;
final String title; // final String title;
final int percentage; // final int percentage;
final String tagText; // final String tagText;
final String clinic; // final String clinic;
final List<String> symptoms; // final List<String> symptoms;
final String description; // final String description;
final String? monitorNote; // final String? monitorNote;
final String? appointmentLabel; // final String? appointmentLabel;
final PossibleConditionsSeverityEnum possibleConditionsSeverityEnum; // final PossibleConditionsSeverityEnum possibleConditionsSeverityEnum;
//
ConditionsModel({ // ConditionsModel({
required this.icon, // required this.icon,
required this.title, // required this.title,
required this.percentage, // required this.percentage,
required this.tagText, // required this.tagText,
required this.clinic, // required this.clinic,
required this.symptoms, // required this.symptoms,
required this.description, // required this.description,
required this.possibleConditionsSeverityEnum, // required this.possibleConditionsSeverityEnum,
this.monitorNote, // this.monitorNote,
this.appointmentLabel, // this.appointmentLabel,
}); // });
} // }
//
List<ConditionsModel> dummyConditions = [ // List<ConditionsModel> dummyConditions = [
ConditionsModel( // ConditionsModel(
icon: Icons.psychology_alt, // icon: Icons.psychology_alt,
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice, // possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice,
title: "Migraine", // title: "Migraine",
percentage: 87, // percentage: 87,
tagText: "Seek Medical Advice", // tagText: "Seek Medical Advice",
clinic: "Internal Medicine Clinic", // clinic: "Internal Medicine Clinic",
symptoms: ["Headache", "Nausea", "Sensitivity to light"], // symptoms: ["Headache", "Nausea", "Sensitivity to light"],
description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.", // description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.",
appointmentLabel: "Book Appointment", // appointmentLabel: "Book Appointment",
), // ),
ConditionsModel( // ConditionsModel(
icon: Icons.deblur, // icon: Icons.deblur,
title: "Tension Headache", // title: "Tension Headache",
percentage: 37, // percentage: 37,
tagText: "Monitor", // tagText: "Monitor",
monitorNote: "No need to visit doctor", // monitorNote: "No need to visit doctor",
clinic: "GP Clinic", // clinic: "GP Clinic",
symptoms: ["Mild head pressure", "Scalp tenderness"], // symptoms: ["Mild head pressure", "Scalp tenderness"],
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.", // description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly, // possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly,
), // ),
ConditionsModel( // ConditionsModel(
icon: Icons.medication_liquid, // icon: Icons.medication_liquid,
title: "Meningitis", // title: "Meningitis",
percentage: 28, // percentage: 28,
tagText: "Emergency", // tagText: "Emergency",
clinic: "Neurology Clinic", // clinic: "Neurology Clinic",
symptoms: ["Mild head pressure", "Scalp tenderness"], // symptoms: ["Mild head pressure", "Scalp tenderness"],
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.", // description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
appointmentLabel: "Book Appointment", // appointmentLabel: "Book Appointment",
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency, // possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency,
), // ),
ConditionsModel( // ConditionsModel(
icon: Icons.psychology_alt, // icon: Icons.psychology_alt,
title: "Migraine", // title: "Migraine",
percentage: 87, // percentage: 87,
tagText: "Seek Medical Advice", // tagText: "Seek Medical Advice",
clinic: "Internal Medicine Clinic", // clinic: "Internal Medicine Clinic",
symptoms: ["Headache", "Nausea", "Sensitivity to light"], // symptoms: ["Headache", "Nausea", "Sensitivity to light"],
description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.", // description: "A migraine is a type of headache that can cause severe throbbing pain, usually on one side of the head.",
appointmentLabel: "Book Appointment", // appointmentLabel: "Book Appointment",
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice, // possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice,
), // ),
ConditionsModel( // ConditionsModel(
icon: Icons.deblur, // icon: Icons.deblur,
title: "Tension Headache", // title: "Tension Headache",
percentage: 37, // percentage: 37,
tagText: "Monitor", // tagText: "Monitor",
monitorNote: "No need to visit doctor", // monitorNote: "No need to visit doctor",
clinic: "GP Clinic", // clinic: "GP Clinic",
symptoms: ["Mild head pressure", "Scalp tenderness"], // symptoms: ["Mild head pressure", "Scalp tenderness"],
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.", // description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly, // possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.monitorOnly,
), // ),
ConditionsModel( // ConditionsModel(
icon: Icons.medication_liquid, // icon: Icons.medication_liquid,
title: "Meningitis", // title: "Meningitis",
percentage: 28, // percentage: 28,
tagText: "Emergency", // tagText: "Emergency",
clinic: "Neurology Clinic", // clinic: "Neurology Clinic",
symptoms: ["Mild head pressure", "Scalp tenderness"], // symptoms: ["Mild head pressure", "Scalp tenderness"],
description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.", // description: "A tension-type headache is generally a mild to moderate pain that feels like a tight band around your head.",
appointmentLabel: "Book Appointment", // appointmentLabel: "Book Appointment",
possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency, // possibleConditionsSeverityEnum: PossibleConditionsSeverityEnum.emergency,
), // ),
]; // ];

@ -3,29 +3,47 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class OrganModel { class OrganModel {
final String id; final String id;
final String name; final String name;
final String nameAr;
final String description; final String description;
final String descriptionAr;
final BodyView bodyView; final BodyView bodyView;
final OrganPosition position; final OrganPosition position;
const OrganModel({ const OrganModel({
required this.id, required this.id,
required this.name, required this.name,
required this.nameAr,
required this.description, required this.description,
required this.descriptionAr,
required this.bodyView, required this.bodyView,
required this.position, required this.position,
}); });
/// Get localized name based on isArabic flag
String getLocalizedName(bool isArabic) {
return isArabic ? nameAr : name;
}
/// Get localized description based on isArabic flag
String getLocalizedDescription(bool isArabic) {
return isArabic ? descriptionAr : description;
}
OrganModel copyWith({ OrganModel copyWith({
String? id, String? id,
String? name, String? name,
String? nameAr,
String? description, String? description,
String? descriptionAr,
BodyView? bodyView, BodyView? bodyView,
OrganPosition? position, OrganPosition? position,
}) { }) {
return OrganModel( return OrganModel(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
nameAr: nameAr ?? this.nameAr,
description: description ?? this.description, description: description ?? this.description,
descriptionAr: descriptionAr ?? this.descriptionAr,
bodyView: bodyView ?? this.bodyView, bodyView: bodyView ?? this.bodyView,
position: position ?? this.position, position: position ?? this.position,
); );

@ -22,6 +22,8 @@ class RiskAndSuggestionsItemModel {
final String? type; final String? type;
final String? name; final String? name;
final String? commonName; final String? commonName;
final String? nameAr;
final String? commonNameAr;
final String? language; final String? language;
RiskAndSuggestionsItemModel({ RiskAndSuggestionsItemModel({
@ -29,6 +31,8 @@ class RiskAndSuggestionsItemModel {
this.type, this.type,
this.name, this.name,
this.commonName, this.commonName,
this.nameAr,
this.commonNameAr,
this.language, this.language,
}); });
@ -38,6 +42,8 @@ class RiskAndSuggestionsItemModel {
type: json['type'], type: json['type'],
name: json['name'], name: json['name'],
commonName: json['common_name'], commonName: json['common_name'],
nameAr: json['nameAr'],
commonNameAr: json['common_nameAr'],
language: json['language'], language: json['language'],
); );
} }
@ -48,12 +54,17 @@ class RiskAndSuggestionsItemModel {
'type': type, 'type': type,
'name': name, 'name': name,
'common_name': commonName, 'common_name': commonName,
'nameAr': nameAr,
'common_nameAr': commonNameAr,
'language': language, 'language': language,
}; };
} }
// Helper method to get display name // Helper method to get display name based on locale
String getDisplayName() { String getDisplayName({bool isArabic = false}) {
if (isArabic) {
return commonNameAr ?? nameAr ?? commonName ?? name ?? '';
}
return commonName ?? name ?? ''; return commonName ?? name ?? '';
} }
} }

@ -1,3 +1,5 @@
import 'package:hmg_patient_app_new/core/enums.dart';
class TriageDataDetails { class TriageDataDetails {
final TriageQuestion? question; final TriageQuestion? question;
final List<TriageCondition>? conditions; final List<TriageCondition>? conditions;
@ -170,13 +172,17 @@ class TriageCondition {
final String? id; final String? id;
final String? name; final String? name;
final String? commonName; final String? commonName;
final String? nameAr;
final String? commonNameAr;
final double? probability; final double? probability;
final dynamic conditionDetails; final ConditionDetails? conditionDetails;
TriageCondition({ TriageCondition({
this.id, this.id,
this.name, this.name,
this.commonName, this.commonName,
this.nameAr,
this.commonNameAr,
this.probability, this.probability,
this.conditionDetails, this.conditionDetails,
}); });
@ -186,8 +192,10 @@ class TriageCondition {
id: json['id'], id: json['id'],
name: json['name'], name: json['name'],
commonName: json['common_name'], commonName: json['common_name'],
nameAr: json['nameAr'],
commonNameAr: json['common_nameAr'],
probability: json['probability']?.toDouble(), probability: json['probability']?.toDouble(),
conditionDetails: json['condition_details'], conditionDetails: json['condition_details'] != null ? ConditionDetails.fromJson(json['condition_details']) : null,
); );
} }
@ -196,14 +204,96 @@ class TriageCondition {
'id': id, 'id': id,
'name': name, 'name': name,
'common_name': commonName, 'common_name': commonName,
'nameAr': nameAr,
'common_nameAr': commonNameAr,
'probability': probability, 'probability': probability,
'condition_details': conditionDetails, 'condition_details': conditionDetails?.toJson(),
}; };
} }
/// Get display name based on locale
String getDisplayName({bool isArabic = false}) {
if (isArabic) {
return commonNameAr ?? nameAr ?? commonName ?? name ?? '';
}
return commonName ?? name ?? '';
}
/// Get probability as percentage /// Get probability as percentage
String getProbabilityPercentage() { String getProbabilityPercentage() {
if (probability == null) return '0%'; if (probability == null) return '0%';
return '${(probability! * 100).toStringAsFixed(1)}%'; return '${(probability! * 100).toStringAsFixed(1)}%';
} }
} }
class ConditionDetails {
final String? icd10Code;
final ConditionCategory? category;
final SeverityEnum? severity;
final TriageLevelEnum? triageLevel;
final String? hint;
final bool? hasPatientEducation;
final String? prevalence;
final String? acuteness;
ConditionDetails({
this.icd10Code,
this.category,
this.severity,
this.triageLevel,
this.hint,
this.hasPatientEducation,
this.prevalence,
this.acuteness,
});
factory ConditionDetails.fromJson(Map<String, dynamic> json) {
return ConditionDetails(
icd10Code: json['icd10_code'],
category: json['category'] != null ? ConditionCategory.fromJson(json['category']) : null,
severity: json['severity'] != null ? SeverityEnumExtension.fromInt(json['severity']) : null,
triageLevel: json['triage_level'] != null ? TriageLevelEnumExtension.fromInt(json['triage_level']) : null,
hint: json['hint'],
hasPatientEducation: json['has_patient_education'],
prevalence: json['prevalence'],
acuteness: json['acuteness'],
);
}
Map<String, dynamic> toJson() {
return {
'icd10_code': icd10Code,
'category': category?.toJson(),
'severity': severity?.toInt,
'triage_level': triageLevel?.toInt,
'hint': hint,
'has_patient_education': hasPatientEducation,
'prevalence': prevalence,
'acuteness': acuteness,
};
}
}
class ConditionCategory {
final String? id;
final String? name;
ConditionCategory({
this.id,
this.name,
});
factory ConditionCategory.fromJson(Map<String, dynamic> json) {
return ConditionCategory(
id: json['id'],
name: json['name'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
}

@ -12,50 +12,42 @@ import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class SymptomsCheckerRepo { abstract class SymptomsCheckerRepo {
Future<Either<Failure, GenericApiModel<SymptomsUserDetailsResponseModel>>> Future<Either<Failure, GenericApiModel<SymptomsUserDetailsResponseModel>>> getUserDetails({
getUserDetails({
required String userName, required String userName,
required String password, required String password,
}); });
Future<Either<Failure, GenericApiModel<BodySymptomResponseModel>>> Future<Either<Failure, GenericApiModel<BodySymptomResponseModel>>> getBodySymptomsByName({
getBodySymptomsByName({
required List<String> organNames, required List<String> organNames,
required String userSessionToken, required String userSessionToken,
required int gender, required int gender,
}); });
Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> getRiskFactors({
getRiskFactors({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
required String language, required String language,
required String userSessionToken, required String userSessionToken,
required int gender,
required String sessionId, required String sessionId,
}); });
Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> getSuggestions({
getSuggestions({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
required String language, required String language,
required String userSessionToken, required String userSessionToken,
required String sessionId, required String sessionId,
required int gender,
}); });
Future<Either<Failure, GenericApiModel<TriageDataDetails>>> Future<Either<Failure, GenericApiModel<TriageDataDetails>>> getDiagnosisForTriage({
getDiagnosisForTriage({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
List<Map<String, String>>? triageEvidence, List<Map<String, String>>? triageEvidence,
required String language, required String language,
required String userSessionToken, required String userSessionToken,
required int gender,
required String sessionId, required String sessionId,
}); });
} }
@ -64,16 +56,14 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
final ApiClient apiClient; final ApiClient apiClient;
final LoggerService loggerService; final LoggerService loggerService;
SymptomsCheckerRepoImp( SymptomsCheckerRepoImp({required this.apiClient, required this.loggerService});
{required this.apiClient, required this.loggerService});
@override @override
Future<Either<Failure, GenericApiModel<SymptomsUserDetailsResponseModel>>> Future<Either<Failure, GenericApiModel<SymptomsUserDetailsResponseModel>>> getUserDetails({
getUserDetails({
required String userName, required String userName,
required String password, required String password,
}) async { }) async {
Map<String, String> body = {"userName": userName, "password": password}; Map<String, dynamic> body = {"userName": userName, "password": password};
try { try {
GenericApiModel<SymptomsUserDetailsResponseModel>? apiResponse; GenericApiModel<SymptomsUserDetailsResponseModel>? apiResponse;
@ -92,11 +82,9 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
// Parse response if it's a string // Parse response if it's a string
final Map<String, dynamic> responseData = final Map<String, dynamic> responseData = response is String ? jsonDecode(response) : response;
response is String ? jsonDecode(response) : response;
SymptomsUserDetailsResponseModel symptomsUserDetailsResponseModel = SymptomsUserDetailsResponseModel symptomsUserDetailsResponseModel = SymptomsUserDetailsResponseModel.fromJson(responseData);
SymptomsUserDetailsResponseModel.fromJson(responseData);
apiResponse = GenericApiModel<SymptomsUserDetailsResponseModel>( apiResponse = GenericApiModel<SymptomsUserDetailsResponseModel>(
messageStatus: messageStatus ?? 1, messageStatus: messageStatus ?? 1,
@ -123,8 +111,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<BodySymptomResponseModel>>> Future<Either<Failure, GenericApiModel<BodySymptomResponseModel>>> getBodySymptomsByName({
getBodySymptomsByName({
required List<String> organNames, required List<String> organNames,
required String userSessionToken, required String userSessionToken,
required int gender, required int gender,
@ -154,8 +141,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
}, },
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
BodySymptomResponseModel bodySymptomResponse = BodySymptomResponseModel bodySymptomResponse = BodySymptomResponseModel.fromJson(response);
BodySymptomResponseModel.fromJson(response);
apiResponse = GenericApiModel<BodySymptomResponseModel>( apiResponse = GenericApiModel<BodySymptomResponseModel>(
messageStatus: messageStatus ?? 1, messageStatus: messageStatus ?? 1,
@ -164,8 +150,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
data: bodySymptomResponse, data: bodySymptomResponse,
); );
} catch (e, stackTrace) { } catch (e, stackTrace) {
loggerService loggerService.logError("Error parsing GetBodySymptomsByName response: $e");
.logError("Error parsing GetBodySymptomsByName response: $e");
loggerService.logError("StackTrace: $stackTrace"); loggerService.logError("StackTrace: $stackTrace");
failure = DataParsingFailure(e.toString()); failure = DataParsingFailure(e.toString());
} }
@ -183,21 +168,19 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> getRiskFactors({
getRiskFactors({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
required String language, required String language,
required String userSessionToken, required String userSessionToken,
required int gender,
required String sessionId, required String sessionId,
}) async { }) async {
final Map<String, dynamic> body = { final Map<String, dynamic> body = {
"age": { "age": {
"value": age, "value": age,
}, },
"sex": sex, "gender": gender,
"evidence": evidenceIds.map((id) => {"id": id}).toList(), "evidence": evidenceIds.map((id) => {"id": id}).toList(),
"language": language, "language": language,
"generalId": sessionId, "generalId": sessionId,
@ -225,11 +208,9 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
// Parse response if it's a string // Parse response if it's a string
final Map<String, dynamic> responseData = final Map<String, dynamic> responseData = response is String ? jsonDecode(response) : response;
response is String ? jsonDecode(response) : response;
RiskAndSuggestionsResponseModel riskFactorsResponse = RiskAndSuggestionsResponseModel riskFactorsResponse = RiskAndSuggestionsResponseModel.fromJson(responseData);
RiskAndSuggestionsResponseModel.fromJson(responseData);
apiResponse = GenericApiModel<RiskAndSuggestionsResponseModel>( apiResponse = GenericApiModel<RiskAndSuggestionsResponseModel>(
messageStatus: messageStatus ?? 1, messageStatus: messageStatus ?? 1,
@ -255,16 +236,14 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
} }
} }
Future<Either<Failure, GenericApiModel<TriageDataDetails>>> @override
getDiagnosisForTriage({ Future<Either<Failure, GenericApiModel<TriageDataDetails>>> getDiagnosisForTriage({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
List<Map<String, String>>? List<Map<String, String>>? triageEvidence, // Additional triage-specific evidence
triageEvidence, // Additional triage-specific evidence
required String language, required String language,
required String userSessionToken, required String userSessionToken,
required int gender,
required String sessionId, required String sessionId,
}) async { }) async {
// Build evidence list: combine initial symptoms with triage evidence // Build evidence list: combine initial symptoms with triage evidence
@ -284,7 +263,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
"age": { "age": {
"value": age, "value": age,
}, },
"sex": sex, "gender": gender,
"evidence": evidenceList, "evidence": evidenceList,
"language": language, "language": language,
"suggest_method": "diagnosis", "suggest_method": "diagnosis",
@ -313,13 +292,11 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
// Parse response if it's a string // Parse response if it's a string
final Map<String, dynamic> responseData = final Map<String, dynamic> responseData = response is String ? jsonDecode(response) : response;
response is String ? jsonDecode(response) : response;
final updatedResponseData = responseData['dataDetails']; final updatedResponseData = responseData['dataDetails'];
TriageDataDetails riskFactorsResponse = TriageDataDetails riskFactorsResponse = TriageDataDetails.fromJson(updatedResponseData);
TriageDataDetails.fromJson(updatedResponseData);
apiResponse = GenericApiModel<TriageDataDetails>( apiResponse = GenericApiModel<TriageDataDetails>(
messageStatus: messageStatus ?? 1, messageStatus: messageStatus ?? 1,
@ -328,8 +305,7 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
data: riskFactorsResponse, data: riskFactorsResponse,
); );
} catch (e, stackTrace) { } catch (e, stackTrace) {
loggerService loggerService.logError("Error parsing getDiagnosisForTriage response: $e");
.logError("Error parsing getDiagnosisForTriage response: $e");
loggerService.logError("StackTrace: $stackTrace"); loggerService.logError("StackTrace: $stackTrace");
failure = DataParsingFailure(e.toString()); failure = DataParsingFailure(e.toString());
} }
@ -347,21 +323,19 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
} }
@override @override
Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> Future<Either<Failure, GenericApiModel<RiskAndSuggestionsResponseModel>>> getSuggestions({
getSuggestions({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
required String language, required String language,
required String userSessionToken, required String userSessionToken,
required String sessionId, required String sessionId,
required int gender,
}) async { }) async {
final Map<String, dynamic> body = { final Map<String, dynamic> body = {
"age": { "age": {
"value": age, "value": age,
}, },
"sex": sex, "gender": gender,
"evidence": evidenceIds.map((id) => {"id": id}).toList(), "evidence": evidenceIds.map((id) => {"id": id}).toList(),
"language": language, "language": language,
"generalId": sessionId, "generalId": sessionId,
@ -389,11 +363,9 @@ class SymptomsCheckerRepoImp implements SymptomsCheckerRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) { onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try { try {
// Parse response if it's a string // Parse response if it's a string
final Map<String, dynamic> responseData = final Map<String, dynamic> responseData = response is String ? jsonDecode(response) : response;
response is String ? jsonDecode(response) : response;
RiskAndSuggestionsResponseModel riskFactorsResponse = RiskAndSuggestionsResponseModel riskFactorsResponse = RiskAndSuggestionsResponseModel.fromJson(responseData);
RiskAndSuggestionsResponseModel.fromJson(responseData);
apiResponse = GenericApiModel<RiskAndSuggestionsResponseModel>( apiResponse = GenericApiModel<RiskAndSuggestionsResponseModel>(
messageStatus: messageStatus ?? 1, messageStatus: messageStatus ?? 1,

@ -1,6 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/data/organ_mapping_data.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/data/organ_mapping_data.dart';
@ -23,6 +23,23 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
required this.appState, required this.appState,
}); });
// Gender constants for both English and Arabic
static const String _maleEn = "male";
static const String _femaleEn = "female";
static const String _maleAr = "ذكر";
static const String _femaleAr = "أنثى";
/// Convert gender string to integer (1 for male, 2 for female)
/// Handles both English and Arabic values
int _getGenderAsInt(String? gender) {
if (gender == null) return 1; // Default to male
final lowerGender = gender.toLowerCase();
if (lowerGender == _maleEn || gender == _maleAr) {
return 1;
}
return 2; // Female or any other value
}
// State variables // State variables
bool isBodyHidden = false; bool isBodyHidden = false;
BodyView _currentView = BodyView.front; BodyView _currentView = BodyView.front;
@ -47,12 +64,9 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
TriageDataDetails? triageDataDetails; TriageDataDetails? triageDataDetails;
// Triage state // Triage state
int? int? _selectedTriageChoiceIndex; // Deprecated - keeping for backward compatibility
_selectedTriageChoiceIndex; // Deprecated - keeping for backward compatibility final Map<String, int> _selectedTriageChoicesByItemId = {}; // Map of itemId -> choiceIndex for multi-item questions
final Map<String, int> _selectedTriageChoicesByItemId = final List<Map<String, String>> _triageEvidenceList = []; // Store triage evidence with proper format
{}; // Map of itemId -> choiceIndex for multi-item questions
final List<Map<String, String>> _triageEvidenceList =
[]; // Store triage evidence with proper format
int _triageQuestionCount = 0; // Track number of triage questions answered int _triageQuestionCount = 0; // Track number of triage questions answered
// Selected risk factors tracking // Selected risk factors tracking
@ -66,8 +80,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
// User Info Flow State // User Info Flow State
int _userInfoCurrentPage = 0; int _userInfoCurrentPage = 0;
bool _isSinglePageEditMode = bool _isSinglePageEditMode = false; // Track if editing single page or full flow
false; // Track if editing single page or full flow
String? _selectedGender; String? _selectedGender;
DateTime? _dateOfBirth; DateTime? _dateOfBirth;
int? _selectedAge; int? _selectedAge;
@ -107,17 +120,14 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
String? get tooltipOrganId => _tooltipOrganId; String? get tooltipOrganId => _tooltipOrganId;
String get currentSessionAuthToken => String get currentSessionAuthToken => symptomsUserDetailsResponseModel?.tokenDetails?.authToken ?? "";
symptomsUserDetailsResponseModel?.tokenDetails?.authToken ?? "";
String get currentSessionId => String get currentSessionId => symptomsUserDetailsResponseModel?.sessionId ?? "";
symptomsUserDetailsResponseModel?.sessionId ?? "";
// Triage-related getters // Triage-related getters
bool get shouldStopTriage => triageDataDetails?.shouldStop ?? false; bool get shouldStopTriage => triageDataDetails?.shouldStop ?? false;
bool get hasEmergencyEvidence => bool get hasEmergencyEvidence => triageDataDetails?.hasEmergencyEvidence ?? false;
triageDataDetails?.hasEmergencyEvidence ?? false;
String? get currentInterviewToken => triageDataDetails?.interviewToken; String? get currentInterviewToken => triageDataDetails?.interviewToken;
@ -137,15 +147,13 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Check if all items in current question have been answered /// Check if all items in current question have been answered
bool get areAllTriageItemsAnswered { bool get areAllTriageItemsAnswered {
if (currentTriageQuestion?.items == null || if (currentTriageQuestion?.items == null || currentTriageQuestion!.items!.isEmpty) {
currentTriageQuestion!.items!.isEmpty) {
return false; return false;
} }
// Check if we have an answer for each item // Check if we have an answer for each item
for (var item in currentTriageQuestion!.items!) { for (var item in currentTriageQuestion!.items!) {
if (item.id != null && if (item.id != null && !_selectedTriageChoicesByItemId.containsKey(item.id)) {
!_selectedTriageChoicesByItemId.containsKey(item.id)) {
return false; return false;
} }
} }
@ -153,8 +161,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
/// Get organs for current view /// Get organs for current view
List<OrganModel> get currentOrgans => List<OrganModel> get currentOrgans => OrganData.getOrgansForView(_currentView);
OrganData.getOrgansForView(_currentView);
/// Get all selected organs from both views /// Get all selected organs from both views
List<OrganModel> get selectedOrgans { List<OrganModel> get selectedOrgans {
@ -162,9 +169,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
...OrganData.frontViewOrgans, ...OrganData.frontViewOrgans,
...OrganData.backViewOrgans, ...OrganData.backViewOrgans,
]; ];
return allOrgans return allOrgans.where((organ) => _selectedOrganIds.contains(organ.id)).toList();
.where((organ) => _selectedOrganIds.contains(organ.id))
.toList();
} }
/// Check if any organs are selected /// Check if any organs are selected
@ -181,13 +186,11 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
int get totalSelectedSymptomsCount { int get totalSelectedSymptomsCount {
return _selectedSymptomsByOrgan.values return _selectedSymptomsByOrgan.values.fold(0, (sum, symptomIds) => sum + symptomIds.length);
.fold(0, (sum, symptomIds) => sum + symptomIds.length);
} }
bool get hasSelectedSymptoms { bool get hasSelectedSymptoms {
return _selectedSymptomsByOrgan.values return _selectedSymptomsByOrgan.values.any((symptomIds) => symptomIds.isNotEmpty);
.any((symptomIds) => symptomIds.isNotEmpty);
} }
/// Get risk factors list /// Get risk factors list
@ -213,8 +216,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
void toggleView() { void toggleView() {
_currentView = _currentView = _currentView == BodyView.front ? BodyView.back : BodyView.front;
_currentView == BodyView.front ? BodyView.back : BodyView.front;
notifyListeners(); notifyListeners();
} }
@ -317,8 +319,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
return; return;
} }
List<String> organNames = List<String> organNames = selectedOrgans.map((organ) => organ.name).toList();
selectedOrgans.map((organ) => organ.name).toList();
await getBodySymptomsByName( await getBodySymptomsByName(
organNames: organNames, organNames: organNames,
@ -368,8 +369,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
} }
if (matchingOrganId != null && if (matchingOrganId != null && _selectedSymptomsByOrgan.containsKey(matchingOrganId)) {
_selectedSymptomsByOrgan.containsKey(matchingOrganId)) {
final selectedIds = _selectedSymptomsByOrgan[matchingOrganId]!; final selectedIds = _selectedSymptomsByOrgan[matchingOrganId]!;
if (organResult.bodySymptoms != null) { if (organResult.bodySymptoms != null) {
@ -420,10 +420,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Get all selected risk factors /// Get all selected risk factors
List<RiskAndSuggestionsItemModel> getAllSelectedRiskFactors() { List<RiskAndSuggestionsItemModel> getAllSelectedRiskFactors() {
return riskFactorsList return riskFactorsList.where((factor) => factor.id != null && _selectedRiskFactorIds.contains(factor.id)).toList();
.where((factor) =>
factor.id != null && _selectedRiskFactorIds.contains(factor.id))
.toList();
} }
/// Clear all risk factor selections /// Clear all risk factor selections
@ -456,12 +453,11 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
// Extract symptom IDs // Extract symptom IDs
List<String> evidenceIds = List<String> evidenceIds = selectedSymptoms.where((s) => s.id != null).map((s) => s.id!).toList();
selectedSymptoms.where((s) => s.id != null).map((s) => s.id!).toList();
await getRiskFactors( await getRiskFactors(
age: _selectedAge!, age: _selectedAge!,
sex: _selectedGender!.toLowerCase(), gender: _getGenderAsInt(_selectedGender),
evidenceIds: evidenceIds, evidenceIds: evidenceIds,
sessionId: currentSessionId, sessionId: currentSessionId,
language: appState.isArabic() ? 'ar' : 'en', language: appState.isArabic() ? 'ar' : 'en',
@ -481,7 +477,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Call Risk Factors API /// Call Risk Factors API
Future<void> getRiskFactors({ Future<void> getRiskFactors({
required int age, required int age,
required String sex, required int gender,
required String sessionId, required String sessionId,
required List<String> evidenceIds, required List<String> evidenceIds,
required String language, required String language,
@ -493,12 +489,11 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
final result = await symptomsCheckerRepo.getRiskFactors( final result = await symptomsCheckerRepo.getRiskFactors(
age: age, age: age,
sex: sex, gender: gender,
evidenceIds: evidenceIds, evidenceIds: evidenceIds,
language: language, language: language,
sessionId: sessionId, sessionId: sessionId,
userSessionToken: currentSessionAuthToken, userSessionToken: currentSessionAuthToken,
gender: (selectedGender ?? "Male").toLowerCase() == "male" ? 1 : 2,
); );
result.fold( result.fold(
@ -515,13 +510,13 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 1 && apiResponse.data != null) { if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
riskFactorsResponse = apiResponse.data; riskFactorsResponse = apiResponse.data;
if (riskFactorsResponse != null && if (riskFactorsResponse != null && riskFactorsResponse!.dataDetails != null) {
riskFactorsResponse!.dataDetails != null) { RiskAndSuggestionsItemModel riskFactorItem = RiskAndSuggestionsItemModel(
RiskAndSuggestionsItemModel riskFactorItem =
RiskAndSuggestionsItemModel(
id: "not_applicable", id: "not_applicable",
commonName: "Not Applicable", commonName: "Not Applicable",
name: "Not Applicable", name: "Not Applicable",
commonNameAr: "لا ينطبق",
nameAr: "لا ينطبق",
language: appState.isArabic() ? 'ar' : 'en', language: appState.isArabic() ? 'ar' : 'en',
type: null, type: null,
); );
@ -572,10 +567,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Get all selected risk factors /// Get all selected risk factors
List<RiskAndSuggestionsItemModel> getAllSelectedSuggestions() { List<RiskAndSuggestionsItemModel> getAllSelectedSuggestions() {
return suggestionsList return suggestionsList.where((factor) => factor.id != null && _selectedSuggestionsIds.contains(factor.id)).toList();
.where((factor) =>
factor.id != null && _selectedSuggestionsIds.contains(factor.id))
.toList();
} }
/// Clear all risk factor selections /// Clear all risk factor selections
@ -590,20 +582,15 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
// Add selected symptoms // Add selected symptoms
final selectedSymptoms = getAllSelectedSymptoms(); final selectedSymptoms = getAllSelectedSymptoms();
evidenceIds evidenceIds.addAll(selectedSymptoms.where((s) => s.id != null).map((s) => s.id!));
.addAll(selectedSymptoms.where((s) => s.id != null).map((s) => s.id!));
// Add selected risk factors (excluding "not_applicable") // Add selected risk factors (excluding "not_applicable")
final selectedRiskFactors = getAllSelectedRiskFactors(); final selectedRiskFactors = getAllSelectedRiskFactors();
evidenceIds.addAll(selectedRiskFactors evidenceIds.addAll(selectedRiskFactors.where((rf) => rf.id != null && rf.id != "not_applicable").map((rf) => rf.id!));
.where((rf) => rf.id != null && rf.id != "not_applicable")
.map((rf) => rf.id!));
// Add selected suggestions (excluding "not_applicable") // Add selected suggestions (excluding "not_applicable")
final selectedSuggestions = getAllSelectedSuggestions(); final selectedSuggestions = getAllSelectedSuggestions();
evidenceIds.addAll(selectedSuggestions evidenceIds.addAll(selectedSuggestions.where((s) => s.id != null && s.id != "not_applicable").map((s) => s.id!));
.where((s) => s.id != null && s.id != "not_applicable")
.map((s) => s.id!));
return evidenceIds; return evidenceIds;
} }
@ -632,23 +619,19 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
} }
// Extract symptom IDs // Extract symptom IDs
List<String> evidenceIds = List<String> evidenceIds = selectedSymptoms.where((s) => s.id != null).map((s) => s.id!).toList();
selectedSymptoms.where((s) => s.id != null).map((s) => s.id!).toList();
// Get all selected symptoms // Get all selected symptoms
final selectedRisks = getAllSelectedRiskFactors(); final selectedRisks = getAllSelectedRiskFactors();
if (selectedRisks.isNotEmpty) { if (selectedRisks.isNotEmpty) {
List<String> evidenceRisksIds = selectedRisks List<String> evidenceRisksIds = selectedRisks.where((s) => s.id != null && s.id != "not_applicable").map((s) => s.id!).toList();
.where((s) => s.id != null && s.id != "not_applicable")
.map((s) => s.id!)
.toList();
evidenceIds.addAll(evidenceRisksIds); evidenceIds.addAll(evidenceRisksIds);
} }
await getSuggestions( await getSuggestions(
age: _selectedAge!, age: _selectedAge!,
sex: _selectedGender!.toLowerCase(), gender: _getGenderAsInt(_selectedGender),
evidenceIds: evidenceIds, evidenceIds: evidenceIds,
language: appState.isArabic() ? 'ar' : 'en', language: appState.isArabic() ? 'ar' : 'en',
onSuccess: (response) { onSuccess: (response) {
@ -667,7 +650,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Call Suggestions API /// Call Suggestions API
Future<void> getSuggestions({ Future<void> getSuggestions({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
required String language, required String language,
Function(RiskAndSuggestionsResponseModel)? onSuccess, Function(RiskAndSuggestionsResponseModel)? onSuccess,
@ -678,12 +661,11 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
final result = await symptomsCheckerRepo.getSuggestions( final result = await symptomsCheckerRepo.getSuggestions(
age: age, age: age,
sex: sex, gender: gender,
evidenceIds: evidenceIds, evidenceIds: evidenceIds,
language: language, language: language,
sessionId: currentSessionId, sessionId: currentSessionId,
userSessionToken: currentSessionAuthToken, userSessionToken: currentSessionAuthToken,
gender: (selectedGender ?? "Male").toLowerCase() == "male" ? 1 : 2,
); );
result.fold( result.fold(
@ -700,13 +682,13 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 1 && apiResponse.data != null) { if (apiResponse.messageStatus == 1 && apiResponse.data != null) {
suggestionsResponse = apiResponse.data; suggestionsResponse = apiResponse.data;
if (suggestionsResponse != null && if (suggestionsResponse != null && suggestionsResponse!.dataDetails != null) {
suggestionsResponse!.dataDetails != null) { RiskAndSuggestionsItemModel riskFactorItem = RiskAndSuggestionsItemModel(
RiskAndSuggestionsItemModel riskFactorItem =
RiskAndSuggestionsItemModel(
id: "not_applicable", id: "not_applicable",
commonName: "Not Applicable", commonName: "Not Applicable",
name: "Not Applicable", name: "Not Applicable",
commonNameAr: "لا ينطبق",
nameAr: "لا ينطبق",
language: appState.isArabic() ? 'ar' : 'en', language: appState.isArabic() ? 'ar' : 'en',
type: null, type: null,
); );
@ -730,7 +712,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
/// Call Diagnosis API for Triage - This is called iteratively until shouldStop is true /// Call Diagnosis API for Triage - This is called iteratively until shouldStop is true
Future<void> getDiagnosisForTriage({ Future<void> getDiagnosisForTriage({
required int age, required int age,
required String sex, required int gender,
required List<String> evidenceIds, required List<String> evidenceIds,
List<Map<String, String>>? triageEvidence, List<Map<String, String>>? triageEvidence,
required String language, required String language,
@ -742,13 +724,12 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
final result = await symptomsCheckerRepo.getDiagnosisForTriage( final result = await symptomsCheckerRepo.getDiagnosisForTriage(
age: age, age: age,
sex: sex, gender: gender,
evidenceIds: evidenceIds, evidenceIds: evidenceIds,
triageEvidence: triageEvidence, triageEvidence: triageEvidence,
language: language, language: language,
sessionId: currentSessionId, sessionId: currentSessionId,
userSessionToken: currentSessionAuthToken, userSessionToken: currentSessionAuthToken,
gender: (selectedGender ?? "Male").toLowerCase() == "male" ? 1 : 2,
); );
result.fold( result.fold(
@ -804,7 +785,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
await getDiagnosisForTriage( await getDiagnosisForTriage(
age: _selectedAge!, age: _selectedAge!,
sex: _selectedGender!.toLowerCase(), gender: _getGenderAsInt(_selectedGender),
evidenceIds: evidenceIds, evidenceIds: evidenceIds,
language: appState.isArabic() ? 'ar' : 'en', language: appState.isArabic() ? 'ar' : 'en',
onSuccess: (response) { onSuccess: (response) {
@ -941,8 +922,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
// Calculate age from date of birth // Calculate age from date of birth
final now = DateTime.now(); final now = DateTime.now();
int age = now.year - dateOfBirth.year; int age = now.year - dateOfBirth.year;
if (now.month < dateOfBirth.month || if (now.month < dateOfBirth.month || (now.month == dateOfBirth.month && now.day < dateOfBirth.day)) {
(now.month == dateOfBirth.month && now.day < dateOfBirth.day)) {
age--; age--;
} }
_selectedAge = age; _selectedAge = age;
@ -968,6 +948,22 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
bool get isUserInfoFirstPage => _userInfoCurrentPage == 0; bool get isUserInfoFirstPage => _userInfoCurrentPage == 0;
/// Check if current user info page has valid selection
bool get isCurrentUserInfoPageValid {
switch (_userInfoCurrentPage) {
case 0: // Gender page
return _selectedGender != null && _selectedGender!.isNotEmpty;
case 1: // Age/Birth date page
return _dateOfBirth != null || (_selectedAge != null && _selectedAge! > 0);
case 2: // Height page
return _selectedHeight > 0;
case 3: // Weight page
return _selectedWeight > 0;
default:
return false;
}
}
/// Validate and submit user info /// Validate and submit user info
Map<String, dynamic> getUserInfoData() { Map<String, dynamic> getUserInfoData() {
return { return {
@ -989,8 +985,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
}) async { }) async {
isBodySymptomsLoading = true; isBodySymptomsLoading = true;
notifyListeners(); notifyListeners();
final result = await symptomsCheckerRepo.getUserDetails( final result = await symptomsCheckerRepo.getUserDetails(userName: userName, password: password);
userName: userName, password: password);
result.fold( result.fold(
(failure) async { (failure) async {
@ -1030,7 +1025,7 @@ class SymptomsCheckerViewModel extends ChangeNotifier {
final result = await symptomsCheckerRepo.getBodySymptomsByName( final result = await symptomsCheckerRepo.getBodySymptomsByName(
organNames: organNames, organNames: organNames,
userSessionToken: currentSessionAuthToken, userSessionToken: currentSessionAuthToken,
gender: (selectedGender ?? "Male").toLowerCase() == "male" ? 1 : 2, gender: _getGenderAsInt(selectedGender ?? "Male"),
); );
result.fold( result.fold(

@ -1371,6 +1371,17 @@ abstract class LocaleKeys {
static const suggestions = 'suggestions'; static const suggestions = 'suggestions';
static const pleaseGoBackAndSelectOrgansFirst = 'pleaseGoBackAndSelectOrgansFirst'; static const pleaseGoBackAndSelectOrgansFirst = 'pleaseGoBackAndSelectOrgansFirst';
static const symptomsSelector = 'symptomsSelector'; static const symptomsSelector = 'symptomsSelector';
static const possibleSymptomsRelatedTo = 'possibleSymptomsRelatedTo';
static const suggestionAIListDescription = 'suggestionAIListDescription';
static const analyzing = 'analyzing';
static const seekMedicalAdvice = 'seekMedicalAdvice';
static const monitorDescription = 'monitorDescription';
static const seekMedicalAdviceDescription = 'seekMedicalAdviceDescription';
static const emergencyDescription = 'emergencyDescription';
static const colorScience = 'colorScience';
static const noNeedToVisitDoctor = 'noNeedToVisitDoctor';
static const commonSymptom = 'commonSymptom';
static const notApplicable = 'notApplicable';
static const emergencyTriage = 'emergencyTriage'; static const emergencyTriage = 'emergencyTriage';
static const emergencyEvidenceDetected = 'emergencyEvidenceDetected'; static const emergencyEvidenceDetected = 'emergencyEvidenceDetected';
static const noQuestionItemsAvailable = 'noQuestionItemsAvailable'; static const noQuestionItemsAvailable = 'noQuestionItemsAvailable';
@ -1488,5 +1499,18 @@ abstract class LocaleKeys {
static const pleaseWaitYouWillBeCalledForVitalSigns = 'pleaseWaitYouWillBeCalledForVitalSigns'; static const pleaseWaitYouWillBeCalledForVitalSigns = 'pleaseWaitYouWillBeCalledForVitalSigns';
static const pleaseVisitRoomForVitalSigns = 'pleaseVisitRoomForVitalSigns'; static const pleaseVisitRoomForVitalSigns = 'pleaseVisitRoomForVitalSigns';
static const pleaseVisitRoomToTheDoctor = 'pleaseVisitRoomToTheDoctor'; static const pleaseVisitRoomToTheDoctor = 'pleaseVisitRoomToTheDoctor';
static const erOnlineCheckInRequest = 'erOnlineCheckInRequest';
static const indoor = 'indoor';
static const navigation = 'navigation';
static const health = 'health';
static const calculators = 'calculators';
static const converters = 'converters';
static const guide = 'guide';
static const liveCareServiceDesc = 'liveCareServiceDesc';
static const bloodGroup = 'bloodGroup';
static const medicalServices = 'medicalServices';
static const insuranceAndPayments = 'insuranceAndPayments';
static const trackerAndOthers = 'trackerAndOthers';
static const bmi = 'bmi';
} }

@ -87,7 +87,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.appointmentDetails.tr(), title: LocaleKeys.appointmentDetails.tr(context: context),
report: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) report: AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? () { ? () {
contactUsViewModel.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel); contactUsViewModel.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel);
@ -105,7 +105,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
AppointmentDoctorCard( AppointmentDoctorCard(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onAskDoctorTap: () async { onAskDoctorTap: () async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context));
await myAppointmentsViewModel.isDoctorAvailable( await myAppointmentsViewModel.isDoctorAvailable(
projectID: widget.patientAppointmentHistoryResponseModel.projectID, projectID: widget.patientAppointmentHistoryResponseModel.projectID,
doctorId: widget.patientAppointmentHistoryResponseModel.doctorID, doctorId: widget.patientAppointmentHistoryResponseModel.doctorID,
@ -135,7 +135,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
onCancelTap: () async { onCancelTap: () async {
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.cancellingAppointmentPleaseWait.tr(context: context));
await myAppointmentsViewModel.cancelAppointment( await myAppointmentsViewModel.cancelAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onSuccess: (apiResponse) { onSuccess: (apiResponse) {
@ -144,7 +144,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getSuccessWidget(loadingText: LocaleKeys.appointmentCancelledSuccessfully.tr()), child: Utils.getSuccessWidget(loadingText: LocaleKeys.appointmentCancelledSuccessfully.tr(context: context)),
callBackFunc: () { callBackFunc: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -181,13 +181,13 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
children: [ children: [
Row( Row(
children: [ children: [
LocaleKeys.appointmentStatus.tr().toText16(isBold: true), LocaleKeys.appointmentStatus.tr(context: context).toText16(isBold: true),
], ],
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
(!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel) (!AppointmentType.isConfirmed(widget.patientAppointmentHistoryResponseModel)
? LocaleKeys.notConfirmed.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500) ? LocaleKeys.notConfirmed.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
: LocaleKeys.confirmed.tr().toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)), : LocaleKeys.confirmed.tr(context: context).toText12(color: AppColors.successColor, fontWeight: FontWeight.w500)),
SizedBox(height: 16.h), SizedBox(height: 16.h),
//TODO Add countdown timer in case of LiveCare Appointment //TODO Add countdown timer in case of LiveCare Appointment
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false
@ -199,7 +199,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.doctorWillCallYou.tr().toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), LocaleKeys.doctorWillCallYou.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
], ],
), ),
), ),
@ -225,7 +225,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!), MapsLauncher.launchCoordinates(double.parse(widget.patientAppointmentHistoryResponseModel.latitude!),
double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName); double.parse(widget.patientAppointmentHistoryResponseModel.longitude!), widget.patientAppointmentHistoryResponseModel.projectName);
}, },
text: LocaleKeys.getDirections.tr(), text: LocaleKeys.getDirections.tr(context: context),
backgroundColor: AppColors.textColor.withValues(alpha: 0.8), backgroundColor: AppColors.textColor.withValues(alpha: 0.8),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.01), borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withValues(alpha: 0.01),
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
@ -280,7 +280,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.setReminder.tr(context: context).toText13(isBold: true), LocaleKeys.setReminder.tr(context: context).toText13(isBold: true),
LocaleKeys.notifyMeBeforeAppointment.tr().toText11(color: AppColors.textColorLight, weight: FontWeight.w500), LocaleKeys.notifyMeBeforeAppointment.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
], ],
), ),
const Spacer(), const Spacer(),
@ -365,7 +365,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
).onPress(() async { ).onPress(() async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingLabResults.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingLabResults.tr(context: context));
await labViewModel.getLabResultsByAppointmentNo( await labViewModel.getLabResultsByAppointmentNo(
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo, appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo,
projectID: widget.patientAppointmentHistoryResponseModel.projectID, projectID: widget.patientAppointmentHistoryResponseModel.projectID,
@ -398,7 +398,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
).onPress(() async { ).onPress(() async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingRadiologyResults.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingRadiologyResults.tr(context: context));
await radiologyViewModel.getPatientRadiologyOrdersByAppointment( await radiologyViewModel.getPatientRadiologyOrdersByAppointment(
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo, appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo,
projectID: widget.patientAppointmentHistoryResponseModel.projectID, projectID: widget.patientAppointmentHistoryResponseModel.projectID,
@ -425,7 +425,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
isLargeText: true, isLargeText: true,
iconSize: 36.w, iconSize: 36.w,
).onPress(() async { ).onPress(() async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingAppointmentPrescriptions.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingAppointmentPrescriptions.tr(context: context));
await prescriptionsViewModel.getPrescriptionDetails( await prescriptionsViewModel.getPrescriptionDetails(
getPrescriptionRequestModel(), getPrescriptionRequestModel(),
onSuccess: (val) { onSuccess: (val) {
@ -453,7 +453,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
} else { } else {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.noPrescriptionsForAppointment.tr()), child: Utils.getErrorWidget(loadingText: LocaleKeys.noPrescriptionsForAppointment.tr(context: context)),
callBackFunc: () {}, callBackFunc: () {},
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,
@ -522,7 +522,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
// ], // ],
// ), // ),
// SizedBox(height: 16.h), // SizedBox(height: 16.h),
// LocaleKeys.prescriptions.tr().toText18(isBold: true), // LocaleKeys.prescriptions.tr(context: context).toText18(isBold: true),
// SizedBox(height: 16.h), // SizedBox(height: 16.h),
// Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) { // Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
// return prescriptionVM.isPrescriptionsDetailsLoading // return prescriptionVM.isPrescriptionsDetailsLoading
@ -708,7 +708,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.amountBeforeTax.tr().toText18(isBold: true), LocaleKeys.amountBeforeTax.tr(context: context).toText18(isBold: true),
Utils.getPaymentAmountWithSymbol( Utils.getPaymentAmountWithSymbol(
widget.patientAppointmentHistoryResponseModel.patientShare!.toString().toText16(isBold: true), widget.patientAppointmentHistoryResponseModel.patientShare!.toString().toText16(isBold: true),
AppColors.blackColor, AppColors.blackColor,
@ -752,7 +752,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h), ).paddingOnly(left: 16.h, top: 24.h, right: 16.h, bottom: 0.h),
AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel) AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)
? CustomButton( ? CustomButton(
text: LocaleKeys.rebookAppointment.tr(), text: LocaleKeys.rebookAppointment.tr(context: context),
onPressed: () { onPressed: () {
openDoctorScheduleCalendar(); openDoctorScheduleCalendar();
}, },
@ -810,13 +810,13 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
projectName: widget.patientAppointmentHistoryResponseModel.projectName, projectName: widget.patientAppointmentHistoryResponseModel.projectName,
); );
bookAppointmentsViewModel.setSelectedDoctor(doctor); bookAppointmentsViewModel.setSelectedDoctor(doctor);
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingDoctorSchedulePleaseWait.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingDoctorSchedulePleaseWait.tr(context: context));
await bookAppointmentsViewModel.getDoctorFreeSlots( await bookAppointmentsViewModel.getDoctorFreeSlots(
isBookingForLiveCare: false, isBookingForLiveCare: false,
onSuccess: (dynamic respData) async { onSuccess: (dynamic respData) async {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
title: LocaleKeys.pickADate.tr(), title: LocaleKeys.pickADate.tr(context: context),
context, context,
child: AppointmentCalendar(), child: AppointmentCalendar(),
isFullScreen: false, isFullScreen: false,
@ -841,14 +841,14 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
case 0: case 0:
break; break;
case 10: case 10:
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingAppointmentPleaseWait.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingAppointmentPleaseWait.tr(context: context));
await myAppointmentsViewModel.confirmAppointment( await myAppointmentsViewModel.confirmAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
onSuccess: (apiResponse) { onSuccess: (apiResponse) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);
myAppointmentsViewModel.getPatientAppointments(true, false); myAppointmentsViewModel.getPatientAppointments(true, false);
showCommonBottomSheet(context, child: Utils.getSuccessWidget(loadingText: LocaleKeys.appointmentConfirmedSuccessfully.tr()), callBackFunc: (str) { showCommonBottomSheet(context, child: Utils.getSuccessWidget(loadingText: LocaleKeys.appointmentConfirmedSuccessfully.tr(context: context)), callBackFunc: (str) {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
title: "", title: "",
@ -869,10 +869,10 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
), ),
); );
case 50: case 50:
// return LocaleKeys.confirmLiveCare.tr(); // return LocaleKeys.confirmLiveCare.tr(context: context);
case 90: case 90:
showCommonBottomSheetWithoutHeight(context, showCommonBottomSheetWithoutHeight(context,
title: LocaleKeys.onlineCheckIn.tr(), title: LocaleKeys.onlineCheckIn.tr(context: context),
child: AppointmentCheckinBottomSheet( child: AppointmentCheckinBottomSheet(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
myAppointmentsViewModel: myAppointmentsViewModel, myAppointmentsViewModel: myAppointmentsViewModel,

@ -90,7 +90,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.appointmentPayment.tr(), title: LocaleKeys.appointmentPayment.tr(context: context),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -248,7 +248,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.insuranceExpiredOrInactive.tr() LocaleKeys.insuranceExpiredOrInactive.tr(context: context)
.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500) .toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500)
.paddingSymmetrical(24.h, 0.h), .paddingSymmetrical(24.h, 0.h),
CustomButton( CustomButton(
@ -274,12 +274,12 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
) )
: const SizedBox(), : const SizedBox(),
SizedBox(height: 24.h), SizedBox(height: 24.h),
LocaleKeys.totalAmountToPay.tr().toText18(isBold: true).paddingSymmetrical(24.h, 0.h), LocaleKeys.totalAmountToPay.tr(context: context).toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h), SizedBox(height: 17.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.amountBeforeTax.tr().toText14(isBold: true), LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true),
Utils.getPaymentAmountWithSymbol( Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true),
AppColors.blackColor, AppColors.blackColor,
@ -380,7 +380,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
} }
void checkPaymentStatus() async { void checkPaymentStatus() async {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingPaymentStatusPleaseWait.tr()); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingPaymentStatusPleaseWait.tr(context: context));
if (selectedPaymentMethod == "TAMARA") { if (selectedPaymentMethod == "TAMARA") {
await payfortViewModel.checkTamaraPaymentStatus( await payfortViewModel.checkTamaraPaymentStatus(
transactionID: transID, transactionID: transID,
@ -438,7 +438,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr()), child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {}, callBackFunc: () {},
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,
@ -519,7 +519,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
} else { } else {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr()), child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {}, callBackFunc: () {},
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,

@ -155,7 +155,7 @@ class _MyAppointmentsPageState extends State<MyAppointmentsPage> {
isLoading: true, isLoading: true,
isFromHomePage: false, isFromHomePage: false,
), ),
).paddingSymmetrical(24.h, 0.h) )
: filteredAppointmentList.isNotEmpty : filteredAppointmentList.isNotEmpty
? AnimationConfiguration.staggeredList( ? AnimationConfiguration.staggeredList(
position: index, position: index,

@ -32,7 +32,7 @@ import '../../../emergency_services/call_ambulance/widgets/type_selection_widget
// crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
// children: [ // children: [
// Text( // Text(
// LocaleKeys.selectHospital.tr(), // LocaleKeys.selectHospital.tr(context: context),
// style: TextStyle( // style: TextStyle(
// fontSize: 21, // fontSize: 21,
// fontWeight: FontWeight.w600, // fontWeight: FontWeight.w600,
@ -40,7 +40,7 @@ import '../../../emergency_services/call_ambulance/widgets/type_selection_widget
// ), // ),
// ), // ),
// Text( // Text(
// LocaleKeys.selectHospitalSubTitle.tr(), // LocaleKeys.selectHospitalSubTitle.tr(context: context),
// style: TextStyle( // style: TextStyle(
// fontSize: 16, // fontSize: 16,
// fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
@ -49,8 +49,8 @@ import '../../../emergency_services/call_ambulance/widgets/type_selection_widget
// ), // ),
// SizedBox(height: 16.h), // SizedBox(height: 16.h),
// TextInputWidget( // TextInputWidget(
// labelText: LocaleKeys.search.tr(), // labelText: LocaleKeys.search.tr(context: context),
// hintText: LocaleKeys.searchHospital.tr(), // hintText: LocaleKeys.searchHospital.tr(context: context),
// controller: searchText, // controller: searchText,
// onChange: (value) { // onChange: (value) {
// appointmentsViewModel.filterHospitalListByString( // appointmentsViewModel.filterHospitalListByString(
@ -135,8 +135,8 @@ class HospitalBottomSheetBody extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.search.tr(), labelText: LocaleKeys.search.tr(context: context),
hintText: LocaleKeys.searchHospital.tr(), hintText: LocaleKeys.searchHospital.tr(context: context),
controller: searchText, controller: searchText,
onChange: (value) { onChange: (value) {
debouncer.run((){ debouncer.run((){

@ -71,10 +71,10 @@ class LoginScreenState extends State<LoginScreen> {
children: [ children: [
Utils.showLottie(context: context, assetPath: AppAnimations.login, width: 200.h, height: 200.h, repeat: true, fit: BoxFit.cover), Utils.showLottie(context: context, assetPath: AppAnimations.login, width: 200.h, height: 200.h, repeat: true, fit: BoxFit.cover),
SizedBox(height: 130.h), // Adjusted to sizer unit SizedBox(height: 130.h), // Adjusted to sizer unit
LocaleKeys.welcomeToDrSulaiman.tr().toText32(isBold: true, color: AppColors.textColor), LocaleKeys.welcomeToDrSulaiman.tr(context: context).toText32(isBold: true, color: AppColors.textColor),
SizedBox(height: 32.h), SizedBox(height: 32.h),
TextInputWidget( TextInputWidget(
labelText: "${LocaleKeys.nationalId.tr()} / ${LocaleKeys.fileNo.tr()}", labelText: "${LocaleKeys.nationalId.tr(context: context)} / ${LocaleKeys.fileNo.tr(context: context)}",
hintText: "xxxxxxxxx", hintText: "xxxxxxxxx",
controller: authVm.nationalIdController, controller: authVm.nationalIdController,
focusNode: _nationalIdFocusNode, focusNode: _nationalIdFocusNode,
@ -87,13 +87,13 @@ class LoginScreenState extends State<LoginScreen> {
isAllowLeadingIcon: true, isAllowLeadingIcon: true,
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 10.h), padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 10.h),
leadingIcon: AppAssets.student_card, leadingIcon: AppAssets.student_card,
errorMessage: LocaleKeys.enterValidIDorIqama.tr(), errorMessage: LocaleKeys.enterValidIDorIqama.tr(context: context),
hasError: false, hasError: false,
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
CustomButton( CustomButton(
height: 50.h, height: 50.h,
text: LocaleKeys.login.tr(), text: LocaleKeys.login.tr(context: context),
icon: AppAssets.login1, icon: AppAssets.login1,
iconColor: Colors.white, iconColor: Colors.white,
onPressed: () { onPressed: () {
@ -116,10 +116,10 @@ class LoginScreenState extends State<LoginScreen> {
text: TextSpan( text: TextSpan(
style: context.dynamicTextStyle(color: Colors.black, fontSize: 14.f, height: 26 / 16, fontWeight: FontWeight.w500), style: context.dynamicTextStyle(color: Colors.black, fontSize: 14.f, height: 26 / 16, fontWeight: FontWeight.w500),
children: <TextSpan>[ children: <TextSpan>[
TextSpan(text: LocaleKeys.dontHaveAccount.tr(), style: context.dynamicTextStyle()), TextSpan(text: LocaleKeys.dontHaveAccount.tr(context: context), style: context.dynamicTextStyle()),
TextSpan(text: " "), TextSpan(text: " "),
TextSpan( TextSpan(
text: LocaleKeys.registernow.tr(), text: LocaleKeys.registernow.tr(context: context),
style: context.dynamicTextStyle( style: context.dynamicTextStyle(
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
fontSize: 14.f, // Adjusted to sizer unit fontSize: 14.f, // Adjusted to sizer unit
@ -172,7 +172,7 @@ class LoginScreenState extends State<LoginScreen> {
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h), padding: EdgeInsets.only(bottom: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(), text: LocaleKeys.sendOTPSMS.tr(context: context),
onPressed: () async { onPressed: () async {
if (ValidationUtils.isValidatePhone( if (ValidationUtils.isValidatePhone(
phoneNumber: phoneNumberController!.text, phoneNumber: phoneNumberController!.text,
@ -196,14 +196,14 @@ class LoginScreenState extends State<LoginScreen> {
children: [ children: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 8.h), padding: EdgeInsets.symmetric(horizontal: 8.h),
child: LocaleKeys.oR.tr().toText16(color: AppColors.textColor), child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor),
), ),
], ],
), ),
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h, top: 10.h), padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(), text: LocaleKeys.sendOTPWHATSAPP.tr(context: context),
onPressed: () async { onPressed: () async {
if (ValidationUtils.isValidatePhone( if (ValidationUtils.isValidatePhone(
phoneNumber: phoneNumberController!.text, phoneNumber: phoneNumberController!.text,

@ -49,7 +49,7 @@ class QuickLoginState extends State<QuickLogin> {
], ],
), ),
Utils.showLottie(context: context, assetPath: AppAnimations.checkmark, width: 120, height: 120, repeat: true), Utils.showLottie(context: context, assetPath: AppAnimations.checkmark, width: 120, height: 120, repeat: true),
LocaleKeys.allSet.tr().toText16(textAlign: TextAlign.center, weight: FontWeight.w500) LocaleKeys.allSet.tr(context: context).toText16(textAlign: TextAlign.center, weight: FontWeight.w500)
// Text( // Text(
// ' TranslationBase.of(context).allSet', // ' TranslationBase.of(context).allSet',
// textAlign: TextAlign.center, // textAlign: TextAlign.center,
@ -67,7 +67,7 @@ class QuickLoginState extends State<QuickLogin> {
children: [ children: [
Image.asset(AppAssets.lockIcon, height: 100), Image.asset(AppAssets.lockIcon, height: 100),
SizedBox(height: 10.h), SizedBox(height: 10.h),
LocaleKeys.enableQuickLogin.tr().toText26(isBold: true), LocaleKeys.enableQuickLogin.tr(context: context).toText26(isBold: true),
// Text( // Text(
// ' TranslationBase.of(context).enableQuickLogin', // ' TranslationBase.of(context).enableQuickLogin',
// style: context.dynamicTextStyle( // style: context.dynamicTextStyle(
@ -77,7 +77,7 @@ class QuickLoginState extends State<QuickLogin> {
// ), // ),
// ), // ),
SizedBox(height: 5.h), SizedBox(height: 5.h),
LocaleKeys.enableQuickLogin.tr().toText16(color: AppColors.quickLoginColor), LocaleKeys.enableQuickLogin.tr(context: context).toText16(color: AppColors.quickLoginColor),
// Description // Description
// Text( // Text(
// 'TranslationBase.of(context).enableMsg', // 'TranslationBase.of(context).enableMsg',
@ -94,7 +94,7 @@ class QuickLoginState extends State<QuickLogin> {
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.enableQuickLogin.tr(), text: LocaleKeys.enableQuickLogin.tr(context: context),
onPressed: () { onPressed: () {
widget.onPressed(); widget.onPressed();
}, },
@ -114,7 +114,7 @@ class QuickLoginState extends State<QuickLogin> {
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.notNow.tr(), text: LocaleKeys.notNow.tr(context: context),
onPressed: () { onPressed: () {
cacheService.saveBool(key: CacheConst.quickLoginEnabled, value: false); cacheService.saveBool(key: CacheConst.quickLoginEnabled, value: false);
Navigator.pop(context, "true"); Navigator.pop(context, "true");

@ -80,7 +80,7 @@ class _RegisterNew extends State<RegisterNew> {
children: [ children: [
Utils.showLottie(context: context, assetPath: 'assets/animations/lottie/register.json', width: 200.w, height: 200.h, fit: BoxFit.cover, repeat: true), Utils.showLottie(context: context, assetPath: 'assets/animations/lottie/register.json', width: 200.w, height: 200.h, fit: BoxFit.cover, repeat: true),
SizedBox(height: 16.h), SizedBox(height: 16.h),
LocaleKeys.prepareToElevate.tr().toText32(isBold: true), LocaleKeys.prepareToElevate.tr(context: context).toText32(isBold: true),
SizedBox(height: 24.h), SizedBox(height: 24.h),
Directionality( Directionality(
textDirection: Directionality.of(context), textDirection: Directionality.of(context),
@ -96,7 +96,7 @@ class _RegisterNew extends State<RegisterNew> {
).withVerticalPadding(8.h), ).withVerticalPadding(8.h),
Divider(height: 1.h), Divider(height: 1.h),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.nationalIdNumber.tr(), labelText: LocaleKeys.nationalIdNumber.tr(context: context),
hintText: "xxxxxxxxx", hintText: "xxxxxxxxx",
controller: authVm.nationalIdController, controller: authVm.nationalIdController,
focusNode: _nationalIdFocusNode, focusNode: _nationalIdFocusNode,
@ -111,7 +111,7 @@ class _RegisterNew extends State<RegisterNew> {
).withVerticalPadding(8), ).withVerticalPadding(8),
Divider(height: 1), Divider(height: 1),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.dob.tr(), labelText: LocaleKeys.dob.tr(context: context),
hintText: "11 July, 1994", hintText: "11 July, 1994",
controller: authVm.dobController, controller: authVm.dobController,
focusNode: _dobFocusNode, focusNode: _dobFocusNode,
@ -156,7 +156,7 @@ class _RegisterNew extends State<RegisterNew> {
Row( Row(
children: [ children: [
Text( Text(
LocaleKeys.iAcceptThe.tr(), LocaleKeys.iAcceptThe.tr(context: context),
style: context.dynamicTextStyle(fontSize: 14.f, fontWeight: FontWeight.w500, color: Color(0xFF2E3039)), style: context.dynamicTextStyle(fontSize: 14.f, fontWeight: FontWeight.w500, color: Color(0xFF2E3039)),
), ),
GestureDetector( GestureDetector(
@ -165,7 +165,7 @@ class _RegisterNew extends State<RegisterNew> {
Navigator.of(context).pushNamed('/terms'); Navigator.of(context).pushNamed('/terms');
}, },
child: Text( child: Text(
LocaleKeys.termsConditoins.tr(), LocaleKeys.termsConditoins.tr(context: context),
style: context.dynamicTextStyle( style: context.dynamicTextStyle(
fontSize: 14.f, fontSize: 14.f,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -179,7 +179,7 @@ class _RegisterNew extends State<RegisterNew> {
), ),
// Expanded( // Expanded(
// child: Text( // child: Text(
// LocaleKeys.iAcceptTermsConditions.tr().split("the").first, // LocaleKeys.iAcceptTermsConditions.tr(context: context).split("the").first,
// style: context.dynamicTextStyle(fontSize: 14.fSize, fontWeight: FontWeight.w500, color: Color(0xFF2E3039)), // style: context.dynamicTextStyle(fontSize: 14.fSize, fontWeight: FontWeight.w500, color: Color(0xFF2E3039)),
// ), // ),
// ), // ),
@ -188,7 +188,7 @@ class _RegisterNew extends State<RegisterNew> {
), ),
SizedBox(height: 25.h), SizedBox(height: 25.h),
CustomButton( CustomButton(
text: LocaleKeys.registernow.tr(), text: LocaleKeys.registernow.tr(context: context),
icon: AppAssets.note_edit, icon: AppAssets.note_edit,
onPressed: () { onPressed: () {
// Dismiss keyboard before proceeding // Dismiss keyboard before proceeding
@ -220,10 +220,10 @@ class _RegisterNew extends State<RegisterNew> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
children: <TextSpan>[ children: <TextSpan>[
TextSpan(text: LocaleKeys.alreadyHaveAccount.tr(), style: context.dynamicTextStyle()), TextSpan(text: LocaleKeys.alreadyHaveAccount.tr(context: context), style: context.dynamicTextStyle()),
TextSpan(text: " "), TextSpan(text: " "),
TextSpan( TextSpan(
text: LocaleKeys.loginNow.tr(), text: LocaleKeys.loginNow.tr(context: context),
style: context.dynamicTextStyle( style: context.dynamicTextStyle(
color: AppColors.primaryRedColor, color: AppColors.primaryRedColor,
fontSize: 16.f, fontSize: 16.f,
@ -271,7 +271,7 @@ class _RegisterNew extends State<RegisterNew> {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.only(bottom: 10),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(), text: LocaleKeys.sendOTPSMS.tr(context: context),
onPressed: () async { onPressed: () async {
// Dismiss keyboard before validation // Dismiss keyboard before validation
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
@ -298,14 +298,14 @@ class _RegisterNew extends State<RegisterNew> {
children: [ children: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 8.h), padding: EdgeInsets.symmetric(horizontal: 8.h),
child: LocaleKeys.oR.tr().toText16(color: AppColors.textColor), child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor),
), ),
], ],
), ),
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h, top: 10.h), padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(), text: LocaleKeys.sendOTPWHATSAPP.tr(context: context),
onPressed: () async { onPressed: () async {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
if (ValidationUtils.isValidatePhone( if (ValidationUtils.isValidatePhone(

@ -73,7 +73,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
LocaleKeys.personalDetailsVerification.tr().toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2), LocaleKeys.personalDetailsVerification.tr(context: context).toText26(color: AppColors.textColor, weight: FontWeight.w600, letterSpacing: -2),
SizedBox(height: 24.h), SizedBox(height: 24.h),
Container( Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(24)),
@ -81,8 +81,8 @@ class _RegisterNew extends State<RegisterNewStep2> {
child: Column( child: Column(
children: [ children: [
TextInputWidget( TextInputWidget(
labelText: authVM!.isUserFromUAE() ? LocaleKeys.fullName.tr() : LocaleKeys.name.tr(), labelText: authVM!.isUserFromUAE() ? LocaleKeys.fullName.tr(context: context) : LocaleKeys.name.tr(context: context),
hintText: authVM!.isUserFromUAE() ? LocaleKeys.enterNameHere.tr() : (name), hintText: authVM!.isUserFromUAE() ? LocaleKeys.enterNameHere.tr(context: context) : (name),
controller: authVM!.isUserFromUAE() ? authVM!.nameController : null, controller: authVM!.isUserFromUAE() ? authVM!.nameController : null,
isEnable: true, isEnable: true,
prefix: null, prefix: null,
@ -100,7 +100,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
).paddingSymmetrical(0.h, 16.h), ).paddingSymmetrical(0.h, 16.h),
Divider(height: 1.h, color: AppColors.greyColor), Divider(height: 1.h, color: AppColors.greyColor),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.nationalIdNumber.tr(), labelText: LocaleKeys.nationalIdNumber.tr(context: context),
hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : (appState.getNHICUserData.idNumber ?? ""), hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : (appState.getNHICUserData.idNumber ?? ""),
controller: null, controller: null,
isEnable: true, isEnable: true,
@ -120,8 +120,8 @@ class _RegisterNew extends State<RegisterNewStep2> {
builder: (context, genderType, child) { builder: (context, genderType, child) {
final authVM = context.read<AuthenticationViewModel>(); final authVM = context.read<AuthenticationViewModel>();
return DropdownWidget( return DropdownWidget(
labelText: LocaleKeys.gender.tr(), labelText: LocaleKeys.gender.tr(context: context),
hintText: LocaleKeys.malE.tr(), hintText: LocaleKeys.malE.tr(context: context),
isEnable: true, isEnable: true,
dropdownItems: GenderTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(), dropdownItems: GenderTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(),
selectedValue: genderType != null ? (appState.isArabic() ? genderType.typeAr : genderType.type) : "", selectedValue: genderType != null ? (appState.isArabic() ? genderType.typeAr : genderType.type) : "",
@ -136,7 +136,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
).withVerticalPadding(8); ).withVerticalPadding(8);
}) })
: TextInputWidget( : TextInputWidget(
labelText: LocaleKeys.gender.tr(), labelText: LocaleKeys.gender.tr(context: context),
hintText: (appState.getNHICUserData.gender ?? ""), hintText: (appState.getNHICUserData.gender ?? ""),
controller: null, controller: null,
isEnable: true, isEnable: true,
@ -157,8 +157,8 @@ class _RegisterNew extends State<RegisterNewStep2> {
builder: (context, maritalStatus, child) { builder: (context, maritalStatus, child) {
final authVM = context.read<AuthenticationViewModel>(); // For onChange final authVM = context.read<AuthenticationViewModel>(); // For onChange
return DropdownWidget( return DropdownWidget(
labelText: LocaleKeys.maritalStatus.tr(), labelText: LocaleKeys.maritalStatus.tr(context: context),
hintText: LocaleKeys.married.tr(), hintText: LocaleKeys.married.tr(context: context),
isEnable: true, isEnable: true,
dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(), dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(),
selectedValue: maritalStatus != null ? (appState.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "", selectedValue: maritalStatus != null ? (appState.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "",
@ -174,7 +174,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
}, },
) )
: TextInputWidget( : TextInputWidget(
labelText: LocaleKeys.maritalStatus.tr(), labelText: LocaleKeys.maritalStatus.tr(context: context),
hintText: appState.isArabic() hintText: appState.isArabic()
? (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.typeAr) ? (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.typeAr)
: (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.type), : (MaritalStatusTypeExtension.fromValue(appState.getNHICUserData.maritalStatusCode)!.type),
@ -203,8 +203,8 @@ class _RegisterNew extends State<RegisterNewStep2> {
builder: (context, data, child) { builder: (context, data, child) {
final authVM = context.read<AuthenticationViewModel>(); final authVM = context.read<AuthenticationViewModel>();
return DropdownWidget( return DropdownWidget(
labelText: LocaleKeys.country.tr(), labelText: LocaleKeys.country.tr(context: context),
hintText: LocaleKeys.uae.tr(), hintText: LocaleKeys.uae.tr(context: context),
isEnable: true, isEnable: true,
dropdownItems: (data.countriesList ?? []).map((e) => data.isArabic ? e.nameN ?? "" : e.name ?? "").toList(), dropdownItems: (data.countriesList ?? []).map((e) => data.isArabic ? e.nameN ?? "" : e.name ?? "").toList(),
selectedValue: data.selectedCountry != null selectedValue: data.selectedCountry != null
@ -224,7 +224,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
}, },
) )
: TextInputWidget( : TextInputWidget(
labelText: LocaleKeys.nationality.tr(), labelText: LocaleKeys.nationality.tr(context: context),
hintText: appState.isArabic() hintText: appState.isArabic()
? (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).nameN ?? "") ? (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).nameN ?? "")
: (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).name ?? ""), : (authVM!.countriesList!.firstWhere((e) => e.id == (appState.getNHICUserData.nationalityCode ?? ""), orElse: () => NationalityCountries()).name ?? ""),
@ -243,7 +243,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
color: AppColors.greyColor, color: AppColors.greyColor,
), ),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.mobileNumber.tr(), labelText: LocaleKeys.mobileNumber.tr(context: context),
hintText: (appState.getUserRegistrationPayload.patientMobileNumber.toString() ?? ""), hintText: (appState.getUserRegistrationPayload.patientMobileNumber.toString() ?? ""),
controller: null, controller: null,
isEnable: false, isEnable: false,
@ -260,7 +260,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
color: AppColors.greyColor, color: AppColors.greyColor,
), ),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.dob.tr(), labelText: LocaleKeys.dob.tr(context: context),
hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.dob! : appState.getNHICUserData.dateOfBirth ?? "", hintText: authVM!.isUserFromUAE() ? appState.getUserRegistrationPayload.dob! : appState.getNHICUserData.dateOfBirth ?? "",
controller: authVM!.isUserFromUAE() ? authVM!.dobController : null, controller: authVM!.isUserFromUAE() ? authVM!.dobController : null,
isEnable: false, isEnable: false,
@ -280,7 +280,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.cancel.tr(), text: LocaleKeys.cancel.tr(context: context),
icon: AppAssets.cancel, icon: AppAssets.cancel,
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
@ -298,7 +298,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
text: LocaleKeys.confirm.tr(), text: LocaleKeys.confirm.tr(context: context),
icon: AppAssets.confirm, icon: AppAssets.confirm,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
onPressed: () { onPressed: () {
@ -345,7 +345,7 @@ class _RegisterNew extends State<RegisterNewStep2> {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.only(bottom: 10),
child: CustomButton( child: CustomButton(
text: LocaleKeys.submit.tr(), text: LocaleKeys.submit.tr(context: context),
onPressed: () { onPressed: () {
if (ValidationUtils.isValidateEmail( if (ValidationUtils.isValidateEmail(
email: authVM!.emailController.text, email: authVM!.emailController.text,

@ -89,8 +89,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1),
initialIndex: bookAppointmentsVM.selectedTabIndex, initialIndex: bookAppointmentsVM.selectedTabIndex,
tabs: [ tabs: [
CustomTabBarModel(null, LocaleKeys.general.tr()), CustomTabBarModel(null, LocaleKeys.general.tr(context: context)),
CustomTabBarModel(null, LocaleKeys.liveCare.tr()), CustomTabBarModel(null, LocaleKeys.liveCare.tr(context: context)),
], ],
onTabChange: (index) { onTabChange: (index) {
bookAppointmentsVM.onTabChanged(index); bookAppointmentsVM.onTabChanged(index);
@ -121,7 +121,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (appState.isAuthenticated) ...[], if (appState.isAuthenticated) ...[],
LocaleKeys.recentVisits.tr().toText18(isBold: true).paddingSymmetrical(24.w, 0.h), LocaleKeys.recentVisits.tr(context: context).toText18(isBold: true).paddingSymmetrical(24.w, 0.h),
SizedBox(height: 16.h), SizedBox(height: 16.h),
SizedBox( SizedBox(
height: 110.h, height: 110.h,
@ -232,8 +232,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.searchByClinic.tr().toText14(color: AppColors.textColor, weight: FontWeight.w500), LocaleKeys.searchByClinic.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
LocaleKeys.tapToSelectClinic.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.tapToSelectClinic.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
], ],
), ),
], ],
@ -264,8 +264,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.searchByDoctor.tr().toText14(color: AppColors.textColor, weight: FontWeight.w500), LocaleKeys.searchByDoctor.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
LocaleKeys.tapToSelect.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.tapToSelect.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
], ],
), ),
], ],
@ -294,8 +294,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.searchByRegion.tr().toText14(color: AppColors.textColor, weight: FontWeight.w500), LocaleKeys.searchByRegion.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
LocaleKeys.centralRegion.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.centralRegion.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
], ],
), ),
], ],
@ -340,8 +340,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.immediateConsultation.tr().toText14(color: AppColors.textColor, weight: FontWeight.w500), LocaleKeys.immediateConsultation.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
LocaleKeys.tapToSelectClinic.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.tapToSelectClinic.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
], ],
), ),
], ],
@ -382,8 +382,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.scheduledConsultation.tr().toText14(color: AppColors.textColor, weight: FontWeight.w500), LocaleKeys.scheduledConsultation.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
LocaleKeys.tapToSelectClinic.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.tapToSelectClinic.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
], ],
), ),
], ],
@ -412,7 +412,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.pharmaLiveCare.tr().toText14(color: AppColors.textColor, weight: FontWeight.w500), LocaleKeys.pharmaLiveCare.tr(context: context).toText14(color: AppColors.textColor, weight: FontWeight.w500),
"".toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), "".toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
], ],
), ),
@ -447,9 +447,9 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.notSureHelpMeChooseClinic.tr().toText16(weight: FontWeight.w600, color: AppColors.textColor), LocaleKeys.notSureHelpMeChooseClinic.tr(context: context).toText16(weight: FontWeight.w600, color: AppColors.textColor),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.mentionYourSymptomsAndFindDoctors.tr().toText12( LocaleKeys.mentionYourSymptomsAndFindDoctors.tr(context: context).toText12(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: AppColors.greyTextColor, color: AppColors.greyTextColor,
), ),
@ -531,7 +531,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
getTitle(AppointmentViaRegionViewmodel data) { getTitle(AppointmentViaRegionViewmodel data) {
if (data.selectedRegionId == null) { if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600); return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600);
} else { } else {
return Transform.flip( return Transform.flip(
flipX: data.isArabic ? true : false, flipX: data.isArabic ? true : false,
@ -558,8 +558,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.immediateService.tr().toText18(color: AppColors.textColor, isBold: true), LocaleKeys.immediateService.tr(context: context).toText18(color: AppColors.textColor, isBold: true),
LocaleKeys.noNeedToWaitGetMedicalConsultation.tr().toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), LocaleKeys.noNeedToWaitGetMedicalConsultation.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
], ],
), ),
), ),
@ -574,7 +574,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.noVisitRequired.tr().toText18(color: AppColors.textColor, isBold: true), LocaleKeys.noVisitRequired.tr(context: context).toText18(color: AppColors.textColor, isBold: true),
LocaleKeys.livecarePoint5.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), LocaleKeys.livecarePoint5.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
], ],
), ),
@ -590,8 +590,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.doctorWillContact.tr().toText18(color: AppColors.textColor, isBold: true), LocaleKeys.doctorWillContact.tr(context: context).toText18(color: AppColors.textColor, isBold: true),
LocaleKeys.specialisedDoctorWillContactYou.tr().toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), LocaleKeys.specialisedDoctorWillContactYou.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
], ],
), ),
), ),
@ -606,8 +606,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.freeMedicineDelivery.tr().toText18(color: AppColors.textColor, isBold: true), LocaleKeys.freeMedicineDelivery.tr(context: context).toText18(color: AppColors.textColor, isBold: true),
LocaleKeys.offersFreeMedicineDelivery.tr().toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), LocaleKeys.offersFreeMedicineDelivery.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500),
], ],
), ),
), ),

@ -79,7 +79,7 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, customBorder: BorderRadius.only(topLeft: Radius.circular(24.r), topRight: Radius.circular(24.r))), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, customBorder: BorderRadius.only(topLeft: Radius.circular(24.r), topRight: Radius.circular(24.r))),
padding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 20.h), padding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 20.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.bookAppo.tr(), text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () { onPressed: () {
if (widget.calculatedResult["clinicId"] == null) { if (widget.calculatedResult["clinicId"] == null) {
bookAppointmentsViewModel.setIsDoctorsListLoading(true); bookAppointmentsViewModel.setIsDoctorsListLoading(true);
@ -1097,7 +1097,7 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
getTitle(AppointmentViaRegionViewmodel data) { getTitle(AppointmentViaRegionViewmodel data) {
if (data.selectedRegionId == null) { if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600); return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600);
} else { } else {
return Transform.flip( return Transform.flip(
flipX: data.isArabic ? true : false, flipX: data.isArabic ? true : false,
@ -1185,7 +1185,7 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.cancel.tr(), text: LocaleKeys.cancel.tr(context: context),
onPressed: () { onPressed: () {
bookAppointmentsViewModel.setIsContinueDentalPlan(false); bookAppointmentsViewModel.setIsContinueDentalPlan(false);
bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true); bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true);
@ -1206,7 +1206,7 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
SizedBox(width: 8.h), SizedBox(width: 8.h),
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.confirm.tr(), text: LocaleKeys.confirm.tr(context: context),
onPressed: () async { onPressed: () async {
bookAppointmentsViewModel.setIsContinueDentalPlan(true); bookAppointmentsViewModel.setIsContinueDentalPlan(true);
Navigator.of(context).pop(); Navigator.of(context).pop();

@ -178,7 +178,7 @@ class _SelectDoctorPageState extends State<SelectDoctorPage> {
children: [ children: [
LocaleKeys.nearestAppo.tr(context: context).toText13(isBold: true), LocaleKeys.nearestAppo.tr(context: context).toText13(isBold: true),
SizedBox(height: 4.h), SizedBox(height: 4.h),
LocaleKeys.viewNearestAppos.toText11(color: AppColors.textColorLight, weight: FontWeight.w500), LocaleKeys.viewNearestAppos.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
], ],
), ),
const Spacer(), const Spacer(),

@ -204,13 +204,13 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
children: [ children: [
Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill), Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h), SizedBox(height: 8.h),
(LocaleKeys.loginToUseService.tr()).toText16(color: AppColors.blackColor), (LocaleKeys.loginToUseService.tr(context: context)).toText16(color: AppColors.blackColor),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.cancel.tr(), text: LocaleKeys.cancel.tr(context: context),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -224,7 +224,7 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
SizedBox(width: 8.h), SizedBox(width: 8.h),
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.confirm.tr(), text: LocaleKeys.confirm.tr(context: context),
onPressed: () async { onPressed: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(

@ -50,7 +50,14 @@ class ServicesPage extends StatelessWidget {
late MedicalFileViewModel medicalFileViewModel; late MedicalFileViewModel medicalFileViewModel;
late final List<HmgServicesComponentModel> hmgServices = [ late final List<HmgServicesComponentModel> hmgServices = [
HmgServicesComponentModel(11, LocaleKeys.emergencyServices.tr(), "", AppAssets.emergency_services_icon, bgColor: AppColors.primaryRedColor, true, route: null, onTap: () async { HmgServicesComponentModel(
11,
LocaleKeys.emergencyServices.tr(),
"",
AppAssets.emergency_services_icon,
bgColor: AppColors.primaryRedColor,
true,
route: null, onTap: () async {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<EmergencyServicesViewModel>().flushData(); getIt.get<EmergencyServicesViewModel>().flushData();
getIt.get<EmergencyServicesViewModel>().getTransportationOrders( getIt.get<EmergencyServicesViewModel>().getTransportationOrders(
@ -59,7 +66,7 @@ class ServicesPage extends StatelessWidget {
getIt.get<EmergencyServicesViewModel>().getRRTOrders( getIt.get<EmergencyServicesViewModel>().getRRTOrders(
showLoader: false, showLoader: false,
); );
Navigator.of(GetIt.instance<NavigationService>().navigatorKey.currentContext!).push( Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute( CustomPageRoute(
page: EmergencyServicesPage(), page: EmergencyServicesPage(),
settings: const RouteSettings(name: '/EmergencyServicesPage'), settings: const RouteSettings(name: '/EmergencyServicesPage'),
@ -78,7 +85,8 @@ class ServicesPage extends StatelessWidget {
true, true,
route: AppRoutes.bookAppointmentPage, route: AppRoutes.bookAppointmentPage,
), ),
HmgServicesComponentModel(5, LocaleKeys.completeCheckup.tr(), "", AppAssets.comprehensiveCheckup, bgColor: AppColors.bgGreenColor, true, route: null, onTap: () async { HmgServicesComponentModel(
5, LocaleKeys.completeCheckup.tr(), "", AppAssets.comprehensiveCheckup, bgColor: AppColors.bgGreenColor, true, route: null, onTap: () async {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.comprehensiveCheckupPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.comprehensiveCheckupPage);
} else { } else {
@ -131,7 +139,7 @@ class ServicesPage extends StatelessWidget {
}, },
), ),
HmgServicesComponentModel( HmgServicesComponentModel(
11, LocaleKeys.eReferralServices.tr(), "", AppAssets.eReferral, bgColor: AppColors.eReferralCardColor, true, route: null, onTap: () async { 11, LocaleKeys.eReferralServices.tr(), "", AppAssets.eReferral, bgColor: AppColors.eReferralCardColor, true, route: null, onTap: () async {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.eReferralPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.eReferralPage);
} else { } else {
@ -387,19 +395,19 @@ class ServicesPage extends StatelessWidget {
? CustomButton( ? CustomButton(
height: 40.h, height: 40.h,
icon: AppAssets.recharge_icon, icon: AppAssets.recharge_icon,
iconSize: 16.w, iconSize: 16.w,
iconColor: AppColors.infoColor, iconColor: AppColors.infoColor,
textColor: AppColors.infoColor, textColor: AppColors.infoColor,
text: LocaleKeys.recharge.tr(), text: LocaleKeys.recharge.tr(),
borderWidth: 0.w, borderWidth: 0.w,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderColor: Colors.transparent, borderColor: Colors.transparent,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08), backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w), padding: EdgeInsets.all(8.w),
fontSize: 12.f, fontSize: 12.f,
onPressed: () { onPressed: () {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
}, },
) )
: SizedBox.shrink(), : SizedBox.shrink(),
], ],
@ -438,60 +446,60 @@ class ServicesPage extends StatelessWidget {
getIt.get<AppState>().isAuthenticated getIt.get<AppState>().isAuthenticated
? Wrap( ? Wrap(
spacing: -8.h, spacing: -8.h,
// runSpacing: 0.h, // runSpacing: 0.h,
children: [ children: [
Utils.buildImgWithAssets( Utils.buildImgWithAssets(
icon: AppAssets.babyGirlImg, icon: AppAssets.babyGirlImg,
height: 28.h, height: 28.h,
width: 28.w, width: 28.w,
border: 1, border: 1,
fit: BoxFit.contain, fit: BoxFit.contain,
borderRadius: 50.r, borderRadius: 50.r,
), ),
Utils.buildImgWithAssets( Utils.buildImgWithAssets(
icon: AppAssets.femaleImg, icon: AppAssets.femaleImg,
height: 28.h, height: 28.h,
width: 28.w, width: 28.w,
border: 1, border: 1,
borderRadius: 50.r, borderRadius: 50.r,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
Utils.buildImgWithAssets( Utils.buildImgWithAssets(
icon: AppAssets.maleImg, icon: AppAssets.maleImg,
height: 28.h, height: 28.h,
width: 28.w, width: 28.w,
border: 1, border: 1,
borderRadius: 50.r, borderRadius: 50.r,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
], ],
) )
: LocaleKeys.loginToViewMedicalFile.tr().toText12(fontWeight: FontWeight.w500, maxLine: 2), : LocaleKeys.loginToViewMedicalFile.tr().toText12(fontWeight: FontWeight.w500, maxLine: 2),
Spacer(), Spacer(),
getIt.get<AppState>().isAuthenticated getIt.get<AppState>().isAuthenticated
? CustomButton( ? CustomButton(
height: 40.h, height: 40.h,
icon: AppAssets.add_icon, icon: AppAssets.add_icon,
iconSize: 16.w, iconSize: 16.w,
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
text: LocaleKeys.addMember.tr(), text: LocaleKeys.addMember.tr(),
borderWidth: 0.w, borderWidth: 0.w,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderColor: Colors.transparent, borderColor: Colors.transparent,
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08), backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w), padding: EdgeInsets.all(8.w),
fontSize: 12.f, fontSize: 12.f,
onPressed: () { onPressed: () {
DialogService dialogService = getIt.get<DialogService>(); DialogService dialogService = getIt.get<DialogService>();
medicalFileViewModel.clearAuthValues(); medicalFileViewModel.clearAuthValues();
dialogService.showAddFamilyFileSheet( dialogService.showAddFamilyFileSheet(
label: LocaleKeys.addFamilyMember.tr(), label: LocaleKeys.addFamilyMember.tr(),
message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(), message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(),
onVerificationPress: () { onVerificationPress: () {
medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
}); });
}, },
) )
: SizedBox.shrink(), : SizedBox.shrink(),
], ],

@ -1,4 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/home/data/service_card_data.dart'; import 'package:hmg_patient_app_new/presentation/home/data/service_card_data.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
@ -7,8 +9,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "emergency", serviceName: "emergency",
icon: AppAssets.emergency_services_icon, icon: AppAssets.emergency_services_icon,
title: "Emergency", title: LocaleKeys.emergency,
subtitle: "Services", subtitle: LocaleKeys.services2,
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
@ -17,8 +19,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "indoor_navigation", serviceName: "indoor_navigation",
icon: AppAssets.indoor_nav_icon, icon: AppAssets.indoor_nav_icon,
title: "Indoor", title: LocaleKeys.indoor,
subtitle: "Navigation", subtitle: LocaleKeys.navigation,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -27,8 +29,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "search_doctor", serviceName: "search_doctor",
icon: AppAssets.search_doctor_icon, icon: AppAssets.search_doctor_icon,
title: "Search", title: LocaleKeys.search,
subtitle: "Doctor", subtitle: LocaleKeys.doctor,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -37,8 +39,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "health_calculators_and_converts", serviceName: "health_calculators_and_converts",
icon: AppAssets.health_calculators_icon, icon: AppAssets.health_calculators_icon,
title: "Health", title: LocaleKeys.health,
subtitle: "Calculators", subtitle: LocaleKeys.calculators,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -47,8 +49,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "health_converters", serviceName: "health_converters",
icon: AppAssets.health_converters_icon, icon: AppAssets.health_converters_icon,
title: "Health", title: LocaleKeys.health,
subtitle: "Converters", subtitle: LocaleKeys.converters,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -57,8 +59,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "parking_guide", serviceName: "parking_guide",
icon: AppAssets.car_parking_icon, icon: AppAssets.car_parking_icon,
title: "Parking", title: LocaleKeys.parking,
subtitle: "Guide", subtitle: LocaleKeys.guide,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -70,8 +72,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "emergency", serviceName: "emergency",
icon: AppAssets.emergency_services_icon, icon: AppAssets.emergency_services_icon,
title: "Emergency", title: LocaleKeys.emergency,
subtitle: "Services", subtitle: LocaleKeys.services2,
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
@ -80,8 +82,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "lab_results", serviceName: "lab_results",
icon: AppAssets.home_lab_result_icon, icon: AppAssets.home_lab_result_icon,
title: "Lab", title: LocaleKeys.lab,
subtitle: "Results", subtitle: LocaleKeys.labSubtitle,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -90,8 +92,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "radiology_results", serviceName: "radiology_results",
icon: AppAssets.my_radiology_icon, icon: AppAssets.my_radiology_icon,
title: "Radiology", title: LocaleKeys.radiology,
subtitle: "Results", subtitle: LocaleKeys.radiologySubtitle,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -100,8 +102,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "prescriptions", serviceName: "prescriptions",
icon: AppAssets.my_prescription_icon, icon: AppAssets.my_prescription_icon,
title: "Prescriptions", title: LocaleKeys.medicinesSubtitle,
subtitle: "Details", subtitle: LocaleKeys.details,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -110,8 +112,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "insurance_update", serviceName: "insurance_update",
icon: AppAssets.insurance_update_icon, icon: AppAssets.insurance_update_icon,
title: "Insurance", title: LocaleKeys.insurance,
subtitle: "Details", subtitle: LocaleKeys.details,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -130,8 +132,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "sick_leaves", serviceName: "sick_leaves",
icon: AppAssets.my_sick_leave_icon, icon: AppAssets.my_sick_leave_icon,
title: "Sick", title: LocaleKeys.sick,
subtitle: "Leaves", subtitle: LocaleKeys.sickSubtitle,
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
iconColor: AppColors.blackColor, iconColor: AppColors.blackColor,
textColor: AppColors.blackColor, textColor: AppColors.blackColor,
@ -143,8 +145,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "livecare", serviceName: "livecare",
icon: AppAssets.small_livecare_icon, icon: AppAssets.small_livecare_icon,
title: "LiveCare", title: LocaleKeys.liveCare,
subtitle: "Explore our app, View our services and offers", subtitle: LocaleKeys.liveCareServiceDesc,
largeCardIcon: AppAssets.liveCareService, largeCardIcon: AppAssets.liveCareService,
backgroundColor: AppColors.successColor, backgroundColor: AppColors.successColor,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
@ -161,8 +163,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "home_health_care", serviceName: "home_health_care",
icon: AppAssets.homeBottom, icon: AppAssets.homeBottom,
title: "Home Health Care", title: LocaleKeys.homeHealthCare,
subtitle: "Explore our app, View our services and offers", subtitle: LocaleKeys.liveCareServiceDesc,
largeCardIcon: AppAssets.homeHealthCareService, largeCardIcon: AppAssets.homeHealthCareService,
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
iconColor: AppColors.whiteColor, iconColor: AppColors.whiteColor,
@ -171,8 +173,8 @@ class LandingPageData {
ServiceCardData( ServiceCardData(
serviceName: "pharmacy", serviceName: "pharmacy",
icon: AppAssets.pharmacy_icon, //359846 icon: AppAssets.pharmacy_icon, //359846
title: "Pharmacy", title: LocaleKeys.hmgPharmacy,
subtitle: "Explore our app, View our services and offers", subtitle: LocaleKeys.liveCareServiceDesc,
largeCardIcon: AppAssets.pharmacyService, largeCardIcon: AppAssets.pharmacyService,
backgroundColor: AppColors.pharmacyBGColor, backgroundColor: AppColors.pharmacyBGColor,
iconColor: null, iconColor: null,

@ -28,7 +28,6 @@ import 'package:hmg_patient_app_new/features/my_appointments/appointment_rating_
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/notifications/notifications_view_model.dart'; import 'package:hmg_patient_app_new/features/notifications/notifications_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart'; import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/appointment_queue_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/appointment_queue_page.dart';
@ -62,8 +61,6 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../active_medication/active_medication_page.dart';
import '../emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart'; import '../emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart';
class LandingPage extends StatefulWidget { class LandingPage extends StatefulWidget {
@ -198,10 +195,11 @@ class _LandingPageState extends State<LandingPage> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
spacing: 12.h, spacing: 12.h,
children: [ children: [
Stack(children: [ appState.isAuthenticated
Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h).onPress(() async { ? Stack(children: [
if (appState.isAuthenticated) { Utils.buildSvgWithAssets(icon: AppAssets.bell, height: 18.h, width: 18.h).onPress(() async {
notificationsViewModel.setNotificationStatusID(2); if (appState.isAuthenticated) {
notificationsViewModel.setNotificationStatusID(2);
notificationsViewModel.getAllNotifications(); notificationsViewModel.getAllNotifications();
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
@ -236,7 +234,8 @@ class _LandingPageState extends State<LandingPage> {
), ),
) )
: SizedBox.shrink(), : SizedBox.shrink(),
]), ])
: SizedBox.shrink(),
Utils.buildSvgWithAssets(icon: AppAssets.indoor_nav_icon, height: 18.h, width: 18.h).onPress(() { Utils.buildSvgWithAssets(icon: AppAssets.indoor_nav_icon, height: 18.h, width: 18.h).onPress(() {
openIndoorNavigationBottomSheet(context); openIndoorNavigationBottomSheet(context);
}), }),
@ -249,6 +248,11 @@ class _LandingPageState extends State<LandingPage> {
isFullScreen: false, isFullScreen: false,
); );
}), }),
!appState.isAuthenticated
? Utils.buildSvgWithAssets(icon: appState.isArabic() ? AppAssets.enLangIcon : AppAssets.arLangIcon, height: 18.h, width: 18.h).onPress(() {
context.setLocale(appState.isArabic() ? Locale('en', 'US') : Locale('ar', 'SA'));
})
: SizedBox.shrink()
], ],
); );
}), }),
@ -305,7 +309,7 @@ class _LandingPageState extends State<LandingPage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"Appointments & Visits".toText16(isBold: true), LocaleKeys.appointmentsAndVisits.tr(context: context).toText16(isBold: true),
Row( Row(
children: [ children: [
LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor), LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor),
@ -394,22 +398,23 @@ class _LandingPageState extends State<LandingPage> {
layout: SwiperLayout.STACK, layout: SwiperLayout.STACK,
loop: true, loop: true,
itemWidth: MediaQuery.of(context).size.width - 48.h, itemWidth: MediaQuery.of(context).size.width - 48.h,
indicatorLayout: PageIndicatorLayout.COLOR, indicatorLayout: PageIndicatorLayout.COLOR,
axisDirection: AxisDirection.right, axisDirection: AxisDirection.right,
controller: _controller, controller: _controller,
itemHeight: 255.h, itemHeight: 255.h,
pagination: SwiperPagination( pagination: SwiperPagination(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
margin: EdgeInsets.only(top: 240.h + 8 + 24), margin: EdgeInsets.only(top: 240.h + 8 + 24),
builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor),
), ),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return getIndexSwiperCard(index); return getIndexSwiperCard(index);
}, },
) )
: Container( : Container(
width: double.infinity, width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true), decoration: RoundedRectangleBorder()
.toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Padding( child: Padding(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
child: Column( child: Column(
@ -465,11 +470,15 @@ class _LandingPageState extends State<LandingPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: "ER Online Check-In Request", labelText: LocaleKeys.erOnlineCheckInRequest.tr(context: context),
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.10), backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.10),
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
), ),
Utils.buildSvgWithAssets(icon: AppAssets.appointment_checkin_icon, width: 24.h, height: 24.h, iconColor: AppColors.primaryRedColor), Utils.buildSvgWithAssets(
icon: AppAssets.appointment_checkin_icon,
width: 24.h,
height: 24.h,
iconColor: AppColors.primaryRedColor),
], ],
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -597,10 +606,10 @@ class _LandingPageState extends State<LandingPage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"Services".toText16(isBold: true), LocaleKeys.services2.tr(context: context).toText16(isBold: true),
Row( Row(
children: [ children: [
"View all services".toText12(color: AppColors.primaryRedColor), LocaleKeys.viewAllServices.tr(context: context).toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h), SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],
@ -690,10 +699,18 @@ class _LandingPageState extends State<LandingPage> {
myAppointmentsViewModel.patientQueueDetailsList.first.queueNo!.toText12(isBold: true), myAppointmentsViewModel.patientQueueDetailsList.first.queueNo!.toText12(isBold: true),
SizedBox(width: 8.w), SizedBox(width: 8.w),
AppCustomChipWidget( AppCustomChipWidget(
deleteIcon: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1 ? AppAssets.call_for_vitals : AppAssets.call_for_doctor, deleteIcon: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1
labelText: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1 ? LocaleKeys.callForVitalSigns.tr() : LocaleKeys.callForDoctor.tr(), ? AppAssets.call_for_vitals
iconColor: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1 ? AppColors.primaryRedColor : AppColors.successColor, : AppAssets.call_for_doctor,
textColor: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1 ? AppColors.primaryRedColor : AppColors.successColor, labelText: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1
? LocaleKeys.callForVitalSigns.tr()
: LocaleKeys.callForDoctor.tr(),
iconColor: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1
? AppColors.primaryRedColor
: AppColors.successColor,
textColor: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1
? AppColors.primaryRedColor
: AppColors.successColor,
iconSize: 14.w, iconSize: 14.w,
backgroundColor: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1 backgroundColor: myAppointmentsViewModel.patientQueueDetailsList.first.callType == 1
? AppColors.primaryRedColor.withValues(alpha: 0.1) ? AppColors.primaryRedColor.withValues(alpha: 0.1)
@ -707,7 +724,8 @@ class _LandingPageState extends State<LandingPage> {
: SizedBox(height: 12.h), : SizedBox(height: 12.h),
SizedBox(height: 5.h), SizedBox(height: 5.h),
CustomButton( CustomButton(
text: Utils.getCardButtonText(myAppointmentsViewModel.currentQueueStatus, myAppointmentsViewModel.currentPatientQueueDetails.roomNo ?? ""), text: Utils.getCardButtonText(
myAppointmentsViewModel.currentQueueStatus, myAppointmentsViewModel.currentPatientQueueDetails.roomNo ?? ""),
onPressed: () {}, onPressed: () {},
backgroundColor: Utils.getCardButtonColor(myAppointmentsViewModel.currentQueueStatus), backgroundColor: Utils.getCardButtonColor(myAppointmentsViewModel.currentQueueStatus),
borderColor: Utils.getCardButtonColor(myAppointmentsViewModel.currentQueueStatus).withValues(alpha: 0.01), borderColor: Utils.getCardButtonColor(myAppointmentsViewModel.currentQueueStatus).withValues(alpha: 0.01),
@ -761,7 +779,8 @@ class _LandingPageState extends State<LandingPage> {
SizedBox(width: 8.w), SizedBox(width: 8.w),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.appointment_calendar_icon, icon: AppAssets.appointment_calendar_icon,
labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(immediateLiveCareViewModel.patientLiveCareHistoryList[0].arrivalTime), false)), labelText: DateUtil.formatDateToDate(
DateUtil.convertStringToDate(immediateLiveCareViewModel.patientLiveCareHistoryList[0].arrivalTime), false)),
], ],
), ),
Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h),
@ -769,9 +788,12 @@ class _LandingPageState extends State<LandingPage> {
], ],
), ),
SizedBox(height: 10.h), SizedBox(height: 10.h),
LocaleKeys.halaFirstName.tr(namedArgs: {'firstName': appState.getAuthenticatedUser()!.firstName!}, context: context).toText16(isBold: true), LocaleKeys.halaFirstName
.tr(namedArgs: {'firstName': appState.getAuthenticatedUser()!.firstName!}, context: context).toText16(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.yourTurnIsAfterPatients.tr(namedArgs: {'count': immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount.toString()}, context: context).toText14(isBold: true), LocaleKeys.yourTurnIsAfterPatients.tr(
namedArgs: {'count': immediateLiveCareViewModel.patientLiveCareHistoryList[0].patCount.toString()},
context: context).toText14(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -840,7 +862,7 @@ class _LandingPageState extends State<LandingPage> {
hasShadow: true, hasShadow: true,
), ),
child: AppointmentCard( child: AppointmentCard(
patientAppointmentHistoryResponseModel: myAppointmentsViewModel.patientUpcomingAppointmentsHistoryList.first, patientAppointmentHistoryResponseModel: myAppointmentsViewModel.patientAppointmentsHistoryList.first,
myAppointmentsViewModel: myAppointmentsViewModel, myAppointmentsViewModel: myAppointmentsViewModel,
bookAppointmentsViewModel: bookAppointmentsViewModel, bookAppointmentsViewModel: bookAppointmentsViewModel,
isLoading: false, isLoading: false,
@ -886,7 +908,7 @@ class _LandingPageState extends State<LandingPage> {
} }
} else if (index == 2) { } else if (index == 2) {
if ((myAppointmentsViewModel.isPatientHasQueueAppointment || immediateLiveCareViewModel.patientHasPendingLiveCareRequest) && if ((myAppointmentsViewModel.isPatientHasQueueAppointment || immediateLiveCareViewModel.patientHasPendingLiveCareRequest) &&
myAppointmentsViewModel.patientUpcomingAppointmentsHistoryList.isNotEmpty) { todoSectionViewModel.patientAncillaryOrdersList.isNotEmpty) {
return AncillaryOrderCard( return AncillaryOrderCard(
order: todoSectionViewModel.patientAncillaryOrdersList.first, order: todoSectionViewModel.patientAncillaryOrdersList.first,
isLoading: false, isLoading: false,
@ -978,7 +1000,6 @@ class _LandingPageState extends State<LandingPage> {
isCloseButtonVisible: true, isCloseButtonVisible: true,
child: StatefulBuilder( child: StatefulBuilder(
builder: (context, setState) { builder: (context, setState) {
return RateAppointmentDoctor(); return RateAppointmentDoctor();
}, },
), ),

@ -8,11 +8,8 @@ import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/hmg_services/services_page.dart'; import 'package:hmg_patient_app_new/presentation/hmg_services/services_page.dart';
import 'package:hmg_patient_app_new/presentation/home/landing_page.dart'; import 'package:hmg_patient_app_new/presentation/home/landing_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection.dart';
import 'package:hmg_patient_app_new/presentation/todo_section/todo_page.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart'; import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
class LandingNavigation extends StatefulWidget { class LandingNavigation extends StatefulWidget {
const LandingNavigation({super.key}); const LandingNavigation({super.key});
@ -53,11 +50,7 @@ class _LandingNavigationState extends State<LandingNavigation> {
} }
if (_currentIndex == 3) { if (_currentIndex == 3) {
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
Navigator.of(context).push( context.navigateWithName(AppRoutes.userInfoSelection);
CustomPageRoute(
page: UserInfoSelectionScreen(),
),
);
} else { } else {
Utils.openWebView( Utils.openWebView(
url: 'https://x.com/HMG', url: 'https://x.com/HMG',

@ -23,10 +23,10 @@ class HabibWalletCard extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"My Balance".toText16(isBold: true), LocaleKeys.myBalance.tr(context: context).toText16(isBold: true),
Row( Row(
children: [ children: [
"View all services".toText12(color: AppColors.primaryRedColor), LocaleKeys.viewAllServices.tr(context: context).toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h), SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],
@ -54,7 +54,7 @@ class HabibWalletCard extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
"Habib Wallet".toText15(isBold: true), LocaleKeys.habibWallet.tr(context: context).toText15(isBold: true),
Container( Container(
height: 40.h, height: 40.h,
width: 40.h, width: 40.h,
@ -94,7 +94,7 @@ class HabibWalletCard extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 50.h), padding: EdgeInsets.symmetric(horizontal: 50.h),
child: Row( child: Row(
children: [ children: [
"View details".toText12(color: AppColors.primaryRedColor), LocaleKeys.viewDetails.tr(context: context).toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h), SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],

@ -89,16 +89,15 @@ class LargeServiceCard extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
serviceCardData.title.toText14(isBold: true, color: AppColors.textColor), serviceCardData.title.tr(context: context).toText14(isBold: true, color: AppColors.textColor),
SizedBox(width: 6.h), serviceCardData.subtitle.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
serviceCardData.subtitle.toText14(weight: FontWeight.w500, color: AppColors.textColorLight),
], ],
), ),
), ),
], ],
).paddingSymmetrical(16.w, 20.h), ).paddingSymmetrical(12.w, 24.h),
CustomButton( CustomButton(
text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr() : LocaleKeys.bookNow.tr(context: context), text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context),
onPressed: () { onPressed: () {
handleOnTap(); handleOnTap();
}, },

@ -65,8 +65,8 @@ class SmallServiceCard extends StatelessWidget {
children: [ children: [
Utils.buildSvgWithAssets(icon: icon, iconColor: iconColor, width: 32.h, height: 32.h), Utils.buildSvgWithAssets(icon: icon, iconColor: iconColor, width: 32.h, height: 32.h),
SizedBox(height: 6.h), SizedBox(height: 6.h),
title.toText11(color: textColor, isBold: isBold, isCenter: true), title.tr(context: context).toText11(color: textColor, isBold: isBold, isCenter: true),
subtitle.toText11(color: textColor, isBold: isBold, isCenter: true), subtitle.tr(context: context).toText11(color: textColor, isBold: isBold, isCenter: true),
], ],
), ),
), ),
@ -173,7 +173,7 @@ class SmallServiceCard extends StatelessWidget {
void openIndoorNavigationBottomSheet(BuildContext context) { void openIndoorNavigationBottomSheet(BuildContext context) {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
title: LocaleKeys.selectHospital.tr(), title: LocaleKeys.selectHospital.tr(context: context),
context, context,
child: ChangeNotifierProvider( child: ChangeNotifierProvider(
create: (context) => HospitalSelectionBottomSheetViewModel(getIt()), create: (context) => HospitalSelectionBottomSheetViewModel(getIt()),

File diff suppressed because one or more lines are too long

@ -74,7 +74,7 @@ class LabResultDetails extends StatelessWidget {
.getSeverityText( .getSeverityText(
recentLabResult.calculatedResultFlag ?? "", recentLabResult.calculatedResultFlag ?? "",
) )
.tr() .tr(context: context)
.toText10(weight: FontWeight.w500, color: AppColors.greyTextColor), .toText10(weight: FontWeight.w500, color: AppColors.greyTextColor),
Utils.buildSvgWithAssets( Utils.buildSvgWithAssets(
icon: AppAssets.lab_result_indicator, icon: AppAssets.lab_result_indicator,
@ -151,8 +151,8 @@ class LabResultDetails extends StatelessWidget {
children: [ children: [
Text( Text(
labmodel.isGraphVisible labmodel.isGraphVisible
? LocaleKeys.historyFlowchart.tr() ? LocaleKeys.historyFlowchart.tr(context: context)
: LocaleKeys.history.tr(), : LocaleKeys.history.tr(context: context),
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontFamily: 'Poppins', fontFamily: 'Poppins',
@ -181,7 +181,7 @@ class LabResultDetails extends StatelessWidget {
height: 24) height: 24)
.onPress(() { .onPress(() {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
title: LocaleKeys.setTheDateRange.tr(), title: LocaleKeys.setTheDateRange.tr(context: context),
context, context,
child: DateRangeSelector( child: DateRangeSelector(
onRangeSelected: (start, end) { onRangeSelected: (start, end) {

@ -192,7 +192,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
SizedBox(width: 4.h), SizedBox(width: 4.h),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, height: 22.h, width: 22.w) Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, height: 22.h, width: 22.w)
], ],
).withHorizontalPadding(24.w).onPress(() { ).onPress(() {
DialogService dialogService = getIt.get<DialogService>(); DialogService dialogService = getIt.get<DialogService>();
dialogService.showFamilyBottomSheetWithoutH( dialogService.showFamilyBottomSheetWithoutH(
label: LocaleKeys.familyTitle.tr(context: context), label: LocaleKeys.familyTitle.tr(context: context),
@ -276,12 +276,12 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: "${appState.getAuthenticatedUser()!.age} Years Old", labelText: LocaleKeys.ageYearsOld.tr(namedArgs: {'age': '${appState.getAuthenticatedUser()!.age}', 'yearsOld': LocaleKeys.yearsOld.tr(context: context)}, context: context),
labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w), labelPadding: EdgeInsetsDirectional.only(start: 8.w, end: 8.w),
), ),
AppCustomChipWidget( AppCustomChipWidget(
icon: AppAssets.blood_icon, icon: AppAssets.blood_icon,
labelText: "Blood: ${appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup}", labelText: LocaleKeys.bloodGroup.tr(namedArgs: {'bloodType': appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup}, context: context),
iconColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor,
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -319,7 +319,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
LocaleKeys.vitalSigns.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2), LocaleKeys.vitalSigns.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
Row( Row(
children: [ children: [
LocaleKeys.viewAll.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
SizedBox(width: 2.h), SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],
@ -359,7 +359,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
children: [ children: [
Utils.buildSvgWithAssets(icon: AppAssets.call_for_vitals, width: 32.h, height: 32.h), Utils.buildSvgWithAssets(icon: AppAssets.call_for_vitals, width: 32.h, height: 32.h),
SizedBox(height: 12.h), SizedBox(height: 12.h),
LocaleKeys.noVitalSignsRecordedYet.tr().toText12(isCenter: true), LocaleKeys.noVitalSignsRecordedYet.tr(context: context).toText12(isCenter: true),
], ],
), ),
), ),
@ -439,14 +439,14 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
itemPadding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.h), itemPadding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.h),
items: [ items: [
ExpandableListItem( ExpandableListItem(
title: "Medical Services".toText18(weight: FontWeight.w600), title: LocaleKeys.medicalServices.tr(context: context).toText18(weight: FontWeight.w600),
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 10.h),
getSelectedTabData(0), getSelectedTabData(0),
], ],
), ),
ExpandableListItem( ExpandableListItem(
title: "Medical Reports".toText18( title: LocaleKeys.medicalReports.tr(context: context).toText18(
weight: FontWeight.w600, weight: FontWeight.w600,
), ),
expandedBackgroundColor: Colors.transparent, expandedBackgroundColor: Colors.transparent,
@ -455,7 +455,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
getSelectedTabData(2), getSelectedTabData(2),
]), ]),
ExpandableListItem( ExpandableListItem(
title: "Insurance & Payments".toText18(weight: FontWeight.w600), title: LocaleKeys.insuranceAndPayments.tr(context: context).toText18(weight: FontWeight.w600),
expandedBackgroundColor: Colors.transparent, expandedBackgroundColor: Colors.transparent,
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 10.h),
@ -463,7 +463,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
), ),
ExpandableListItem( ExpandableListItem(
title: "Tracker & Others".toText18(weight: FontWeight.w600), title: LocaleKeys.trackerAndOthers.tr(context: context).toText18(weight: FontWeight.w600),
expandedBackgroundColor: Colors.transparent, expandedBackgroundColor: Colors.transparent,
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 10.h),
@ -577,10 +577,10 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.appointmentsAndVisits.tr().toText16(weight: FontWeight.w500, letterSpacing: -0.2), LocaleKeys.appointmentsAndVisits.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
Row( Row(
children: [ children: [
LocaleKeys.viewAll.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
SizedBox(width: 2.h), SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],
@ -645,6 +645,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
shrinkWrap: true, shrinkWrap: true,
itemCount: myAppointmentsVM.patientAppointmentsHistoryList.length, itemCount: myAppointmentsVM.patientAppointmentsHistoryList.length,
padding: EdgeInsets.zero,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
@ -699,12 +700,12 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
), ),
)); ));
}, },
separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.h), separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 12.w),
), ),
).paddingSymmetrical(0.w, 0.h); );
}), }),
SizedBox(height: 10.h), SizedBox(height: 10.h),
LocaleKeys.labAndRadiology.tr().toText16(weight: FontWeight.w500, letterSpacing: -0.2), LocaleKeys.labAndRadiology.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( Row(
children: [ children: [
@ -743,7 +744,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
).paddingSymmetrical(0.w, 0.h), ).paddingSymmetrical(0.w, 0.h),
SizedBox(height: 24.h), SizedBox(height: 24.h),
LocaleKeys.activeMedicationsAndPrescriptions.tr().toText16(weight: FontWeight.w500, letterSpacing: -0.2), LocaleKeys.activeMedicationsAndPrescriptions.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) { Consumer<PrescriptionsViewModel>(builder: (context, prescriptionVM, child) {
return prescriptionVM.isPrescriptionsOrdersLoading return prescriptionVM.isPrescriptionsOrdersLoading
@ -901,7 +902,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
LocaleKeys.myDoctor.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2), LocaleKeys.myDoctor.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
Row( Row(
children: [ children: [
LocaleKeys.viewAll.tr().toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500), LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
SizedBox(width: 2.w), SizedBox(width: 2.w),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
], ],
@ -1351,7 +1352,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( Row(
children: [ children: [
LocaleKeys.others.tr().toText16(weight: FontWeight.w500, color: AppColors.textColor), LocaleKeys.others.tr(context: context).toText16(weight: FontWeight.w500, color: AppColors.textColor),
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -1484,7 +1485,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Expanded( Expanded(
child: _buildVitalSignCard( child: _buildVitalSignCard(
icon: AppAssets.bmiVital, icon: AppAssets.bmiVital,
label: "BMI", label: LocaleKeys.bmi.tr(context: context),
value: vitalSign.bodyMassIndex?.toString() ?? '--', value: vitalSign.bodyMassIndex?.toString() ?? '--',
unit: '', unit: '',
status: vitalSign.bodyMassIndex != null ? _getBMIStatus(vitalSign.bodyMassIndex) : null, status: vitalSign.bodyMassIndex != null ? _getBMIStatus(vitalSign.bodyMassIndex) : null,
@ -1495,7 +1496,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Expanded( Expanded(
child: _buildVitalSignCard( child: _buildVitalSignCard(
icon: AppAssets.heightVital, icon: AppAssets.heightVital,
label: "Height", label: LocaleKeys.height.tr(context: context),
value: vitalSign.heightCm?.toString() ?? '--', value: vitalSign.heightCm?.toString() ?? '--',
unit: 'cm', unit: 'cm',
status: null, status: null,
@ -1511,7 +1512,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Expanded( Expanded(
child: _buildVitalSignCard( child: _buildVitalSignCard(
icon: AppAssets.weightVital, icon: AppAssets.weightVital,
label: "Weight", label: LocaleKeys.weight.tr(context: context),
value: vitalSign.weightKg?.toString() ?? '--', value: vitalSign.weightKg?.toString() ?? '--',
unit: 'kg', unit: 'kg',
status: vitalSign.weightKg != null ? "Normal" : null, status: vitalSign.weightKg != null ? "Normal" : null,
@ -1522,7 +1523,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
Expanded( Expanded(
child: _buildVitalSignCard( child: _buildVitalSignCard(
icon: AppAssets.bloodPressure, icon: AppAssets.bloodPressure,
label: "Blood Pressure", label: LocaleKeys.bloodPressure.tr(context: context),
value: vitalSign.bloodPressureLower != null && vitalSign.bloodPressureHigher != null value: vitalSign.bloodPressureLower != null && vitalSign.bloodPressureHigher != null
? "${vitalSign.bloodPressureHigher}/${vitalSign.bloodPressureLower}" ? "${vitalSign.bloodPressureHigher}/${vitalSign.bloodPressureLower}"
: '--', : '--',

@ -117,8 +117,8 @@ class ProfileSettingsState extends State<ProfileSettings> {
onAddFamilyMemberPress: () { onAddFamilyMemberPress: () {
DialogService dialogService = getIt.get<DialogService>(); DialogService dialogService = getIt.get<DialogService>();
dialogService.showAddFamilyFileSheet( dialogService.showAddFamilyFileSheet(
label: LocaleKeys.addFamilyMember.tr(), label: LocaleKeys.addFamilyMember.tr(context: context),
message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(), message: LocaleKeys.pleaseFillBelowFieldToAddNewFamilyMember.tr(context: context),
onVerificationPress: () { onVerificationPress: () {
medicalVm.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); medicalVm.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms);
}); });
@ -199,18 +199,18 @@ class ProfileSettingsState extends State<ProfileSettings> {
1.divider, 1.divider,
actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () {}), actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () {}),
1.divider, 1.divider,
actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(), () {}, switchValue: true), actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true),
], ],
), ),
), ),
LocaleKeys.personalInformation.tr().toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w), LocaleKeys.personalInformation.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
Container( Container(
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h), margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h), padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column( child: Column(
children: [ children: [
actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(), () {}), actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(context: context), () {}),
// 1.divider, // 1.divider,
// actionItem(AppAssets.smart_phone_fill, "Phone Number".needTranslation, () {}), // actionItem(AppAssets.smart_phone_fill, "Phone Number".needTranslation, () {}),
// 1.divider, // 1.divider,
@ -220,7 +220,7 @@ class ProfileSettingsState extends State<ProfileSettings> {
], ],
), ),
), ),
LocaleKeys.helpAndSupport.tr().toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w), LocaleKeys.helpAndSupport.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
Container( Container(
margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h), margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h),
padding: EdgeInsets.only(top: 4.h, bottom: 4.h), padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
@ -231,9 +231,9 @@ class ProfileSettingsState extends State<ProfileSettings> {
launchUrl(Uri.parse("tel://" + "+966 11 525 9999")); launchUrl(Uri.parse("tel://" + "+966 11 525 9999"));
}, trailingLabel: "011 525 9999"), }, trailingLabel: "011 525 9999"),
1.divider, 1.divider,
actionItem(AppAssets.permission, LocaleKeys.permissions.tr(), () {}, trailingLabel: "Location, Camera"), actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"),
1.divider, 1.divider,
actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(), () { actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(context: context), () {
if (Platform.isAndroid) { if (Platform.isAndroid) {
Utils.openWebView( Utils.openWebView(
url: 'https://play.google.com/store/apps/details?id=com.ejada.hmg', url: 'https://play.google.com/store/apps/details?id=com.ejada.hmg',
@ -245,7 +245,7 @@ class ProfileSettingsState extends State<ProfileSettings> {
} }
}, isExternalLink: true), }, isExternalLink: true),
1.divider, 1.divider,
actionItem(AppAssets.privacy_terms, LocaleKeys.privacyPolicy.tr(), () { actionItem(AppAssets.privacy_terms, LocaleKeys.privacyPolicy.tr(context: context), () {
Utils.openWebView( Utils.openWebView(
url: 'https://hmg.com/en/Pages/Privacy.aspx', url: 'https://hmg.com/en/Pages/Privacy.aspx',
); );
@ -262,7 +262,7 @@ class ProfileSettingsState extends State<ProfileSettings> {
CustomButton( CustomButton(
height: 56.h, height: 56.h,
icon: AppAssets.minus, icon: AppAssets.minus,
text: LocaleKeys.deactivateAccount.tr(), text: LocaleKeys.deactivateAccount.tr(context: context),
onPressed: () {}, onPressed: () {},
).paddingAll(24.w), ).paddingAll(24.w),
], ],
@ -345,7 +345,8 @@ class FamilyCardWidget extends StatelessWidget {
), ),
], ],
).expanded, ).expanded,
Icon(Icons.qr_code, size: 56.h) // Icon(Icons.qr_code, size: 56.h)
Image.network("https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=${profile.responseId.toString()}", fit: BoxFit.contain, height: 56.h, width: 56.w)
], ],
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
@ -420,7 +421,7 @@ class FamilyCardWidget extends StatelessWidget {
), ),
], ],
).paddingOnly(top: 16.h, right: 16.w, left: 16.w, bottom: 12.h), ).paddingOnly(top: 16.h, right: 16.w, left: 16.w, bottom: 12.h),
1.divider, 1.divider.paddingSymmetrical(16.w, 0.h),
_buildActionButton(appState), _buildActionButton(appState),
], ],
), ),
@ -444,7 +445,7 @@ class FamilyCardWidget extends StatelessWidget {
return CustomButton( return CustomButton(
icon: canSwitch ? AppAssets.switch_user : AppAssets.add_family, icon: canSwitch ? AppAssets.switch_user : AppAssets.add_family,
text: canSwitch ? LocaleKeys.switchFamilyFile.tr() : LocaleKeys.addANewFamilyMember.tr(), text: canSwitch ? LocaleKeys.switchAccount.tr() : LocaleKeys.addANewFamilyMember.tr(),
onPressed: canSwitch ? () => onFamilySwitchPress(profile) : onAddFamilyMemberPress, onPressed: canSwitch ? () => onFamilySwitchPress(profile) : onAddFamilyMemberPress,
backgroundColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor, backgroundColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor, borderColor: canSwitch ? AppColors.secondaryLightRedColor : AppColors.primaryRedColor,
@ -460,7 +461,7 @@ class FamilyCardWidget extends StatelessWidget {
return CustomButton( return CustomButton(
icon: AppAssets.switch_user, icon: AppAssets.switch_user,
text: canSwitchBack ? LocaleKeys.switchBackFamilyFile.tr() : LocaleKeys.switchLogin.tr(), text: canSwitchBack ? LocaleKeys.switchBackFamilyFile.tr() : LocaleKeys.switchAccount.tr(),
backgroundColor: canSwitchBack ? AppColors.primaryRedColor : Colors.grey.shade200, backgroundColor: canSwitchBack ? AppColors.primaryRedColor : Colors.grey.shade200,
borderColor: canSwitchBack ? AppColors.primaryRedColor : Colors.grey.shade200, borderColor: canSwitchBack ? AppColors.primaryRedColor : Colors.grey.shade200,
textColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor, textColor: canSwitchBack ? AppColors.whiteColor : AppColors.greyTextColor,

@ -7,7 +7,6 @@ import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@ -44,7 +43,9 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
); );
return; return;
} }
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.pleaseWait.tr(context: context),); LoaderBottomSheet.showLoader(
loadingText: LocaleKeys.pleaseWait.tr(context: context),
);
final String userName = 'guest_user'; final String userName = 'guest_user';
final String password = '123456'; final String password = '123456';
@ -102,7 +103,7 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
width: 32.h, width: 32.h,
height: 32.h, height: 32.h,
), ),
padding: const EdgeInsets.only(left: 12), padding: EdgeInsetsDirectional.only(start: 12),
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
), ),
@ -125,21 +126,32 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
} }
Widget _buildBodyViewer(SymptomsCheckerViewModel viewModel) { Widget _buildBodyViewer(SymptomsCheckerViewModel viewModel) {
return Padding( return GestureDetector(
padding: EdgeInsets.fromLTRB(16.h, 16.h, 16.h, 60.h), onHorizontalDragEnd: (details) {
child: AnimatedSwitcher( // Swipe left or right to toggle view
duration: const Duration(milliseconds: 600), if (details.primaryVelocity != null) {
transitionBuilder: (child, animation) => _build3DFlipTransition(child, animation), if (details.primaryVelocity! < -200 || details.primaryVelocity! > 200) {
switchInCurve: Curves.easeInOut, viewModel.toggleView();
switchOutCurve: Curves.easeInOut, }
child: InteractiveBodyWidget( }
key: ValueKey<BodyView>(viewModel.currentView), },
bodyImageAsset: viewModel.currentView == BodyView.front ? AppAssets.fullBodyFront : AppAssets.fullBodyBack, child: Padding(
organs: viewModel.currentOrgans, padding: EdgeInsets.fromLTRB(16.h, 16.h, 16.h, 60.h),
selectedOrganIds: viewModel.selectedOrganIds, child: AnimatedSwitcher(
onOrganTap: viewModel.toggleOrganSelection, duration: const Duration(milliseconds: 600),
isBodyHidden: viewModel.isBodyHidden, transitionBuilder: (child, animation) => _build3DFlipTransition(child, animation),
tooltipOrganId: viewModel.tooltipOrganId, switchInCurve: Curves.easeInOut,
switchOutCurve: Curves.easeInOut,
child: InteractiveBodyWidget(
key: ValueKey<BodyView>(viewModel.currentView),
bodyImageAsset: viewModel.currentView == BodyView.front ? AppAssets.fullBodyFront : AppAssets.fullBodyBack,
organs: viewModel.currentOrgans,
selectedOrganIds: viewModel.selectedOrganIds,
onOrganTap: viewModel.toggleOrganSelection,
isBodyHidden: viewModel.isBodyHidden,
tooltipOrganId: viewModel.tooltipOrganId,
isArabic: _appState.isArabic(),
),
), ),
), ),
); );
@ -169,8 +181,8 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
} }
Widget _buildViewToggleButtons(SymptomsCheckerViewModel viewModel) { Widget _buildViewToggleButtons(SymptomsCheckerViewModel viewModel) {
return Positioned( return PositionedDirectional(
left: 16.w, start: 16.w,
top: 36.h, top: 36.h,
child: Column( child: Column(
children: [ children: [
@ -275,6 +287,8 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
); );
} }
final isArabic = _appState.isArabic();
return ConstrainedBox( return ConstrainedBox(
constraints: BoxConstraints(maxHeight: 150.h), constraints: BoxConstraints(maxHeight: 150.h),
child: SingleChildScrollView( child: SingleChildScrollView(
@ -284,7 +298,7 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
runSpacing: 8.h, runSpacing: 8.h,
children: viewModel.selectedOrgans.map((organ) { children: viewModel.selectedOrgans.map((organ) {
return AppCustomChipWidget( return AppCustomChipWidget(
labelText: organ.description, labelText: organ.getLocalizedDescription(isArabic),
backgroundColor: AppColors.secondaryLightRedColor, backgroundColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
deleteIcon: AppAssets.cancel, deleteIcon: AppAssets.cancel,
@ -313,8 +327,8 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
} }
Widget _buildExpandCollapseButton(SymptomsCheckerViewModel viewModel) { Widget _buildExpandCollapseButton(SymptomsCheckerViewModel viewModel) {
return Positioned( return PositionedDirectional(
right: 24.w, end: 24.w,
top: -24.h, top: -24.h,
child: GestureDetector( child: GestureDetector(
onTap: viewModel.toggleBottomSheet, onTap: viewModel.toggleBottomSheet,
@ -331,13 +345,16 @@ class _OrganSelectorPageState extends State<OrganSelectorPage> {
borderRadius: 11.r, borderRadius: 11.r,
), ),
child: Center( child: Center(
child: AnimatedRotation( child: Transform.flip(
duration: const Duration(milliseconds: 300), flipX: _appState.isArabic(),
turns: viewModel.isBottomSheetExpanded ? 0.25 : -0.25, child: AnimatedRotation(
child: Utils.buildSvgWithAssets( duration: const Duration(milliseconds: 300),
icon: AppAssets.arrowRight, turns: viewModel.isBottomSheetExpanded ? 0.25 : -0.25,
width: 25.w, child: Utils.buildSvgWithAssets(
height: 25.h, icon: AppAssets.arrowRight,
width: 25.w,
height: 25.h,
),
), ),
), ),
), ),

@ -3,13 +3,14 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/conditions_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/condition_card.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/condition_card.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
@ -45,7 +46,7 @@ class PossibleConditionsPage extends StatelessWidget {
); );
} }
Widget _buildPredictionsList(BuildContext context, List<ConditionsModel> conditions) { Widget _buildPredictionsList(BuildContext context, List<TriageCondition> conditions, List<String> symptoms) {
if (conditions.isEmpty) { if (conditions.isEmpty) {
return Center( return Center(
child: Padding( child: Padding(
@ -74,19 +75,13 @@ class PossibleConditionsPage extends StatelessWidget {
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) => SizedBox(height: 16.h), separatorBuilder: (context, index) => SizedBox(height: 16.h),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final conditionModel = conditions[index]; final condition = conditions[index];
return ConditionCard( return ConditionCard(
icon: conditionModel.icon, condition: condition,
title: conditionModel.title, symptoms: symptoms,
percentage: conditionModel.percentage,
tagText: conditionModel.tagText,
clinic: conditionModel.clinic,
symptoms: conditionModel.symptoms,
description: conditionModel.description,
possibleConditionsSeverityEnum: conditionModel.possibleConditionsSeverityEnum,
onActionPressed: () { onActionPressed: () {
dialogService.showErrorBottomSheet( dialogService.showErrorBottomSheet(
message: 'We are not available for a week. May you Rest In Peace :(', message: 'icd10 Code is ${condition.conditionDetails?.icd10Code}. We need to get the clinics mapped against this code.',
); );
}, },
); );
@ -102,7 +97,7 @@ class PossibleConditionsPage extends StatelessWidget {
title: LocaleKeys.notice.tr(context: context), title: LocaleKeys.notice.tr(context: context),
context, context,
child: Utils.getWarningWidget( child: Utils.getWarningWidget(
loadingText: LocaleKeys.areYouSureYouWantToRestartOrganSelection.tr(context: context), loadingText: LocaleKeys.areYouSureYouWantToExitProgress.tr(context: context),
isShowActionButtons: true, isShowActionButtons: true,
onCancelTap: () => Navigator.pop(context), onCancelTap: () => Navigator.pop(context),
onConfirmTap: () => onConfirm(), onConfirmTap: () => onConfirm(),
@ -113,47 +108,88 @@ class PossibleConditionsPage extends StatelessWidget {
); );
} }
_restartOrganSelection(BuildContext context) async { Widget _buildInfoTile({required PossibleConditionsSeverityEnum severityEnum, required BuildContext context}) {
final symptomsCheckerVm = context.read<SymptomsCheckerViewModel>(); String title;
symptomsCheckerVm.reset(); String description;
context.pop(); Color dotColor;
await Future.delayed(Duration(seconds: 1)).whenComplete(() => context.pop());
}
_navigateToLandingPage() { switch (severityEnum) {
NavigationService navigationService = getIt.get<NavigationService>(); case PossibleConditionsSeverityEnum.monitorOnly:
navigationService.replaceAllRoutesAndNavigateToLanding(); title = LocaleKeys.monitor.tr(context: context);
} description = LocaleKeys.monitorDescription.tr(context: context);
dotColor = AppColors.chipColorMonitor;
break;
case PossibleConditionsSeverityEnum.seekMedicalAdvice:
title = LocaleKeys.seekMedicalAdvice.tr(context: context);
description = LocaleKeys.seekMedicalAdviceDescription.tr(context: context);
dotColor = AppColors.chipColorSeekMedicalAdvice;
break;
case PossibleConditionsSeverityEnum.emergency:
title = LocaleKeys.emergency.tr(context: context);
description = LocaleKeys.emergencyDescription.tr(context: context);
dotColor = AppColors.chipColorEmergency;
break;
}
_buildTrailingSection(BuildContext context) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
height: 40.h, height: 14.h,
padding: EdgeInsets.all(8.w), width: 14.w,
child: Center( decoration: BoxDecoration(shape: BoxShape.circle, color: dotColor),
child: Utils.buildSvgWithAssets( ).paddingOnly(top: 3.h),
icon: AppAssets.refreshIcon, SizedBox(width: 8.w),
height: 20.h, Expanded(
width: 20.w, child: Column(
iconColor: AppColors.textColor, crossAxisAlignment: CrossAxisAlignment.start,
), children: [
title.toText14(weight: FontWeight.w600, color: AppColors.textColor),
SizedBox(height: 4.h),
description.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
],
), ),
).onPress(() => _buildConfirmationBottomSheet(context: context, onConfirm: () => _restartOrganSelection(context))), ),
Container(
height: 40.h,
padding: EdgeInsets.all(8.w),
child: Center(
child: Utils.buildSvgWithAssets(
icon: AppAssets.homeBorderedIcon,
height: 20.h,
width: 20.w,
iconColor: AppColors.textColor,
),
),
).onPress(() => _buildConfirmationBottomSheet(context: context, onConfirm: () => _navigateToLandingPage())),
], ],
).paddingSymmetrical(20.w, 0); );
}
_buildSeverityDetailsBottomsheet({required BuildContext context}) {
return showCommonBottomSheetWithoutHeight(
title: LocaleKeys.colorScience.tr(context: context),
context,
child: Container(
padding: EdgeInsets.all(16.w),
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column(
children: [
_buildInfoTile(severityEnum: PossibleConditionsSeverityEnum.monitorOnly, context: context),
Divider(color: AppColors.bottomNAVBorder, height: 24.h, thickness: 1),
_buildInfoTile(severityEnum: PossibleConditionsSeverityEnum.seekMedicalAdvice, context: context),
Divider(color: AppColors.bottomNAVBorder, height: 24.h, thickness: 1),
_buildInfoTile(severityEnum: PossibleConditionsSeverityEnum.emergency, context: context),
],
),
),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
_buildTrailingSection(BuildContext context) {
return Container(
height: 40.h,
padding: EdgeInsets.all(8.w),
child: Center(
child: Utils.buildSvgWithAssets(
icon: AppAssets.coloredDotsIcon,
height: 20.h,
width: 20.w,
),
),
).onPress(() => _buildSeverityDetailsBottomsheet(context: context));
} }
@override @override
@ -162,13 +198,32 @@ class PossibleConditionsPage extends StatelessWidget {
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: LocaleKeys.possibleConditions.tr(context: context), title: LocaleKeys.possibleConditions.tr(context: context),
leadingCallback: () => _buildConfirmationBottomSheet(
context: context,
onConfirm: () {
context.pop();
final SymptomsCheckerViewModel symptomsCheckerViewModel = context.read<SymptomsCheckerViewModel>();
symptomsCheckerViewModel.reset(); // Clear all symptoms checker data
final navigationService = getIt.get<NavigationService>();
navigationService.replaceAllRoutesAndNavigateToLanding();
},
),
trailing: _buildTrailingSection(context), trailing: _buildTrailingSection(context),
child: Consumer<SymptomsCheckerViewModel>( child: Consumer<SymptomsCheckerViewModel>(
builder: (context, symptomsCheckerViewModel, child) { builder: (context, symptomsCheckerViewModel, child) {
if (symptomsCheckerViewModel.isPossibleConditionsLoading || symptomsCheckerViewModel.isPossibleConditionsLoading) { if (symptomsCheckerViewModel.isPossibleConditionsLoading || symptomsCheckerViewModel.isTriageDiagnosisLoading) {
return _buildLoadingShimmer(); return _buildLoadingShimmer();
} }
return _buildPredictionsList(context, dummyConditions); // Get conditions directly from ViewModel
final conditions = symptomsCheckerViewModel.currentConditions ?? [];
// Get selected symptoms names for display
final symptoms = symptomsCheckerViewModel
.getAllSelectedSymptoms()
.map((s) => s.commonName ?? s.name ?? '')
.where((name) => name.isNotEmpty)
.take(3)
.toList();
return _buildPredictionsList(context, conditions, symptoms);
}, },
), ),
), ),

@ -3,6 +3,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
@ -25,11 +26,13 @@ class RiskFactorsScreen extends StatefulWidget {
class _RiskFactorsScreenState extends State<RiskFactorsScreen> { class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
late DialogService dialogService; late DialogService dialogService;
late AppState _appState;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
dialogService = getIt<DialogService>(); dialogService = getIt<DialogService>();
_appState = getIt<AppState>();
// Fetch risk factors based on selected symptoms // Fetch risk factors based on selected symptoms
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
final viewModel = context.read<SymptomsCheckerViewModel>(); final viewModel = context.read<SymptomsCheckerViewModel>();
@ -90,6 +93,8 @@ class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
} }
Widget _buildRiskFactorsList(SymptomsCheckerViewModel viewModel) { Widget _buildRiskFactorsList(SymptomsCheckerViewModel viewModel) {
final isArabic = _appState.isArabic();
return Container( return Container(
key: ValueKey<int>(viewModel.riskFactorsList.length), key: ValueKey<int>(viewModel.riskFactorsList.length),
width: double.infinity, width: double.infinity,
@ -100,7 +105,7 @@ class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
...viewModel.riskFactorsList.map((factor) { ...viewModel.riskFactorsList.map((factor) {
return _buildRiskFactorItem(viewModel, factor.id ?? '', factor.getDisplayName()); return _buildRiskFactorItem(viewModel, factor.id ?? '', factor.getDisplayName(isArabic: isArabic));
}), }),
SizedBox(height: 12.w), SizedBox(height: 12.w),
Row( Row(
@ -196,7 +201,7 @@ class _RiskFactorsScreenState extends State<RiskFactorsScreen> {
border: Border.all(color: AppColors.bottomNAVBorder, width: 1), border: Border.all(color: AppColors.bottomNAVBorder, width: 1),
), ),
child: Text( child: Text(
'Not Applicable Risk Factor', 'Not Applicable Risk Factor'.needTranslation,
style: TextStyle(fontSize: 14.f, color: AppColors.textColor), style: TextStyle(fontSize: 14.f, color: AppColors.textColor),
), ),
).toShimmer2(isShow: true, radius: 24.r); ).toShimmer2(isShow: true, radius: 24.r);

@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
@ -24,11 +25,13 @@ class SuggestionsScreen extends StatefulWidget {
class _SuggestionsScreenState extends State<SuggestionsScreen> { class _SuggestionsScreenState extends State<SuggestionsScreen> {
late DialogService dialogService; late DialogService dialogService;
late AppState _appState;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
dialogService = getIt<DialogService>(); dialogService = getIt<DialogService>();
_appState = getIt<AppState>();
// Initialize symptom groups based on selected organs // Initialize symptom groups based on selected organs
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
final viewModel = context.read<SymptomsCheckerViewModel>(); final viewModel = context.read<SymptomsCheckerViewModel>();
@ -92,6 +95,8 @@ class _SuggestionsScreenState extends State<SuggestionsScreen> {
} }
Widget _buildSuggestionsList(SymptomsCheckerViewModel viewModel) { Widget _buildSuggestionsList(SymptomsCheckerViewModel viewModel) {
final isArabic = _appState.isArabic();
return Container( return Container(
key: ValueKey<int>(viewModel.suggestionsList.length), key: ValueKey<int>(viewModel.suggestionsList.length),
width: double.infinity, width: double.infinity,
@ -102,7 +107,7 @@ class _SuggestionsScreenState extends State<SuggestionsScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
...viewModel.suggestionsList.map((factor) { ...viewModel.suggestionsList.map((factor) {
return _buildSuggestionItem(viewModel, factor.id ?? '', factor.getDisplayName()); return _buildSuggestionItem(viewModel, factor.id ?? '', factor.getDisplayName(isArabic: isArabic));
}), }),
SizedBox(height: 12.w), SizedBox(height: 12.w),
Row( Row(
@ -115,7 +120,7 @@ class _SuggestionsScreenState extends State<SuggestionsScreen> {
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Expanded( Expanded(
child: "This is a list of symptoms suggested by our AI, based on the information gathered so far during the interview".toText12( child: LocaleKeys.suggestionAIListDescription.tr(context: context).toText12(
color: AppColors.greyInfoTextColor, color: AppColors.greyInfoTextColor,
), ),
) )

@ -1,15 +1,16 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/body_symptom_response_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/body_symptom_response_model.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -26,11 +27,13 @@ class SymptomsSelectorPage extends StatefulWidget {
class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> { class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
late DialogService dialogService; late DialogService dialogService;
late AppState _appState;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
dialogService = getIt<DialogService>(); dialogService = getIt<DialogService>();
_appState = getIt<AppState>();
// Initialize symptom groups based on selected organs // Initialize symptom groups based on selected organs
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
final viewModel = context.read<SymptomsCheckerViewModel>(); final viewModel = context.read<SymptomsCheckerViewModel>();
@ -82,10 +85,12 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
title: LocaleKeys.symptomsSelector.tr(), title: LocaleKeys.symptomsSelector.tr(),
leadingCallback: () => _buildConfirmationBottomSheet( leadingCallback: () => _buildConfirmationBottomSheet(
context: context, context: context,
onConfirm: () => { onConfirm: () {
context.pop(), context.pop();
context.pop(), viewModel.reset(); // Clear all symptoms checker data
}), final navigationService = getIt.get<NavigationService>();
navigationService.replaceAllRoutesAndNavigateToLanding();
}),
child: viewModel.isBodySymptomsLoading child: viewModel.isBodySymptomsLoading
? _buildLoadingShimmer() ? _buildLoadingShimmer()
: viewModel.organSymptomsResults.isEmpty : viewModel.organSymptomsResults.isEmpty
@ -98,10 +103,11 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
// Find matching organ ID from selected organs // Find matching organ ID from selected organs
String? organId; String? organId;
String? organName; String? organName;
final isArabic = _appState.isArabic();
for (var organ in viewModel.selectedOrgans) { for (var organ in viewModel.selectedOrgans) {
if (organ.name == organResult.name) { if (organ.name == organResult.name) {
organId = organ.id; organId = organ.id;
organName = organ.description; organName = organ.getLocalizedDescription(isArabic);
break; break;
} }
} }
@ -139,6 +145,8 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
String organName, String organName,
List<BodySymptom> symptoms, List<BodySymptom> symptoms,
) { ) {
final isArabic = _appState.isArabic();
return Container( return Container(
width: double.infinity, width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 24.w), margin: EdgeInsets.symmetric(horizontal: 24.w),
@ -152,7 +160,7 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
'Possible symptoms related to "$organName"', '${LocaleKeys.possibleSymptomsRelatedTo.tr(context: context)} "$organName"',
style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor), style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor),
), ),
), ),
@ -164,7 +172,7 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
spacing: 8.w, spacing: 8.w,
children: symptoms.map((symptom) { children: symptoms.map((symptom) {
final symptomId = symptom.id ?? ''; final symptomId = symptom.id ?? '';
final symptomLabel = symptom.getDisplayName(false); // Pass isArabic from AppState if needed final symptomLabel = symptom.getDisplayName(isArabic);
bool isSelected = viewModel.isSymptomSelected(organId, symptomId); bool isSelected = viewModel.isSymptomSelected(organId, symptomId);
return GestureDetector( return GestureDetector(
onTap: () => viewModel.toggleSymptomSelection(organId, symptomId), onTap: () => viewModel.toggleSymptomSelection(organId, symptomId),
@ -304,7 +312,7 @@ class _SymptomsSelectorPageState extends State<SymptomsSelectorPage> {
fontSize: 16.f, fontSize: 16.f,
), ),
), ),
], ],
), ),
SizedBox(height: 24.h), SizedBox(height: 24.h),
], ],

@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
@ -14,6 +15,7 @@ import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_v
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/custom_progress_bar.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/custom_progress_bar.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -31,12 +33,14 @@ class TriagePage extends StatefulWidget {
class _TriagePageState extends State<TriagePage> { class _TriagePageState extends State<TriagePage> {
late SymptomsCheckerViewModel viewModel; late SymptomsCheckerViewModel viewModel;
late DialogService dialogService; late DialogService dialogService;
late AppState _appState;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
viewModel = context.read<SymptomsCheckerViewModel>(); viewModel = context.read<SymptomsCheckerViewModel>();
dialogService = getIt.get<DialogService>(); dialogService = getIt.get<DialogService>();
_appState = getIt.get<AppState>();
// Start triage process when screen loads // Start triage process when screen loads
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@ -119,12 +123,14 @@ class _TriagePageState extends State<TriagePage> {
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.emergencyTriage.tr(context: context).toText28(color: AppColors.whiteColor, isBold: true), LocaleKeys.emergencyTriage.tr(context: context).toText28(color: AppColors.whiteColor, isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.emergencyEvidenceDetected.tr(context: context) LocaleKeys.emergencyEvidenceDetected.tr(context: context).toText14(color: AppColors.whiteColor, weight: FontWeight.w500),
.toText14(color: AppColors.whiteColor, weight: FontWeight.w500),
SizedBox(height: 24.h), SizedBox(height: 24.h),
CustomButton( CustomButton(
text: LocaleKeys.confirm.tr(context: context), text: LocaleKeys.confirm.tr(context: context),
onPressed: () async => Navigator.of(context).pop(), onPressed: () {
context.pop();
context.navigateWithName(AppRoutes.possibleConditionsPage);
},
backgroundColor: AppColors.whiteColor, backgroundColor: AppColors.whiteColor,
borderColor: AppColors.whiteColor, borderColor: AppColors.whiteColor,
textColor: AppColors.primaryRedColor, textColor: AppColors.primaryRedColor,
@ -197,7 +203,7 @@ class _TriagePageState extends State<TriagePage> {
// Call API with updated evidence // Call API with updated evidence
viewModel.getDiagnosisForTriage( viewModel.getDiagnosisForTriage(
age: viewModel.selectedAge!, age: viewModel.selectedAge!,
sex: viewModel.selectedGender!.toLowerCase(), gender: viewModel.selectedGender!.toLowerCase() == "male" ? 1 : 2,
evidenceIds: initialEvidenceIds, evidenceIds: initialEvidenceIds,
triageEvidence: triageEvidence, triageEvidence: triageEvidence,
language: viewModel.appState.isArabic() ? 'ar' : 'en', language: viewModel.appState.isArabic() ? 'ar' : 'en',
@ -307,8 +313,10 @@ class _TriagePageState extends State<TriagePage> {
isShowActionButtons: true, isShowActionButtons: true,
onCancelTap: () => Navigator.pop(context), onCancelTap: () => Navigator.pop(context),
onConfirmTap: () { onConfirmTap: () {
Navigator.pop(context);
context.pop(); context.pop();
viewModel.reset(); // Clear all symptoms checker data
final navigationService = getIt.get<NavigationService>();
navigationService.replaceAllRoutesAndNavigateToLanding();
}, },
), ),
callBackFunc: () {}, callBackFunc: () {},
@ -431,7 +439,8 @@ class _TriagePageState extends State<TriagePage> {
Widget _buildStickyBottomCard(BuildContext context, SymptomsCheckerViewModel viewModel) { Widget _buildStickyBottomCard(BuildContext context, SymptomsCheckerViewModel viewModel) {
// Get the top condition with highest probability // Get the top condition with highest probability
final conditions = viewModel.currentConditions ?? []; final conditions = viewModel.currentConditions ?? [];
String suggestedCondition = "Analyzing..."; final isArabic = _appState.isArabic();
String suggestedCondition = LocaleKeys.analyzing.tr(context: context);
double probability = 0.0; double probability = 0.0;
if (conditions.isNotEmpty) { if (conditions.isNotEmpty) {
@ -440,7 +449,7 @@ class _TriagePageState extends State<TriagePage> {
sortedConditions.sort((a, b) => (b.probability ?? 0.0).compareTo(a.probability ?? 0.0)); sortedConditions.sort((a, b) => (b.probability ?? 0.0).compareTo(a.probability ?? 0.0));
final topCondition = sortedConditions.first; final topCondition = sortedConditions.first;
suggestedCondition = topCondition.commonName ?? topCondition.name ?? "Unknown"; suggestedCondition = topCondition.getDisplayName(isArabic: isArabic);
probability = (topCondition.probability ?? 0.0) * 100; // Convert to percentage probability = (topCondition.probability ?? 0.0) * 100; // Convert to percentage
} }
// final bool isHighConfidence = probability >= 70.0; // final bool isHighConfidence = probability >= 70.0;

@ -16,14 +16,14 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class UserInfoSelectionScreen extends StatefulWidget { class UserInfoSelectionPage extends StatefulWidget {
const UserInfoSelectionScreen({super.key}); const UserInfoSelectionPage({super.key});
@override @override
State<UserInfoSelectionScreen> createState() => _UserInfoSelectionScreenState(); State<UserInfoSelectionPage> createState() => _UserInfoSelectionPageState();
} }
class _UserInfoSelectionScreenState extends State<UserInfoSelectionScreen> { class _UserInfoSelectionPageState extends State<UserInfoSelectionPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -43,13 +43,10 @@ class _UserInfoSelectionScreenState extends State<UserInfoSelectionScreen> {
if (user == null) return; if (user == null) return;
// Populate gender (gender is int: 1=Male, 2=Female) // Populate gender (gender is int: 1=Male, 2=Female)
// Use internal keys (male/female) for storage
if (user.gender != null) { if (user.gender != null) {
String genderStr = user.gender == 1 String genderKey = user.gender == 1 ? "male" : user.gender == 2 ? "female" : "other";
? "Male" viewModel.setGender(genderKey);
: user.gender == 2
? "Female"
: "Other";
viewModel.setGender(genderStr);
} }
if (user.dateofBirth != null && user.dateofBirth!.isNotEmpty) { if (user.dateofBirth != null && user.dateofBirth!.isNotEmpty) {
@ -84,12 +81,13 @@ class _UserInfoSelectionScreenState extends State<UserInfoSelectionScreen> {
child: Row( child: Row(
children: [ children: [
Container( Container(
height: 40.h, height: 40.h,
width: 40.h, width: 40.h,
margin: EdgeInsets.only(right: 10.h), margin: EdgeInsetsDirectional.only(end: 10.h),
padding: EdgeInsets.all(8.h), padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.greyColor), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.greyColor),
child: Utils.buildSvgWithAssets(icon: leadingIcon, iconColor: iconColor)), child: Utils.buildSvgWithAssets(icon: leadingIcon, iconColor: iconColor),
),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -112,6 +110,20 @@ class _UserInfoSelectionScreenState extends State<UserInfoSelectionScreen> {
).paddingSymmetrical(0, 8.h); ).paddingSymmetrical(0, 8.h);
} }
/// Convert internal gender key to localized display string
String _getLocalizedGender(String? genderKey, BuildContext context) {
if (genderKey == null) return LocaleKeys.notSet.tr(context: context);
final lowerKey = genderKey.toLowerCase();
if (lowerKey == "male") {
return LocaleKeys.malE.tr(context: context);
} else if (lowerKey == "female") {
return LocaleKeys.femaleGender.tr(context: context);
} else {
return genderKey; // Return as-is if not recognized
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>(); AppState appState = getIt.get<AppState>();
@ -151,14 +163,16 @@ class _UserInfoSelectionScreenState extends State<UserInfoSelectionScreen> {
viewModel.selectedWeight == null; viewModel.selectedWeight == null;
// Get display values // Get display values
String genderText = viewModel.selectedGender ?? LocaleKeys.notSet.tr(context: context); String genderText = _getLocalizedGender(viewModel.selectedGender, context);
// Show age calculated from DOB (prefer viewModel's age, fallback to calculated from user's DOB) // Show age calculated from DOB (prefer viewModel's age, fallback to calculated from user's DOB)
int? displayAge = viewModel.selectedAge ?? userAgeFromDOB; int? displayAge = viewModel.selectedAge ?? userAgeFromDOB;
String ageText = displayAge != null ? "$displayAge ${LocaleKeys.years.tr(context: context)}" : LocaleKeys.notSet.tr(context: context); String ageText = displayAge != null ? "$displayAge ${LocaleKeys.years.tr(context: context)}" : LocaleKeys.notSet.tr(context: context);
String heightText = String heightText = viewModel.selectedHeight != null
viewModel.selectedHeight != null ? "${viewModel.selectedHeight!.round()} ${viewModel.isHeightCm ? 'cm' : 'ft'}" : LocaleKeys.notSet.tr(context: context); ? "${viewModel.selectedHeight!.round()} ${viewModel.isHeightCm ? 'cm' : 'ft'}"
String weightText = : LocaleKeys.notSet.tr(context: context);
viewModel.selectedWeight != null ? "${viewModel.selectedWeight!.round()} ${viewModel.isWeightKg ? 'kg' : 'lbs'}" : LocaleKeys.notSet.tr(context: context); String weightText = viewModel.selectedWeight != null
? "${viewModel.selectedWeight!.round()} ${viewModel.isWeightKg ? 'kg' : 'lbs'}"
: LocaleKeys.notSet.tr(context: context);
return Column( return Column(
children: [ children: [
@ -176,9 +190,9 @@ class _UserInfoSelectionScreenState extends State<UserInfoSelectionScreen> {
child: Column( child: Column(
children: [ children: [
LocaleKeys.helloIsYourInformationUpToDate.tr(namedArgs: {'name': name}).toText16( LocaleKeys.helloIsYourInformationUpToDate.tr(namedArgs: {'name': name}).toText16(
weight: FontWeight.w600, weight: FontWeight.w600,
color: AppColors.textColor, color: AppColors.textColor,
), ),
SizedBox(height: 32.h), SizedBox(height: 32.h),
_buildEditInfoTile( _buildEditInfoTile(
context: context, context: context,

@ -15,12 +15,16 @@ class GenderSelectionPage extends StatelessWidget {
final String? selectedGender; final String? selectedGender;
final Function(String) onGenderSelected; final Function(String) onGenderSelected;
GenderSelectionPage({ const GenderSelectionPage({
super.key, super.key,
required this.selectedGender, required this.selectedGender,
required this.onGenderSelected, required this.onGenderSelected,
}); });
// Internal gender keys (constant, not localized)
static const String maleKey = "male";
static const String femaleKey = "female";
_buildGenderOption(String iconPng, String label, bool isSelected) { _buildGenderOption(String iconPng, String label, bool isSelected) {
return Container( return Container(
height: 160.h, height: 160.h,
@ -40,7 +44,27 @@ class GenderSelectionPage extends StatelessWidget {
); );
} }
final genders = ["Male", "Female"]; /// Check if the selected gender matches the given key
/// Handles both internal keys and localized strings
bool _isGenderSelected(String genderKey, String? currentSelection, BuildContext context) {
if (currentSelection == null) return false;
final lowerSelection = currentSelection.toLowerCase();
if (genderKey == maleKey) {
// Check against internal key, English, and Arabic
return lowerSelection == maleKey ||
lowerSelection == "male" ||
currentSelection == LocaleKeys.malE.tr(context: context) ||
currentSelection == "ذكر";
} else {
// Check against internal key, English, and Arabic
return lowerSelection == femaleKey ||
lowerSelection == "female" ||
currentSelection == LocaleKeys.femaleGender.tr(context: context) ||
currentSelection == "أنثى";
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -56,16 +80,25 @@ class GenderSelectionPage extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () => onGenderSelected(genders[0]), onTap: () => onGenderSelected(maleKey),
child: _buildGenderOption(AppAssets.maleIcon, LocaleKeys.malE.tr(context: context), symptomsViewModel.selectedGender == genders[0]), child: _buildGenderOption(
AppAssets.maleIcon,
LocaleKeys.malE.tr(context: context),
_isGenderSelected(maleKey, symptomsViewModel.selectedGender, context),
),
), ),
), ),
SizedBox(width: 16.w), SizedBox(width: 16.w),
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () => onGenderSelected(genders[1]), onTap: () => onGenderSelected(femaleKey),
child: _buildGenderOption(AppAssets.femaleIcon, LocaleKeys.femaleGender.tr(context: context), symptomsViewModel.selectedGender == genders[1]), child: _buildGenderOption(
)) AppAssets.femaleIcon,
LocaleKeys.femaleGender.tr(context: context),
_isGenderSelected(femaleKey, symptomsViewModel.selectedGender, context),
),
),
)
], ],
), ),
], ],

@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart'; import 'package:hmg_patient_app_new/features/symptoms_checker/symptoms_checker_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/pages/age_selection_page.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/user_info_selection/pages/age_selection_page.dart';
@ -29,13 +28,15 @@ class _UserInfoFlowManagerState extends State<UserInfoFlowManager> {
late PageController _pageController; late PageController _pageController;
late SymptomsCheckerViewModel _viewModel; late SymptomsCheckerViewModel _viewModel;
// Page titles // Get localized page titles
final List<String> _pageTitles = [ List<String> _getPageTitles(BuildContext context) {
"Your Gender", return [
"Your Birth Date", LocaleKeys.genderSymptoms.tr(context: context),
"Your Height", LocaleKeys.dateOfBirthSymptoms.tr(context: context),
"Your Weight", LocaleKeys.heightSymptoms.tr(context: context),
]; LocaleKeys.weightSymptoms.tr(context: context),
];
}
@override @override
void initState() { void initState() {
@ -187,9 +188,11 @@ class _UserInfoFlowManagerState extends State<UserInfoFlowManager> {
? // Single page edit mode - show only Save button ? // Single page edit mode - show only Save button
CustomButton( CustomButton(
text: LocaleKeys.save.tr(context: context), text: LocaleKeys.save.tr(context: context),
onPressed: _onNext, isDisabled: !(viewModel.isCurrentUserInfoPageValid),
backgroundColor: AppColors.primaryRedColor, onPressed: () => viewModel.isCurrentUserInfoPageValid ? _onNext() : () {},
borderColor: AppColors.primaryRedColor, backgroundColor:
viewModel.isCurrentUserInfoPageValid ? AppColors.primaryRedColor : AppColors.primaryRedColor.withValues(alpha: 0.5),
borderColor: viewModel.isCurrentUserInfoPageValid ? AppColors.primaryRedColor : AppColors.primaryRedColor.withValues(alpha: 0.5),
textColor: AppColors.whiteColor, textColor: AppColors.whiteColor,
fontSize: 16.f, fontSize: 16.f,
) )
@ -228,6 +231,8 @@ class _UserInfoFlowManagerState extends State<UserInfoFlowManager> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final pageTitles = _getPageTitles(context);
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: Column( body: Column(
@ -235,7 +240,7 @@ class _UserInfoFlowManagerState extends State<UserInfoFlowManager> {
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
title: _pageTitles[_viewModel.userInfoCurrentPage], title: pageTitles[_viewModel.userInfoCurrentPage],
isLeading: true, isLeading: true,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

@ -2,9 +2,12 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/symptoms_checker/models/resp_models/triage_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/custom_progress_bar.dart'; import 'package:hmg_patient_app_new/presentation/symptoms_checker/widgets/custom_progress_bar.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
@ -12,33 +15,131 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
class ConditionCard extends StatelessWidget { class ConditionCard extends StatelessWidget {
final IconData icon; final TriageCondition condition;
final String title;
final int percentage;
final String tagText;
final String clinic;
final List<String> symptoms; final List<String> symptoms;
final String description;
final String? monitorNote;
final String? appointmentLabel;
final PossibleConditionsSeverityEnum possibleConditionsSeverityEnum;
final VoidCallback? onActionPressed; final VoidCallback? onActionPressed;
const ConditionCard({ const ConditionCard({
super.key, super.key,
required this.icon, required this.condition,
required this.title,
required this.percentage,
required this.tagText,
required this.clinic,
required this.symptoms, required this.symptoms,
required this.description,
this.monitorNote,
this.appointmentLabel,
required this.possibleConditionsSeverityEnum,
this.onActionPressed, this.onActionPressed,
}); });
/// Get title from condition (localized)
String get title {
final appState = getIt<AppState>();
return condition.getDisplayName(isArabic: appState.isArabic());
}
/// Get percentage from probability (0-1 to 0-100)
int get percentage => ((condition.probability ?? 0) * 100).toInt();
/// Get clinic name from category
String get clinic => condition.conditionDetails?.category?.name ?? '';
/// Get description from hint
String get description => condition.conditionDetails?.hint ?? '';
/// Get severity enum based on triage level
PossibleConditionsSeverityEnum get severityEnum {
final triageLevel = condition.conditionDetails?.triageLevel;
if (triageLevel != null) {
switch (triageLevel) {
case TriageLevelEnum.emergencyAmbulance:
case TriageLevelEnum.emergency:
return PossibleConditionsSeverityEnum.emergency;
case TriageLevelEnum.consultation24:
case TriageLevelEnum.consultation:
return PossibleConditionsSeverityEnum.seekMedicalAdvice;
case TriageLevelEnum.selfCare:
return PossibleConditionsSeverityEnum.monitorOnly;
}
}
// Default based on probability
if (percentage >= 70) {
return PossibleConditionsSeverityEnum.seekMedicalAdvice;
} else {
return PossibleConditionsSeverityEnum.monitorOnly;
}
}
/// Get tag text based on triage level
String getTagText(BuildContext context) {
final triageLevel = condition.conditionDetails?.triageLevel;
if (triageLevel != null) {
switch (triageLevel) {
case TriageLevelEnum.emergencyAmbulance:
case TriageLevelEnum.emergency:
return LocaleKeys.emergency.tr(context: context);
case TriageLevelEnum.consultation24:
case TriageLevelEnum.consultation:
return LocaleKeys.seekMedicalAdvice.tr(context: context);
case TriageLevelEnum.selfCare:
return LocaleKeys.monitor.tr(context: context);
}
}
// Default based on probability
if (percentage >= 70) {
return LocaleKeys.seekMedicalAdvice.tr(context: context);
} else {
return LocaleKeys.monitor.tr(context: context);
}
}
/// Get monitor note if applicable
String? getMonitorNote(BuildContext context) {
if (severityEnum == PossibleConditionsSeverityEnum.monitorOnly) {
return LocaleKeys.noNeedToVisitDoctor.tr(context: context);
}
return null;
}
/// Get icon based on category name from API
IconData get icon {
final categoryName = condition.conditionDetails?.category?.name?.toLowerCase() ?? '';
if (categoryName.contains('cardio') || categoryName.contains('heart')) {
return Icons.favorite;
} else if (categoryName.contains('neuro') || categoryName.contains('brain')) {
return Icons.psychology_alt;
} else if (categoryName.contains('psychiatr') || categoryName.contains('mental')) {
return Icons.psychology;
} else if (categoryName.contains('eye') || categoryName.contains('ophthalmo')) {
return Icons.remove_red_eye;
} else if (categoryName.contains('ent') || categoryName.contains('ear')) {
return Icons.hearing;
} else if (categoryName.contains('derma') || categoryName.contains('skin')) {
return Icons.face;
} else if (categoryName.contains('ortho') || categoryName.contains('bone')) {
return Icons.accessibility_new;
} else if (categoryName.contains('gyneco') || categoryName.contains('obstet')) {
return Icons.pregnant_woman;
} else if (categoryName.contains('pediatr') || categoryName.contains('child')) {
return Icons.child_care;
} else if (categoryName.contains('surg')) {
return Icons.local_hospital;
} else if (categoryName.contains('pulmo') || categoryName.contains('lung') || categoryName.contains('respiratory')) {
return Icons.air;
} else if (categoryName.contains('gastro') || categoryName.contains('digest')) {
return Icons.restaurant;
} else if (categoryName.contains('nephro') || categoryName.contains('kidney')) {
return Icons.water_drop;
} else if (categoryName.contains('hemato') || categoryName.contains('blood')) {
return Icons.bloodtype;
} else if (categoryName.contains('infect') || categoryName.contains('virus')) {
return Icons.coronavirus;
} else if (categoryName.contains('emergency')) {
return Icons.emergency;
} else if (categoryName.contains('geriatr') || categoryName.contains('elder')) {
return Icons.elderly;
} else if (categoryName.contains('internal')) {
return Icons.medical_services;
}
return Icons.medical_services;
}
Color getChipColorBySeverityEnum(PossibleConditionsSeverityEnum possibleConditionsSeverityEnum) { Color getChipColorBySeverityEnum(PossibleConditionsSeverityEnum possibleConditionsSeverityEnum) {
switch (possibleConditionsSeverityEnum) { switch (possibleConditionsSeverityEnum) {
case PossibleConditionsSeverityEnum.seekMedicalAdvice: case PossibleConditionsSeverityEnum.seekMedicalAdvice:
@ -67,7 +168,7 @@ class ConditionCard extends StatelessWidget {
crossAxisAlignment: WrapCrossAlignment.center, crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
for (int i = 0; i < symptoms.length; i++) ...[ for (int i = 0; i < symptoms.length; i++) ...[
Text(symptoms[i], style: TextStyle(color: AppColors.greyTextColor, fontWeight: FontWeight.w500, fontSize: 12.f)), "${symptoms[i]}".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
if (i != symptoms.length - 1) if (i != symptoms.length - 1)
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w), padding: EdgeInsets.symmetric(horizontal: 2.w),
@ -80,9 +181,12 @@ class ConditionCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// final monitorNote = getMonitorNote(context);
final tagText = getTagText(context);
return Container( return Container(
width: double.infinity, width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -90,14 +194,14 @@ class ConditionCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
width: 48.w, width: 32.w,
height: 48.w, height: 32.w,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: getChipColorBySeverityEnum(possibleConditionsSeverityEnum).withValues(alpha: 0.2), color: getChipColorBySeverityEnum(severityEnum).withValues(alpha: 0.2),
borderRadius: 12.r, borderRadius: 8.r,
hasShadow: false, hasShadow: false,
), ),
child: Icon(icon, color: getChipTextColorBySeverityEnum(possibleConditionsSeverityEnum), size: 24.f), child: Icon(icon, color: getChipTextColorBySeverityEnum(severityEnum), size: 16.f),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Expanded( Expanded(
@ -108,34 +212,23 @@ class ConditionCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( Expanded(
child: Text( child: title.toText18(weight: FontWeight.w600, color: AppColors.textColor),
title,
style: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, color: AppColors.textColor),
overflow: TextOverflow.ellipsis,
),
), ),
AppCustomChipWidget( AppCustomChipWidget(
labelText: tagText, labelText: tagText,
backgroundColor: getChipColorBySeverityEnum(possibleConditionsSeverityEnum).withValues(alpha: 0.2), backgroundColor: getChipColorBySeverityEnum(severityEnum).withValues(alpha: 0.2),
textColor: getChipTextColorBySeverityEnum(possibleConditionsSeverityEnum), textColor: getChipTextColorBySeverityEnum(severityEnum),
), ),
], ],
), ),
CustomRoundedProgressBar( CustomRoundedProgressBar(
percentage: percentage, percentage: percentage,
height: 6.h, height: 6.h,
color: getChipColorBySeverityEnum(possibleConditionsSeverityEnum), color: getChipColorBySeverityEnum(severityEnum),
backgroundColor: AppColors.scaffoldBgColor, backgroundColor: AppColors.scaffoldBgColor,
titleWidget: Row( titleWidget: Row(
children: [ children: [
Text( "$percentage%".toText12(fontWeight: FontWeight.bold, color: getChipColorBySeverityEnum(severityEnum)),
"$percentage%",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.f,
color: getChipColorBySeverityEnum(possibleConditionsSeverityEnum),
),
),
], ],
).paddingSymmetrical(0, 4.h), ).paddingSymmetrical(0, 4.h),
), ),
@ -148,50 +241,42 @@ class ConditionCard extends StatelessWidget {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( LocaleKeys.commonSymptom.tr(context: context).toText14(weight: FontWeight.w600, color: AppColors.textColor),
clinic,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14.f,
color: AppColors.textColor,
),
),
_buildSymptomsRow(), _buildSymptomsRow(),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Text(LocaleKeys.description.tr(context: context), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.f, color: AppColors.textColor)), LocaleKeys.description.tr(context: context).toText14(weight: FontWeight.bold, color: AppColors.textColor),
SizedBox(height: 2.h), SizedBox(height: 2.h),
Text(description, style: TextStyle(color: AppColors.greyTextColor, fontWeight: FontWeight.w500, fontSize: 12.f)), description.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
if (possibleConditionsSeverityEnum == PossibleConditionsSeverityEnum.emergency) if (severityEnum != PossibleConditionsSeverityEnum.monitorOnly)
CustomButton( CustomButton(
text: appointmentLabel ?? LocaleKeys.bookAppointment.tr(context: context), text: LocaleKeys.bookAppointment.tr(context: context),
onPressed: () { onPressed: () {
if (onActionPressed != null) { if (onActionPressed != null) {
onActionPressed!(); onActionPressed!();
} }
}, },
backgroundColor: AppColors.lightRedButtonColor, backgroundColor: AppColors.primaryRedColor,
borderColor: Colors.transparent, borderColor: Colors.transparent,
textColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor,
fontSize: 16.f, fontSize: 14.f,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w), padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 48.h,
icon: AppAssets.add_icon, icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor, height: 48.h,
iconSize: 18.h, iconColor: AppColors.whiteColor,
).paddingOnly(top: 16.w), ).paddingOnly(top: 16.w),
if (monitorNote != null)
Container( // if (monitorNote != null)
margin: EdgeInsets.only(top: 12.h), // Container(
child: AppCustomChipWidget( // margin: EdgeInsets.only(top: 12.h),
labelText: monitorNote!, // child: AppCustomChipWidget(
backgroundColor: AppColors.whiteColor, // labelText: monitorNote,
textColor: AppColors.textColor, // backgroundColor: AppColors.whiteColor,
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 8.h), // textColor: AppColors.textColor,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)), // padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 8.h),
), // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
), // ),
// ),
], ],
).paddingAll(16.w), ).paddingAll(16.w),
], ],

@ -13,6 +13,7 @@ class InteractiveBodyWidget extends StatefulWidget {
final bool isBodyHidden; final bool isBodyHidden;
final Function(String organId) onOrganTap; final Function(String organId) onOrganTap;
final String? tooltipOrganId; final String? tooltipOrganId;
final bool isArabic;
const InteractiveBodyWidget({ const InteractiveBodyWidget({
super.key, super.key,
@ -22,6 +23,7 @@ class InteractiveBodyWidget extends StatefulWidget {
required this.onOrganTap, required this.onOrganTap,
this.isBodyHidden = false, this.isBodyHidden = false,
this.tooltipOrganId, this.tooltipOrganId,
this.isArabic = false,
}); });
@override @override
@ -118,7 +120,10 @@ class _InteractiveBodyWidgetState extends State<InteractiveBodyWidget> {
(organ) { (organ) {
final centerX = organ.position.x * imageConstraints.maxWidth; final centerX = organ.position.x * imageConstraints.maxWidth;
final centerY = organ.position.y * imageConstraints.maxHeight; final centerY = organ.position.y * imageConstraints.maxHeight;
return OrganTooltipWidget(organName: organ.description, position: Offset(centerX, centerY)); return OrganTooltipWidget(
organName: organ.getLocalizedDescription(widget.isArabic),
position: Offset(centerX, centerY),
);
}, },
), ),
], ],

@ -145,7 +145,7 @@ class AncillaryOrderCard extends StatelessWidget {
if (!isLoading) ...[ if (!isLoading) ...[
Image.network( Image.network(
"https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png", "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png",
width: 63.w, width: 63.h,
height: 63.h, height: 63.h,
fit: BoxFit.cover, fit: BoxFit.cover,
).circle(100.r), ).circle(100.r),
@ -177,11 +177,11 @@ class AncillaryOrderCard extends StatelessWidget {
labelText: order.projectName ?? '-', labelText: order.projectName ?? '-',
).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
// orderNo // orderNo
// if (order.orderNo != null || isLoading) if (order.orderNo != null || isLoading)
// AppCustomChipWidget( AppCustomChipWidget(
// // icon: AppAssets.calendar, // icon: AppAssets.calendar,
// labelText: "${"Order# :".needTranslation}${order.orderNo ?? '-'}", labelText: "${LocaleKeys.orderNumber.tr(context: context)}${order.orderNo ?? '-'}",
// ).toShimmer2(isShow: isLoading), ).toShimmer2(isShow: isLoading),
// Appointment Date // Appointment Date
if (order.appointmentDate != null || isLoading) if (order.appointmentDate != null || isLoading)

@ -1,5 +1,6 @@
import 'dart:ui'; import 'dart:ui';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
@ -8,6 +9,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/vital_sign_respo_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/vital_sign_respo_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
@ -42,7 +44,7 @@ class _VitalSignPageState extends State<VitalSignPage> {
return Scaffold( return Scaffold(
backgroundColor: AppColors.bgScaffoldColor, backgroundColor: AppColors.bgScaffoldColor,
body: CollapsingListView( body: CollapsingListView(
title: 'Vital Signs', title: LocaleKeys.vitalSigns.tr(context: context),
child: Consumer<HmgServicesViewModel>( child: Consumer<HmgServicesViewModel>(
builder: (context, viewModel, child) { builder: (context, viewModel, child) {
@ -70,14 +72,14 @@ class _VitalSignPageState extends State<VitalSignPage> {
// BMI Card // BMI Card
_buildVitalSignCard( _buildVitalSignCard(
icon: AppAssets.bmiVital, icon: AppAssets.bmiVital,
label: 'BMI', label: LocaleKeys.bmi.tr(context: context),
value: latestVitalSign?.bodyMassIndex?.toString() ?? '--', value: latestVitalSign?.bodyMassIndex?.toString() ?? '--',
unit: '', unit: '',
status: VitalSignUiModel.bmiStatus(latestVitalSign?.bodyMassIndex), status: VitalSignUiModel.bmiStatus(latestVitalSign?.bodyMassIndex),
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.bmi, metric: VitalSignMetric.bmi,
title: 'BMI', title: LocaleKeys.bmi.tr(context: context),
icon: AppAssets.bmiVital, icon: AppAssets.bmiVital,
unit: '', unit: '',
), ),
@ -88,14 +90,14 @@ class _VitalSignPageState extends State<VitalSignPage> {
// Height Card // Height Card
_buildVitalSignCard( _buildVitalSignCard(
icon: AppAssets.heightVital, icon: AppAssets.heightVital,
label: 'Height', label: LocaleKeys.height.tr(context: context),
value: latestVitalSign?.heightCm?.toString() ?? '--', value: latestVitalSign?.heightCm?.toString() ?? '--',
unit: 'cm', unit: 'cm',
status: null, status: null,
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.height, metric: VitalSignMetric.height,
title: 'Height', title: LocaleKeys.height.tr(context: context),
icon: AppAssets.heightVital, icon: AppAssets.heightVital,
unit: 'cm', unit: 'cm',
), ),
@ -106,14 +108,14 @@ class _VitalSignPageState extends State<VitalSignPage> {
// Weight Card // Weight Card
_buildVitalSignCard( _buildVitalSignCard(
icon: AppAssets.weightVital, icon: AppAssets.weightVital,
label: 'Weight', label: LocaleKeys.weight.tr(context: context),
value: latestVitalSign?.weightKg?.toString() ?? '--', value: latestVitalSign?.weightKg?.toString() ?? '--',
unit: 'kg', unit: 'kg',
status: (latestVitalSign?.weightKg != null) ? 'Normal' : null, status: (latestVitalSign?.weightKg != null) ? 'Normal' : null,
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.weight, metric: VitalSignMetric.weight,
title: 'Weight', title: LocaleKeys.height.tr(context: context),
icon: AppAssets.weightVital, icon: AppAssets.weightVital,
unit: 'kg', unit: 'kg',
), ),
@ -124,7 +126,7 @@ class _VitalSignPageState extends State<VitalSignPage> {
// Blood Pressure Card // Blood Pressure Card
_buildVitalSignCard( _buildVitalSignCard(
icon: AppAssets.bloodPressure, icon: AppAssets.bloodPressure,
label: 'Blood Pressure', label: LocaleKeys.bloodPressure.tr(context: context),
value: latestVitalSign != null && value: latestVitalSign != null &&
latestVitalSign.bloodPressureHigher != null && latestVitalSign.bloodPressureHigher != null &&
latestVitalSign.bloodPressureLower != null latestVitalSign.bloodPressureLower != null
@ -136,9 +138,9 @@ class _VitalSignPageState extends State<VitalSignPage> {
diastolic: latestVitalSign?.bloodPressureLower, diastolic: latestVitalSign?.bloodPressureLower,
), ),
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.bloodPressure, metric: VitalSignMetric.bloodPressure,
title: 'Blood Pressure', title: LocaleKeys.bloodPressure.tr(context: context),
icon: AppAssets.bloodPressure, icon: AppAssets.bloodPressure,
unit: 'mmHg', unit: 'mmHg',
low: 90, low: 90,
@ -151,14 +153,14 @@ class _VitalSignPageState extends State<VitalSignPage> {
// Temperature Card // Temperature Card
_buildVitalSignCard( _buildVitalSignCard(
icon: AppAssets.temperature, icon: AppAssets.temperature,
label: 'Temperature', label: LocaleKeys.temperature.tr(context: context),
value: latestVitalSign?.temperatureCelcius?.toString() ?? '--', value: latestVitalSign?.temperatureCelcius?.toString() ?? '--',
unit: '°C', unit: '°C',
status: null, status: null,
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.temperature, metric: VitalSignMetric.temperature,
title: 'Temperature', title: LocaleKeys.temperature.tr(context: context),
icon: AppAssets.temperature, icon: AppAssets.temperature,
unit: '°C', unit: '°C',
low: 36.1, low: 36.1,
@ -226,14 +228,14 @@ class _VitalSignPageState extends State<VitalSignPage> {
bottom: 12.h, bottom: 12.h,
child: _buildVitalSignCard( child: _buildVitalSignCard(
icon: AppAssets.heart, icon: AppAssets.heart,
label: 'Heart Rate', label: LocaleKeys.heart.tr(context: context),
value: latestVitalSign?.heartRate?.toString() ?? latestVitalSign?.pulseBeatPerMinute?.toString() ?? '--', value: latestVitalSign?.heartRate?.toString() ?? latestVitalSign?.pulseBeatPerMinute?.toString() ?? '--',
unit: 'bpm', unit: 'bpm',
status: 'Normal', status: 'Normal',
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.heartRate, metric: VitalSignMetric.heartRate,
title: 'Heart Rate', title: LocaleKeys.heart.tr(context: context),
icon: AppAssets.heart, icon: AppAssets.heart,
unit: 'bpm', unit: 'bpm',
low: 60, low: 60,
@ -250,15 +252,15 @@ class _VitalSignPageState extends State<VitalSignPage> {
// Respiratory rate Card // Respiratory rate Card
_buildVitalSignCard( _buildVitalSignCard(
icon: AppAssets.respRate, icon: AppAssets.respRate,
label: 'Respiratory rate', label: LocaleKeys.respirationRate.tr(context: context),
value: latestVitalSign?.respirationBeatPerMinute?.toString() ?? '--', value: latestVitalSign?.respirationBeatPerMinute?.toString() ?? '--',
unit: 'bpm', unit: 'bpm',
status: 'Normal', status: 'Normal',
onTap: () => _openDetails( onTap: () => _openDetails(
const VitalSignDetailsArgs( VitalSignDetailsArgs(
metric: VitalSignMetric.respiratoryRate, metric: VitalSignMetric.respiratoryRate,
title: 'Respiratory rate', title: LocaleKeys.respirationRate.tr(context: context),
icon: AppAssets.respRate, icon: AppAssets.respRate,
unit: 'bpm', unit: 'bpm',
low: 12, low: 12,
high: 20, high: 20,

@ -9,6 +9,7 @@ import 'package:hmg_patient_app_new/presentation/child_vaccine/my_child_vaccine_
import 'package:hmg_patient_app_new/presentation/comprehensive_checkup/comprehensive_checkup_page.dart'; import 'package:hmg_patient_app_new/presentation/comprehensive_checkup/comprehensive_checkup_page.dart';
import 'package:hmg_patient_app_new/presentation/covid19test/covid19_landing_page.dart'; import 'package:hmg_patient_app_new/presentation/covid19test/covid19_landing_page.dart';
import 'package:hmg_patient_app_new/presentation/e_referral/new_e_referral.dart'; import 'package:hmg_patient_app_new/presentation/e_referral/new_e_referral.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/emergency_services_page.dart';
import 'package:hmg_patient_app_new/presentation/health_calculators_and_converts/health_calculators_page.dart'; import 'package:hmg_patient_app_new/presentation/health_calculators_and_converts/health_calculators_page.dart';
import 'package:hmg_patient_app_new/presentation/health_trackers/add_health_tracker_entry_page.dart'; import 'package:hmg_patient_app_new/presentation/health_trackers/add_health_tracker_entry_page.dart';
import 'package:hmg_patient_app_new/presentation/health_trackers/health_tracker_detail_page.dart'; import 'package:hmg_patient_app_new/presentation/health_trackers/health_tracker_detail_page.dart';
@ -31,16 +32,14 @@ import 'package:hmg_patient_app_new/presentation/vital_sign/vital_sign_page.dart
import 'package:hmg_patient_app_new/presentation/water_monitor/water_consumption_page.dart'; import 'package:hmg_patient_app_new/presentation/water_monitor/water_consumption_page.dart';
import 'package:hmg_patient_app_new/presentation/water_monitor/water_monitor_settings_page.dart'; import 'package:hmg_patient_app_new/presentation/water_monitor/water_monitor_settings_page.dart';
import 'package:hmg_patient_app_new/splashPage.dart'; import 'package:hmg_patient_app_new/splashPage.dart';
import 'package:provider/provider.dart';
import '../features/qr_parking/qr_parking_view_model.dart';
import '../presentation/covid19test/covid19_landing_page.dart';
import '../core/dependencies.dart'; import '../core/dependencies.dart';
import '../features/monthly_reports/monthly_reports_repo.dart'; import '../features/monthly_reports/monthly_reports_repo.dart';
import '../features/monthly_reports/monthly_reports_view_model.dart'; import '../features/monthly_reports/monthly_reports_view_model.dart';
import '../features/qr_parking/qr_parking_view_model.dart';
import '../presentation/parking/paking_page.dart'; import '../presentation/parking/paking_page.dart';
import '../services/error_handler_service.dart'; import '../services/error_handler_service.dart';
import 'package:provider/provider.dart';
class AppRoutes { class AppRoutes {
static const String initialRoute = '/initialRoute'; static const String initialRoute = '/initialRoute';
@ -86,8 +85,10 @@ class AppRoutes {
static const String addHealthTrackerEntryPage = '/addHealthTrackerEntryPage'; static const String addHealthTrackerEntryPage = '/addHealthTrackerEntryPage';
static const String healthTrackerDetailPage = '/healthTrackerDetailPage'; static const String healthTrackerDetailPage = '/healthTrackerDetailPage';
static Map<String, WidgetBuilder> get routes => // Emergency Services
{ static const String emergencyServicesPage = '/emergencyServicesPage';
static Map<String, WidgetBuilder> get routes => {
initialRoute: (context) => SplashPage(), initialRoute: (context) => SplashPage(),
loginScreen: (context) => LoginScreen(), loginScreen: (context) => LoginScreen(),
landingScreen: (context) => LandingNavigation(), landingScreen: (context) => LandingNavigation(),
@ -107,7 +108,7 @@ class AppRoutes {
bloodDonationPage: (context) => BloodDonationPage(), bloodDonationPage: (context) => BloodDonationPage(),
myChildVaccine: (context) => MyChildVaccinePage(), myChildVaccine: (context) => MyChildVaccinePage(),
bookAppointmentPage: (context) => BookAppointmentPage(), bookAppointmentPage: (context) => BookAppointmentPage(),
userInfoSelection: (context) => UserInfoSelectionScreen(), userInfoSelection: (context) => UserInfoSelectionPage(),
userInfoFlowManager: (context) => UserInfoFlowManager(), userInfoFlowManager: (context) => UserInfoFlowManager(),
smartWatches: (context) => SmartwatchInstructionsPage(), smartWatches: (context) => SmartwatchInstructionsPage(),
huaweiHealthExample: (context) => HuaweiHealthExample(), huaweiHealthExample: (context) => HuaweiHealthExample(),
@ -118,34 +119,28 @@ class AppRoutes {
healthConvertersPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.converter), healthConvertersPage: (context) => HealthCalculatorsPage(type: HealthCalConEnum.converter),
healthTrackersPage: (context) => HealthTrackersPage(), healthTrackersPage: (context) => HealthTrackersPage(),
vitalSign: (context) => VitalSignPage(), vitalSign: (context) => VitalSignPage(),
emergencyServicesPage: (context) => EmergencyServicesPage(),
addHealthTrackerEntryPage: (context) { addHealthTrackerEntryPage: (context) {
final args = ModalRoute final args = ModalRoute.of(context)?.settings.arguments as HealthTrackerTypeEnum?;
.of(context)
?.settings
.arguments as HealthTrackerTypeEnum?;
return AddHealthTrackerEntryPage( return AddHealthTrackerEntryPage(
trackerType: args ?? HealthTrackerTypeEnum.bloodSugar, trackerType: args ?? HealthTrackerTypeEnum.bloodSugar,
); );
}, },
healthTrackerDetailPage: (context) { healthTrackerDetailPage: (context) {
final args = ModalRoute final args = ModalRoute.of(context)?.settings.arguments as HealthTrackerTypeEnum?;
.of(context)
?.settings
.arguments as HealthTrackerTypeEnum?;
return HealthTrackerDetailPage( return HealthTrackerDetailPage(
trackerType: args ?? HealthTrackerTypeEnum.bloodSugar, trackerType: args ?? HealthTrackerTypeEnum.bloodSugar,
); );
}, },
monthlyReports: (context) => ChangeNotifierProvider(
monthlyReports: (context) => ChangeNotifierProvider( create: (_) => MonthlyReportsViewModel(
create: (_) => MonthlyReportsViewModel( monthlyReportsRepo: getIt<MonthlyReportsRepo>(),
monthlyReportsRepo: getIt<MonthlyReportsRepo>(), errorHandlerService: getIt<ErrorHandlerService>(),
errorHandlerService: getIt<ErrorHandlerService>(), ),
), ),
), qrParking: (context) => ChangeNotifierProvider<QrParkingViewModel>(
qrParking: (context) => ChangeNotifierProvider<QrParkingViewModel>( create: (_) => getIt<QrParkingViewModel>(),
create: (_) => getIt<QrParkingViewModel>(), child: const ParkingPage(),
child: const ParkingPage(),
) )
}; };
} }

@ -230,7 +230,7 @@ Widget exceptionBottomSheetWidget(
children: [ children: [
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.cancel.tr(), text: LocaleKeys.cancel.tr(context: context),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -244,7 +244,7 @@ Widget exceptionBottomSheetWidget(
SizedBox(width: 10.h), SizedBox(width: 10.h),
Expanded( Expanded(
child: CustomButton( child: CustomButton(
text: LocaleKeys.confirm.tr(), text: LocaleKeys.confirm.tr(context: context),
onPressed: onOkPressed, onPressed: onOkPressed,
backgroundColor: AppColors.bgGreenColor, backgroundColor: AppColors.bgGreenColor,
borderColor: AppColors.bgGreenColor, borderColor: AppColors.bgGreenColor,
@ -258,7 +258,7 @@ Widget exceptionBottomSheetWidget(
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h), padding: EdgeInsets.only(bottom: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.cancel.tr(), text: LocaleKeys.cancel.tr(context: context),
onPressed: (onCancelPressed == null) onPressed: (onCancelPressed == null)
? () { ? () {
context.pop(); context.pop();
@ -286,7 +286,7 @@ Widget showPhoneNumberPickerWidget(
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h), padding: EdgeInsets.only(bottom: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(), text: LocaleKeys.sendOTPSMS.tr(context: context),
onPressed: onSMSPress, onPressed: onSMSPress,
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor, borderColor: AppColors.primaryRedBorderColor,
@ -300,14 +300,14 @@ Widget showPhoneNumberPickerWidget(
children: [ children: [
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 8.h), padding: EdgeInsets.symmetric(horizontal: 8.h),
child: LocaleKeys.oR.tr().toText16(color: AppColors.textColor), child: LocaleKeys.oR.tr(context: context).toText16(color: AppColors.textColor),
), ),
], ],
), ),
Padding( Padding(
padding: EdgeInsets.only(bottom: 10.h, top: 10.h), padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton( child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(), text: LocaleKeys.sendOTPWHATSAPP.tr(context: context),
onPressed: onWhatsappPress, onPressed: onWhatsappPress,
backgroundColor: Colors.white, backgroundColor: Colors.white,
borderColor: AppColors.borderOnlyColor, borderColor: AppColors.borderOnlyColor,

@ -92,7 +92,7 @@ class AppColors {
// SymptomsChecker // SymptomsChecker
static const Color chipColorSeekMedicalAdvice = Color(0xFFFFAF15); // #FFAF15 static const Color chipColorSeekMedicalAdvice = Color(0xFFFFAF15); // #FFAF15
static const Color chipTextColorSeekMedicalAdvice = Color(0xFFAB7103); // #AB7103 static const Color chipTextColorSeekMedicalAdvice = Color(0xFFD48D05); // #AB7103
static const Color chipColorMonitor = Color(0xFF18C273); // #18C273 static const Color chipColorMonitor = Color(0xFF18C273); // #18C273
static const Color chipColorEmergency = Color(0xFFED1C2B); // #ED1C2B static const Color chipColorEmergency = Color(0xFFED1C2B); // #ED1C2B

@ -48,7 +48,7 @@ class _AppLanguageChangeState extends State<AppLanguageChange> {
), ),
), ),
CustomButton( CustomButton(
text: LocaleKeys.save.tr(), text: LocaleKeys.save.tr(context: context),
onPressed: () { onPressed: () {
context.setLocale(selectedValue == 'en' ? Locale('en', 'US') : Locale('ar', 'SA')).then((val) { context.setLocale(selectedValue == 'en' ? Locale('en', 'US') : Locale('ar', 'SA')).then((val) {
Navigator.pop(context); Navigator.pop(context);

@ -74,26 +74,25 @@ class CustomButton extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (icon != null) if (icon != null)
Padding( Flexible(
padding: text.isNotEmpty ? EdgeInsets.only(right: 8.w, left: 8.w) : EdgeInsets.zero, child: Padding(
child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconS, height: iconS), padding: text.isNotEmpty ? EdgeInsets.only(right: 4.w, left: 4.w) : EdgeInsets.zero,
child: Utils.buildSvgWithAssets(icon: icon!, iconColor: iconColor, isDisabled: isDisabled, width: iconS, height: iconS),
),
), ),
Visibility( if (text.isNotEmpty)
visible: text.isNotEmpty, Text(
child: Padding( text,
padding: EdgeInsets.only(top: 0), overflow: textOverflow ?? TextOverflow.ellipsis,
child: Text( maxLines: 1,
text, textAlign: TextAlign.center,
overflow: textOverflow, style: context.dynamicTextStyle(
style: context.dynamicTextStyle( fontSize: fontS,
fontSize: fontS, color: isDisabled ? AppColors.greyTextColor : textColor,
color: isDisabled ? AppColors.greyTextColor : textColor, letterSpacing: 0,
letterSpacing: 0, fontWeight: fontWeight,
fontWeight: fontWeight,
),
), ),
), ),
),
], ],
), ),
)); ));

@ -42,13 +42,13 @@ class BottomSheetUtils{
Future<void> _showReminderBottomSheet(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, Future<void> _showReminderBottomSheet(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted,
{required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async { {required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async {
showCommonBottomSheetWithoutHeight(providedContext, title: LocaleKeys.setTimerOfReminder.tr(), child: PrescriptionReminderView( showCommonBottomSheetWithoutHeight(providedContext, title: LocaleKeys.setTimerOfReminder.tr(context: providedContext), child: PrescriptionReminderView(
setReminder: (int value) async { setReminder: (int value) async {
if (!isMultiAllowed!) { if (!isMultiAllowed!) {
if (onMultiDateSuccess == null) { if (onMultiDateSuccess == null) {
CalenderUtilsNew calendarUtils = CalenderUtilsNew.instance; CalenderUtilsNew calendarUtils = CalenderUtilsNew.instance;
await calendarUtils.createOrUpdateEvent( await calendarUtils.createOrUpdateEvent(
title: title ?? LocaleKeys.youHaveAppointmentWithDr.tr() + doctorName, title: title ?? LocaleKeys.youHaveAppointmentWithDr.tr(context: providedContext) + doctorName,
description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted,
scheduleDateTime: dateTime, scheduleDateTime: dateTime,
eventId: eventId, eventId: eventId,

@ -282,9 +282,9 @@ class ExpandableListTheme {
dividerColor: dividerColor ?? Colors.grey.shade300, dividerColor: dividerColor ?? Colors.grey.shade300,
defaultTrailingIcon: defaultTrailingIcon ?? defaultTrailingIcon: defaultTrailingIcon ??
Icon(Icons.keyboard_arrow_down, color: Colors.black, size: 24), Icon(Icons.keyboard_arrow_down, color: Colors.black, size: 24),
itemPadding: itemPadding ?? const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), itemPadding: itemPadding ?? EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
contentPadding: contentPadding ?? const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0), contentPadding: contentPadding ?? EdgeInsets.only(left: 16.w, right: 16.w, bottom: 16.h),
leadingSpacing: leadingSpacing ?? 12.0, leadingSpacing: leadingSpacing ?? 12.w,
); );
} }
} }

@ -153,10 +153,18 @@ class TextInputWidget extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildLabelText(labelColor).paddingOnly(right: (appState.getLanguageCode() == "ar" ? 10 : 0)), _buildLabelText(labelColor).paddingOnly(
right: (appState.getLanguageCode() == "ar" ? 10 : 0),
left: (appState.getLanguageCode() == "en" ? 10 : 0),
),
Row( Row(
children: [ children: [
Expanded(child: _buildTextField(context)), Expanded(
child: _buildTextField(context).paddingOnly(
right: (appState.getLanguageCode() == "ar" ? 10 : 0),
left: (appState.getLanguageCode() == "en" ? 10 : 0),
),
)
], ],
), ),
], ],
@ -191,7 +199,7 @@ class TextInputWidget extends StatelessWidget {
return Container( return Container(
height: 40.h, height: 40.h,
width: 40.h, width: 40.h,
margin: EdgeInsets.only(right: 10.h), // margin: EdgeInsets.symmetric(horizontal: 10.w),
padding: EdgeInsets.all(8.h), padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
borderRadius: 12.r, borderRadius: 12.r,
@ -204,7 +212,7 @@ class TextInputWidget extends StatelessWidget {
final AppState appState = getIt.get<AppState>(); final AppState appState = getIt.get<AppState>();
return Container( return Container(
height: 40.h, height: 40.h,
width: 40.h, width: 40.w,
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
padding: EdgeInsets.all(8.h), padding: EdgeInsets.all(8.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.whiteColor), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 12.r, color: AppColors.whiteColor),

Loading…
Cancel
Save