feat:register page ui done

This commit is contained in:
jahongireshonqulov
2025-10-29 15:16:44 +05:00
parent 2ed2c430c0
commit ece15635eb
18 changed files with 708 additions and 241 deletions

View File

@@ -163,9 +163,19 @@
"password": "Password", "password": "Password",
"enter_password": "Enter password", "enter_password": "Enter password",
"forgot_password": "Forgot password", "forgot_password": "Forgot password",
"Continue": "Continue", "continue_str": "Continue",
"dont_have_account": "Don't have an account?", "dont_have_account": "Don't have an account?",
"sign_up": "SignUp" "sign_up": "SignUp",
"field_cannot_be_empty": "This field cannot be empty",
"password_too_short": "Password must be at least 6 characters long",
"invalid_phone_format": "Invalid phone number format",
"first_name": "First name",
"enter_first_name": "Enter first name",
"repeat_password": "Repeat password",
"enter_repeat_password": "Enter repeat password",
"already_has_account": "Already have an account?",
"unexpected_error": "Unexpected error"

View File

@@ -158,9 +158,19 @@
"password": "Пароль", "password": "Пароль",
"enter_password": "Введите пароль", "enter_password": "Введите пароль",
"forgot_password": "Забыли пароль", "forgot_password": "Забыли пароль",
"Continue": "Продолжить", "continue_str": "Продолжить",
"dont_have_account": "У вас нет аккаунта?", "dont_have_account": "У вас нет аккаунта?",
"sign_up": "Зарегистрироваться" "sign_up": "Зарегистрироваться",
"field_cannot_be_empty": "Это поле не может быть пустым",
"password_too_short": "Пароль не может быть короче 6 символов",
"invalid_phone_format": "Неверный формат номера телефона",
"first_name": "Имя",
"enter_first_name": "Введите имя",
"repeat_password": "Повторите пароль",
"enter_repeat_password": "Введите пароль ещё раз",
"already_has_account": "Уже есть аккаунт?",
"unexpected_error": "Неожиданная ошибка"

View File

@@ -158,9 +158,19 @@
"password": "Parol", "password": "Parol",
"enter_password": "Parolni kiriting", "enter_password": "Parolni kiriting",
"forgot_password": "Parolni unutdingizmi", "forgot_password": "Parolni unutdingizmi",
"Continue": "Davom etish", "continue_str": "Davom etish",
"dont_have_account": "Hisobingiz yoqmi?", "dont_have_account": "Hisobingiz yoqmi?",
"sign_up": "Royxatdan otish" "sign_up": "Royxatdan otish",
"field_cannot_be_empty": "Bu maydon bo'sh bo'lishi mumkin emas",
"password_too_short": "Parol 6 ta belgidan kam bo'lishi mumkin emas",
"invalid_phone_format": "Noto'g'ri telefon raqam formati",
"first_name": "Ism",
"enter_first_name": "Ismingizni kiriting",
"repeat_password": "Parolni takrorlang",
"enter_repeat_password": "Parolni qayta kiriting",
"already_has_account": "Akkountingiz bormi?",
"unexpected_error": "Kutilmagan xatolik"

View File

@@ -0,0 +1,28 @@
import 'package:food_delivery_client/core/core.dart';
abstract class Validators {
static String? validatePhoneNumber(String phoneNumber) {
if (phoneNumber.isEmpty) {
return navigatorKey.currentContext?.loc.field_cannot_be_empty;
} else if (phoneNumber.length < 12) {
return navigatorKey.currentContext?.loc.invalid_phone_format;
}
return null;
}
static String? validatePassword(String password) {
if (password.isEmpty) {
return navigatorKey.currentContext?.loc.field_cannot_be_empty;
} else if (password.length < 6) {
return navigatorKey.currentContext?.loc.password_too_short;
}
return null;
}
static String? validateFields(String value) {
if (value.isEmpty) {
return navigatorKey.currentContext?.loc.field_cannot_be_empty;
}
return null;
}
}

View File

