Compare commits

...

2 Commits

Author SHA1 Message Date
jahongireshonqulov
8c4e082c57 feat:resetting password done 2025-11-01 20:41:28 +05:00
jahongireshonqulov
c5a6c2dbed feat:verify your account page ui done 2025-11-01 18:33:03 +05:00
26 changed files with 1015 additions and 34 deletions

View File

@@ -0,0 +1,3 @@
<svg width="49" height="56" viewBox="0 0 49 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M39.3392 31.4713C40.2309 31.4713 41.0963 31.5762 41.9618 31.7074V23.6035C41.9618 22.2124 41.4092 20.8782 40.4255 19.8946C39.4418 18.9109 38.1077 18.3583 36.7166 18.3583H34.0939V13.1131C34.0939 5.87465 28.2193 0 20.9809 0C13.7425 0 7.86783 5.87465 7.86783 13.1131V18.3583H5.24522C3.8541 18.3583 2.51996 18.9109 1.53629 19.8946C0.55262 20.8782 0 22.2124 0 23.6035V49.8296C0 52.7407 2.33412 55.0748 5.24522 55.0748H25.7278C24.3903 52.7669 23.6035 50.0919 23.6035 47.207C23.6035 38.5262 30.6583 31.4713 39.3392 31.4713ZM13.1131 13.1131C13.1131 8.75952 16.6274 5.24522 20.9809 5.24522C25.3344 5.24522 28.8487 8.75952 28.8487 13.1131V18.3583H13.1131V13.1131ZM20.9809 41.9618C19.9435 41.9618 18.9294 41.6542 18.0668 41.0778C17.2042 40.5015 16.5319 39.6823 16.1349 38.7238C15.7379 37.7654 15.6341 36.7107 15.8365 35.6933C16.0388 34.6758 16.5384 33.7412 17.272 33.0076C18.0055 32.2741 18.9401 31.7745 19.9576 31.5721C20.9751 31.3697 22.0297 31.4736 22.9881 31.8706C23.9466 32.2676 24.7658 32.9399 25.3421 33.8025C25.9185 34.665 26.2261 35.6792 26.2261 36.7166C26.2261 39.6277 23.892 41.9618 20.9809 41.9618ZM48.5183 42.6174L36.0609 55.0748L28.8487 47.207L31.891 44.1648L36.0609 48.3347L45.4761 38.9196L48.5183 42.6174Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -21,7 +21,7 @@
}, },
"please_login": "Please login to your account", "please_login": "Please login to your account",
"email_or_phone": "Phone Number", "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", "password": "Password",
"enter_password": "Enter your password", "enter_password": "Enter your password",
"forgot_password": "Forgot Password?", "forgot_password": "Forgot Password?",
@@ -35,6 +35,25 @@
"discover": "Discover", "discover": "Discover",
"cart": "Cart", "cart": "Cart",
"transactions": "Transactions", "transactions": "Transactions",
"profile": "Profile" "profile": "Profile",
"forgotPassword": "Forgot Password",
"forgotPasswordSubtitle": "Please enter your phone number to reset your password.",
"phoneNumber": "Phone Number",
"sendCode": "Send Code",
"verifyYourAccount": "Verify Your Account",
"verifyAccountSubtitle": "Weve sent a verification code to",
"verifyAccount": "Verify Account",
"didNotReceiveCode": "Didnt receive the code?",
"resend": "Resend",
"createNewPassword": "Create New Password",
"createNewPasswordSubtitle": "Please create your new password.",
"oldPassword": "Old Password",
"newPassword": "New Password",
"confirmNewPassword": "Confirm New Password",
"passwordHint": "*Password must have at least 8 characters, including number and symbol.",
"resetPassword": "Reset Password",
"changePasswordSuccess": "Change Password Success",
"changePasswordMessage": "We have updated your password. Please remember your password, thank you!",
"login": "Login"
} }

View File

@@ -21,7 +21,7 @@
}, },
"please_login": "Пожалуйста, войдите в свой аккаунт", "please_login": "Пожалуйста, войдите в свой аккаунт",
"email_or_phone": "Номер телефона", "email_or_phone": "Номер телефона",
"enter_email_or_phone": "Введите свою почту или номер телефона", "enter_email_or_phone": "Введите свою номер телефона",
"password": "Пароль", "password": "Пароль",
"enter_password": "Введите свой пароль", "enter_password": "Введите свой пароль",
"forgot_password": "Забыли пароль?", "forgot_password": "Забыли пароль?",
@@ -35,6 +35,25 @@
"discover": "Обзор", "discover": "Обзор",
"cart": "Корзина", "cart": "Корзина",
"transactions": "Транзакции", "transactions": "Транзакции",
"profile": "Профиль" "profile": "Профиль",
"forgotPassword": "Забыли пароль",
"forgotPasswordSubtitle": "Пожалуйста, введите свой номер телефона, чтобы сбросить пароль.",
"phoneNumber": "Номер телефона",
"sendCode": "Отправить код",
"verifyYourAccount": "Подтвердите аккаунт",
"verifyAccountSubtitle": "Мы отправили код подтверждения на",
"verifyAccount": "Подтвердить",
"didNotReceiveCode": "Не получили код?",
"resend": "Отправить повторно",
"createNewPassword": "Создайте новый пароль",
"createNewPasswordSubtitle": "Пожалуйста, создайте новый пароль.",
"oldPassword": "Старый пароль",
"newPassword": "Новый пароль",
"confirmNewPassword": "Подтвердите пароль",
"passwordHint": "*Пароль должен содержать не менее 8 символов, включая цифры и символы.",
"resetPassword": "Сбросить пароль",
"changePasswordSuccess": "Пароль успешно изменён",
"changePasswordMessage": "Ваш пароль был обновлён. Пожалуйста, запомните его. Спасибо!",
"login": "Войти"
} }

