feat:verify phone number page ui done

This commit is contained in:
jahongireshonqulov
2025-10-29 15:51:55 +05:00
parent a2fbd9f90d
commit 5e4d362039
17 changed files with 264 additions and 6 deletions

View File

@@ -174,7 +174,16 @@
"repeat_password": "Repeat password",
"enter_repeat_password": "Enter repeat password",
"already_has_account": "Already have an account?",
"unexpected_error": "Unexpected error"
"unexpected_error": "Unexpected error",
"consent_message": "By proceeding, you consent to get calls or SMS messages, including by automated means, from {appName} and its affiliates to the number provided.",
"@consent_message": {
"placeholders": {
"appName": {
"type": "String",
"example": "Uber"
}
}
}

View File

@@ -169,7 +169,16 @@
"repeat_password": "Повторите пароль",
"enter_repeat_password": "Введите пароль ещё раз",
"already_has_account": "Уже есть аккаунт?",
"unexpected_error": "Неожиданная ошибка"
"unexpected_error": "Неожиданная ошибка",
"consent_message": "Продолжая, вы соглашаетесь получать звонки или SMS-сообщения, включая автоматические, от {appName} и его партнёров на указанный номер.",
"@consent_message": {
"placeholders": {
"appName": {
"type": "String",
"example": "Uber"
}
}
}

View File

@@ -169,7 +169,16 @@
"repeat_password": "Parolni takrorlang",
"enter_repeat_password": "Parolni qayta kiriting",
"already_has_account": "Akkountingiz bormi?",
"unexpected_error": "Kutilmagan xatolik"
"unexpected_error": "Kutilmagan xatolik",
"consent_message": "Davom etish orqali siz {appName} va uning hamkorlaridan siz kiritgan raqamga, shu jumladan avtomatik vositalar orqali, qongiroqlar yoki SMS xabarlar olishingizga rozilik bildirasiz.",
"@consent_message": {
"placeholders": {
"appName": {
"type": "String",
"example": "Uber"
}
}
}

View File

@@ -861,6 +861,12 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Unexpected error'**
String get unexpected_error;
/// No description provided for @consent_message.
///
/// In en, this message translates to:
/// **'By proceeding, you consent to get calls or SMS messages, including by automated means, from {appName} and its affiliates to the number provided.'**
String consent_message(String appName);
}
class _AppLocalizationsDelegate

View File

@@ -401,4 +401,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get unexpected_error => 'Unexpected error';
@override
String consent_message(String appName) {
return 'By proceeding, you consent to get calls or SMS messages, including by automated means, from $appName and its affiliates to the number provided.';
}
}

View File

@@ -401,4 +401,9 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get unexpected_error => 'Неожиданная ошибка';
@override
String consent_message(String appName) {
return 'Продолжая, вы соглашаетесь получать звонки или SMS-сообщения, включая автоматические, от $appName и его партнёров на указанный номер.';
}
}

View File

@@ -402,4 +402,9 @@ class AppLocalizationsUz extends AppLocalizations {
@override
String get unexpected_error => 'Kutilmagan xatolik';
@override
String consent_message(String appName) {
return 'Davom etish orqali siz $appName va uning hamkorlaridan siz kiritgan raqamga, shu jumladan avtomatik vositalar orqali, qongiroqlar yoki SMS xabarlar olishingizga rozilik bildirasiz.';
}
}

View File

