diff --git a/assets/translations/app_en.arb b/assets/translations/app_en.arb index 57e9fcb..bab40d2 100644 --- a/assets/translations/app_en.arb +++ b/assets/translations/app_en.arb @@ -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" + } + } + } diff --git a/assets/translations/app_ru.arb b/assets/translations/app_ru.arb index e4384b7..e7a7fc7 100644 --- a/assets/translations/app_ru.arb +++ b/assets/translations/app_ru.arb @@ -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" + } + } + } diff --git a/assets/translations/app_uz.arb b/assets/translations/app_uz.arb index 3477e47..9b25a58 100644 --- a/assets/translations/app_uz.arb +++ b/assets/translations/app_uz.arb @@ -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, qo‘ng‘iroqlar yoki SMS xabarlar olishingizga rozilik bildirasiz.", + "@consent_message": { + "placeholders": { + "appName": { + "type": "String", + "example": "Uber" + } + } + } diff --git a/lib/core/l10n/app_localizations.dart b/lib/core/l10n/app_localizations.dart index eec988d..efbc7ee 100644 --- a/lib/core/l10n/app_localizations.dart +++ b/lib/core/l10n/app_localizations.dart @@ -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 diff --git a/lib/core/l10n/app_localizations_en.dart b/lib/core/l10n/app_localizations_en.dart index 6d45150..f479403 100644 --- a/lib/core/l10n/app_localizations_en.dart +++ b/lib/core/l10n/app_localizations_en.dart @@ -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.'; + } } diff --git a/lib/core/l10n/app_localizations_ru.dart b/lib/core/l10n/app_localizations_ru.dart index 3f27729..b343dcb 100644 --- a/lib/core/l10n/app_localizations_ru.dart +++ b/lib/core/l10n/app_localizations_ru.dart @@ -401,4 +401,9 @@ class AppLocalizationsRu extends AppLocalizations { @override String get unexpected_error => 'Неожиданная ошибка'; + + @override + String consent_message(String appName) { + return 'Продолжая, вы соглашаетесь получать звонки или SMS-сообщения, включая автоматические, от $appName и его партнёров на указанный номер.'; + } } diff --git a/lib/core/l10n/app_localizations_uz.dart b/lib/core/l10n/app_localizations_uz.dart index c26cc86..17444df 100644 --- a/lib/core/l10n/app_localizations_uz.dart +++ b/lib/core/l10n/app_localizations_uz.dart @@ -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, qo‘ng‘iroqlar yoki SMS xabarlar olishingizga rozilik bildirasiz.'; + } } diff --git a/lib/core/router/app_routes.dart b/lib/core/router/app_routes.dart index 36f59e7..f9071af 100644 --- a/lib/core/router/app_routes.dart +++ b/lib/core/router/app_routes.dart @@ -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, diff --git a/lib/core/router/routes_name.dart b/lib/core/router/routes_name.dart index bf001c0..d771e1f 100644 --- a/lib/core/router/routes_name.dart +++ b/lib/core/router/routes_name.dart @@ -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"; } diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index cbc0c35..02c4884 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -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); + } diff --git a/lib/core/theme/app_textstyles.dart b/lib/core/theme/app_textstyles.dart index e928d03..b8fe921 100644 --- a/lib/core/theme/app_textstyles.dart +++ b/lib/core/theme/app_textstyles.dart @@ -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, diff --git a/lib/feature/auth/presentation/pages/login_page/widgets/login_body.dart b/lib/feature/auth/presentation/pages/login_page/widgets/login_body.dart index c317d36..a75fe6b 100644 --- a/lib/feature/auth/presentation/pages/login_page/widgets/login_body.dart +++ b/lib/feature/auth/presentation/pages/login_page/widgets/login_body.dart @@ -105,7 +105,7 @@ class _WLoginBodyState extends State { 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 { ), TextButton( onPressed: () { - context.pushReplacement(Routes.register); + context.push( + Routes.verifyPhoneNumber, + extra: true, + ); }, child: Text( context.loc.sign_up, diff --git a/lib/feature/auth/presentation/pages/reset_password_page/reset_password_page.dart b/lib/feature/auth/presentation/pages/reset_password_page/reset_password_page.dart new file mode 100644 index 0000000..c10a6f4 --- /dev/null +++ b/lib/feature/auth/presentation/pages/reset_password_page/reset_password_page.dart @@ -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: [], + ), + ), + ), + ); + } +} diff --git a/lib/feature/auth/presentation/pages/verify_otp_code_page/verify_otp_code_page.dart b/lib/feature/auth/presentation/pages/verify_otp_code_page/verify_otp_code_page.dart new file mode 100644 index 0000000..77f7549 --- /dev/null +++ b/lib/feature/auth/presentation/pages/verify_otp_code_page/verify_otp_code_page.dart @@ -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())), + ); + } +} diff --git a/lib/feature/auth/presentation/pages/verify_phone_number_page/verify_phone_page.dart b/lib/feature/auth/presentation/pages/verify_phone_number_page/verify_phone_page.dart new file mode 100644 index 0000000..170c1e5 --- /dev/null +++ b/lib/feature/auth/presentation/pages/verify_phone_number_page/verify_phone_page.dart @@ -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 createState() => _VerifyPhoneNumberPageState(); +} + +class _VerifyPhoneNumberPageState extends State { + late TextEditingController _phoneNumberController; + final _formKey = GlobalKey(); + + @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), + ), + ), + ), + ), + ); + } +} diff --git a/lib/feature/common/common.dart b/lib/feature/common/common.dart index e024ca3..f1b8234 100644 --- a/lib/feature/common/common.dart +++ b/lib/feature/common/common.dart @@ -1,2 +1,3 @@ export 'presentation/widgets/widgets.dart'; -export 'presentation/blocs/language_bloc/language_bloc.dart'; \ No newline at end of file +export 'presentation/blocs/language_bloc/language_bloc.dart'; +export 'data/models/success_model.dart'; \ No newline at end of file diff --git a/lib/feature/common/data/models/success_model.dart b/lib/feature/common/data/models/success_model.dart new file mode 100644 index 0000000..7b141e3 --- /dev/null +++ b/lib/feature/common/data/models/success_model.dart @@ -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 json) { + return SuccessModel( + message: json['message'] as String? ?? '', + success: json['success'] as bool? ?? false, + ); + } + + Map toJson() { + return { + 'message': message, + 'success': success, + }; + } + + SuccessModel copyWith({ + String? message, + bool? success, + }) { + return SuccessModel( + message: message ?? this.message, + success: success ?? this.success, + ); + } + + @override + List get props => [message, success]; +}