@@ -63,7 +63,8 @@ import 'app_localizations_uz.dart';
/// be consistent with the languages listed in the AppLocalizations.supportedLocales /// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property. /// property.
abstract class AppLocalizations { abstract class AppLocalizations {
AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); AppLocalizations(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName; final String localeName;
@@ -71,7 +72,8 @@ abstract class AppLocalizations {
return Localizations.of<AppLocalizations>(context, AppLocalizations); return Localizations.of<AppLocalizations>(context, AppLocalizations);
} }
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate(); static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations /// A list of this localizations delegate along with the default localizations
/// delegates. /// delegates.
@@ -83,18 +85,19 @@ abstract class AppLocalizations {
/// Additional delegates can be added by appending to this list in /// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list /// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required. /// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[ static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
delegate, <LocalizationsDelegate<dynamic>>[
GlobalMaterialLocalizations.delegate, delegate,
GlobalCupertinoLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
]; GlobalWidgetsLocalizations.delegate,
];
/// A list of this localizations delegate's supported locales. /// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[ static const List<Locale> supportedLocales = <Locale>[
Locale('en'), Locale('en'),
Locale('ru'), Locale('ru'),
Locale('uz') Locale('uz'),
]; ];
/// No description provided for @useYourTAxiAccount. /// No description provided for @useYourTAxiAccount.
@@ -787,11 +790,11 @@ abstract class AppLocalizations {
/// **'Forgot password'** /// **'Forgot password'**
String get forgot_password; String get forgot_password;
/// No description provided for @continue. /// No description provided for @continue_str.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Continue'** /// **'Continue'**
String get Continue; String get continue_str;
/// No description provided for @dont_have_account. /// No description provided for @dont_have_account.
/// ///
@@ -804,9 +807,64 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'SignUp'** /// **'SignUp'**
String get sign_up; String get sign_up;
/// No description provided for @field_cannot_be_empty.
///
/// In en, this message translates to:
/// **'This field cannot be empty'**
String get field_cannot_be_empty;
/// No description provided for @password_too_short.
///
/// In en, this message translates to:
/// **'Password must be at least 6 characters long'**
String get password_too_short;
/// No description provided for @invalid_phone_format.
///
/// In en, this message translates to:
/// **'Invalid phone number format'**
String get invalid_phone_format;
/// No description provided for @first_name.
///
/// In en, this message translates to:
/// **'First name'**
String get first_name;
/// No description provided for @enter_first_name.
///
/// In en, this message translates to:
/// **'Enter first name'**
String get enter_first_name;
/// No description provided for @repeat_password.
///
/// In en, this message translates to:
/// **'Repeat password'**
String get repeat_password;
/// No description provided for @enter_repeat_password.
///
/// In en, this message translates to:
/// **'Enter repeat password'**
String get enter_repeat_password;
/// No description provided for @already_has_account.
///
/// In en, this message translates to:
/// **'Already have an account?'**
String get already_has_account;
/// No description provided for @unexpected_error.
///
/// In en, this message translates to:
/// **'Unexpected error'**
String get unexpected_error;
} }
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> { class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate(); const _AppLocalizationsDelegate();
@override @override
@@ -815,26 +873,28 @@ class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations>
} }
@override @override
bool isSupported(Locale locale) => <String>['en', 'ru', 'uz'].contains(locale.languageCode); bool isSupported(Locale locale) =>
<String>['en', 'ru', 'uz'].contains(locale.languageCode);
@override @override
bool shouldReload(_AppLocalizationsDelegate old) => false; bool shouldReload(_AppLocalizationsDelegate old) => false;
} }
AppLocalizations lookupAppLocalizations(Locale locale) { AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified. // Lookup logic when only language code is specified.
switch (locale.languageCode) { switch (locale.languageCode) {
case 'en': return AppLocalizationsEn(); case 'en':
case 'ru': return AppLocalizationsRu(); return AppLocalizationsEn();
case 'uz': return AppLocalizationsUz(); case 'ru':
return AppLocalizationsRu();
case 'uz':
return AppLocalizationsUz();
} }
throw FlutterError( throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue ' 'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration ' 'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.' 'that was used.',
); );
} }

View File

@@ -21,7 +21,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get next => 'Next'; String get next => 'Next';
@override @override
String get contestToGetCallAndSms => 'By proceeding, you consent to get calls, Whatsapp or SMS messages, including by automated means, from uber and its affiliates to the number provided.'; String get contestToGetCallAndSms =>
'By proceeding, you consent to get calls, Whatsapp or SMS messages, including by automated means, from uber and its affiliates to the number provided.';
@override @override
String get continueWithGoogle => 'Continue with google'; String get continueWithGoogle => 'Continue with google';
@@ -238,7 +239,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get addItemsStartBasket => 'Add items to start a basket'; String get addItemsStartBasket => 'Add items to start a basket';
@override @override
String get basketHint => 'Once you add items from a restaurant or store, your basket will appear here.'; String get basketHint =>
'Once you add items from a restaurant or store, your basket will appear here.';
@override @override
String get startShopping => 'Start Shopping'; String get startShopping => 'Start Shopping';
@@ -364,11 +366,39 @@ class AppLocalizationsEn extends AppLocalizations {
String get forgot_password => 'Forgot password'; String get forgot_password => 'Forgot password';
@override @override
String get Continue => 'Continue'; String get continue_str => 'Continue';
@override @override
String get dont_have_account => 'Don\'t have an account?'; String get dont_have_account => 'Don\'t have an account?';
@override @override
String get sign_up => 'SignUp'; String get sign_up => 'SignUp';
@override
String get field_cannot_be_empty => 'This field cannot be empty';
@override
String get password_too_short =>
'Password must be at least 6 characters long';
@override
String get invalid_phone_format => 'Invalid phone number format';
@override
String get first_name => 'First name';
@override
String get enter_first_name => 'Enter first name';
@override
String get repeat_password => 'Repeat password';
@override
String get enter_repeat_password => 'Enter repeat password';
@override
String get already_has_account => 'Already have an account?';
@override
String get unexpected_error => 'Unexpected error';
} }

