From 3b1b51ef6fa2a5c45946da661fa6d32186d23ed6 Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Wed, 17 Sep 2025 16:42:39 +0300 Subject: [PATCH 1/2] otp screen & register Uae & resend Activation Code. --- .../authentication_view_model.dart | 176 +++++++++--------- lib/widgets/common_bottom_sheet.dart | 12 +- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index 3c05b52..db86889 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -57,7 +57,8 @@ class AuthenticationViewModel extends ChangeNotifier { required NavigationService navigationService, required CacheService cacheService, required LocalAuthService localAuthService, - }) : _navigationService = navigationService, + }) + : _navigationService = navigationService, _dialogService = dialogService, _errorHandlerService = errorHandlerService, _appState = appState, @@ -202,13 +203,13 @@ class AuthenticationViewModel extends ChangeNotifier { final result = await _authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken); result.fold( - (failure) async { + (failure) async { // LoadingUtils.hideFullScreenLoader(); // await _errorHandlerService.handleError(failure: failure); LoaderBottomSheet.hideLoader(); _navigationService.pushPage(page: LoginScreen()); }, - (apiResponse) { + (apiResponse) { // LoadingUtils.hideFullScreenLoader(); log("apiResponse: ${apiResponse.data.toString()}"); log("messageStatus: ${apiResponse.messageStatus.toString()}"); @@ -298,7 +299,8 @@ class AuthenticationViewModel extends ChangeNotifier { final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); result.fold( - (failure) async => await _errorHandlerService.handleError( + (failure) async => + await _errorHandlerService.handleError( failure: failure, onUnHandledFailure: (failure) async { LoaderBottomSheet.hideLoader(); @@ -312,7 +314,7 @@ class AuthenticationViewModel extends ChangeNotifier { _navigationService.pop(); }); }), - (apiResponse) async { + (apiResponse) async { if (apiResponse.messageStatus == 2) { LoaderBottomSheet.hideLoader(); await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {}); @@ -355,8 +357,8 @@ class AuthenticationViewModel extends ChangeNotifier { patientOutSA: isForRegister ? isPatientOutsideSA(request: payload) : selectedCountrySignup.countryCode == CountryEnum.saudiArabia - ? false - : true, + ? false + : true, payload: payload, ); @@ -370,8 +372,8 @@ class AuthenticationViewModel extends ChangeNotifier { final resultEither = await _authenticationRepo.sendActivationCodeRepo(sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er'); resultEither.fold( - (failure) async => await _errorHandlerService.handleError(failure: failure), - (apiResponse) async { + (failure) async => await _errorHandlerService.handleError(failure: failure), + (apiResponse) async { if (apiResponse.messageStatus == 2) { LoaderBottomSheet.hideLoader(); await _dialogService.showCommonBottomSheetWithoutH( @@ -405,27 +407,27 @@ class AuthenticationViewModel extends ChangeNotifier { bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1); final request = RequestUtils.getCommonRequestWelcome( - phoneNumber: phoneNumberController.text, - otpTypeEnum: otpTypeEnum, - deviceToken: _appState.deviceToken, - // patientOutSA: _appState.getUserRegistrationPayload.projectOutSa == 1 ? true : false, - patientOutSA: isForRegister - ? _appState.getUserRegistrationPayload.projectOutSa == true - ? true - : false - : _appState.getSelectDeviceByImeiRespModelElement != null - ? _appState.getSelectDeviceByImeiRespModelElement!.outSa! - : selectedCountrySignup == CountryEnum.saudiArabia - ? false - : true, - loginTokenID: _appState.appAuthToken, - registeredData: isForRegister ? _appState.getUserRegistrationPayload : null, - nationIdText: nationalIdController.text, - countryCode: _appState.getSelectDeviceByImeiRespModelElement != null && _appState.getSelectDeviceByImeiRespModelElement!.outSa == true - ? CountryEnum.unitedArabEmirates.countryCode - : selectedCountrySignup.countryCode, - //TODO: Error Here IN Zip Code. - loginType: loginTypeEnum.toInt) + phoneNumber: phoneNumberController.text, + otpTypeEnum: otpTypeEnum, + deviceToken: _appState.deviceToken, + // patientOutSA: _appState.getUserRegistrationPayload.projectOutSa == 1 ? true : false, + patientOutSA: isForRegister + ? _appState.getUserRegistrationPayload.projectOutSa == true + ? true + : false + : _appState.getSelectDeviceByImeiRespModelElement != null + ? _appState.getSelectDeviceByImeiRespModelElement!.outSa! + : selectedCountrySignup == CountryEnum.saudiArabia + ? false + : true, + loginTokenID: _appState.appAuthToken, + registeredData: isForRegister ? _appState.getUserRegistrationPayload : null, + nationIdText: nationalIdController.text, + countryCode: _appState.getSelectDeviceByImeiRespModelElement != null && _appState.getSelectDeviceByImeiRespModelElement!.outSa == true + ? CountryEnum.unitedArabEmirates.countryCode + : selectedCountrySignup.countryCode, + //TODO: Error Here IN Zip Code. + loginType: loginTypeEnum.toInt) .toJson(); LoaderBottomSheet.showLoader(); if (isForRegister) { @@ -441,7 +443,8 @@ class AuthenticationViewModel extends ChangeNotifier { LoaderBottomSheet.hideLoader(); resultEither.fold( - (failure) async => await _errorHandlerService.handleError( + (failure) async => + await _errorHandlerService.handleError( failure: failure, onUnHandledFailure: (failure) async { LoaderBottomSheet.hideLoader(); @@ -468,7 +471,8 @@ class AuthenticationViewModel extends ChangeNotifier { final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: CheckActivationCodeRegisterReq.fromJson(request), activationCode: activationCode, isRegister: false); resultEither.fold( - (failure) async => await _errorHandlerService.handleError( + (failure) async => + await _errorHandlerService.handleError( failure: failure, onUnHandledFailure: (failure) async { LoaderBottomSheet.hideLoader(); @@ -652,15 +656,15 @@ class AuthenticationViewModel extends ChangeNotifier { bool isOutSidePatient = selectedCountrySignup.countryCode == CountryEnum.unitedArabEmirates.countryCode ? true : false; LoaderBottomSheet.showLoader(); final request = await RequestUtils.getPatientAuthenticationRequest( - phoneNumber: phoneNumberController.text, - nationId: nationalIdController.text, - patientOutSA: isOutSidePatient, - otpTypeEnum: otpTypeEnum, - isForRegister: true, - patientId: 0, - zipCode: selectedCountrySignup.countryCode, - calenderType: calenderType, - dob: dob) + phoneNumber: phoneNumberController.text, + nationId: nationalIdController.text, + patientOutSA: isOutSidePatient, + otpTypeEnum: otpTypeEnum, + isForRegister: true, + patientId: 0, + zipCode: selectedCountrySignup.countryCode, + calenderType: calenderType, + dob: dob) .toJson(); var nRequest = Map.from(request); @@ -796,22 +800,22 @@ class AuthenticationViewModel extends ChangeNotifier { Future insertPatientIMEIData(int loginType) async { final resultEither = await _authenticationRepo.insertPatientIMEIData( patientIMEIDataRequest: PatientInsertDeviceImei( - imei: _appState.deviceToken, - deviceTypeId: _appState.getDeviceTypeID(), - patientId: _appState.getAuthenticatedUser()!.patientId!, - patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, - identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, - firstName: _appState.getAuthenticatedUser()!.firstName!, - lastName: _appState.getAuthenticatedUser()!.lastName!, - patientTypeId: _appState.getAuthenticatedUser()!.patientType, - mobileNo: _appState.getAuthenticatedUser()!.mobileNumber!, - logInTypeId: loginType, - patientOutSa: _appState.getAuthenticatedUser()!.outSa!, - outSa: _appState.getAuthenticatedUser()!.outSa == 1 ? true : false, - biometricEnabled: loginType == 1 || loginType == 2 ? false : true, - firstNameN: _appState.getAuthenticatedUser()!.firstNameN, - lastNameN: _appState.getAuthenticatedUser()!.lastNameN, - ).toJson()); + imei: _appState.deviceToken, + deviceTypeId: _appState.getDeviceTypeID(), + patientId: _appState.getAuthenticatedUser()!.patientId!, + patientIdentificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, + identificationNo: _appState.getAuthenticatedUser()!.patientIdentificationNo!, + firstName: _appState.getAuthenticatedUser()!.firstName!, + lastName: _appState.getAuthenticatedUser()!.lastName!, + patientTypeId: _appState.getAuthenticatedUser()!.patientType, + mobileNo: _appState.getAuthenticatedUser()!.mobileNumber!, + logInTypeId: loginType, + patientOutSa: _appState.getAuthenticatedUser()!.outSa!, + outSa: _appState.getAuthenticatedUser()!.outSa == 1 ? true : false, + biometricEnabled: loginType == 1 || loginType == 2 ? false : true, + firstNameN: _appState.getAuthenticatedUser()!.firstNameN, + lastNameN: _appState.getAuthenticatedUser()!.lastNameN, + ).toJson()); resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { if (apiResponse.messageStatus == 1) { log("Insert IMEI Success"); @@ -825,20 +829,20 @@ class AuthenticationViewModel extends ChangeNotifier { Future insertPatientDeviceData(int loginType) async { final resultEither = await _authenticationRepo.insertPatientDeviceData( patientDeviceDataRequest: InsertPatientMobileDeviceInfo( - deviceToken: _appState.deviceToken, - deviceTypeId: _appState.getDeviceTypeID(), - patientId: _appState.getAuthenticatedUser()!.patientId!, - patientTypeId: _appState.getAuthenticatedUser()!.patientType, - patientOutSa: _appState.getAuthenticatedUser()!.outSa!, - loginType: loginType, - languageId: _appState.getLanguageID(), - latitude: _appState.userLat, - longitude: _appState.userLong, - voipToken: "", - deviceType: _appState.deviceTypeID, - patientMobileNumber: _appState.getAuthenticatedUser()!.mobileNumber, - nationalId: _appState.getAuthenticatedUser()!.patientIdentificationNo, - gender: _appState.getAuthenticatedUser()!.gender) + deviceToken: _appState.deviceToken, + deviceTypeId: _appState.getDeviceTypeID(), + patientId: _appState.getAuthenticatedUser()!.patientId!, + patientTypeId: _appState.getAuthenticatedUser()!.patientType, + patientOutSa: _appState.getAuthenticatedUser()!.outSa!, + loginType: loginType, + languageId: _appState.getLanguageID(), + latitude: _appState.userLat, + longitude: _appState.userLong, + voipToken: "", + deviceType: _appState.deviceTypeID, + patientMobileNumber: _appState.getAuthenticatedUser()!.mobileNumber, + nationalId: _appState.getAuthenticatedUser()!.patientIdentificationNo, + gender: _appState.getAuthenticatedUser()!.gender) .toJson()); resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { if (apiResponse.messageStatus == 1) { @@ -852,18 +856,18 @@ class AuthenticationViewModel extends ChangeNotifier { Future getPatientDeviceData(int loginType) async { final resultEither = await _authenticationRepo.getPatientDeviceData( patientDeviceDataRequest: GetUserMobileDeviceData( - deviceToken: _appState.deviceToken, - deviceTypeId: _appState.getDeviceTypeID(), - patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!, - patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType, - patientOutSa: _appState.getSelectDeviceByImeiRespModelElement!.outSa == true ? 1 : 0, - loginType: loginType, - languageId: _appState.getLanguageID(), - latitude: _appState.userLat, - longitude: _appState.userLong, - mobileNo: _appState.getSelectDeviceByImeiRespModelElement!.mobile!, - patientMobileNumber: int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!), - nationalId: _appState.getSelectDeviceByImeiRespModelElement!.identificationNo) + deviceToken: _appState.deviceToken, + deviceTypeId: _appState.getDeviceTypeID(), + patientId: _appState.getSelectDeviceByImeiRespModelElement!.patientId!, + patientType: _appState.getSelectDeviceByImeiRespModelElement!.patientType, + patientOutSa: _appState.getSelectDeviceByImeiRespModelElement!.outSa == true ? 1 : 0, + loginType: loginType, + languageId: _appState.getLanguageID(), + latitude: _appState.userLat, + longitude: _appState.userLong, + mobileNo: _appState.getSelectDeviceByImeiRespModelElement!.mobile!, + patientMobileNumber: int.parse(_appState.getSelectDeviceByImeiRespModelElement!.mobile!), + nationalId: _appState.getSelectDeviceByImeiRespModelElement!.identificationNo) .toJson()); resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { if (apiResponse.messageStatus == 1) { @@ -878,7 +882,7 @@ class AuthenticationViewModel extends ChangeNotifier { message: apiResponse.errorMessage ?? "", label: LocaleKeys.notice.tr(), onOkPressed: () { - _dialogService.showPhoneNumberPickerSheet(onSMSPress: () { + _dialogService.showPhoneNumberPickerSheet(label:"Where would you like to receive OTP?", message:"Please select from the below options to receive OTP.", onSMSPress: () { checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms); }, onWhatsappPress: () { checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp); @@ -907,8 +911,8 @@ class AuthenticationViewModel extends ChangeNotifier { List projectDetailListModel = []; resultEither.fold( - (failure) async => await _errorHandlerService.handleError(failure: failure), - (apiResponse) async { + (failure) async => await _errorHandlerService.handleError(failure: failure), + (apiResponse) async { if (apiResponse.messageStatus == 2) { await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); } else { diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart index 576e923..c50ffad 100644 --- a/lib/widgets/common_bottom_sheet.dart +++ b/lib/widgets/common_bottom_sheet.dart @@ -109,11 +109,11 @@ void showCommonBottomSheetWithoutHeight( required Widget child, required VoidCallback callBackFunc, String title = "", - - bool isCloseButtonVisible = true, - bool isFullScreen = true, - bool isDismissible = true, - Widget? titleWidget,}) { + bool isCloseButtonVisible = true, + bool isFullScreen = true, + bool isDismissible = true, + Widget? titleWidget, +}) { showModalBottomSheet( sheetAnimationStyle: AnimationStyle( duration: Duration(milliseconds: 500), // Custom animation duration @@ -141,7 +141,7 @@ void showCommonBottomSheetWithoutHeight( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - titleWidget ?? title.toText20(weight: FontWeight.w600), + titleWidget ?? Expanded(child: title.toText20(weight: FontWeight.w600)), Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() { Navigator.of(context).pop(); }), -- 2.30.2 From 2b7656d83a10e5304f3c275b2047af804665f9cc Mon Sep 17 00:00:00 2001 From: aamir-csol Date: Thu, 18 Sep 2025 10:07:34 +0300 Subject: [PATCH 2/2] otp screen & register Uae & resend Activation Code. --- assets/langs/ar-SA.json | 33 ++++- assets/langs/en-US.json | 39 ++++-- lib/core/enums.dart | 2 +- lib/core/utils/validation_utils.dart | 26 ++-- lib/extensions/string_extensions.dart | 2 +- .../widgets/otp_verification_screen.dart | 129 +++++------------- lib/generated/locale_keys.g.dart | 21 +++ lib/presentation/authentication/register.dart | 4 +- .../authentication/register_step2.dart | 8 +- lib/widgets/appbar/app_bar_widget.dart | 7 +- .../bottomsheet/generic_bottom_sheet.dart | 3 +- .../dropdown/country_dropdown_widget.dart | 81 ++++++++++- lib/widgets/input_widget.dart | 2 +- 13 files changed, 222 insertions(+), 135 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 08ef65c..ea6ad94 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -778,13 +778,13 @@ "aboutApp": "حول التطبيق", "dontHaveAccount": "ليس لديك حساب؟", "loginOrRegister": "تسجيل الدخول أو التسجيل", - "myFiles" : "ملفاتي", + "myFiles": "ملفاتي", "resultsPending": "النتائج معلقة", "resultsAvailable": "النتائج متاحة", "viewReport": "عرض التقرير", "checkAvailability": "التحقق من التوفر", "readInstructions": "قراءة التعليمات", - "searchLabReport" : "ابحث عن تقرير المختبر", + "searchLabReport": "ابحث عن تقرير المختبر", "prescriptionDeliveryError": "هذه العيادة لا تدعم إعادة التعبئة والتسليم.", "receiveOtpToast": "أين تود تلقي رمز التحقق OTP؟", "enterPhoneNumber": "أدخل رقم الهاتف", @@ -807,10 +807,10 @@ "loginByOTP": "تسجيل الدخول بواسطة OTP", "guest": "زائر", "switchAccount": "تبديل الحساب", - "lastLoginBy":"آخر تسجيل دخول بواسطة", + "lastLoginBy": "آخر تسجيل دخول بواسطة", "allSet": "جاهز! الآن يمكنك تسجيل الدخول باستخدام Face ID / Biometric أو البصمة", - "enableQuickLogin":"تمكين تسجيل الدخول السريع", - "enableMsg":"تمكين تسجيل الدخول السريع سيسمح بالتحقق من خلال Face ID / Biometric الخاص بجهازك الحالي", + "enableQuickLogin": "تمكين تسجيل الدخول السريع", + "enableMsg": "تمكين تسجيل الدخول السريع سيسمح بالتحقق من خلال Face ID / Biometric الخاص بجهازك الحالي", "notNow": "ليس الآن", "pendingActivation": "في انتظار التنشيط", "awaitingApproval": "انتظر القبول", @@ -825,6 +825,27 @@ "selectFacility": "اختر المرافق", "selectFacilitiesSubTitle": "يرجى اختيار المرفق للموعد", "selectHospitalSubTitle": "يرجى اختيار المستشفى للموعد", - "iAcceptThe" : "أوافق على", + "iAcceptThe": "أوافق على", "personalDetailsVerification": "التحقق من التفاصيل الشخصية", + "otpVerification": "التحقق من OTP", + "weHaveSendOTP": "لقد أرسلنا OTP إلى", + "via": "عبر", + "forRegistrationVerification": "للتحقق من التسجيل", + "didntReceiveIt": "لم تستلمه؟", + "resendOTP": "إعادة إرسال", + "resendIn": "إعادة الإرسال في", + "pleaseEnterAnationalID": "يرجى إدخال رقم الهوية الوطنية", + "pleaseEnterAFileNumber": "يرجى إدخال رقم الملف", + "pleaseEnterAValidEmail": "يرجى إدخال بريد إلكتروني صالح", + "pleaseEnterFullName": "يرجى إدخال الاسم الكامل", + "pleaseAcceptTermsConditions": "يرجى قبول الشروط والأحكام", + "pleaseEnterAValidIqamaID": "يرجى إدخال رقم إقامة صالح", + "pleaseEnterAValidNationalID": "يرجى إدخال رقم هوية وطنية صالح", + "pleaseEnterAValidDateOfBirth": "يرجى إدخال تاريخ ميلاد صالح", + "pleaseEnterAValidName": "يرجى إدخال اسم صالح", + "pleaseSelectAGender": "يرجى اختيار الجنس", + "pleaseSelectAMaritalStatus": "يرجى اختيار الحالة الاجتماعية", + "pleaseSelectACountry": "يرجى اختيار الدولة", + "pleaseEnterEmail": "يرجى إدخال البريد الإلكتروني", + "pleaseEnterAValidEmailFormat": "يرجى إدخال تنسيق بريد إلكتروني صالح" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index b8506f4..b90557e 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -785,7 +785,7 @@ "viewReport": "View Report", "checkAvailability": "Check Availability", "readInstructions": "Read Instructions", - "searchLabReport" : "Search Lab Report", + "searchLabReport": "Search Lab Report", "prescriptionDeliveryError": "This clinic doesn't support refill", "prepareToElevate": "Prepared to elevate your health and well-being?", "iAcceptTermsConditions": "I Accept the Terms and Conditions", @@ -797,7 +797,7 @@ "sendOTPSMS": "Send me OTP on SMS", "fullName": "Full Name", "married": "Married", - "uae" : "United Arab Emirates", + "uae": "United Arab Emirates", "malE": "Male", "loginBy": "Login By", "loginByOTP": "Login By OTP", @@ -806,22 +806,43 @@ "lastloginBy": "Last login by", "allSet": "All Set! Now you can login with Face ID or Biometric", "enableQuickLogin": "Enable Quick Login", - "enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric", - "notNow": "Not Now", + "enableMsg": "Enabling the quick login will verify through your existing device Face ID / Biometric", + "notNow": "Not Now", "pendingActivation": "Pending Activation", "awaitingApproval": "Awaiting Approval", "enterValidNationalId": "Please enter a valid national ID or file number", "enterValidPhoneNumber": "Please enter a valid phone number", "ready": "Ready", - "medicalCentersWithCount" : "{count} Medical Centers", - "medicalCenters" : " Medical Centers", - "hospitalsWithCount" : "{count} Hospitals", + "medicalCentersWithCount": "{count} Medical Centers", + "medicalCenters": " Medical Centers", + "hospitalsWithCount": "{count} Hospitals", "selectRegion": "Select Region", "selectFacility": "Select Facilities", "selectFacilitiesSubTitle": "Please select the facility for the appointment", "selectHospitalSubTitle": "Please select the hospital for the appointment", "news": "News", - "iAcceptThe" : "I Accept the", - "personalDetailsVerification": "Personal Details Verification" + "iAcceptThe": "I Accept the", + "personalDetailsVerification": "Personal Details Verification", + "otpVerification": "OTP Verification", + "weHaveSendOTP": "We have sent you the OTP code on", + "via": "via", + "forRegistrationVerification": "for registration verification", + "didntReceiveIt": "Didn't receive it?", + "resendOTP": "Resend", + "resendIn": "resend in", + "pleaseEnterAnationalID": "Please enter a national ID", + "pleaseEnterAFileNumber": "Please enter a file number", + "pleaseEnterAValidEmail": "Please enter a valid email", + "pleaseEnterFullName": "Please enter full name", + "pleaseAcceptTermsConditions": "Please accept the terms and conditions", + "pleaseEnterAValidIqamaID": "Please enter a valid Iqama ID", + "pleaseEnterAValidNationalID": "Please enter a valid national ID", + "pleaseEnterAValidDateOfBirth": "Please enter a valid date of birth", + "pleaseEnterAValidName": "Please enter a valid name", + "pleaseSelectAGender": "Please select a gender", + "pleaseSelectAMaritalStatus": "Please select a marital status", + "pleaseSelectACountry": "Please select a country", + "pleaseEnterEmail": "Please enter email", + "pleaseEnterAValidEmailFormat": "Please enter a valid email format" } \ No newline at end of file diff --git a/lib/core/enums.dart b/lib/core/enums.dart index 05a6f43..d4eafff 100644 --- a/lib/core/enums.dart +++ b/lib/core/enums.dart @@ -94,7 +94,7 @@ extension LoginTypeExtension on LoginTypeEnum { String get displayName { AppState appState = getIt.get(); - bool isArabic = appState.getLanguageID() == "ar"; + bool isArabic = appState.getLanguageID() == 1 ? true : false; switch (this) { case LoginTypeEnum.sms: return isArabic ? 'رسالة نصية' : 'SMS'; diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart index e180eaa..e335c6b 100644 --- a/lib/core/utils/validation_utils.dart +++ b/lib/core/utils/validation_utils.dart @@ -29,32 +29,32 @@ class ValidationUtils { static bool isValidatedId({String? nationalId, required Function() onOkPress, CountryEnum? selectedCountry, bool? isTermsAccepted, String? dob}) { bool isCorrectID = true; if (nationalId == null || nationalId.isEmpty) { - _dialogService.showExceptionBottomSheet(message: "Please enter a national ID", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAnationalID.tr(), onOkPressed: onOkPress); isCorrectID = false; } if (nationalId != null && nationalId.isNotEmpty && selectedCountry != null) { if (selectedCountry == CountryEnum.saudiArabia) { if (!validateIqama(nationalId)) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid Iqama ID", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidIqamaID.tr(), onOkPressed: onOkPress); return false; } } if (selectedCountry == CountryEnum.unitedArabEmirates) { if (!validateUaeNationalId(nationalId)) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid national ID", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidNationalID.tr(), onOkPressed: onOkPress); return false; } } if (dob == null || dob.isEmpty) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid date of birth", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidDateOfBirth.tr(), onOkPressed: onOkPress); return false; } if (isTermsAccepted != null && !isTermsAccepted) { - _dialogService.showExceptionBottomSheet(message: "Please accept the terms and conditions", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseAcceptTermsConditions.tr(), onOkPressed: onOkPress); return false; } } @@ -63,7 +63,7 @@ class ValidationUtils { static bool isValidatePhone({String? phoneNumber, required Function() onOkPress}) { if (phoneNumber == null || phoneNumber.isEmpty) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid phone number", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.enterValidPhoneNumber.tr(), onOkPressed: onOkPress); return false; } return true; @@ -71,7 +71,7 @@ class ValidationUtils { static bool isValidate({String? phoneNumber, required Function() onOkPress}) { if (phoneNumber == null || phoneNumber.isEmpty) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid phone number", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.enterValidPhoneNumber.tr(), onOkPressed: onOkPress); return false; } return true; @@ -104,22 +104,22 @@ class ValidationUtils { static bool validateUaeRegistration({String? name, GenderTypeEnum? gender, NationalityCountries? country, MaritalStatusTypeEnum? maritalStatus, required Function() onOkPress}) { if (name == null || name.isEmpty) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid name", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidName.tr(), onOkPressed: onOkPress); return false; } if (gender == null) { - _dialogService.showExceptionBottomSheet(message: "Please select a gender", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseSelectAGender.tr(), onOkPressed: onOkPress); return false; } if (maritalStatus == null) { - _dialogService.showExceptionBottomSheet(message: "Please select a marital status", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseSelectAMaritalStatus.tr(), onOkPressed: onOkPress); return false; } if (country == null) { - _dialogService.showExceptionBottomSheet(message: "Please select a country", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseSelectACountry.tr(), onOkPressed: onOkPress); return false; } @@ -128,13 +128,13 @@ class ValidationUtils { static bool isValidateEmail({String? email, required Function() onOkPress}) { if (email == null || email.isEmpty) { - _dialogService.showExceptionBottomSheet(message: "Please enter email", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterEmail.tr(), onOkPressed: onOkPress); return false; } final bool emailIsValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}$").hasMatch(email); if (!emailIsValid) { - _dialogService.showExceptionBottomSheet(message: "Please enter a valid email format", onOkPressed: onOkPress); + _dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidEmailFormat.tr(), onOkPressed: onOkPress); return false; } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 41b604f..02e99f1 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -381,7 +381,7 @@ class FontUtils { /// Get the appropriate font family for a specific language static String getFontFamilyForLanguage(bool isArabic) { - return isArabic ? 'Cairo' : 'Poppins'; + return isArabic ? 'GESSTwo' : 'Poppins'; } } diff --git a/lib/features/authentication/widgets/otp_verification_screen.dart b/lib/features/authentication/widgets/otp_verification_screen.dart index c6f1069..5f8cdf0 100644 --- a/lib/features/authentication/widgets/otp_verification_screen.dart +++ b/lib/features/authentication/widgets/otp_verification_screen.dart @@ -1,15 +1,21 @@ import 'dart:async'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:get_it/get_it.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.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/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/services/cache_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart'; @@ -53,7 +59,8 @@ class OTPWidget extends StatefulWidget { final FocusNode? focusNode; final AnimatedSwitcherTransitionBuilder? pinTextAnimatedSwitcherTransition; final Duration pinTextAnimatedSwitcherDuration; - final TextDirection textDirection; + + // final TextDirection textDirection; final TextInputType keyboardType; final EdgeInsets pinBoxOuterPadding; @@ -74,7 +81,6 @@ class OTPWidget extends StatefulWidget { this.onTextChanged, this.autoFocus = false, this.focusNode, - this.textDirection = TextDirection.ltr, this.keyboardType = TextInputType.number, this.pinBoxOuterPadding = const EdgeInsets.symmetric(horizontal: 4.0), this.pinBoxColor = Colors.white, @@ -182,17 +188,9 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi widget.controller!.clear(); } - // Remove focus from the input if (focusNode.hasFocus) { focusNode.unfocus(); } - - // Optionally refocus after a short delay to allow user to re-enter OTP - Future.delayed(const Duration(milliseconds: 100), () { - if (mounted && widget.autoFocus) { - FocusScope.of(context).requestFocus(focusNode); - } - }); } } @@ -402,58 +400,6 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi ); } - // Widget _buildPinCode(int i, BuildContext context) { - // Color pinBoxColor = widget.pinBoxColor; - // - // if (widget.hasError) { - // pinBoxColor = widget.errorBorderColor; - // } else if (i < text.length) { - // pinBoxColor = AppColors.blackBgColor; // Custom color for filled boxes - // } else { - // pinBoxColor = widget.pinBoxColor; - // } - // - // // Change color to success when all fields are complete - // if (text.length == widget.maxLength) { - // pinBoxColor = AppColors.successColor; - // } - // - // EdgeInsets insets; - // if (i == 0) { - // insets = EdgeInsets.only( - // left: 0, - // top: widget.pinBoxOuterPadding.top, - // right: widget.pinBoxOuterPadding.right, - // bottom: widget.pinBoxOuterPadding.bottom, - // ); - // } else if (i == strList.length - 1) { - // insets = EdgeInsets.only( - // left: widget.pinBoxOuterPadding.left, - // top: widget.pinBoxOuterPadding.top, - // right: 0, - // bottom: widget.pinBoxOuterPadding.bottom, - // ); - // } else { - // insets = widget.pinBoxOuterPadding; - // } - // - // return AnimatedContainer( - // duration: const Duration(milliseconds: 200), - // curve: Curves.easeInOut, - // key: ValueKey("container$i"), - // alignment: Alignment.center, - // padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 1.0), - // margin: insets, - // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - // color: pinBoxColor, - // borderRadius: widget.pinBoxRadius, - // ), - // width: widget.pinBoxWidth, - // height: widget.pinBoxHeight, - // child: _animatedTextBox(strList[i], i), - // ); - // } - Widget _animatedTextBox(String text, int i) { if (widget.pinTextAnimatedSwitcherTransition != null) { return AnimatedSwitcher( @@ -586,6 +532,7 @@ class _OTPVerificationScreenState extends State { @override Widget build(BuildContext context) { + AuthenticationViewModel authVM = context.read(); return Scaffold( backgroundColor: AppColors.scaffoldBgColor, appBar: CustomAppBar( @@ -601,19 +548,22 @@ class _OTPVerificationScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox(height: 40.h), - Text( - 'OTP Verification', - style: TextStyle(fontSize: 24.fSize, fontWeight: FontWeight.bold), - ), - SizedBox(height: 16.h), - Text( - 'We have sent you the OTP code on ${_getMaskedPhoneNumber()} via SMS for registration verification', - style: TextStyle(fontSize: 16.fSize, color: Colors.grey), + SizedBox(height: 10.h), + LocaleKeys.otpVerification.tr().toText24(isBold: true), + SizedBox(height: 20.h), + Wrap( + spacing: 4.h, + runSpacing: 8.0, + children: [ + LocaleKeys.weHaveSendOTP.tr().toText16(color: AppColors.inputLabelTextColor), + _getMaskedPhoneNumber().toText16(color: AppColors.inputLabelTextColor, isBold: true), + LocaleKeys.via.tr().toText16(color: AppColors.inputLabelTextColor), + authVM.loginTypeEnum.displayName.toText16(color: AppColors.inputLabelTextColor), + LocaleKeys.forRegistrationVerification.tr().toText16(color: AppColors.inputLabelTextColor), + ], ), - SizedBox(height: 40.h), - // OTP Input Fields using new OTP Widget + SizedBox(height: 16.h), Center( child: OTPWidget( maxLength: _otpLength, @@ -635,38 +585,32 @@ class _OTPVerificationScreenState extends State { ), ), ), - - const SizedBox(height: 32), + SizedBox(height: 32.h), // Resend OTP Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text("Didn't receive it? "), + LocaleKeys.didntReceiveIt.tr().toText16(color: AppColors.inputLabelTextColor), + SizedBox(width: 5.h), if (_resendTime > 0) Builder( - // Use a Builder to easily calculate minutes and seconds inline builder: (context) { - final minutes = (_resendTime ~/ 60) - .toString() - .padLeft(2, '0'); // Integer division for minutes final seconds = (_resendTime % 60).toString().padLeft(2, '0'); // Modulo for remaining seconds - final seconds = (_resendTime % 60).toString().padLeft(2, '0'); // Modulo for remaining seconds // <--- HERE IT IS - return Text( - 'resend in ($minutes:$seconds). ', - style: const TextStyle(color: Colors.grey), + final minutes = (_resendTime ~/ 60).toString().padLeft(2, '0'); + final seconds = (_resendTime % 60).toString().padLeft(2, '0'); + return Row( + children: [ + LocaleKeys.resendIn.tr().toText16(color: AppColors.inputLabelTextColor), + SizedBox(width: 2.h), + ' ($minutes:$seconds). '.toText16(color: AppColors.inputLabelTextColor) + ], ); }, ) else GestureDetector( onTap: _resendOtp, - child: const Text( - 'Resend', - style: TextStyle( - color: AppColors.primaryRedColor, - fontWeight: FontWeight.bold, - ), - ), + child: LocaleKeys.resendOTP.tr().toText16(color: AppColors.primaryRedColor), ), ], ), @@ -678,7 +622,6 @@ class _OTPVerificationScreenState extends State { } void _verifyOtp(String otp) { - debugPrint('Verifying OTP: $otp'); widget.checkActivationCode(int.parse(otp)); } @@ -689,6 +632,6 @@ class _OTPVerificationScreenState extends State { _isVerifying = false; _otpController.text = otp; setState(() {}); - _onOtpChanged(otp); // Ensure verification and color update + _onOtpChanged(otp); } } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 85c4d6d..6445de8 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -825,5 +825,26 @@ abstract class LocaleKeys { static const selectHospitalSubTitle = 'selectHospitalSubTitle'; static const iAcceptThe = 'iAcceptThe'; static const personalDetailsVerification = 'personalDetailsVerification'; + static const otpVerification = 'otpVerification'; + static const weHaveSendOTP = 'weHaveSendOTP'; + static const via = 'via'; + static const forRegistrationVerification = 'forRegistrationVerification'; + static const didntReceiveIt = 'didntReceiveIt'; + static const resendOTP = 'resendOTP'; + static const resendIn = 'resendIn'; + static const pleaseEnterAnationalID = 'pleaseEnterAnationalID'; + static const pleaseEnterAFileNumber = 'pleaseEnterAFileNumber'; + static const pleaseEnterAValidEmail = 'pleaseEnterAValidEmail'; + static const pleaseEnterFullName = 'pleaseEnterFullName'; + static const pleaseAcceptTermsConditions = 'pleaseAcceptTermsConditions'; + static const pleaseEnterAValidIqamaID = 'pleaseEnterAValidIqamaID'; + static const pleaseEnterAValidNationalID = 'pleaseEnterAValidNationalID'; + static const pleaseEnterAValidDateOfBirth = 'pleaseEnterAValidDateOfBirth'; + static const pleaseEnterAValidName = 'pleaseEnterAValidName'; + static const pleaseSelectAGender = 'pleaseSelectAGender'; + static const pleaseSelectAMaritalStatus = 'pleaseSelectAMaritalStatus'; + static const pleaseSelectACountry = 'pleaseSelectACountry'; + static const pleaseEnterEmail = 'pleaseEnterEmail'; + static const pleaseEnterAValidEmailFormat = 'pleaseEnterAValidEmailFormat'; } diff --git a/lib/presentation/authentication/register.dart b/lib/presentation/authentication/register.dart index 5150b0c..df1c8c7 100644 --- a/lib/presentation/authentication/register.dart +++ b/lib/presentation/authentication/register.dart @@ -93,7 +93,7 @@ class _RegisterNew extends State { CustomCountryDropdown( countryList: CountryEnum.values, onCountryChange: authVm.onCountryChange, - isRtl: Directionality.of(context) == TextDirection.LTR, + // isRtl: Directionality.of(context) == TextDirection.LTR, ).withVerticalPadding(8.h), Divider(height: 1.h), TextInputWidget( @@ -189,7 +189,7 @@ class _RegisterNew extends State { ), SizedBox(height: 25.h), CustomButton( - text: "Register", + text: LocaleKeys.registernow.tr(), icon: AppAssets.note_edit, onPressed: () { // Dismiss keyboard before proceeding diff --git a/lib/presentation/authentication/register_step2.dart b/lib/presentation/authentication/register_step2.dart index 23ea7ae..8dbe8e8 100644 --- a/lib/presentation/authentication/register_step2.dart +++ b/lib/presentation/authentication/register_step2.dart @@ -43,6 +43,9 @@ class _RegisterNew extends State { @override Widget build(BuildContext context) { AppState appState = getIt.get(); + var name = appState.getLanguageCode() == "en" + ? ("${appState.getNHICUserData.firstNameEn!.toUpperCase()} ${appState.getNHICUserData.lastNameEn!.toUpperCase()}") + : ("${appState.getNHICUserData.firstNameAr!.toUpperCase()} ${appState.getNHICUserData.lastNameAr!.toUpperCase()}"); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, appBar: CustomAppBar( @@ -71,8 +74,7 @@ class _RegisterNew extends State { children: [ TextInputWidget( labelText: authVM!.isUserFromUAE() ? LocaleKeys.fullName.tr() : LocaleKeys.name.tr(), - hintText: - authVM!.isUserFromUAE() ? LocaleKeys.enterNameHere.tr() : ("${appState.getNHICUserData.firstNameEn!.toUpperCase()} ${appState.getNHICUserData.lastNameEn!.toUpperCase()}"), + hintText: authVM!.isUserFromUAE() ? LocaleKeys.enterNameHere.tr() : (name), controller: authVM!.isUserFromUAE() ? authVM!.nameController : null, isEnable: true, prefix: null, @@ -332,7 +334,7 @@ class _RegisterNew extends State { Padding( padding: const EdgeInsets.only(bottom: 10), child: CustomButton( - text: LocaleKeys.submit, + text: LocaleKeys.submit.tr(), onPressed: () { if (ValidationUtils.isValidateEmail( email: authVM!.emailController.text, diff --git a/lib/widgets/appbar/app_bar_widget.dart b/lib/widgets/appbar/app_bar_widget.dart index 1b6b8f1..b446f90 100644 --- a/lib/widgets/appbar/app_bar_widget.dart +++ b/lib/widgets/appbar/app_bar_widget.dart @@ -39,7 +39,12 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { alignment: context.locale.languageCode == "ar" ? Alignment.centerRight : Alignment.centerLeft, child: GestureDetector( onTap: onBackPressed, - child: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 32.h, height: 32.h), + child: context.locale.languageCode == "ar" + ? RotatedBox( + quarterTurns: 90, + child: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 32.h, height: 32.h), + ) + : Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 32.h, height: 32.h), ), ), ), diff --git a/lib/widgets/bottomsheet/generic_bottom_sheet.dart b/lib/widgets/bottomsheet/generic_bottom_sheet.dart index 03145c8..05275fa 100644 --- a/lib/widgets/bottomsheet/generic_bottom_sheet.dart +++ b/lib/widgets/bottomsheet/generic_bottom_sheet.dart @@ -78,7 +78,6 @@ class _GenericBottomSheetState extends State { bottom: Platform.isIOS ? false : true, child: GestureDetector( onTap: () { - // Dismiss keyboard and unfocus text field _textFieldFocusNode.unfocus(); FocusScope.of(context).unfocus(); }, @@ -130,7 +129,7 @@ class _GenericBottomSheetState extends State { else ...[ widget.textController != null ? TextInputWidget( - labelText: widget.isForEmail ? LocaleKeys.email : LocaleKeys.phoneNumber, + labelText: widget.isForEmail ? LocaleKeys.email.tr() : LocaleKeys.phoneNumber.tr(), hintText: widget.isForEmail ? "demo@gmail.com" : "5xxxxxxxx", controller: widget.textController!, focusNode: _textFieldFocusNode, diff --git a/lib/widgets/dropdown/country_dropdown_widget.dart b/lib/widgets/dropdown/country_dropdown_widget.dart index dd45df4..772bf39 100644 --- a/lib/widgets/dropdown/country_dropdown_widget.dart +++ b/lib/widgets/dropdown/country_dropdown_widget.dart @@ -14,7 +14,6 @@ class CustomCountryDropdown extends StatefulWidget { final List countryList; final Function(CountryEnum)? onCountryChange; final Function(String)? onPhoneNumberChanged; - final bool isRtl; final bool isFromBottomSheet; final bool isEnableTextField; Widget? textField; @@ -24,7 +23,6 @@ class CustomCountryDropdown extends StatefulWidget { required this.countryList, this.onCountryChange, this.onPhoneNumberChanged, - required this.isRtl, this.isFromBottomSheet = false, this.isEnableTextField = false, this.textField, @@ -147,11 +145,23 @@ class _CustomCountryDropdownState extends State { void _openDropdown() { if (textFocusNode.hasFocus) { textFocusNode.unfocus(); + // Wait for keyboard to close before calculating position + Future.delayed(Duration(milliseconds: 300), () { + _showDropdown(); + }); + } else { + _showDropdown(); } + } + + void _showDropdown() { AppState appState = getIt.get(); RenderBox renderBox = context.findRenderObject() as RenderBox; Offset offset = renderBox.localToGlobal(Offset.zero); + bool isRtl = appState.getLanguageCode() == "ar"; + double leftPosition = isRtl ? offset.dx + 8 + renderBox.size.width - (!widget.isFromBottomSheet ? renderBox.size.width : 60.h) : offset.dx; + _overlayEntry = OverlayEntry( builder: (context) => Stack( children: [ @@ -164,7 +174,7 @@ class _CustomCountryDropdownState extends State { ), Positioned( top: offset.dy + renderBox.size.height, - left: widget.isRtl ? offset.dx + 6.h : offset.dx - 6.h, + left: leftPosition, width: !widget.isFromBottomSheet ? renderBox.size.width : 60.h, child: Material( child: Container( @@ -209,6 +219,71 @@ class _CustomCountryDropdownState extends State { }); } + // void _openDropdown() { + // if (textFocusNode.hasFocus) { + // textFocusNode.unfocus(); + // } + // AppState appState = getIt.get(); + // RenderBox renderBox = context.findRenderObject() as RenderBox; + // Offset offset = renderBox.localToGlobal(Offset.zero); + // + // _overlayEntry = OverlayEntry( + // builder: (context) => Stack( + // children: [ + // Positioned.fill( + // child: GestureDetector( + // onTap: _closeDropdown, + // behavior: HitTestBehavior.translucent, + // child: Container(), + // ), + // ), + // Positioned( + // top: offset.dy + renderBox.size.height, + // left: offset.dx, + // width: !widget.isFromBottomSheet ? renderBox.size.width : 60.h, + // child: Material( + // child: Container( + // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: Colors.white, borderRadius: 12), + // child: Column( + // children: widget.countryList + // .map( + // (country) => GestureDetector( + // onTap: () { + // setState(() { + // selectedCountry = country; + // }); + // widget.onCountryChange?.call(country); + // _closeDropdown(); + // }, + // child: Container( + // padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h), + // decoration: RoundedRectangleBorder().toSmoothCornerDecoration(borderRadius: 16.h), + // child: Row( + // children: [ + // Utils.buildSvgWithAssets(icon: country.iconPath, width: 38.h, height: 38.h), + // if (!widget.isFromBottomSheet) SizedBox(width: 12.h), + // if (!widget.isFromBottomSheet) + // Text(appState.getLanguageCode() == "ar" ? country.nameArabic : country.displayName, + // style: TextStyle(fontSize: 14.fSize, height: 21 / 14, fontWeight: FontWeight.w500, letterSpacing: -0.2)), + // ], + // ), + // )), + // ) + // .toList(), + // ), + // ), + // ), + // ), + // ], + // ), + // ); + // + // Overlay.of(context)?.insert(_overlayEntry); + // setState(() { + // _isDropdownOpen = true; + // }); + // } + void _closeDropdown() { _overlayEntry.remove(); setState(() { diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart index fa2d873..a527054 100644 --- a/lib/widgets/input_widget.dart +++ b/lib/widgets/input_widget.dart @@ -126,7 +126,6 @@ class TextInputWidget extends StatelessWidget { ? CustomCountryDropdown( countryList: CountryEnum.values, onCountryChange: onCountryChange, - isRtl: Directionality.of(context) == TextDirection.rtl, isFromBottomSheet: isCountryDropDown, isEnableTextField: true, onPhoneNumberChanged: onChange, @@ -191,6 +190,7 @@ class TextInputWidget extends StatelessWidget { switcherIcon: Utils.buildSvgWithAssets(icon: AppAssets.language, width: 24.h, height: 24.h), language: appState.getLanguageCode()!, initialDate: DateTime.now(), + fontFamily: appState.getLanguageCode() == "ar" ? "GESSTwo" : "Poppins", okWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.confirm, width: 24.h, height: 24.h)), cancelWidget: Padding(padding: EdgeInsets.only(right: 8.h), child: Utils.buildSvgWithAssets(icon: AppAssets.cancel, iconColor: Colors.white, width: 24.h, height: 24.h)), onCalendarTypeChanged: (bool value) { -- 2.30.2