View File

@@ -21,7 +21,7 @@
}, },
"please_login": "Iltimos, akkauntingizga kiring", "please_login": "Iltimos, akkauntingizga kiring",
"email_or_phone": "Telefon raqami", "email_or_phone": "Telefon raqami",
"enter_email_or_phone": "Email yoki telefon raqamingizni kiriting", "enter_email_or_phone": "Telefon raqamingizni kiriting",
"password": "Parol", "password": "Parol",
"enter_password": "Parolingizni kiriting", "enter_password": "Parolingizni kiriting",
"forgot_password": "Parolni unutdingizmi?", "forgot_password": "Parolni unutdingizmi?",
@@ -35,6 +35,25 @@
"discover": "Kashf etish", "discover": "Kashf etish",
"cart": "Savat", "cart": "Savat",
"transactions": "Tranzaksiyalar", "transactions": "Tranzaksiyalar",
"profile": "Profil" "profile": "Profil",
"forgotPassword": "Parolni unutdingizmi",
"forgotPasswordSubtitle": "Parolingizni tiklash uchun telefon raqamingizni kiriting.",
"phoneNumber": "Telefon raqami",
"sendCode": "Kod yuborish",
"verifyYourAccount": "Hisobni tasdiqlang",
"verifyAccountSubtitle": "Tasdiqlash kodi quyidagi raqamga yuborildi",
"verifyAccount": "Hisobni tasdiqlash",
"didNotReceiveCode": "Kod kelmadimi?",
"resend": "Qayta yuborish",
"createNewPassword": "Yangi parol yarating",
"createNewPasswordSubtitle": "Iltimos, yangi parolingizni yarating.",
"oldPassword": "Eski parol",
"newPassword": "Yangi parol",
"confirmNewPassword": "Parolni tasdiqlang",
"passwordHint": "*Parol kamida 8 ta belgi, raqam va belgidan iborat bolishi kerak.",
"resetPassword": "Parolni tiklash",
"changePasswordSuccess": "Parol muvaffaqiyatli ozgartirildi",
"changePasswordMessage": "Parolingiz yangilandi. Iltimos, uni eslab qoling. Rahmat!",
"login": "Kirish"
} }

View File

@@ -0,0 +1,22 @@
class StringHelpers {
static String formatUzbekPhoneNumber(String input) {
final digits = input.replaceAll(RegExp(r'\D'), '');
String formatted = digits;
if (formatted.startsWith('998')) {
formatted = formatted.substring(3);
} else if (formatted.startsWith('8')) {
formatted = formatted.substring(1);
}
final buffer = StringBuffer('+998 ');
for (int i = 0; i < formatted.length && i < 9; i++) {
buffer.write(formatted[i]);
if (i == 1 || i == 4 || i == 6) {
buffer.write(' ');
}
}
return buffer.toString().trim();
}
}

View File

