diff --git a/assets/icons/check.svg b/assets/icons/check.svg new file mode 100644 index 00000000..d0d70964 --- /dev/null +++ b/assets/icons/check.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/check_filled.svg b/assets/icons/check_filled.svg new file mode 100644 index 00000000..2366f097 --- /dev/null +++ b/assets/icons/check_filled.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/close_mark.svg b/assets/icons/close_mark.svg new file mode 100644 index 00000000..dad9d60c --- /dev/null +++ b/assets/icons/close_mark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/lib/core/theme/theme_helper.dart b/lib/core/theme/theme_helper.dart index 421247b6..301e7471 100644 --- a/lib/core/theme/theme_helper.dart +++ b/lib/core/theme/theme_helper.dart @@ -131,6 +131,7 @@ class PrimaryColors { Color get greenA70001 => const Color(0XFF00BE13); Color get green => const Color(0XFF0BB450); + Color get darkGreen => const Color(0XFF16A249); // LightGreen Color get lightGreen300 => const Color(0XFFB2DF8A); @@ -163,7 +164,7 @@ class PrimaryColors { Color get transparentBlue => const Color(0xFF2F80ED).withValues(alpha: 0.1); Color get lightGray0 => const Color(0xFFF6F6F6); - + Color get darkGrey => const Color(0xFF5B656F); Color get lightGray00 => const Color(0xFFE9E9EA); diff --git a/lib/features/registration_v2/presentation/widgets/first_step_content.dart b/lib/features/registration_v2/presentation/widgets/first_step_content.dart index d87499c8..55c46b68 100644 --- a/lib/features/registration_v2/presentation/widgets/first_step_content.dart +++ b/lib/features/registration_v2/presentation/widgets/first_step_content.dart @@ -2,7 +2,9 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; +import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_cubit.dart'; +import 'package:eatvio_app/features/registration_v2/cubit/registration_state.dart'; import 'package:eatvio_app/features/registration_v2/presentation/widgets/sex_widget.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; @@ -15,75 +17,84 @@ class FirstStepContent extends StatelessWidget { @override Widget build(BuildContext context) { final s = S.of(context); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + return BlocBuilder( + builder: (context, state) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.first_name, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const SizedBox(height: 4), - CustomTextFormField(hintText: s.your_name), - ], - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.last_name, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const SizedBox(height: 4), - CustomTextFormField(hintText: s.your_last_name), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - Text(s.email, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - CustomTextFormField(hintText: s.type_email), - const SizedBox(height: 12), - Text(s.phone, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const CustomTextFormField(hintText: '+7 (999) 999 99 99'), - const SizedBox(height: 12), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.date_of_birth, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const SizedBox(height: 4), - CustomTextFormField( - textInputAction: TextInputAction.done, - hintText: '01.01.2000', - keyboardType: TextInputType.number, - inputFormatters: [maskFormatterForBirthday], + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(s.first_name, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const SizedBox(height: 4), + CustomTextFormField(hintText: s.your_name, hasError: !state.isFirstNameValid), + if (!state.isFirstNameValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.first_name_validation_error)], + ], ), - ], - ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(s.last_name, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const SizedBox(height: 4), + CustomTextFormField(hintText: s.your_last_name, hasError: !state.isLastNameValid), + if (!state.isLastNameValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.last_name_error)], + ], + ), + ), + ], ), - const SizedBox(width: 12), - const Expanded(child: SexWidget()), + const SizedBox(height: 12), + Text(s.email, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + CustomTextFormField(hintText: s.type_email, hasError: !state.isEmailValid), + if (!state.isEmailValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.email_error)], + const SizedBox(height: 12), + Text(s.phone, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const CustomTextFormField(hintText: '+7 (999) 999 99 99'), + const SizedBox(height: 12), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(s.date_of_birth, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const SizedBox(height: 4), + CustomTextFormField( + textInputAction: TextInputAction.done, + hintText: '01.01.2000', + keyboardType: TextInputType.number, + inputFormatters: [maskFormatterForBirthday], + hasError: !state.isBirthdayValid, + ), + if (!state.isBirthdayValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.date_of_birth_error)], + ], + ), + ), + const SizedBox(width: 12), + const Expanded(child: SexWidget()), + ], + ), + const Spacer(), + CustomOutlinedButton( + onPressed: () { + context.read().nextStep(); + }, + text: s.next, + height: 52, + buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700), + buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), + ), + const SizedBox(height: 20), ], - ), - const Spacer(), - CustomOutlinedButton( - onPressed: () { - context.read().nextStep(); - }, - text: s.next, - height: 52, - buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700), - buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), - ), - const SizedBox(height: 20), - ], + ); + }, ); } } diff --git a/lib/features/registration_v2/presentation/widgets/password_field.dart b/lib/features/registration_v2/presentation/widgets/password_field.dart index cb0a7a0a..29d7882c 100644 --- a/lib/features/registration_v2/presentation/widgets/password_field.dart +++ b/lib/features/registration_v2/presentation/widgets/password_field.dart @@ -2,8 +2,11 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_cubit.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_state.dart'; +import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; class PasswordField extends StatefulWidget { const PasswordField({super.key, required this.cubit}); @@ -13,8 +16,10 @@ class PasswordField extends StatefulWidget { } class _PasswordFieldState extends State { + bool copied = false; @override Widget build(BuildContext context) { + final s = S.of(context); return BlocBuilder( bloc: widget.cubit, builder: (context, state) { @@ -26,10 +31,43 @@ class _PasswordFieldState extends State { width: double.infinity, child: Row( children: [ - Text('Klknasd978!9', style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black)), + Text('qweqweqwe', style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black)), + const Spacer(), + GestureDetector( + onTap: copied + ? null + : () async { + Clipboard.setData(const ClipboardData(text: 'qweqwe')); + setState(() { + copied = true; + }); + Future.delayed(const Duration(seconds: 3), () { + setState(() { + copied = false; + }); + }); + }, + child: SvgPicture.asset( + copied ? 'assets/icons/check_filled.svg' : 'assets/icons/copy2.svg', + height: 20, + width: 20, + colorFilter: copied ? null : ColorFilter.mode(appTheme.black, BlendMode.srcIn), + ), + ), ], ), ), + if (copied) ...[ + const SizedBox(height: 6), + Row( + children: [ + SvgPicture.asset('assets/icons/check.svg', height: 10, width: 10), + const SizedBox(width: 4), + Text(s.copied2, style: TextStyles.textSMedium.copyWith(color: appTheme.darkGreen)), + ], + ), + ], + SizedBox(height: copied ? 18 : 12), ], ); }, diff --git a/lib/features/registration_v2/presentation/widgets/second_step_content.dart b/lib/features/registration_v2/presentation/widgets/second_step_content.dart index d20de147..c6004bf6 100644 --- a/lib/features/registration_v2/presentation/widgets/second_step_content.dart +++ b/lib/features/registration_v2/presentation/widgets/second_step_content.dart @@ -5,8 +5,9 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; -import 'package:eatvio_app/core/widgets/show_error_dialog.dart'; +import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_cubit.dart'; +import 'package:eatvio_app/features/registration_v2/cubit/registration_state.dart'; import 'package:eatvio_app/features/registration_v2/presentation/widgets/phisical_activity.dart'; import 'package:eatvio_app/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart'; import 'package:eatvio_app/generated/l10n.dart'; @@ -21,100 +22,105 @@ class SecondStepContent extends StatelessWidget { @override Widget build(BuildContext context) { final s = S.of(context); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.last_step, style: TextStyles.textFS24FW700.copyWith(color: appTheme.black)), - const SizedBox(height: 12), - Text(s.user_data_desc, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const SizedBox(height: 16), - Row( + return BlocBuilder( + builder: (context, state) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.height, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const SizedBox(height: 4), - CustomTextFormField(hintText: s.type_height), - ], - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.weight, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const SizedBox(height: 4), - CustomTextFormField(hintText: s.type_weight), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - Text(s.email, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - const PhisicalActivity(), - const SizedBox(height: 12), - const Spacer(), - Row( - children: [ - InkWell( - onTap: () { - context.read().prevStep(); - }, - borderRadius: BorderRadius.circular(20), - child: Ink( - height: 52, - width: 52, - decoration: BoxDecoration(color: appTheme.gray50, borderRadius: BorderRadius.circular(20)), - child: Center(child: Icon(Icons.arrow_back_ios_new_rounded, color: appTheme.blueA400, size: 24)), - ), - ), - const SizedBox(width: 4), - Expanded( - child: CustomOutlinedButton( - onPressed: () { - showSuccessfulRegistrationBottomSheet(context, context.read()); - // showErrorDialog(context); - }, - text: s.register, - height: 52, - buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700), - buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), - ), - ), - ], - ), - const SizedBox(height: 12), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - text: 'Нажимая “Зарегистрироваться”, Вы соглашаетесь \n', - style: const TextStyle(fontSize: 12, color: Colors.black), + Text(s.last_step, style: TextStyles.textFS24FW700.copyWith(color: appTheme.black)), + const SizedBox(height: 12), + Text(s.user_data_desc, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const SizedBox(height: 16), + Row( children: [ - const TextSpan(text: 'c '), - if (!hidePlans) ...[ - TextSpan( - text: ' Публичной офертой', - style: TextStyle(fontSize: 12, color: appTheme.blueA400, decorationColor: appTheme.blueA400, decoration: TextDecoration.underline), - recognizer: TapGestureRecognizer()..onTap = () async => await launchUrl(Uri.parse('${sl().baseUrl}/oferta_bs.pdf')), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(s.height, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const SizedBox(height: 4), + CustomTextFormField(hintText: s.type_height, hasError: !state.isHeightValid), + if (!state.isHeightValid) ValidationErrorWidget(error: s.height_error), + ], + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(s.weight, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const SizedBox(height: 4), + CustomTextFormField(hintText: s.type_weight, hasError: !state.isWeightValid), + if (!state.isWeightValid) ValidationErrorWidget(error: s.weight_error), + ], ), - const TextSpan(text: ' и '), - ], - TextSpan( - text: 'Политикой конфиденциальности\nи защитой персональных данных', - style: TextStyle(fontSize: 12, color: appTheme.blueA400, decorationColor: appTheme.blueA400, decoration: TextDecoration.underline), - recognizer: TapGestureRecognizer()..onTap = () async => await launchUrl(Uri.parse('${sl().baseUrl}/docs/privacy.pdf')), ), ], ), - ), - ), - const SizedBox(height: 30), - ], + const SizedBox(height: 12), + Text(s.phisical_activity, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + const PhisicalActivity(), + const SizedBox(height: 12), + const Spacer(), + Row( + children: [ + InkWell( + onTap: () { + context.read().prevStep(); + }, + borderRadius: BorderRadius.circular(20), + child: Ink( + height: 52, + width: 52, + decoration: BoxDecoration(color: appTheme.gray50, borderRadius: BorderRadius.circular(20)), + child: Center(child: Icon(Icons.arrow_back_ios_new_rounded, color: appTheme.blueA400, size: 24)), + ), + ), + const SizedBox(width: 4), + Expanded( + child: CustomOutlinedButton( + onPressed: () { + showRegistrationBottomSheet(context, context.read(), false, () async {}); + }, + text: s.register, + height: 52, + buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700), + buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), + ), + ), + ], + ), + const SizedBox(height: 12), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: 'Нажимая “Зарегистрироваться”, Вы соглашаетесь \n', + style: const TextStyle(fontSize: 12, color: Colors.black), + children: [ + const TextSpan(text: 'c '), + if (!hidePlans) ...[ + TextSpan( + text: ' Публичной офертой', + style: TextStyle(fontSize: 12, color: appTheme.blueA400, decorationColor: appTheme.blueA400, decoration: TextDecoration.underline), + recognizer: TapGestureRecognizer()..onTap = () async => await launchUrl(Uri.parse('${sl().baseUrl}/oferta_bs.pdf')), + ), + const TextSpan(text: ' и '), + ], + TextSpan( + text: 'Политикой конфиденциальности\nи защитой персональных данных', + style: TextStyle(fontSize: 12, color: appTheme.blueA400, decorationColor: appTheme.blueA400, decoration: TextDecoration.underline), + recognizer: TapGestureRecognizer()..onTap = () async => await launchUrl(Uri.parse('${sl().baseUrl}/docs/privacy.pdf')), + ), + ], + ), + ), + ), + const SizedBox(height: 30), + ], + ); + }, ); } } diff --git a/lib/features/registration_v2/presentation/widgets/sex_widget.dart b/lib/features/registration_v2/presentation/widgets/sex_widget.dart index ccddcb17..60f0944f 100644 --- a/lib/features/registration_v2/presentation/widgets/sex_widget.dart +++ b/lib/features/registration_v2/presentation/widgets/sex_widget.dart @@ -1,5 +1,6 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; +import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_cubit.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_state.dart'; import 'package:eatvio_app/generated/l10n.dart'; @@ -14,31 +15,70 @@ class SexWidget extends StatelessWidget { final s = S.of(context); return BlocBuilder( builder: (context, state) { - return Row( - crossAxisAlignment: CrossAxisAlignment.end, + return Column( children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.sex, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), - InkWell( + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(s.sex, style: TextStyles.textSMedium.copyWith(color: appTheme.black)), + InkWell( + onTap: () { + context.read().setGender('male'); + }, + borderRadius: BorderRadius.circular(20), + child: Ink( + height: 60, + decoration: BoxDecoration( + color: const Color(0xFFF6F6F6), + borderRadius: BorderRadius.circular(20), + border: state.isGenderValid + ? state.gender == 'male' + ? Border.all(width: 2, color: appTheme.blueA400) + : null + : Border.all(width: 1, color: appTheme.red), + ), + child: Center( + child: Text( + s.male_short, + style: TextStyle( + color: state.gender == 'male' ? appTheme.blueA400 : const Color(0xFF323F4B), + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + ], + ), + ), + const SizedBox(width: 4), + Expanded( + child: InkWell( onTap: () { - context.read().setGender('male'); + context.read().setGender('female'); }, borderRadius: BorderRadius.circular(20), child: Ink( - height: 52, + height: 60, decoration: BoxDecoration( color: const Color(0xFFF6F6F6), borderRadius: BorderRadius.circular(20), - border: state.gender == 'male' ? Border.all(width: 2, color: appTheme.blueA400) : null, + border: state.isGenderValid + ? state.gender == 'female' + ? Border.all(width: 2, color: appTheme.blueA400) + : null + : Border.all(width: 1, color: appTheme.red), ), child: Center( child: Text( - s.male_short, + s.female_short, style: TextStyle( - color: state.gender == 'male' ? appTheme.blueA400 : const Color(0xFF323F4B), + color: state.gender == 'female' ? appTheme.blueA400 : const Color(0xFF323F4B), fontSize: 16, fontWeight: FontWeight.w500, ), @@ -46,36 +86,10 @@ class SexWidget extends StatelessWidget { ), ), ), - ], - ), - ), - const SizedBox(width: 4), - Expanded( - child: InkWell( - onTap: () { - context.read().setGender('female'); - }, - borderRadius: BorderRadius.circular(20), - child: Ink( - height: 52, - decoration: BoxDecoration( - color: const Color(0xFFF6F6F6), - borderRadius: BorderRadius.circular(20), - border: state.gender == 'female' ? Border.all(width: 2, color: appTheme.blueA400) : null, - ), - child: Center( - child: Text( - s.female_short, - style: TextStyle( - color: state.gender == 'female' ? appTheme.blueA400 : const Color(0xFF323F4B), - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ), ), - ), + ], ), + if (!state.isGenderValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.gender_error)], ], ); }, diff --git a/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart b/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart index 132a0b33..7514b60d 100644 --- a/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart +++ b/lib/features/registration_v2/presentation/widgets/show_successful_registration_bottom_sheet.dart @@ -1,12 +1,13 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; +import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/features/registration_v2/cubit/registration_cubit.dart'; import 'package:eatvio_app/features/registration_v2/presentation/widgets/password_field.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -void showSuccessfulRegistrationBottomSheet(BuildContext context, RegistrationCubitV2 cubit) { +void showRegistrationBottomSheet(BuildContext context, RegistrationCubitV2 cubit, bool isSuccess, Future Function() tryAgain) { showModalBottomSheet( context: context, isScrollControlled: true, @@ -14,14 +15,27 @@ void showSuccessfulRegistrationBottomSheet(BuildContext context, RegistrationCub builder: (context) => Container( margin: EdgeInsets.only(left: 8, right: 8, bottom: MediaQuery.of(context).viewInsets.bottom + MediaQuery.of(context).padding.bottom), decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), color: appTheme.whiteA700), - child: SuccessfulBottomSheet(cubit: cubit), + child: RegistrationBottomSheet(cubit: cubit, isSuccess: isSuccess), ), ); } -class SuccessfulBottomSheet extends StatelessWidget { - const SuccessfulBottomSheet({super.key, required this.cubit}); +class RegistrationBottomSheet extends StatefulWidget { + const RegistrationBottomSheet({super.key, required this.cubit, required this.isSuccess}); final RegistrationCubitV2 cubit; + final bool isSuccess; + @override + State createState() => _RegistrationBottomSheetState(); +} + +class _RegistrationBottomSheetState extends State { + late bool isSuccess; + @override + void initState() { + super.initState(); + isSuccess = widget.isSuccess; + } + @override Widget build(BuildContext context) { final s = S.of(context); @@ -29,27 +43,64 @@ class SuccessfulBottomSheet extends StatelessWidget { padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 12.0), - child: Row( - children: [ - SvgPicture.asset('assets/icons/sucess.svg', height: 16, width: 16), - const SizedBox(width: 8), - Text(s.registration_completed, style: TextStyles.textFS22FW600.copyWith(color: appTheme.black)), - ], - ), - ), + children: isSuccess + ? [ + Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: Row( + children: [ + SvgPicture.asset('assets/icons/sucess.svg', height: 16, width: 16), + const SizedBox(width: 8), + Text(s.registration_completed, style: TextStyles.textFS22FW600.copyWith(color: appTheme.black)), + ], + ), + ), - Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: Text(s.acc_has_been_created, style: TextStyles.textMMediumAuto.copyWith(color: appTheme.darkGrey)), - ), - PasswordField(cubit: cubit), - Text(s.password_desc, style: TextStyles.textSMedium.copyWith(color: appTheme.darkGrey)), - const SizedBox(width: 20), - //button - ], + Padding( + padding: const EdgeInsets.only(bottom: 16.0), + child: Text(s.acc_has_been_created, style: TextStyles.textMMediumAuto.copyWith(color: appTheme.darkGrey)), + ), + PasswordField(cubit: widget.cubit), + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: Text(s.password_desc, style: TextStyles.textSMedium.copyWith(color: appTheme.darkGrey)), + ), + + CustomOutlinedButton( + text: s.login, + height: 52, + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), + buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), + onPressed: () async {}, + ), + const SizedBox(width: 20), + //button + ] + : [ + Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: Row( + children: [ + SvgPicture.asset('assets/icons/close_mark.svg', height: 16, width: 16), + const SizedBox(width: 8), + Text(s.signUpFailed, style: TextStyles.textFS22FW600.copyWith(color: appTheme.black)), + ], + ), + ), + + Padding( + padding: const EdgeInsets.only(bottom: 16.0), + child: Text(s.error_desc, style: TextStyles.textMMediumAuto.copyWith(color: appTheme.darkGrey)), + ), + CustomOutlinedButton( + text: s.try_again, + height: 52, + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), + buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)), + onPressed: () async {}, + ), + const SizedBox(width: 20), + ], ), ); } diff --git a/lib/features/registration_v2/presentation/widgets/step_progress.dart b/lib/features/registration_v2/presentation/widgets/step_progress.dart index 96d796ad..7bb3497c 100644 --- a/lib/features/registration_v2/presentation/widgets/step_progress.dart +++ b/lib/features/registration_v2/presentation/widgets/step_progress.dart @@ -11,17 +11,12 @@ class StepProgress extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - return GestureDetector( - onTap: () { - context.read().nextStep(); - }, - child: LinearProgressIndicator( - value: state.step == 0 ? 0.5 : 1, - borderRadius: BorderRadius.circular(6), - color: appTheme.blueA400, - backgroundColor: appTheme.greyD9, - minHeight: 8, - ), + return LinearProgressIndicator( + value: state.step == 0 ? 0.5 : 1, + borderRadius: BorderRadius.circular(6), + color: appTheme.blueA400, + backgroundColor: appTheme.greyD9, + minHeight: 8, ); }, ); diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index ed7ea1b8..db607c88 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -232,6 +232,7 @@ class MessageLookup extends MessageLookupByLibrary { "continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"), "continue_": MessageLookupByLibrary.simpleMessage("Продолжить"), "copied": MessageLookupByLibrary.simpleMessage("cкопирован"), + "copied2": MessageLookupByLibrary.simpleMessage("Скопировано!"), "copy": MessageLookupByLibrary.simpleMessage("Скопировать"), "copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"), "copy_referral_link": MessageLookupByLibrary.simpleMessage( @@ -279,6 +280,9 @@ class MessageLookup extends MessageLookupByLibrary { "Дата старта начала консультации установлена", ), "date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"), + "date_of_birth_error": MessageLookupByLibrary.simpleMessage( + "Некорректная дата рождения", + ), "day": MessageLookupByLibrary.simpleMessage("День"), "dayComment": MessageLookupByLibrary.simpleMessage( "Комментарий ко всему дню", @@ -334,6 +338,9 @@ class MessageLookup extends MessageLookupByLibrary { "email_empty": MessageLookupByLibrary.simpleMessage( "Необходимо ввести адрес электронной почты", ), + "email_error": MessageLookupByLibrary.simpleMessage( + "Некорректный адрес электронной почты", + ), "email_invalid": MessageLookupByLibrary.simpleMessage( "Некорректный адрес электронной почты", ), @@ -352,6 +359,9 @@ class MessageLookup extends MessageLookupByLibrary { "enter_information": MessageLookupByLibrary.simpleMessage( "Введите информацию...", ), + "error_desc": MessageLookupByLibrary.simpleMessage( + "Произошла ошибка. Мы уже работаем над её устранением. Попробуйте позже", + ), "exit": MessageLookupByLibrary.simpleMessage("Выйти"), "expand": MessageLookupByLibrary.simpleMessage("Показать полностью"), "explainResonOfCancelation": MessageLookupByLibrary.simpleMessage( @@ -391,6 +401,9 @@ class MessageLookup extends MessageLookupByLibrary { "first_name_short": MessageLookupByLibrary.simpleMessage( "В имени должен быть минимум 1 символ", ), + "first_name_validation_error": MessageLookupByLibrary.simpleMessage( + "Имя обязательно к заполнению", + ), "fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"), "fit_type_desc": MessageLookupByLibrary.simpleMessage( "План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;", @@ -410,6 +423,7 @@ class MessageLookup extends MessageLookupByLibrary { "from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"), "from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"), "gallery": MessageLookupByLibrary.simpleMessage("Галерея"), + "gender_error": MessageLookupByLibrary.simpleMessage("Выберите пол"), "general_info": MessageLookupByLibrary.simpleMessage("Общая информация"), "go_to_diary": MessageLookupByLibrary.simpleMessage("Перейти в дневник"), "gr": MessageLookupByLibrary.simpleMessage("гр"), @@ -427,6 +441,7 @@ class MessageLookup extends MessageLookupByLibrary { "Враждебные высказывания", ), "height": MessageLookupByLibrary.simpleMessage("Рост"), + "height_error": MessageLookupByLibrary.simpleMessage("Введите рост"), "height_measurements": MessageLookupByLibrary.simpleMessage("Замер роста"), "hide": MessageLookupByLibrary.simpleMessage("Свернуть"), "hip_circumference": MessageLookupByLibrary.simpleMessage("Обхват бедер"), @@ -454,6 +469,9 @@ class MessageLookup extends MessageLookupByLibrary { "last_name_empty": MessageLookupByLibrary.simpleMessage( "Фамилия обязательна для заполнения", ), + "last_name_error": MessageLookupByLibrary.simpleMessage( + "Фамилия обязательна для заполнения", + ), "last_name_short": MessageLookupByLibrary.simpleMessage( "В фамилии должен быть минимум 6 символов", ), @@ -474,6 +492,7 @@ class MessageLookup extends MessageLookupByLibrary { "Ссылка успешно скопирована", ), "loading": MessageLookupByLibrary.simpleMessage("Загрузка..."), + "login": MessageLookupByLibrary.simpleMessage("Войти в аккаунт"), "lower": MessageLookupByLibrary.simpleMessage("Нижнее"), "mail_was_copied": MessageLookupByLibrary.simpleMessage( "Почта успешно скопирована", @@ -591,7 +610,13 @@ class MessageLookup extends MessageLookupByLibrary { "pending_payment": MessageLookupByLibrary.simpleMessage("Ожидается оплата"), "personal": MessageLookupByLibrary.simpleMessage("Персональные"), "personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"), + "phisical_activity": MessageLookupByLibrary.simpleMessage( + "Уровень физической активности", + ), "phone": MessageLookupByLibrary.simpleMessage("Телефон"), + "phone_error": MessageLookupByLibrary.simpleMessage( + "Некорректный номер телефона", + ), "photo": MessageLookupByLibrary.simpleMessage("Фото"), "physical_fitness": MessageLookupByLibrary.simpleMessage( "Физическая форма", @@ -681,6 +706,9 @@ class MessageLookup extends MessageLookupByLibrary { "settings": MessageLookupByLibrary.simpleMessage("Настройки"), "sex": MessageLookupByLibrary.simpleMessage("Пол"), "share": MessageLookupByLibrary.simpleMessage("Поделиться"), + "signUpFailed": MessageLookupByLibrary.simpleMessage( + "Регистрация не удалась!", + ), "skip": MessageLookupByLibrary.simpleMessage("Пропустить"), "slim": MessageLookupByLibrary.simpleMessage("Похудение"), "slim_type": MessageLookupByLibrary.simpleMessage("Похудение"), @@ -818,6 +846,7 @@ class MessageLookup extends MessageLookupByLibrary { "weapon": MessageLookupByLibrary.simpleMessage("Оружие"), "weight": MessageLookupByLibrary.simpleMessage("Вес"), "weight_chart": MessageLookupByLibrary.simpleMessage("График веса"), + "weight_error": MessageLookupByLibrary.simpleMessage("Введите вес"), "weight_measurements": MessageLookupByLibrary.simpleMessage("Замер веса"), "wellness": MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"), "wellness_type": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 4c5fd8fb..19c2d935 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -3683,6 +3683,126 @@ class S { args: [], ); } + + /// `Имя обязательно к заполнению` + String get first_name_validation_error { + return Intl.message( + 'Имя обязательно к заполнению', + name: 'first_name_validation_error', + desc: '', + args: [], + ); + } + + /// `Фамилия обязательна для заполнения` + String get last_name_error { + return Intl.message( + 'Фамилия обязательна для заполнения', + name: 'last_name_error', + desc: '', + args: [], + ); + } + + /// `Некорректный адрес электронной почты` + String get email_error { + return Intl.message( + 'Некорректный адрес электронной почты', + name: 'email_error', + desc: '', + args: [], + ); + } + + /// `Некорректный номер телефона` + String get phone_error { + return Intl.message( + 'Некорректный номер телефона', + name: 'phone_error', + desc: '', + args: [], + ); + } + + /// `Выберите пол` + String get gender_error { + return Intl.message( + 'Выберите пол', + name: 'gender_error', + desc: '', + args: [], + ); + } + + /// `Некорректная дата рождения` + String get date_of_birth_error { + return Intl.message( + 'Некорректная дата рождения', + name: 'date_of_birth_error', + desc: '', + args: [], + ); + } + + /// `Введите рост` + String get height_error { + return Intl.message( + 'Введите рост', + name: 'height_error', + desc: '', + args: [], + ); + } + + /// `Введите вес` + String get weight_error { + return Intl.message( + 'Введите вес', + name: 'weight_error', + desc: '', + args: [], + ); + } + + /// `Уровень физической активности` + String get phisical_activity { + return Intl.message( + 'Уровень физической активности', + name: 'phisical_activity', + desc: '', + args: [], + ); + } + + /// `Скопировано!` + String get copied2 { + return Intl.message('Скопировано!', name: 'copied2', desc: '', args: []); + } + + /// `Войти в аккаунт` + String get login { + return Intl.message('Войти в аккаунт', name: 'login', desc: '', args: []); + } + + /// `Регистрация не удалась!` + String get signUpFailed { + return Intl.message( + 'Регистрация не удалась!', + name: 'signUpFailed', + desc: '', + args: [], + ); + } + + /// `Произошла ошибка. Мы уже работаем над её устранением. Попробуйте позже` + String get error_desc { + return Intl.message( + 'Произошла ошибка. Мы уже работаем над её устранением. Попробуйте позже', + name: 'error_desc', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 6c9b22d2..1ce89654 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -436,6 +436,19 @@ "registration_completed": "Регистрация завершена!", "acc_has_been_created": "Ваш аккаунт создан. Для входа используйте этот пароль:", "password_desc": "Сохраните его в надежном месте! Вы сможете изменить пароль в настройках профиля", - "acc_has_been_created_btn": "Войти в аккаунт" + "acc_has_been_created_btn": "Войти в аккаунт", + "first_name_validation_error": "Имя обязательно к заполнению", + "last_name_error": "Фамилия обязательна для заполнения", + "email_error": "Некорректный адрес электронной почты", + "phone_error": "Некорректный номер телефона", + "gender_error": "Выберите пол", + "date_of_birth_error": "Некорректная дата рождения", + "height_error": "Введите рост", + "weight_error": "Введите вес", + "phisical_activity": "Уровень физической активности", + "copied2": "Скопировано!", + "login": "Войти в аккаунт", + "signUpFailed": "Регистрация не удалась!", + "error_desc": "Произошла ошибка. Мы уже работаем над её устранением. Попробуйте позже" }