Merge pull request 'haroon_dev' (#204) from haroon_dev into master

Reviewed-on: https://34.17.182.140/Haroon6138/HMG_Patient_App_New/pulls/204
master
Haroon6138 2 days ago
commit ecdef5f057

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

@ -187,7 +187,7 @@
"lastName": "اسم العائلة", "lastName": "اسم العائلة",
"female": "أنثى", "female": "أنثى",
"male": "ذكر", "male": "ذكر",
"preferredLanguage": "اللغة المفضلة *", "preferredLanguage": "اللغة المفضلة",
"locationsRegister": "أين ترغب في إنشاء هذا الملف؟", "locationsRegister": "أين ترغب في إنشاء هذا الملف؟",
"ksa": "السعودية", "ksa": "السعودية",
"dubai": "دبي", "dubai": "دبي",
@ -1612,7 +1612,10 @@
"verifyInsurance": "التحقق من التأمين", "verifyInsurance": "التحقق من التأمين",
"tests": "تحليل", "tests": "تحليل",
"calendarPermissionAlert": "يرجى منح إذن الوصول إلى التقويم من إعدادات التطبيق لضبط تذكير تناول الدواء.", "calendarPermissionAlert": "يرجى منح إذن الوصول إلى التقويم من إعدادات التطبيق لضبط تذكير تناول الدواء.",
"sortByNearestLocation": "فرز حسب الأقرب إلى موقعك",
"giveLocationPermissionForNearestList": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق لعرض أقرب المواقع.",
"sortByLocation": "الترتيب حسب الموقع", "sortByLocation": "الترتيب حسب الموقع",
"timeForFirstReminder": "وقت التذكير الأول", "timeForFirstReminder": "وقت التذكير الأول",
"reminderRemovalNote": "يمكنك إزالتها من التقويم الخاص بك لاحقاً عن طريق إيقاف تشغيل التذكير" "reminderRemovalNote": "يمكنك إزالتها من التقويم الخاص بك لاحقاً عن طريق إيقاف تشغيل التذكير",
"communicationLanguage": "لغة التواصل"
} }

@ -187,7 +187,7 @@
"lastName": "Last Name", "lastName": "Last Name",
"female": "Female", "female": "Female",
"male": "Male", "male": "Male",
"preferredLanguage": "Preferred Language *", "preferredLanguage": "Preferred Language",
"locationsRegister": "Where do you want to create this file?", "locationsRegister": "Where do you want to create this file?",
"ksa": "KSA", "ksa": "KSA",
"dubai": "Dubai", "dubai": "Dubai",
@ -1605,7 +1605,10 @@
"verifyInsurance": "Verify Insurance", "verifyInsurance": "Verify Insurance",
"tests": "tests", "tests": "tests",
"calendarPermissionAlert": "Please grant calendar access permission from app settings to set medication reminder.", "calendarPermissionAlert": "Please grant calendar access permission from app settings to set medication reminder.",
"sortByLocation": "Sort by location",
"timeForFirstReminder": "Time for 1st reminder", "timeForFirstReminder": "Time for 1st reminder",
"reminderRemovalNote": "You can remove it from your calendar later by switching off the reminder" "reminderRemovalNote": "You can remove it from your calendar later by switching off the reminder",
"sortByLocation": "Sort by location",
"sortByNearestLocation": "Sort by nearest to your location",
"giveLocationPermissionForNearestList": "Please grant location permission from app settings to see the nearest locations.",
"communicationLanguage": "Communication Language"
} }

@ -233,7 +233,7 @@ class ApiConsts {
static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API"; static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
// ************ static values for Api **************** // ************ static values for Api ****************
static final double appVersionID = 20.5; static final double appVersionID = 20.9;
// static final double appVersionID = 50.7; // static final double appVersionID = 50.7;
static final int appChannelId = 3; static final int appChannelId = 3;

@ -359,6 +359,11 @@ class AppAssets {
static const String homeHealthCareService = '$pngBasePath/home_health_care.png'; static const String homeHealthCareService = '$pngBasePath/home_health_care.png';
static const String pharmacyService = '$pngBasePath/pharmacy_service.png'; static const String pharmacyService = '$pngBasePath/pharmacy_service.png';
static const String bloodDonationService = '$pngBasePath/blood_donation_image.png';
static const String waterConsumptionService = '$pngBasePath/water_consumption_image.png';
static const String emergencyService = '$pngBasePath/emergency_services_image.png';
static const String cmcService = '$pngBasePath/cmc_services_image.png';
static const String eReferralService = '$pngBasePath/ereferral_services_image.png';
static const String maleImg = '$pngBasePath/male_img.png'; static const String maleImg = '$pngBasePath/male_img.png';
static const String femaleImg = '$pngBasePath/female_img.png'; static const String femaleImg = '$pngBasePath/female_img.png';

@ -169,7 +169,7 @@ class AppState {
///this will be called if there is any problem in getting the user location ///this will be called if there is any problem in getting the user location
void resetLocation() { void resetLocation() {
userLong = 0.0; userLong = 0.0;
userLong = 0.0; userLat = 0.0;
} }
setRatedVisible(bool value) { setRatedVisible(bool value) {

@ -382,7 +382,7 @@ class Utils {
children: [ children: [
Lottie.asset(AppAnimations.checkmark, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill), Lottie.asset(AppAnimations.checkmark, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h), SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor), (loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 8.h), SizedBox(height: 8.h),
], ],
).center; ).center;
@ -396,7 +396,7 @@ class Utils {
Lottie.asset(AppAnimations.errorAnimation, Lottie.asset(AppAnimations.errorAnimation,
repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill), repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h), SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor), (loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 8.h), SizedBox(height: 8.h),
], ],
).center; ).center;
@ -769,20 +769,20 @@ class Utils {
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Image.asset(AppAssets.mada, width: 25.h, height: 25.h), Image.asset(AppAssets.mada, width: 35.h, height: 35.h),
Image.asset( Image.asset(
AppAssets.tamaraEng, AppAssets.tamaraEng,
width: 25.h, width: 35.h,
height: 25.h, height: 35.h,
fit: BoxFit.contain, fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) { errorBuilder: (context, error, stackTrace) {
debugPrint('Failed to load Tamara PNG in payment methods: $error'); debugPrint('Failed to load Tamara PNG in payment methods: $error');
return Utils.buildSvgWithAssets(icon: AppAssets.tamara, width: 25.h, height: 25.h, fit: BoxFit.contain); return Utils.buildSvgWithAssets(icon: AppAssets.tamara, width: 35.h, height: 35.h, fit: BoxFit.contain);
}, },
), ),
Image.asset(AppAssets.visa, width: 25.h, height: 25.h), Image.asset(AppAssets.visa, width: 35.h, height: 35.h),
Image.asset(AppAssets.mastercard, width: 25.h, height: 25.h), Image.asset(AppAssets.mastercard, width: 35.h, height: 25.h),
Image.asset(AppAssets.applePay, width: 25.h, height: 25.h), Image.asset(AppAssets.applePay, width: 35.h, height: 35.h),
], ],
); );
} }

@ -48,13 +48,14 @@ class VitalSignUiModel {
); );
} }
if (s.contains('low')) { // Warning for both low and overweight/underweight BMI, since they can indicate potential health issues.
final Color yellowBg = AppColors.warningColor.withValues(alpha: 0.12); if (s.contains('low') || s.contains('underweight') || s.contains('overweight')) {
final Color yellowBg = AppColors.highAndLow.withValues(alpha: 0.12);
return VitalSignUiModel( return VitalSignUiModel(
iconBg: yellowBg, iconBg: yellowBg,
iconFg: AppColors.warningColor, iconFg: AppColors.highAndLow,
chipBg: yellowBg, chipBg: yellowBg,
chipFg: AppColors.warningColor, chipFg: AppColors.highAndLow,
); );
} }
@ -91,12 +92,27 @@ class VitalSignUiModel {
} }
static String bmiStatus(dynamic bmi) { static String bmiStatus(dynamic bmi) {
if (bmi == null) return 'N/A'; String bmiStatus = 'Normal';
final double bmiValue = double.tryParse(bmi.toString()) ?? 0; final double bmiResult = double.tryParse(bmi.toString()) ?? 0;
if (bmiValue < 18.5) return 'Underweight';
if (bmiValue < 25) return 'Normal'; if (bmiResult >= 30) {
if (bmiValue < 30) return 'Overweight'; bmiStatus = "High";
return 'High'; } else if (bmiResult < 30 && bmiResult >= 25) {
bmiStatus = "Overweight";
} else if (bmiResult < 25 && bmiResult >= 18.5) {
bmiStatus = "Normal";
} else if (bmiResult < 18.5) {
bmiStatus = "Underweight";
}
// if (bmi == null) return 'N/A';
// final double bmiValue = double.tryParse(bmi.toString()) ?? 0;
// if (bmiValue < 18.5) return 'Underweight';
// if (bmiValue < 25) return 'Normal';
// if (bmiValue < 30) return 'Overweight';
// return 'High';
return bmiStatus;
} }
} }