@@ -193,7 +193,7 @@ abstract class AppLocalizations {
/// No description provided for @enter_email_or_phone. /// No description provided for @enter_email_or_phone.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Enter your email or phone number'** /// **'Enter your phone number'**
String get enter_email_or_phone; String get enter_email_or_phone;
/// No description provided for @password. /// No description provided for @password.
@@ -279,6 +279,114 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Profile'** /// **'Profile'**
String get profile; String get profile;
/// No description provided for @forgotPassword.
///
/// In en, this message translates to:
/// **'Forgot Password'**
String get forgotPassword;
/// No description provided for @forgotPasswordSubtitle.
///
/// In en, this message translates to:
/// **'Please enter your phone number to reset your password.'**
String get forgotPasswordSubtitle;
/// No description provided for @phoneNumber.
///
/// In en, this message translates to:
/// **'Phone Number'**
String get phoneNumber;
/// No description provided for @sendCode.
///
/// In en, this message translates to:
/// **'Send Code'**
String get sendCode;
/// No description provided for @verifyYourAccount.
///
/// In en, this message translates to:
/// **'Verify Your Account'**
String get verifyYourAccount;
/// No description provided for @verifyAccountSubtitle.
///
/// In en, this message translates to:
/// **'Weve sent a verification code to'**
String get verifyAccountSubtitle;
/// No description provided for @verifyAccount.
///
/// In en, this message translates to:
/// **'Verify Account'**
String get verifyAccount;
/// No description provided for @didNotReceiveCode.
///
/// In en, this message translates to:
/// **'Didnt receive the code?'**
String get didNotReceiveCode;
/// No description provided for @resend.
///
/// In en, this message translates to:
/// **'Resend'**
String get resend;
/// No description provided for @createNewPassword.
///
/// In en, this message translates to:
/// **'Create New Password'**
String get createNewPassword;
/// No description provided for @createNewPasswordSubtitle.
///
/// In en, this message translates to:
/// **'Please create your new password.'**
String get createNewPasswordSubtitle;
/// No description provided for @oldPassword.
///
/// In en, this message translates to:
/// **'Old Password'**
String get oldPassword;
/// No description provided for @newPassword.
///
/// In en, this message translates to:
/// **'New Password'**
String get newPassword;
/// No description provided for @confirmNewPassword.
///
/// In en, this message translates to:
/// **'Confirm New Password'**
String get confirmNewPassword;
/// No description provided for @passwordHint.
///
/// In en, this message translates to:
/// **'*Password must have at least 8 characters, including number and symbol.'**
String get passwordHint;
/// No description provided for @resetPassword.
///
/// In en, this message translates to:
/// **'Reset Password'**
String get resetPassword;
/// No description provided for @changePasswordSuccess.
///
/// In en, this message translates to:
/// **'Change Password Success'**
String get changePasswordSuccess;
/// No description provided for @changePasswordMessage.
///
/// In en, this message translates to:
/// **'We have updated your password. Please remember your password, thank you!'**
String get changePasswordMessage;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View File

@@ -62,7 +62,7 @@ class AppLocalizationsEn extends AppLocalizations {
String get email_or_phone => 'Phone Number'; String get email_or_phone => 'Phone Number';
@override @override
String get enter_email_or_phone => 'Enter your email or phone number'; String get enter_email_or_phone => 'Enter your phone number';
@override @override
String get password => 'Password'; String get password => 'Password';
@@ -105,4 +105,61 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get profile => 'Profile'; String get profile => 'Profile';
@override
String get forgotPassword => 'Forgot Password';
@override
String get forgotPasswordSubtitle =>
'Please enter your phone number to reset your password.';
@override
String get phoneNumber => 'Phone Number';
@override
String get sendCode => 'Send Code';
@override
String get verifyYourAccount => 'Verify Your Account';
@override
String get verifyAccountSubtitle => 'Weve sent a verification code to';
@override
String get verifyAccount => 'Verify Account';
@override
String get didNotReceiveCode => 'Didnt receive the code?';
@override
String get resend => 'Resend';
@override
String get createNewPassword => 'Create New Password';
@override
String get createNewPasswordSubtitle => 'Please create your new password.';
@override
String get oldPassword => 'Old Password';
@override
String get newPassword => 'New Password';
@override
String get confirmNewPassword => 'Confirm New Password';
@override
String get passwordHint =>
'*Password must have at least 8 characters, including number and symbol.';
@override
String get resetPassword => 'Reset Password';
@override
String get changePasswordSuccess => 'Change Password Success';
@override
String get changePasswordMessage =>
'We have updated your password. Please remember your password, thank you!';
} }

View File

@@ -60,7 +60,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get email_or_phone => 'Номер телефона'; String get email_or_phone => 'Номер телефона';
@override @override
String get enter_email_or_phone => 'Введите свою почту или номер телефона'; String get enter_email_or_phone => 'Введите свою номер телефона';
@override @override
String get password => 'Пароль'; String get password => 'Пароль';
@@ -103,4 +103,61 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get profile => 'Профиль'; String get profile => 'Профиль';
@override
String get forgotPassword => 'Забыли пароль';
@override
String get forgotPasswordSubtitle =>
'Пожалуйста, введите свой номер телефона, чтобы сбросить пароль.';
@override
String get phoneNumber => 'Номер телефона';
@override
String get sendCode => 'Отправить код';
@override
String get verifyYourAccount => 'Подтвердите аккаунт';
@override
String get verifyAccountSubtitle => 'Мы отправили код подтверждения на';
@override
String get verifyAccount => 'Подтвердить';
@override
String get didNotReceiveCode => 'Не получили код?';
@override
String get resend => 'Отправить повторно';
@override
String get createNewPassword => 'Создайте новый пароль';
@override
String get createNewPasswordSubtitle => 'Пожалуйста, создайте новый пароль.';
@override
String get oldPassword => 'Старый пароль';
@override
String get newPassword => 'Новый пароль';
@override
String get confirmNewPassword => 'Подтвердите пароль';
@override
String get passwordHint =>
'*Пароль должен содержать не менее 8 символов, включая цифры и символы.';
@override
String get resetPassword => 'Сбросить пароль';
@override
String get changePasswordSuccess => 'Пароль успешно изменён';
@override
String get changePasswordMessage =>
'Ваш пароль был обновлён. Пожалуйста, запомните его. Спасибо!';
} }

View File

