diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json
index 958a4902..268bf0a3 100644
--- a/assets/langs/ar-SA.json
+++ b/assets/langs/ar-SA.json
@@ -811,7 +811,7 @@
"awaitingApproval": "انتظر القبول",
"news": "أخبار",
"ready": "جاهز",
- "enterValidNationalId": "الرجاء إدخال رقم الهوية الوطنية أو رقم الملف الصحيح",
+ "enterValidNationalId": "رقم الهوية أو رقم الملف غير صحيح",
"enterValidPhoneNumber": "الرجاء إدخال رقم هاتف صالح",
"cannotEnterSaudiOrUAENumber": "لا يمكنك إدخال أرقام هواتف السعودية (00966) أو الإمارات (00971) عند اختيار دولة 'أخرى'",
"medicalCentersWithCount": "{count} مراكز طبية",
@@ -1274,7 +1274,7 @@
"noVitalSignsRecordedYet": "لا توجد علامات حيوية مسجلة بعد",
"appointmentsAndVisits": "المواعيد والزيارات",
"labAndRadiology": "المختبر والأشعة",
- "activeMedicationsAndPrescriptions": "الأدوية النشطة والوصفات الطبية",
+ "activeMedicationsAndPrescriptions": "الوصفات الطبية",
"allPrescriptions": "جميع الوصفات",
"allMedications": "جميع الأدوية",
"youDontHaveAnyPrescriptionsYet": "ليس لديك أي وصفات طبية بعد.",
@@ -1586,5 +1586,6 @@
"generateAiAnalysisResult": "قم بإجراء تحليل لهذا المختبر AI",
"ratings": "التقييمات",
"hmgPharmacyText": "صيدلية الحبيب، المتجر الصيدلاني الإلكتروني المتكامل الذي تقدمه لكم مجموعة خدمات الدكتور سليمان الحبيب الطبية.",
- "insuranceRequestSubmittedSuccessfully": "تم إرسال طلب تحديث بيانات التأمين بنجاح. سيتم إعلامك بمجرد الانتهاء."
+ "insuranceRequestSubmittedSuccessfully": "تم إرسال طلب تحديث بيانات التأمين بنجاح. سيتم إعلامك بمجرد الانتهاء.",
+ "updatingEmailAddress": "جارٍ تحديث عنوان البريد الإلكتروني، يرجى الانتظار..."
}
diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json
index cea0082a..d1a48222 100644
--- a/assets/langs/en-US.json
+++ b/assets/langs/en-US.json
@@ -802,7 +802,7 @@
"notNow": "Not Now",
"pendingActivation": "Pending Activation",
"awaitingApproval": "Awaiting Approval",
- "enterValidNationalId": "Please enter a valid national ID or file number",
+ "enterValidNationalId": "Invalid Identification or file number",
"enterValidPhoneNumber": "Please enter a valid phone number",
"cannotEnterSaudiOrUAENumber": "You cannot enter Saudi Arabia (00966) or UAE (00971) phone numbers when 'Others' country is selected",
"ready": "Ready",
@@ -1266,7 +1266,7 @@
"noVitalSignsRecordedYet": "No vital signs recorded yet",
"appointmentsAndVisits": "Appointments & visits",
"labAndRadiology": "Lab & Radiology",
- "activeMedicationsAndPrescriptions": "Active Medications & Prescriptions",
+ "activeMedicationsAndPrescriptions": "Recent Prescriptions",
"allPrescriptions": "All Prescriptions",
"allMedications": "All Medications",
"youDontHaveAnyPrescriptionsYet": "You don't have any prescriptions yet.",
@@ -1580,5 +1580,6 @@
"generateAiAnalysisResult": "Generate AI analysis for this result",
"ratings": "Ratings",
"hmgPharmacyText": "Al Habib Pharmacy, the complete online Pharmaceutical store brought to you by Dr. Sulaiman Al Habib Medical Services Group.",
- "insuranceRequestSubmittedSuccessfully": "Your insurance update request has been successfully submitted. You will be notified once completed."
+ "insuranceRequestSubmittedSuccessfully": "Your insurance update request has been successfully submitted. You will be notified once completed.",
+ "updatingEmailAddress": "Updating email address, Please wait..."
}
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 8ed9d257..6a81b151 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -343,10 +343,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
+ inputPaths = (
+ );
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
+ outputPaths = (
+ );
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@@ -360,10 +364,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
+ inputPaths = (
+ );
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
+ outputPaths = (
+ );
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
@@ -523,7 +531,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 14;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -709,7 +717,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 14;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -738,7 +746,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 14;
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 9c805ac5..f412b006 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -101,7 +101,6 @@
audio
fetch
- location
remote-notification
voip
diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart
index 6ad7b7ce..5fae22b1 100644
--- a/lib/core/api_consts.dart
+++ b/lib/core/api_consts.dart
@@ -233,7 +233,7 @@ class ApiConsts {
static String getAiOverViewLabOrder = "Services/Patients.svc/REST/HMGAI_Lab_Analyzer_API";
// ************ static values for Api ****************
- static final double appVersionID = 20.3;
+ static final double appVersionID = 20.5;
// static final double appVersionID = 50.7;
static final int appChannelId = 3;
@@ -920,6 +920,10 @@ const DASHBOARD = 'Services/Patients.svc/REST/PatientDashboard';
const SEND_PATIENT_IMMEDIATE_UPDATE_INSURANCE_REQUEST = 'Services/OUTPs.svc/REST/PatientCompanyUpdate';
+const PROFILE_SETTING = 'Services/Patients.svc/REST/GetPateintInfoForUpdate';
+
+const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo';
+
class ApiKeyConstants {
static final String googleMapsApiKey = 'AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng';
}
diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart
index 4266aa3b..657d03ea 100644
--- a/lib/core/dependencies.dart
+++ b/lib/core/dependencies.dart
@@ -50,6 +50,7 @@ import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_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_view_model.dart';
import 'package:hmg_patient_app_new/features/qr_parking/qr_parking_repo.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
@@ -172,6 +173,7 @@ class AppDependencies {
getIt.registerLazySingleton(() => NotificationsRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => AskDoctorRepoImp(loggerService: getIt(), apiClient: getIt()));
getIt.registerLazySingleton(() => ServicesPriceListRepoImp(loggerService: getIt(), apiClient: getIt()));
+ getIt.registerLazySingleton(() => ProfileSettingsRepoImp(loggerService: getIt(), apiClient: getIt()));
// ViewModels
// Global/shared VMs → LazySingleton
@@ -224,7 +226,11 @@ class AppDependencies {
authenticationRepo: getIt(), cacheService: getIt(), navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), localAuthService: getIt()),
);
- getIt.registerLazySingleton(() => ProfileSettingsViewModel(cacheService: getIt()));
+ getIt.registerLazySingleton(() => ProfileSettingsViewModel(
+ cacheService: getIt(),
+ profileSettingsRepo: getIt(),
+ errorHandlerService: getIt(),
+ ));
getIt.registerLazySingleton(() => DateRangeSelectorRangeViewModel());
diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart
index a8bc03d3..b5651648 100644
--- a/lib/core/utils/validation_utils.dart
+++ b/lib/core/utils/validation_utils.dart
@@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
@@ -32,6 +33,13 @@ class ValidationUtils {
isCorrectID = false;
}
+ if(nationalId!.length == 10) {
+ if (Utils.isSAUDIIDValid(nationalId!) == false) {
+ _dialogService.showExceptionBottomSheet(message: LocaleKeys.enterValidNationalId.tr(), onOkPressed: onOkPress);
+ isCorrectID = false;
+ }
+ }
+
if (nationalId != null && nationalId.isNotEmpty && selectedCountry != null) {
if (selectedCountry == CountryEnum.saudiArabia) {
if (!validateIqama(nationalId)) {
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 93901497..6e28ffda 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -320,9 +320,9 @@ extension EmailValidator on String {
height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
);
- Widget toText44({Color? color, bool isBold = false}) => Text(
+ Widget toText44({Color? color, bool isBold = false, bool isEnglishOnly = false,}) => Text(
this,
- style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, fontFamily: (isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins'),),
);
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index ce54c69f..336b35ae 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -28,6 +28,7 @@ import 'package:hmg_patient_app_new/features/authentication/models/resp_models/a
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
+import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
@@ -619,11 +620,12 @@ class AuthenticationViewModel extends ChangeNotifier {
} else {
activation.list!.first.isParentUser = true;
}
- activation.list!.first.bloodGroup = activation.patientBlodType;
+ activation.list!.first.bloodGroup = activation.patientBloodType;
activation.list!.first.zipCode = selectedCountrySignup == CountryEnum.others ? '0' : selectedCountrySignup.countryCode;
_appState.setAuthenticatedUser(activation.list!.first);
_appState.setPrivilegeModelList(activation.list!.first.listPrivilege!);
- _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A";
+ // _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A";
+ _appState.setUserBloodGroup = activation.patientBloodType ?? "N/A";
}
// _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppAuthToken = activation.authenticationTokenId;
@@ -646,6 +648,7 @@ class AuthenticationViewModel extends ChangeNotifier {
await clearDefaultInputValues();
myAppointmentsVM.setIsAppointmentDataToBeLoaded(true);
getIt.get().setIsInsuranceDataToBeLoaded(true);
+ getIt.get().setHasVitalSignDataLoaded(false);
if (isUserAgreedBefore) {
LoaderBottomSheet.hideLoader();
navigateToHomeScreen();
diff --git a/lib/features/authentication/widgets/otp_verification_screen.dart b/lib/features/authentication/widgets/otp_verification_screen.dart
index 7ddccda8..9e80dbb9 100644
--- a/lib/features/authentication/widgets/otp_verification_screen.dart
+++ b/lib/features/authentication/widgets/otp_verification_screen.dart
@@ -20,6 +20,8 @@ import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
import 'package:provider/provider.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
+import 'dart:ui' as ui;
+
typedef OnDone = void Function(String text);
class ProvidedPinBoxTextAnimation {
@@ -564,23 +566,27 @@ class _OTPVerificationScreenState extends State {
SizedBox(height: 16.h),
Center(
- child: OTPWidget(
- maxLength: _otpLength,
- controller: _otpController,
- pinBoxWidth: 70.h,
- pinBoxHeight: 100.h,
- pinBoxRadius: 16,
- pinBoxBorderWidth: 0,
- pinBoxOuterPadding: EdgeInsets.symmetric(horizontal: 4.h),
- defaultBorderColor: Colors.transparent,
- textBorderColor: Colors.transparent,
- pinBoxColor: AppColors.whiteColor,
- autoFocus: true,
- onTextChanged: _onOtpChanged,
- pinTextStyle: TextStyle(
- fontSize: 40.f,
- fontWeight: FontWeight.bold,
- color: AppColors.whiteColor,
+ child: Directionality(
+ textDirection: ui.TextDirection.ltr,
+ child: OTPWidget(
+ maxLength: _otpLength,
+ controller: _otpController,
+ pinBoxWidth: 70.h,
+ pinBoxHeight: 100.h,
+ pinBoxRadius: 16,
+ pinBoxBorderWidth: 0,
+ pinBoxOuterPadding: EdgeInsets.symmetric(horizontal: 4.h),
+ defaultBorderColor: Colors.transparent,
+ textBorderColor: Colors.transparent,
+ pinBoxColor: AppColors.whiteColor,
+ autoFocus: true,
+ onTextChanged: _onOtpChanged,
+ pinTextStyle: TextStyle(
+ fontSize: 40.f,
+ fontWeight: FontWeight.bold,
+ color: AppColors.whiteColor,
+ fontFamily: "Poppins"
+ ),
),
),
),
@@ -601,7 +607,7 @@ class _OTPVerificationScreenState extends State {
children: [
LocaleKeys.resendIn.tr(context: context).toText16(color: AppColors.inputLabelTextColor),
SizedBox(width: 2.h),
- ' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor)
+ ' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor, isEnglishOnly: true)
],
);
},
diff --git a/lib/features/hmg_services/hmg_services_view_model.dart b/lib/features/hmg_services/hmg_services_view_model.dart
index 5bf450ba..7b32cc6e 100644
--- a/lib/features/hmg_services/hmg_services_view_model.dart
+++ b/lib/features/hmg_services/hmg_services_view_model.dart
@@ -85,6 +85,11 @@ class HmgServicesViewModel extends ChangeNotifier {
List covidTestProcedureList = [];
Covid19GetPaymentInfo? covidPaymentInfo;
+ void setHasVitalSignDataLoaded(bool hasVitalSignDataLoaded) {
+ this.hasVitalSignDataLoaded = hasVitalSignDataLoaded;
+ notifyListeners();
+ }
+
Future getOrdersList() async {}
// HHC multiple services selection
diff --git a/lib/features/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart
index d66a7a22..d1423113 100644
--- a/lib/features/insurance/insurance_view_model.dart
+++ b/lib/features/insurance/insurance_view_model.dart
@@ -88,7 +88,7 @@ class InsuranceViewModel extends ChangeNotifier {
(failure) async {
debugPrint("InsuranceViewModel: API call failed - ${failure.toString()}");
isInsuranceLoading = false;
- isInsuranceDataToBeLoaded = false;
+ isInsuranceDataToBeLoaded = true;
isInsuranceExpired = false;
isInsuranceActive = false;
notifyListeners();
diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart
index d2296a66..1584f891 100644
--- a/lib/features/my_appointments/my_appointments_view_model.dart
+++ b/lib/features/my_appointments/my_appointments_view_model.dart
@@ -634,6 +634,7 @@ class MyAppointmentsViewModel extends ChangeNotifier {
Future getPatientMyDoctors({Function(dynamic)? onSuccess, Function(String)? onError}) async {
// if (!isAppointmentDataToBeLoaded) return;
isPatientMyDoctorsLoading = true;
+ patientMyDoctorsList.clear();
notifyListeners();
final result = await myAppointmentsRepo.getPatientDoctorsList();
diff --git a/lib/features/profile_settings/profile_settings_repo.dart b/lib/features/profile_settings/profile_settings_repo.dart
new file mode 100644
index 00000000..253bf505
--- /dev/null
+++ b/lib/features/profile_settings/profile_settings_repo.dart
@@ -0,0 +1,100 @@
+import 'package:dartz/dartz.dart';
+import 'package:hmg_patient_app_new/core/api/api_client.dart';
+import 'package:hmg_patient_app_new/core/api_consts.dart';
+import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
+import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
+import 'package:hmg_patient_app_new/services/logger_service.dart';
+
+abstract class ProfileSettingsRepo {
+ /// Updates general patient info (name, phone, etc.).
+ Future>> updatePatientInfo({
+ required Map patientInfo,
+ });
+
+ /// Deactivates (deletes) the patient's account.
+ Future>> deactivateAccount();
+}
+
+class ProfileSettingsRepoImp implements ProfileSettingsRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ ProfileSettingsRepoImp({
+ required this.loggerService,
+ required this.apiClient,
+ });
+
+ @override
+ Future>> updatePatientInfo({
+ required Map patientInfo,
+ }) async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ await apiClient.post(
+ SAVE_SETTING,
+ body: patientInfo,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> deactivateAccount() async {
+ final Map body = {};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+
+ await apiClient.post(
+ // TODO: Replace with actual deactivate-account endpoint once available
+ 'Services/Patients.svc/REST/Patient_DeactivateAccount',
+ body: body,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: errorMessage,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+}
+
diff --git a/lib/features/profile_settings/profile_settings_view_model.dart b/lib/features/profile_settings/profile_settings_view_model.dart
index e001d1bd..92f11528 100644
--- a/lib/features/profile_settings/profile_settings_view_model.dart
+++ b/lib/features/profile_settings/profile_settings_view_model.dart
@@ -1,18 +1,42 @@
import 'package:flutter/foundation.dart';
+import 'package:hmg_patient_app_new/features/profile_settings/profile_settings_repo.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/theme/colors.dart';
class ProfileSettingsViewModel extends ChangeNotifier {
static const String _darkModeKey = 'is_dark_mode';
final CacheService _cacheService;
+ final ProfileSettingsRepo profileSettingsRepo;
+ final ErrorHandlerService errorHandlerService;
+ // ── Dark-mode state ──────────────────────────────────────────────────
bool _isDarkMode = false;
-
bool get isDarkMode => _isDarkMode;
- ProfileSettingsViewModel({required CacheService cacheService})
- : _cacheService = cacheService;
+ // ── Update email state ───────────────────────────────────────────────
+ bool isUpdateEmailLoading = false;
+ bool isUpdateEmailSuccess = false;
+ String? updateEmailError;
+
+ // ── Update patient info state ────────────────────────────────────────
+ bool isUpdatePatientInfoLoading = false;
+ bool isUpdatePatientInfoSuccess = false;
+ String? updatePatientInfoError;
+
+ // ── Deactivate account state ─────────────────────────────────────────
+ bool isDeactivateAccountLoading = false;
+ bool isDeactivateAccountSuccess = false;
+ String? deactivateAccountError;
+
+ ProfileSettingsViewModel({
+ required CacheService cacheService,
+ required this.profileSettingsRepo,
+ required this.errorHandlerService,
+ }) : _cacheService = cacheService;
+
+ // ── Dark mode ────────────────────────────────────────────────────────
/// Call once at app startup (before the first frame) to restore the
/// persisted dark-mode preference.
@@ -30,6 +54,75 @@ class ProfileSettingsViewModel extends ChangeNotifier {
notifyListeners();
}
+ // ── Update patient info ──────────────────────────────────────────────
+
+ Future updatePatientInfo({
+ required Map patientInfo,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ isUpdatePatientInfoLoading = true;
+ isUpdatePatientInfoSuccess = false;
+ updatePatientInfoError = null;
+ notifyListeners();
+
+ final result = await profileSettingsRepo.updatePatientInfo(patientInfo: patientInfo);
+
+ result.fold(
+ (failure) {
+ isUpdatePatientInfoLoading = false;
+ updatePatientInfoError = failure.message;
+ notifyListeners();
+ if (onError != null) {
+ onError(failure.message);
+ } else {
+ errorHandlerService.handleError(failure: failure);
+ }
+ },
+ (response) {
+ isUpdatePatientInfoLoading = false;
+ isUpdatePatientInfoSuccess = true;
+ notifyListeners();
+ onSuccess?.call(response.data);
+ },
+ );
+ }
+
+ // ── Deactivate account ───────────────────────────────────────────────
+
+ Future deactivateAccount({
+ Function(dynamic)? onSuccess,
+ Function(String)? onError,
+ }) async {
+ isDeactivateAccountLoading = true;
+ isDeactivateAccountSuccess = false;
+ deactivateAccountError = null;
+ notifyListeners();
+
+ final result = await profileSettingsRepo.deactivateAccount();
+
+ result.fold(
+ (failure) {
+ isDeactivateAccountLoading = false;
+ deactivateAccountError = failure.message;
+ notifyListeners();
+ if (onError != null) {
+ onError(failure.message);
+ } else {
+ errorHandlerService.handleError(failure: failure);
+ }
+ },
+ (response) {
+ isDeactivateAccountLoading = false;
+ isDeactivateAccountSuccess = true;
+ notifyListeners();
+ onSuccess?.call(response.data);
+ },
+ );
+ }
+
+ // ── Helpers ──────────────────────────────────────────────────────────
+
void notify() {
notifyListeners();
}
diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart
index 2aeb87f1..031e1be9 100644
--- a/lib/generated/locale_keys.g.dart
+++ b/lib/generated/locale_keys.g.dart
@@ -1581,5 +1581,6 @@ abstract class LocaleKeys {
static const ratings = 'ratings';
static const hmgPharmacyText = 'hmgPharmacyText';
static const insuranceRequestSubmittedSuccessfully = 'insuranceRequestSubmittedSuccessfully';
+ static const updatingEmailAddress = 'updatingEmailAddress';
}
diff --git a/lib/presentation/appointments/my_doctors_page.dart b/lib/presentation/appointments/my_doctors_page.dart
index d1ea0e98..002f537c 100644
--- a/lib/presentation/appointments/my_doctors_page.dart
+++ b/lib/presentation/appointments/my_doctors_page.dart
@@ -93,8 +93,6 @@ class _MyDoctorsPageState extends State {
borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
-
-
),
SizedBox(width: 8.h),
CustomButton(
@@ -280,7 +278,7 @@ class _MyDoctorsPageState extends State {
runSpacing: 4.h,
children: [
AppCustomChipWidget(
- labelText: isSortByClinic ? (doctor?.clinicName ?? "") : (doctor?.projectName ?? ""),
+ labelText: isSortByClinic ? (doctor?.projectName ?? "") : (doctor?.clinicName ?? ""),
),
],
),
diff --git a/lib/presentation/book_appointment/widgets/doctor_rating_details.dart b/lib/presentation/book_appointment/widgets/doctor_rating_details.dart
index 6d9e1cb2..1a5eedfe 100644
--- a/lib/presentation/book_appointment/widgets/doctor_rating_details.dart
+++ b/lib/presentation/book_appointment/widgets/doctor_rating_details.dart
@@ -20,13 +20,20 @@ class DoctorRatingDetails extends StatelessWidget {
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.ceilToDouble().toString().toText44(isBold: true),
+ bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.ceilToDouble().toString().toText44(isBold: true, isEnglishOnly: true),
SizedBox(height: 4.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- "${bookAppointmentsVM.doctorsProfileResponseModel.noOfPatientsRate} ${LocaleKeys.reviews.tr(context: context)}"
- .toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor),
+ Row(
+ children: [
+ "${bookAppointmentsVM.doctorsProfileResponseModel.noOfPatientsRate} "
+ .toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor, isEnglishOnly: true),
+ LocaleKeys.reviews.tr(context: context)
+ .toText16(weight: FontWeight.w500, color: AppColors.greyInfoTextColor,),
+ ],
+ ),
+
RatingBar(
initialRating: bookAppointmentsVM.doctorsProfileResponseModel.actualDoctorRate!.toDouble(),
direction: Axis.horizontal,
@@ -75,7 +82,7 @@ class DoctorRatingDetails extends StatelessWidget {
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
- child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
+ child: Text("${getRatingWidth(bookAppointmentsVM.doctorDetailsList[0].ratio).round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
),
],
),
@@ -95,7 +102,7 @@ class DoctorRatingDetails extends StatelessWidget {
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
- child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
+ child: Text("${bookAppointmentsVM.doctorDetailsList[1].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
),
],
),
@@ -115,7 +122,7 @@ class DoctorRatingDetails extends StatelessWidget {
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
- child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
+ child: Text("${bookAppointmentsVM.doctorDetailsList[2].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
),
],
),
@@ -135,7 +142,7 @@ class DoctorRatingDetails extends StatelessWidget {
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
- child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
+ child: Text("${bookAppointmentsVM.doctorDetailsList[3].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
),
],
),
@@ -156,7 +163,7 @@ class DoctorRatingDetails extends StatelessWidget {
),
Container(
margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0),
- child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600)),
+ child: Text("${bookAppointmentsVM.doctorDetailsList[4].ratio.round()}%", style: TextStyle(fontSize: 14.0, color: AppColors.textColor, fontWeight: FontWeight.w600, fontFamily: "Poppins")),
),
],
),
diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart
index 3012876f..0c17434e 100644
--- a/lib/presentation/home/landing_page.dart
+++ b/lib/presentation/home/landing_page.dart
@@ -407,10 +407,10 @@ class _LandingPageState extends State {
? myAppointmentsVM.patientAppointmentsHistoryList.length
: 3,
layout: SwiperLayout.STACK,
- loop: true,
+ loop: false,
itemWidth: MediaQuery.of(context).size.width - 48.h,
indicatorLayout: PageIndicatorLayout.COLOR,
- axisDirection: AxisDirection.right,
+ axisDirection: getIt.get().isArabic() ? AxisDirection.left : AxisDirection.right,
controller: _controller,
itemHeight: 255.h + 20,
// extra space for shadow
diff --git a/lib/presentation/home/widgets/large_service_card.dart b/lib/presentation/home/widgets/large_service_card.dart
index 4405a197..b89e58c5 100644
--- a/lib/presentation/home/widgets/large_service_card.dart
+++ b/lib/presentation/home/widgets/large_service_card.dart
@@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
+import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@@ -92,12 +93,12 @@ class LargeServiceCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
serviceCardData.title.tr(context: context).toText14(isBold: true, color: AppColors.textColor),
- serviceCardData.subtitle.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight),
+ serviceCardData.subtitle.tr(context: context).toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight, maxLine: 2),
],
),
),
],
- ).paddingSymmetrical(16.w, 0.h).expanded,
+ ).paddingSymmetrical(8.w, 0.h).expanded,
CustomButton(
text: serviceCardData.isBold ? LocaleKeys.visitPharmacyOnline.tr(context: context) : LocaleKeys.bookNow.tr(context: context),
onPressed: () {
@@ -177,7 +178,9 @@ class FadedLargeServiceCard extends StatelessWidget {
children: [
ClipRRect(
borderRadius: BorderRadius.circular(24.r),
- child: Image.asset(serviceCardData.largeCardIcon, fit: BoxFit.cover, width: 520.w, height: 250.h),
+ child: Transform.flip(
+ flipX: getIt.get().isArabic(),
+ child: Image.asset(serviceCardData.largeCardIcon, fit: BoxFit.cover, width: 520.w, height: 250.h)),
),
Positioned(
top: 0,
@@ -216,11 +219,14 @@ class FadedLargeServiceCard extends StatelessWidget {
),
child: Padding(
padding: EdgeInsets.all(8.h),
- child: Utils.buildSvgWithAssets(
- icon: serviceCardData.icon,
- iconColor: serviceCardData.iconColor,
- fit: BoxFit.contain,
- applyThemeColor: false
+ child: Transform.flip(
+ flipX: getIt.get().isArabic(),
+ child: Utils.buildSvgWithAssets(
+ icon: serviceCardData.icon,
+ iconColor: serviceCardData.iconColor,
+ fit: BoxFit.contain,
+ applyThemeColor: false
+ ),
),
),
),
diff --git a/lib/presentation/insurance/widgets/insurance_update_details_card.dart b/lib/presentation/insurance/widgets/insurance_update_details_card.dart
index 59a4dd97..2136f0cb 100644
--- a/lib/presentation/insurance/widgets/insurance_update_details_card.dart
+++ b/lib/presentation/insurance/widgets/insurance_update_details_card.dart
@@ -110,6 +110,7 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
LoaderBottomSheet.hideLoader();
insuranceViewModel.setIsInsuranceDataToBeLoaded(true);
insuranceViewModel.initInsuranceProvider();
+ Navigator.pop(context);
}, onError: (err) {
insuranceViewModel.updatePatientInsuranceCard(
patientID: appState.getAuthenticatedUser()!.patientId!,
@@ -129,9 +130,9 @@ class PatientInsuranceCardUpdateCard extends StatelessWidget {
isFullScreen: false,
isCloseButtonVisible: false,
);
- Future.delayed(Duration(milliseconds: 2000)).then((value) async {
- Navigator.pop(context);
- });
+ // Future.delayed(Duration(milliseconds: 2000)).then((value) async {
+ // Navigator.pop(context);
+ // });
},
onError: (err) {
LoaderBottomSheet.hideLoader();
diff --git a/lib/presentation/lab/lab_order_by_test.dart b/lib/presentation/lab/lab_order_by_test.dart
index 1b5db920..ac6f0f3b 100644
--- a/lib/presentation/lab/lab_order_by_test.dart
+++ b/lib/presentation/lab/lab_order_by_test.dart
@@ -59,7 +59,7 @@ class LabOrderByTest extends StatelessWidget {
icon: AppAssets.view_report_icon,
iconColor: AppColors.primaryRedColor,
iconSize: 16.h,
- text: LocaleKeys.viewReport.tr(context: context),
+ text: LocaleKeys.viewResults.tr(context: context),
onPressed: () {
onTap();
},
diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart
index b804a751..1c839c10 100644
--- a/lib/presentation/medical_file/medical_file_page.dart
+++ b/lib/presentation/medical_file/medical_file_page.dart
@@ -283,9 +283,9 @@ class _MedicalFilePageState extends State {
),
AppCustomChipWidget(
icon: AppAssets.blood_icon,
- labelText: LocaleKeys.bloodGroup.tr(namedArgs: {'bloodType': appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup}, context: context),
+ labelText: appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup,
iconColor: AppColors.primaryRedColor,
- labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
+ labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
padding: EdgeInsets.zero,
),
Consumer(builder: (context, insuranceVM, child) {
@@ -749,7 +749,26 @@ class _MedicalFilePageState extends State {
],
).paddingSymmetrical(0.w, 0.h),
SizedBox(height: 24.h),
- LocaleKeys.activeMedicationsAndPrescriptions.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ LocaleKeys.activeMedicationsAndPrescriptions.tr(context: context).toText16(weight: FontWeight.w500, letterSpacing: -0.2),
+ Row(
+ children: [
+ LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500),
+ SizedBox(width: 2.w),
+ Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
+ ],
+ ).onPress(() {
+ // myAppointmentsViewModel.getPatientMyDoctors();
+ Navigator.of(context).push(
+ CustomPageRoute(
+ page: PrescriptionsListPage(),
+ ),
+ );
+ }),
+ ],
+ ),
SizedBox(height: 16.h),
Consumer(builder: (context, prescriptionVM, child) {
return prescriptionVM.isPrescriptionsOrdersLoading
@@ -830,55 +849,55 @@ class _MedicalFilePageState extends State {
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
SizedBox(height: 16.h),
- Divider(color: AppColors.dividerColor),
- SizedBox(height: 16.h),
- Row(
- children: [
- Expanded(
- child: CustomButton(
- text: LocaleKeys.allPrescriptions.tr(context: context),
- onPressed: () {
- Navigator.of(context).push(
- CustomPageRoute(
- page: PrescriptionsListPage(),
- ),
- );
- },
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- fontSize: 12.f,
- fontWeight: FontWeight.w500,
- borderRadius: 12.r,
- height: 40.h,
- icon: AppAssets.requests,
- iconColor: AppColors.primaryRedColor,
- iconSize: 16.w,
- ),
- ),
- SizedBox(width: 6.w),
- Expanded(
- child: CustomButton(
- text: LocaleKeys.allMedications.tr(context: context),
- onPressed: () { Navigator.of(context).push(
- CustomPageRoute(
- page: ActiveMedicationPage(),
- ),
- );},
- backgroundColor: AppColors.secondaryLightRedColor,
- borderColor: AppColors.secondaryLightRedColor,
- textColor: AppColors.primaryRedColor,
- fontSize: 12.f,
- fontWeight: FontWeight.w500,
- borderRadius: 12.h,
- height: 40.h,
- icon: AppAssets.all_medications_icon,
- iconColor: AppColors.primaryRedColor,
- iconSize: 16.h,
- ),
- ),
- ],
- ),
+ // Divider(color: AppColors.dividerColor),
+ // SizedBox(height: 16.h),
+ // Row(
+ // children: [
+ // Expanded(
+ // child: CustomButton(
+ // text: LocaleKeys.allPrescriptions.tr(context: context),
+ // onPressed: () {
+ // Navigator.of(context).push(
+ // CustomPageRoute(
+ // page: PrescriptionsListPage(),
+ // ),
+ // );
+ // },
+ // backgroundColor: AppColors.secondaryLightRedColor,
+ // borderColor: AppColors.secondaryLightRedColor,
+ // textColor: AppColors.primaryRedColor,
+ // fontSize: 12.f,
+ // fontWeight: FontWeight.w500,
+ // borderRadius: 12.r,
+ // height: 40.h,
+ // icon: AppAssets.requests,
+ // iconColor: AppColors.primaryRedColor,
+ // iconSize: 16.w,
+ // ),
+ // ),
+ // SizedBox(width: 6.w),
+ // Expanded(
+ // child: CustomButton(
+ // text: LocaleKeys.allMedications.tr(context: context),
+ // onPressed: () { Navigator.of(context).push(
+ // CustomPageRoute(
+ // page: ActiveMedicationPage(),
+ // ),
+ // );},
+ // backgroundColor: AppColors.secondaryLightRedColor,
+ // borderColor: AppColors.secondaryLightRedColor,
+ // textColor: AppColors.primaryRedColor,
+ // fontSize: 12.f,
+ // fontWeight: FontWeight.w500,
+ // borderRadius: 12.h,
+ // height: 40.h,
+ // icon: AppAssets.all_medications_icon,
+ // iconColor: AppColors.primaryRedColor,
+ // iconSize: 16.h,
+ // ),
+ // ),
+ // ],
+ // ),
],
),
),
@@ -911,7 +930,7 @@ class _MedicalFilePageState extends State {
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
).onPress(() {
- myAppointmentsViewModel.getPatientMyDoctors();
+ // myAppointmentsViewModel.getPatientMyDoctors();
Navigator.of(context).push(
CustomPageRoute(
page: MyDoctorsPage(),
@@ -1210,6 +1229,26 @@ class _MedicalFilePageState extends State {
// Requests Tab Data
return Column(
children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}".toText16(isBold: true),
+ Row(
+ children: [
+ LocaleKeys.viewAll.tr(context: context).toText12(color: AppColors.primaryRedColor),
+ SizedBox(width: 2.h),
+ Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
+ ],
+ ),
+ ],
+ ).onPress(() {
+ Navigator.of(context).push(
+ CustomPageRoute(
+ page: PatientSickleavesListPage(),
+ ),
+ );
+ }),
+ SizedBox(height: 16.h),
Consumer(builder: (context, medicalFileVM, child) {
return medicalFileVM.isPatientSickLeaveListLoading
? PatientSickLeaveCard(
@@ -1279,20 +1318,20 @@ class _MedicalFilePageState extends State {
),
);
}),
- MedicalFileCard(
- label: LocaleKeys.sickLeaveReport.tr(context: context),
- textColor: AppColors.blackColor,
- backgroundColor: AppColors.whiteColor,
- svgIcon: AppAssets.sick_leave_report_icon,
- isLargeText: true,
- iconSize: 36.h,
- ).onPress(() {
- Navigator.of(context).push(
- CustomPageRoute(
- page: PatientSickleavesListPage(),
- ),
- );
- }),
+ // MedicalFileCard(
+ // label: LocaleKeys.sickLeaveReport.tr(context: context),
+ // textColor: AppColors.blackColor,
+ // backgroundColor: AppColors.whiteColor,
+ // svgIcon: AppAssets.sick_leave_report_icon,
+ // isLargeText: true,
+ // iconSize: 36.h,
+ // ).onPress(() {
+ // Navigator.of(context).push(
+ // CustomPageRoute(
+ // page: PatientSickleavesListPage(),
+ // ),
+ // );
+ // }),
],
).paddingSymmetrical(0.w, 0.0),
SizedBox(height: 24.h),
diff --git a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
index a0c54e68..18bd2e69 100644
--- a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
+++ b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart
@@ -40,18 +40,17 @@ class PatientSickLeaveCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- "${LocaleKeys.sick.tr(context: context)} ${LocaleKeys.sickSubtitle.tr(context: context)}".toText16(isBold: true).toShimmer2(isShow: isLoading),
- AppCustomChipWidget(
- labelText: isLoading ? "" : getStatusText(context),
- backgroundColor: getStatusColor().withOpacity(0.15),
- textColor: getStatusColor(),
- ).toShimmer2(isShow: isLoading, width: 100.h),
- ],
- ),
- SizedBox(height: 16.h),
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ // children: [
+ // AppCustomChipWidget(
+ // labelText: isLoading ? "" : getStatusText(context),
+ // backgroundColor: getStatusColor().withOpacity(0.15),
+ // textColor: getStatusColor(),
+ // ).toShimmer2(isShow: isLoading, width: 100.h),
+ // ],
+ // ),
+ // SizedBox(height: 16.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
diff --git a/lib/presentation/my_family/widget/family_cards.dart b/lib/presentation/my_family/widget/family_cards.dart
index 826b1741..f304fcc3 100644
--- a/lib/presentation/my_family/widget/family_cards.dart
+++ b/lib/presentation/my_family/widget/family_cards.dart
@@ -102,7 +102,7 @@ class _FamilyCardsState extends State {
: profile.status == FamilyFileEnum.active.toInt
? AppColors.lightGreenColor
: AppColors.lightGrayBGColor,
- chipText: profile.statusDescription ?? "N/A",
+ chipText: profile.statusDescription ?? " N/A",
iconAsset: null,
isShowBorder: false,
borderRadius: 8.h,
@@ -154,7 +154,7 @@ class _FamilyCardsState extends State {
crossAxisCount: 2,
crossAxisSpacing: 10.w,
mainAxisSpacing: 10.h,
- childAspectRatio: widget.isShowDetails ? 0.56.h : 0.64.h,
+ childAspectRatio: widget.isShowDetails ? 0.56.h : 0.74.h,
),
padding: EdgeInsets.only(bottom: 20.h),
itemBuilder: (context, index) {
@@ -164,7 +164,7 @@ class _FamilyCardsState extends State {
final canSwitch = isParentUser || (!isParentUser && profile.responseId == appState.getSuperUserID);
return Container(
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 15.h),
- decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24),
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
child: Opacity(
opacity: isActive || profile.status == FamilyFileEnum.pending.toInt || !canSwitch ? 0.4 : 1.0, // Fade all content if active
child: Stack(
@@ -187,7 +187,7 @@ class _FamilyCardsState extends State {
CustomChipWidget(
chipType: ChipTypeEnum.alert,
backgroundColor: AppColors.lightGrayBGColor,
- chipText: "Relation:${profile.relationship ?? " N/A"}",
+ chipText: "Relation: ${profile.relationship ?? " N/A"}",
iconAsset: AppAssets.heart,
isShowBorder: false,
borderRadius: 8.h,
diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart
index e975d6f4..98002ca9 100644
--- a/lib/presentation/profile_settings/profile_settings.dart
+++ b/lib/presentation/profile_settings/profile_settings.dart
@@ -24,6 +24,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_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/profile_settings/widgets/update_email_widget.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/widgets/app_language_change.dart';
@@ -115,7 +116,7 @@ class ProfileSettingsState extends State {
// extra space for shadow
itemWidth: SizeUtils.width - 30.w,
indicatorLayout: PageIndicatorLayout.COLOR,
- axisDirection: AxisDirection.right,
+ axisDirection: getIt.get().isArabic() ? AxisDirection.left : AxisDirection.right,
controller: _controller,
pagination: SwiperPagination(
alignment: Alignment.bottomCenter,
@@ -234,24 +235,24 @@ class ProfileSettingsState extends State {
],
),
),
- 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.language_change, LocaleKeys.language.tr(context: context), () {
- showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.language.tr(context: context), child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false);
- }, trailingLabel: Utils.appState.isArabic() ? "العربية" : "English"),
- 1.divider,
- actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () {
- openAppSettings();
- }),
- // 1.divider,
- // actionItem(AppAssets.touch_face_id, LocaleKeys.touchIDFaceIDServices.tr(context: context), () {}, switchValue: true),
- ],
- ),
- ),
+ // 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.language_change, LocaleKeys.language.tr(context: context), () {
+ // showCommonBottomSheetWithoutHeight(context, title: LocaleKeys.language.tr(context: context), child: AppLanguageChange(), callBackFunc: () {}, isFullScreen: false);
+ // }, trailingLabel: Utils.appState.isArabic() ? "العربية" : "English"),
+ // 1.divider,
+ // actionItem(AppAssets.bell, LocaleKeys.notificationsSettings.tr(context: context), () {
+ // openAppSettings();
+ // }),
+ // // 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),
@@ -259,7 +260,15 @@ class ProfileSettingsState extends State {
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r, hasShadow: true),
child: Column(
children: [
- actionItem(AppAssets.email_transparent, LocaleKeys.updateEmailAddress.tr(context: context), () {}),
+ 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,
@@ -385,10 +394,24 @@ class FamilyCardWidget extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
"${profile.patientName}".toText18(isBold: true, weight: FontWeight.w600, textOverflow: TextOverflow.ellipsis, maxlines: 1, isEnglishOnly: true),
- AppCustomChipWidget(
- icon: AppAssets.file_icon,
- labelText: "${LocaleKeys.fileNo.tr(context: context)}: ${profile.responseId}",
- iconSize: 12.w,
+ Wrap(
+ direction: Axis.horizontal,
+ spacing: 4.w,
+ runSpacing: 6.w,
+ children: [
+ AppCustomChipWidget(
+ labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
+ icon: AppAssets.file_icon,
+ labelText: "${LocaleKeys.fileno.tr(context: context)}: ${profile.responseId}",
+ iconSize: 12.w,
+ ),
+ isActive ? AppCustomChipWidget(
+ icon: AppAssets.checkmark_icon,
+ labelText: LocaleKeys.verified.tr(context: context),
+ iconColor: AppColors.successColor,
+ labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w),
+ ) : SizedBox.shrink(),
+ ],
),
],
).expanded,
@@ -406,13 +429,14 @@ class FamilyCardWidget extends StatelessWidget {
AppCustomChipWidget(
labelText: LocaleKeys.ageYearsOld.tr(namedArgs: {'age': profile.age.toString(), 'yearsOld': LocaleKeys.yearsOld.tr(context: context)}),
),
- isActive && appState.getAuthenticatedUser()!.bloodGroup != null
- ? AppCustomChipWidget(
- icon: AppAssets.blood_icon,
+ // isActive && appState.getAuthenticatedUser()!.bloodGroup != null
+ // ?
+ isActive ? AppCustomChipWidget(
+ icon: AppAssets.blood_icon,
labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 8.w),
- labelText: "Blood: ${appState.getAuthenticatedUser()!.bloodGroup ?? ""}",
- iconColor: AppColors.primaryRedColor)
- : SizedBox(),
+ labelText: appState.getAuthenticatedUser()!.bloodGroup ?? "N/A",
+ iconColor: AppColors.primaryRedColor)
+ : SizedBox(),
Consumer(builder: (context, insuranceVM, child) {
return isActive
? AppCustomChipWidget(
diff --git a/lib/presentation/profile_settings/widgets/update_email_widget.dart b/lib/presentation/profile_settings/widgets/update_email_widget.dart
new file mode 100644
index 00000000..ad9b9d5a
--- /dev/null
+++ b/lib/presentation/profile_settings/widgets/update_email_widget.dart
@@ -0,0 +1,106 @@
+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 UpdateEmailDialog extends StatefulWidget {
+ UpdateEmailDialog({super.key});
+
+ @override
+ State createState() => _UpdateEmailDialogState();
+}
+
+class _UpdateEmailDialogState extends State {
+ late FocusNode _textFieldFocusNode;
+ late TextEditingController? textController;
+ ProfileSettingsViewModel? profileSettingsViewModel;
+
+ @override
+ void initState() {
+ _textFieldFocusNode = FocusNode();
+ textController = TextEditingController();
+ textController!.text = getIt.get().getAuthenticatedUser()!.emailAddress ?? "";
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ _textFieldFocusNode.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ profileSettingsViewModel = Provider.of(context);
+ return GestureDetector(
+ onTap: () {
+ _textFieldFocusNode.unfocus();
+ FocusScope.of(context).unfocus();
+ },
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Enter the new email address to be updated in your HMG File: ".toText16(textAlign: TextAlign.start, weight: FontWeight.w500),
+ SizedBox(height: 12.h),
+ TextInputWidget(
+ labelText: LocaleKeys.email.tr(),
+ hintText: "demo@gmail.com",
+ controller: textController,
+ focusNode: _textFieldFocusNode,
+ autoFocus: true,
+ padding: EdgeInsets.all(8.h),
+ keyboardType: TextInputType.emailAddress,
+ isEnable: true,
+ isReadOnly: false,
+ prefix: null,
+ isBorderAllowed: false,
+ isAllowLeadingIcon: true,
+ fontSize: 14.f,
+ isCountryDropDown: false,
+ leadingIcon: AppAssets.email,
+ fontFamily: "Poppins",
+ ),
+ SizedBox(height: 12.h),
+ CustomButton(
+ text: LocaleKeys.submit.tr(context: context),
+ onPressed: () {
+ LoaderBottomSheet.showLoader(loadingText: LocaleKeys.updatingEmailAddress.tr(context: context));
+ profileSettingsViewModel!.updatePatientInfo(
+ patientInfo: {"EmailAddress": textController!.text},
+ 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();
+ }, 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),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/presentation/symptoms_checker/user_info_selection.dart b/lib/presentation/symptoms_checker/user_info_selection.dart
index f1e8413d..b245c014 100644
--- a/lib/presentation/symptoms_checker/user_info_selection.dart
+++ b/lib/presentation/symptoms_checker/user_info_selection.dart
@@ -100,7 +100,7 @@ class _UserInfoSelectionPageState extends State {
children: [
title.toText14(weight: FontWeight.w500),
subTitle
- .toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500)
+ .toText12(color: AppColors.primaryRedColor, fontWeight: FontWeight.w500, isEnglishOnly: true)
.toShimmer2(isShow: (leadingIcon == AppAssets.rulerIcon || leadingIcon == AppAssets.weightScale) && hmgServicesVM.isVitalSignLoading),
],
),
diff --git a/lib/presentation/symptoms_checker/widgets/condition_card.dart b/lib/presentation/symptoms_checker/widgets/condition_card.dart
index e48f41ea..d753b780 100644
--- a/lib/presentation/symptoms_checker/widgets/condition_card.dart
+++ b/lib/presentation/symptoms_checker/widgets/condition_card.dart
@@ -168,7 +168,7 @@ class ConditionCard extends StatelessWidget {
crossAxisAlignment: WrapCrossAlignment.center,
children: [
for (int i = 0; i < symptoms.length; i++) ...[
- "● ${symptoms[i]}".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
+ "● ${symptoms[i]}".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor, isEnglishOnly: true),
if (i != symptoms.length - 1)
Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w),
@@ -228,7 +228,7 @@ class ConditionCard extends StatelessWidget {
backgroundColor: AppColors.scaffoldBgColor,
titleWidget: Row(
children: [
- "$percentage%".toText12(fontWeight: FontWeight.bold, color: getChipColorBySeverityEnum(severityEnum)),
+ "$percentage%".toText12(fontWeight: FontWeight.bold, color: getChipColorBySeverityEnum(severityEnum), isEnglishOnly: true),
],
).paddingSymmetrical(0, 4.h),
),
diff --git a/lib/widgets/appbar/collapsing_list_view.dart b/lib/widgets/appbar/collapsing_list_view.dart
index 4a315c6e..b933e530 100644
--- a/lib/widgets/appbar/collapsing_list_view.dart
+++ b/lib/widgets/appbar/collapsing_list_view.dart
@@ -259,7 +259,7 @@ class _ScrollAnimatedTitleState extends State {
super.dispose();
}
- double t = 0;
+ double t = 1.0;
void _onScroll() {
final double offset = widget.controller.offset;
diff --git a/pubspec.yaml b/pubspec.yaml
index bca92d54..4484fa77 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -2,8 +2,8 @@ name: hmg_patient_app_new
description: "New HMG Patient App"
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
-#version: 0.0.13+10
-version: 0.0.1+13
+version: 0.0.15+12
+#version: 0.0.1+14
environment:
sdk: ">=3.6.0 <4.0.0"