@ -43,9 +43,20 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier {
int hmgCount = 0; int hmgCount = 0;
int hmcCount = 0; int hmcCount = 0;
RegionBottomSheetType regionBottomSheetType = RegionBottomSheetType.FOR_REGION; RegionBottomSheetType regionBottomSheetType = RegionBottomSheetType.FOR_REGION;
bool sortByLocation = false;
AppointmentViaRegionViewmodel({required this.navigationService,required this.appState}); AppointmentViaRegionViewmodel({required this.navigationService,required this.appState});
void initSortByLocation() {
sortByLocation = (appState.userLat != 0.0) && (appState.userLong != 0.0);
notifyListeners();
}
void setSortByLocation(bool value) {
sortByLocation = value;
notifyListeners();
}
void setSelectedRegionId(String? regionId) { void setSelectedRegionId(String? regionId) {
selectedRegionId = regionId; selectedRegionId = regionId;
notifyListeners(); notifyListeners();
@ -122,6 +133,7 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier {
setFacility(null); setFacility(null);
setBottomSheetType(RegionBottomSheetType.FOR_REGION); setBottomSheetType(RegionBottomSheetType.FOR_REGION);
setBottomSheetState(AppointmentViaRegionState.REGION_SELECTION); setBottomSheetState(AppointmentViaRegionState.REGION_SELECTION);
sortByLocation = false;
} }
void setHospitalModel(PatientDoctorAppointmentList? hospital) { void setHospitalModel(PatientDoctorAppointmentList? hospital) {

@ -0,0 +1,136 @@
class GetPatientInfoForUpdate {
int? projectID;
int? patientType;
int? patientID;
String? emailAddress;
bool? isEmailAlertRequired;
bool? isSMSAlertRequired;
String? preferredLanguage;
String? emergencyContactName;
String? emergencyContactNo;
int? editedBy;
String? editedOn;
String? patientIdentificationNo;
int? patientIdentificationType;
String? firstName;
String? middleName;
String? lastName;
int? gender;
String? dateofBirth;
String? dateofBirthN;
String? firstNameN;
String? middleNameN;
String? lastNameN;
int? projectID1;
int? patientType1;
int? patientID1;
bool? isIVRStopped;
String? aGE;
String? genderString;
bool? isNeedUpdateIdintificationNo;
String? nationality;
String? type;
GetPatientInfoForUpdate(
{this.projectID,
this.patientType,
this.patientID,
this.emailAddress,
this.isEmailAlertRequired,
this.isSMSAlertRequired,
this.preferredLanguage,
this.emergencyContactName,
this.emergencyContactNo,
this.editedBy,
this.editedOn,
this.patientIdentificationNo,
this.patientIdentificationType,
this.firstName,
this.middleName,
this.lastName,
this.gender,
this.dateofBirth,
this.dateofBirthN,
this.firstNameN,
this.middleNameN,
this.lastNameN,
this.projectID1,
this.patientType1,
this.patientID1,
this.isIVRStopped,
this.aGE,
this.genderString,
this.isNeedUpdateIdintificationNo,
this.nationality,
this.type});
GetPatientInfoForUpdate.fromJson(Map<String, dynamic> json) {
projectID = json['ProjectID'];
patientType = json['PatientType'];
patientID = json['PatientID'];
emailAddress = json['EmailAddress'];
isEmailAlertRequired = json['IsEmailAlertRequired'];
isSMSAlertRequired = json['IsSMSAlertRequired'];
preferredLanguage = json['PreferredLanguage'];
emergencyContactName = json['EmergencyContactName'];
emergencyContactNo = json['EmergencyContactNo'];
editedBy = json['EditedBy'];
editedOn = json['EditedOn'];
patientIdentificationNo = json['PatientIdentificationNo'];
patientIdentificationType = json['PatientIdentificationType'];
firstName = json['FirstName'];
middleName = json['MiddleName'];
lastName = json['LastName'];
gender = json['Gender'];
dateofBirth = json['DateofBirth'];
dateofBirthN = json['DateofBirthN'];
firstNameN = json['FirstNameN'];
middleNameN = json['MiddleNameN'];
lastNameN = json['LastNameN'];
projectID1 = json['ProjectID1'];
patientType1 = json['PatientType1'];
patientID1 = json['PatientID1'];
isIVRStopped = json['IsIVRStopped'];
aGE = json['AGE'];
genderString = json['GenderString'];
isNeedUpdateIdintificationNo = json['IsNeedUpdateIdintificationNo'];
nationality = json['Nationality'];
type = json['Type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ProjectID'] = this.projectID;
data['PatientType'] = this.patientType;
data['PatientID'] = this.patientID;
data['EmailAddress'] = this.emailAddress;
data['IsEmailAlertRequired'] = this.isEmailAlertRequired;
data['IsSMSAlertRequired'] = this.isSMSAlertRequired;
data['PreferredLanguage'] = this.preferredLanguage;
data['EmergencyContactName'] = this.emergencyContactName;
data['EmergencyContactNo'] = this.emergencyContactNo;
data['EditedBy'] = this.editedBy;
data['EditedOn'] = this.editedOn;
data['PatientIdentificationNo'] = this.patientIdentificationNo;
data['PatientIdentificationType'] = this.patientIdentificationType;
data['FirstName'] = this.firstName;
data['MiddleName'] = this.middleName;
data['LastName'] = this.lastName;
data['Gender'] = this.gender;
data['DateofBirth'] = this.dateofBirth;
data['DateofBirthN'] = this.dateofBirthN;
data['FirstNameN'] = this.firstNameN;
data['MiddleNameN'] = this.middleNameN;
data['LastNameN'] = this.lastNameN;
data['ProjectID1'] = this.projectID1;
data['PatientType1'] = this.patientType1;
data['PatientID1'] = this.patientID1;
data['IsIVRStopped'] = this.isIVRStopped;
data['AGE'] = this.aGE;
data['GenderString'] = this.genderString;
data['IsNeedUpdateIdintificationNo'] = this.isNeedUpdateIdintificationNo;
data['Nationality'] = this.nationality;
data['Type'] = this.type;
return data;
}
}

@ -3,6 +3,7 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/profile_settings/models/get_patient_info_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class ProfileSettingsRepo { abstract class ProfileSettingsRepo {
@ -13,6 +14,8 @@ abstract class ProfileSettingsRepo {
/// Deactivates (deletes) the patient's account. /// Deactivates (deletes) the patient's account.
Future<Either<Failure, GenericApiModel<dynamic>>> deactivateAccount(); Future<Either<Failure, GenericApiModel<dynamic>>> deactivateAccount();
Future<Either<Failure, GenericApiModel<dynamic>>> getProfileSettings();
} }
class ProfileSettingsRepoImp implements ProfileSettingsRepo { class ProfileSettingsRepoImp implements ProfileSettingsRepo {
@ -96,5 +99,43 @@ class ProfileSettingsRepoImp implements ProfileSettingsRepo {
return Left(UnknownFailure(e.toString())); return Left(UnknownFailure(e.toString()));
} }
} }
@override
Future<Either<Failure, GenericApiModel>> getProfileSettings() async {
final Map<String, dynamic> body = {};
try {
GenericApiModel<GetPatientInfoForUpdate>? apiResponse;
Failure? failure;
await apiClient.post(
PROFILE_SETTING,
body: body,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final patientProfileInfo = GetPatientInfoForUpdate.fromJson(response['PateintInfoForUpdateList'][0]);
apiResponse = GenericApiModel<GetPatientInfoForUpdate>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: errorMessage,
data: patientProfileInfo,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
} }

@ -1,8 +1,16 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/features/profile_settings/models/get_patient_info_response_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.dart'; import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/preferred_language_widget.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
class ProfileSettingsViewModel extends ChangeNotifier { class ProfileSettingsViewModel extends ChangeNotifier {
static const String _darkModeKey = 'is_dark_mode'; static const String _darkModeKey = 'is_dark_mode';
@ -30,6 +38,9 @@ class ProfileSettingsViewModel extends ChangeNotifier {
bool isDeactivateAccountSuccess = false; bool isDeactivateAccountSuccess = false;
String? deactivateAccountError; String? deactivateAccountError;
late GetPatientInfoForUpdate getPatientInfoForUpdate;
bool isPatientProfileLoading = false;
ProfileSettingsViewModel({ ProfileSettingsViewModel({
required CacheService cacheService, required CacheService cacheService,
required this.profileSettingsRepo, required this.profileSettingsRepo,
@ -88,6 +99,34 @@ class ProfileSettingsViewModel extends ChangeNotifier {
); );
} }
Future<void> getProfileSettings({
Function(dynamic)? onSuccess,
Function(String)? onError,
}) async {
isPatientProfileLoading = true;
notifyListeners();
final result = await profileSettingsRepo.getProfileSettings();
result.fold(
(failure) {
isPatientProfileLoading = false;
notifyListeners();
if (onError != null) {
onError(failure.message);
} else {
errorHandlerService.handleError(failure: failure);
}
},
(response) {
getPatientInfoForUpdate = response.data;
isPatientProfileLoading = false;
notifyListeners();
onSuccess?.call(response.data);
},
);
}
// Deactivate account // Deactivate account
Future<void> deactivateAccount({ Future<void> deactivateAccount({
@ -123,7 +162,14 @@ class ProfileSettingsViewModel extends ChangeNotifier {
// Helpers // Helpers
void notify() { openPreferredLanguageBottomSheet() {
notifyListeners(); showCommonBottomSheetWithoutHeight(
title: LocaleKeys.preferredLanguage.tr(),
GetIt.instance<NavigationService>().navigatorKey.currentContext!,
child: PreferredLanguageWidget(),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} }
} }

@ -1604,9 +1604,12 @@ abstract class LocaleKeys {
static const verifyInsurance = 'verifyInsurance'; static const verifyInsurance = 'verifyInsurance';
static const tests = 'tests'; static const tests = 'tests';
static const calendarPermissionAlert = 'calendarPermissionAlert'; static const calendarPermissionAlert = 'calendarPermissionAlert';
static const sortByNearestLocation = 'sortByNearestLocation';
static const giveLocationPermissionForNearestList = 'giveLocationPermissionForNearestList';
static const sortByLocation = 'sortByLocation'; static const sortByLocation = 'sortByLocation';
static const timeForFirstReminder = 'timeForFirstReminder'; static const timeForFirstReminder = 'timeForFirstReminder';
static const reminderRemovalNote = 'reminderRemovalNote'; static const reminderRemovalNote = 'reminderRemovalNote';
static const communicationLanguage = 'communicationLanguage';
static const featureComingSoonDescription = 'featureComingSoonDescription'; static const featureComingSoonDescription = 'featureComingSoonDescription';
} }

@ -286,7 +286,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
Positioned( Positioned(
bottom: 0, bottom: 0,
child: SizedBox( child: SizedBox(
width: MediaQuery.of(context).size.width * 0.785, width: MediaQuery.of(context).size.width - 85.w,
child: CustomButton( child: CustomButton(
onPressed: () async { onPressed: () async {
if (widget.patientAppointmentHistoryResponseModel.projectID == 130 || widget.patientAppointmentHistoryResponseModel.projectID == 120) { if (widget.patientAppointmentHistoryResponseModel.projectID == 130 || widget.patientAppointmentHistoryResponseModel.projectID == 120) {
@ -394,7 +394,6 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
}, },
isMultiAllowed: true, isMultiAllowed: true,
onMultiDateSuccess: (int selectedIndex) async { onMultiDateSuccess: (int selectedIndex) async {
isEventAddedOrRemoved = await calender.createOrUpdateEvent( isEventAddedOrRemoved = await calender.createOrUpdateEvent(
title: title:
"Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}", "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget.patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}",
@ -822,8 +821,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
child: LocaleKeys.upcomingPaymentNow child: LocaleKeys.upcomingPaymentNow
.tr(context: context) .tr(context: context)
.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)), .toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor)),
"VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})" "VAT 15%(${widget.patientAppointmentHistoryResponseModel.patientTaxAmount})".toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -0.64),
.toText14(isBold: true, color: AppColors.greyTextColor, letterSpacing: -2),
], ],
), ),
SizedBox(height: 18.h), SizedBox(height: 18.h),
@ -831,7 +829,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox( SizedBox(
width: 150.h, width: 200.h,
child: Utils.getPaymentMethods(), child: Utils.getPaymentMethods(),
), ),
Row( Row(

@ -1,11 +1,13 @@
import 'package:easy_localization/easy_localization.dart' show StringTranslateExtension; import 'package:easy_localization/easy_localization.dart' show StringTranslateExtension;
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/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/debouncer.dart'; import 'package:hmg_patient_app_new/core/utils/debouncer.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/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/core/utils/utils.dart' show Utils;
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@ -14,7 +16,6 @@ import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors;
import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../../../features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel;
import '../../../emergency_services/call_ambulance/widgets/type_selection_widget.dart' show TypeSelectionWidget; import '../../../emergency_services/call_ambulance/widgets/type_selection_widget.dart' show TypeSelectionWidget;
// class HospitalBottomSheetBody extends StatelessWidget { // class HospitalBottomSheetBody extends StatelessWidget {
@ -125,12 +126,26 @@ class HospitalBottomSheetBody extends StatelessWidget {
final Function(FacilitySelection) onFacilityClicked; final Function(FacilitySelection) onFacilityClicked;
final Function(PatientDoctorAppointmentList) onHospitalClicked; final Function(PatientDoctorAppointmentList) onHospitalClicked;
final Function(String) onHospitalSearch; final Function(String) onHospitalSearch;
final bool sortByLocation;
final Function(bool)? onSortByLocationToggle;
HospitalBottomSheetBody({super.key, required this.hmcCount, required this.hmgCount, this.displayList, required this.selectedFacility, required this.onFacilityClicked, required this.onHospitalClicked, required this.onHospitalSearch, required this.searchText}); HospitalBottomSheetBody({super.key, required this.hmcCount, required this.hmgCount, this.displayList, required this.selectedFacility, required this.onFacilityClicked, required this.onHospitalClicked, required this.onHospitalSearch, required this.searchText, this.sortByLocation = false, this.onSortByLocationToggle});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<BookAppointmentsViewModel>(builder: (context, myAppointmentsVM, child) {
if (myAppointmentsVM.isRegionListLoading) {
return Container(
height: MediaQuery.of(context).size.height * 0.3,
decoration: BoxDecoration(
color: AppColors.whiteColor,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Center(
child: Utils.getLoadingWidget(),
),
);
} else {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -145,7 +160,6 @@ class HospitalBottomSheetBody extends StatelessWidget {
}, },
isEnable: true, isEnable: true,
prefix: null, prefix: null,
autoFocus: false, autoFocus: false,
isBorderAllowed: false, isBorderAllowed: false,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
@ -156,7 +170,37 @@ class HospitalBottomSheetBody extends StatelessWidget {
horizontal: ResponsiveExtension(15).h, horizontal: ResponsiveExtension(15).h,
), ),
), ),
SizedBox(height: 24.h), SizedBox(height: 16.h),
if (onSortByLocationToggle != null)
Padding(
padding: EdgeInsets.symmetric(horizontal: 4.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.location, iconColor: AppColors.greyTextColor, width: 18.h, height: 18.h),
SizedBox(width: 8.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.sortByLocation.tr(context: context).toText14(isBold: true),
// SizedBox(height: 4.h),
LocaleKeys.sortByNearestLocation.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
],
),
Switch(
value: sortByLocation,
onChanged: onSortByLocationToggle,
activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: 0.15),
),
],
),
),
if (onSortByLocationToggle != null) SizedBox(height: 8.h),
TypeSelectionWidget( TypeSelectionWidget(
selectedFacility: selectedFacility, selectedFacility: selectedFacility,
hmcCount: hmcCount.toString(), hmcCount: hmcCount.toString(),
@ -169,15 +213,15 @@ class HospitalBottomSheetBody extends StatelessWidget {
SizedBox( SizedBox(
height: MediaQuery.sizeOf(context).height * .4, height: MediaQuery.sizeOf(context).height * .4,
child: ListView.separated( child: ListView.separated(
itemBuilder: (_, index) itemBuilder: (_, index) {
{
var hospital = displayList?[index]; var hospital = displayList?[index];
return HospitalListItem( return HospitalListItem(
hospitalData: hospital, hospitalData: hospital,
isLocationEnabled: true, isLocationEnabled: sortByLocation,
).onPress(() { ).onPress(() {
onHospitalClicked(hospital!); onHospitalClicked(hospital!);
});}, });
},
separatorBuilder: (_, __) => SizedBox( separatorBuilder: (_, __) => SizedBox(
height: 16.h, height: 16.h,
), ),
@ -186,5 +230,7 @@ class HospitalBottomSheetBody extends StatelessWidget {
], ],
); );
} }
});
}
} }

@ -97,14 +97,14 @@ class HospitalListItem extends StatelessWidget {
// ) // )
], ],
)), )),
Visibility( // Visibility(
visible: !isLocationEnabled, // visible: !isLocationEnabled,
child: AppCustomChipWidget( // child: AppCustomChipWidget(
labelText: "Location turned off", // labelText: "Location turned off",
deleteIcon: AppAssets.location_unavailable, // deleteIcon: AppAssets.location_unavailable,
deleteIconSize: Size(9.w, 12.h), // deleteIconSize: Size(9.w, 12.h),
textColor: AppColors.blackColor, // textColor: AppColors.blackColor,
)), // )),
], ],
); );
} }

