From 8c4e082c573b53d6cd2a0849af1a1042c81a4b81 Mon Sep 17 00:00:00 2001 From: jahongireshonqulov Date: Sat, 1 Nov 2025 20:41:28 +0500 Subject: [PATCH] feat:resetting password done --- assets/icons/common/ic_clock.svg | 3 + assets/translations/app_en.arb | 2 +- assets/translations/app_ru.arb | 2 +- assets/translations/app_uz.arb | 2 +- lib/core/l10n/app_localizations.dart | 2 +- lib/core/l10n/app_localizations_en.dart | 2 +- lib/core/l10n/app_localizations_ru.dart | 2 +- lib/core/l10n/app_localizations_uz.dart | 2 +- lib/core/theme/app_colors.dart | 3 + lib/core/theme/app_icons.dart | 2 + lib/core/theme/app_theme_colors.dart | 6 + .../create_new_password_page.dart | 4 +- .../widgets/change_password_success.dart | 95 ++++++++++++++ .../widgets/create_new_password_body.dart | 124 +++++++++++++++++- .../widgets/forgot_password_body.dart | 2 + .../widgets/verify_account_body.dart | 11 +- .../widgets/app_text_form_field.dart | 7 +- .../presentation/widgets/w_back_button.dart | 6 +- lib/main.dart | 2 +- 19 files changed, 259 insertions(+), 20 deletions(-) create mode 100644 assets/icons/common/ic_clock.svg create mode 100644 lib/feature/auth/presentation/pages/create_new_password_page/widgets/change_password_success.dart diff --git a/assets/icons/common/ic_clock.svg b/assets/icons/common/ic_clock.svg new file mode 100644 index 0000000..32ed2cc --- /dev/null +++ b/assets/icons/common/ic_clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/translations/app_en.arb b/assets/translations/app_en.arb index 9c3e567..1b28a2f 100644 --- a/assets/translations/app_en.arb +++ b/assets/translations/app_en.arb @@ -21,7 +21,7 @@ }, "please_login": "Please login to your account", "email_or_phone": "Phone Number", - "enter_email_or_phone": "Enter your email or phone number", + "enter_email_or_phone": "Enter your phone number", "password": "Password", "enter_password": "Enter your password", "forgot_password": "Forgot Password?", diff --git a/assets/translations/app_ru.arb b/assets/translations/app_ru.arb index eb72bc0..6a1fc89 100644 --- a/assets/translations/app_ru.arb +++ b/assets/translations/app_ru.arb @@ -21,7 +21,7 @@ }, "please_login": "Пожалуйста, войдите в свой аккаунт", "email_or_phone": "Номер телефона", - "enter_email_or_phone": "Введите свою почту или номер телефона", + "enter_email_or_phone": "Введите свою номер телефона", "password": "Пароль", "enter_password": "Введите свой пароль", "forgot_password": "Забыли пароль?", diff --git a/assets/translations/app_uz.arb b/assets/translations/app_uz.arb index e63a256..810be9a 100644 --- a/assets/translations/app_uz.arb +++ b/assets/translations/app_uz.arb @@ -21,7 +21,7 @@ }, "please_login": "Iltimos, akkauntingizga kiring", "email_or_phone": "Telefon raqami", - "enter_email_or_phone": "Email yoki telefon raqamingizni kiriting", + "enter_email_or_phone": "Telefon raqamingizni kiriting", "password": "Parol", "enter_password": "Parolingizni kiriting", "forgot_password": "Parolni unutdingizmi?", diff --git a/lib/core/l10n/app_localizations.dart b/lib/core/l10n/app_localizations.dart index b5d288e..e442304 100644 --- a/lib/core/l10n/app_localizations.dart +++ b/lib/core/l10n/app_localizations.dart @@ -193,7 +193,7 @@ abstract class AppLocalizations { /// No description provided for @enter_email_or_phone. /// /// In en, this message translates to: - /// **'Enter your email or phone number'** + /// **'Enter your phone number'** String get enter_email_or_phone; /// No description provided for @password. diff --git a/lib/core/l10n/app_localizations_en.dart b/lib/core/l10n/app_localizations_en.dart index a29949e..586c410 100644 --- a/lib/core/l10n/app_localizations_en.dart +++ b/lib/core/l10n/app_localizations_en.dart @@ -62,7 +62,7 @@ class AppLocalizationsEn extends AppLocalizations { String get email_or_phone => 'Phone Number'; @override - String get enter_email_or_phone => 'Enter your email or phone number'; + String get enter_email_or_phone => 'Enter your phone number'; @override String get password => 'Password'; diff --git a/lib/core/l10n/app_localizations_ru.dart b/lib/core/l10n/app_localizations_ru.dart index c9a2178..9c098b6 100644 --- a/lib/core/l10n/app_localizations_ru.dart +++ b/lib/core/l10n/app_localizations_ru.dart @@ -60,7 +60,7 @@ class AppLocalizationsRu extends AppLocalizations { String get email_or_phone => 'Номер телефона'; @override - String get enter_email_or_phone => 'Введите свою почту или номер телефона'; + String get enter_email_or_phone => 'Введите свою номер телефона'; @override String get password => 'Пароль'; diff --git a/lib/core/l10n/app_localizations_uz.dart b/lib/core/l10n/app_localizations_uz.dart index bee7956..f7d5ef8 100644 --- a/lib/core/l10n/app_localizations_uz.dart +++ b/lib/core/l10n/app_localizations_uz.dart @@ -60,7 +60,7 @@ class AppLocalizationsUz extends AppLocalizations { String get email_or_phone => 'Telefon raqami'; @override - String get enter_email_or_phone => 'Email yoki telefon raqamingizni kiriting'; + String get enter_email_or_phone => 'Telefon raqamingizni kiriting'; @override String get password => 'Parol'; diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index 88d03c8..ff965c5 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -56,4 +56,7 @@ abstract class AppColors { static const Color c151B33 = Color(0xFF151B33); static const Color cE5E7EB = Color(0xFFE5E7EB); static const Color cE2E8F0 = Color(0xFFE2E8F0); + static const Color cDFE2EB = Color(0xFFDFE2EB); + static const Color c9FB6FA = Color(0xFF9FB6FA); + } diff --git a/lib/core/theme/app_icons.dart b/lib/core/theme/app_icons.dart index 4ec9ed3..6de39b4 100644 --- a/lib/core/theme/app_icons.dart +++ b/lib/core/theme/app_icons.dart @@ -13,6 +13,8 @@ abstract class AppIcons { static const String icCart1 = "$baseUrl/ic_cart1.svg"; static const String icTransactions = "$baseUrl/ic_transactions.svg"; static const String icProfile = "$baseUrl/ic_profile.svg"; + static const String icClock = "$baseUrl/ic_clock.svg"; + } abstract class AppLightSvgs { diff --git a/lib/core/theme/app_theme_colors.dart b/lib/core/theme/app_theme_colors.dart index b1b17e6..6ce5862 100644 --- a/lib/core/theme/app_theme_colors.dart +++ b/lib/core/theme/app_theme_colors.dart @@ -10,6 +10,7 @@ class AppThemeColors extends ThemeExtension { final Color inActiveColor; final Color inActiveColor1; final Color inActiveColor2; + final Color rippleColor; AppThemeColors({ required this.onBoardingColor, @@ -20,6 +21,7 @@ class AppThemeColors extends ThemeExtension { required this.inActiveColor, required this.inActiveColor1, required this.inActiveColor2, + required this.rippleColor, }); static AppThemeColors light = AppThemeColors( @@ -31,6 +33,7 @@ class AppThemeColors extends ThemeExtension { inActiveColor: AppColors.cE2E4EA, inActiveColor1: AppColors.cA9A9A9, inActiveColor2: AppColors.cE5E7EB, + rippleColor: AppColors.c9FB6FA, ); static AppThemeColors dark = AppThemeColors( @@ -42,6 +45,7 @@ class AppThemeColors extends ThemeExtension { inActiveColor: AppColors.c292F3D, inActiveColor1: AppColors.c626262, inActiveColor2: AppColors.c292F3D, + rippleColor: AppColors.cFF6F00, ); @override @@ -54,6 +58,7 @@ class AppThemeColors extends ThemeExtension { Color? inActiveColor, Color? inActiveColor1, Color? inActiveColor2, + Color? rippleColor, }) { return AppThemeColors( onBoardingColor: onBoardingColor ?? this.onBoardingColor, @@ -64,6 +69,7 @@ class AppThemeColors extends ThemeExtension { inActiveColor: inActiveColor ?? this.inActiveColor, inActiveColor1: inActiveColor1 ?? this.inActiveColor1, inActiveColor2: inActiveColor2 ?? this.inActiveColor2, + rippleColor: rippleColor ?? this.rippleColor, ); } diff --git a/lib/feature/auth/presentation/pages/create_new_password_page/create_new_password_page.dart b/lib/feature/auth/presentation/pages/create_new_password_page/create_new_password_page.dart index 6adcbb3..0dce854 100644 --- a/lib/feature/auth/presentation/pages/create_new_password_page/create_new_password_page.dart +++ b/lib/feature/auth/presentation/pages/create_new_password_page/create_new_password_page.dart @@ -1,3 +1,5 @@ +import 'package:food_delivery_client/feature/auth/presentation/pages/create_new_password_page/widgets/create_new_password_body.dart'; + import '../../../../../food_delivery_client.dart'; class CreateNewPasswordPage extends StatelessWidget { @@ -7,6 +9,6 @@ class CreateNewPasswordPage extends StatelessWidget { @override Widget build(BuildContext context) { - return WLayout(child: Scaffold()); + return CreateNewPasswordBody(phoneNumber: phoneNumber ); } } diff --git a/lib/feature/auth/presentation/pages/create_new_password_page/widgets/change_password_success.dart b/lib/feature/auth/presentation/pages/create_new_password_page/widgets/change_password_success.dart new file mode 100644 index 0000000..4261089 --- /dev/null +++ b/lib/feature/auth/presentation/pages/create_new_password_page/widgets/change_password_success.dart @@ -0,0 +1,95 @@ +import '../../../../../../food_delivery_client.dart'; + +class ChangePasswordSuccessPassword extends StatelessWidget { + const ChangePasswordSuccessPassword({super.key}); + + void show(BuildContext context) { + showModalBottomSheet( + context: context, + backgroundColor: AppColors.cTransparent, + enableDrag: false, + isDismissible: false, + useSafeArea: false, + builder: (context) => Wrap(children: [this]), + ); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: context.w, + child: DecoratedBox( + decoration: BoxDecoration( + color: context.theme.scaffoldBackgroundColor, + borderRadius: AppUtils.kBorderRadius30, + ), + child: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + 10.verticalSpace, + SizedBox( + height: 6, + width: 60, + child: DecoratedBox( + decoration: BoxDecoration( + color: AppColors.cDFE2EB, + borderRadius: AppUtils.kBorderRadius10, + ), + ), + ), + 54.verticalSpace, + SizedBox( + height: 162, + width: 162, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(160), + color: context.appThemeColors.rippleColor.newWithOpacity( + .2, + ), + ), + child: Center( + child: SizedBox( + height: 103.74, + width: 103.74, + child: DecoratedBox( + decoration: BoxDecoration( + color: AppColors.cFF6F00, + borderRadius: BorderRadius.circular(100), + ), + child: Center( + child: SvgPicture.asset(AppIcons.icClock), + ), + ), + ), + ), + ), + ), + 54.verticalSpace, + Text( + context.loc.changePasswordSuccess, + style: context.appThemeTextStyles.size24Bold, + textAlign: TextAlign.center, + ), + 14.verticalSpace, + Text( + context.loc.changePasswordMessage, + style: context.appThemeTextStyles.size14Regular, + textAlign: TextAlign.center, + ), + 65.verticalSpace, + AppButton( + name: context.loc.login, + onPressed: () { + context.go(Routes.login); + }, + ), + 15.verticalSpace, + ], + ).paddingSymmetric(horizontal: 24), + ), + ), + ); + } +} diff --git a/lib/feature/auth/presentation/pages/create_new_password_page/widgets/create_new_password_body.dart b/lib/feature/auth/presentation/pages/create_new_password_page/widgets/create_new_password_body.dart index 0a96a3b..8234284 100644 --- a/lib/feature/auth/presentation/pages/create_new_password_page/widgets/create_new_password_body.dart +++ b/lib/feature/auth/presentation/pages/create_new_password_page/widgets/create_new_password_body.dart @@ -1,10 +1,126 @@ -import '../../../../../../food_delivery_client.dart'; +import 'package:food_delivery_client/core/helpers/validator_helpers.dart'; +import 'package:food_delivery_client/feature/common/presentation/widgets/app_text_form_field.dart'; -class CreateNewPasswordBody extends StatelessWidget { - const CreateNewPasswordBody({super.key}); +import '../../../../../../food_delivery_client.dart'; +import 'change_password_success.dart'; + +class CreateNewPasswordBody extends StatefulWidget { + const CreateNewPasswordBody({super.key, required this.phoneNumber}); + + final String phoneNumber; + + @override + State createState() => _CreateNewPasswordBodyState(); +} + +class _CreateNewPasswordBodyState extends State { + late TextEditingController _passwordController; + late TextEditingController _repeatPasswordController; + final _formKey = GlobalKey(); + bool _isValid = false; + + void _validateForm() { + final isValid = _formKey.currentState?.validate() ?? false; + if (_isValid != isValid) { + setState(() { + _isValid = isValid; + }); + } + } + + @override + void initState() { + _passwordController = TextEditingController(); + _repeatPasswordController = TextEditingController(); + _passwordController.addListener(_validateForm); + _repeatPasswordController.addListener(_validateForm); + super.initState(); + } + + @override + void dispose() { + _passwordController.removeListener(_validateForm); + _repeatPasswordController.removeListener(_validateForm); + _passwordController.dispose(); + _repeatPasswordController.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { - return WLayout(child: Scaffold()); + return Form( + key: _formKey, + autovalidateMode: AutovalidateMode.onUserInteraction, + child: WLayout( + child: Scaffold( + resizeToAvoidBottomInset: true, + body: SingleChildScrollView( + keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, + physics: const NeverScrollableScrollPhysics(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 30.verticalSpace, + WBackButton(), + 20.verticalSpace, + Text( + context.loc.createNewPassword, + style: context.appThemeTextStyles.size24Bold, + ), + 8.verticalSpace, + Text( + context.loc.createNewPasswordSubtitle, + style: context.appThemeTextStyles.size14Regular, + ), + + 40.verticalSpace, + Text( + context.loc.newPassword, + style: context.appThemeTextStyles.size16Medium, + ), + 10.verticalSpace, + AppTextFormField( + obscureText: true, + controller: _passwordController, + keyBoardType: TextInputType.visiblePassword, + hintText: context.loc.enter_password, + validator: (value) { + return Validators.validatePassword( + _passwordController.text.trim(), + ); + }, + ), + 16.verticalSpace, + Text( + context.loc.confirmNewPassword, + style: context.appThemeTextStyles.size16Medium, + ), + 10.verticalSpace, + AppTextFormField( + obscureText: true, + controller: _repeatPasswordController, + keyBoardType: TextInputType.visiblePassword, + hintText: context.loc.enter_password, + validator: (value) { + return Validators.validateRepeatPassword( + _repeatPasswordController.text.trim(), + _passwordController.text.trim(), + ); + }, + ), + 130.verticalSpace, + AppButton( + name: context.loc.resetPassword, + isActive: _isValid, + onPressed: () { + ChangePasswordSuccessPassword().show(context); + }, + ), + ], + ).paddingSymmetric(horizontal: 24), + ), + ), + ), + ); } } diff --git a/lib/feature/auth/presentation/pages/forgot_password_page/widgets/forgot_password_body.dart b/lib/feature/auth/presentation/pages/forgot_password_page/widgets/forgot_password_body.dart index c5cc56a..4cadf6f 100644 --- a/lib/feature/auth/presentation/pages/forgot_password_page/widgets/forgot_password_body.dart +++ b/lib/feature/auth/presentation/pages/forgot_password_page/widgets/forgot_password_body.dart @@ -75,8 +75,10 @@ class _ForgotPasswordBodyState extends State { ), 10.verticalSpace, AppTextFormField( + controller: _phoneNumberController, keyBoardType: TextInputType.number, + hintText: context.loc.enter_email_or_phone, prefixIcon: Text( "+ 998", style: context.appThemeTextStyles.size14Regular, diff --git a/lib/feature/auth/presentation/pages/verify_account_page/widgets/verify_account_body.dart b/lib/feature/auth/presentation/pages/verify_account_page/widgets/verify_account_body.dart index 5eea5e0..5394623 100644 --- a/lib/feature/auth/presentation/pages/verify_account_page/widgets/verify_account_body.dart +++ b/lib/feature/auth/presentation/pages/verify_account_page/widgets/verify_account_body.dart @@ -98,7 +98,7 @@ class _VerifyAccountBodyState extends State { Pinput( autofocus: true, enabled: true, - length: 5, + length: 5, controller: _otpController, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -123,7 +123,14 @@ class _VerifyAccountBodyState extends State { AppButton( isActive: _isValid, name: context.loc.verifyAccount, - onPressed: () {}, + onPressed: () { + if (_formKey.currentState?.validate() ?? false) { + context.push( + Routes.createNewPassword, + extra: widget.phoneNumber, + ); + } + }, ), 20.verticalSpace, Align( diff --git a/lib/feature/common/presentation/widgets/app_text_form_field.dart b/lib/feature/common/presentation/widgets/app_text_form_field.dart index c2b4d02..fa98d10 100644 --- a/lib/feature/common/presentation/widgets/app_text_form_field.dart +++ b/lib/feature/common/presentation/widgets/app_text_form_field.dart @@ -92,7 +92,7 @@ class _AppTextFormFieldState extends State { widget.hintTextStyle ?? context.appThemeTextStyles.size14Regular.copyWith( color: AppColors.cA7AEC1, - ), + ), suffixIcon: widget.obscureText ? IconButton( onPressed: () { @@ -101,8 +101,9 @@ class _AppTextFormFieldState extends State { }); }, icon: SvgPicture.asset( - visibility ? AppIcons.icVisibility : AppIcons.icVisibilityOff, - color: AppColors.c000000, + visibility + ? AppIcons.icVisibility + : AppIcons.icVisibilityOff, ), ) : widget.suffixIcon, diff --git a/lib/feature/common/presentation/widgets/w_back_button.dart b/lib/feature/common/presentation/widgets/w_back_button.dart index 7d6386a..3f7ff20 100644 --- a/lib/feature/common/presentation/widgets/w_back_button.dart +++ b/lib/feature/common/presentation/widgets/w_back_button.dart @@ -6,7 +6,9 @@ class WBackButton extends StatelessWidget { @override Widget build(BuildContext context) { return InkWell( - onTap: () {}, + onTap: () { + context.pop(); + }, borderRadius: AppUtils.kBorderRadius22, child: Ink( height: 44, @@ -19,7 +21,7 @@ class WBackButton extends StatelessWidget { color: AppColors.cA7AEC1.newWithOpacity(.3), offset: const Offset(0, 4), blurRadius: 80, - ), + ), ], ), child: SvgPicture.asset( diff --git a/lib/main.dart b/lib/main.dart index d1319ad..a6ff3be 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -62,7 +62,7 @@ class _MyAppState extends State { debugShowCheckedModeBanner: false, theme: AppTheme.lightTheme, darkTheme: AppTheme.darkTheme, - themeMode: ThemeMode.dark, + themeMode: ThemeMode.light, // themeMode: themeState.themeMode, routerConfig: sl().router, locale: state.currentLocale,