@@ -60,7 +60,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get email_or_phone => 'Telefon raqami'; String get email_or_phone => 'Telefon raqami';
@override @override
String get enter_email_or_phone => 'Email yoki telefon raqamingizni kiriting'; String get enter_email_or_phone => 'Telefon raqamingizni kiriting';
@override @override
String get password => 'Parol'; String get password => 'Parol';
@@ -103,4 +103,63 @@ class AppLocalizationsUz extends AppLocalizations {
@override @override
String get profile => 'Profil'; String get profile => 'Profil';
@override
String get forgotPassword => 'Parolni unutdingizmi';
@override
String get forgotPasswordSubtitle =>
'Parolingizni tiklash uchun telefon raqamingizni kiriting.';
@override
String get phoneNumber => 'Telefon raqami';
@override
String get sendCode => 'Kod yuborish';
@override
String get verifyYourAccount => 'Hisobni tasdiqlang';
@override
String get verifyAccountSubtitle =>
'Tasdiqlash kodi quyidagi raqamga yuborildi';
@override
String get verifyAccount => 'Hisobni tasdiqlash';
@override
String get didNotReceiveCode => 'Kod kelmadimi?';
@override
String get resend => 'Qayta yuborish';
@override
String get createNewPassword => 'Yangi parol yarating';
@override
String get createNewPasswordSubtitle =>
'Iltimos, yangi parolingizni yarating.';
@override
String get oldPassword => 'Eski parol';
@override
String get newPassword => 'Yangi parol';
@override
String get confirmNewPassword => 'Parolni tasdiqlang';
@override
String get passwordHint =>
'*Parol kamida 8 ta belgi, raqam va belgidan iborat bolishi kerak.';
@override
String get resetPassword => 'Parolni tiklash';
@override
String get changePasswordSuccess => 'Parol muvaffaqiyatli ozgartirildi';
@override
String get changePasswordMessage =>
'Parolingiz yangilandi. Iltimos, uni eslab qoling. Rahmat!';
} }

View File

@@ -1,5 +1,8 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/create_new_password_page/create_new_password_page.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/forgot_password_page/forgot_password_page.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/login_page/login_page.dart'; import 'package:food_delivery_client/feature/auth/presentation/pages/login_page/login_page.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/verify_account_page/verify_account_page.dart';
import 'package:food_delivery_client/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart'; import 'package:food_delivery_client/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart';
import 'package:food_delivery_client/feature/onboarding/presentation/pages/splash_page/splash_page.dart'; import 'package:food_delivery_client/feature/onboarding/presentation/pages/splash_page/splash_page.dart';
@@ -30,6 +33,23 @@ class AppRoutes {
path: Routes.main, path: Routes.main,
pageBuilder: (context, state) => CupertinoPage(child: MainPage()), pageBuilder: (context, state) => CupertinoPage(child: MainPage()),
), ),
GoRoute(
path: Routes.forgotPassword,
pageBuilder: (context, state) =>
CupertinoPage(child: ForgotPasswordPage()),
),
GoRoute(
path: Routes.verifyAccount,
pageBuilder: (context, state) => CupertinoPage(
child: VerifyAccountPage(phoneNumber: state.extra as String),
),
),
GoRoute(
path: Routes.createNewPassword,
pageBuilder: (context, state) => CupertinoPage(
child: CreateNewPasswordPage(phoneNumber: state.extra as String),
),
),
], ],
); );
} }

View File

@@ -4,12 +4,7 @@ abstract class Routes {
static const String login = '/login'; static const String login = '/login';
static const String register = '/register'; static const String register = '/register';
static const String main = '/main'; static const String main = '/main';
static const String categories = '/categories'; static const String createNewPassword = '/create-new-password';
static const String filters = '/filters'; static const String forgotPassword = '/forgot-password';
static const String browse = '/browse'; static const String verifyAccount = '/verify-account';
static const String forgotPassword = "/forgot-password";
static const String restaurantsByCategory = '/restaurants-by-category';
static const String verifyPhoneNumber = "/verify-phone-number";
static const String verifyOtpCode = "/verify-otp-code";
static const String resetPassword = "/reset-password";
} }

View File

@@ -55,6 +55,8 @@ abstract class AppColors {
static const Color cA7AEC1 = Color(0xFFA7AEC1); static const Color cA7AEC1 = Color(0xFFA7AEC1);
static const Color c151B33 = Color(0xFF151B33); static const Color c151B33 = Color(0xFF151B33);
static const Color cE5E7EB = Color(0xFFE5E7EB); static const Color cE5E7EB = Color(0xFFE5E7EB);
static const Color cE2E8F0 = Color(0xFFE2E8F0);
static const Color cDFE2EB = Color(0xFFDFE2EB);
static const Color c9FB6FA = Color(0xFF9FB6FA);
} }

View File