@ -3,6 +3,9 @@ import 'dart:async';
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_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.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/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils; import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils;
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -14,6 +17,7 @@ import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bot
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/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:lottie/lottie.dart'; import 'package:lottie/lottie.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -33,6 +37,7 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
@override @override
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
regionalViewModel.initSortByLocation();
if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION || regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER ) { if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION || regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER ) {
myAppointmentsViewModel.getRegionMappedProjectList(); myAppointmentsViewModel.getRegionMappedProjectList();
} else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) {
@ -110,6 +115,41 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
} else { } else {
return SizedBox( return SizedBox(
height: MediaQuery.of(context).size.height * 0.5, height: MediaQuery.of(context).size.height * 0.5,
child: Column(
children: [
Consumer<AppointmentViaRegionViewmodel>(
builder: (context, regionVM, _) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 4.w, vertical: 8.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.location, iconColor: AppColors.greyTextColor, width: 24.h, height: 24.h),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.sortByLocation.tr(context: context).toText14(isBold: true),
// SizedBox(height: 4.h),
LocaleKeys.sortByNearestLocation.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
],
),
Switch(
value: regionVM.sortByLocation,
onChanged: (value) => _handleSortByLocationToggle(value),
activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: 0.15),
),
],
),
);
},
),
Expanded(
child: ListView.separated( child: ListView.separated(
itemCount: myAppointmentsVM.hospitalList?.registeredDoctorMap?.length ?? 0, itemCount: myAppointmentsVM.hospitalList?.registeredDoctorMap?.length ?? 0,
separatorBuilder: (_, __) { separatorBuilder: (_, __) {
@ -131,9 +171,80 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
}); });
}, },
), ),
),
],
),
); );
} }
}, },
); );
} }
void _handleSortByLocationToggle(bool value) {
if (value) {
// User wants to sort by location check permission & get location
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionalViewModel.setSortByLocation(true);
if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION || regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) {
myAppointmentsViewModel.getRegionMappedProjectList();
} else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) {
myAppointmentsViewModel.getMappedDoctors();
}
},
onFailure: () {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context),
isShowActionButtons: true,
onCancelTap: () {
Navigator.of(context).pop();
},
onConfirmTap: () async {
Navigator.of(context).pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
regionalViewModel.setSortByLocation(false);
},
onLocationDeniedForever: () {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context),
isShowActionButtons: true,
onCancelTap: () {
Navigator.of(context).pop();
},
onConfirmTap: () async {
Navigator.of(context).pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
regionalViewModel.setSortByLocation(false);
},
);
} else {
// User turned off sort by location reset location & re-fetch
final appState = getIt.get<AppState>();
appState.resetLocation();
regionalViewModel.setSortByLocation(false);
if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION || regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) {
myAppointmentsViewModel.getRegionMappedProjectList();
} else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) {
myAppointmentsViewModel.getMappedDoctors();
}
}
}
} }

@ -7,6 +7,7 @@ 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/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/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/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';
@ -32,6 +33,7 @@ import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart' show showC
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart'; import '../appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart';
@ -57,7 +59,7 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
scheduleMicrotask(() { scheduleMicrotask(() {
// bookAppointmentsViewModel.selectedTabIndex = 0; // bookAppointmentsViewModel.selectedTabIndex = 0;
bookAppointmentsViewModel.initBookAppointmentViewModel(); bookAppointmentsViewModel.initBookAppointmentViewModel();
bookAppointmentsViewModel.getLocation(); // bookAppointmentsViewModel.getLocation();
immediateLiveCareViewModel.initImmediateLiveCare(); immediateLiveCareViewModel.initImmediateLiveCare();
if (appState.isAuthenticated) { if (appState.isAuthenticated) {
getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors(); getIt.get<MyAppointmentsViewModel>().getPatientMyDoctors();
@ -510,6 +512,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
selectedFacility: data.selectedFacility, selectedFacility: data.selectedFacility,
hmcCount: data.hmcCount, hmcCount: data.hmcCount,
hmgCount: data.hmgCount, hmgCount: data.hmgCount,
sortByLocation: data.sortByLocation,
onSortByLocationToggle: (value) => _handleSortByLocationToggle(value, data),
); );
} }
if (data.bottomSheetState == AppointmentViaRegionState.CLINIC_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.CLINIC_SELECTION) {
@ -523,6 +527,78 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
return SizedBox.shrink(); return SizedBox.shrink();
} }
void _handleSortByLocationToggle(bool value, AppointmentViaRegionViewmodel regionVM) {
if (value) {
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionVM.setSortByLocation(true);
_refreshHospitalListAfterApi(regionVM);
},
onFailure: () {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context),
isShowActionButtons: true,
onCancelTap: () {
Navigator.of(context).pop();
},
onConfirmTap: () async {
Navigator.of(context).pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
regionVM.setSortByLocation(false);
},
onLocationDeniedForever: () {
showCommonBottomSheetWithoutHeight(
title: LocaleKeys.notice.tr(context: context),
context,
child: Utils.getWarningWidget(
loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context),
isShowActionButtons: true,
onCancelTap: () {
Navigator.of(context).pop();
},
onConfirmTap: () async {
Navigator.of(context).pop();
openAppSettings();
}),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
regionVM.setSortByLocation(false);
},
);
} else {
final appState = getIt.get<AppState>();
appState.resetLocation();
regionVM.setSortByLocation(false);
_refreshHospitalListAfterApi(regionVM);
}
}
void _refreshHospitalListAfterApi(AppointmentViaRegionViewmodel regionVM) {
void listener() {
if (!bookAppointmentsViewModel.isRegionListLoading) {
bookAppointmentsViewModel.removeListener(listener);
final selectedRegion = regionVM.selectedRegionId;
if (selectedRegion != null && bookAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion] != null) {
regionVM.setDisplayListAndRegionHospitalList(bookAppointmentsViewModel.hospitalList!.registeredDoctorMap![selectedRegion]);
}
}
}
bookAppointmentsViewModel.addListener(listener);
bookAppointmentsViewModel.getRegionMappedProjectList();
}
getTitle(AppointmentViaRegionViewmodel data) { getTitle(AppointmentViaRegionViewmodel data) {
if (data.selectedRegionId == null) { if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600); return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600);

@ -85,10 +85,12 @@ class DoctorProfilePage extends StatelessWidget {
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
backgroundColor: AppColors.whiteColor,
iconColor: AppColors.ratingColorYellow, iconColor: AppColors.ratingColorYellow,
labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.projectName}", labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.projectName}",
), ),
AppCustomChipWidget( AppCustomChipWidget(
backgroundColor: AppColors.whiteColor,
iconColor: AppColors.ratingColorYellow, iconColor: AppColors.ratingColorYellow,
labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.clinicDescription}", labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.clinicDescription}",
), ),

@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/int_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/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
@ -82,9 +83,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} ${LocaleKeys.yearsOld.tr(context: context)}"), AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} ${LocaleKeys.yearsOld.tr(context: context)}"),
AppCustomChipWidget( AppCustomChipWidget(labelText: "${LocaleKeys.gender.tr(context: context)}: ${appState.getAuthenticatedUser()?.gender == 1 ? LocaleKeys.malE.tr(context: context) : LocaleKeys.femaleGender.tr(context: context)}"),
labelText:
"${LocaleKeys.clinic.tr()}: ${(appState.isArabic() ? immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceNameN : immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceName) ?? ""}"),
], ],
), ),
], ],
@ -105,7 +104,16 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
), ),
child: Padding( child: Padding(
padding: EdgeInsets.all(16.h), padding: EdgeInsets.all(16.h),
child: Row( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppCustomChipWidget(
labelText:
"${LocaleKeys.clinic.tr()}: ${(appState.isArabic() ? immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceNameN : immediateLiveCareVM.immediateLiveCareSelectedClinic.serviceName) ?? ""}"),
SizedBox(height: 16.h),
1.divider,
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
@ -118,6 +126,8 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
Utils.buildSvgWithAssets(icon: AppAssets.edit_icon, width: 24.h, height: 24.h, fit: BoxFit.contain), Utils.buildSvgWithAssets(icon: AppAssets.edit_icon, width: 24.h, height: 24.h, fit: BoxFit.contain),
], ],
), ),
],
),
), ),
).onPress(() { ).onPress(() {
showCommonBottomSheetWithoutHeight(context, child: SelectLiveCareCallType(immediateLiveCareViewModel: immediateLiveCareVM), callBackFunc: () async { showCommonBottomSheetWithoutHeight(context, child: SelectLiveCareCallType(immediateLiveCareViewModel: immediateLiveCareVM), callBackFunc: () async {
@ -202,7 +212,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox(width: 150.h, child: Utils.getPaymentMethods()), SizedBox(width: 200.h, child: Utils.getPaymentMethods()),
Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true), AppColors.blackColor, 17, Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" ||
immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")),

@ -109,8 +109,8 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
SizedBox(height: 12.h), SizedBox(height: 12.h),
Wrap( Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
spacing: 8.h, spacing: 4.h,
runSpacing: 8.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: "${LocaleKeys.clinic.tr(context: context)}: ${bookAppointmentsViewModel.selectedDoctor.clinicName}", labelText: "${LocaleKeys.clinic.tr(context: context)}: ${bookAppointmentsViewModel.selectedDoctor.clinicName}",
@ -156,7 +156,15 @@ class _ReviewAppointmentPageState extends State<ReviewAppointmentPage> {
children: [ children: [
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true), "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Wrap(
direction: Axis.horizontal,
spacing: 4.h,
runSpacing: 4.h,
children: [
AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"), AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"),
AppCustomChipWidget(labelText: "${LocaleKeys.gender.tr(context: context)}: ${appState.getAuthenticatedUser()?.gender == 1 ? LocaleKeys.malE.tr(context: context) : LocaleKeys.femaleGender.tr(context: context)}"),
],
),
], ],
), ),
], ],

@ -52,7 +52,7 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.chooseDoctor.tr(), title: LocaleKeys.chooseDoctor.tr(context: context),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.h), padding: EdgeInsets.symmetric(horizontal: 24.h),
@ -142,49 +142,49 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (bookAppointmentsVM.isDoctorSearchByNameStarted) // if (bookAppointmentsVM.isDoctorSearchByNameStarted)
Row( // Row(
children: [ // children: [
CustomButton( // CustomButton(
text: LocaleKeys.byClinic.tr(context: context), // text: LocaleKeys.byClinic.tr(context: context),
onPressed: () { // onPressed: () {
bookAppointmentsVM.sortFilteredDoctorList(true); // bookAppointmentsVM.sortFilteredDoctorList(true);
}, // },
backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), // borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2),
textColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // textColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
SizedBox(width: 8.h), // SizedBox(width: 8.h),
CustomButton( // CustomButton(
text: LocaleKeys.byHospital.tr(context: context), // text: LocaleKeys.byHospital.tr(context: context),
onPressed: () { // onPressed: () {
bookAppointmentsVM.sortFilteredDoctorList(false); // bookAppointmentsVM.sortFilteredDoctorList(false);
}, // },
backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor, // borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor,
textColor: bookAppointmentsVM.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // textColor: bookAppointmentsVM.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
], // ],
).paddingSymmetrical(0.h, 0.h), // ).paddingSymmetrical(0.h, 0.h),
bookAppointmentsVM.isDoctorSearchByNameStarted bookAppointmentsVM.isDoctorSearchByNameStarted
? ListView.separated( ? ListView.separated(
padding: EdgeInsets.only(top: 20.h), padding: EdgeInsets.only(top: 20.h),
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemCount: bookAppointmentsVM.isDoctorsListLoading ? 5 : bookAppointmentsVM.getGroupedFilteredDoctorsList().length, itemCount: bookAppointmentsVM.isDoctorsListLoading ? 5 : bookAppointmentsVM.filteredDoctorList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final isExpanded = bookAppointmentsVM.expandedGroupIndex == index; // final isExpanded = bookAppointmentsVM.expandedGroupIndex == index;
final groupedDoctors = bookAppointmentsVM.getGroupedFilteredDoctorsList(); // final groupedDoctors = bookAppointmentsVM.getGroupedFilteredDoctorsList();
return bookAppointmentsVM.isDoctorsListLoading return bookAppointmentsVM.isDoctorsListLoading
? DoctorCard( ? DoctorCard(
@ -203,73 +203,15 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, curve: Curves.easeInOut,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: InkWell( child: Container(
onTap: () {
bookAppointmentsVM.toggleGroupExpansion(index);
// After rebuild, ensure the expanded item is visible
WidgetsBinding.instance.addPostFrameCallback((_) {
final key = _itemKeys[index];
if (key != null && key.currentContext != null && bookAppointmentsVM.expandedGroupIndex == index) {
Scrollable.ensureVisible(
key.currentContext!,
duration: Duration(milliseconds: 350),
curve: Curves.easeInOut,
alignment: 0.1,
);
}
});
},
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomButton(
text: "${groupedDoctors[index].length} ${'doctors'}",
onPressed: () {},
backgroundColor: AppColors.greyColor,
borderColor: AppColors.greyColor,
textColor: AppColors.blackColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 30.h),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
],
),
SizedBox(height: 8.h),
// Clinic/Hospital name as group title
Text(
bookAppointmentsVM.isSortByClinic
? (groupedDoctors[index].first.clinicName ?? 'Unknown')
: (groupedDoctors[index].first.projectName ?? 'Unknown'),
style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600),
overflow: TextOverflow.ellipsis,
),
// Expanded content - list of doctors in this group
AnimatedSwitcher(
duration: Duration(milliseconds: 400),
child: isExpanded
? Container(
key: ValueKey<int>(index), key: ValueKey<int>(index),
padding: EdgeInsets.only(top: 12.h), padding: EdgeInsets.only(top: 12.h),
child: Column( child: DoctorCard(
children: groupedDoctors[index].asMap().entries.map<Widget>((entry) { doctorsListResponseModel: bookAppointmentsVM.filteredDoctorList[index],
final doctorIndex = entry.key;
final doctor = entry.value;
final isLastDoctor = doctorIndex == groupedDoctors[index].length - 1;
return Column(
children: [
DoctorCard(
doctorsListResponseModel: doctor,
isLoading: false, isLoading: false,
bookAppointmentsViewModel: bookAppointmentsViewModel, bookAppointmentsViewModel: bookAppointmentsViewModel,
).onPress(() async { ).paddingSymmetrical(16.h, 0.h).onPress(() async {
bookAppointmentsVM.setSelectedDoctor(doctor); bookAppointmentsVM.setSelectedDoctor(bookAppointmentsVM.filteredDoctorList[index]);
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
await bookAppointmentsVM.getDoctorProfile( await bookAppointmentsVM.getDoctorProfile(
onSuccess: (dynamic respData) { onSuccess: (dynamic respData) {
@ -291,24 +233,154 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
); );
}, },
); );
// Column(
// children: bookAppointmentsVM.doctorsList[index].map<Widget>((entry) {
// final doctorIndex = entry.key;
// final doctor = entry.value;
// final isLastDoctor = doctorIndex == groupedDoctors[index].length - 1;
// return Column(
// children: [
// DoctorCard(
// doctorsListResponseModel: doctor,
// isLoading: false,
// bookAppointmentsViewModel: bookAppointmentsViewModel,
// ).onPress(() async {
// bookAppointmentsVM.setSelectedDoctor(doctor);
// LoaderBottomSheet.showLoader();
// await bookAppointmentsVM.getDoctorProfile(
// onSuccess: (dynamic respData) {
// LoaderBottomSheet.hideLoader();
// Navigator.of(context).push(
// CustomPageRoute(
// page: DoctorProfilePage(),
// ),
// );
// },
// onError: (err) {
// LoaderBottomSheet.hideLoader();
// showCommonBottomSheetWithoutHeight(
// context,
// child: Utils.getErrorWidget(loadingText: err),
// callBackFunc: () {},
// isFullScreen: false,
// isCloseButtonVisible: true,
// );
// },
// );
// }),
// if (!isLastDoctor)
// Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// ],
// );
// }).toList(),
// ),
}), }),
if (!isLastDoctor) // InkWell(
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // onTap: () {
], // bookAppointmentsVM.toggleGroupExpansion(index);
); // // After rebuild, ensure the expanded item is visible
}).toList(), // WidgetsBinding.instance.addPostFrameCallback((_) {
), // final key = _itemKeys[index];
) // if (key != null && key.currentContext != null && bookAppointmentsVM.expandedGroupIndex == index) {
: SizedBox.shrink(), // Scrollable.ensureVisible(
), // key.currentContext!,
], // duration: Duration(milliseconds: 350),
), // curve: Curves.easeInOut,
), // alignment: 0.1,
// );
// }
// });
// },
// child: Padding(
// padding: EdgeInsets.all(16.h),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// CustomButton(
// text: "${groupedDoctors[index].length} ${'doctors'}",
// onPressed: () {},
// backgroundColor: AppColors.greyColor,
// borderColor: AppColors.greyColor,
// textColor: AppColors.blackColor,
// fontSize: 10,
// fontWeight: FontWeight.w500,
// borderRadius: 8,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 30.h),
// Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
// ],
// ),
// SizedBox(height: 8.h),
// // Clinic/Hospital name as group title
// Text(
// bookAppointmentsVM.isSortByClinic
// ? (groupedDoctors[index].first.clinicName ?? 'Unknown')
// : (groupedDoctors[index].first.projectName ?? 'Unknown'),
// style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600),
// overflow: TextOverflow.ellipsis,
// ),
// // Expanded content - list of doctors in this group
// // AnimatedSwitcher(
// // duration: Duration(milliseconds: 400),
// // child: isExpanded
// // ? Container(
// // key: ValueKey<int>(index),
// // padding: EdgeInsets.only(top: 12.h),
// // child: Column(
// // children: groupedDoctors[index].asMap().entries.map<Widget>((entry) {
// // final doctorIndex = entry.key;
// // final doctor = entry.value;
// // final isLastDoctor = doctorIndex == groupedDoctors[index].length - 1;
// // return Column(
// // children: [
// // DoctorCard(
// // doctorsListResponseModel: doctor,
// // isLoading: false,
// // bookAppointmentsViewModel: bookAppointmentsViewModel,
// // ).onPress(() async {
// // bookAppointmentsVM.setSelectedDoctor(doctor);
// // LoaderBottomSheet.showLoader();
// // await bookAppointmentsVM.getDoctorProfile(
// // onSuccess: (dynamic respData) {
// // LoaderBottomSheet.hideLoader();
// // Navigator.of(context).push(
// // CustomPageRoute(
// // page: DoctorProfilePage(),
// // ),
// // );
// // },
// // onError: (err) {
// // LoaderBottomSheet.hideLoader();
// // showCommonBottomSheetWithoutHeight(
// // context,
// // child: Utils.getErrorWidget(loadingText: err),
// // callBackFunc: () {},
// // isFullScreen: false,
// // isCloseButtonVisible: true,
// // );
// // },
// // );
// // }),
// // if (!isLastDoctor)
// // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// // ],
// // );
// // }).toList(),
// // ),
// // )
// // : SizedBox.shrink(),
// // ),
// ],
// ),
// ),
// ),
), ),
), ),
), ),
), ));
);
}, },
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
) )