View File

@@ -9,7 +9,8 @@ class AppLocalizationsRu extends AppLocalizations {
AppLocalizationsRu([String locale = 'ru']) : super(locale); AppLocalizationsRu([String locale = 'ru']) : super(locale);
@override @override
String get useYourTAxiAccount => 'Используйте свой аккаунт Uber, чтобы начать'; String get useYourTAxiAccount =>
'Используйте свой аккаунт Uber, чтобы начать';
@override @override
String get enterYourMobileNumber => 'Введите свой номер телефона'; String get enterYourMobileNumber => 'Введите свой номер телефона';
@@ -21,7 +22,8 @@ class AppLocalizationsRu extends AppLocalizations {
String get next => 'Далее'; String get next => 'Далее';
@override @override
String get contestToGetCallAndSms => 'Продолжая, вы соглашаетесь получать звонки, сообщения WhatsApp или SMS, включая автоматические, от Uber и его партнеров на указанный номер.'; String get contestToGetCallAndSms =>
'Продолжая, вы соглашаетесь получать звонки, сообщения WhatsApp или SMS, включая автоматические, от Uber и его партнеров на указанный номер.';
@override @override
String get continueWithGoogle => 'Продолжить через Google'; String get continueWithGoogle => 'Продолжить через Google';
@@ -238,7 +240,8 @@ class AppLocalizationsRu extends AppLocalizations {
String get addItemsStartBasket => 'Добавьте товары, чтобы создать корзину'; String get addItemsStartBasket => 'Добавьте товары, чтобы создать корзину';
@override @override
String get basketHint => 'Когда вы добавите товары из ресторана или магазина, ваша корзина появится здесь.'; String get basketHint =>
'Когда вы добавите товары из ресторана или магазина, ваша корзина появится здесь.';
@override @override
String get startShopping => 'Начать покупки'; String get startShopping => 'Начать покупки';
@@ -346,29 +349,56 @@ class AppLocalizationsRu extends AppLocalizations {
String get language => 'Язык'; String get language => 'Язык';
@override @override
String get login => 'Login'; String get login => 'Вход';
@override @override
String get phone_number => 'Phone number'; String get phone_number => 'Номер телефона';
@override @override
String get enter_phone_number => 'Enter phone number'; String get enter_phone_number => 'Введите номер телефона';
@override @override
String get password => 'Password'; String get password => 'Пароль';
@override @override
String get enter_password => 'Enter password'; String get enter_password => 'Введите пароль';
@override @override
String get forgot_password => 'Forgot password'; String get forgot_password => 'Забыли пароль';
@override @override
String get Continue => 'Continue'; String get continue_str => 'Продолжить';
@override @override
String get dont_have_account => 'Don\'t have an account?'; String get dont_have_account => 'У вас нет аккаунта?';
@override @override
String get sign_up => 'SignUp'; String get sign_up => 'Зарегистрироваться';
@override
String get field_cannot_be_empty => 'Это поле не может быть пустым';
@override
String get password_too_short => 'Пароль не может быть короче 6 символов';
@override
String get invalid_phone_format => 'Неверный формат номера телефона';
@override
String get first_name => 'Имя';
@override
String get enter_first_name => 'Введите имя';
@override
String get repeat_password => 'Повторите пароль';
@override
String get enter_repeat_password => 'Введите пароль ещё раз';
@override
String get already_has_account => 'Уже есть аккаунт?';
@override
String get unexpected_error => 'Неожиданная ошибка';
} }

View File

@@ -9,7 +9,8 @@ class AppLocalizationsUz extends AppLocalizations {
AppLocalizationsUz([String locale = 'uz']) : super(locale); AppLocalizationsUz([String locale = 'uz']) : super(locale);
@override @override
String get useYourTAxiAccount => 'Boshlash uchun Uber hisobingizdan foydalaning'; String get useYourTAxiAccount =>
'Boshlash uchun Uber hisobingizdan foydalaning';
@override @override
String get enterYourMobileNumber => 'Telefon raqamingizni kiriting'; String get enterYourMobileNumber => 'Telefon raqamingizni kiriting';
@@ -21,7 +22,8 @@ class AppLocalizationsUz extends AppLocalizations {
String get next => 'Keyingi'; String get next => 'Keyingi';
@override @override
String get contestToGetCallAndSms => 'Davom etish orqali siz Uber va uning hamkorlaridan avtomatlashtirilgan qongiroqlar, WhatsApp yoki SMS xabarlarini olishga rozilik bildirasiz.'; String get contestToGetCallAndSms =>
'Davom etish orqali siz Uber va uning hamkorlaridan avtomatlashtirilgan qongiroqlar, WhatsApp yoki SMS xabarlarini olishga rozilik bildirasiz.';
@override @override
String get continueWithGoogle => 'Google orqali davom etish'; String get continueWithGoogle => 'Google orqali davom etish';
@@ -238,7 +240,8 @@ class AppLocalizationsUz extends AppLocalizations {
String get addItemsStartBasket => 'Savatni boshlash uchun mahsulot qoshing'; String get addItemsStartBasket => 'Savatni boshlash uchun mahsulot qoshing';
@override @override
String get basketHint => 'Restorandan yoki do\'kondan mahsulot qoshsangiz, savatingiz shu yerda paydo boladi.'; String get basketHint =>
'Restorandan yoki do\'kondan mahsulot qoshsangiz, savatingiz shu yerda paydo boladi.';
@override @override
String get startShopping => 'Xaridni boshlash'; String get startShopping => 'Xaridni boshlash';
@@ -346,29 +349,57 @@ class AppLocalizationsUz extends AppLocalizations {
String get language => 'Til'; String get language => 'Til';
@override @override
String get login => 'Login'; String get login => 'Kirish';
@override @override
String get phone_number => 'Phone number'; String get phone_number => 'Telefon raqami';
@override @override
String get enter_phone_number => 'Enter phone number'; String get enter_phone_number => 'Telefon raqamingizni kiriting';
@override @override
String get password => 'Password'; String get password => 'Parol';
@override @override
String get enter_password => 'Enter password'; String get enter_password => 'Parolni kiriting';
@override @override
String get forgot_password => 'Forgot password'; String get forgot_password => 'Parolni unutdingizmi';
@override @override
String get Continue => 'Continue'; String get continue_str => 'Davom etish';
@override @override
String get dont_have_account => 'Don\'t have an account?'; String get dont_have_account => 'Hisobingiz yoqmi?';
@override @override
String get sign_up => 'SignUp'; String get sign_up => 'Royxatdan otish';
@override
String get field_cannot_be_empty => 'Bu maydon bo\'sh bo\'lishi mumkin emas';
@override
String get password_too_short =>
'Parol 6 ta belgidan kam bo\'lishi mumkin emas';
@override
String get invalid_phone_format => 'Noto\'g\'ri telefon raqam formati';
@override
String get first_name => 'Ism';
@override
String get enter_first_name => 'Ismingizni kiriting';
@override
String get repeat_password => 'Parolni takrorlang';
@override
String get enter_repeat_password => 'Parolni qayta kiriting';
@override
String get already_has_account => 'Akkountingiz bormi?';
@override
String get unexpected_error => 'Kutilmagan xatolik';
} }

View File

@@ -25,5 +25,6 @@ abstract class AppColors {
static const Color cE8E8E8 = Color(0xFFE8E8E8); static const Color cE8E8E8 = Color(0xFFE8E8E8);
static const Color c660000 = Color(0x66000000); static const Color c660000 = Color(0x66000000);
static const Color c6A6E7F = Color(0xFF6A6E7F); static const Color c6A6E7F = Color(0xFF6A6E7F);
static const Color c7F7F7F = Color(0xFF7F7F7F);
} }

View File

@@ -13,6 +13,7 @@ abstract class AppUtils {
static const Radius kRadius22 = Radius.circular(22); static const Radius kRadius22 = Radius.circular(22);
static const Radius kRadius24 = Radius.circular(24); static const Radius kRadius24 = Radius.circular(24);
static const Radius kRadius25 = Radius.circular(25); static const Radius kRadius25 = Radius.circular(25);
static const Radius kRadius30 = Radius.circular(30);
static const BorderRadius kBorderRadius = BorderRadius.zero; static const BorderRadius kBorderRadius = BorderRadius.zero;
static const BorderRadius kBorderRadius2 = BorderRadius.all( static const BorderRadius kBorderRadius2 = BorderRadius.all(
Radius.circular(2), Radius.circular(2),
@@ -92,6 +93,11 @@ abstract class AppUtils {
topLeft: kRadius20, topLeft: kRadius20,
topRight: kRadius20, topRight: kRadius20,
); );
static const BorderRadius kBorderRadiusTop30 = BorderRadius.only(
topLeft: kRadius30,
topRight: kRadius30,
);
static const BorderRadius kBorderRadiusTop20Bottom20 = BorderRadius.only( static const BorderRadius kBorderRadiusTop20Bottom20 = BorderRadius.only(
bottomRight: kRadius20, bottomRight: kRadius20,
topRight: kRadius20, topRight: kRadius20,

View File

@@ -32,6 +32,8 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
(r) { (r) {
showSuccessToast("Login success"); showSuccessToast("Login success");
_storageService.setString(key: AppLocaleKeys.token, value: r.token); _storageService.setString(key: AppLocaleKeys.token, value: r.token);
final token = _storageService.getString(key: AppLocaleKeys.token);
log('Token:$token');
emit(state.copyWith(status: RequestStatus.loaded)); emit(state.copyWith(status: RequestStatus.loaded));
}, },
); );

View File

@@ -1,6 +1,5 @@
import 'package:food_delivery_client/feature/auth/presentation/blocs/login_bloc/login_bloc.dart'; import 'package:food_delivery_client/feature/auth/presentation/blocs/login_bloc/login_bloc.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/login_page/widgets/login_body.dart'; import 'package:food_delivery_client/feature/auth/presentation/pages/login_page/widgets/login_body.dart';
import '../../../../../food_delivery_client.dart'; import '../../../../../food_delivery_client.dart';
class LoginPage extends StatelessWidget { class LoginPage extends StatelessWidget {
@@ -10,12 +9,10 @@ class LoginPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => sl<LoginBloc>(), create: (context) => sl<LoginBloc>(),
child: WLayout( child: WLayout(
child: Scaffold( top: false,
body: WLoginBody(), child: Scaffold(resizeToAvoidBottomInset: true, body: WLoginBody()),
),
), ),
); );
} }
} }

View File

@@ -1,5 +1,7 @@
import 'package:food_delivery_client/core/helpers/formatters.dart'; 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/auth/domain/usecases/login_usecase.dart'; import 'package:food_delivery_client/feature/auth/domain/usecases/login_usecase.dart';
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../../food_delivery_client.dart'; import '../../../../../../food_delivery_client.dart';
import '../../../blocs/login_bloc/login_bloc.dart'; import '../../../blocs/login_bloc/login_bloc.dart';
@@ -36,126 +38,130 @@ class _WLoginBodyState extends State<WLoginBody> {
return Form( return Form(
key: _formKey, key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
child: LayoutBuilder( child: WAuthBackground(
builder: (context, constraints) { child: Column(
return ConstrainedBox( mainAxisSize: MainAxisSize.min,
constraints: BoxConstraints(), crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: [
mainAxisSize: MainAxisSize.min, 25.verticalSpace,
crossAxisAlignment: CrossAxisAlignment.start, Align(
children: [ alignment: AlignmentGeometry.center,
45.verticalSpace, child: Text(
Align( context.loc.login,
alignment: AlignmentGeometry.center, style: AppTextStyles.size24Bold,
child: Text(context.loc.login, style: AppTextStyles.size24Bold), ),
), ),
20.verticalSpace, 20.verticalSpace,
Text( Text(
context.loc.phone_number, context.loc.phone_number,
style: AppTextStyles.size14Regular.copyWith( style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F, color: AppColors.c6A6E7F,
), ),
), ),
5.verticalSpace, 5.verticalSpace,
AppTextFormField( AppTextFormField(
height: 50, hintText: context.loc.enter_phone_number,
hintText: context.loc.enter_phone_number, prefixIcon: Text(
prefixIcon: Text( "+ 998",
"+ 998", style: AppTextStyles.size16Regular.copyWith(fontSize: 16),
style: AppTextStyles.size16Regular.copyWith( ),
fontSize: 16, borderRadius: AppUtils.kBorderRadius8,
), controller: _phoneController,
), keyBoardType: TextInputType.number,
borderRadius: AppUtils.kBorderRadius8,
controller: _phoneController,
keyBoardType: TextInputType.number,
inputFormatters: [ inputFormatters: [
FilteringTextInputFormatter.digitsOnly, FilteringTextInputFormatter.digitsOnly,
Formatters.phoneFormatter, Formatters.phoneFormatter,
LengthLimitingTextInputFormatter(12), LengthLimitingTextInputFormatter(12),
],
),
20.verticalSpace,
Text(
context.loc.password,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
height: 50,
obscureText: true,
hintText: context.loc.enter_password,
keyBoardType: TextInputType.text,
borderRadius: AppUtils.kBorderRadius8,
controller: _passwordController,
),
Align(
alignment: AlignmentGeometry.centerRight,
child: TextButton(
onPressed: () {
context.push(Routes.forgotPassword);
},
child: Text(
context.loc.forgot_password,
style: AppTextStyles.size14Medium.copyWith(
color: AppColors.c34A853,
),
),
),
),
const Spacer(),
AppButton(
name: context.loc.Continue,
isLoading: state.status.isLoading(),
trailing: SvgPicture.asset(
AppIcons.icArrowRightLight,
).paddingOnly(left: 10),
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
context.read<LoginBloc>().add(
LoginEvent.login(
LoginParams(
phoneNumber:
"+998${_phoneController.text.trim().replaceAll(" ", "")}",
password: _passwordController.text.trim(),
),
),
);
}
},
borderRadius: 15,
backgroundColor: AppColors.c34A853,
),
20.verticalSpace,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.loc.dont_have_account,
style: AppTextStyles.size14Medium,
),
TextButton(
onPressed: () {
context.pushReplacement(Routes.register);
},
child: Text(
context.loc.sign_up,
style: AppTextStyles.size15Bold.copyWith(
color: AppColors.c34A853,
),
),
),
],
),
20.verticalSpace,
], ],
).paddingSymmetric(horizontal: 16), validator: (value) {
); return Validators.validatePhoneNumber(
}, _phoneController.text.trim(),
);
},
),
10.verticalSpace,
Text(
context.loc.password,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
height: 50,
obscureText: true,
hintText: context.loc.enter_password,
keyBoardType: TextInputType.text,
borderRadius: AppUtils.kBorderRadius8,
controller: _passwordController,
validator: (value) {
return Validators.validatePassword(
_passwordController.text.trim(),
);
},
),
Align(
alignment: AlignmentGeometry.centerRight,
child: TextButton(
onPressed: () {
context.push(Routes.forgotPassword);
},
child: Text(
context.loc.forgot_password,
style: AppTextStyles.size14Medium.copyWith(
color: AppColors.c34A853,
),
),
),
),
40.verticalSpace,
AppButton(
name: context.loc.continue_str,
isLoading: state.status.isLoading(),
trailing: SvgPicture.asset(
AppIcons.icArrowRightLight,
).paddingOnly(left: 10),
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
context.read<LoginBloc>().add(
LoginEvent.login(
LoginParams(
phoneNumber:
"+998${_phoneController.text.trim().replaceAll(" ", "")}",
password: _passwordController.text.trim(),
),
),
);
}
},
borderRadius: 15,
backgroundColor: AppColors.c34A853,
),
20.verticalSpace,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.loc.dont_have_account,
style: AppTextStyles.size14Medium,
),
TextButton(
onPressed: () {
context.pushReplacement(Routes.register);
},
child: Text(
context.loc.sign_up,
style: AppTextStyles.size15Bold.copyWith(
color: AppColors.c34A853,
),
),
),
],
),
20.verticalSpace,
],
).paddingSymmetric(horizontal: 16),
), ),
); );
}, },

