forked from eatvio/eatvio_app
Merge pull request 'registration_validation' (#2) from registration_validation into main
Reviewed-on: maxxkim/eatvio_app#2
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
import 'package:eatvio_app/core/app_export.dart';
|
||||
//import 'package:eatvio_app/core/app_export.dart';
|
||||
|
||||
class ApiClient {}
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class UserRegistrationSheet {
|
||||
String name;
|
||||
String firstName;
|
||||
String lastName;
|
||||
String email;
|
||||
String password;
|
||||
String passwordConfirmation;
|
||||
bool termsAccepted;
|
||||
DateTime birthdate;
|
||||
String termsAccepted;
|
||||
String birthdate;
|
||||
String gender;
|
||||
String country;
|
||||
String city;
|
||||
String lang;
|
||||
int weight;
|
||||
int height;
|
||||
int chestCircumference;
|
||||
int waistCircumference;
|
||||
int hipCircumference;
|
||||
int bloodPressureUp;
|
||||
int bloodPressureDown;
|
||||
bool hasHypo = false;
|
||||
bool hasHyper = false;
|
||||
String weight;
|
||||
String height;
|
||||
String chestCircumference;
|
||||
String waistCircumference;
|
||||
String hipCircumference;
|
||||
String bloodPressureUp;
|
||||
String bloodPressureDown;
|
||||
String hasHypo = '';
|
||||
String hasHyper = '';
|
||||
String aboutAllergy = '';
|
||||
String aboutTakingPils = '';
|
||||
String aboutSportHobbies = '';
|
||||
@@ -30,6 +28,7 @@ class UserRegistrationSheet {
|
||||
String additionalInfo = '';
|
||||
|
||||
UserRegistrationSheet({
|
||||
required this.name,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
@@ -60,13 +59,14 @@ class UserRegistrationSheet {
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'first_name': firstName,
|
||||
'last_name': lastName,
|
||||
'email': email,
|
||||
'password': password,
|
||||
'password_confirmation': passwordConfirmation,
|
||||
'terms': termsAccepted,
|
||||
'birthdate': birthdate.toIso8601String(),
|
||||
'birthdate': birthdate.toString(),
|
||||
'gender': gender,
|
||||
'country': country,
|
||||
'city': city,
|
||||
@@ -88,15 +88,4 @@ class UserRegistrationSheet {
|
||||
'additional_info': additionalInfo,
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> sendJson(Uri url) async {
|
||||
final response = await http.post(
|
||||
url,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: jsonEncode(toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to send data');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'ru/ru_translations.dart';
|
||||
import 'en_us/en_us_translations.dart';
|
||||
//import 'en_us/en_us_translations.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import '../core/app_export.dart';
|
||||
@@ -9,10 +9,12 @@ class AppLocalization {
|
||||
|
||||
Locale locale;
|
||||
|
||||
static final Map<String, Map<String, String>> _localizedValues = {'ru': ru};
|
||||
static final Map<String, Map<String, String>> __localizedValues = {
|
||||
'en': enUs
|
||||
static final Map<String, Map<String, String>> _localizedValues = {
|
||||
'ru': ru,
|
||||
};
|
||||
/*static final Map<String, Map<String, String>> __localizedValues = {
|
||||
'en': enUs
|
||||
};*/
|
||||
|
||||
static AppLocalization of() {
|
||||
return Localizations.of<AppLocalization>(
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
final Map<String, String> ru = {
|
||||
//credentials Screen
|
||||
"user_registration": "Регистрация пользователя",
|
||||
"email": "Элетронная почта",
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"password_confirmation": "Подтвердите пароль",
|
||||
|
||||
//name Screen
|
||||
"first_name": "Имя",
|
||||
"last_name": "Фамилия",
|
||||
"what_is_your_name": "Как вас зовут?",
|
||||
|
||||
// date_of_birth Screen
|
||||
"date_of_birth": "Дата рождения",
|
||||
// city_of_living Screen
|
||||
"country": "Страна", "Russia": "Россия", "city": "Город", "Moscow": "Москва",
|
||||
"place_of_living": "Место проживания",
|
||||
"what_is_your_name": "Как вас зовут?",
|
||||
|
||||
// body_circumferences Screen
|
||||
"hip_circumference": "Обхват бедр", "chest_circumference": "Обхват груди",
|
||||
"hip_circumference": "Обхват бедер", "chest_circumference": "Обхват груди",
|
||||
"waist_circumference": "Обхват талии",
|
||||
"initial_measurements": "Первичные замеры",
|
||||
|
||||
@@ -61,14 +65,38 @@ final Map<String, String> ru = {
|
||||
// language_select Screen
|
||||
"lbl_english": "English",
|
||||
"finish": "Завершить",
|
||||
"preferred_language": "Предпочетаемый язык общения?",
|
||||
"preferred_language": "Предпочитаемый язык общения?",
|
||||
|
||||
// Common String
|
||||
"continue": "Продолжить", "skip": "Пропустить",
|
||||
"fill_in_information": "Заполните информацию:",
|
||||
"enter_information": "Введите информацию...",
|
||||
|
||||
// Network Error String
|
||||
// Network Error String
|
||||
"msg_network_err": "Сетевая ошибка!",
|
||||
"msg_something_went_wrong": "Что то пошло не так!",
|
||||
|
||||
// Errors
|
||||
// Credentials
|
||||
"email_empty": "Необходимо ввести адрес электронной почты",
|
||||
"email_invalid": "Некорректный адрес электронной почты",
|
||||
"password_empty": "Пароль обязателен для заполнения",
|
||||
"password_short": "В пароле должно быть минимум 6 символов",
|
||||
"name_empty": "Имя пользователя обязательно для заполнения",
|
||||
"name_short": "В имени пользователя должно быть минимум 6 символов",
|
||||
"password_confirmation_mismatch": "Пароли не совпадают",
|
||||
|
||||
// Name
|
||||
"first_name_empty": "Имя обязательно для заполнения",
|
||||
"first_name_short": "В имени должен быть минимум 1 символ",
|
||||
"last_name_empty": "Фамилия обязательна для заполнения",
|
||||
"last_name_short": "В фамилии должен быть минимум 6 символов",
|
||||
|
||||
// Body Circumference
|
||||
"circumference_empty": "Все замеры обязательны к заполнению",
|
||||
"circumference_is_not_a_number": "Все замеры должны быть числами",
|
||||
|
||||
// Body Circumference
|
||||
"pressure_empty": "Все показатели давления обязательны к заполнению",
|
||||
"pressure_is_not_a_number": "Все показатели давления должны быть числами",
|
||||
};
|
||||
|
||||
@@ -9,8 +9,9 @@ import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_m
|
||||
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class AdditionalInformationScreen extends StatefulWidget {
|
||||
class AdditionalInformationScreen extends StatelessWidget {
|
||||
const AdditionalInformationScreen({Key? key}) : super(key: key);
|
||||
|
||||
static Widget builder(BuildContext context) {
|
||||
@@ -25,13 +26,6 @@ class AdditionalInformationScreen extends StatefulWidget {
|
||||
child: AdditionalInformationScreen());
|
||||
}
|
||||
|
||||
@override
|
||||
State<AdditionalInformationScreen> createState() =>
|
||||
_AdditionalInformationScreenState();
|
||||
}
|
||||
|
||||
class _AdditionalInformationScreenState
|
||||
extends State<AdditionalInformationScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
@@ -70,17 +64,19 @@ class _AdditionalInformationScreenState
|
||||
margin: EdgeInsets.only(
|
||||
left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: () {
|
||||
var message;
|
||||
onPressed: () async {
|
||||
UserRegistrationSheet sheet = state
|
||||
.additionalInformationModelObj!
|
||||
.userRegistrationSheet;
|
||||
sheet.additionalInfo = state.editTextController!.text;
|
||||
message = sheet.toJson();
|
||||
print(message);
|
||||
final response = await http.post(
|
||||
Uri.parse('http://10.55.5.126:1092/api/register'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode(sheet),
|
||||
);
|
||||
print(response.body);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
@@ -140,7 +136,7 @@ class _AdditionalInformationScreenState
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('Регистрация завершена!'),
|
||||
content: const Text(text),
|
||||
content: const Text('1'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
|
||||
@@ -11,8 +11,7 @@ class AdditionalInformationModel extends Equatable {
|
||||
|
||||
AdditionalInformationModel copyWith() {
|
||||
return AdditionalInformationModel(
|
||||
userRegistrationSheet:
|
||||
userRegistrationSheet ?? this.userRegistrationSheet,
|
||||
userRegistrationSheet: userRegistrationSheet,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,16 +50,16 @@ class _AllergiesScreenState extends State<AllergiesScreen> {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
child: LinearProgressIndicator(
|
||||
value: 0.62,
|
||||
value: 0.76,
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
appTheme.blueA400)))),
|
||||
SizedBox(height: 22.v),
|
||||
Text("allergies_presence".tr,
|
||||
style: CustomTextStyles.headlineSmallMulish),
|
||||
style: theme.textTheme.headlineSmall),
|
||||
Spacer(flex: 36),
|
||||
_buildTextFormField(context),
|
||||
Spacer(flex: 63),
|
||||
Spacer(flex: 54),
|
||||
BlocBuilder<AllergiesBloc, AllergiesState>(
|
||||
builder: (context, state) {
|
||||
return NextStepButton(
|
||||
@@ -79,8 +79,21 @@ class _AllergiesScreenState extends State<AllergiesScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
Text("skip".tr, style: theme.textTheme.bodyLarge)
|
||||
BlocBuilder<AllergiesBloc, AllergiesState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
UserRegistrationSheet sheet =
|
||||
state.allergiesModelObj!.userRegistrationSheet;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.medicineIntakeScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
},
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
}),
|
||||
]))));
|
||||
}
|
||||
|
||||
@@ -120,11 +133,4 @@ class _AllergiesScreenState extends State<AllergiesScreen> {
|
||||
onTapArrowLeft(BuildContext context) {
|
||||
NavigatorService.goBack();
|
||||
}
|
||||
|
||||
/// Navigates to the medicineIntakeScreen when the action is triggered.
|
||||
navigateToMedicine(BuildContext context) {
|
||||
NavigatorService.pushNamed(
|
||||
AppRoutes.medicineIntakeScreen,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ class AllergiesModel extends Equatable {
|
||||
|
||||
AllergiesModel copyWith() {
|
||||
return AllergiesModel(
|
||||
userRegistrationSheet:
|
||||
userRegistrationSheet ?? this.userRegistrationSheet,
|
||||
userRegistrationSheet: userRegistrationSheet,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ class BloodPressureBloc extends Bloc<BloodPressureEvent, BloodPressureState> {
|
||||
Emitter<BloodPressureState> emit,
|
||||
) {
|
||||
if (event.value.id == 1) {
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHyper = true;
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHyper = '1';
|
||||
} else {
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHyper = false;
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHyper = '0';
|
||||
}
|
||||
emit(state.copyWith(selectedHyperValue: event.value));
|
||||
}
|
||||
@@ -30,9 +30,9 @@ class BloodPressureBloc extends Bloc<BloodPressureEvent, BloodPressureState> {
|
||||
Emitter<BloodPressureState> emit,
|
||||
) {
|
||||
if (event.value.id == 1) {
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHypo = true;
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHypo = '1';
|
||||
} else {
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHypo = false;
|
||||
state.bloodPressureModelObj!.userRegistrationSheet.hasHypo = '0';
|
||||
}
|
||||
emit(state.copyWith(selectedHypoValue: event.value));
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class _BloodPressureScreenState extends State<BloodPressureScreen> {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
child: LinearProgressIndicator(
|
||||
value: 0.76,
|
||||
value: 0.62,
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
appTheme.blueA400))))),
|
||||
@@ -175,21 +175,61 @@ class _BloodPressureScreenState extends State<BloodPressureScreen> {
|
||||
left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: () {
|
||||
UserRegistrationSheet sheet = state
|
||||
.bloodPressureModelObj!.userRegistrationSheet;
|
||||
sheet.bloodPressureUp =
|
||||
int.tryParse(state.upPressureController!.text)!;
|
||||
sheet.bloodPressureDown =
|
||||
int.tryParse(state.downPressureController!.text)!;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.favoriteSportsScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
List<String> errors = validateFields(
|
||||
state.upPressureController!.text,
|
||||
state.downPressureController!.text);
|
||||
if (errors.isEmpty) {
|
||||
UserRegistrationSheet sheet = state
|
||||
.bloodPressureModelObj!.userRegistrationSheet;
|
||||
sheet.bloodPressureUp =
|
||||
state.upPressureController!.text;
|
||||
sheet.bloodPressureDown =
|
||||
state.downPressureController!.text;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.favoriteSportsScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
} else {
|
||||
String errorMessage = '';
|
||||
|
||||
for (var error in errors) {
|
||||
errorMessage += error + '\n\n';
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Ошибка'),
|
||||
content: Text(errorMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
Text("skip".tr, style: theme.textTheme.bodyLarge)
|
||||
BlocBuilder<BloodPressureBloc, BloodPressureState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
UserRegistrationSheet sheet =
|
||||
state.bloodPressureModelObj!.userRegistrationSheet;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.allergiesScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
},
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
}),
|
||||
]))));
|
||||
}
|
||||
|
||||
@@ -212,10 +252,21 @@ class _BloodPressureScreenState extends State<BloodPressureScreen> {
|
||||
NavigatorService.goBack();
|
||||
}
|
||||
|
||||
/// Navigates to the favoriteSportsScreen when the action is triggered.
|
||||
navigateToSports(BuildContext context) {
|
||||
NavigatorService.pushNamed(
|
||||
AppRoutes.favoriteSportsScreen,
|
||||
);
|
||||
List<String> validateFields(
|
||||
String bloodPressureUp,
|
||||
String bloodPressureDown,
|
||||
) {
|
||||
List<String> errors = [];
|
||||
|
||||
if (bloodPressureUp.isEmpty | bloodPressureDown.isEmpty) {
|
||||
errors.add('pressure_empty'.tr);
|
||||
}
|
||||
|
||||
if (![bloodPressureUp, bloodPressureDown]
|
||||
.every((pressure) => int.tryParse(pressure) != null)) {
|
||||
errors.add('pressure_is_not_a_number'.tr);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,23 +106,50 @@ class BodyCircumferencesScreen extends StatelessWidget {
|
||||
left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: () {
|
||||
UserRegistrationSheet sheet = state
|
||||
.bodyCircumferencesModelObj!
|
||||
.userRegistrationSheet;
|
||||
sheet.chestCircumference = int.tryParse(
|
||||
state.chestCircumferenceController!.text)!;
|
||||
sheet.waistCircumference = int.tryParse(
|
||||
state.waistCircumferenceController!.text)!;
|
||||
sheet.hipCircumference = int.tryParse(
|
||||
state.hipCircumferenceController!.text)!;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.weightScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
List<String> errors = validateFields(
|
||||
state.chestCircumferenceController!.text,
|
||||
state.waistCircumferenceController!.text,
|
||||
state.hipCircumferenceController!.text);
|
||||
if (errors.isEmpty) {
|
||||
UserRegistrationSheet sheet = state
|
||||
.bodyCircumferencesModelObj!
|
||||
.userRegistrationSheet;
|
||||
sheet.chestCircumference =
|
||||
state.chestCircumferenceController!.text;
|
||||
sheet.waistCircumference =
|
||||
state.waistCircumferenceController!.text;
|
||||
sheet.hipCircumference =
|
||||
state.hipCircumferenceController!.text;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.weightScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
} else {
|
||||
String errorMessage = '';
|
||||
|
||||
for (var error in errors) {
|
||||
errorMessage += error + '\n\n';
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Ошибка'),
|
||||
content: Text(errorMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
@@ -151,4 +178,25 @@ class BodyCircumferencesScreen extends StatelessWidget {
|
||||
AppRoutes.weightScreen,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> validateFields(
|
||||
String chestCircumference,
|
||||
String waistCircumference,
|
||||
String hipCircumference,
|
||||
) {
|
||||
List<String> errors = [];
|
||||
|
||||
if (chestCircumference.isEmpty |
|
||||
waistCircumference.isEmpty |
|
||||
hipCircumference.isEmpty) {
|
||||
errors.add('circumference_empty'.tr);
|
||||
}
|
||||
|
||||
if (![chestCircumference, waistCircumference, hipCircumference]
|
||||
.every((circumference) => int.tryParse(circumference) != null)) {
|
||||
errors.add('circumference_is_not_a_number'.tr);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ class BodyCircumferencesModel extends Equatable {
|
||||
|
||||
BodyCircumferencesModel copyWith() {
|
||||
return BodyCircumferencesModel(
|
||||
userRegistrationSheet:
|
||||
userRegistrationSheet ?? this.userRegistrationSheet,
|
||||
userRegistrationSheet: userRegistrationSheet,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ class CityOfLivingScreen extends StatelessWidget {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ class CityOfLivingModel extends Equatable {
|
||||
List<SelectionPopupModel>? dropdownItemList1,
|
||||
}) {
|
||||
return CityOfLivingModel(
|
||||
userRegistrationSheet:
|
||||
userRegistrationSheet ?? this.userRegistrationSheet,
|
||||
userRegistrationSheet: userRegistrationSheet,
|
||||
dropdownItemList: dropdownItemList ?? this.dropdownItemList,
|
||||
dropdownItemList1: dropdownItemList1 ?? this.dropdownItemList1,
|
||||
);
|
||||
|
||||
@@ -16,7 +16,8 @@ class CredentialsBloc extends Bloc<CredentialsEvent, CredentialsState> {
|
||||
Emitter<CredentialsState> emit,
|
||||
) async {
|
||||
emit(state.copyWith(
|
||||
valueController: TextEditingController(),
|
||||
emailController: TextEditingController(),
|
||||
nameController: TextEditingController(),
|
||||
passwordController: TextEditingController(),
|
||||
passwordConfirmationController: TextEditingController()));
|
||||
}
|
||||
|
||||
@@ -5,13 +5,16 @@ part of 'credentials_bloc.dart';
|
||||
/// Represents the state of Credentials in the application.
|
||||
class CredentialsState extends Equatable {
|
||||
CredentialsState({
|
||||
this.valueController,
|
||||
this.emailController,
|
||||
this.nameController,
|
||||
this.passwordController,
|
||||
this.passwordConfirmationController,
|
||||
this.credentialsModelObj,
|
||||
});
|
||||
|
||||
TextEditingController? valueController;
|
||||
TextEditingController? emailController;
|
||||
|
||||
TextEditingController? nameController;
|
||||
|
||||
TextEditingController? passwordController;
|
||||
|
||||
@@ -21,19 +24,22 @@ class CredentialsState extends Equatable {
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
valueController,
|
||||
emailController,
|
||||
nameController,
|
||||
passwordController,
|
||||
passwordConfirmationController,
|
||||
credentialsModelObj,
|
||||
];
|
||||
CredentialsState copyWith({
|
||||
TextEditingController? valueController,
|
||||
TextEditingController? nameController,
|
||||
TextEditingController? emailController,
|
||||
TextEditingController? passwordController,
|
||||
TextEditingController? passwordConfirmationController,
|
||||
CredentialsModel? credentialsModelObj,
|
||||
}) {
|
||||
return CredentialsState(
|
||||
valueController: valueController ?? this.valueController,
|
||||
emailController: emailController ?? this.emailController,
|
||||
nameController: nameController ?? this.nameController,
|
||||
passwordController: passwordController ?? this.passwordController,
|
||||
passwordConfirmationController:
|
||||
passwordConfirmationController ?? this.passwordConfirmationController,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'bloc/credentials_bloc.dart';
|
||||
import 'models/credentials_model.dart';
|
||||
import 'package:eatvio_app/core/app_export.dart';
|
||||
import 'package:eatvio_app/widgets/app_bar/appbar_leading_image.dart';
|
||||
import 'package:eatvio_app/widgets/app_bar/appbar_title_image.dart';
|
||||
import 'package:eatvio_app/widgets/app_bar/custom_app_bar.dart';
|
||||
import 'package:validators/validators.dart';
|
||||
import 'package:eatvio_app/widgets/next_step_button.dart';
|
||||
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
|
||||
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
|
||||
@@ -58,10 +58,21 @@ class CredentialsScreen extends StatelessWidget {
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<CredentialsBloc, CredentialsState,
|
||||
TextEditingController?>(
|
||||
selector: (state) => state.valueController,
|
||||
builder: (context, valueController) {
|
||||
selector: (state) => state.emailController,
|
||||
builder: (context, emailController) {
|
||||
return CustomTextFormField(
|
||||
controller: valueController,
|
||||
controller: emailController,
|
||||
textInputAction: TextInputAction.done);
|
||||
}),
|
||||
SizedBox(height: 22.v),
|
||||
Text("username".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<CredentialsBloc, CredentialsState,
|
||||
TextEditingController?>(
|
||||
selector: (state) => state.nameController,
|
||||
builder: (context, nameController) {
|
||||
return CustomTextFormField(
|
||||
controller: nameController,
|
||||
textInputAction: TextInputAction.done);
|
||||
}),
|
||||
SizedBox(height: 19.v),
|
||||
@@ -98,20 +109,49 @@ class CredentialsScreen extends StatelessWidget {
|
||||
left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: () {
|
||||
UserRegistrationSheet sheet =
|
||||
state.credentialsModelObj!.userRegistrationSheet;
|
||||
sheet.email = state.valueController!.text;
|
||||
sheet.password = state.passwordController!.text;
|
||||
sheet.passwordConfirmation =
|
||||
state.passwordConfirmationController!.text;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.nameScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
List<String> errors = validateFields(
|
||||
state.emailController!.text,
|
||||
state.nameController!.text,
|
||||
state.passwordController!.text,
|
||||
state.passwordConfirmationController!.text);
|
||||
if (errors.isEmpty) {
|
||||
UserRegistrationSheet sheet = state
|
||||
.credentialsModelObj!.userRegistrationSheet;
|
||||
sheet.email = state.emailController!.text;
|
||||
sheet.name = state.nameController!.text;
|
||||
sheet.password = state.passwordController!.text;
|
||||
sheet.passwordConfirmation =
|
||||
state.passwordConfirmationController!.text;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.nameScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
} else {
|
||||
String errorMessage = '';
|
||||
|
||||
for (var error in errors) {
|
||||
errorMessage += error + '\n\n';
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Ошибка'),
|
||||
content: Text(errorMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
@@ -119,18 +159,42 @@ class CredentialsScreen extends StatelessWidget {
|
||||
PreferredSizeWidget _buildAppBar(BuildContext context) {
|
||||
return CustomAppBar(
|
||||
leadingWidth: 29.h,
|
||||
leading: AppbarLeadingImage(
|
||||
imagePath: ImageConstant.imgArrowLeft,
|
||||
margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v),
|
||||
onTap: () {
|
||||
onTapArrowLeft(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
|
||||
}
|
||||
|
||||
/// Navigates to the previous screen.
|
||||
onTapArrowLeft(BuildContext context) {
|
||||
NavigatorService.goBack();
|
||||
List<String> validateFields(
|
||||
String email, String name, String password, String passwordConfirmation) {
|
||||
List<String> errors = [];
|
||||
|
||||
if (!isEmail(email)) {
|
||||
errors.add('email_invalid'.tr);
|
||||
}
|
||||
|
||||
if (email.isEmpty) {
|
||||
errors.add('email_empty'.tr);
|
||||
}
|
||||
|
||||
if (name.length < 6) {
|
||||
errors.add('name_short'.tr);
|
||||
}
|
||||
|
||||
if (name.isEmpty) {
|
||||
errors.add('name_empty'.tr);
|
||||
}
|
||||
|
||||
if (password.isEmpty) {
|
||||
errors.add('name_empty'.tr);
|
||||
}
|
||||
|
||||
if (password.length < 6) {
|
||||
errors.add('password_short'.tr);
|
||||
}
|
||||
|
||||
if (password != passwordConfirmation) {
|
||||
errors.add('password_confirmation_mismatch'.tr);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
|
||||
onPressed: () {
|
||||
UserRegistrationSheet sheet = state
|
||||
.dateOfBirthModelObj!.userRegistrationSheet;
|
||||
sheet.birthdate = selectedDate;
|
||||
sheet.birthdate = selectedDate.toString();
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.cityOfLivingScreen,
|
||||
@@ -80,7 +80,6 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ class DateOfBirthModel extends Equatable {
|
||||
|
||||
DateOfBirthModel copyWith() {
|
||||
return DateOfBirthModel(
|
||||
userRegistrationSheet:
|
||||
userRegistrationSheet ?? this.userRegistrationSheet,
|
||||
userRegistrationSheet: userRegistrationSheet,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ class _FavoriteFoodsScreenState extends State<FavoriteFoodsScreen> {
|
||||
return NextStepButton(
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(
|
||||
left: 16.h, right: 16.h, bottom: 50.v),
|
||||
left: 16.h, right: 16.h, bottom: 40.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: () {
|
||||
UserRegistrationSheet sheet = state
|
||||
@@ -90,8 +90,21 @@ class _FavoriteFoodsScreenState extends State<FavoriteFoodsScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
Text("skip".tr, style: theme.textTheme.bodyLarge)
|
||||
BlocBuilder<FavoriteFoodsBloc, FavoriteFoodsState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
UserRegistrationSheet sheet =
|
||||
state.favoriteFoodsModelObj!.userRegistrationSheet;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.additionalInformationScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
},
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
}),
|
||||
]))));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ class FavoriteFoodsModel extends Equatable {
|
||||
|
||||
FavoriteFoodsModel copyWith() {
|
||||
return FavoriteFoodsModel(
|
||||
userRegistrationSheet:
|
||||
userRegistrationSheet ?? this.userRegistrationSheet,
|
||||
userRegistrationSheet: userRegistrationSheet,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,9 +84,22 @@ class _FavoriteSportsScreenState extends State<FavoriteSportsScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 4.v)
|
||||
BlocBuilder<FavoriteSportsBloc, FavoriteSportsState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
UserRegistrationSheet sheet = state
|
||||
.favoriteSportsModelObj!.userRegistrationSheet;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.favoriteFoodsScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
},
|
||||
child:
|
||||
Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
}),
|
||||
]))));
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ class _GenderScreenState extends State<GenderScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ class HeightBloc extends Bloc<HeightEvent, HeightState> {
|
||||
Emitter<HeightState> emit,
|
||||
) {
|
||||
emit(state.copyWith(selectedDropDownValue: event.value));
|
||||
state.heightModelObj?.userRegistrationSheet.height =
|
||||
int.tryParse(event.value.title)!;
|
||||
state.heightModelObj?.userRegistrationSheet.height = event.value.title;
|
||||
}
|
||||
|
||||
List<SelectionPopupModel> fillDropdownItemList() {
|
||||
|
||||
@@ -98,12 +98,11 @@ class _HeightScreenState extends State<HeightScreen> {
|
||||
state.heightModelObj!.userRegistrationSheet;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.allergiesScreen,
|
||||
AppRoutes.bloodPressureScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,26 +9,27 @@ import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model
|
||||
class LanguageSelectModel extends Equatable {
|
||||
LanguageSelectModel({this.dropdownItemList = const []});
|
||||
UserRegistrationSheet userRegistrationSheet = UserRegistrationSheet(
|
||||
name: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
passwordConfirmation: '',
|
||||
termsAccepted: false,
|
||||
birthdate: DateTime.now(),
|
||||
termsAccepted: 'accepted',
|
||||
birthdate: DateTime.now().toString(),
|
||||
gender: '',
|
||||
country: '',
|
||||
city: '',
|
||||
lang: '',
|
||||
weight: 0,
|
||||
height: 0,
|
||||
chestCircumference: 0,
|
||||
waistCircumference: 0,
|
||||
hipCircumference: 0,
|
||||
bloodPressureUp: 0,
|
||||
bloodPressureDown: 0,
|
||||
hasHypo: false,
|
||||
hasHyper: false,
|
||||
weight: '',
|
||||
height: '',
|
||||
chestCircumference: '',
|
||||
waistCircumference: '',
|
||||
hipCircumference: '',
|
||||
bloodPressureUp: '',
|
||||
bloodPressureDown: '',
|
||||
hasHypo: '',
|
||||
hasHyper: '',
|
||||
aboutAllergy: '',
|
||||
aboutTakingPils: '',
|
||||
aboutSportHobbies: '',
|
||||
|
||||
@@ -63,7 +63,7 @@ class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: CustomTextStyles.headlineSmallMulish)),
|
||||
style: theme.textTheme.headlineSmall)),
|
||||
SizedBox(height: 86.v),
|
||||
_buildTextFormField(context),
|
||||
Spacer(),
|
||||
@@ -86,8 +86,21 @@ class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
Text("skip".tr, style: theme.textTheme.bodyLarge)
|
||||
BlocBuilder<MedicineIntakeBloc, MedicineIntakeState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
UserRegistrationSheet sheet =
|
||||
state.medicineIntakeModelObj!.userRegistrationSheet;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.bloodPressureScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
},
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
}),
|
||||
]))));
|
||||
}
|
||||
|
||||
|
||||
@@ -83,18 +83,44 @@ class NameScreen extends StatelessWidget {
|
||||
left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: () {
|
||||
UserRegistrationSheet sheet =
|
||||
state.nameModelObj!.userRegistrationSheet;
|
||||
sheet.firstName = state.firstNameController!.text;
|
||||
sheet.lastName = state.lastNameController!.text;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.genderScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
List<String> errors = validateFields(
|
||||
state.firstNameController!.text,
|
||||
state.lastNameController!.text);
|
||||
if (errors.isEmpty) {
|
||||
UserRegistrationSheet sheet =
|
||||
state.nameModelObj!.userRegistrationSheet;
|
||||
sheet.firstName = state.firstNameController!.text;
|
||||
sheet.lastName = state.lastNameController!.text;
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
AppRoutes.genderScreen,
|
||||
arguments: sheet,
|
||||
);
|
||||
} else {
|
||||
String errorMessage = '';
|
||||
|
||||
for (var error in errors) {
|
||||
errorMessage += error + '\n\n';
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Ошибка'),
|
||||
content: Text(errorMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
@@ -116,4 +142,29 @@ class NameScreen extends StatelessWidget {
|
||||
onTapArrowLeft(BuildContext context) {
|
||||
NavigatorService.goBack();
|
||||
}
|
||||
|
||||
List<String> validateFields(
|
||||
String firstName,
|
||||
String lastName,
|
||||
) {
|
||||
List<String> errors = [];
|
||||
|
||||
if (firstName.isEmpty) {
|
||||
errors.add('first_name_empty'.tr);
|
||||
}
|
||||
|
||||
if (firstName.length < 1) {
|
||||
errors.add('first_name_short'.tr);
|
||||
}
|
||||
|
||||
if (lastName.isEmpty) {
|
||||
errors.add('last_name_empty'.tr);
|
||||
}
|
||||
|
||||
if (lastName.length < 1) {
|
||||
errors.add('last_name_short'.tr);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ class WeightBloc extends Bloc<WeightEvent, WeightState> {
|
||||
Emitter<WeightState> emit,
|
||||
) {
|
||||
emit(state.copyWith(selectedDropDownValue: event.value));
|
||||
state.weightModelObj?.userRegistrationSheet.weight =
|
||||
int.tryParse(event.value.title)!;
|
||||
state.weightModelObj?.userRegistrationSheet.weight = event.value.title;
|
||||
}
|
||||
|
||||
List<SelectionPopupModel> fillDropdownItemList() {
|
||||
|
||||
@@ -103,7 +103,6 @@ class _WeightScreenState extends State<WeightScreen> {
|
||||
);
|
||||
});
|
||||
}),
|
||||
SizedBox(height: 17.v),
|
||||
]))));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ dependencies:
|
||||
cached_network_image: ^3.2.1
|
||||
flutter_svg: ^2.0.9
|
||||
equatable: ^2.0.0
|
||||
validators: ^3.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
Reference in New Issue
Block a user