@@ -2,6 +2,9 @@ import 'package:flutter/cupertino.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/register_page/register_page.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/reset_password_page/reset_password_page.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/verify_otp_code_page/verify_otp_code_page.dart';
import 'package:food_delivery_client/feature/auth/presentation/pages/verify_phone_number_page/verify_phone_page.dart';
import 'package:food_delivery_client/feature/home/presentation/pages/restaurants_by_category_page/restaurants_by_category_page.dart';
import '../../food_delivery_client.dart';
@@ -29,6 +32,25 @@ class AppRoutes {
pageBuilder: (context, state) =>
CupertinoPage(child: ForgotPasswordPage()),
),
GoRoute(
path: Routes.verifyPhoneNumber,
pageBuilder: (context, state) => CupertinoPage(
child: VerifyPhoneNumberPage(isRegister: state.extra as bool),
),
),
GoRoute(
path: Routes.verifyOtpCode,
pageBuilder: (context, state) => CupertinoPage(
child: VerifyOtpCodePage(isRegister: state.extra as bool),
),
),
GoRoute(
path: Routes.resetPassword,
pageBuilder: (context, state) =>
CupertinoPage(child: ResetPasswordPage()),
),
GoRoute(
path: Routes.main,

View File

@@ -8,4 +8,7 @@ abstract class Routes {
static const String browse = '/browse';
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

@@ -26,5 +26,7 @@ abstract class AppColors {
static const Color c660000 = Color(0x66000000);
static const Color c6A6E7F = Color(0xFF6A6E7F);
static const Color c7F7F7F = Color(0xFF7F7F7F);
static const Color c888888 = Color(0xFF888888);
}

View File

@@ -49,6 +49,12 @@ abstract class AppTextStyles {
fontWeight: FontWeight.w500,
);
static const TextStyle size12Medium = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_12,
fontFamily: _fontMedium,
fontWeight: FontWeight.w500,
);
static const TextStyle size15Medium = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_15,

View File

@@ -105,7 +105,7 @@ class _WLoginBodyState extends State<WLoginBody> {
alignment: AlignmentGeometry.centerRight,
child: TextButton(
onPressed: () {
context.push(Routes.forgotPassword);
context.push(Routes.verifyPhoneNumber, extra: false);
},
child: Text(
context.loc.forgot_password,
@@ -148,7 +148,10 @@ class _WLoginBodyState extends State<WLoginBody> {
),
TextButton(
onPressed: () {
context.pushReplacement(Routes.register);
context.push(
Routes.verifyPhoneNumber,
extra: true,
);
},
child: Text(
context.loc.sign_up,

View File

@@ -0,0 +1,22 @@
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../food_delivery_client.dart';
class ResetPasswordPage extends StatelessWidget {
const ResetPasswordPage({super.key});
@override
Widget build(BuildContext context) {
return WLayout(
top: false,
child: Scaffold(
body: WAuthBackground(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [],
),
),
),
);
}
}

View File

@@ -0,0 +1,17 @@
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../food_delivery_client.dart';
class VerifyOtpCodePage extends StatelessWidget {
const VerifyOtpCodePage({super.key, required this.isRegister});
final bool isRegister;
@override
Widget build(BuildContext context) {
return WLayout(
top: false,
child: Scaffold(body: WAuthBackground(child: Column())),
);
}
}

View File

@@ -0,0 +1,96 @@
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/presentation/widgets/w_auth_background.dart';
import '../../../../../food_delivery_client.dart';
class VerifyPhoneNumberPage extends StatefulWidget {
const VerifyPhoneNumberPage({super.key, required this.isRegister});
final bool isRegister;
@override
State<VerifyPhoneNumberPage> createState() => _VerifyPhoneNumberPageState();
}
class _VerifyPhoneNumberPageState extends State<VerifyPhoneNumberPage> {
late TextEditingController _phoneNumberController;
final _formKey = GlobalKey<FormState>();
@override
void initState() {
_phoneNumberController = TextEditingController();
super.initState();
}
@override
void dispose() {
_phoneNumberController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: WLayout(
top: false,
child: Scaffold(
body: WAuthBackground(
child: SizedBox(
width: context.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
50.verticalSpace,
Text(
context.loc.enter_phone_number,
style: AppTextStyles.size20Medium,
),
20.verticalSpace,
AppTextFormField(
controller: _phoneNumberController,
borderRadius: AppUtils.kBorderRadius8,
hintText: context.loc.phone_number,
keyBoardType: TextInputType.phone,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
Formatters.phoneFormatter,
LengthLimitingTextInputFormatter(12),
],
prefixIcon: Text(
"+ 998",
style: AppTextStyles.size16Regular,
),
validator: (value) {
return Validators.validatePhoneNumber(
_phoneNumberController.text.trim(),
);
},
),
25.verticalSpace,
AppButton(
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {}
},
name: context.loc.continue_str,
borderRadius: 15,
backgroundColor: AppColors.c34A853,
),
10.verticalSpace,
Text(
context.loc.consent_message("Felix Eats"),
style: AppTextStyles.size12Medium.copyWith(
color: AppColors.c888888,
),
),
],
).paddingSymmetric(horizontal: 16),
),
),
),
),
);
}
}

View File

@@ -1,2 +1,3 @@
export 'presentation/widgets/widgets.dart';
export 'presentation/blocs/language_bloc/language_bloc.dart';
export 'data/models/success_model.dart';

View File

@@ -0,0 +1,38 @@
import 'package:equatable/equatable.dart';
class SuccessModel extends Equatable {
final String message;
final bool success;
const SuccessModel({
required this.message,
required this.success,
});
factory SuccessModel.fromJson(Map<String, dynamic> json) {
return SuccessModel(
message: json['message'] as String? ?? '',
success: json['success'] as bool? ?? false,
);
}
Map<String, dynamic> toJson() {
return {
'message': message,
'success': success,
};
}
SuccessModel copyWith({
String? message,
bool? success,
}) {
return SuccessModel(
message: message ?? this.message,
success: success ?? this.success,
);
}
@override
List<Object?> get props => [message, success];
}