From c666ba219c418a86117c3043106c050a55ca3535 Mon Sep 17 00:00:00 2001 From: Aamir Muhammad Date: Mon, 11 Aug 2025 16:36:18 +0300 Subject: [PATCH] changes --- lib/config/config.dart | 4 +- lib/config/localized_values.dart | 4 +- .../ExceptionBottomSheet.dart | 2 +- .../otp/otp_validation_bootmsheet_widget.dart | 139 +- .../health_calculator/carbs/carbs.dart | 1579 ++++++++++++----- lib/pages/login/register_new.dart | 89 +- lib/pages/login/saved_login.dart | 234 ++- lib/pages/login/welcome.dart | 13 - lib/uitl/translations_delegate_base.dart | 2 + lib/widgets/otp/sms-popup.dart | 2 +- lib/widgets/otp_widget.dart | 61 +- pubspec.yaml | 6 +- 12 files changed, 1477 insertions(+), 658 deletions(-) diff --git a/lib/config/config.dart b/lib/config/config.dart index fb64f682..e425c27d 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -21,8 +21,8 @@ var PACKAGES_ORDERS = '/api/orders'; var PACKAGES_ORDER_HISTORY = '/api/orders/items'; var PACKAGES_TAMARA_OPT = '/api/orders/paymentoptions/tamara'; // var BASE_URL = 'http://10.50.100.198:2018/'; - // var BASE_URL = 'https://uat.hmgwebservices.com/'; -var BASE_URL = 'https://hmgwebservices.com/'; + var BASE_URL = 'https://uat.hmgwebservices.com/'; +// var BASE_URL = 'https://hmgwebservices.com/'; // var BASE_URL = 'http://10.201.204.103/'; // var BASE_URL = 'https://orash.cloudsolutions.com.sa/'; // var BASE_URL = 'https://vidauat.cloudsolutions.com.sa/'; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 0ed4b76f..90384560 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -2329,7 +2329,7 @@ const Map localizedValues = { "clickPrivacyPolicy": {"en": "Please click here to view the privacy policy", "ar": "الرجاء الضغط هنا لعرض سياسة الخصوصية"}, "welcomeToDrSulaiman": {"en": "Welcome to Dr. Sulaiman Al Habib Medical Group", "ar": "مرحباً بكم في مجموعة الدكتور سليمان الحبيب الطبية"}, "dontHaveAccount": {"en": "Don’t have an account?", "ar": "ليس لديك حساب؟"}, - "loginByOTP": {"en": "Login By SMS", "ar":" تسجيل الدخول بواسطة الرسائل القصيرة"}, + "loginByOTP": {"en": "Login By OTP", "ar":"تسجيل الدخول بواسطة OTP"}, "loginBy": {"en": "Login By", "ar":"تسجيل الدخول بواسطة"}, "prepareToElevate": {"en": "Prepared to elevate your health and well-being?", "ar": "هل أنت مستعد لتحسين صحتك ورفاهتك؟"}, "alreadyHaveAccount": {"en": "Already have an account?", "ar": "هل لديك حساب بالفعل؟"}, @@ -2363,6 +2363,8 @@ const Map localizedValues = { "otpVerification": {"en": "OTP Verification", "ar":"التحقق من OTP"}, "submiT": {"en": "Submit", "ar":"إرسال"}, "notice": {"en": "Notice", "ar":"إشعار"}, + "receiveOtpToast": {"en": "Where would you like to receive OTP?", "ar":"أين تود تلقي رمز التحقق OTP؟"}, + "pleaseChooseOption": {"en": "Please select from the below options to receive OTP.", "ar":"الرجاء اختيار من الخيارات أدناه لتلقي رمز التحقق OTP."}, diff --git a/lib/new_ui/exception_widget/ExceptionBottomSheet.dart b/lib/new_ui/exception_widget/ExceptionBottomSheet.dart index d44fc55c..635cee27 100644 --- a/lib/new_ui/exception_widget/ExceptionBottomSheet.dart +++ b/lib/new_ui/exception_widget/ExceptionBottomSheet.dart @@ -93,7 +93,7 @@ class _ExceptionBottomSheetState extends State { ), Expanded( child: CustomButton( - text: TranslationBase.of(context).ok, + text: widget.showCancel ? TranslationBase.of(context).confirm : TranslationBase.of(context).ok, onPressed: widget.onOkPressed, backgroundColor: CustomColors.bgRedColor, borderColor: CustomColors.bgRedBorderColor, diff --git a/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart b/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart index 5cd2bc4a..45331cd9 100644 --- a/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart +++ b/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart @@ -19,11 +19,9 @@ class GenericBottomSheet extends StatefulWidget { final bool isEnableCountryDropdown; final bool isFromSavedLogin; Function(String?)? onChange; - FocusNode? focusNode; GenericBottomSheet( - {Key? key, - this.countryCode = "", + {this.countryCode = "", this.initialPhoneNumber = "", required this.buttons, this.textController, @@ -31,9 +29,7 @@ class GenericBottomSheet extends StatefulWidget { this.onCountryChange, this.isEnableCountryDropdown = false, this.isFromSavedLogin = false, - this.focusNode, - this.onChange}) - : super(key: key); + this.onChange}); @override _GenericBottomSheetState createState() => _GenericBottomSheetState(); @@ -64,50 +60,102 @@ class _GenericBottomSheetState extends State { // Only unfocus if the tap is not on the text field area FocusScope.of(context).unfocus(); }, - child: Builder(builder: (context) { - // final isRtl = Directionality.of(context) == TextDirection.rtl; - return Directionality( - textDirection: Directionality.of(context), - child: Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: Color(0xFFF8F8FA), - borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // Title - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AppText(widget.isForEmail ? TranslationBase.of(context).enterEmail : TranslationBase.of(context).enterPhoneNumber, - fontSize: 28, letterSpacing: -2, color: Color(0xFF2E3039), fontWeight: FontWeight.w600), - InkWell( - onTap: () { - Navigator.of(context).pop(); - }, - child: SvgPicture.asset("assets/images/svg/cross-circle.svg", width: 24, height: 24)), - ], - ), - const SizedBox(height: 10), - // Subtitle - AppText(widget.isForEmail ? TranslationBase.of(context).enterEmailDesc : TranslationBase.of(context).enterPhoneDesc, - fontSize: 16, color: Color(0xFF2E3039), fontWeight: FontWeight.w500), - const SizedBox(height: 10), + child: Directionality( + textDirection: Directionality.of(context), + child: Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: Color(0xFFF8F8FA), + borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Title + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: AppText( + widget.isFromSavedLogin + ? TranslationBase.of(context).receiveOtpToast + : widget.isForEmail + ? TranslationBase.of(context).enterEmail + : TranslationBase.of(context).enterPhoneNumber, + fontSize: 28, + letterSpacing: -2, + color: Color(0xFF2E3039), + fontWeight: FontWeight.w600), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Padding( + padding: const EdgeInsets.only(top: 10), + child: SvgPicture.asset("assets/images/svg/cross-circle.svg", width: 24, height: 24), + )), + ], + ), + const SizedBox(height: 10), + // Subtitle + AppText( + widget.isFromSavedLogin + ? TranslationBase.of(context).pleaseChooseOption + : widget.isForEmail + ? TranslationBase.of(context).enterEmailDesc + : TranslationBase.of(context).enterPhoneDesc, + fontSize: 16, + color: Color(0xFF2E3039), + fontWeight: FontWeight.w500), + const SizedBox(height: 10), + + if (widget.isFromSavedLogin) + ...[] + else ...[ widget.textController != null ? Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + // Directionality( + // textDirection: TextDirection.ltr, + // child: newInputWidget( + // labelText: widget.isForEmail ? TranslationBase.of(context).email : TranslationBase.of(context).phoneNumber, + // hintText: widget.isForEmail ? "demo@gmail.com" : "5xxxxxxxx", + // controller: widget.textController, + // padding: const EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8), + // keyboardType: widget.isForEmail ? TextInputType.emailAddress : TextInputType.number, + // onChange: (value) { + // if (value != null) { + // widget.textController?.text = value; + // widget.onChange?.call(value); + // } + // }, + // isEnable: true, + // autoFocus: true, + // keepFocus: true, + // refocusOnChange: true, + // isReadOnly: widget.isFromSavedLogin, + // prefix: widget.isForEmail ? null : widget.countryCode, + // hasSelection: false, + // isBorderAllowed: false, + // isAllowLeadingIcon: true, + // countryList: Country.values, + // isCountryDropDown: widget.isEnableCountryDropdown, + // onCountryChange: widget.onCountryChange, + // leadingIcon: widget.isForEmail ? "assets/images/svg/email.svg" : "assets/images/svg/smart-phone.svg", + // ), + // ), Directionality( textDirection: TextDirection.ltr, child: newInputWidget( widget.isForEmail ? TranslationBase.of(context).email : TranslationBase.of(context).phoneNumber, widget.isForEmail ? "demo@gmail.com" : "5xxxxxxxx", widget.textController!, - focusNode: widget.focusNode!, + // focusNode: widget.focusNode!, padding: EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8), keyboardType: widget.isForEmail ? TextInputType.emailAddress : TextInputType.number, onChange: (value) { @@ -134,13 +182,14 @@ class _GenericBottomSheetState extends State { ], ) : SizedBox(), - SizedBox(height: 24), - ...widget.buttons, ], - ), + + SizedBox(height: 24), + ...widget.buttons, + ], ), - ); - }), + ), + ), ), ); } diff --git a/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart b/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart index 18f17591..d13aebd9 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart @@ -42,27 +42,37 @@ class _CarbsState extends State { double? fCalMeal; void calculateDietRatios() { - if (dropdownValue == TranslationBase.of(context).dietVeryLow) { + if (dropdownValue == TranslationBase + .of(context) + .dietVeryLow) { meals = 3; protein = 45; carbs = 10; fat = 45; - } else if (dropdownValue == TranslationBase.of(context).dietLow) { + } else if (dropdownValue == TranslationBase + .of(context) + .dietLow) { meals = 3; protein = 40; carbs = 30; fat = 30; - } else if (dropdownValue == TranslationBase.of(context).dietModerate) { + } else if (dropdownValue == TranslationBase + .of(context) + .dietModerate) { meals = 3; protein = 25; carbs = 50; fat = 25; - } else if (dropdownValue == TranslationBase.of(context).dietUSDA) { + } else if (dropdownValue == TranslationBase + .of(context) + .dietUSDA) { meals = 3; protein = 15; carbs = 55; fat = 30; - } else if (dropdownValue == TranslationBase.of(context).dietZone) { + } else if (dropdownValue == TranslationBase + .of(context) + .dietZone) { meals = 3; protein = 30; carbs = 40; @@ -88,13 +98,17 @@ class _CarbsState extends State { Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); - dropdownValue = TranslationBase.of(context).dietVeryLow; + dropdownValue = TranslationBase + .of(context) + .dietVeryLow; return AppScaffold( isShowAppBar: true, isShowDecPage: false, showNewAppBarTitle: true, showNewAppBar: true, - appBarTitle: TranslationBase.of(context).carbohydrate, + appBarTitle: TranslationBase + .of(context) + .carbohydrate, appBarIcons: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 7.0), @@ -114,7 +128,9 @@ class _CarbsState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - TranslationBase.of(context).carbProteinDesc, + TranslationBase + .of(context) + .carbProteinDesc, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -129,7 +145,9 @@ class _CarbsState extends State { mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ - inputWidget(TranslationBase.of(context).calDay, "0", textController), + inputWidget(TranslationBase + .of(context) + .calDay, "0", textController), InkWell( onTap: () { Navigator.push( @@ -140,8 +158,14 @@ class _CarbsState extends State { child: Padding( padding: const EdgeInsets.all(12.0), child: Text( - TranslationBase.of(context).notSure, - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, letterSpacing: -0.56, color: CustomColors.accentColor, decoration: TextDecoration.underline), + TranslationBase + .of(context) + .notSure, + style: TextStyle(fontSize: 12, + fontWeight: FontWeight.w600, + letterSpacing: -0.56, + color: CustomColors.accentColor, + decoration: TextDecoration.underline), ), ), ) @@ -166,7 +190,9 @@ class _CarbsState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - TranslationBase.of(context).selectDiet, + TranslationBase + .of(context) + .selectDiet, style: TextStyle( fontSize: 11, letterSpacing: -0.44, @@ -195,11 +221,21 @@ class _CarbsState extends State { }); }, items: [ - TranslationBase.of(context).dietVeryLow, - TranslationBase.of(context).dietLow, - TranslationBase.of(context).dietModerate, - TranslationBase.of(context).dietUSDA, - TranslationBase.of(context).dietZone + TranslationBase + .of(context) + .dietVeryLow, + TranslationBase + .of(context) + .dietLow, + TranslationBase + .of(context) + .dietModerate, + TranslationBase + .of(context) + .dietUSDA, + TranslationBase + .of(context) + .dietZone ].map>((String value) { return DropdownMenuItem( value: value, @@ -233,7 +269,9 @@ class _CarbsState extends State { margin: EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), color: Colors.white, child: SecondaryButton( - label: TranslationBase.of(context).calculate, + label: TranslationBase + .of(context) + .calculate, color: CustomColors.accentColor, onTap: () { setState(() { @@ -243,16 +281,16 @@ class _CarbsState extends State { context, FadePage( page: CarbsResult( - cCal: cCal!, - pCal: pCal!, - fCal: fCal!, - pCalGram: pCalGram!, - pCalMeal: pCalMeal!, - fCalGram: fCalGram!, - fCalMeal: fCalMeal!, - cCalGram: cCalGram!, - cCalMeal: cCalMeal!, - )), + cCal: cCal!, + pCal: pCal!, + fCal: fCal!, + pCalGram: pCalGram!, + pCalMeal: pCalMeal!, + fCalGram: fCalGram!, + fCalMeal: fCalMeal!, + cCalGram: cCalGram!, + cCalMeal: cCalMeal!, + )), ); } }); @@ -308,31 +346,30 @@ class _CarbsState extends State { // } } -Widget inputWidget( - String _labelText, - String _hintText, - TextEditingController? _controller, { - Function(String?)? onChange, - String? prefix, - bool isEnable = true, - bool hasSelection = false, - bool hasSelectionCustomIcon = false, - String? selectionCustomIcon, - bool isBorderAllowed = true, - bool isAllowLeadingIcon = false, - bool isLeadingCountry = false, - String? leadingIcon, - bool removePadding = false, - bool isAllowRadius = true, - bool isReadOnly = false, - TextInputType keyboardType = TextInputType.number, - List? dropdownItems, - String? selectedValue, - SelectionType? selectionType, - Function(bool)? onCalendarTypeChanged, - EdgeInsetsGeometry? padding, - String lang = 'en', -}) { +Widget inputWidget(String _labelText, + String _hintText, + TextEditingController? _controller, { + Function(String?)? onChange, + String? prefix, + bool isEnable = true, + bool hasSelection = false, + bool hasSelectionCustomIcon = false, + String? selectionCustomIcon, + bool isBorderAllowed = true, + bool isAllowLeadingIcon = false, + bool isLeadingCountry = false, + String? leadingIcon, + bool removePadding = false, + bool isAllowRadius = true, + bool isReadOnly = false, + TextInputType keyboardType = TextInputType.number, + List? dropdownItems, + String? selectedValue, + SelectionType? selectionType, + Function(bool)? onCalendarTypeChanged, + EdgeInsetsGeometry? padding, + String lang = 'en', + }) { return Builder( builder: (context) { final isRtl = Directionality.of(context) == TextDirection.rtl; @@ -343,8 +380,8 @@ Widget inputWidget( padding: padding != null ? padding : removePadding - ? const EdgeInsets.only(top: 16, bottom: 16) - : const EdgeInsets.symmetric(horizontal: 16, vertical: 15), + ? const EdgeInsets.only(top: 16, bottom: 16) + : const EdgeInsets.symmetric(horizontal: 16, vertical: 15), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: isAllowRadius ? BorderRadius.circular(15) : null, @@ -382,177 +419,176 @@ Widget inputWidget( letterSpacing: -0.2, height: 18 / 12, ) - // style: TextStyle( - // fontSize: 12, - // fontWeight: FontWeight.w500, - // color: const Color(0xff898A8D), - // // fontFamily: FontUtils.getFontFamily(context), - // letterSpacing: -0.2, - // height: 18 / 12, - // ), - ), + // style: TextStyle( + // fontSize: 12, + // fontWeight: FontWeight.w500, + // color: const Color(0xff898A8D), + // // fontFamily: FontUtils.getFontFamily(context), + // letterSpacing: -0.2, + // height: 18 / 12, + // ), + ), ), hasSelection ? GestureDetector( - onTap: isEnable && !isReadOnly - ? () async { - if (selectionType == SelectionType.dropdown) { - final renderBox = context.findRenderObject() as RenderBox; - final offset = renderBox.localToGlobal(Offset.zero); - final selected = await showMenu( - context: context, - position: RelativeRect.fromLTRB( - offset.dx, - offset.dy + renderBox.size.height, - offset.dx + renderBox.size.width, - 0, - ), - items: dropdownItems - ?.map( - (e) => PopupMenuItem( - value: e, - child: Text(e), - ), - ) - .toList() ?? - [], - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ); - - if (selected != null && onChange != null) { - onChange(selected); - } - } else if (selectionType == SelectionType.calendar) { - bool isGregorian = true; - // final picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1900), lastDate: DateTime(2100)); - final picked = await showHijriGregBottomSheet( - context, - switcherIcon: SvgPicture.asset("assets/images/svg/language.svg", width: 24), - // fontFamily: FontUtils.getFontFamily(context), - language: lang, - initialDate: DateTime.now(), - okWidget: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: SvgPicture.asset( - "assets/images/svg/confirm.svg", - width: 24, - height: 24, - ), - ), - cancelWidget: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: SvgPicture.asset( - "assets/images/svg/cancel.svg", - colorFilter: ColorFilter.mode( - Colors.white, - BlendMode.srcIn, - ), - width: 24, - height: 24, - ), - ), - onCalendarTypeChanged: (bool value) { - isGregorian = value; - }, - ); - if (picked != null && onChange != null) { - print(picked.toIso8601String()); - if (onCalendarTypeChanged != null) { - print(isGregorian.toString()); - onCalendarTypeChanged.call(isGregorian); - } - onChange(picked.toIso8601String()); - } - } - } - : null, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text((selectedValue == null || selectedValue.isEmpty) ? _hintText : selectedValue, - textAlign: isRtl ? TextAlign.right : TextAlign.left, - textDirection: isRtl ? TextDirection.rtl : TextDirection.ltr, - style: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 14, - fontWeight: FontWeight.w500, - // fontFamily: FontUtils.getFontFamily(context), - color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), - letterSpacing: -0.2, - ) - // style: TextStyle( - // fontSize: 14, - // height: 21 / 14, - // fontWeight: FontWeight.w500, - // // fontFamily: FontUtils.getFontFamily(context), - // color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), - // letterSpacing: -0.2, - // ), - ), + onTap: isEnable && !isReadOnly + ? () async { + if (selectionType == SelectionType.dropdown) { + final renderBox = context.findRenderObject() as RenderBox; + final offset = renderBox.localToGlobal(Offset.zero); + final selected = await showMenu( + context: context, + position: RelativeRect.fromLTRB( + offset.dx, + offset.dy + renderBox.size.height, + offset.dx + renderBox.size.width, + 0, + ), + items: dropdownItems + ?.map( + (e) => + PopupMenuItem( + value: e, + child: Text(e), + ), + ) + .toList() ?? + [], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ); + + if (selected != null && onChange != null) { + onChange(selected); + } + } else if (selectionType == SelectionType.calendar) { + bool isGregorian = true; + // final picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1900), lastDate: DateTime(2100)); + final picked = await showHijriGregBottomSheet( + context, + switcherIcon: SvgPicture.asset("assets/images/svg/language.svg", width: 24), + // fontFamily: FontUtils.getFontFamily(context), + language: lang, + initialDate: DateTime.now(), + okWidget: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SvgPicture.asset( + "assets/images/svg/confirm.svg", + width: 24, + height: 24, + ), + ), + cancelWidget: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SvgPicture.asset( + "assets/images/svg/cancel.svg", + colorFilter: ColorFilter.mode( + Colors.white, + BlendMode.srcIn, ), - if (hasSelectionCustomIcon && selectionCustomIcon != null) - SvgPicture.asset(selectionCustomIcon, width: 24, height: 24) - else - const Icon(Icons.keyboard_arrow_down_outlined), - ], + width: 24, + height: 24, + ), ), - ) + onCalendarTypeChanged: (bool value) { + isGregorian = value; + }, + ); + if (picked != null && onChange != null) { + if (onCalendarTypeChanged != null) { + onCalendarTypeChanged.call(isGregorian); + } + onChange(picked.toIso8601String()); + } + } + } + : null, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text((selectedValue == null || selectedValue.isEmpty) ? _hintText : selectedValue, + textAlign: isRtl ? TextAlign.right : TextAlign.left, + textDirection: isRtl ? TextDirection.rtl : TextDirection.ltr, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + // fontFamily: FontUtils.getFontFamily(context), + color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), + letterSpacing: -0.2, + ) + // style: TextStyle( + // fontSize: 14, + // height: 21 / 14, + // fontWeight: FontWeight.w500, + // // fontFamily: FontUtils.getFontFamily(context), + // color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), + // letterSpacing: -0.2, + // ), + ), + ), + if (hasSelectionCustomIcon && selectionCustomIcon != null) + SvgPicture.asset(selectionCustomIcon, width: 24, height: 24) + else + const Icon(Icons.keyboard_arrow_down_outlined), + ], + ), + ) : TextField( - enabled: isEnable, - scrollPadding: EdgeInsets.zero, - keyboardType: keyboardType, - controller: _controller, - readOnly: isReadOnly, - textAlignVertical: TextAlignVertical.top, - textAlign: isRtl ? TextAlign.right : TextAlign.left, - textDirection: isRtl ? TextDirection.rtl : TextDirection.ltr, - onChanged: onChange, + enabled: isEnable, + scrollPadding: EdgeInsets.zero, + keyboardType: keyboardType, + controller: _controller, + readOnly: isReadOnly, + textAlignVertical: TextAlignVertical.top, + textAlign: isRtl ? TextAlign.right : TextAlign.left, + textDirection: isRtl ? TextDirection.rtl : TextDirection.ltr, + onChanged: onChange, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: const Color(0xff2E3039), + letterSpacing: -0.2, + ), + // TextStyle( + // fontSize: 14, + // height: 21 / 14, + // // fontFamily: FontUtils.getFontFamily(context), + // + // fontWeight: FontWeight.w500, + // color: const Color(0xff2E3039), + // letterSpacing: -0.2, + // ), + decoration: InputDecoration( + isDense: true, + hintText: _hintText, + hintStyle: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 16, + fontWeight: FontWeight.w500, + color: const Color(0xff898A8D), + letterSpacing: -0.2, + ), + prefixIconConstraints: const BoxConstraints(minWidth: 45), + prefixIcon: prefix == null + ? null + : Text("+" + prefix, style: context.dynamicTextStyle( fontSize: 14, height: 21 / 14, fontWeight: FontWeight.w500, - color: const Color(0xff2E3039), + color: const Color(0xff2E303A), letterSpacing: -0.2, - ), - // TextStyle( - // fontSize: 14, - // height: 21 / 14, - // // fontFamily: FontUtils.getFontFamily(context), - // - // fontWeight: FontWeight.w500, - // color: const Color(0xff2E3039), - // letterSpacing: -0.2, - // ), - decoration: InputDecoration( - isDense: true, - hintText: _hintText, - hintStyle: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 16, - fontWeight: FontWeight.w500, - color: const Color(0xff898A8D), - letterSpacing: -0.2, - ), - prefixIconConstraints: const BoxConstraints(minWidth: 45), - prefixIcon: prefix == null - ? null - : Text("+" + prefix, - style: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 14, - fontWeight: FontWeight.w500, - color: const Color(0xff2E303A), - letterSpacing: -0.2, - )), - contentPadding: EdgeInsets.zero, - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - ), - ), + )), + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + ), ], ), ), @@ -565,35 +601,36 @@ Widget inputWidget( } Widget newInputWidget( - String _labelText, - String _hintText, - TextEditingController? _controller, { - Function(String?)? onChange, - String? prefix, - bool isEnable = true, - bool hasSelection = false, - bool hasSelectionCustomIcon = false, - String? selectionCustomIcon, - bool isBorderAllowed = true, - bool isAllowLeadingIcon = false, - bool isLeadingCountry = false, - String? leadingIcon, - bool removePadding = false, - bool isAllowRadius = true, - bool isReadOnly = false, - TextInputType keyboardType = TextInputType.number, - List? dropdownItems, - String? selectedValue, - SelectionType? selectionType, - Function(bool)? onCalendarTypeChanged, - EdgeInsetsGeometry? padding, - String lang = 'en', - bool isCountryDropDown = false, - List countryList = const [], - FocusNode? focusNode, - bool autoFocus = false, - Function(Country)? onCountryChange, -}) { + String _labelText, + String _hintText, + TextEditingController? _controller, { + Function(String?)? onChange, + String? prefix, + bool isEnable = true, + bool hasSelection = false, + bool hasSelectionCustomIcon = false, + String? selectionCustomIcon, + bool isBorderAllowed = true, + bool isAllowLeadingIcon = false, + bool isLeadingCountry = false, + String? leadingIcon, + bool removePadding = false, + bool isAllowRadius = true, + bool isReadOnly = false, + TextInputType keyboardType = TextInputType.number, + List? dropdownItems, + String? selectedValue, + SelectionType? selectionType, + Function(bool)? onCalendarTypeChanged, + EdgeInsetsGeometry? padding, + String lang = 'en', + bool isCountryDropDown = false, + List countryList = const [], + FocusNode? focusNode, + bool autoFocus = false, + Function(Country)? onCountryChange, + Key? key, + }) { return Builder( builder: (context) { // final isRtl = Directionality.of(context) == TextDirection.ltr; @@ -618,32 +655,32 @@ Widget newInputWidget( if (isAllowLeadingIcon && leadingIcon != null) isCountryDropDown ? _CustomCountryDropdown( - logo: SvgPicture.asset( - prefix == "966" ? "assets/images/svg/ksa.svg" : "assets/images/svg/uae.svg", - width: 40, - height: 40, - fit: BoxFit.cover, - ), - countryList: countryList, - onCountryChange: onCountryChange, - isRtl: Directionality.of(context) == TextDirection.rtl, - ) + logo: SvgPicture.asset( + prefix == "966" ? "assets/images/svg/ksa.svg" : "assets/images/svg/uae.svg", + width: 40, + height: 40, + fit: BoxFit.cover, + ), + countryList: countryList, + onCountryChange: onCountryChange, + isRtl: Directionality.of(context) == TextDirection.rtl, + ) : Container( - height: 40, - width: 40, - margin: const EdgeInsets.only(right: 10), - padding: isLeadingCountry ? null : const EdgeInsets.all(8), - decoration: const BoxDecoration( - color: Color(0xFFEFEFF0), - borderRadius: BorderRadius.all(Radius.circular(10)), - ), - child: SvgPicture.asset( - leadingIcon, - width: 24, - height: 24, - fit: BoxFit.cover, - ), - ), + height: 40, + width: 40, + margin: const EdgeInsets.only(right: 10), + padding: isLeadingCountry ? null : const EdgeInsets.all(8), + decoration: const BoxDecoration( + color: Color(0xFFEFEFF0), + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: SvgPicture.asset( + leadingIcon, + width: 24, + height: 24, + fit: BoxFit.cover, + ), + ), Expanded( child: Column( mainAxisSize: MainAxisSize.min, @@ -661,152 +698,153 @@ Widget newInputWidget( ), hasSelection ? GestureDetector( - onTap: isEnable && !isReadOnly - ? () async { - if (selectionType == SelectionType.dropdown) { - final renderBox = context.findRenderObject() as RenderBox; - final offset = renderBox.localToGlobal(Offset.zero); - final selected = await showMenu( - context: context, - position: RelativeRect.fromLTRB( - offset.dx, - offset.dy + renderBox.size.height, - offset.dx + renderBox.size.width, - 0, - ), - items: dropdownItems - ?.map( - (e) => PopupMenuItem( - value: e, - child: Text(e), - ), - ) - .toList() ?? - [], - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ); - - if (selected != null && onChange != null) { - onChange(selected); - } - } else if (selectionType == SelectionType.calendar) { - bool isGregorian = true; - // final picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1900), lastDate: DateTime(2100)); - final picked = await showHijriGregBottomSheet( - context, - switcherIcon: SvgPicture.asset("assets/images/svg/language.svg", width: 24), - // fontFamily: FontUtils.getFontFamily(context), - language: lang, - initialShowGregorian: true, - initialDate: DateTime.now(), - okWidget: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: SvgPicture.asset( - "assets/images/svg/confirm.svg", - width: 24, - height: 24, - ), - ), - cancelWidget: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: SvgPicture.asset( - "assets/images/svg/cancel.svg", - colorFilter: ColorFilter.mode( - Colors.white, - BlendMode.srcIn, - ), - width: 24, - height: 24, - ), - ), - onCalendarTypeChanged: (bool value) { - isGregorian = value; - }, - ); - if (picked != null && onChange != null) { - print(picked.toIso8601String()); - if (onCalendarTypeChanged != null) { - print(isGregorian.toString()); - onCalendarTypeChanged.call(isGregorian); - } - onChange(picked.toIso8601String()); - } - } - } - : null, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text((selectedValue == null || selectedValue.isEmpty) ? _hintText : selectedValue, - textAlign: TextAlign.left, - textDirection: TextDirection.ltr, - style: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 14, - fontWeight: FontWeight.w500, - color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), - letterSpacing: -0.2, - )), - ), - if (hasSelectionCustomIcon && selectionCustomIcon != null) - SvgPicture.asset(selectionCustomIcon, width: 24, height: 24) - else - const Icon(Icons.keyboard_arrow_down_outlined), - ], + onTap: isEnable && !isReadOnly + ? () async { + if (selectionType == SelectionType.dropdown) { + final renderBox = context.findRenderObject() as RenderBox; + final offset = renderBox.localToGlobal(Offset.zero); + final selected = await showMenu( + context: context, + position: RelativeRect.fromLTRB( + offset.dx, + offset.dy + renderBox.size.height, + offset.dx + renderBox.size.width, + 0, ), - ) - : TextField( - enabled: isEnable, - scrollPadding: EdgeInsets.zero, - keyboardType: keyboardType, - controller: _controller, - readOnly: isReadOnly, - textAlignVertical: TextAlignVertical.top, - textAlign: TextAlign.left, - - textDirection: TextDirection.ltr, - onChanged: onChange, - focusNode: focusNode, - autofocus: autoFocus, - style: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 14, - fontWeight: FontWeight.w500, - color: const Color(0xff2E3039), - letterSpacing: -0.2, + items: dropdownItems + ?.map( + (e) => PopupMenuItem( + value: e, + child: Text(e), + ), + ) + .toList() ?? + [], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), ), - decoration: InputDecoration( - isDense: true, - hintText: _hintText, - hintStyle: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 16, - fontWeight: FontWeight.w500, - color: const Color(0xff898A8D), - letterSpacing: -0.2, + ); + + if (selected != null && onChange != null) { + onChange(selected); + } + } else if (selectionType == SelectionType.calendar) { + bool isGregorian = true; + // final picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime(1900), lastDate: DateTime(2100)); + final picked = await showHijriGregBottomSheet( + context, + switcherIcon: SvgPicture.asset("assets/images/svg/language.svg", width: 24), + // fontFamily: FontUtils.getFontFamily(context), + language: lang, + fontFamily: FontUtils.getFontFamilyForLanguage(context.selectedLanguage == "ar" ? true : false), + initialShowGregorian: true, + initialDate: DateTime.now(), + okWidget: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SvgPicture.asset( + "assets/images/svg/confirm.svg", + width: 24, + height: 24, ), - prefixIconConstraints: const BoxConstraints(minWidth: 45), - prefixIcon: prefix == null - ? null - : Text( - "+" + prefix, - style: context.dynamicTextStyle( - fontSize: 14, - height: 21 / 14, - fontWeight: FontWeight.w500, - color: const Color(0xff2E303A), - letterSpacing: -0.2, - ), - ), - contentPadding: EdgeInsets.zero, - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, ), + cancelWidget: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SvgPicture.asset( + "assets/images/svg/cancel.svg", + colorFilter: ColorFilter.mode( + Colors.white, + BlendMode.srcIn, + ), + width: 24, + height: 24, + ), + ), + onCalendarTypeChanged: (bool value) { + isGregorian = value; + }, + ); + if (picked != null && onChange != null) { + print(picked.toIso8601String()); + if (onCalendarTypeChanged != null) { + print(isGregorian.toString()); + onCalendarTypeChanged.call(isGregorian); + } + onChange(picked.toIso8601String()); + } + } + } + : null, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text((selectedValue == null || selectedValue.isEmpty) ? _hintText : selectedValue, + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), + letterSpacing: -0.2, + )), + ), + if (hasSelectionCustomIcon && selectionCustomIcon != null) + SvgPicture.asset(selectionCustomIcon, width: 24, height: 24) + else + const Icon(Icons.keyboard_arrow_down_outlined), + ], + ), + ) + : TextField( + enabled: isEnable, + key: key, + scrollPadding: EdgeInsets.zero, + keyboardType: keyboardType, + controller: _controller, + readOnly: isReadOnly, + textAlignVertical: TextAlignVertical.top, + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + onChanged: onChange, + focusNode: focusNode, + autofocus: autoFocus, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: const Color(0xff2E3039), + letterSpacing: -0.2, + ), + decoration: InputDecoration( + isDense: true, + hintText: _hintText, + hintStyle: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 16, + fontWeight: FontWeight.w500, + color: const Color(0xff898A8D), + letterSpacing: -0.2, + ), + prefixIconConstraints: const BoxConstraints(minWidth: 45), + prefixIcon: prefix == null + ? null + : Text( + "+" + prefix, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: const Color(0xff2E303A), + letterSpacing: -0.2, ), + ), + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + ), ], ), ), @@ -817,8 +855,260 @@ Widget newInputWidget( ); } +// Widget newInputWidget(String _labelText, +// String _hintText, +// TextEditingController? _controller, { +// Function(String?)? onChange, +// String? prefix, +// bool isEnable = true, +// bool hasSelection = false, +// bool hasSelectionCustomIcon = false, +// String? selectionCustomIcon, +// bool isBorderAllowed = true, +// bool isAllowLeadingIcon = false, +// bool isLeadingCountry = false, +// String? leadingIcon, +// bool removePadding = false, +// bool isAllowRadius = true, +// bool isReadOnly = false, +// TextInputType keyboardType = TextInputType.number, +// List? dropdownItems, +// String? selectedValue, +// SelectionType? selectionType, +// Function(bool)? onCalendarTypeChanged, +// EdgeInsetsGeometry? padding, +// String lang = 'en', +// bool isCountryDropDown = false, +// List countryList = const [], +// FocusNode? focusNode, +// bool autoFocus = false, +// Function(Country)? onCountryChange, +// Key? key, +// }) { +// return Builder( +// builder: (context) { +// // final isRtl = Directionality.of(context) == TextDirection.ltr; +// return Container( +// padding: padding, +// // padding: removePadding && isAllowLeadingIcon && prefix == null +// // ? const EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8) +// // : removePadding && !hasSelection +// // ? const EdgeInsets.only(top: 8, bottom: 8, left: 0, right: 0) +// // : removePadding && hasSelection +// // ? null +// // : const EdgeInsets.symmetric(horizontal: 16, vertical: 15), +// alignment: Alignment.center, +// decoration: BoxDecoration( +// borderRadius: isAllowRadius ? BorderRadius.circular(15) : null, +// color: Colors.white, +// border: isBorderAllowed ? Border.all(color: const Color(0xffefefef), width: 1) : null, +// ), +// child: Row( +// textDirection: Directionality.of(context), +// children: [ +// if (isAllowLeadingIcon && leadingIcon != null) +// isCountryDropDown +// ? _CustomCountryDropdown( +// logo: SvgPicture.asset( +// prefix == "966" ? "assets/images/svg/ksa.svg" : "assets/images/svg/uae.svg", +// width: 40, +// height: 40, +// fit: BoxFit.cover, +// ), +// countryList: countryList, +// onCountryChange: onCountryChange, +// isRtl: Directionality.of(context) == TextDirection.rtl, +// ) +// : Container( +// height: 40, +// width: 40, +// margin: const EdgeInsets.only(right: 10), +// padding: isLeadingCountry ? null : const EdgeInsets.all(8), +// decoration: const BoxDecoration( +// color: Color(0xFFEFEFF0), +// borderRadius: BorderRadius.all(Radius.circular(10)), +// ), +// child: SvgPicture.asset( +// leadingIcon, +// width: 24, +// height: 24, +// fit: BoxFit.cover, +// ), +// ), +// Expanded( +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// _labelText, +// style: context.dynamicTextStyle( +// fontSize: 12, +// fontWeight: FontWeight.w500, +// color: const Color(0xff898A8D), +// letterSpacing: -0.2, +// height: 18 / 12, +// ), +// ), +// hasSelection +// ? GestureDetector( +// onTap: isEnable && !isReadOnly +// ? () async { +// if (selectionType == SelectionType.dropdown) { +// final renderBox = context.findRenderObject() as RenderBox; +// final offset = renderBox.localToGlobal(Offset.zero); +// final selected = await showMenu( +// context: context, +// position: RelativeRect.fromLTRB( +// offset.dx, +// offset.dy + renderBox.size.height, +// offset.dx + renderBox.size.width, +// 0, +// ), +// items: dropdownItems +// ?.map( +// (e) => +// PopupMenuItem( +// value: e, +// child: Text(e), +// ), +// ) +// .toList() ?? +// [], +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(12), +// ), +// ); +// +// if (selected != null) { +// _handleOnChange(selected); +// } +// } else if (widget.selectionType == SelectionType.calendar) { +// bool isGregorian = true; +// final picked = await showHijriGregBottomSheet( +// context, +// switcherIcon: SvgPicture.asset("assets/images/svg/language.svg", width: 24), +// language: widget.lang, +// fontFamily: FontUtils.getFontFamilyForLanguage(context.selectedLanguage == "ar" ? true : false), +// initialShowGregorian: true, +// initialDate: DateTime.now(), +// okWidget: Padding( +// padding: const EdgeInsets.only(right: 8.0), +// child: SvgPicture.asset( +// "assets/images/svg/confirm.svg", +// width: 24, +// height: 24, +// ), +// ), +// cancelWidget: Padding( +// padding: const EdgeInsets.only(right: 8.0), +// child: SvgPicture.asset( +// "assets/images/svg/cancel.svg", +// colorFilter: ColorFilter.mode( +// Colors.white, +// BlendMode.srcIn, +// ), +// width: 24, +// height: 24, +// ), +// ), +// onCalendarTypeChanged: (bool value) { +// isGregorian = value; +// }, +// ); +// if (picked != null) { +// if (widget.onCalendarTypeChanged != null) { +// widget.onCalendarTypeChanged!.call(isGregorian); +// } +// _handleOnChange(picked.toIso8601String()); +// } +// } +// } +// : null, +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Expanded( +// child: Text((selectedValue == null || selectedValue.isEmpty) ? _hintText : selectedValue, +// textAlign: TextAlign.left, +// textDirection: TextDirection.ltr, +// style: context.dynamicTextStyle( +// fontSize: 14, +// height: 21 / 14, +// fontWeight: FontWeight.w500, +// color: (selectedValue != null && selectedValue.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), +// letterSpacing: -0.2, +// )), +// ), +// if (hasSelectionCustomIcon && selectionCustomIcon != null) +// SvgPicture.asset(selectionCustomIcon, width: 24, height: 24) +// else +// const Icon(Icons.keyboard_arrow_down_outlined), +// ], +// ), +// ) +// : TextField( +// enabled: isEnable, +// key: key, +// scrollPadding: EdgeInsets.zero, +// keyboardType: keyboardType, +// controller: _controller, +// readOnly: isReadOnly, +// textAlignVertical: TextAlignVertical.top, +// textAlign: TextAlign.left, +// textDirection: TextDirection.ltr, +// onChanged: onChange, +// focusNode: focusNode, +// autofocus: autoFocus, +// style: context.dynamicTextStyle( +// fontSize: 14, +// height: 21 / 14, +// fontWeight: FontWeight.w500, +// color: const Color(0xff2E3039), +// letterSpacing: -0.2, +// ), +// decoration: InputDecoration( +// isDense: true, +// hintText: _hintText, +// hintStyle: context.dynamicTextStyle( +// fontSize: 14, +// height: 21 / 16, +// fontWeight: FontWeight.w500, +// color: const Color(0xff898A8D), +// letterSpacing: -0.2, +// ), +// prefixIconConstraints: const BoxConstraints(minWidth: 45), +// prefixIcon: prefix == null +// ? null +// : Text( +// "+" + prefix, +// style: context.dynamicTextStyle( +// fontSize: 14, +// height: 21 / 14, +// fontWeight: FontWeight.w500, +// color: const Color(0xff2E303A), +// letterSpacing: -0.2, +// ), +// ), +// contentPadding: EdgeInsets.zero, +// border: InputBorder.none, +// focusedBorder: InputBorder.none, +// enabledBorder: InputBorder.none, +// ), +// ), +// ], +// ), +// ), +// ], +// ), +// ); +// }, +// ); +// } + extension BorderedContainer on Widget { - Widget get withBorderedContainer => Container( + Widget get withBorderedContainer => + Container( padding: EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15), alignment: Alignment.center, decoration: BoxDecoration( @@ -891,65 +1181,67 @@ class __CustomCountryDropdownState extends State<_CustomCountryDropdown> { Offset offset = renderBox.localToGlobal(Offset.zero); _overlayEntry = OverlayEntry( - builder: (context) => Stack( - children: [ - // Dismiss dropdown when tapping outside - Positioned.fill( - child: GestureDetector( - onTap: _closeDropdown, - behavior: HitTestBehavior.translucent, - child: Container(), - ), - ), - Positioned( - top: offset.dy + renderBox.size.height, - left: widget.isRtl ? offset.dx + 15 : offset.dx - 15, - width: renderBox.size.width, - child: Material( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Color(0xFFF8F8FA), - blurRadius: 8, - offset: Offset(0, 2), - ), - ], + builder: (context) => + Stack( + children: [ + // Dismiss dropdown when tapping outside + Positioned.fill( + child: GestureDetector( + onTap: _closeDropdown, + behavior: HitTestBehavior.translucent, + child: Container(), ), - child: Column( - children: widget.countryList - .map( - (country) => GestureDetector( - onTap: () { - setState(() { - selectedCountry = country; - }); - widget.onCountryChange?.call(country); - _closeDropdown(); - }, - child: Container( - padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), - child: Row( - children: [ - SvgPicture.asset( - country.iconPath, - width: 38, - height: 38, - fit: BoxFit.cover, + ), + Positioned( + top: offset.dy + renderBox.size.height, + left: widget.isRtl ? offset.dx + 15 : offset.dx - 15, + width: renderBox.size.width, + child: Material( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Color(0xFFF8F8FA), + blurRadius: 8, + offset: Offset(0, 2), + ), + ], + ), + child: Column( + children: widget.countryList + .map( + (country) => + GestureDetector( + onTap: () { + setState(() { + selectedCountry = country; + }); + widget.onCountryChange?.call(country); + _closeDropdown(); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), + child: Row( + children: [ + SvgPicture.asset( + country.iconPath, + width: 38, + height: 38, + fit: BoxFit.cover, + ), + ], ), - ], + ), ), - ), - ), ) - .toList(), + .toList(), + ), + ), ), ), - ), + ], ), - ], - ), ); Overlay.of(context)?.insert(_overlayEntry); @@ -965,3 +1257,364 @@ class __CustomCountryDropdownState extends State<_CustomCountryDropdown> { }); } } + +class NewInputField extends StatefulWidget { + final String labelText; + final String hintText; + final TextEditingController? controller; + final Function(String?)? onChange; + final String? prefix; + final bool isEnable; + final bool hasSelection; + final bool hasSelectionCustomIcon; + final String? selectionCustomIcon; + final bool isBorderAllowed; + final bool isAllowLeadingIcon; + final bool isLeadingCountry; + final String? leadingIcon; + final bool removePadding; + final bool isAllowRadius; + final bool isReadOnly; + final TextInputType keyboardType; + final List? dropdownItems; + final String? selectedValue; + final SelectionType? selectionType; + final Function(bool)? onCalendarTypeChanged; + final EdgeInsetsGeometry? padding; + final String lang; + final bool isCountryDropDown; + final List countryList; + final bool autoFocus; + final Function(Country)? onCountryChange; + final bool keepFocus; // New parameter to maintain focus + final bool refocusOnChange; // New parameter to refocus when onChange is triggered + + const NewInputField({ + required this.labelText, + required this.hintText, + this.controller, + this.onChange, + this.prefix, + this.isEnable = true, + this.hasSelection = false, + this.hasSelectionCustomIcon = false, + this.selectionCustomIcon, + this.isBorderAllowed = true, + this.isAllowLeadingIcon = false, + this.isLeadingCountry = false, + this.leadingIcon, + this.removePadding = false, + this.isAllowRadius = true, + this.isReadOnly = false, + this.keyboardType = TextInputType.number, + this.dropdownItems, + this.selectedValue, + this.selectionType, + this.onCalendarTypeChanged, + this.padding, + this.lang = 'en', + this.isCountryDropDown = false, + this.countryList = const [], + this.autoFocus = false, + this.onCountryChange, + this.keepFocus = false, + this.refocusOnChange = false, + }); + + @override + State createState() => _NewInputFieldState(); +} + +class _NewInputFieldState extends State { + late FocusNode _internalFocusNode; + bool _isInitialFocusSet = false; + bool _shouldMaintainFocus = false; + + @override + void initState() { + super.initState(); + _internalFocusNode = FocusNode(); + _shouldMaintainFocus = widget.keepFocus; + + // Add listener to handle focus loss if keepFocus is enabled + if (widget.keepFocus) { + _internalFocusNode.addListener(_handleFocusChange); + } + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (widget.autoFocus && !_isInitialFocusSet) { + _isInitialFocusSet = true; + _requestFocus(); + } + } + + @override + void didUpdateWidget(NewInputField oldWidget) { + super.didUpdateWidget(oldWidget); + + // Update focus management settings if they changed + if (oldWidget.keepFocus != widget.keepFocus) { + _shouldMaintainFocus = widget.keepFocus; + if (widget.keepFocus) { + _internalFocusNode.addListener(_handleFocusChange); + } else { + _internalFocusNode.removeListener(_handleFocusChange); + } + } + } + + void _handleFocusChange() { + // If keepFocus is enabled and focus is lost, regain it + if (_shouldMaintainFocus && !_internalFocusNode.hasFocus && mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted && _internalFocusNode.canRequestFocus && !_internalFocusNode.hasFocus) { + _internalFocusNode.requestFocus(); + } + }); + } + } + + void _requestFocus() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted && _internalFocusNode.canRequestFocus) { + _internalFocusNode.requestFocus(); + } + }); + } + + void _handleOnChange(String? value) { + // Call the original onChange callback + if (widget.onChange != null) { + widget.onChange!(value); + } + + // If refocusOnChange is enabled, refocus the field + if (widget.refocusOnChange && mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted && _internalFocusNode.canRequestFocus) { + _internalFocusNode.requestFocus(); + } + }); + } + } + + @override + void dispose() { + _internalFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: widget.padding, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: widget.isAllowRadius ? BorderRadius.circular(15) : null, + color: Colors.white, + border: widget.isBorderAllowed ? Border.all(color: const Color(0xffefefef), width: 1) : null, + ), + child: Row( + textDirection: Directionality.of(context), + children: [ + if (widget.isAllowLeadingIcon && widget.leadingIcon != null) + widget.isCountryDropDown + ? _CustomCountryDropdown( + logo: SvgPicture.asset( + widget.prefix == "966" ? "assets/images/svg/ksa.svg" : "assets/images/svg/uae.svg", + width: 40, + height: 40, + fit: BoxFit.cover, + ), + countryList: widget.countryList, + onCountryChange: widget.onCountryChange, + isRtl: Directionality.of(context) == TextDirection.rtl, + ) + : Container( + height: 40, + width: 40, + margin: const EdgeInsets.only(right: 10), + padding: widget.isLeadingCountry ? null : const EdgeInsets.all(8), + decoration: const BoxDecoration( + color: Color(0xFFEFEFF0), + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: SvgPicture.asset( + widget.leadingIcon!, + width: 24, + height: 24, + fit: BoxFit.cover, + ), + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.labelText, + style: context.dynamicTextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: const Color(0xff898A8D), + letterSpacing: -0.2, + height: 18 / 12, + ), + ), + widget.hasSelection + ? GestureDetector( + onTap: widget.isEnable && !widget.isReadOnly + ? () async { + if (widget.selectionType == SelectionType.dropdown) { + final renderBox = context.findRenderObject() as RenderBox; + final offset = renderBox.localToGlobal(Offset.zero); + final selected = await showMenu( + context: context, + position: RelativeRect.fromLTRB( + offset.dx, + offset.dy + renderBox.size.height, + offset.dx + renderBox.size.width, + 0, + ), + items: widget.dropdownItems + ?.map( + (e) => + PopupMenuItem( + value: e, + child: Text(e), + ), + ) + .toList() ?? + [], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ); + + if (selected != null) { + _handleOnChange(selected); + } + } else if (widget.selectionType == SelectionType.calendar) { + bool isGregorian = true; + final picked = await showHijriGregBottomSheet( + context, + switcherIcon: SvgPicture.asset("assets/images/svg/language.svg", width: 24), + language: widget.lang, + fontFamily: FontUtils.getFontFamilyForLanguage(context.selectedLanguage == "ar" ? true : false), + initialShowGregorian: true, + initialDate: DateTime.now(), + okWidget: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SvgPicture.asset( + "assets/images/svg/confirm.svg", + width: 24, + height: 24, + ), + ), + cancelWidget: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: SvgPicture.asset( + "assets/images/svg/cancel.svg", + colorFilter: ColorFilter.mode( + Colors.white, + BlendMode.srcIn, + ), + width: 24, + height: 24, + ), + ), + onCalendarTypeChanged: (bool value) { + isGregorian = value; + }, + ); + if (picked != null) { + if (widget.onCalendarTypeChanged != null) { + widget.onCalendarTypeChanged!.call(isGregorian); + } + _handleOnChange(picked.toIso8601String()); + } + } + } + : null, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text((widget.selectedValue == null || widget.selectedValue!.isEmpty) ? widget.hintText : widget.selectedValue!, + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: (widget.selectedValue != null && widget.selectedValue!.isNotEmpty) ? const Color(0xff2E3039) : const Color(0xffB0B0B0), + letterSpacing: -0.2, + )), + ), + if (widget.hasSelectionCustomIcon && widget.selectionCustomIcon != null) + SvgPicture.asset(widget.selectionCustomIcon!, width: 24, height: 24) + else + const Icon(Icons.keyboard_arrow_down_outlined), + ], + ), + ) + : TextField( + enabled: widget.isEnable, + scrollPadding: EdgeInsets.zero, + keyboardType: widget.keyboardType, + controller: widget.controller, + readOnly: widget.isReadOnly, + textAlignVertical: TextAlignVertical.top, + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + onChanged:_handleOnChange, + focusNode: _internalFocusNode, + autofocus: widget.autoFocus, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: const Color(0xff2E3039), + letterSpacing: -0.2, + ), + decoration: InputDecoration( + isDense: true, + hintText: widget.hintText, + hintStyle: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 16, + fontWeight: FontWeight.w500, + color: const Color(0xff898A8D), + letterSpacing: -0.2, + ), + prefixIconConstraints: const BoxConstraints(minWidth: 45), + prefixIcon: widget.prefix == null + ? null + : Text( + "+" + widget.prefix!, + style: context.dynamicTextStyle( + fontSize: 14, + height: 21 / 14, + fontWeight: FontWeight.w500, + color: const Color(0xff2E303A), + letterSpacing: -0.2, + ), + ), + contentPadding: EdgeInsets.zero, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + ), + ], + ), + ), + ], + ), + ); + } +} + diff --git a/lib/pages/login/register_new.dart b/lib/pages/login/register_new.dart index 2fcb9e63..d51d5aad 100644 --- a/lib/pages/login/register_new.dart +++ b/lib/pages/login/register_new.dart @@ -548,31 +548,34 @@ class _RegisterNew extends State { request.isRegister = true; request.dob = isHijri == 1 ? selectedDOB!.toString() : dateFormat.format(selectedDOB!); request.isHijri = isHijri ?? 0; - this.checkPatientForRegisteration(registrationData: request, type: type); + checkPatientForRegistration(registrationData: request, type: type); // } } - checkPatientForRegisteration({required CheckPatientForRegistration registrationData, type}) { + checkPatientForRegistration({required CheckPatientForRegistration registrationData, type}) { int languageID = Provider.of(context, listen: false).isArabic ? 1 : 2; GifLoaderDialogUtils.showMyDialog(context); - authService.checkPatientForRegisteration(registrationData, languageID).then((response) => {checkUserStatus(response, registrationData, type)}).catchError((err) { + authService.checkPatientForRegisteration(registrationData, languageID).then((response) => { + // Keep loader active, continue to next step + checkUserStatus(response, registrationData, type) + }).catchError((err) { GifLoaderDialogUtils.hideDialog(context); - ConfirmDialog dialog = ConfirmDialog( - context: context, - confirmMessage: err, - okText: TranslationBase.of(context).confirm, - cancelText: TranslationBase.of(context).cancel_nocaps, - okFunction: () => { - ConfirmDialog.closeAlertDialog(context), - Navigator.of(context).push(FadePage(page: RegisterNew())), - }, - cancelFunction: () => {ConfirmDialog.closeAlertDialog(context)}); - dialog.showAlertDialog(context); + + context.showBottomSheet( + child: ExceptionBottomSheet( + showCancel: true, + message: err, + onOkPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).push(FadePage(page: RegisterNew())); + }, + ), + ); }); } checkUserStatus(response, CheckPatientForRegistration request, type) async { - GifLoaderDialogUtils.hideDialog(context); + // No loader shown here since it's already hidden in checkPatientForRegisteration if (response is Map) { var nRequest = request.toJson(); nRequest['LogInTokenID'] = response['LogInTokenID']; @@ -609,20 +612,19 @@ class _RegisterNew extends State { } else { // if (response['ErrorCode'] == '-986') { //AppToast.showErrorToast(message: response); - AlertDialogBox( - context: context, - confirmMessage: response, - okText: TranslationBase.of(context).ok, - okFunction: () { - AlertDialogBox.closeAlertDialog(context); + context.showBottomSheet( + child: ExceptionBottomSheet( + message: response, + onOkPressed: () { Navigator.of(context).pop(); - }).showAlertDialog(context); - //} + }, + ), + ); } } chekUserData(loginToken, int type) { - GifLoaderDialogUtils.showMyDialog(context); + // Keep existing loader active, don't show new one var request = CheckUserStatusRequest(); request.patientIdentificationID = nationalIDorFile.text; request.dOB = isHijri == 1 ? selectedDOB!.toString() : dateFormat.format(selectedDOB!); @@ -630,19 +632,17 @@ class _RegisterNew extends State { request.patientOutSA = selectedCountry.countryCode == '966' ? 0 : 1; this.authService.checkUserStatus(request).then((result) { - GifLoaderDialogUtils.hideDialog(context); + // Keep loader active, continue to next step if (result is Map) { RegisterInfoResponse? resultSet; - CheckUserStatusResponse res = CheckUserStatusResponse.fromJson(result as Map); nHICData = res; sharedPref.setObject(NHIC_DATA, res.toJson()); resultSet = RegisterInfoResponse.fromJson(res.toJson()); - // widget.changePageViewIndex!(1), - // Navigator.of(context).push(FadePage(page: ConfirmLogin(changePageViewIndex: widget.changePageViewIndex, fromRegistration: true))), sendActivationCode(type, loginToken, resultSet, isSkipRegistration); } else { + GifLoaderDialogUtils.hideDialog(context); context.showBottomSheet( child: ExceptionBottomSheet( message: result != null ? result : TranslationBase.of(context).somethingWentWrong, @@ -653,6 +653,17 @@ class _RegisterNew extends State { ), ); } + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(context); + context.showBottomSheet( + child: ExceptionBottomSheet( + message: err.toString(), + showCancel: false, + onOkPressed: () { + Navigator.of(context).pop(); + }, + ), + ); }); } @@ -666,13 +677,12 @@ class _RegisterNew extends State { patientOutSA: selectedCountry.countryCode == "966" ? 0 : 1, loginTokenID: LoginTokenID, selectedOption: type, + type: type, user: SelectDeviceIMEIRES()); request.isRegister = true; request.dob = isHijri == 1 ? selectedDOB!.toString() : dateFormat.format(selectedDOB!); request.sMSSignature = await SMSOTP.getSignature(); - // print(request.oTPSendType); - // request.oTPSendType = type; - GifLoaderDialogUtils.showMyDialog(context); + print("Otp Send Type =" + request.oTPSendType.toString()); if (selectedCountry.countryCode == "966" && !skipRegistration) { request.healthId = nHICData!.healthId; @@ -683,11 +693,13 @@ class _RegisterNew extends State { request.patientIdentificationID = nationalIDorFile.text; } request.isHijri = isHijri ?? 0; - // request.oTPSendType = type; + if (skipRegistration) { + // Keep existing loader active, don't show new one var req = getCommonRequest(type: type); req.logInTokenID = ""; var request = CheckPatientAuthenticationReq.fromJson(req.toJson()); + authService.checkPatientAuthentication(request).then((value) async { if (value['isSMSSent']) { sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']); @@ -700,6 +712,7 @@ class _RegisterNew extends State { request.isHijri = 0; await authService.sendActivationCode(request).then((result) { + // Hide loader before navigation to SMS OTP GifLoaderDialogUtils.hideDialog(context); if (result != null && result['isSMSSent'] == true) { startSMSService(request.loginType, skipRegistration); @@ -718,7 +731,12 @@ class _RegisterNew extends State { }); } else { if (value['IsAuthenticated']) { - checkActivationCode(onWrongActivationCode: (String? message, bool? isReroute) {}); + // Keep loader active and proceed to checkActivationCode + checkActivationCode(onWrongActivationCode: (String? message, bool? isReroute) { + GifLoaderDialogUtils.hideDialog(context); + }); + } else { + GifLoaderDialogUtils.hideDialog(context); } } }).catchError((err) { @@ -736,11 +754,12 @@ class _RegisterNew extends State { ); }); } else { + // Keep existing loader active, don't show new one await this.authService.sendActivationCodeRegister(request).then((result) { + // Hide loader before navigation to SMS OTP GifLoaderDialogUtils.hideDialog(context); if (result != null && result['isSMSSent'] == true) { print(result); - // LoginTokenID = result["LogInTokenID"]; startSMSService(type, skipRegistration); } }).catchError((r) { @@ -840,6 +859,7 @@ class _RegisterNew extends State { result = await authService.checkActivationCodeRegister(req.toJson(), value); if (result is Map) { final activation = CheckActivationCode.fromJson(result as Map); + GifLoaderDialogUtils.hideDialog(context); Navigator.of(context).push( FadePage(page: RegisterNewStep2(nHICData, req)), ); @@ -916,6 +936,7 @@ class _RegisterNew extends State { startSMSService(type, skipRegistration) { late SMSOTP smsOtp; + smsOtp = SMSOTP( context, type, diff --git a/lib/pages/login/saved_login.dart b/lib/pages/login/saved_login.dart index e85950fa..63708495 100644 --- a/lib/pages/login/saved_login.dart +++ b/lib/pages/login/saved_login.dart @@ -191,9 +191,9 @@ class _SavedLogin extends State { checkUserAuthentication(val); } }, - backgroundColor: Color(0xffFEE9EA), + backgroundColor: Color(0xffED1C2B), borderColor: Color(0xffFEE9EA), - textColor: Color(0xffED1C2B), + textColor: Colors.white, fontSize: 12, fontWeight: FontWeight.w500, borderRadius: 12, @@ -217,37 +217,120 @@ class _SavedLogin extends State { widget.savedLoginData.logInType != null && widget.savedLoginData.logInType != 1 ? Column( children: [ - widget.savedLoginData.logInType !=1 ? CustomButton( - text: TranslationBase.of(context).loginByOTP, - onPressed: () { - widget.savedLoginData.logInType = 1; - int? val = widget.savedLoginData.logInType!; - checkUserAuthentication(val); - }, - backgroundColor: Colors.white, - borderColor: Color(0xFF2E3039), - textColor: Color(0xFF2E3039), - borderWidth: 2, - padding: EdgeInsets.fromLTRB(0, 14, 0, 14), - icon: "assets/images/svg/password-validation.svg", - ) : Container(), + widget.savedLoginData.logInType != 1 + ? CustomButton( + text: TranslationBase.of(context).loginByOTP, + onPressed: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + isDismissible: false, + useSafeArea: true, + backgroundColor: Colors.transparent, + enableDrag: false, + // Prevent dragging to avoid focus conflicts + builder: (bottomSheetContext) => StatefulBuilder(builder: (BuildContext context, StateSetter setModalState) { + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(bottomSheetContext).viewInsets.bottom), + child: SingleChildScrollView( + child: GenericBottomSheet( + countryCode: selectedCountry.countryCode, + initialPhoneNumber: phoneNumber != null ? phoneNumber : "", + textController: phoneController, + isFromSavedLogin: true, + isEnableCountryDropdown: true, + onCountryChange: (value) { + selectedCountry = value; + setModalState(() {}); + }, + onChange: (String? value) { + phoneNumber = value; + }, + buttons: [ + Padding( + padding: const EdgeInsets.only(bottom: 10), + child: CustomButton( + text: TranslationBase.of(context).sendOTPSMS, + onPressed: () { + // int? val = Utils.onOtpBtnPressed(OTPType.sms, phoneNumber, context); + // if (val != null) checkUserAuthentication(val); + Navigator.of(context).pop(); + widget.savedLoginData.logInType = 1; + int? val = widget.savedLoginData.logInType!; + checkUserAuthentication(val); + }, + backgroundColor: CustomColors.bgRedColor, + borderColor: CustomColors.bgRedBorderColor, + textColor: Colors.white, + icon: "assets/images/svg/message.svg", + ), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: AppText( + TranslationBase.of(context).oR, + fontSize: 16, + color: Color(0xFF2E3039), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.only(bottom: 10, top: 10), + child: CustomButton( + text: TranslationBase.of(context).sendOTPWHATSAPP, + onPressed: () { + Navigator.of(context).pop(); + widget.savedLoginData.logInType = 4; + int? val = widget.savedLoginData.logInType!; + checkUserAuthentication(val); + + // int? val = Utils.onOtpBtnPressed(OTPType.whatsapp, phoneNumber, context); + // if (val != null) checkUserAuthentication(val); + }, + backgroundColor: Colors.white, + borderColor: Color(0xFF2E3039), + textColor: Color(0xFF2E3039), + icon: "assets/images/svg/whatsapp.svg", + ), + ), + ], + ), + ), + ); + }), + ); + }, + backgroundColor: Colors.white, + borderColor: Color(0xFF2E3039), + textColor: Color(0xFF2E3039), + borderWidth: 2, + padding: EdgeInsets.fromLTRB(0, 14, 0, 14), + icon: "assets/images/svg/password-validation.svg", + ) + : Container(), SizedBox( height: 20, ), - widget.savedLoginData.logInType !=4 ? CustomButton( - text: "${TranslationBase.of(context).loginBy} ${getType(4, context)}", - onPressed: () { - widget.savedLoginData.logInType = 4; - int? val = widget.savedLoginData.logInType!; - checkUserAuthentication(val); - }, - backgroundColor: Colors.white, - borderColor: Color(0xFF2E3039), - textColor: Color(0xFF2E3039), - borderWidth: 2, - padding: EdgeInsets.fromLTRB(0, 14, 0, 14), - icon: "assets/images/svg/whatsapp.svg", - ) : Container(), + // widget.savedLoginData.logInType !=4 ? CustomButton( + // text: "${TranslationBase.of(context).loginBy} ${getType(4, context)}", + // onPressed: () { + // widget.savedLoginData.logInType = 4; + // int? val = widget.savedLoginData.logInType!; + // checkUserAuthentication(val); + // }, + // backgroundColor: Colors.white, + // borderColor: Color(0xFF2E3039), + // textColor: Color(0xFF2E3039), + // borderWidth: 2, + // padding: EdgeInsets.fromLTRB(0, 14, 0, 14), + // icon: "assets/images/svg/whatsapp.svg", + // ) : Container(), ], ) : CustomButton( @@ -276,33 +359,78 @@ class _SavedLogin extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( - onPressed: () { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (BuildContext context) => LandingPage(), - ), - ); - }, - child: Text( - TranslationBase.of(context).guest, - style: context.dynamicTextStyle(color: CustomColors.bgRedColor, fontSize: 16, fontWeight: FontWeight.w500, height: 16 / 26), + Expanded( + child: Container( + height: 56, + child: CustomButton( + text: TranslationBase.of(context).guest, + onPressed: () { + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (BuildContext context) => LandingPage()), + ); + }, + backgroundColor: Color(0xffFEE9EA), + borderColor: Color(0xffFEE9EA), + textColor: Color(0xffED1C2B), + fontSize: 12, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + // icon: "assets/images/svg/apple-finder.svg", + ), ), ), - const SizedBox(width: 24), - TextButton( - onPressed: () { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (BuildContext context) => WelcomeLogin(), - ), - ); - }, - child: Text( - TranslationBase.of(context).switchAccount, - style: context.dynamicTextStyle(color: CustomColors.bgRedColor, fontSize: 16, fontWeight: FontWeight.w500, height: 16 / 26), + SizedBox( + width: 24, + ), + Expanded( + child: Container( + height: 56, + child: CustomButton( + text: TranslationBase.of(context).switchAccount, + onPressed: () { + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (BuildContext context) => WelcomeLogin()), + ); + }, + backgroundColor: Color(0xffFEE9EA), + borderColor: Color(0xffFEE9EA), + textColor: Color(0xffED1C2B), + fontSize: 12, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + // icon: "assets/images/svg/apple-finder.svg", + ), ), ), + // TextButton( + // onPressed: () { + // Navigator.of(context).pushReplacement( + // MaterialPageRoute( + // builder: (BuildContext context) => LandingPage(), + // ), + // ); + // }, + // child: Text( + // TranslationBase.of(context).guest, + // style: context.dynamicTextStyle(color: CustomColors.bgRedColor, fontSize: 16, fontWeight: FontWeight.w500, height: 16 / 26), + // ), + // ), + // const SizedBox(width: 24), + // TextButton( + // onPressed: () { + // Navigator.of(context).pushReplacement( + // MaterialPageRoute( + // builder: (BuildContext context) => WelcomeLogin(), + // ), + // ); + // }, + // child: Text( + // TranslationBase.of(context).switchAccount, + // style: context.dynamicTextStyle(color: CustomColors.bgRedColor, fontSize: 16, fontWeight: FontWeight.w500, height: 16 / 26), + // ), + // ), ], ), const SizedBox(height: 20), diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart index 4ad9679b..7703b619 100644 --- a/lib/pages/login/welcome.dart +++ b/lib/pages/login/welcome.dart @@ -90,19 +90,16 @@ class _WelcomeLogin extends State { late int isHijri; var healthId; - late FocusNode _focusNode; @override void initState() { isLoading = true; super.initState(); - _focusNode = FocusNode(); phoneController = TextEditingController(); } @override void dispose() { - _focusNode.dispose(); super.dispose(); } @@ -210,7 +207,6 @@ class _WelcomeLogin extends State { countryCode: selectedCountry.countryCode, initialPhoneNumber: phoneNumber != null ? phoneNumber : "", textController: phoneController, - focusNode: _focusNode, isEnableCountryDropdown: true, onCountryChange: (value) { selectedCountry = value; @@ -218,15 +214,6 @@ class _WelcomeLogin extends State { }, onChange: (String? value) { phoneNumber = value; - // WidgetsBinding.instance.addPostFrameCallback((_) { - // Future.delayed(Duration(milliseconds: 300), () { - // if (mounted && _focusNode.canRequestFocus) { - // _focusNode.requestFocus(); - // } - // }); - // }); - - FocusNode().requestFocus(_focusNode); }, buttons: [ Padding( diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index ecc98192..2bd0a54d 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -3510,6 +3510,8 @@ class TranslationBase { String get otpVerfication => localizedValues["otpVerification"][locale.languageCode]; String get submiT => localizedValues["submiT"][locale.languageCode]; String get notice => localizedValues["notice"][locale.languageCode]; + String get receiveOtpToast => localizedValues["receiveOtpToast"][locale.languageCode]; + String get pleaseChooseOption => localizedValues["pleaseChooseOption"][locale.languageCode]; } diff --git a/lib/widgets/otp/sms-popup.dart b/lib/widgets/otp/sms-popup.dart index 1bee1380..d6e78aad 100644 --- a/lib/widgets/otp/sms-popup.dart +++ b/lib/widgets/otp/sms-popup.dart @@ -136,7 +136,7 @@ class SMSOTP { child: OTPWidget( autoFocus: true, controller: _pinPutController, - defaultBorderColor: Color(0xffE0E0E0), // Changed from white to light gray + defaultBorderColor: Color(0xffffffff), maxLength: 4, onTextChanged: (text) {}, pinBoxColor: Colors.white, diff --git a/lib/widgets/otp_widget.dart b/lib/widgets/otp_widget.dart index 69cc054f..6fd4f274 100644 --- a/lib/widgets/otp_widget.dart +++ b/lib/widgets/otp_widget.dart @@ -165,26 +165,9 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi } } - // Updated: Accept context to access MediaQuery + // Updated: Always use full screen width for responsive design double _width(BuildContext context) { - // For tablets, use full screen width - if (MediaQuery.of(context).size.shortestSide >= 600) { - return MediaQuery.of(context).size.width; - } - - // For phones, use original fixed width - var width = 0.0; - for (var i = 0; i < widget.maxLength; i++) { - width += widget.pinBoxWidth; - if (i == 0) { - width += widget.pinBoxOuterPadding.left; - } else if (i + 1 == widget.maxLength) { - width += widget.pinBoxOuterPadding.right; - } else { - width += widget.pinBoxOuterPadding.left; - } - } - return width; + return MediaQuery.of(context).size.width; } @override @@ -298,31 +281,27 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi Widget _pinBoxRow(BuildContext context) { _calculateStrList(); - // Determine if it's a tablet - bool isTablet = MediaQuery.of(context).size.shortestSide >= 600; - double boxWidth = widget.pinBoxWidth; - - // Calculate dynamic width for tablets - if (isTablet) { - double screenWidth = MediaQuery.of(context).size.width; - double totalMargin = (widget.maxLength - 1) * - (widget.pinBoxOuterPadding.left + widget.pinBoxOuterPadding.right); - double availableWidth = screenWidth - totalMargin; - boxWidth = (availableWidth / widget.maxLength).clamp(100.0, 180.0); // Reasonable limits - } + // Calculate dynamic width for all screen sizes to prevent scrolling + double screenWidth = MediaQuery.of(context).size.width; + double totalHorizontalPadding = widget.pinBoxOuterPadding.left + widget.pinBoxOuterPadding.right; + double totalMargin = widget.maxLength * totalHorizontalPadding; + double availableWidth = screenWidth - totalMargin - 32; // 32 for additional safe padding + double boxWidth = (availableWidth / widget.maxLength).clamp(60.0, 200.0); // Reasonable limits List pinCodes = List.generate(widget.maxLength, (int i) { - return _buildPinCode(i, context, boxWidth); // Pass dynamic width + return Expanded( + child: Container( + margin: widget.pinBoxOuterPadding, + child: _buildPinCode(i, context, boxWidth), + ), + ); }); - return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: pinCodes, - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - ), + return Row( + children: pinCodes, + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, ); } @@ -353,14 +332,12 @@ class OTPWidgetState extends State with SingleTickerProviderStateMixi return Container( key: ValueKey("container$i"), alignment: Alignment.center, - margin: widget.pinBoxOuterPadding, padding: EdgeInsets.zero, decoration: BoxDecoration( color: bgColor, border: Border.all(color: borderColor, width: 1), borderRadius: BorderRadius.circular(16), ), - width: boxWidth, // Use dynamic width height: widget.pinBoxHeight, child: _animatedTextBox( strList[i], diff --git a/pubspec.yaml b/pubspec.yaml index 027f5d13..c61bdf0a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,9 +65,9 @@ dependencies: url: https://github.com/crasowas/hms-flutter-plugin.git path: flutter-hms-push # huawei_push: ^6.12.0+303 - # hijri_gregorian_calendar: - # path: /Users/aamir/StudioProjects/hijri_gregorian_calendar - hijri_gregorian_calendar: ^0.0.3 +# hijri_gregorian_calendar: +# path: /Users/aamir/StudioProjects/hijri_gregorian_calendar + hijri_gregorian_calendar: ^0.0.4 # Qr code Scanner location: ^8.0.1