forked from eatvio/eatvio_app
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -1,176 +1,178 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.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';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
|
||||
|
||||
class FirstStepContent extends StatefulWidget {
|
||||
const FirstStepContent({super.key});
|
||||
|
||||
@override
|
||||
State<FirstStepContent> createState() => _FirstStepContentState();
|
||||
}
|
||||
|
||||
class _FirstStepContentState extends State<FirstStepContent> {
|
||||
final maskFormatterForBirthday = MaskTextInputFormatter(mask: '##.##.####', filter: {"#": RegExp(r'[0-9]')}, type: MaskAutoCompletionType.lazy);
|
||||
|
||||
final firstNameController = TextEditingController();
|
||||
|
||||
final lastNameController = TextEditingController();
|
||||
|
||||
final emailController = TextEditingController();
|
||||
|
||||
final phoneController = TextEditingController();
|
||||
|
||||
final dateController = TextEditingController();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
firstNameController.text = context.read<RegistrationCubitV2>().state.firstName;
|
||||
lastNameController.text = context.read<RegistrationCubitV2>().state.lastName;
|
||||
emailController.text = context.read<RegistrationCubitV2>().state.email;
|
||||
phoneController.text = context.read<RegistrationCubitV2>().state.phone;
|
||||
dateController.text = context.read<RegistrationCubitV2>().state.birthday?.format('dd.MM.yyyy') ?? '';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return BlocBuilder<RegistrationCubitV2, RegistrationStateV2>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
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,
|
||||
controller: firstNameController,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setFirstName(val);
|
||||
},
|
||||
),
|
||||
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,
|
||||
controller: lastNameController,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setLastName(val);
|
||||
},
|
||||
),
|
||||
if (!state.isLastNameValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.last_name_error)],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(s.email, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
CustomTextFormField(
|
||||
hintText: s.type_email,
|
||||
hasError: !state.isEmailValid,
|
||||
controller: emailController,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setEmail(val);
|
||||
},
|
||||
),
|
||||
if (!state.isEmailValid) ...[
|
||||
const SizedBox(height: 4),
|
||||
ValidationErrorWidget(error: state.emailDisplayError.isEmpty ? s.email_error : state.emailDisplayError),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
Text(s.phone, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
Column(
|
||||
children: [
|
||||
CustomTextFormField(
|
||||
hintText: '+7 (999) 999 99 99',
|
||||
controller: phoneController,
|
||||
hasError: !state.isPhoneValid,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setPhone(val);
|
||||
},
|
||||
),
|
||||
if (!state.isPhoneValid) ...[
|
||||
const SizedBox(height: 4),
|
||||
ValidationErrorWidget(error: state.phoneDisplayError.isEmpty ? s.phone_error : state.phoneDisplayError),
|
||||
],
|
||||
],
|
||||
),
|
||||
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,
|
||||
controller: dateController,
|
||||
onChanged: (val) {
|
||||
final dateArray = val.split('.');
|
||||
if (dateArray.length != 3) return;
|
||||
final date = DateTime(int.parse(dateArray[2]), int.parse(dateArray[1]), int.parse(dateArray[0]));
|
||||
context.read<RegistrationCubitV2>().setBirthday(date);
|
||||
},
|
||||
),
|
||||
if (!state.isBirthdayValid) ...[
|
||||
const SizedBox(height: 4),
|
||||
ValidationErrorWidget(error: state.dateOfBirthDisplayError.isEmpty ? s.date_of_birth_error : state.dateOfBirthDisplayError),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const Expanded(child: SexWidget()),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
CustomOutlinedButton(
|
||||
onPressed: () {
|
||||
context.read<RegistrationCubitV2>().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),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.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';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
|
||||
|
||||
class FirstStepContent extends StatefulWidget {
|
||||
const FirstStepContent({super.key});
|
||||
|
||||
@override
|
||||
State<FirstStepContent> createState() => _FirstStepContentState();
|
||||
}
|
||||
|
||||
class _FirstStepContentState extends State<FirstStepContent> {
|
||||
final maskFormatterForBirthday = MaskTextInputFormatter(mask: '##.##.####', filter: {"#": RegExp(r'[0-9]')}, type: MaskAutoCompletionType.lazy);
|
||||
|
||||
final firstNameController = TextEditingController();
|
||||
|
||||
final lastNameController = TextEditingController();
|
||||
|
||||
final emailController = TextEditingController();
|
||||
|
||||
final phoneController = TextEditingController();
|
||||
|
||||
final dateController = TextEditingController();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
firstNameController.text = context.read<RegistrationCubitV2>().state.firstName;
|
||||
lastNameController.text = context.read<RegistrationCubitV2>().state.lastName;
|
||||
emailController.text = context.read<RegistrationCubitV2>().state.email;
|
||||
phoneController.text = context.read<RegistrationCubitV2>().state.phone;
|
||||
dateController.text = context.read<RegistrationCubitV2>().state.birthday?.format('dd.MM.yyyy') ?? '';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return BlocBuilder<RegistrationCubitV2, RegistrationStateV2>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
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,
|
||||
controller: firstNameController,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setFirstName(val);
|
||||
},
|
||||
),
|
||||
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,
|
||||
controller: lastNameController,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setLastName(val);
|
||||
},
|
||||
),
|
||||
if (!state.isLastNameValid) ...[const SizedBox(height: 4), ValidationErrorWidget(error: s.last_name_error)],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(s.email, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
CustomTextFormField(
|
||||
hintText: s.type_email,
|
||||
hasError: !state.isEmailValid,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
controller: emailController,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setEmail(val);
|
||||
},
|
||||
),
|
||||
if (!state.isEmailValid) ...[
|
||||
const SizedBox(height: 4),
|
||||
ValidationErrorWidget(error: state.emailDisplayError.isEmpty ? s.email_error : state.emailDisplayError),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
Text(s.phone, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
Column(
|
||||
children: [
|
||||
CustomTextFormField(
|
||||
hintText: '+7 (999) 999 99 99',
|
||||
controller: phoneController,
|
||||
hasError: !state.isPhoneValid,
|
||||
keyboardType: TextInputType.phone,
|
||||
onChanged: (val) {
|
||||
context.read<RegistrationCubitV2>().setPhone(val);
|
||||
},
|
||||
),
|
||||
if (!state.isPhoneValid) ...[
|
||||
const SizedBox(height: 4),
|
||||
ValidationErrorWidget(error: state.phoneDisplayError.isEmpty ? s.phone_error : state.phoneDisplayError),
|
||||
],
|
||||
],
|
||||
),
|
||||
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,
|
||||
controller: dateController,
|
||||
onChanged: (val) {
|
||||
final dateArray = val.split('.');
|
||||
if (dateArray.length != 3) return;
|
||||
final date = DateTime(int.parse(dateArray[2]), int.parse(dateArray[1]), int.parse(dateArray[0]));
|
||||
context.read<RegistrationCubitV2>().setBirthday(date);
|
||||
},
|
||||
),
|
||||
if (!state.isBirthdayValid) ...[
|
||||
const SizedBox(height: 4),
|
||||
ValidationErrorWidget(error: state.dateOfBirthDisplayError.isEmpty ? s.date_of_birth_error : state.dateOfBirthDisplayError),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const Expanded(child: SexWidget()),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
CustomOutlinedButton(
|
||||
onPressed: () {
|
||||
context.read<RegistrationCubitV2>().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),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,12 @@ class _SecondStepContentState extends State<SecondStepContent> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
heightController.text = context.read<RegistrationCubitV2>().state.height.toString();
|
||||
weightController.text = context.read<RegistrationCubitV2>().state.weight.toString();
|
||||
heightController.text = context.read<RegistrationCubitV2>().state.height.toString() == '0'
|
||||
? ''
|
||||
: context.read<RegistrationCubitV2>().state.height.toString();
|
||||
weightController.text = context.read<RegistrationCubitV2>().state.weight.toString() == '0'
|
||||
? ''
|
||||
: context.read<RegistrationCubitV2>().state.weight.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -61,6 +65,7 @@ class _SecondStepContentState extends State<SecondStepContent> {
|
||||
hintText: s.type_height,
|
||||
hasError: !state.isHeightValid,
|
||||
controller: heightController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputType: const TextInputType.numberWithOptions(),
|
||||
onChanged: (val) {
|
||||
final height = int.tryParse(val);
|
||||
@@ -84,6 +89,7 @@ class _SecondStepContentState extends State<SecondStepContent> {
|
||||
hintText: s.type_weight,
|
||||
hasError: !state.isWeightValid,
|
||||
controller: weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputType: const TextInputType.numberWithOptions(),
|
||||
onChanged: (val) {
|
||||
final weight = int.tryParse(val);
|
||||
|
||||
Reference in New Issue
Block a user