From 7ff7f88e24c21bb2112e9666cee86dd662c42c30 Mon Sep 17 00:00:00 2001 From: Aamir Muhammad Date: Sun, 6 Jul 2025 15:21:46 +0300 Subject: [PATCH] updated app to latest flutter sdk with android native changes. --- assets/images/svg/smart-phone.svg | 4 + lib/config/config.dart | 4 +- .../otp/otp_validation_bootmsheet_widget.dart | 220 ++++++++++++++++++ .../health_calculator/carbs/carbs.dart | 93 +++++--- lib/pages/login/welcome.dart | 77 +++--- lib/widgets/mobile-no/mobile_no.dart | 5 +- 6 files changed, 330 insertions(+), 73 deletions(-) create mode 100644 assets/images/svg/smart-phone.svg create mode 100644 lib/new_ui/otp/otp_validation_bootmsheet_widget.dart diff --git a/assets/images/svg/smart-phone.svg b/assets/images/svg/smart-phone.svg new file mode 100644 index 00000000..a276f85f --- /dev/null +++ b/assets/images/svg/smart-phone.svg @@ -0,0 +1,4 @@ + + + + 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/new_ui/otp/otp_validation_bootmsheet_widget.dart b/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart new file mode 100644 index 00000000..41f30bbf --- /dev/null +++ b/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart @@ -0,0 +1,220 @@ +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart'; +import 'package:hmg_patient_app/uitl/translations_delegate_base.dart'; +import 'package:hmg_patient_app/widgets/mobile-no/mobile_no.dart'; +import 'package:hmg_patient_app/widgets/text/app_texts_widget.dart'; + +class OtpVerificationBottomSheet extends StatefulWidget { + final String countryCode; + final String initialPhoneNumber; + final Function(String phoneNumber, bool viaWhatsApp) onOtpRequested; + + const OtpVerificationBottomSheet({ + Key? key, + this.countryCode = "+966", + this.initialPhoneNumber = "", + required this.onOtpRequested, + }) : super(key: key); + + @override + _OtpVerificationBottomSheetState createState() => _OtpVerificationBottomSheetState(); +} + +class _OtpVerificationBottomSheetState extends State { + late TextEditingController _phoneController; + bool _viaWhatsApp = true; + + @override + void initState() { + super.initState(); + _phoneController = TextEditingController(text: widget.initialPhoneNumber); + } + + @override + void dispose() { + _phoneController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return 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("Enter Phone Number", fontSize: 28, letterSpacing: -2, fontFamily: 'poppins', color: Color(0xFF2E3039), fontWeight: FontWeight.w600), Icon(Icons.close_outlined)], + ), + const SizedBox(height: 10), + // Subtitle + AppText("Enter your phone number to receive OTP verification code", fontSize: 16, fontFamily: 'poppins', color: Color(0xFF2E3039), fontWeight: FontWeight.w500), + const SizedBox(height: 10), + _buildPhoneNumberSection(), + const SizedBox(height: 24), + _buildDeliveryMethodSection(), + ], + ), + ); + } + + Widget _buildPhoneNumberSection() { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Directionality( + textDirection: TextDirection.ltr, + child: inputWidget(TranslationBase.of(context).phoneNumber, "5xxxxxxxx", _phoneController, isEnable: true, prefix: "966", hasSelection: false, isBorderAllowed: false, isAllowLeadingIcon: true), + ), + ], + ); + } + + Widget _buildDeliveryMethodSection() { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // SMS Option + InkWell( + onTap: () { + setState(() { + _viaWhatsApp = false; + }); + }, + child: Row( + children: [ + CustomButton( + text: "Send me OTP on SMS", + onPressed: () { + setState(() { + _viaWhatsApp = false; + }); + }, + backgroundColor: Colors.red, + borderColor: Colors.red, + textColor: Colors.white, + borderRadius: 12, + padding: const EdgeInsets.fromLTRB(8, 16, 8, 16), + fontSize: 16, + fontFamily: 'poppins', + fontWeight: FontWeight.w500, + ), + ], + ), + ), + const SizedBox(height: 10), + // OR Divider + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child:AppText("OR", fontSize: 16, fontFamily: 'poppins', color: Color(0xFF2E3039), fontWeight: FontWeight.w500), + + ), + ], + ), + const SizedBox(height: 10), + InkWell( + onTap: () { + setState(() { + _viaWhatsApp = true; + }); + }, + child: Row( + children: [ + CustomButton( + text: "Send me OTP on WhatsApp", + onPressed: () { + setState(() { + _viaWhatsApp = true; + }); + }, + backgroundColor: Colors.white, + borderColor: Color(0xFF2E3039), + textColor: Color(0xFF2E3039), + borderRadius: 12, + padding: const EdgeInsets.fromLTRB(8, 16, 8, 16), + fontSize: 16, + borderWidth: 2, + fontFamily: 'poppins', + fontWeight: FontWeight.w500, + ), + ], + ), + ), + ], + ); + } +} + +class CustomButton extends StatelessWidget { + final String text; + final VoidCallback onPressed; + final Color backgroundColor; + final Color borderColor; + final Color textColor; + final double borderRadius; + final double borderWidth; + final EdgeInsetsGeometry padding; + final double fontSize; + final String fontFamily; + final FontWeight fontWeight; + final bool isDisabled; + + const CustomButton({ + Key? key, + required this.text, + required this.onPressed, + this.backgroundColor = Colors.red, + this.borderColor = Colors.red, + this.textColor = Colors.white, + this.borderRadius = 12, + this.borderWidth = 1, + this.padding = const EdgeInsets.fromLTRB(8, 16, 8, 16), + this.fontSize = 16, + this.fontFamily = 'poppins', + this.fontWeight = FontWeight.w500, + this.isDisabled = false, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Expanded( + child: GestureDetector( + onTap: isDisabled ? null : onPressed, + child: Container( + padding: padding, + decoration: BoxDecoration( + color: isDisabled ? backgroundColor.withOpacity(0.5) : backgroundColor, + borderRadius: BorderRadius.circular(borderRadius), + border: Border.all( + color: isDisabled ? borderColor.withOpacity(0.5) : borderColor, + width: borderWidth, + ), + ), + child: Center( + child: Text( + text, + style: TextStyle( + fontSize: fontSize, + fontFamily: fontFamily, + color: isDisabled ? textColor.withOpacity(0.5) : textColor, + fontWeight: fontWeight, + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart b/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart index 4d92cb0f..3699ed30 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/carbs/carbs.dart @@ -1,3 +1,4 @@ +import 'package:flutter_svg/svg.dart'; import 'package:hmg_patient_app/core/viewModels/project_view_model.dart'; import 'package:hmg_patient_app/pages/AlHabibMedicalService/health_calculator/calorie_calculator/calorie_calculator.dart'; import 'package:hmg_patient_app/theme/colors.dart'; @@ -260,7 +261,6 @@ class _CarbsState extends State { ); } - void openDropdown(GlobalKey key) { GestureDetector? detector; @@ -282,45 +282,62 @@ class _CarbsState extends State { detector!.onTap!(); } - - // void openDropdown(GlobalKey key) { - // GestureDetector detector; - // void searchForGestureDetector(BuildContext element) { - // element.visitChildElements((element) { - // if (element.widget != null && element.widget is GestureDetector) { - // detector = element.widget; - // return false; - // } else { - // searchForGestureDetector(element); - // } - // - // return true; - // }); - // } - // - // searchForGestureDetector(key.currentContext); - // assert(detector != null); - // - // detector.onTap(); - // } + +// void openDropdown(GlobalKey key) { +// GestureDetector detector; +// void searchForGestureDetector(BuildContext element) { +// element.visitChildElements((element) { +// if (element.widget != null && element.widget is GestureDetector) { +// detector = element.widget; +// return false; +// } else { +// searchForGestureDetector(element); +// } +// +// return true; +// }); +// } +// +// searchForGestureDetector(key.currentContext); +// assert(detector != null); +// +// detector.onTap(); +// } } -Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller, {String? prefix, bool isEnable = true, bool hasSelection = false}) { +Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller, + {String? prefix, bool isEnable = true, bool hasSelection = false, bool isBorderAllowed = true, bool isAllowLeadingIcon = false}) { return Container( padding: EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white, - border: Border.all( - color: Color(0xffefefef), - width: 1, - ), + border: isBorderAllowed + ? Border.all( + color: Color(0xffefefef), + width: 1, + ) + : null, ), child: InkWell( onTap: hasSelection ? () {} : null, child: Row( children: [ + if (isAllowLeadingIcon) + Container( + height: 40, + width: 40, + margin: EdgeInsets.only(right: 10), + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Color(0xFFEFEFF0), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + child: SvgPicture.asset("assets/images/svg/smart-phone.svg", width: 24,height: 24,), + ), Expanded( child: Column( mainAxisSize: MainAxisSize.min, @@ -329,10 +346,12 @@ Widget inputWidget(String _labelText, String _hintText, TextEditingController _c Text( _labelText, style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w600, - color: Color(0xff2B353E), - letterSpacing: -0.44, + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xff898A8D), + fontFamily: 'poppins', + letterSpacing: -0.2, + height: 18/12 ), ), TextField( @@ -344,9 +363,9 @@ Widget inputWidget(String _labelText, String _hintText, TextEditingController _c style: TextStyle( fontSize: 14, height: 21 / 14, - fontWeight: FontWeight.w400, - color: Color(0xff2B353E), - letterSpacing: -0.44, + fontWeight: FontWeight.w500, + color: Color(0xff2E3039), + letterSpacing: -0.2, ), decoration: InputDecoration( isDense: true, @@ -354,9 +373,9 @@ Widget inputWidget(String _labelText, String _hintText, TextEditingController _c hintStyle: TextStyle( fontSize: 14, height: 21 / 14, - fontWeight: FontWeight.w400, - color: Color(0xff575757), - letterSpacing: -0.56, + fontWeight: FontWeight.w500, + color: Color(0xff2E3039), + letterSpacing: -0.2, ), prefixIconConstraints: BoxConstraints(minWidth: 50), prefixIcon: prefix == null diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart index 4bf15073..356fded6 100644 --- a/lib/pages/login/welcome.dart +++ b/lib/pages/login/welcome.dart @@ -1,5 +1,6 @@ import 'package:hmg_patient_app/analytics/google-analytics.dart'; import 'package:hmg_patient_app/locator.dart'; +import 'package:hmg_patient_app/new_ui/otp/otp_validation_bootmsheet_widget.dart'; import 'package:hmg_patient_app/pages/login/login-type.dart'; import 'package:hmg_patient_app/pages/login/register.dart'; import 'package:hmg_patient_app/pages/login/register_new.dart'; @@ -41,7 +42,7 @@ class _WelcomeLogin extends State { padding: EdgeInsets.only(left: 21, right: 21), physics: BouncingScrollPhysics(), children: [ - SizedBox(height: 12), + SizedBox(height: 30), Row( children: [ SvgPicture.asset( @@ -51,26 +52,24 @@ class _WelcomeLogin extends State { ), ], ), - SizedBox(height: 24), - Text( - TranslationBase.of(context).welcome, - style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xff2B353E), letterSpacing: -1.44, height: 23 / 24), - ), - SizedBox(height: 16), - // Text( - // TranslationBase.of(context).welcomeText, - // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 23 / 16), - // ), - Text( - TranslationBase.of(context).welcomeText2, - style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 23 / 16), - ), - SizedBox( - height: 14, - ), ], ), ), + Expanded( + child: Container( + padding: EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21), + child: Column( + children: [ + Text( + // TranslationBase.of(context).welcome, + "Welcome to Dr. Sulaiman Al Habib Medical Group", + style: TextStyle(fontSize: 36, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.4, height: 47 / 36), + ), + SizedBox(height: 16) + ], + ), + ), + ), Container( color: Colors.white, padding: EdgeInsets.only(top: 16, bottom: 16, right: 21, left: 21), @@ -79,26 +78,40 @@ class _WelcomeLogin extends State { children: [ Expanded( child: DefaultButton( - TranslationBase.of(context).no, + TranslationBase.of(context).login, () => { - Navigator.of(context).push(FadePage(page: RegisterNew())), - locator().loginRegistration.visited_alhabib_group(false), + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => OtpVerificationBottomSheet( + countryCode: "+966", // Default is +966 as in your example + initialPhoneNumber: "574345434", // Optional initial value + onOtpRequested: (phoneNumber, viaWhatsApp) { + // Handle OTP request here + print("Requesting OTP for $phoneNumber via ${viaWhatsApp ? "WhatsApp" : "SMS"}"); + Navigator.pop(context); + }, + )) + + // Navigator.of(context).push(FadePage(page: RegisterNew())), + // locator().loginRegistration.visited_alhabib_group(false), }, color: CustomColors.accentColor, textColor: Colors.white, ), ), - SizedBox(width: 8), - Expanded( - child: DefaultButton( - TranslationBase.of(context).yes, - () => { - Navigator.of(context).push(FadePage(page: LoginType())), - locator().loginRegistration.visited_alhabib_group(true), - }, - color: CustomColors.green, - ), - ), + // SizedBox(width: 8), + // Expanded( + // child: DefaultButton( + // TranslationBase.of(context).yes, + // () => { + // Navigator.of(context).push(FadePage(page: LoginType())), + // locator().loginRegistration.visited_alhabib_group(true), + // }, + // color: CustomColors.green, + // ), + // ), ], ), ), diff --git a/lib/widgets/mobile-no/mobile_no.dart b/lib/widgets/mobile-no/mobile_no.dart index b248c4d1..e9ba63e6 100644 --- a/lib/widgets/mobile-no/mobile_no.dart +++ b/lib/widgets/mobile-no/mobile_no.dart @@ -15,8 +15,9 @@ class PhoneNumberSelectorWidget extends StatefulWidget { final String? mobileNo; bool isLiveCareTypeSelect; bool isEnable; + bool isShowCountrySelector; - PhoneNumberSelectorWidget({Key? key, this.onNumberChange, this.onCountryChange, this.mobileNo, this.isLiveCareTypeSelect = false, this.isEnable = true}) : super(key: key); + PhoneNumberSelectorWidget({Key? key, this.onNumberChange, this.onCountryChange, this.mobileNo, this.isLiveCareTypeSelect = false, this.isEnable = true, this.isShowCountrySelector = true}) : super(key: key); @override _PhoneNumberSelectorWidgetState createState() { @@ -58,7 +59,7 @@ class _PhoneNumberSelectorWidgetState extends State { return Column( children: [ - inputWidget(TranslationBase.of(context).country, countryName!, isEnable: true, hasSelection: true), + widget.isShowCountrySelector ? inputWidget(TranslationBase.of(context).country, countryName!, isEnable: true, hasSelection: true) : SizedBox(), SizedBox(height: 12), Directionality(textDirection: TextDirection.ltr, child: inputWidget(TranslationBase.of(context).phoneNumber, isEnable: widget.isEnable, widget.mobileNo ?? "5xxxxxxxx", prefix: countryCode)), ],