@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -1118,6 +1119,8 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
selectedFacility: data.selectedFacility, selectedFacility: data.selectedFacility,
hmcCount: data.hmcCount, hmcCount: data.hmcCount,
hmgCount: data.hmgCount, hmgCount: data.hmgCount,
sortByLocation: data.sortByLocation,
onSortByLocationToggle: (value) => _handleSortByLocationToggle(value, data),
); );
} }
if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) {
@ -1301,4 +1304,49 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
initDentalAppointmentBookingFlow(int.parse(bookAppointmentsViewModel.currentlySelectedHospitalFromRegionFlow ?? "0")); initDentalAppointmentBookingFlow(int.parse(bookAppointmentsViewModel.currentlySelectedHospitalFromRegionFlow ?? "0"));
return; return;
} }
void _handleSortByLocationToggle(bool value, AppointmentViaRegionViewmodel regionVM) {
if (value) {
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionVM.setSortByLocation(true);
_refreshHospitalListAfterApi(regionVM);
},
onFailure: () {
regionVM.setSortByLocation(false);
},
onLocationDeniedForever: () {
regionVM.setSortByLocation(false);
},
);
} else {
final appState = getIt.get<AppState>();
appState.resetLocation();
regionVM.setSortByLocation(false);
_refreshHospitalListAfterApi(regionVM);
}
}
void _refreshHospitalListAfterApi(AppointmentViaRegionViewmodel regionVM) {
void listener() {
if (!bookAppointmentsViewModel.isRegionListLoading) {
bookAppointmentsViewModel.removeListener(listener);
final selectedRegion = regionVM.selectedRegionId;
if (selectedRegion != null && bookAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion] != null) {
regionVM.setDisplayListAndRegionHospitalList(bookAppointmentsViewModel.hospitalList!.registeredDoctorMap![selectedRegion]);
}
}
}
bookAppointmentsViewModel.addListener(listener);
if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION || regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) {
bookAppointmentsViewModel.getRegionMappedProjectList();
} else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) {
bookAppointmentsViewModel.getMappedDoctors();
}
// bookAppointmentsViewModel.getRegionMappedProjectList();
}
} }

@ -99,12 +99,12 @@ class _AppointmentCalendarState extends State<AppointmentCalendar> {
showNavigationArrow: true, showNavigationArrow: true,
headerHeight: 60.h, headerHeight: 60.h,
headerStyle: CalendarHeaderStyle( headerStyle: CalendarHeaderStyle(
backgroundColor: AppColors.scaffoldBgColor, backgroundColor: AppColors.transparent,
textAlign: TextAlign.start, textAlign: TextAlign.start,
textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"), textStyle: TextStyle(fontSize: 18.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"),
), ),
viewHeaderStyle: ViewHeaderStyle( viewHeaderStyle: ViewHeaderStyle(
backgroundColor: AppColors.scaffoldBgColor, // backgroundColor: AppColors.scaffoldBgColor,
dayTextStyle: TextStyle(fontSize: 14.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor, fontFamily: "Poppins"), dayTextStyle: TextStyle(fontSize: 14.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor, fontFamily: "Poppins"),
), ),
view: CalendarView.month, view: CalendarView.month,

@ -127,23 +127,23 @@ class DoctorCard extends StatelessWidget {
spacing: 3.h, spacing: 3.h,
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget(
labelText: "${isLoading ? "Cardiologist" : doctorsListResponseModel.clinicName}",
).toShimmer2(isShow: isLoading),
AppCustomChipWidget(
labelText: "${isLoading ? "Olaya Hospital" : doctorsListResponseModel.projectName}",
).toShimmer2(isShow: isLoading),
bookAppointmentsViewModel.isNearestAppointmentSelected bookAppointmentsViewModel.isNearestAppointmentSelected
? doctorsListResponseModel.nearestFreeSlot != null ? doctorsListResponseModel.nearestFreeSlot != null
? AppCustomChipWidget( ? AppCustomChipWidget(
// labelText: (isLoading ? "Cardiologist" : DateUtil.getDateStringForNearestSlot(doctorsListResponseModel.nearestFreeSlot)), labelText: (isLoading ? "Cardiologist" : DateUtil.getDateStringForNearestSlot(doctorsListResponseModel.nearestFreeSlot)),
richText: (isLoading ? "Cardiologist" : DateUtil.getDateStringForNearestSlot(doctorsListResponseModel.nearestFreeSlot)) // richText: (isLoading ? "Cardiologist" : DateUtil.getDateStringForNearestSlot(doctorsListResponseModel.nearestFreeSlot))
.toText10(isEnglishOnly: true, color: AppColors.whiteColor), // .toText10(isEnglishOnly: true, color: AppColors.textColor),
backgroundColor: AppColors.successColor, // backgroundColor: AppColors.successColor,
textColor: AppColors.whiteColor, textColor: AppColors.textColor,
).toShimmer2(isShow: isLoading) ).toShimmer2(isShow: isLoading)
: SizedBox.shrink() : SizedBox.shrink()
: SizedBox.shrink(), : SizedBox.shrink(),
AppCustomChipWidget(
labelText: "${isLoading ? "Cardiologist" : doctorsListResponseModel.clinicName}",
).toShimmer2(isShow: isLoading),
AppCustomChipWidget(
labelText: "${isLoading ? "Olaya Hospital" : doctorsListResponseModel.projectName}",
).toShimmer2(isShow: isLoading),
], ],
), ),
], ],
@ -155,7 +155,7 @@ class DoctorCard extends StatelessWidget {
), ),
], ],
), ),
SizedBox(height: 12.h), SizedBox(height: 16.h),
CustomButton( CustomButton(
text: LocaleKeys.bookAppo.tr(context: context), text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () async { onPressed: () async {

@ -14,6 +14,8 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart'; import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/find_us_page.dart'; import 'package:hmg_patient_app_new/presentation/contact_us/find_us_page.dart';
import 'package:hmg_patient_app_new/presentation/contact_us/live_chat_page.dart'; import 'package:hmg_patient_app_new/presentation/contact_us/live_chat_page.dart';
import 'package:hmg_patient_app_new/presentation/home/service_info_page.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/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -80,15 +82,23 @@ class ContactUs extends StatelessWidget {
LocaleKeys.liveChat.tr(), LocaleKeys.liveChat.tr(),
LocaleKeys.liveChatWithHMG.tr(), LocaleKeys.liveChatWithHMG.tr(),
).onPress(() { ).onPress(() {
locationUtils.getCurrentLocation(onSuccess: (value) { if (getIt.get<AppState>().isAuthenticated) {
contactUsViewModel.getLiveChatProjectsList();
Navigator.pop(context);
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
page: LiveChatPage(), page: LiveChatPage(),
), ),
); );
}); } else {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.liveChat.tr(),
serviceHeader: "HMG Hospital E-Referral: Streamlined patient referrals".needTranslation,
serviceDescription: "Facilitate seamless patient transfers to HMG with our secure e-referral system. Ensure continuity of care for every patient.".needTranslation,
serviceImage: AppAssets.eReferralService),
),
);
}
}), }),
], ],
); );

@ -59,7 +59,7 @@ class FindUsPage extends StatelessWidget {
children: [ children: [
LocaleKeys.sortByLocation.tr(context: context).toText14(isBold: true), LocaleKeys.sortByLocation.tr(context: context).toText14(isBold: true),
SizedBox(height: 4.h), SizedBox(height: 4.h),
"Sort the locations by nearest to your location".toText11(color: AppColors.textColorLight, weight: FontWeight.w500), LocaleKeys.sortByNearestLocation.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
], ],
), ),
const Spacer(), const Spacer(),

