otp screen & register Uae & resend Activation Code.

pull/45/head
aamir-csol 1 month ago
parent 3ddd7781cd
commit 2b7656d83a

@ -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": "يرجى إدخال تنسيق بريد إلكتروني صالح"
}

@ -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",
@ -813,15 +813,36 @@
"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"
}

@ -94,7 +94,7 @@ extension LoginTypeExtension on LoginTypeEnum {
String get displayName {
AppState appState = getIt.get<AppState>();
bool isArabic = appState.getLanguageID() == "ar";
bool isArabic = appState.getLanguageID() == 1 ? true : false;
switch (this) {
case LoginTypeEnum.sms:
return isArabic ? 'رسالة نصية' : 'SMS';

@ -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;
}

@ -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';
}
}

@ -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<OTPWidget> 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<OTPWidget> 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<String>("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<OTPVerificationScreen> {
@override
Widget build(BuildContext context) {
AuthenticationViewModel authVM = context.read<AuthenticationViewModel>();
return Scaffold(
backgroundColor: AppColors.scaffoldBgColor,
appBar: CustomAppBar(
@ -601,19 +548,22 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
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<OTPVerificationScreen> {
),
),
),
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<OTPVerificationScreen> {
}
void _verifyOtp(String otp) {
debugPrint('Verifying OTP: $otp');
widget.checkActivationCode(int.parse(otp));
}
@ -689,6 +632,6 @@ class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
_isVerifying = false;
_otpController.text = otp;
setState(() {});
_onOtpChanged(otp); // Ensure verification and color update
_onOtpChanged(otp);
}
}

@ -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';
}

@ -93,7 +93,7 @@ class _RegisterNew extends State<RegisterNew> {
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<RegisterNew> {
),
SizedBox(height: 25.h),
CustomButton(
text: "Register",
text: LocaleKeys.registernow.tr(),
icon: AppAssets.note_edit,
onPressed: () {
// Dismiss keyboard before proceeding

@ -43,6 +43,9 @@ class _RegisterNew extends State<RegisterNewStep2> {
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
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<RegisterNewStep2> {
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<RegisterNewStep2> {
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: CustomButton(
text: LocaleKeys.submit,
text: LocaleKeys.submit.tr(),
onPressed: () {
if (ValidationUtils.isValidateEmail(
email: authVM!.emailController.text,

@ -39,7 +39,12 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
alignment: context.locale.languageCode == "ar" ? Alignment.centerRight : Alignment.centerLeft,
child: GestureDetector(
onTap: onBackPressed,
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),
),
),
),

@ -78,7 +78,6 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
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<GenericBottomSheet> {
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,

@ -14,7 +14,6 @@ class CustomCountryDropdown extends StatefulWidget {
final List<CountryEnum> 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<CustomCountryDropdown> {
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<AppState>();
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<CustomCountryDropdown> {
),
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<CustomCountryDropdown> {
});
}
// void _openDropdown() {
// if (textFocusNode.hasFocus) {
// textFocusNode.unfocus();
// }
// AppState appState = getIt.get<AppState>();
// 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(() {

@ -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) {

Loading…
Cancel
Save