View File

@@ -1,3 +1,5 @@
import 'package:food_delivery_client/feature/auth/presentation/pages/register_page/widgets/w_register_body.dart';
import '../../../../../food_delivery_client.dart'; import '../../../../../food_delivery_client.dart';
class RegisterPage extends StatelessWidget { class RegisterPage extends StatelessWidget {
@@ -6,7 +8,7 @@ class RegisterPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WLayout( return WLayout(
child: Scaffold(body: Column(children: [Text("register")])), top: false,
); child: Scaffold(body: WRegisterBody()));
} }
} }

View File

@@ -0,0 +1,205 @@
import 'package:food_delivery_client/core/helpers/validator_helpers.dart';
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../../food_delivery_client.dart';
class WRegisterBody extends StatefulWidget {
const WRegisterBody({super.key});
@override
State<WRegisterBody> createState() => _WRegisterBodyState();
}
class _WRegisterBodyState extends State<WRegisterBody> {
late TextEditingController _firstNameController;
late TextEditingController _lastNameController;
late TextEditingController _phoneNumberController;
late TextEditingController _passwordController;
late TextEditingController _repeatPasswordController;
final _formKey = GlobalKey<FormState>();
@override
void initState() {
_firstNameController = TextEditingController();
_lastNameController = TextEditingController();
_phoneNumberController = TextEditingController();
_passwordController = TextEditingController();
_repeatPasswordController = TextEditingController();
super.initState();
}
@override
void dispose() {
_firstNameController.dispose();
_lastNameController.dispose();
_phoneNumberController.dispose();
_passwordController.dispose();
_repeatPasswordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: WAuthBackground(
child: SizedBox(
width: context.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
20.verticalSpace,
Align(
alignment: AlignmentGeometry.center,
child: Text(
context.loc.sign_up,
style: AppTextStyles.size24Bold,
),
),
20.verticalSpace,
Text(
context.loc.first_name,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
hintText: context.loc.enter_first_name,
controller: _firstNameController,
borderRadius: AppUtils.kBorderRadius8,
keyBoardType: TextInputType.name,
validator: (value) {
return Validators.validateFields(
_firstNameController.text.trim(),
);
},
),
10.verticalSpace,
Text(
'Last name',
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
hintText: "Enter LastName",
controller: _lastNameController,
borderRadius: AppUtils.kBorderRadius8,
keyBoardType: TextInputType.text,
validator: (value) {
return Validators.validateFields(
_lastNameController.text.trim(),
);
},
),
10.verticalSpace,
/* Text(
context.loc.phone_number,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
hintText: context.loc.enter_phone_number,
controller: _phoneNumberController,
borderRadius: AppUtils.kBorderRadius8,
keyBoardType: TextInputType.phone,
prefixIcon: Text("+ 998", style: AppTextStyles.size16Regular),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
Formatters.phoneFormatter,
LengthLimitingTextInputFormatter(12),
],
validator: (value) {
return Validators.validatePhoneNumber(
_phoneNumberController.text.trim(),
);
},
),
*/
10.verticalSpace,
Text(
context.loc.enter_password,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
obscureText: true,
hintText: context.loc.password,
controller: _passwordController,
borderRadius: AppUtils.kBorderRadius8,
keyBoardType: TextInputType.visiblePassword,
validator: (value) {
return Validators.validatePassword(
_passwordController.text.trim(),
);
},
),
10.verticalSpace,
Text(
context.loc.repeat_password,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
obscureText: true,
hintText: context.loc.enter_repeat_password,
controller: _repeatPasswordController,
borderRadius: AppUtils.kBorderRadius8,
keyBoardType: TextInputType.visiblePassword,
validator: (value) {
return Validators.validatePassword(
_repeatPasswordController.text.trim(),
);
},
),
20.verticalSpace,
AppButton(
name: context.loc.continue_str,
borderRadius: 15,
backgroundColor: AppColors.c34A853,
trailing: SvgPicture.asset(
AppIcons.icArrowRightLight,
).paddingOnly(left: 8),
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {}
},
),
20.verticalSpace,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.loc.already_has_account,
style: AppTextStyles.size14Medium,
),
TextButton(
onPressed: () {
context.pushReplacement(Routes.login);
},
child: Text(
context.loc.login,
style: AppTextStyles.size15Bold.copyWith(
color: AppColors.c34A853,
),
),
),
],
),
],
).paddingSymmetric(horizontal: 16),
),
),
);
}
}