@ -1,6 +1,8 @@
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_assets.dart'; import 'package:hmg_patient_app_new/core/app_assets.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/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -12,7 +14,9 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/RRT/rrt_request_type_select.dart'; import 'package:hmg_patient_app_new/presentation/emergency_services/RRT/rrt_request_type_select.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart'; import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/ambulance_option_selection_bottomsheet.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/pickup_location.dart'; import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/pickup_location.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/history/er_history_listing.dart'; import 'package:hmg_patient_app_new/presentation/emergency_services/history/er_history_listing.dart';
import 'package:hmg_patient_app_new/presentation/home/service_info_page.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';
@ -22,23 +26,46 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:lottie/lottie.dart'; import 'package:lottie/lottie.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class EmergencyServicesPage extends StatelessWidget { class EmergencyServicesPage extends StatefulWidget {
EmergencyServicesPage({super.key}); EmergencyServicesPage({super.key});
@override
State<EmergencyServicesPage> createState() => _EmergencyServicesPageState();
}
class _EmergencyServicesPageState extends State<EmergencyServicesPage> {
late EmergencyServicesViewModel emergencyServicesViewModel; late EmergencyServicesViewModel emergencyServicesViewModel;
_handleConfirmationBottomSheet() {} late AppState appState;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (appState.isAuthenticated) {
emergencyServicesViewModel.flushData();
emergencyServicesViewModel.getTransportationOrders(
showLoader: false,
);
emergencyServicesViewModel.getRRTOrders(
showLoader: false,
);
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false); emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
appState = getIt.get<AppState>();
return CollapsingListView( return CollapsingListView(
title: LocaleKeys.emergencyServices.tr(), title: LocaleKeys.emergencyServices.tr(),
history: () { history: appState.isAuthenticated
? () {
emergencyServicesViewModel.changeOrderDisplayItems(OrderDislpay.ALL); emergencyServicesViewModel.changeOrderDisplayItems(OrderDislpay.ALL);
Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up)); Navigator.of(context).push(CustomPageRoute(page: ErHistoryListing(), direction: AxisDirection.up));
}, }
: null,
child: Padding( child: Padding(
padding: EdgeInsets.all(24.h), padding: EdgeInsets.all(24.h),
child: Column( child: Column(
@ -60,8 +87,7 @@ class EmergencyServicesPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.callAmbulance.tr().toText16(isBold: true, color: AppColors.blackColor), LocaleKeys.callAmbulance.tr().toText16(isBold: true, color: AppColors.blackColor),
LocaleKeys.requestAmbulanceInEmergency.tr() LocaleKeys.requestAmbulanceInEmergency.tr().toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
.toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
], ],
), ),
), ),
@ -69,6 +95,7 @@ class EmergencyServicesPage extends StatelessWidget {
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, width: 13.h, height: 13.h), Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, width: 13.h, height: 13.h),
], ],
).onPress(() { ).onPress(() {
if(appState.isAuthenticated) {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Container( child: Container(
@ -96,13 +123,11 @@ class EmergencyServicesPage extends StatelessWidget {
}), }),
], ],
), ),
Lottie.asset(AppAnimations.ambulanceAlert, Lottie.asset(AppAnimations.ambulanceAlert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.confirmation.tr().toText28(color: Colors.white, isBold: true), LocaleKeys.confirmation.tr().toText28(color: Colors.white, isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.areYouSureYouWantToCallAmbulance.tr() LocaleKeys.areYouSureYouWantToCallAmbulance.tr().toText14(color: Colors.white, weight: FontWeight.w500),
.toText14(color: Colors.white, 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),
@ -128,6 +153,17 @@ class EmergencyServicesPage extends StatelessWidget {
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
callBackFunc: () {}, callBackFunc: () {},
); );
} else {
Navigator.of(context).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.emergencyServices.tr(),
serviceHeader: "ER Check-in, Faster Than Ever. Call ambulance / Rapid Response Team instantly".needTranslation,
serviceDescription: "In a medical emergency? Our ambulances and rapid response teams are on standby 24/7. Plus, quick ER check-in for faster care.".needTranslation,
serviceImage: AppAssets.emergencyService),
),
);
}
}), }),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -147,8 +183,7 @@ class EmergencyServicesPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.nearester.tr(context: context).toText16(isBold: true, color: AppColors.blackColor), LocaleKeys.nearester.tr(context: context).toText16(isBold: true, color: AppColors.blackColor),
LocaleKeys.getDetailsOfNearestBranch.tr() LocaleKeys.getDetailsOfNearestBranch.tr().toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
.toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
], ],
), ),
), ),
@ -176,8 +211,7 @@ class EmergencyServicesPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.rapidResponseTeam.tr(context: context).toText16(isBold: true, color: AppColors.blackColor), LocaleKeys.rapidResponseTeam.tr(context: context).toText16(isBold: true, color: AppColors.blackColor),
"Comprehensive medical service for all sorts of urgent and stable cases" "Comprehensive medical service for all sorts of urgent and stable cases".toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
.toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
], ],
), ),
), ),
@ -185,6 +219,7 @@ class EmergencyServicesPage extends StatelessWidget {
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, width: 13.h, height: 13.h), Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, width: 13.h, height: 13.h),
], ],
).onPress(() { ).onPress(() {
if(appState.isAuthenticated) {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Container( child: Container(
@ -197,18 +232,31 @@ class EmergencyServicesPage extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"".toText14(),
Utils.buildSvgWithAssets(
icon: AppAssets.cancel_circle_icon,
iconColor: Colors.white,
width: 24.h,
height: 24.h,
fit: BoxFit.contain,
).onPress(() {
Navigator.of(context).pop();
}),
],
),
Lottie.asset(AppAnimations.ambulanceAlert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain), Lottie.asset(AppAnimations.ambulanceAlert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.confirm.tr().toText28(color: Colors.white, isBold: true), LocaleKeys.confirm.tr().toText28(color: Colors.white, isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.areYouSureYouWantToCallRRT.tr() LocaleKeys.areYouSureYouWantToCallRRT.tr().toText14(color: Colors.white, weight: FontWeight.w500),
.toText14(color: Colors.white, 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 { onPressed: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
emergencyServicesViewModel.clearRRTData(); emergencyServicesViewModel.clearRRTData();
await emergencyServicesViewModel.getRRTProcedures(onSuccess: (val) { await emergencyServicesViewModel.getRRTProcedures(onSuccess: (val) {
@ -223,7 +271,6 @@ class EmergencyServicesPage extends StatelessWidget {
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
).onPress(() { ).onPress(() {
Navigator.pop(context); Navigator.pop(context);
}), }),
// title: "Rapid Response Team (RRT)".needTranslation, // title: "Rapid Response Team (RRT)".needTranslation,
@ -256,6 +303,17 @@ class EmergencyServicesPage extends StatelessWidget {
context.read<EmergencyServicesViewModel>().setTermsAndConditions(false); context.read<EmergencyServicesViewModel>().setTermsAndConditions(false);
}, },
); );
} else {
Navigator.of(context).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.emergencyServices.tr(),
serviceHeader: "ER Check-in, Faster Than Ever. Call ambulance / Rapid Response Team instantly".needTranslation,
serviceDescription: "In a medical emergency? Our ambulances and rapid response teams are on standby 24/7. Plus, quick ER check-in for faster care.".needTranslation,
serviceImage: AppAssets.emergencyService),
),
);
}
}), }),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -275,8 +333,7 @@ class EmergencyServicesPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
LocaleKeys.emergencyCheckIn.tr(context: context).toText16(isBold: true, color: AppColors.blackColor), LocaleKeys.emergencyCheckIn.tr(context: context).toText16(isBold: true, color: AppColors.blackColor),
LocaleKeys.priorERCheckInToSkipLine.tr() LocaleKeys.priorERCheckInToSkipLine.tr().toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
.toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500),
], ],
), ),
), ),
@ -284,6 +341,10 @@ class EmergencyServicesPage extends StatelessWidget {
Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, width: 13.h, height: 13.h), Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, width: 13.h, height: 13.h),
], ],
).onPress(() { ).onPress(() {
if(appState.isAuthenticated) {
if (emergencyServicesViewModel.patientHasAdvanceERBalance) {
Navigator.of(context).push(CustomPageRoute(page: ErOnlineCheckinHome()));
} else {
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Container( child: Container(
@ -308,8 +369,7 @@ class EmergencyServicesPage extends StatelessWidget {
}), }),
], ],
), ),
Lottie.asset(AppAnimations.ambulanceAlert, Lottie.asset(AppAnimations.ambulanceAlert, repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
repeat: false, reverse: false, frameRate: FrameRate(60), width: 120.h, height: 120.h, fit: BoxFit.contain),
SizedBox(height: 8.h), SizedBox(height: 8.h),
LocaleKeys.confirm.tr().toText28(color: Colors.white, isBold: true), LocaleKeys.confirm.tr().toText28(color: Colors.white, isBold: true),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -342,6 +402,18 @@ class EmergencyServicesPage extends StatelessWidget {
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
callBackFunc: () {}, callBackFunc: () {},
); );
}
} else {
Navigator.of(context).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.emergencyServices.tr(),
serviceHeader: "ER Check-in, Faster Than Ever. Call ambulance / Rapid Response Team instantly".needTranslation,
serviceDescription: "In a medical emergency? Our ambulances and rapid response teams are on standby 24/7. Plus, quick ER check-in for faster care.".needTranslation,
serviceImage: AppAssets.emergencyService),
),
);
}
}), }),
), ),
], ],

@ -128,7 +128,7 @@ class ErOnlineCheckinPaymentDetailsPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox( SizedBox(
width: 150.h, width: 200.h,
child: Utils.getPaymentMethods(), child: Utils.getPaymentMethods(),
), ),
Row( Row(

@ -468,12 +468,12 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
context, context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)), child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () { callBackFunc: () {
Navigator.pushAndRemoveUntil( // Navigator.pushAndRemoveUntil(
context, // context,
CustomPageRoute( // CustomPageRoute(
page: LandingNavigation(), // page: LandingNavigation(),
), // ),
(r) => false); // (r) => false);
}, },
isFullScreen: false, isFullScreen: false,
isCloseButtonVisible: true, isCloseButtonVisible: true,

@ -26,6 +26,7 @@ import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.
import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/hmg_services/services_view.dart'; import 'package:hmg_patient_app_new/presentation/hmg_services/services_view.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart'; import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
import 'package:hmg_patient_app_new/presentation/home/service_info_page.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.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/parking/paking_page.dart'; import 'package:hmg_patient_app_new/presentation/parking/paking_page.dart';
@ -54,23 +55,23 @@ class ServicesPage extends StatelessWidget {
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(
showLoader: false, // showLoader: false,
); // );
getIt.get<EmergencyServicesViewModel>().getRRTOrders( // getIt.get<EmergencyServicesViewModel>().getRRTOrders(
showLoader: false, // showLoader: false,
); // );
Navigator.of(getIt.get<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'),
), ),
); );
} else { // } else {
await getIt.get<AuthenticationViewModel>().onLoginPressed(); // await getIt.get<AuthenticationViewModel>().onLoginPressed();
} // }
}), }),
HmgServicesComponentModel( HmgServicesComponentModel(
11, 11,
@ -85,7 +86,15 @@ class ServicesPage extends StatelessWidget {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.comprehensiveCheckupPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.comprehensiveCheckupPage);
} else { } else {
await getIt.get<AuthenticationViewModel>().onLoginPressed(); Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.comprehensiveMedicalCheckup.tr(),
serviceHeader: "Complete Health Checkup: Advanced diagnostics, Detailed Health insights".needTranslation,
serviceDescription: "Get detailed insights into your health with our advanced diagnostics. Understand your body better for a healthier future.".needTranslation,
serviceImage: AppAssets.cmcService),
),
);
} }
}), }),
HmgServicesComponentModel( HmgServicesComponentModel(
@ -137,7 +146,15 @@ class ServicesPage extends StatelessWidget {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.eReferralPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.eReferralPage);
} else { } else {
await getIt.get<AuthenticationViewModel>().onLoginPressed(); Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.eReferralServices.tr(),
serviceHeader: "HMG Hospital E-Referral: Streamlined patient referrals".needTranslation,
serviceDescription: "Facilitate seamless patient transfers to HMG with our secure e-referral system. Ensure continuity of care for every patient.".needTranslation,
serviceImage: AppAssets.eReferralService),
),
);
} }
}), }),
HmgServicesComponentModel( HmgServicesComponentModel(
@ -147,7 +164,26 @@ class ServicesPage extends StatelessWidget {
AppAssets.blood_donation_icon, AppAssets.blood_donation_icon,
bgColor: AppColors.bloodDonationCardColor, bgColor: AppColors.bloodDonationCardColor,
true, true,
route: AppRoutes.bloodDonationPage, route: null,
onTap: () {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: BloodDonationPage(),
),
);
} else {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.bloodDonation.tr(),
serviceHeader: "Give Blood, Save Lives. Your donation makes a difference.".needTranslation,
serviceDescription: "Donate blood, empower lives. Your contribution creates hope. Join our blood drive and be a lifeline for those in need. Every drop counts!".needTranslation,
serviceImage: AppAssets.bloodDonationService),
),
);
}
}
), ),
HmgServicesComponentModel( HmgServicesComponentModel(
113, 113,
@ -230,7 +266,15 @@ class ServicesPage extends StatelessWidget {
if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.healthTrackersPage); getIt.get<NavigationService>().pushPageRoute(AppRoutes.healthTrackersPage);
} else { } else {
await getIt.get<AuthenticationViewModel>().onLoginPressed(); Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.healthTrackers.tr(),
serviceHeader: "HMG Hospital E-Referral: Streamlined patient referrals".needTranslation,
serviceDescription: "Facilitate seamless patient transfers to HMG with our secure e-referral system. Ensure continuity of care for every patient.".needTranslation,
serviceImage: AppAssets.eReferralService),
),
);
} }
}, },
), ),
@ -263,7 +307,15 @@ class ServicesPage extends StatelessWidget {
}, },
); );
} else { } else {
await getIt.get<AuthenticationViewModel>().onLoginPressed(); Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.waterConsumption.tr(),
serviceHeader: "Stay Hydrated, Stay Healthy. Track your daily water intake with ease.".needTranslation,
serviceDescription: "Quench your thirst, track your health. Effortlessly monitor your daily water intake with our user-friendly app, ensuring optimal hydration and well-being.".needTranslation,
serviceImage: AppAssets.waterConsumptionService),
),
);
} }
}, },
), ),
@ -294,8 +346,21 @@ class ServicesPage extends StatelessWidget {
true, true,
route: null, route: null,
onTap: () async { onTap: () async {
// if (getIt.get<AppState>().isAuthenticated) { if (getIt.get<AppState>().isAuthenticated) {
getIt.get<NavigationService>().pushPageRoute(AppRoutes.smartWatches); getIt.get<NavigationService>().pushPageRoute(AppRoutes.smartWatches);
} else {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.smartWatches.tr(),
serviceHeader: "HMG Hospital E-Referral: Streamlined patient referrals".needTranslation,
serviceDescription: "Facilitate seamless patient transfers to HMG with our secure e-referral system. Ensure continuity of care for every patient.".needTranslation,
serviceImage: AppAssets.eReferralService),
),
);
}
// if (getIt.get<AppState>().isAuthenticated) {
// getIt.get<NavigationService>().pushPageRoute(AppRoutes.smartWatches);
// } else { // } else {
// await getIt.get<AuthenticationViewModel>().onLoginPressed(); // await getIt.get<AuthenticationViewModel>().onLoginPressed();
// } // }
@ -368,6 +433,8 @@ class ServicesPage extends StatelessWidget {
), ),
), ),
SizedBox(height: 24.h), SizedBox(height: 24.h),
getIt.get<AppState>().isAuthenticated ? Column(
children: [
LocaleKeys.personalServices.tr().toText18(weight: FontWeight.w600).paddingSymmetrical(24.w, 0), LocaleKeys.personalServices.tr().toText18(weight: FontWeight.w600).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( Row(
@ -530,6 +597,8 @@ class ServicesPage extends StatelessWidget {
), ),
], ],
).paddingSymmetrical(24.w, 0), ).paddingSymmetrical(24.w, 0),
],
) : SizedBox(),
SizedBox(height: 24.h), SizedBox(height: 24.h),
LocaleKeys.healthTools.tr().toText18(weight: FontWeight.w600).paddingSymmetrical(24.w, 0), LocaleKeys.healthTools.tr().toText18(weight: FontWeight.w600).paddingSymmetrical(24.w, 0),
SizedBox(height: 16.h), SizedBox(height: 16.h),