@@ -13,6 +13,8 @@ abstract class AppIcons {
static const String icCart1 = "$baseUrl/ic_cart1.svg"; static const String icCart1 = "$baseUrl/ic_cart1.svg";
static const String icTransactions = "$baseUrl/ic_transactions.svg"; static const String icTransactions = "$baseUrl/ic_transactions.svg";
static const String icProfile = "$baseUrl/ic_profile.svg"; static const String icProfile = "$baseUrl/ic_profile.svg";
static const String icClock = "$baseUrl/ic_clock.svg";
} }
abstract class AppLightSvgs { abstract class AppLightSvgs {

View File

@@ -10,8 +10,7 @@ class AppThemeColors extends ThemeExtension<AppThemeColors> {
final Color inActiveColor; final Color inActiveColor;
final Color inActiveColor1; final Color inActiveColor1;
final Color inActiveColor2; final Color inActiveColor2;
final Color rippleColor;
AppThemeColors({ AppThemeColors({
required this.onBoardingColor, required this.onBoardingColor,
@@ -22,7 +21,7 @@ class AppThemeColors extends ThemeExtension<AppThemeColors> {
required this.inActiveColor, required this.inActiveColor,
required this.inActiveColor1, required this.inActiveColor1,
required this.inActiveColor2, required this.inActiveColor2,
required this.rippleColor,
}); });
static AppThemeColors light = AppThemeColors( static AppThemeColors light = AppThemeColors(
@@ -33,7 +32,8 @@ class AppThemeColors extends ThemeExtension<AppThemeColors> {
borderColor: AppColors.cE2E4EA, borderColor: AppColors.cE2E4EA,
inActiveColor: AppColors.cE2E4EA, inActiveColor: AppColors.cE2E4EA,
inActiveColor1: AppColors.cA9A9A9, inActiveColor1: AppColors.cA9A9A9,
inActiveColor2: AppColors.cE5E7EB inActiveColor2: AppColors.cE5E7EB,
rippleColor: AppColors.c9FB6FA,
); );
static AppThemeColors dark = AppThemeColors( static AppThemeColors dark = AppThemeColors(
@@ -44,7 +44,8 @@ class AppThemeColors extends ThemeExtension<AppThemeColors> {
borderColor: AppColors.c292F3D, borderColor: AppColors.c292F3D,
inActiveColor: AppColors.c292F3D, inActiveColor: AppColors.c292F3D,
inActiveColor1: AppColors.c626262, inActiveColor1: AppColors.c626262,
inActiveColor2: AppColors.c292F3D inActiveColor2: AppColors.c292F3D,
rippleColor: AppColors.cFF6F00,
); );
@override @override
@@ -57,7 +58,7 @@ class AppThemeColors extends ThemeExtension<AppThemeColors> {
Color? inActiveColor, Color? inActiveColor,
Color? inActiveColor1, Color? inActiveColor1,
Color? inActiveColor2, Color? inActiveColor2,
Color? rippleColor,
}) { }) {
return AppThemeColors( return AppThemeColors(
onBoardingColor: onBoardingColor ?? this.onBoardingColor, onBoardingColor: onBoardingColor ?? this.onBoardingColor,
@@ -67,7 +68,8 @@ class AppThemeColors extends ThemeExtension<AppThemeColors> {
borderColor: borderColor ?? this.borderColor, borderColor: borderColor ?? this.borderColor,
inActiveColor: inActiveColor ?? this.inActiveColor, inActiveColor: inActiveColor ?? this.inActiveColor,
inActiveColor1: inActiveColor1 ?? this.inActiveColor1, inActiveColor1: inActiveColor1 ?? this.inActiveColor1,
inActiveColor2: inActiveColor2??this.inActiveColor2 inActiveColor2: inActiveColor2 ?? this.inActiveColor2,
rippleColor: rippleColor ?? this.rippleColor,
); );
} }

View File

@@ -5,6 +5,8 @@ import 'package:food_delivery_client/core/core.dart';
class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> { class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
//Regular fonts //Regular fonts
final TextStyle size14Regular; final TextStyle size14Regular;
final TextStyle size14Regular1;
//Medium //Medium
@@ -14,6 +16,8 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
final TextStyle size16SemiBold; final TextStyle size16SemiBold;
final TextStyle size24SemiBold; final TextStyle size24SemiBold;
final TextStyle size24SemiBold1;
//Bold //Bold
@@ -25,9 +29,11 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
AppThemeTextStyles({ AppThemeTextStyles({
required this.size14Regular, required this.size14Regular,
required this.size14Regular1,
required this.size16Medium, required this.size16Medium,
required this.size16SemiBold, required this.size16SemiBold,
required this.size24SemiBold, required this.size24SemiBold,
required this.size24SemiBold1,
required this.size14Bold, required this.size14Bold,
required this.size24Bold, required this.size24Bold,
required this.size64Black, required this.size64Black,
@@ -47,6 +53,13 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
fontFamily: _fontRegular, fontFamily: _fontRegular,
color: AppColors.c151B33, color: AppColors.c151B33,
), ),
size14Regular1: TextStyle(
fontSize: 14,
height: 1.6,
fontWeight: FontWeight.w400,
fontFamily: _fontRegular,
color: AppColors.c151B33,
),
size16Medium: TextStyle( size16Medium: TextStyle(
fontSize: 16, fontSize: 16,
height: 1.3, height: 1.3,
@@ -67,6 +80,14 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
fontFamily: _fontSemiBold, fontFamily: _fontSemiBold,
color: AppColors.c1A202C, color: AppColors.c1A202C,
), ),
size24SemiBold1: TextStyle(
fontSize: 24,
height: 1.25,
letterSpacing: -.48,
fontWeight: FontWeight.w600,
fontFamily: _fontSemiBold,
color: AppColors.c000000,
),
size14Bold: TextStyle( size14Bold: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
@@ -95,6 +116,13 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
fontFamily: _fontRegular, fontFamily: _fontRegular,
color: AppColors.cFFFFFF, color: AppColors.cFFFFFF,
), ),
size14Regular1: TextStyle(
fontSize: 14,
height: 1.6,
fontWeight: FontWeight.w400,
fontFamily: _fontRegular,
color: AppColors.cA9A9A9,
),
size16Medium: TextStyle( size16Medium: TextStyle(
fontSize: 16, fontSize: 16,
height: 1.3, height: 1.3,
@@ -115,6 +143,14 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
fontFamily: _fontSemiBold, fontFamily: _fontSemiBold,
color: AppColors.cFFFFFF, color: AppColors.cFFFFFF,
), ),
size24SemiBold1: TextStyle(
fontSize: 24,
height: 1.25,
letterSpacing: -.48,
fontWeight: FontWeight.w600,
fontFamily: _fontSemiBold,
color: AppColors.cFFFFFF,
),
size14Bold: TextStyle( size14Bold: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
@@ -138,18 +174,22 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
@override @override
ThemeExtension<AppThemeTextStyles> copyWith({ ThemeExtension<AppThemeTextStyles> copyWith({
TextStyle? size14Regular, TextStyle? size14Regular,
TextStyle? size14Regular1,
TextStyle? size16Medium, TextStyle? size16Medium,
TextStyle? size16SemiBold, TextStyle? size16SemiBold,
TextStyle? size24SemiBold, TextStyle? size24SemiBold,
TextStyle? size24SemiBold1,
TextStyle? size14Bold, TextStyle? size14Bold,
TextStyle? size24Bold, TextStyle? size24Bold,
TextStyle? size64Black, TextStyle? size64Black,
}) { }) {
return AppThemeTextStyles( return AppThemeTextStyles(
size14Regular: size14Regular ?? this.size14Regular, size14Regular: size14Regular ?? this.size14Regular,
size14Regular1: size14Regular1 ?? this.size14Regular1,
size16Medium: size16Medium ?? this.size16Medium, size16Medium: size16Medium ?? this.size16Medium,
size16SemiBold: size16SemiBold ?? this.size16SemiBold, size16SemiBold: size16SemiBold ?? this.size16SemiBold,
size24SemiBold: size24SemiBold ?? this.size24SemiBold, size24SemiBold: size24SemiBold ?? this.size24SemiBold,
size24SemiBold1: size24SemiBold1 ?? this.size24SemiBold1,
size14Bold: size14Bold ?? this.size14Bold, size14Bold: size14Bold ?? this.size14Bold,
size24Bold: size24Bold ?? this.size24Bold, size24Bold: size24Bold ?? this.size24Bold,
size64Black: size64Black ?? this.size64Black, size64Black: size64Black ?? this.size64Black,
@@ -164,9 +204,11 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
if (other is! AppThemeTextStyles) return this; if (other is! AppThemeTextStyles) return this;
return AppThemeTextStyles( return AppThemeTextStyles(
size14Regular: TextStyle.lerp(size14Regular, other.size14Regular, t)!, size14Regular: TextStyle.lerp(size14Regular, other.size14Regular, t)!,
size14Regular1: TextStyle.lerp(size14Regular1, other.size14Regular1, t)!,
size16Medium: TextStyle.lerp(size16Medium, other.size16Medium, t)!, size16Medium: TextStyle.lerp(size16Medium, other.size16Medium, t)!,
size16SemiBold: TextStyle.lerp(size16SemiBold, other.size16SemiBold, t)!, size16SemiBold: TextStyle.lerp(size16SemiBold, other.size16SemiBold, t)!,
size24SemiBold: TextStyle.lerp(size24SemiBold, other.size24SemiBold, t)!, size24SemiBold: TextStyle.lerp(size24SemiBold, other.size24SemiBold, t)!,
size24SemiBold1: TextStyle.lerp(size24SemiBold1, other.size24SemiBold1, t)!,
size14Bold: TextStyle.lerp(size14Bold, other.size14Bold, t)!, size14Bold: TextStyle.lerp(size14Bold, other.size14Bold, t)!,
size24Bold: TextStyle.lerp(size24Bold, other.size24Bold, t)!, size24Bold: TextStyle.lerp(size24Bold, other.size24Bold, t)!,
size64Black: TextStyle.lerp(size64Black, other.size64Black, t)!, size64Black: TextStyle.lerp(size64Black, other.size64Black, t)!,

View File

@@ -0,0 +1,14 @@
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 {
const CreateNewPasswordPage({super.key, required this.phoneNumber});
final String phoneNumber;
@override
Widget build(BuildContext context) {
return CreateNewPasswordBody(phoneNumber: phoneNumber );
}
}

View File

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

View File

@@ -0,0 +1,126 @@
import 'package:food_delivery_client/core/helpers/validator_helpers.dart';
import 'package:food_delivery_client/feature/common/presentation/widgets/app_text_form_field.dart';
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<CreateNewPasswordBody> createState() => _CreateNewPasswordBodyState();
}
class _CreateNewPasswordBodyState extends State<CreateNewPasswordBody> {
late TextEditingController _passwordController;
late TextEditingController _repeatPasswordController;
final _formKey = GlobalKey<FormState>();
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 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),
),
),
),
);
}
}

View File

@@ -0,0 +1,12 @@
import 'package:food_delivery_client/feature/auth/presentation/pages/forgot_password_page/widgets/forgot_password_body.dart';
import '../../../../../food_delivery_client.dart';
class ForgotPasswordPage extends StatelessWidget {
const ForgotPasswordPage({super.key});
@override
Widget build(BuildContext context) {
return ForgotPasswordBody();
}
}

View File

@@ -0,0 +1,117 @@
import 'package:food_delivery_client/core/helpers/formatters.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';
import '../../../../../../food_delivery_client.dart';
class ForgotPasswordBody extends StatefulWidget {
const ForgotPasswordBody({super.key});
@override
State<ForgotPasswordBody> createState() => _ForgotPasswordBodyState();
}
class _ForgotPasswordBodyState extends State<ForgotPasswordBody> {
late final TextEditingController _phoneNumberController;
final _formKey = GlobalKey<FormState>();
bool _isValid = false;
void _validateForm() {
final isValid = _formKey.currentState?.validate() ?? false;
if (isValid != _isValid) {
setState(() {
_isValid = isValid;
});
}
}
@override
void initState() {
_phoneNumberController = TextEditingController();
_phoneNumberController.addListener(_validateForm);
super.initState();
}
@override
void dispose() {
_phoneNumberController.removeListener(_validateForm);
_phoneNumberController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: WLayout(
child: Scaffold(
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
30.verticalSpace,
WBackButton(),
20.verticalSpace,
Text(
context.loc.forgotPassword,
style: context.appThemeTextStyles.size24Bold,
),
8.verticalSpace,
Text(
context.loc.forgotPasswordSubtitle,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.cA7AEC1,
height: 1.6,
),
).paddingOnly(right: 50),
30.verticalSpace,
Text(
context.loc.phoneNumber,
style: context.appThemeTextStyles.size16Medium,
),
10.verticalSpace,
AppTextFormField(
controller: _phoneNumberController,
keyBoardType: TextInputType.number,
hintText: context.loc.enter_email_or_phone,
prefixIcon: Text(
"+ 998",
style: context.appThemeTextStyles.size14Regular,
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
Formatters.phoneFormatter,
LengthLimitingTextInputFormatter(12),
],
validator: (value) {
return Validators.validatePhoneNumber(
_phoneNumberController.text.trim(),
);
},
),
100.verticalSpace,
AppButton(
name: context.loc.sendCode,
isActive: _isValid,
onPressed: () {
context.push(
Routes.verifyAccount,
extra:
"+998${_phoneNumberController.text.trim().replaceAll(" ", "")}",
);
if (_formKey.currentState?.validate() ?? false) {}
},
),
],
).paddingSymmetric(horizontal: 24),
),
),
),
);
}
}

View File

@@ -108,7 +108,12 @@ class _WLoginBodyState extends State<WLoginBody> {
), ),
10.verticalSpace, 10.verticalSpace,
AppTextFormField( AppTextFormField(
prefixIcon: Text("+ 998"), prefixIcon: Text(
"+ 998",
style: context
.appThemeTextStyles
.size14Regular,
),
controller: _phoneNumberController, controller: _phoneNumberController,
hintText: context.loc.enter_email_or_phone, hintText: context.loc.enter_email_or_phone,
inputFormatters: [ inputFormatters: [
@@ -143,7 +148,9 @@ class _WLoginBodyState extends State<WLoginBody> {
Align( Align(
alignment: AlignmentGeometry.centerRight, alignment: AlignmentGeometry.centerRight,
child: TextButton( child: TextButton(
onPressed: () {}, onPressed: () {
context.push(Routes.forgotPassword);
},
child: Text( child: Text(
context.loc.forgot_password, context.loc.forgot_password,
style: AppTextStyles.size14Regular style: AppTextStyles.size14Regular

View File

@@ -0,0 +1,13 @@
import 'package:food_delivery_client/feature/auth/presentation/pages/verify_account_page/widgets/verify_account_body.dart';
import '../../../../../food_delivery_client.dart';
class VerifyAccountPage extends StatelessWidget {
const VerifyAccountPage({super.key, required this.phoneNumber});
final String phoneNumber;
@override
Widget build(BuildContext context) {
return VerifyAccountBody(phoneNumber: phoneNumber);
}
}

View File

@@ -0,0 +1,167 @@
import 'package:food_delivery_client/core/helpers/string_helpers.dart';
import 'package:food_delivery_client/core/helpers/validator_helpers.dart';
import 'package:pinput/pinput.dart';
import '../../../../../../food_delivery_client.dart';
class VerifyAccountBody extends StatefulWidget {
const VerifyAccountBody({super.key, required this.phoneNumber});
final String phoneNumber;
@override
State<VerifyAccountBody> createState() => _VerifyAccountBodyState();
}
class _VerifyAccountBodyState extends State<VerifyAccountBody> {
late TextEditingController _otpController;
final _formKey = GlobalKey<FormState>();
bool _isValid = false;
void _formValidator() {
final isValid = _formKey.currentState?.validate() ?? false;
if (_isValid != isValid) {
setState(() {
_isValid = isValid;
});
}
}
@override
void initState() {
_otpController = TextEditingController();
_otpController.addListener(_formValidator);
super.initState();
}
@override
void dispose() {
_otpController.removeListener(_formValidator);
_otpController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final defaultPinTheme = PinTheme(
height: 56,
width: 56,
textStyle: context.appThemeTextStyles.size24SemiBold1,
decoration: BoxDecoration(
border: Border.all(
color: context.appThemeColors.borderColor,
style: BorderStyle.solid,
width: 1,
),
color: context.theme.scaffoldBackgroundColor,
borderRadius: AppUtils.kBorderRadius12,
),
);
return Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: WLayout(
child: Scaffold(
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
30.verticalSpace,
WBackButton(),
20.verticalSpace,
Text(
context.loc.verifyYourAccount,
style: context.appThemeTextStyles.size24Bold,
),
8.verticalSpace,
RichText(
text: TextSpan(
text: context.loc.verifyAccountSubtitle,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.cA7AEC1,
height: 1.6,
),
children: [
TextSpan(text: " "),
TextSpan(
text: StringHelpers.formatUzbekPhoneNumber(
widget.phoneNumber,
),
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.cFF6F00,
),
),
],
),
),
50.verticalSpace,
Pinput(
autofocus: true,
enabled: true,
length: 5,
controller: _otpController,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(5),
],
defaultPinTheme: defaultPinTheme,
focusedPinTheme: defaultPinTheme.copyWith(
decoration: defaultPinTheme.decoration?.copyWith(
border: Border.all(color: AppColors.cFF6F00),
),
),
validator: (value) {
return Validators.validateOtpFields(
_otpController.text.trim(),
);
},
),
90.verticalSpace,
AppButton(
isActive: _isValid,
name: context.loc.verifyAccount,
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
context.push(
Routes.createNewPassword,
extra: widget.phoneNumber,
);
}
},
),
20.verticalSpace,
Align(
alignment: AlignmentGeometry.center,
child: RichText(
text: TextSpan(
text: context.loc.didNotReceiveCode,
style: context.appThemeTextStyles.size14Regular1,
children: [
WidgetSpan(
baseline: TextBaseline.alphabetic,
alignment: PlaceholderAlignment.baseline,
child: TextButton(
onPressed: () {},
child: Text(
context.loc.resend,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.cFF6F00,
),
),
),
),
],
),
),
),
],
).paddingSymmetric(horizontal: 24),
),
),
),
);
}
}

View File

@@ -92,7 +92,7 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
widget.hintTextStyle ?? widget.hintTextStyle ??
context.appThemeTextStyles.size14Regular.copyWith( context.appThemeTextStyles.size14Regular.copyWith(
color: AppColors.cA7AEC1, color: AppColors.cA7AEC1,
), ),
suffixIcon: widget.obscureText suffixIcon: widget.obscureText
? IconButton( ? IconButton(
onPressed: () { onPressed: () {
@@ -101,8 +101,9 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
}); });
}, },
icon: SvgPicture.asset( icon: SvgPicture.asset(
visibility ? AppIcons.icVisibility : AppIcons.icVisibilityOff, visibility
color: AppColors.c000000, ? AppIcons.icVisibility
: AppIcons.icVisibilityOff,
), ),
) )
: widget.suffixIcon, : widget.suffixIcon,

View File

@@ -6,7 +6,9 @@ class WBackButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
onTap: () {}, onTap: () {
context.pop();
},
borderRadius: AppUtils.kBorderRadius22, borderRadius: AppUtils.kBorderRadius22,
child: Ink( child: Ink(
height: 44, height: 44,
@@ -19,7 +21,7 @@ class WBackButton extends StatelessWidget {
color: AppColors.cA7AEC1.newWithOpacity(.3), color: AppColors.cA7AEC1.newWithOpacity(.3),
offset: const Offset(0, 4), offset: const Offset(0, 4),
blurRadius: 80, blurRadius: 80,
), ),
], ],
), ),
child: SvgPicture.asset( child: SvgPicture.asset(

View File

@@ -62,7 +62,8 @@ class _MyAppState extends State<MyApp> {
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
theme: AppTheme.lightTheme, theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme, darkTheme: AppTheme.darkTheme,
themeMode: themeState.themeMode, themeMode: ThemeMode.light,
// themeMode: themeState.themeMode,
routerConfig: sl<AppRoutes>().router, routerConfig: sl<AppRoutes>().router,
locale: state.currentLocale, locale: state.currentLocale,
supportedLocales: L10n.locales, supportedLocales: L10n.locales,