View File

@@ -0,0 +1,35 @@
import '../../../../food_delivery_client.dart';
class WAuthBackground extends StatelessWidget {
const WAuthBackground({super.key, required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
return Stack(
children: [
SizedBox(
height: context.h * .3,
child: Image.asset(AppImages.imgBurger2, fit: BoxFit.cover),
),
SingleChildScrollView(
// keyboardDismissBehavior:
// ScrollViewKeyboardDismissBehavior.onDrag,
child: Column(
children: [
SizedBox(height: context.h * .2),
DecoratedBox(
decoration: BoxDecoration(
color: AppColors.cFFFFFF,
borderRadius: AppUtils.kBorderRadiusTop20,
),
child: child,
),
],
),
),
],
);
}
}

View File

@@ -1,7 +1,7 @@
import '../../../../food_delivery_client.dart'; import '../../../../food_delivery_client.dart';
class AppTextFormField extends StatefulWidget { class AppTextFormField extends StatefulWidget {
const AppTextFormField({ AppTextFormField({
super.key, super.key,
this.maxLines, this.maxLines,
this.minLines, this.minLines,
@@ -22,6 +22,7 @@ class AppTextFormField extends StatefulWidget {
this.borderRadius, this.borderRadius,
this.height, this.height,
this.suffixIcon, this.suffixIcon,
this.validator,
}); });
final int? maxLines; final int? maxLines;
@@ -43,78 +44,78 @@ class AppTextFormField extends StatefulWidget {
final BorderRadius? borderRadius; final BorderRadius? borderRadius;
final double? height; final double? height;
final Widget? suffixIcon; final Widget? suffixIcon;
FormFieldValidator<String>? validator;
@override @override
State<AppTextFormField> createState() => _AppTextFormFieldState(); State<AppTextFormField> createState() => _AppTextFormFieldState();
} }
class _AppTextFormFieldState extends State<AppTextFormField> { class _AppTextFormFieldState extends State<AppTextFormField> {
FormFieldValidator<String>? validator;
bool visibility = true; bool visibility = true;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return TextFormField(
height: widget.height ?? 44, enabled: true,
child: TextFormField( //autofocus: true,
maxLines: widget.maxLines ?? 1,
minLines: widget.minLines ?? 1,
onChanged: widget.onChanged,
focusNode: widget.focusNode,
inputFormatters: widget.inputFormatters,
keyboardType: widget.keyBoardType,
style: widget.textStyle ?? AppTextStyles.size16Regular,
onTap: widget.onTap,
textAlign: widget.textAlign ?? TextAlign.start,
controller: widget.controller,
validator: widget.validator,
obscureText: widget.obscureText ? visibility : false,
obscuringCharacter: "*",
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: InputDecoration(
enabled: true, enabled: true,
autofocus: true, filled: true,
maxLines: widget.maxLines ?? 1,
minLines: widget.minLines ?? 1, fillColor: widget.fillColor ?? AppColors.cEEEEEE,
onChanged: widget.onChanged, hintText: widget.hintText,
focusNode: widget.focusNode, hintStyle:
inputFormatters: widget.inputFormatters, widget.hintTextStyle ??
keyboardType: widget.keyBoardType, AppTextStyles.size16Regular.copyWith(color: AppColors.c7F7F7F),
style: widget.textStyle ?? AppTextStyles.size16Regular, suffixIcon: widget.obscureText
onTap: widget.onTap, ? IconButton(
textAlign: widget.textAlign ?? TextAlign.start, onPressed: () {
controller: widget.controller, setState(() {
validator: validator, visibility = !visibility;
obscureText: widget.obscureText?visibility:false, });
obscuringCharacter: "*", },
autovalidateMode: AutovalidateMode.onUserInteraction, icon: Icon(
decoration: InputDecoration( visibility ? Icons.visibility : Icons.visibility_off,
enabled: true, color: AppColors.c000000,
filled: true, ),
fillColor: widget.fillColor ?? AppColors.cEEEEEE, )
hintText: widget.hintText, : widget.suffixIcon,
hintStyle: widget.hintTextStyle, prefixIconConstraints: BoxConstraints(minHeight: 24, minWidth: 0),
suffixIcon: widget.obscureText prefixIcon: widget.prefixIcon?.paddingOnly(left: 10).paddingAll(3),
? IconButton( contentPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 12),
onPressed: () { border: OutlineInputBorder(
setState(() { borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
visibility = !visibility; borderSide: BorderSide.none,
}); ),
}, errorBorder: OutlineInputBorder(
icon: Icon( borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
visibility ? Icons.visibility : Icons.visibility_off, borderSide: BorderSide.none,
), ),
) enabledBorder: OutlineInputBorder(
: widget.suffixIcon, borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
prefixIconConstraints: BoxConstraints(minHeight: 24, minWidth: 0), borderSide: BorderSide.none,
prefixIcon: widget.prefixIcon?.paddingOnly(left: 10).paddingAll(3), ),
contentPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), focusedBorder: OutlineInputBorder(
border: OutlineInputBorder( borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderSide: BorderSide.none,
borderSide: BorderSide.none, ),
), disabledBorder: OutlineInputBorder(
errorBorder: OutlineInputBorder( borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderSide: BorderSide.none,
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
disabledBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
), ),
), ),
); );

View File

@@ -6,7 +6,10 @@ showErrorToast(String? message) {
context: navigatorKey.currentContext, context: navigatorKey.currentContext,
type: ToastificationType.error, type: ToastificationType.error,
style: ToastificationStyle.fillColored, style: ToastificationStyle.fillColored,
title: Text(message ?? "", maxLines: 5), title: Text(
message ?? navigatorKey.currentContext!.loc.unexpected_error,
maxLines: 5,
),
autoCloseDuration: TimeDelayConst.duration3, autoCloseDuration: TimeDelayConst.duration3,
); );
} }