@ -498,66 +498,66 @@ class _LandingPageState extends State<LandingPage> {
), ),
// Consumer for ER Online Check-In pending request // Consumer for ER Online Check-In pending request
Consumer<EmergencyServicesViewModel>( // Consumer<EmergencyServicesViewModel>(
builder: (context, emergencyServicesVM, child) { // builder: (context, emergencyServicesVM, child) {
return emergencyServicesVM.patientHasAdvanceERBalance // return emergencyServicesVM.patientHasAdvanceERBalance
? Column( // ? Column(
children: [ // children: [
SizedBox(height: 16.h), // SizedBox(height: 16.h),
Container( // Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, // color: AppColors.whiteColor,
borderRadius: 20.r, // borderRadius: 20.r,
hasShadow: false, // hasShadow: false,
side: BorderSide(color: AppColors.primaryRedColor, width: 3.h), // side: BorderSide(color: AppColors.primaryRedColor, width: 3.h),
), // ),
width: double.infinity, // width: double.infinity,
child: Padding( // child: Padding(
padding: EdgeInsets.all(16.h), // padding: EdgeInsets.all(16.h),
child: Column( // child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
children: [ // children: [
// // Row(
// // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// // children: [
// // AppCustomChipWidget(
// // labelText: LocaleKeys.erOnlineCheckInRequest.tr(context: context),
// // backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.10),
// // textColor: AppColors.primaryRedColor,
// // ),
// // Utils.buildSvgWithAssets(icon: AppAssets.appointment_checkin_icon, width: 24.h, height: 24.h, iconColor: AppColors.primaryRedColor),
// // ],
// // ),
// SizedBox(height: 8.h),
// Row( // Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [ // children: [
// AppCustomChipWidget( // LocaleKeys.youHaveEROnlineCheckInRequest.tr(context: context).toText12(isBold: true),
// labelText: LocaleKeys.erOnlineCheckInRequest.tr(context: context), // Transform.flip(
// backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.10), // flipX: getIt.get<AppState>().isArabic(),
// textColor: AppColors.primaryRedColor, // child: Utils.buildSvgWithAssets(
// icon: AppAssets.forward_arrow_icon_small,
// iconColor: AppColors.blackColor,
// width: 20.h,
// height: 15.h,
// fit: BoxFit.contain,
// ),
// ), // ),
// Utils.buildSvgWithAssets(icon: AppAssets.appointment_checkin_icon, width: 24.h, height: 24.h, iconColor: AppColors.primaryRedColor),
// ], // ],
// ), // ),
SizedBox(height: 8.h), // ],
Row( // ),
mainAxisAlignment: MainAxisAlignment.spaceBetween, // ),
children: [ // ).paddingSymmetrical(24.h, 0.h).onPress(() {
LocaleKeys.youHaveEROnlineCheckInRequest.tr(context: context).toText12(isBold: true), // Navigator.of(context).push(CustomPageRoute(page: ErOnlineCheckinHome()));
Transform.flip( // // context.read<EmergencyServicesViewModel>().navigateToEROnlineCheckIn();
flipX: getIt.get<AppState>().isArabic(), // }),
child: Utils.buildSvgWithAssets( // SizedBox(height: 12.h),
icon: AppAssets.forward_arrow_icon_small, // ],
iconColor: AppColors.blackColor, // )
width: 20.h, // : SizedBox(height: 0.h);
height: 15.h, // },
fit: BoxFit.contain, // ),
),
),
],
),
],
),
),
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: ErOnlineCheckinHome()));
// context.read<EmergencyServicesViewModel>().navigateToEROnlineCheckIn();
}),
SizedBox(height: 12.h),
],
)
: SizedBox(height: 0.h);
},
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -591,17 +591,13 @@ class _LandingPageState extends State<LandingPage> {
trackColor: Color(0xffD9D9D9), trackColor: Color(0xffD9D9D9),
trackBorderColor: Colors.transparent, trackBorderColor: Colors.transparent,
trackRadius: Radius.circular(10.0), trackRadius: Radius.circular(10.0),
padding: EdgeInsets.only(top: 92.h + 32.h, left: MediaQuery padding: EdgeInsets.only(top: 92.h + 32.h, left: MediaQuery.sizeOf(context).width / 2.5 - 10, right: MediaQuery.sizeOf(context).width / 2.5 - 10),
.sizeOf(context)
.width / 2 - 35, right: MediaQuery
.sizeOf(context)
.width / 2 - 35),
child: ListView.separated( child: ListView.separated(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getLoggedInServiceCardsList.length, itemCount: LandingPageData.getLoggedInServiceCardsList.length,
shrinkWrap: true, shrinkWrap: true,
controller: _horizontalScrollController, controller: _horizontalScrollController,
padding: EdgeInsets.only(left: 16.h, right: 16.h, top: 16.h, bottom: 12.h), padding: EdgeInsets.only(left: 0.h, right: 0.h, top: 16.h, bottom: 12.h),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
@ -624,7 +620,7 @@ class _LandingPageState extends State<LandingPage> {
); );
}, },
separatorBuilder: (BuildContext cxt, int index) => 10.width, separatorBuilder: (BuildContext cxt, int index) => 10.width,
), ).paddingSymmetrical(16.h, 0.h),
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -634,7 +630,6 @@ class _LandingPageState extends State<LandingPage> {
], ],
) )
: Container( : Container(
// height: 141.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: Column( child: Column(
children: [ children: [
@ -649,14 +644,13 @@ class _LandingPageState extends State<LandingPage> {
trackColor: Color(0xffD9D9D9), trackColor: Color(0xffD9D9D9),
trackBorderColor: Colors.transparent, trackBorderColor: Colors.transparent,
trackRadius: Radius.circular(10.0), trackRadius: Radius.circular(10.0),
padding: EdgeInsets.only(top: 92.h + 32.h, left: MediaQuery.sizeOf(context).width / 2 - 35, right: MediaQuery.sizeOf(context).width / 2 - 35), padding: EdgeInsets.only(top: 92.h + 32.h, left: MediaQuery.sizeOf(context).width / 2.5 - 10, right: MediaQuery.sizeOf(context).width / 2.5 - 10),
child: ListView.separated( child: ListView.separated(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getNotLoggedInServiceCardsList.length, itemCount: LandingPageData.getNotLoggedInServiceCardsList.length,
shrinkWrap: true, shrinkWrap: true,
controller: _horizontalScrollController, controller: _horizontalScrollController,
padding: EdgeInsets.only(left: 16.h, right: 16.h, top: 16.h, bottom: 12.h), padding: EdgeInsets.only(left: 0.h, right: 0.h, top: 16.h, bottom: 12.h),
// padding: EdgeInsets.zero,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
@ -679,7 +673,7 @@ class _LandingPageState extends State<LandingPage> {
); );
}, },
separatorBuilder: (BuildContext cxt, int index) => 0.width, separatorBuilder: (BuildContext cxt, int index) => 0.width,
), ).paddingSymmetrical(16.h, 0.h),
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),

@ -0,0 +1,74 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_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/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
class ServiceInfoPage extends StatelessWidget {
final String serviceName;
final String serviceHeader;
final String serviceDescription;
final String serviceImage;
const ServiceInfoPage({required this.serviceName, required this.serviceHeader, required this.serviceDescription, required this.serviceImage, super.key});
@override
Widget build(BuildContext context) {
return CollapsingListView(
title: "",
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppCustomChipWidget(
richText: serviceName.toText14(color: AppColors.infoColor, weight: FontWeight.w500),
backgroundColor: AppColors.infoColor.withAlpha(50),
textColor: AppColors.infoColor,
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
serviceHeader.toText28(isBold: true, height: 1.4).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
serviceDescription.toText14(weight: FontWeight.w500, color: AppColors.greyTextColor).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
CustomButton(
text: LocaleKeys.login.tr(context: context),
onPressed: () {
getIt<AuthenticationViewModel>().onLoginPressed();
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 12.r,
padding: EdgeInsets.symmetric(horizontal: 10.w),
height: 40.h,
icon: AppAssets.login1,
iconColor: AppColors.primaryRedColor,
iconSize: 18.h,
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 36.h),
ClipRRect(
borderRadius: BorderRadius.circular(24.r),
child: Transform.flip(
flipX: getIt.get<AppState>().isArabic(),
child: Image.asset(
serviceImage,
fit: BoxFit.fitHeight,
width: 520.w,
),
),
),
],
),
);
}
}

@ -115,7 +115,7 @@ class HabibWalletCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox( SizedBox(
width: 150.h, width: 200.h,
child: Utils.getPaymentMethods(), child: Utils.getPaymentMethods(),
), ),
CustomButton( CustomButton(

@ -1,6 +1,7 @@
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/api_consts.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
@ -10,6 +11,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/book_appointments
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/book_appointment/book_appointment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.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/presentation/home/service_info_page.dart';
import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart'; import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -135,11 +137,23 @@ class LargeServiceCard extends StatelessWidget {
} }
case "home_health_care": case "home_health_care":
{ {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push( Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute( CustomPageRoute(
page: HhcProceduresPage(), page: HhcProceduresPage(),
), ),
); );
} else {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.homeHealthCare.tr(),
serviceHeader: "Your Health, Elevated. Premium care, delivered to your doorstep.",
serviceDescription: "We bring quality healthcare to your doorstep. Experienced nurses providing compassionate care in the comfort of your home.",
serviceImage: AppAssets.homeHealthCareService),
),
);
}
} }
case "pharmacy": case "pharmacy":
{ {
@ -270,11 +284,23 @@ class FadedLargeServiceCard extends StatelessWidget {
} }
case "home_health_care": case "home_health_care":
{ {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push( Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute( CustomPageRoute(
page: HhcProceduresPage(), page: HhcProceduresPage(),
), ),
); );
} else {
Navigator.of(getIt<NavigationService>().navigatorKey.currentContext!).push(
CustomPageRoute(
page: ServiceInfoPage(
serviceName: LocaleKeys.homeHealthCare.tr(),
serviceHeader: "Your Health, Elevated. Premium care, delivered to your doorstep.".needTranslation,
serviceDescription: "We bring quality healthcare to your doorstep. Experienced nurses providing compassionate care in the comfort of your home.".needTranslation,
serviceImage: AppAssets.homeHealthCareService),
),
);
}
} }
case "pharmacy": case "pharmacy":
{ {

@ -7,6 +7,7 @@ import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
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/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_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/insurance/insurance_home_page.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart'; import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart';
@ -40,6 +41,7 @@ class WelcomeWidget extends StatelessWidget {
spacing: 8.h, spacing: 8.h,
children: [ children: [
Icon(Icons.menu, color: AppColors.textColor).onPress(() { Icon(Icons.menu, color: AppColors.textColor).onPress(() {
getIt.get<ProfileSettingsViewModel>().getProfileSettings();
Navigator.of(context).push(springPageRoute(ProfileSettings())); Navigator.of(context).push(springPageRoute(ProfileSettings()));
}), }),
Image.asset(imageUrl, width: 40, height: 40), Image.asset(imageUrl, width: 40, height: 40),

@ -136,7 +136,7 @@ class PatientInsuranceCard extends StatelessWidget {
insuranceCardDetailsModel.groupName!.toText12(isBold: true), insuranceCardDetailsModel.groupName!.toText12(isBold: true),
Row( Row(
children: [ children: [
insuranceCardDetailsModel.companyName!.toText12(isBold: true), (insuranceCardDetailsModel.companyName!.length > 40 ? "${insuranceCardDetailsModel.companyName!.substring(0, 40)}..." : insuranceCardDetailsModel.companyName!).toText12(isBold: true),
SizedBox( SizedBox(
width: 6.h, width: 6.h,
), ),
@ -146,7 +146,7 @@ class PatientInsuranceCard extends StatelessWidget {
color: AppColors.infoColor, color: AppColors.infoColor,
borderRadius: 50.r, borderRadius: 50.r,
), ),
child: (insuranceCardDetailsModel.subCategoryDesc!.length > 5 ? insuranceCardDetailsModel.subCategoryDesc!.substring(0, 12) : insuranceCardDetailsModel.subCategoryDesc!) child: ((insuranceCardDetailsModel.subCategoryDesc ?? "").length > 10 ? (insuranceCardDetailsModel.subCategoryDesc ?? "").substring(0, 10) : (insuranceCardDetailsModel.subCategoryDesc ?? ""))
.toText8(isBold: true, color: AppColors.whiteColor), .toText8(isBold: true, color: AppColors.whiteColor),
), ),
], ],

@ -473,8 +473,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
], ],
); );
}), }),
SizedBox(height: 16.h), SizedBox(height: 24.h),
// TextInputWidget( // TextInputWidget(
// labelText: LocaleKeys.search.tr(context: context), // labelText: LocaleKeys.search.tr(context: context),
// hintText: "Type any record".needTranslation, // hintText: "Type any record".needTranslation,
@ -489,7 +488,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
// leadingIcon: AppAssets.search_icon, // leadingIcon: AppAssets.search_icon,
// hintColor: AppColors.textColor, // hintColor: AppColors.textColor,
// ).paddingSymmetrical(24.w, 0.0), // ).paddingSymmetrical(24.w, 0.0),
SizedBox(height: 16.h), // SizedBox(height: 16.h),
// Using CustomExpandableList // Using CustomExpandableList
CustomExpandableList( CustomExpandableList(
expansionMode: ExpansionMode.exactlyOne, expansionMode: ExpansionMode.exactlyOne,
@ -1538,6 +1537,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
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,
// status: "Overweight",
onTap: onTap, onTap: onTap,
), ),
), ),

@ -6,6 +6,7 @@ import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/int_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/my_invoices/models/get_invoice_details_response_model.dart'; import 'package:hmg_patient_app_new/features/my_invoices/models/get_invoice_details_response_model.dart';
@ -183,9 +184,6 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Container( Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
@ -197,23 +195,19 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
widget.getInvoiceDetailsResponseModel.listConsultation!.first.procedureName!.toText16(isBold: true), "Insurance Details".toText16(isBold: true),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Wrap( widget.getInvoiceDetailsResponseModel.groupName!.toText14(isBold: true),
direction: Axis.horizontal, Row(
spacing: 6.w,
runSpacing: 6.h,
children: [ children: [
AppCustomChipWidget( Expanded(child: widget.getInvoiceDetailsResponseModel.companyName!.toText14(isBold: true)),
labelText: "${LocaleKeys.quantity.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.quantity!}", ],
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
),
AppCustomChipWidget(
labelText: "${LocaleKeys.price.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.price!} ${LocaleKeys.sar.tr()}",
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
), ),
SizedBox(height: 12.h),
Row(
children: [
AppCustomChipWidget( AppCustomChipWidget(
labelText: "${LocaleKeys.total.tr()}: ${widget.getInvoiceDetailsResponseModel.listConsultation!.first.total!} ${LocaleKeys.sar.tr()}", labelText: "Insurance ID: ${widget.getInvoiceDetailsResponseModel.insuranceID ?? "-"}",
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
), ),
], ],
@ -222,10 +216,12 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
), ),
), ),
), ),
],
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Container( Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor, color: AppColors.whiteColor,
borderRadius: 20.h, borderRadius: 20.h,
@ -236,27 +232,41 @@ class _MyInvoicesDetailsPageState extends State<MyInvoicesDetailsPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"Insurance Details".toText16(isBold: true), // Header row
SizedBox(height: 16.h),
widget.getInvoiceDetailsResponseModel.groupName!.toText14(isBold: true),
Row( Row(
children: [ children: [
Expanded(child: widget.getInvoiceDetailsResponseModel.companyName!.toText14(isBold: true)), Expanded(flex: 3, child: LocaleKeys.name.tr().toText12(color: AppColors.textColor, fontWeight: FontWeight.w600)),
Expanded(flex: 1, child: LocaleKeys.quantity.tr().toText12(color: AppColors.textColor, fontWeight: FontWeight.w600, isCenter: true)),
Expanded(
flex: 2, child: LocaleKeys.price.tr().toText12(color: AppColors.textColor, fontWeight: FontWeight.w600, isCenter: true)),
Expanded(
flex: 2, child: LocaleKeys.total.tr().toText12(color: AppColors.textColor, fontWeight: FontWeight.w600, isCenter: true)),
], ],
), ),
SizedBox(height: 16.h),
2.divider,
SizedBox(height: 12.h), SizedBox(height: 12.h),
Row( // Data rows
...widget.getInvoiceDetailsResponseModel.listConsultation!.map(
(consultation) => Padding(
padding: EdgeInsets.symmetric(vertical: 6.h),
child: Row(
children: [ children: [
AppCustomChipWidget( Expanded(flex: 3, child: (consultation.procedureName ?? '-').toText12(fontWeight: FontWeight.w500)),
labelText: "Insurance ID: ${widget.getInvoiceDetailsResponseModel.insuranceID ?? "-"}", Expanded(flex: 1, child: '${consultation.quantity ?? '-'}'.toText12(fontWeight: FontWeight.w500, isCenter: true)),
labelPadding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w), Expanded(flex: 2, child: '${consultation.price ?? '-'}'.toText12(fontWeight: FontWeight.w500, isCenter: true)),
), Expanded(flex: 2, child: '${consultation.total ?? '-'}'.toText12(fontWeight: FontWeight.w500, isCenter: true)),
], ],
), ),
),
),
], ],
), ),
), ),
), ),
),
],
),
], ],
), ),
), ),

@ -207,7 +207,7 @@ class PrescriptionItemView extends StatelessWidget {
initialHour: DateTime.now().hour, initialHour: DateTime.now().hour,
initialMinute: DateTime.now().minute, initialMinute: DateTime.now().minute,
use24HourFormat: true, use24HourFormat: true,
pickerHeight: 120.h, pickerHeight: 200.h,
itemExtent: 100.h, itemExtent: 100.h,
onTimeChanged: (time) { onTimeChanged: (time) {
// Handle selected time // Handle selected time

@ -20,7 +20,7 @@ class PrescriptionReminderView extends StatefulWidget {
} }
class _PrescriptionReminderViewState extends State<PrescriptionReminderView> { class _PrescriptionReminderViewState extends State<PrescriptionReminderView> {
final List<int> _options = [15, 30, 60, 90]; final List<int> _options = [60, 360, 720, 1440];
int _selectedOption = 0; // Nullable to represent no selection initially int _selectedOption = 0; // Nullable to represent no selection initially
@override @override
@ -54,7 +54,7 @@ class _PrescriptionReminderViewState extends State<PrescriptionReminderView> {
), ),
child: RadioListTile<int>( child: RadioListTile<int>(
title: Text( title: Text(
"${_options[index]} ${LocaleKeys.minute.tr(context: context)}", "${(_options[index] / 60).toInt()} ${LocaleKeys.hours.tr(context: context)}",
style: TextStyle( style: TextStyle(
fontSize: 16.h, fontSize: 16.h,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,

@ -28,6 +28,7 @@ import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.
import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart';
import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart'; import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/update_email_widget.dart'; import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/update_email_widget.dart';
import 'package:hmg_patient_app_new/presentation/profile_settings/widgets/update_emergency_contact_widget.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/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/app_language_change.dart'; import 'package:hmg_patient_app_new/widgets/app_language_change.dart';
@ -39,6 +40,7 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:in_app_review/in_app_review.dart';
class ProfileSettings extends StatefulWidget { class ProfileSettings extends StatefulWidget {
const ProfileSettings({super.key}); const ProfileSettings({super.key});
@ -48,6 +50,9 @@ class ProfileSettings extends StatefulWidget {
} }
class ProfileSettingsState extends State<ProfileSettings> { class ProfileSettingsState extends State<ProfileSettings> {
final InAppReview inAppReview = InAppReview.instance;
@override @override
void initState() { void initState() {
scheduleMicrotask(() { scheduleMicrotask(() {
@ -242,49 +247,47 @@ class ProfileSettingsState extends State<ProfileSettings> {
], ],
), ),
), ),
// Container( LocaleKeys.personalInformation.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
// margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h), Container(
// padding: EdgeInsets.only(top: 4.h, bottom: 4.h), margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true), padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
// child: Column( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
// children: [ child: Column(
// actionItem(AppAssets.language_change, LocaleKeys.language.tr(context: context), () { children: [
// showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.language.tr(context: context), child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false); actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(context: context), () {
// }, trailingLabel: Utils.appState.isArabic() ? "العربية" : "English"), showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.updateEmailAddress.tr(context: context),
child: UpdateEmailDialog(),
callBackFunc: () {},
isFullScreen: false,
);
}),
1.divider,
actionItem(AppAssets.language, LocaleKeys.communicationLanguage.tr(context: context), () {
profileVm.openPreferredLanguageBottomSheet();
},
trailingLabel: profileVm.isPatientProfileLoading
? "English"
: (profileVm.getPatientInfoForUpdate.preferredLanguage! == "1" ? LocaleKeys.arabic.tr(context: context) : LocaleKeys.english.tr(context: context)),
isShowLoading: profileVm.isPatientProfileLoading),
1.divider,
actionItem(AppAssets.smart_phone_fill, LocaleKeys.emrgNo.tr(context: context), () {
showCommonBottomSheetWithoutHeight(
context,
title: LocaleKeys.emrgNo.tr(context: context),
child: UpdateEmergencyContactDialog(),
callBackFunc: () {},
isFullScreen: false,
);
}),
// 1.divider, // 1.divider,
// actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () { // actionItem(AppAssets.my_address, "My Addresses".needTranslation, () {}),
// openAppSettings(); // 1.divider,
// }), // actionItem(AppAssets.emergency, "Emergency Contact".needTranslation, () {}),
// // 1.divider, ],
// // actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true), ),
// ], ),
// ),
// ),
// LocaleKeys.personalInformation.tr(context: context).toText18(weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1).paddingOnly(left: 24.w, right: 24.w),
// Container(
// margin: EdgeInsets.only(left: 24.w, right: 24.w, top: 16.h, bottom: 24.h),
// padding: EdgeInsets.only(top: 4.h, bottom: 4.h),
// decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
// child: Column(
// children: [
// actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(context: context), () {
// showCommonBottomSheetWithoutHeight(
// context,
// title: LocaleKeys.updateEmailAddress.tr(context: context),
// child: UpdateEmailDialog(),
// callBackFunc: () {},
// isFullScreen: false,
// );
// }),
// // 1.divider,
// // actionItem(AppAssets.smart_phone_fill, "Phone Number".needTranslation, () {}),
// // 1.divider,
// // actionItem(AppAssets.my_address, "My Addresses".needTranslation, () {}),
// // 1.divider,
// // actionItem(AppAssets.emergency, "Emergency Contact".needTranslation, () {}),
// ],
// ),
// ),
LocaleKeys.helpAndSupport.tr(context: context).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),
@ -314,17 +317,23 @@ class ProfileSettingsState extends State<ProfileSettings> {
1.divider, 1.divider,
// actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"), // actionItem(AppAssets.permission, LocaleKeys.permissions.tr(context: context), () {}, trailingLabel: "Location, Camera"),
// 1.divider, // 1.divider,
actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(context: context), () { actionItem(AppAssets.rate, LocaleKeys.rateApp.tr(context: context), () async {
if (Platform.isAndroid) { if (await inAppReview.isAvailable()) {
Utils.openWebView( inAppReview.requestReview();
url: 'https://play.google.com/store/apps/details?id=com.ejada.hmg',
);
} else { } else {
Utils.openWebView( inAppReview.openStoreListing(appStoreId: '6758851027');
url: 'https://itunes.apple.com/app/id733503978',
);
} }
}, isExternalLink: true), // if (Platform.isAndroid) {
// Utils.openWebView(
// url: 'https://play.google.com/store/apps/details?id=com.ejada.hmg',
// );
// } else {
// Utils.openWebView(
// url: 'https://itunes.apple.com/app/id733503978',
// );
// }
// }, isExternalLink: true),
}),
1.divider, 1.divider,
actionItem(AppAssets.privacy_terms, LocaleKeys.privacyPolicy.tr(context: context), () { actionItem(AppAssets.privacy_terms, LocaleKeys.privacyPolicy.tr(context: context), () {
Utils.openWebView( Utils.openWebView(
@ -340,12 +349,12 @@ class ProfileSettingsState extends State<ProfileSettings> {
], ],
), ),
), ),
CustomButton( // CustomButton(
height: 56.h, // height: 56.h,
icon: AppAssets.minus, // icon: AppAssets.minus,
text: LocaleKeys.deactivateAccount.tr(context: context), // text: LocaleKeys.deactivateAccount.tr(context: context),
onPressed: () {}, // onPressed: () {},
).paddingAll(24.w), // ).paddingAll(24.w),
], ],
); );
}, },
@ -382,7 +391,8 @@ class ProfileSettingsState extends State<ProfileSettings> {
return _permissionsLabel; return _permissionsLabel;
} }
Widget actionItem(String icon, String label, VoidCallback onPress, {String trailingLabel = "", bool? switchValue, ValueChanged<bool>? onSwitchChanged, bool isExternalLink = false}) { Widget actionItem(String icon, String label, VoidCallback onPress,
{String trailingLabel = "", bool? switchValue, ValueChanged<bool>? onSwitchChanged, bool isExternalLink = false, bool isShowLoading = false}) {
return SizedBox( return SizedBox(
height: 56.h, height: 56.h,
child: Row( child: Row(
@ -390,7 +400,11 @@ class ProfileSettingsState extends State<ProfileSettings> {
children: [ children: [
Utils.buildSvgWithAssets(icon: icon, iconColor: AppColors.greyTextColor), Utils.buildSvgWithAssets(icon: icon, iconColor: AppColors.greyTextColor),
label.toText14(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).expanded, label.toText14(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).expanded,
if (trailingLabel.isNotEmpty) trailingLabel.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1), if (trailingLabel.isNotEmpty)
ConstrainedBox(
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.35),
child: trailingLabel.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).toShimmer2(isShow: isShowLoading),
),
switchValue != null switchValue != null
? Switch( ? Switch(
value: switchValue, value: switchValue,

@ -0,0 +1,116 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/int_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/features/profile_settings/profile_settings_view_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/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart';
class PreferredLanguageWidget extends StatefulWidget {
PreferredLanguageWidget({super.key});
@override
State<PreferredLanguageWidget> createState() => _PreferredLanguageWidgetState();
}
class _PreferredLanguageWidgetState extends State<PreferredLanguageWidget> {
String? selectedValue;
late ProfileSettingsViewModel profileSettingsViewModel;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
selectedValue = profileSettingsViewModel.getPatientInfoForUpdate.preferredLanguage!;
});
});
}
@override
Widget build(BuildContext context) {
profileSettingsViewModel = Provider.of<ProfileSettingsViewModel>(context, listen: false);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 24.h,
children: [
LocaleKeys.communicationLanguage.tr(context: context).toText14(),
Container(
padding: EdgeInsets.only(top: 4, bottom: 4),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: Column(
children: [
languageItem("English", "2"),
1.divider,
languageItem("العربية", "1"),
],
),
),
CustomButton(
text: LocaleKeys.save.tr(context: context),
onPressed: () {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context));
profileSettingsViewModel!.updatePatientInfo(
patientInfo: {
"PreferredLanguage": selectedValue,
"EmailAddress": profileSettingsViewModel.getPatientInfoForUpdate.emailAddress,
"EmergencyContactName": profileSettingsViewModel.getPatientInfoForUpdate.emergencyContactName,
"EmergencyContactNo": profileSettingsViewModel.getPatientInfoForUpdate.emergencyContactNo,
"IsEmailAlertRequired": true,
"IsSMSAlertRequired": true,
},
onSuccess: (response) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()),
callBackFunc: () async {
Navigator.of(context).pop();
profileSettingsViewModel.getProfileSettings();
}, isFullScreen: false);
},
onError: (error) {
LoaderBottomSheet.hideLoader();
// Show error message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(error)),
);
},
);
}),
],
);
}
Widget languageItem(String title, String _value) {
return SizedBox(
height: 72,
child: Row(
spacing: 8.h,
children: [
Radio(
value: _value,
groupValue: selectedValue,
activeColor: AppColors.errorColor,
onChanged: (value) {
setState(() {
selectedValue = _value;
});
},
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
title.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, fontFamily: _value == "1" ? 'GESSTwo' : 'Poppins').expanded,
],
).paddingOnly(left: 16, right: 16).onPress(() {
setState(() {
selectedValue = _value;
});
}),
);
}
}

@ -31,7 +31,11 @@ class _UpdateEmailDialogState extends State<UpdateEmailDialog> {
void initState() { void initState() {
_textFieldFocusNode = FocusNode(); _textFieldFocusNode = FocusNode();
textController = TextEditingController(); textController = TextEditingController();
textController!.text = getIt.get<AppState>().getAuthenticatedUser()!.emailAddress ?? ""; WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
textController!.text = profileSettingsViewModel!.getPatientInfoForUpdate.emailAddress ?? "";
});
});
super.initState(); super.initState();
} }
@ -52,7 +56,7 @@ class _UpdateEmailDialogState extends State<UpdateEmailDialog> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"Enter the new email address to be updated in your HMG File: ".toText16(textAlign: TextAlign.start, weight: FontWeight.w500), "Enter the new email address to be updated: ".toText16(textAlign: TextAlign.start, weight: FontWeight.w500),
SizedBox(height: 12.h), SizedBox(height: 12.h),
TextInputWidget( TextInputWidget(
labelText: LocaleKeys.email.tr(), labelText: LocaleKeys.email.tr(),
@ -78,12 +82,20 @@ class _UpdateEmailDialogState extends State<UpdateEmailDialog> {
onPressed: () { onPressed: () {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.updatingEmailAddress.tr(context: context)); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.updatingEmailAddress.tr(context: context));
profileSettingsViewModel!.updatePatientInfo( profileSettingsViewModel!.updatePatientInfo(
patientInfo: {"EmailAddress": textController!.text}, patientInfo: {
"PreferredLanguage": profileSettingsViewModel!.getPatientInfoForUpdate.preferredLanguage,
"EmailAddress": textController!.text,
"EmergencyContactName": profileSettingsViewModel!.getPatientInfoForUpdate.emergencyContactName,
"EmergencyContactNo": profileSettingsViewModel!.getPatientInfoForUpdate.emergencyContactNo,
"IsEmailAlertRequired": true,
"IsSMSAlertRequired": true,
},
onSuccess: (response) { onSuccess: (response) {
LoaderBottomSheet.hideLoader(); LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()),
callBackFunc: () async { callBackFunc: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
profileSettingsViewModel!.getProfileSettings();
}, isFullScreen: false); }, isFullScreen: false);
}, },
onError: (error) { onError: (error) {

@ -0,0 +1,118 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_view_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/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:provider/provider.dart';
class UpdateEmergencyContactDialog extends StatefulWidget {
UpdateEmergencyContactDialog({super.key});
@override
State<UpdateEmergencyContactDialog> createState() => _UpdateEmergencyContactDialogState();
}
class _UpdateEmergencyContactDialogState extends State<UpdateEmergencyContactDialog> {
late FocusNode _textFieldFocusNode;
late TextEditingController? textController;
ProfileSettingsViewModel? profileSettingsViewModel;
@override
void initState() {
_textFieldFocusNode = FocusNode();
textController = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
textController!.text = profileSettingsViewModel!.getPatientInfoForUpdate.emergencyContactNo!;
});
});
super.initState();
}
@override
void dispose() {
_textFieldFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
profileSettingsViewModel = Provider.of<ProfileSettingsViewModel>(context);
return GestureDetector(
onTap: () {
_textFieldFocusNode.unfocus();
FocusScope.of(context).unfocus();
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Enter the new emergency contact number to be updated: ".toText16(textAlign: TextAlign.start, weight: FontWeight.w500),
SizedBox(height: 12.h),
TextInputWidget(
labelText: LocaleKeys.emrgNo.tr(),
hintText: "05xxxxxxxx",
controller: textController,
focusNode: _textFieldFocusNode,
autoFocus: true,
padding: EdgeInsets.all(8.h),
keyboardType: TextInputType.number,
isEnable: true,
isReadOnly: false,
prefix: null,
isBorderAllowed: false,
isAllowLeadingIcon: true,
fontSize: 14.f,
isCountryDropDown: false,
leadingIcon: AppAssets.call_fill,
fontFamily: "Poppins",
),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.submit.tr(context: context),
onPressed: () {
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context));
profileSettingsViewModel!.updatePatientInfo(
patientInfo: {
"PreferredLanguage": profileSettingsViewModel!.getPatientInfoForUpdate.preferredLanguage,
"EmailAddress": profileSettingsViewModel!.getPatientInfoForUpdate.emailAddress,
"EmergencyContactName": profileSettingsViewModel!.getPatientInfoForUpdate.emergencyContactName,
"EmergencyContactNo": textController!.text,
"IsEmailAlertRequired": true,
"IsSMSAlertRequired": true,
},
onSuccess: (response) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.success.tr(context: context), child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()),
callBackFunc: () async {
Navigator.of(context).pop();
profileSettingsViewModel!.getProfileSettings();
}, isFullScreen: false);
},
onError: (error) {
LoaderBottomSheet.hideLoader();
// Show error message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(error)),
);
},
);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
textColor: const Color(0xFFffffff),
),
],
),
);
}
}

@ -2,8 +2,10 @@ 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/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/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';
@ -337,6 +339,8 @@ class PossibleConditionsPage extends StatelessWidget {
selectedFacility: data.selectedFacility, selectedFacility: data.selectedFacility,
hmcCount: data.hmcCount, hmcCount: data.hmcCount,
hmgCount: data.hmgCount, hmgCount: data.hmgCount,
sortByLocation: data.sortByLocation,
onSortByLocationToggle: (value) => _handleSortByLocationToggle(value, data),
); );
} }
if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) {
@ -354,4 +358,42 @@ class PossibleConditionsPage extends StatelessWidget {
} }
return SizedBox.shrink(); return SizedBox.shrink();
} }
void _handleSortByLocationToggle(bool value, AppointmentViaRegionViewmodel regionVM) {
if (value) {
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionVM.setSortByLocation(true);
_refreshHospitalListAfterApi(regionVM);
},
onFailure: () {
regionVM.setSortByLocation(false);
},
onLocationDeniedForever: () {
regionVM.setSortByLocation(false);
},
);
} else {
final appState = getIt.get<AppState>();
appState.resetLocation();
regionVM.setSortByLocation(false);
_refreshHospitalListAfterApi(regionVM);
}
}
void _refreshHospitalListAfterApi(AppointmentViaRegionViewmodel regionVM) {
void listener() {
if (!bookAppointmentsViewModel.isRegionListLoading) {
bookAppointmentsViewModel.removeListener(listener);
final selectedRegion = regionVM.selectedRegionId;
if (selectedRegion != null && bookAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion] != null) {
regionVM.setDisplayListAndRegionHospitalList(bookAppointmentsViewModel.hospitalList!.registeredDoctorMap![selectedRegion]);
}
}
}
bookAppointmentsViewModel.addListener(listener);
bookAppointmentsViewModel.getRegionMappedProjectList();
}
} }

@ -640,7 +640,7 @@ class _AncillaryOrderDetailsListState extends State<AncillaryOrderDetailsList> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SizedBox( SizedBox(
width: 150.h, width: 200.h,
child: Utils.getPaymentMethods(), child: Utils.getPaymentMethods(),
), ),
Row( Row(

@ -69,16 +69,16 @@ class _VitalSignPageState extends State<VitalSignPage> {
: null; : null;
// Debug logging for blood pressure // Debug logging for blood pressure
if (latestVitalSign != null) { // if (latestVitalSign != null) {
print('=== Blood Pressure Debug ==='); // print('=== Blood Pressure Debug ===');
print('bloodPressureHigher: ${latestVitalSign.bloodPressureHigher}'); // print('bloodPressureHigher: ${latestVitalSign.bloodPressureHigher}');
print('bloodPressureLower: ${latestVitalSign.bloodPressureLower}'); // print('bloodPressureLower: ${latestVitalSign.bloodPressureLower}');
print('bloodPressureHigher type: ${latestVitalSign.bloodPressureHigher.runtimeType}'); // print('bloodPressureHigher type: ${latestVitalSign.bloodPressureHigher.runtimeType}');
print('bloodPressureLower type: ${latestVitalSign.bloodPressureLower.runtimeType}'); // print('bloodPressureLower type: ${latestVitalSign.bloodPressureLower.runtimeType}');
print('bloodPressureHigher == 0: ${latestVitalSign.bloodPressureHigher == 0}'); // print('bloodPressureHigher == 0: ${latestVitalSign.bloodPressureHigher == 0}');
print('bloodPressureLower == 0: ${latestVitalSign.bloodPressureLower == 0}'); // print('bloodPressureLower == 0: ${latestVitalSign.bloodPressureLower == 0}');
print('========================'); // print('========================');
} // }
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: Column(

@ -115,7 +115,7 @@ class _ScrollWheelTimePickerState extends State<ScrollWheelTimePicker> {
widget.use24HourFormat ? index : index + 1; widget.use24HourFormat ? index : index + 1;
final isSelected = hour == _selectedHour; final isSelected = hour == _selectedHour;
return Visibility( return Visibility(
visible: isSelected, visible: true,
child: Center( child: Center(
child: AnimatedDefaultTextStyle( child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
@ -124,9 +124,12 @@ class _ScrollWheelTimePickerState extends State<ScrollWheelTimePicker> {
? AppColors.textColor ? AppColors.textColor
: AppColors.textColor.withValues(alpha: 0.3), : AppColors.textColor.withValues(alpha: 0.3),
), ),
child: Text(hour.toString().padLeft(2, '0')), child: Text(
hour.toString().padLeft(2, '0'),
), ),
)); ),
),
);
}, },
), ),
), ),
@ -157,7 +160,7 @@ class _ScrollWheelTimePickerState extends State<ScrollWheelTimePicker> {
builder: (context, index) { builder: (context, index) {
final isSelected = index == _selectedMinute; final isSelected = index == _selectedMinute;
return Visibility( return Visibility(
visible: isSelected, visible: true,
child: child:
Center( Center(
child: AnimatedDefaultTextStyle( child: AnimatedDefaultTextStyle(

@ -2,8 +2,8 @@ name: hmg_patient_app_new
description: "New HMG Patient App" description: "New HMG Patient App"
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.15+12 #version: 0.0.15+12
#version: 0.0.1+14 version: 0.0.1+16
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"
@ -99,6 +99,8 @@ dependencies:
scrollable_positioned_list: ^0.3.8 scrollable_positioned_list: ^0.3.8
in_app_review: ^2.0.11
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter

Loading…
Cancel
Save