Merge pull request 'registration_logic' (#1) from registration_logic into main

Reviewed-on: maxxkim/eatvio_app#1
This commit is contained in:
2023-12-26 08:33:29 +00:00
70 changed files with 1526 additions and 774 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/images/img_male.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

1
devtools_options.yaml Normal file
View File

@@ -0,0 +1 @@
extensions:

View File

@@ -1,7 +1,5 @@
//ignore: unused_import
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/scheduler.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PrefUtils {

View File

@@ -0,0 +1,102 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
class UserRegistrationSheet {
String firstName;
String lastName;
String email;
String password;
String passwordConfirmation;
bool termsAccepted;
DateTime 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 aboutAllergy = '';
String aboutTakingPils = '';
String aboutSportHobbies = '';
String favoriteFoods = '';
String unfavoriteFoods = '';
String additionalInfo = '';
UserRegistrationSheet({
required this.firstName,
required this.lastName,
required this.email,
required this.password,
required this.passwordConfirmation,
required this.termsAccepted,
required this.birthdate,
required this.gender,
required this.country,
required this.city,
required this.lang,
required this.weight,
required this.height,
required this.chestCircumference,
required this.waistCircumference,
required this.hipCircumference,
required this.bloodPressureUp,
required this.bloodPressureDown,
required this.hasHypo,
required this.hasHyper,
required this.aboutAllergy,
required this.aboutTakingPils,
required this.aboutSportHobbies,
required this.favoriteFoods,
required this.unfavoriteFoods,
required this.additionalInfo,
});
Map<String, dynamic> toJson() {
return {
'first_name': firstName,
'last_name': lastName,
'email': email,
'password': password,
'password_confirmation': passwordConfirmation,
'terms': termsAccepted,
'birthdate': birthdate.toIso8601String(),
'gender': gender,
'country': country,
'city': city,
'lang': lang,
'weight': weight,
'height': height,
'chest_circumference': chestCircumference,
'waist_circumference': waistCircumference,
'hip_circumference': hipCircumference,
'blood_pressure_up': bloodPressureUp,
'blood_pressure_down': bloodPressureDown,
'has_hypo': hasHypo,
'has_hyper': hasHyper,
'about_alergy': aboutAllergy,
'about_taking_pils': aboutTakingPils,
'about_sport_hobbies': aboutSportHobbies,
'favorite_foods': favoriteFoods,
'unfavorite_foods': unfavoriteFoods,
'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');
}
}
}

View File

@@ -1,10 +1,17 @@
final Map<String, String> ru = {
"user_registration": "Регистрация пользователя",
"email": "Элетронная почта",
"password": "Пароль",
"password_confirmation": "Подтвердите пароль",
"first_name": "Имя",
"last_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": "Обхват груди",
@@ -29,6 +36,8 @@ final Map<String, String> ru = {
"do_you_have_hypertension_tendency": "Есть ли у вас склонность к гипертонии?",
"your_blood_pressure": "Ваше артериальное давление?",
"average_pressure": "Средние показатели давления:",
"up_pressure": "Верхние показатели давления:",
"down_pressure": "Нижние показатели давления:",
"do_you_have_hypotension_tendency": "Есть ли у вас склонность к гипотонии?",
// favorite_sports Screen
@@ -51,6 +60,7 @@ final Map<String, String> ru = {
// language_select Screen
"lbl_english": "English",
"finish": "Завершить",
"preferred_language": "Предпочетаемый язык общения?",
// Common String

View File

@@ -4,22 +4,34 @@ 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:eatvio_app/widgets/custom_outlined_button.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';
import 'package:flutter/material.dart';
import 'dart:convert';
class AdditionalInformationScreen extends StatelessWidget {
class AdditionalInformationScreen extends StatefulWidget {
const AdditionalInformationScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<AdditionalInformationBloc>(
create: (context) => AdditionalInformationBloc(
AdditionalInformationState(
additionalInformationModelObj: AdditionalInformationModel()))
additionalInformationModelObj:
AdditionalInformationModel(userRegistrationSheet: sheet)))
..add(AdditionalInformationInitialEvent()),
child: AdditionalInformationScreen());
}
@override
State<AdditionalInformationScreen> createState() =>
_AdditionalInformationScreenState();
}
class _AdditionalInformationScreenState
extends State<AdditionalInformationScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -32,26 +44,43 @@ class AdditionalInformationScreen extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
_buildProgressIndicator(context),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 1,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 20.v),
SizedBox(
width: 192.h,
child: Text("additional_information".tr,
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: theme.textTheme.headlineSmall)),
SizedBox(height: 73.v),
_buildTextFormField(context),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
showSuccessMessage(context);
}),
BlocBuilder<AdditionalInformationBloc,
AdditionalInformationState>(builder: (context, state) {
return NextStepButton(
text: "finish".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
var message;
UserRegistrationSheet sheet = state
.additionalInformationModelObj!
.userRegistrationSheet;
sheet.additionalInfo = state.editTextController!.text;
message = sheet.toJson();
print(message);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
}
@@ -69,34 +98,12 @@ class AdditionalInformationScreen extends StatelessWidget {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildProgressIndicator(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 332.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Section Widget
Widget _buildTextFormField(BuildContext context) {
return SizedBox(
height: 257.v,
width: 343.h,
child: Stack(alignment: Alignment.center, children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: EdgeInsets.only(left: 10.h, top: 69.v),
child: Text("enter_information".tr,
style: theme.textTheme.bodyLarge))),
Align(
alignment: Alignment.center,
child: Column(mainAxisSize: MainAxisSize.min, children: [
@@ -128,13 +135,12 @@ class AdditionalInformationScreen extends StatelessWidget {
/// Displays an alert dialog when the action is triggered.
/// The dialog box contains a title and a message with the `Теперь вы можете пользоваться полным функционалом приложения`
showSuccessMessage(BuildContext context) {
showSuccessMessage(BuildContext context, String text) {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text('Регистрация завершена!'),
content: const Text(
'Теперь вы можете пользоваться полным функционалом приложения'),
content: const Text(text),
actions: [
TextButton(
onPressed: () {

View File

@@ -1,16 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [additional_information_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class AdditionalInformationModel extends Equatable {
AdditionalInformationModel() {}
UserRegistrationSheet userRegistrationSheet;
AdditionalInformationModel({required this.userRegistrationSheet});
AdditionalInformationModel copyWith() {
return AdditionalInformationModel();
return AdditionalInformationModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -4,21 +4,29 @@ 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:eatvio_app/widgets/custom_outlined_button.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';
import 'package:flutter/material.dart';
class AllergiesScreen extends StatelessWidget {
class AllergiesScreen extends StatefulWidget {
const AllergiesScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<AllergiesBloc>(
create: (context) =>
AllergiesBloc(AllergiesState(allergiesModelObj: AllergiesModel()))
..add(AllergiesInitialEvent()),
create: (context) => AllergiesBloc(AllergiesState(
allergiesModelObj: AllergiesModel(userRegistrationSheet: sheet)))
..add(AllergiesInitialEvent()),
child: AllergiesScreen());
}
@override
State<AllergiesScreen> createState() => _AllergiesScreenState();
}
class _AllergiesScreenState extends State<AllergiesScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -42,7 +50,7 @@ class AllergiesScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.41,
value: 0.62,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
@@ -52,12 +60,25 @@ class AllergiesScreen extends StatelessWidget {
Spacer(flex: 36),
_buildTextFormField(context),
Spacer(flex: 63),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToMedicine(context);
}),
BlocBuilder<AllergiesBloc, AllergiesState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet =
state.allergiesModelObj!.userRegistrationSheet;
sheet.aboutAllergy =
state.enterInformationController!.text;
Navigator.pushNamed(
context,
AppRoutes.medicineIntakeScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));

View File

@@ -1,16 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [allergies_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class AllergiesModel extends Equatable {
AllergiesModel() {}
UserRegistrationSheet userRegistrationSheet;
AllergiesModel({required this.userRegistrationSheet});
AllergiesModel copyWith() {
return AllergiesModel();
return AllergiesModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -3,7 +3,7 @@ import 'models/app_navigation_model.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';
class AppNavigationScreen extends StatelessWidget {
class AppNavigationScreen extends StatefulWidget {
const AppNavigationScreen({Key? key})
: super(
key: key,
@@ -19,6 +19,11 @@ class AppNavigationScreen extends StatelessWidget {
);
}
@override
State<AppNavigationScreen> createState() => _AppNavigationScreenState();
}
class _AppNavigationScreenState extends State<AppNavigationScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);

View File

@@ -5,7 +5,7 @@ import 'package:equatable/equatable.dart';
/// This class defines the variables used in the [app_navigation_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class AppNavigationModel extends Equatable {
AppNavigationModel() {}
AppNavigationModel();
AppNavigationModel copyWith() {
return AppNavigationModel();

View File

@@ -9,20 +9,41 @@ part 'blood_pressure_state.dart';
class BloodPressureBloc extends Bloc<BloodPressureEvent, BloodPressureState> {
BloodPressureBloc(BloodPressureState initialState) : super(initialState) {
on<BloodPressureInitialEvent>(_onInitialize);
on<ChangeDropDownEvent>(_changeDropDown);
on<ChangeHypoDownEvent>(_changeHypoDropDown);
on<ChangeHyperDropDownEvent>(_changeHyperDropDown);
}
_changeDropDown(
ChangeDropDownEvent event,
_changeHyperDropDown(
ChangeHyperDropDownEvent event,
Emitter<BloodPressureState> emit,
) {
emit(state.copyWith(selectedDropDownValue: event.value));
if (event.value.id == 1) {
state.bloodPressureModelObj!.userRegistrationSheet.hasHyper = true;
} else {
state.bloodPressureModelObj!.userRegistrationSheet.hasHyper = false;
}
emit(state.copyWith(selectedHyperValue: event.value));
}
_changeHypoDropDown(
ChangeHypoDownEvent event,
Emitter<BloodPressureState> emit,
) {
if (event.value.id == 1) {
state.bloodPressureModelObj!.userRegistrationSheet.hasHypo = true;
} else {
state.bloodPressureModelObj!.userRegistrationSheet.hasHypo = false;
}
emit(state.copyWith(selectedHypoValue: event.value));
}
List<SelectionPopupModel> fillDropdownItemList() {
return [
SelectionPopupModel(id: 1, title: "Да", isSelected: true),
SelectionPopupModel(id: 2, title: "Нет"),
SelectionPopupModel(
id: 1,
title: "Да",
),
SelectionPopupModel(id: 2, title: "Нет", isSelected: true),
];
}
@@ -31,8 +52,8 @@ class BloodPressureBloc extends Bloc<BloodPressureEvent, BloodPressureState> {
Emitter<BloodPressureState> emit,
) async {
emit(state.copyWith(
valueController: TextEditingController(),
valueController1: TextEditingController()));
upPressureController: TextEditingController(),
downPressureController: TextEditingController()));
emit(state.copyWith(
bloodPressureModelObj: state.bloodPressureModelObj
?.copyWith(dropdownItemList: fillDropdownItemList())));

View File

@@ -16,8 +16,19 @@ class BloodPressureInitialEvent extends BloodPressureEvent {
}
///event for dropdown selection
class ChangeDropDownEvent extends BloodPressureEvent {
ChangeDropDownEvent({required this.value});
class ChangeHyperDropDownEvent extends BloodPressureEvent {
ChangeHyperDropDownEvent({required this.value});
SelectionPopupModel value;
@override
List<Object?> get props => [
value,
];
}
class ChangeHypoDownEvent extends BloodPressureEvent {
ChangeHypoDownEvent({required this.value});
SelectionPopupModel value;

View File

@@ -5,38 +5,44 @@ part of 'blood_pressure_bloc.dart';
/// Represents the state of BloodPressure in the application.
class BloodPressureState extends Equatable {
BloodPressureState({
this.valueController,
this.valueController1,
this.selectedDropDownValue,
this.upPressureController,
this.downPressureController,
this.selectedHyperValue,
this.selectedHypoValue,
this.bloodPressureModelObj,
});
TextEditingController? valueController;
TextEditingController? upPressureController;
TextEditingController? valueController1;
TextEditingController? downPressureController;
SelectionPopupModel? selectedDropDownValue;
SelectionPopupModel? selectedHypoValue;
SelectionPopupModel? selectedHyperValue;
BloodPressureModel? bloodPressureModelObj;
@override
List<Object?> get props => [
valueController,
valueController1,
selectedDropDownValue,
upPressureController,
downPressureController,
selectedHyperValue,
selectedHypoValue,
bloodPressureModelObj,
];
BloodPressureState copyWith({
TextEditingController? valueController,
TextEditingController? valueController1,
SelectionPopupModel? selectedDropDownValue,
TextEditingController? upPressureController,
TextEditingController? downPressureController,
SelectionPopupModel? selectedHyperValue,
SelectionPopupModel? selectedHypoValue,
BloodPressureModel? bloodPressureModelObj,
}) {
return BloodPressureState(
valueController: valueController ?? this.valueController,
valueController1: valueController1 ?? this.valueController1,
selectedDropDownValue:
selectedDropDownValue ?? this.selectedDropDownValue,
upPressureController: upPressureController ?? this.upPressureController,
downPressureController:
downPressureController ?? this.downPressureController,
selectedHyperValue: selectedHyperValue ?? this.selectedHyperValue,
selectedHypoValue: selectedHypoValue ?? this.selectedHypoValue,
bloodPressureModelObj:
bloodPressureModelObj ?? this.bloodPressureModelObj,
);

View File

@@ -1,27 +1,38 @@
import 'bloc/blood_pressure_bloc.dart';
import 'package:flutter/services.dart';
import 'models/blood_pressure_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:eatvio_app/widgets/custom_drop_down.dart';
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:flutter/material.dart';
class BloodPressureScreen extends StatelessWidget {
class BloodPressureScreen extends StatefulWidget {
const BloodPressureScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<BloodPressureBloc>(
create: (context) => BloodPressureBloc(
BloodPressureState(bloodPressureModelObj: BloodPressureModel()))
create: (context) => BloodPressureBloc(BloodPressureState(
bloodPressureModelObj:
BloodPressureModel(userRegistrationSheet: sheet)))
..add(BloodPressureInitialEvent()),
child: BloodPressureScreen());
}
@override
State<BloodPressureScreen> createState() => _BloodPressureScreenState();
}
class _BloodPressureScreenState extends State<BloodPressureScreen> {
@override
Widget build(BuildContext context) {
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
mediaQueryData = MediaQuery.of(context);
return SafeArea(
child: Scaffold(
@@ -46,7 +57,7 @@ class BloodPressureScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.63,
value: 0.76,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400))))),
@@ -58,8 +69,42 @@ class BloodPressureScreen extends StatelessWidget {
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: theme.textTheme.headlineSmall)),
SizedBox(height: 77.v),
_buildThirtyThree(context),
SizedBox(height: 21.v),
Container(
margin: EdgeInsets.only(right: 1.h),
padding: EdgeInsets.symmetric(horizontal: 3.h),
child: Column(children: [
Text("up_pressure".tr,
style: theme.textTheme.bodyLarge),
SizedBox(height: 2.v),
BlocSelector<BloodPressureBloc, BloodPressureState,
TextEditingController?>(
selector: (state) => state.upPressureController,
builder: (context, upPressureController) {
return CustomTextFormField(
inputFormatters: [digitsOnly],
controller: upPressureController,
hintText: "90".tr);
})
])),
SizedBox(height: 21.v),
Container(
margin: EdgeInsets.only(right: 1.h),
padding: EdgeInsets.symmetric(horizontal: 3.h),
child: Column(children: [
Text("down_pressure".tr,
style: theme.textTheme.bodyLarge),
SizedBox(height: 2.v),
BlocSelector<BloodPressureBloc, BloodPressureState,
TextEditingController?>(
selector: (state) => state.downPressureController,
builder: (context, downPressureController) {
return CustomTextFormField(
inputFormatters: [digitsOnly],
controller: downPressureController,
hintText: "90".tr);
})
])),
SizedBox(height: 22.v),
Text("do_you_have_hypotension_tendency".tr,
style: theme.textTheme.bodyLarge),
@@ -81,14 +126,14 @@ class BloodPressureScreen extends StatelessWidget {
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "no".tr,
hintText: "Не выбрано".tr,
items:
bloodPressureModelObj?.dropdownItemList ??
[],
onChanged: (value) {
context
.read<BloodPressureBloc>()
.add(ChangeDropDownEvent(value: value));
.add(ChangeHypoDownEvent(value: value));
});
})),
SizedBox(height: 22.v),
@@ -112,24 +157,37 @@ class BloodPressureScreen extends StatelessWidget {
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "no".tr,
hintText: "Не выбрано".tr,
items:
bloodPressureModelObj?.dropdownItemList ??
[],
onChanged: (value) {
context
.read<BloodPressureBloc>()
.add(ChangeDropDownEvent(value: value));
context.read<BloodPressureBloc>().add(
ChangeHyperDropDownEvent(value: value));
});
})),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.symmetric(horizontal: 4.h),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToSports(context);
}),
BlocBuilder<BloodPressureBloc, BloodPressureState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
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,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
@@ -149,24 +207,6 @@ class BloodPressureScreen extends StatelessWidget {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildThirtyThree(BuildContext context) {
return Container(
margin: EdgeInsets.only(right: 1.h),
padding: EdgeInsets.symmetric(horizontal: 3.h),
child: Column(children: [
Text("average_pressure".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 2.v),
BlocSelector<BloodPressureBloc, BloodPressureState,
TextEditingController?>(
selector: (state) => state.valueController,
builder: (context, valueController) {
return CustomTextFormField(
controller: valueController, hintText: "90".tr);
})
]));
}
/// Navigates to the previous screen.
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();

View File

@@ -2,20 +2,25 @@
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [blood_pressure_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class BloodPressureModel extends Equatable {
BloodPressureModel({this.dropdownItemList = const []}) {}
UserRegistrationSheet userRegistrationSheet;
BloodPressureModel(
{required this.userRegistrationSheet, this.dropdownItemList = const []});
List<SelectionPopupModel> dropdownItemList;
BloodPressureModel copyWith({List<SelectionPopupModel>? dropdownItemList}) {
return BloodPressureModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
dropdownItemList: dropdownItemList ?? this.dropdownItemList,
);
}
@override
List<Object?> get props => [dropdownItemList];
List<Object?> get props => [dropdownItemList, userRegistrationSheet];
}

View File

@@ -18,8 +18,8 @@ class BodyCircumferencesBloc
Emitter<BodyCircumferencesState> emit,
) async {
emit(state.copyWith(
valueController: TextEditingController(),
valueController1: TextEditingController(),
valueController2: TextEditingController()));
chestCircumferenceController: TextEditingController(),
waistCircumferenceController: TextEditingController(),
hipCircumferenceController: TextEditingController()));
}
}

View File

@@ -5,37 +5,40 @@ part of 'body_circumferences_bloc.dart';
/// Represents the state of BodyCircumferences in the application.
class BodyCircumferencesState extends Equatable {
BodyCircumferencesState({
this.valueController,
this.valueController1,
this.valueController2,
this.chestCircumferenceController,
this.waistCircumferenceController,
this.hipCircumferenceController,
this.bodyCircumferencesModelObj,
});
TextEditingController? valueController;
TextEditingController? chestCircumferenceController;
TextEditingController? valueController1;
TextEditingController? waistCircumferenceController;
TextEditingController? valueController2;
TextEditingController? hipCircumferenceController;
BodyCircumferencesModel? bodyCircumferencesModelObj;
@override
List<Object?> get props => [
valueController,
valueController1,
valueController2,
chestCircumferenceController,
waistCircumferenceController,
hipCircumferenceController,
bodyCircumferencesModelObj,
];
BodyCircumferencesState copyWith({
TextEditingController? valueController,
TextEditingController? valueController1,
TextEditingController? valueController2,
TextEditingController? chestCircumferenceController,
TextEditingController? waistCircumferenceController,
TextEditingController? hipCircumferenceController,
BodyCircumferencesModel? bodyCircumferencesModelObj,
}) {
return BodyCircumferencesState(
valueController: valueController ?? this.valueController,
valueController1: valueController1 ?? this.valueController1,
valueController2: valueController2 ?? this.valueController2,
chestCircumferenceController:
chestCircumferenceController ?? this.chestCircumferenceController,
waistCircumferenceController:
waistCircumferenceController ?? this.waistCircumferenceController,
hipCircumferenceController:
hipCircumferenceController ?? this.hipCircumferenceController,
bodyCircumferencesModelObj:
bodyCircumferencesModelObj ?? this.bodyCircumferencesModelObj,
);

View File

@@ -1,10 +1,12 @@
import 'bloc/body_circumferences_bloc.dart';
import 'package:flutter/services.dart';
import 'models/body_circumferences_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:eatvio_app/widgets/custom_outlined_button.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';
import 'package:flutter/material.dart';
@@ -12,15 +14,19 @@ class BodyCircumferencesScreen extends StatelessWidget {
const BodyCircumferencesScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<BodyCircumferencesBloc>(
create: (context) => BodyCircumferencesBloc(BodyCircumferencesState(
bodyCircumferencesModelObj: BodyCircumferencesModel()))
bodyCircumferencesModelObj:
BodyCircumferencesModel(userRegistrationSheet: sheet)))
..add(BodyCircumferencesInitialEvent()),
child: BodyCircumferencesScreen());
}
@override
Widget build(BuildContext context) {
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
mediaQueryData = MediaQuery.of(context);
return SafeArea(
child: Scaffold(
@@ -42,7 +48,7 @@ class BodyCircumferencesScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.29,
value: 0.40,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
@@ -50,17 +56,32 @@ class BodyCircumferencesScreen extends StatelessWidget {
Text("initial_measurements".tr,
style: theme.textTheme.headlineSmall),
SizedBox(height: 93.v),
_buildTwentySeven(context),
Column(children: [
Text("chest_circumference".tr,
style: theme.textTheme.bodyLarge),
SizedBox(height: 3.v),
BlocSelector<BodyCircumferencesBloc,
BodyCircumferencesState, TextEditingController?>(
selector: (state) => state.chestCircumferenceController,
builder: (context, chestCircumferenceController) {
return CustomTextFormField(
inputFormatters: [digitsOnly],
controller: chestCircumferenceController,
hintText: "90".tr);
})
]),
SizedBox(height: 19.v),
Text("waist_circumference".tr,
style: theme.textTheme.bodyLarge),
SizedBox(height: 5.v),
BlocSelector<BodyCircumferencesBloc, BodyCircumferencesState,
TextEditingController?>(
selector: (state) => state.valueController1,
builder: (context, valueController1) {
selector: (state) => state.waistCircumferenceController,
builder: (context, waistCircumferenceController) {
return CustomTextFormField(
controller: valueController1, hintText: "60".tr);
inputFormatters: [digitsOnly],
controller: waistCircumferenceController,
hintText: "60".tr);
}),
SizedBox(height: 21.v),
Text("hip_circumference".tr,
@@ -68,22 +89,40 @@ class BodyCircumferencesScreen extends StatelessWidget {
SizedBox(height: 3.v),
BlocSelector<BodyCircumferencesBloc, BodyCircumferencesState,
TextEditingController?>(
selector: (state) => state.valueController2,
builder: (context, valueController2) {
selector: (state) => state.hipCircumferenceController,
builder: (context, hipCircumferenceController) {
return CustomTextFormField(
controller: valueController2,
inputFormatters: [digitsOnly],
controller: hipCircumferenceController,
hintText: "90".tr,
textInputAction: TextInputAction.done);
}),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToWeight(context);
}),
BlocBuilder<BodyCircumferencesBloc, BodyCircumferencesState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
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,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
}
@@ -101,21 +140,6 @@ class BodyCircumferencesScreen extends StatelessWidget {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildTwentySeven(BuildContext context) {
return Column(children: [
Text("chest_circumference".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 3.v),
BlocSelector<BodyCircumferencesBloc, BodyCircumferencesState,
TextEditingController?>(
selector: (state) => state.valueController,
builder: (context, valueController) {
return CustomTextFormField(
controller: valueController, hintText: "90".tr);
})
]);
}
/// Navigates to the previous screen.
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();

View File

@@ -1,16 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [body_circumferences_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class BodyCircumferencesModel extends Equatable {
BodyCircumferencesModel() {}
UserRegistrationSheet userRegistrationSheet;
BodyCircumferencesModel({required this.userRegistrationSheet});
BodyCircumferencesModel copyWith() {
return BodyCircumferencesModel();
return BodyCircumferencesModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -28,6 +28,8 @@ class CityOfLivingBloc extends Bloc<CityOfLivingEvent, CityOfLivingState> {
Emitter<CityOfLivingState> emit,
) {
emit(state.copyWith(selectedDropDownValue: event.value));
state.cityOfLivingModelObj?.userRegistrationSheet.country =
event.value.title;
}
_changeDropDown1(
@@ -35,6 +37,7 @@ class CityOfLivingBloc extends Bloc<CityOfLivingEvent, CityOfLivingState> {
Emitter<CityOfLivingState> emit,
) {
emit(state.copyWith(selectedDropDownValue1: event.value));
state.cityOfLivingModelObj?.userRegistrationSheet.city = event.value.title;
}
List<SelectionPopupModel> fillDropdownItemList() {

View File

@@ -5,16 +5,20 @@ 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:eatvio_app/widgets/custom_drop_down.dart';
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:flutter/material.dart';
class CityOfLivingScreen extends StatelessWidget {
const CityOfLivingScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<CityOfLivingBloc>(
create: (context) => CityOfLivingBloc(
CityOfLivingState(cityOfLivingModelObj: CityOfLivingModel()))
create: (context) => CityOfLivingBloc(CityOfLivingState(
cityOfLivingModelObj:
CityOfLivingModel(userRegistrationSheet: sheet)))
..add(CityOfLivingInitialEvent()),
child: CityOfLivingScreen());
}
@@ -41,12 +45,13 @@ class CityOfLivingScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.23,
value: 0.32,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 39.v),
Text("Moscow".tr, style: theme.textTheme.headlineSmall),
Text("place_of_living".tr,
style: theme.textTheme.headlineSmall),
Spacer(flex: 34),
Text("country".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 2.v),
@@ -64,7 +69,7 @@ class CityOfLivingScreen extends StatelessWidget {
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "Russia".tr,
hintText: "Не выбрано".tr,
items: cityOfLivingModelObj?.dropdownItemList ?? [],
onChanged: (value) {
context
@@ -89,7 +94,7 @@ class CityOfLivingScreen extends StatelessWidget {
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "Moscow".tr,
hintText: "Не выбрано".tr,
items:
cityOfLivingModelObj?.dropdownItemList1 ?? [],
onChanged: (value) {
@@ -99,14 +104,24 @@ class CityOfLivingScreen extends StatelessWidget {
});
}),
Spacer(flex: 65),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToCircumferences(context);
}),
BlocBuilder<CityOfLivingBloc, CityOfLivingState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet =
state.cityOfLivingModelObj!.userRegistrationSheet;
Navigator.pushNamed(
context,
AppRoutes.bodyCircumferencesScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
}
@@ -128,11 +143,4 @@ class CityOfLivingScreen extends StatelessWidget {
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();
}
/// Navigates to the bodyCircumferencesScreen when the action is triggered.
navigateToCircumferences(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.bodyCircumferencesScreen,
);
}
}

View File

@@ -2,14 +2,17 @@
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [city_of_living_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class CityOfLivingModel extends Equatable {
UserRegistrationSheet userRegistrationSheet;
CityOfLivingModel({
required this.userRegistrationSheet,
this.dropdownItemList = const [],
this.dropdownItemList1 = const [],
}) {}
});
List<SelectionPopupModel> dropdownItemList;
@@ -20,11 +23,14 @@ class CityOfLivingModel extends Equatable {
List<SelectionPopupModel>? dropdownItemList1,
}) {
return CityOfLivingModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
dropdownItemList: dropdownItemList ?? this.dropdownItemList,
dropdownItemList1: dropdownItemList1 ?? this.dropdownItemList1,
);
}
@override
List<Object?> get props => [dropdownItemList, dropdownItemList1];
List<Object?> get props =>
[dropdownItemList, dropdownItemList1, userRegistrationSheet];
}

View File

@@ -0,0 +1,23 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import '/core/app_export.dart';
import 'package:eatvio_app/presentation/credentials_screen/models/credentials_model.dart';
part 'credentials_event.dart';
part 'credentials_state.dart';
/// A bloc that manages the state of a Credentials according to the event that is dispatched to it.
class CredentialsBloc extends Bloc<CredentialsEvent, CredentialsState> {
CredentialsBloc(CredentialsState initialState) : super(initialState) {
on<CredentialsInitialEvent>(_onInitialize);
}
_onInitialize(
CredentialsInitialEvent event,
Emitter<CredentialsState> emit,
) async {
emit(state.copyWith(
valueController: TextEditingController(),
passwordController: TextEditingController(),
passwordConfirmationController: TextEditingController()));
}
}

View File

@@ -0,0 +1,16 @@
// ignore_for_file: must_be_immutable
part of 'credentials_bloc.dart';
/// Abstract class for all events that can be dispatched from the
///Credentials widget.
///
/// Events must be immutable and implement the [Equatable] interface.
@immutable
abstract class CredentialsEvent extends Equatable {}
/// Event that is dispatched when the Credentials widget is first created.
class CredentialsInitialEvent extends CredentialsEvent {
@override
List<Object?> get props => [];
}

View File

@@ -0,0 +1,43 @@
// ignore_for_file: must_be_immutable
part of 'credentials_bloc.dart';
/// Represents the state of Credentials in the application.
class CredentialsState extends Equatable {
CredentialsState({
this.valueController,
this.passwordController,
this.passwordConfirmationController,
this.credentialsModelObj,
});
TextEditingController? valueController;
TextEditingController? passwordController;
TextEditingController? passwordConfirmationController;
CredentialsModel? credentialsModelObj;
@override
List<Object?> get props => [
valueController,
passwordController,
passwordConfirmationController,
credentialsModelObj,
];
CredentialsState copyWith({
TextEditingController? valueController,
TextEditingController? passwordController,
TextEditingController? passwordConfirmationController,
CredentialsModel? credentialsModelObj,
}) {
return CredentialsState(
valueController: valueController ?? this.valueController,
passwordController: passwordController ?? this.passwordController,
passwordConfirmationController:
passwordConfirmationController ?? this.passwordConfirmationController,
credentialsModelObj: credentialsModelObj ?? this.credentialsModelObj,
);
}
}

View File

@@ -0,0 +1,136 @@
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: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';
import 'package:flutter/material.dart';
class CredentialsScreen extends StatelessWidget {
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<CredentialsBloc>(
create: (context) => CredentialsBloc(
CredentialsState(
credentialsModelObj: CredentialsModel(userRegistrationSheet: sheet),
),
)..add(CredentialsInitialEvent()),
child: CredentialsScreen(),
);
}
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: _buildAppBar(context),
body: Container(
width: double.maxFinite,
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.05,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 39.v),
Text("user_registration".tr,
style: theme.textTheme.headlineSmall),
SizedBox(height: 93.v),
Text("email".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 3.v),
BlocSelector<CredentialsBloc, CredentialsState,
TextEditingController?>(
selector: (state) => state.valueController,
builder: (context, valueController) {
return CustomTextFormField(
controller: valueController,
textInputAction: TextInputAction.done);
}),
SizedBox(height: 19.v),
Text("password".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 5.v),
BlocSelector<CredentialsBloc, CredentialsState,
TextEditingController?>(
selector: (state) => state.passwordController,
builder: (context, passwordController) {
return CustomTextFormField(
obscureText: true,
controller: passwordController,
);
}),
SizedBox(height: 21.v),
Text("password_confirmation".tr,
style: theme.textTheme.bodyLarge),
SizedBox(height: 3.v),
BlocSelector<CredentialsBloc, CredentialsState,
TextEditingController?>(
selector: (state) => state.passwordConfirmationController,
builder: (context, passwordConfirmationController) {
return CustomTextFormField(
obscureText: true,
controller: passwordConfirmationController,
textInputAction: TextInputAction.done);
}),
Spacer(),
BlocBuilder<CredentialsBloc, CredentialsState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
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,
);
});
}),
SizedBox(height: 17.v),
]))));
}
/// Section Widget
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();
}
}

View File

@@ -0,0 +1,22 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [credentials_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class CredentialsModel extends Equatable {
UserRegistrationSheet userRegistrationSheet;
CredentialsModel({required this.userRegistrationSheet});
CredentialsModel copyWith({UserRegistrationSheet? userRegistrationSheet}) {
return CredentialsModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -4,16 +4,20 @@ 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:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:flutter/material.dart';
class DateOfBirthScreen extends StatefulWidget {
const DateOfBirthScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<DateOfBirthBloc>(
create: (context) => DateOfBirthBloc(
DateOfBirthState(dateOfBirthModelObj: DateOfBirthModel()))
create: (context) => DateOfBirthBloc(DateOfBirthState(
dateOfBirthModelObj:
DateOfBirthModel(userRegistrationSheet: sheet)))
..add(DateOfBirthInitialEvent()),
child: DateOfBirthScreen());
}
@@ -37,25 +41,46 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
padding:
EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
_buildProgressIndicator(context),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.24,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 38.v),
Text("date_of_birth".tr,
style: theme.textTheme.headlineSmall),
Spacer(flex: 39),
_buildDateInput(context),
Spacer(flex: 60),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToCity(context);
}),
BlocBuilder<DateOfBirthBloc, DateOfBirthState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet = state
.dateOfBirthModelObj!.userRegistrationSheet;
sheet.birthdate = selectedDate;
Navigator.pushNamed(
context,
AppRoutes.cityOfLivingScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Padding(
padding: EdgeInsets.only(left: 8.h),
child:
Text("skip".tr, style: theme.textTheme.bodyLarge))
]))));
});
}
@@ -74,23 +99,6 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildProgressIndicator(BuildContext context) {
return Container(
width: 343.h,
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 60.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Section Widget
Widget _buildDateInput(BuildContext context) {
return Container(
@@ -131,11 +139,10 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
///
/// This function returns a `Future` that completes with `void`.
Future<void> openDatePickerDialog(BuildContext context) async {
var initialState = BlocProvider.of<DateOfBirthBloc>(context).state;
DateTime? dateTime = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1970),
firstDate: DateTime(1924),
lastDate: DateTime(
DateTime.now().year, DateTime.now().month, DateTime.now().day));
if (dateTime != null) {
@@ -144,11 +151,4 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
});
}
}
/// Navigates to the cityOfLivingScreen when the action is triggered.
navigateToCity(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.cityOfLivingScreen,
);
}
}

View File

@@ -1,16 +1,22 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [date_of_birth_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class DateOfBirthModel extends Equatable {
DateOfBirthModel() {}
UserRegistrationSheet userRegistrationSheet;
DateOfBirthModel({required this.userRegistrationSheet});
DateOfBirthModel copyWith() {
return DateOfBirthModel();
return DateOfBirthModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -16,7 +16,7 @@ class FavoriteFoodsBloc extends Bloc<FavoriteFoodsEvent, FavoriteFoodsState> {
Emitter<FavoriteFoodsState> emit,
) async {
emit(state.copyWith(
enterinformationController: TextEditingController(),
enterinformationController1: TextEditingController()));
favoriteFoodsController: TextEditingController(),
unfavoriteFoodsController: TextEditingController()));
}
}

View File

@@ -5,33 +5,33 @@ part of 'favorite_foods_bloc.dart';
/// Represents the state of FavoriteFoods in the application.
class FavoriteFoodsState extends Equatable {
FavoriteFoodsState({
this.enterinformationController,
this.enterinformationController1,
this.favoriteFoodsController,
this.unfavoriteFoodsController,
this.favoriteFoodsModelObj,
});
TextEditingController? enterinformationController;
TextEditingController? favoriteFoodsController;
TextEditingController? enterinformationController1;
TextEditingController? unfavoriteFoodsController;
FavoriteFoodsModel? favoriteFoodsModelObj;
@override
List<Object?> get props => [
enterinformationController,
enterinformationController1,
favoriteFoodsController,
unfavoriteFoodsController,
favoriteFoodsModelObj,
];
FavoriteFoodsState copyWith({
TextEditingController? enterinformationController,
TextEditingController? enterinformationController1,
TextEditingController? favoriteFoodsController,
TextEditingController? unfavoriteFoodsController,
FavoriteFoodsModel? favoriteFoodsModelObj,
}) {
return FavoriteFoodsState(
enterinformationController:
enterinformationController ?? this.enterinformationController,
enterinformationController1:
enterinformationController1 ?? this.enterinformationController1,
favoriteFoodsController:
favoriteFoodsController ?? this.favoriteFoodsController,
unfavoriteFoodsController:
unfavoriteFoodsController ?? this.unfavoriteFoodsController,
favoriteFoodsModelObj:
favoriteFoodsModelObj ?? this.favoriteFoodsModelObj,
);

View File

@@ -4,21 +4,30 @@ 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:eatvio_app/widgets/custom_outlined_button.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';
import 'package:flutter/material.dart';
class FavoriteFoodsScreen extends StatelessWidget {
class FavoriteFoodsScreen extends StatefulWidget {
const FavoriteFoodsScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<FavoriteFoodsBloc>(
create: (context) => FavoriteFoodsBloc(
FavoriteFoodsState(favoriteFoodsModelObj: FavoriteFoodsModel()))
create: (context) => FavoriteFoodsBloc(FavoriteFoodsState(
favoriteFoodsModelObj:
FavoriteFoodsModel(userRegistrationSheet: sheet)))
..add(FavoriteFoodsInitialEvent()),
child: FavoriteFoodsScreen());
}
@override
State<FavoriteFoodsScreen> createState() => _FavoriteFoodsScreenState();
}
class _FavoriteFoodsScreenState extends State<FavoriteFoodsScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -31,7 +40,21 @@ class FavoriteFoodsScreen extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
_buildProgressIndicator(context),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.90,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 19.v),
Container(
width: 327.h,
@@ -42,16 +65,31 @@ class FavoriteFoodsScreen extends StatelessWidget {
textAlign: TextAlign.center,
style: theme.textTheme.headlineSmall)),
SizedBox(height: 23.v),
_buildTextFormField(context),
_buildTextFormFieldFav(context),
SizedBox(height: 22.v),
_buildTextFormField1(context),
_buildTextFormFieldUnfav(context),
SizedBox(height: 27.v),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToSchedule(context);
}),
BlocBuilder<FavoriteFoodsBloc, FavoriteFoodsState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet = state
.favoriteFoodsModelObj!.userRegistrationSheet;
sheet.favoriteFoods =
state.favoriteFoodsController!.text;
sheet.unfavoriteFoods =
state.unfavoriteFoodsController!.text;
Navigator.pushNamed(
context,
AppRoutes.additionalInformationScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
@@ -72,33 +110,16 @@ class FavoriteFoodsScreen extends StatelessWidget {
}
/// Section Widget
Widget _buildProgressIndicator(BuildContext context) {
return Container(
width: 343.h,
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 279.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Section Widget
Widget _buildTextFormField(BuildContext context) {
Widget _buildTextFormFieldFav(BuildContext context) {
return Column(children: [
Text("favorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI),
SizedBox(height: 2.v),
BlocSelector<FavoriteFoodsBloc, FavoriteFoodsState,
TextEditingController?>(
selector: (state) => state.enterinformationController,
builder: (context, enterinformationController) {
selector: (state) => state.favoriteFoodsController,
builder: (context, favoriteFoodsController) {
return CustomTextFormField(
controller: enterinformationController,
controller: favoriteFoodsController,
hintText: "enter_information".tr,
maxLines: 7);
})
@@ -106,16 +127,16 @@ class FavoriteFoodsScreen extends StatelessWidget {
}
/// Section Widget
Widget _buildTextFormField1(BuildContext context) {
Widget _buildTextFormFieldUnfav(BuildContext context) {
return Column(children: [
Text("unfavorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI),
SizedBox(height: 2.v),
BlocSelector<FavoriteFoodsBloc, FavoriteFoodsState,
TextEditingController?>(
selector: (state) => state.enterinformationController1,
builder: (context, enterinformationController1) {
selector: (state) => state.unfavoriteFoodsController,
builder: (context, unfavoriteFoodsController) {
return CustomTextFormField(
controller: enterinformationController1,
controller: unfavoriteFoodsController,
hintText: "enter_information".tr,
textInputAction: TextInputAction.done,
maxLines: 7);
@@ -129,9 +150,9 @@ class FavoriteFoodsScreen extends StatelessWidget {
}
/// Navigates to the scheduleScreen when the action is triggered.
navigateToSchedule(BuildContext context) {
navigateToAdditionalInformationScreen(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.scheduleScreen,
AppRoutes.additionalInformationScreen,
);
}
}

View File

@@ -1,16 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [favorite_foods_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class FavoriteFoodsModel extends Equatable {
FavoriteFoodsModel() {}
UserRegistrationSheet userRegistrationSheet;
FavoriteFoodsModel({required this.userRegistrationSheet});
FavoriteFoodsModel copyWith() {
return FavoriteFoodsModel();
return FavoriteFoodsModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -4,21 +4,30 @@ 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:eatvio_app/widgets/custom_outlined_button.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';
import 'package:flutter/material.dart';
class FavoriteSportsScreen extends StatelessWidget {
class FavoriteSportsScreen extends StatefulWidget {
const FavoriteSportsScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<FavoriteSportsBloc>(
create: (context) => FavoriteSportsBloc(
FavoriteSportsState(favoriteSportsModelObj: FavoriteSportsModel()))
create: (context) => FavoriteSportsBloc(FavoriteSportsState(
favoriteSportsModelObj:
FavoriteSportsModel(userRegistrationSheet: sheet)))
..add(FavoriteSportsInitialEvent()),
child: FavoriteSportsScreen());
}
@override
State<FavoriteSportsScreen> createState() => _FavoriteSportsScreenState();
}
class _FavoriteSportsScreenState extends State<FavoriteSportsScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -33,19 +42,48 @@ class FavoriteSportsScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 20.v),
_buildProgressIndicatorSection(context),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary,
width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.83,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 38.v),
Text("your_favorite_sports".tr,
style: theme.textTheme.headlineSmall),
Spacer(flex: 32),
_buildTextFormFieldSection(context),
Spacer(flex: 67),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToFoods(context);
}),
BlocBuilder<FavoriteSportsBloc, FavoriteSportsState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet = state
.favoriteSportsModelObj!
.userRegistrationSheet;
sheet.aboutSportHobbies =
state.enterinformationController!.text;
Navigator.pushNamed(
context,
AppRoutes.favoriteFoodsScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 4.v)
@@ -65,23 +103,6 @@ class FavoriteSportsScreen extends StatelessWidget {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildProgressIndicatorSection(BuildContext context) {
return Container(
width: 343.h,
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 259.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Section Widget
Widget _buildTextFormFieldSection(BuildContext context) {
return Column(children: [
@@ -104,11 +125,4 @@ class FavoriteSportsScreen extends StatelessWidget {
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();
}
/// Navigates to the favoriteFoodsScreen when the action is triggered.
navigateToFoods(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.favoriteFoodsScreen,
);
}
}

View File

@@ -1,16 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [favorite_sports_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class FavoriteSportsModel extends Equatable {
FavoriteSportsModel() {}
UserRegistrationSheet userRegistrationSheet;
FavoriteSportsModel({required this.userRegistrationSheet});
FavoriteSportsModel copyWith() {
return FavoriteSportsModel();
return FavoriteSportsModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -9,10 +9,21 @@ part 'gender_state.dart';
class GenderBloc extends Bloc<GenderEvent, GenderState> {
GenderBloc(GenderState initialState) : super(initialState) {
on<GenderInitialEvent>(_onInitialize);
on<GenderSelectEvent>(_genderSelect);
}
_onInitialize(
GenderInitialEvent event,
Emitter<GenderState> emit,
) async {}
) async {
emit(state.copyWith(genderModelObj: state.genderModelObj));
}
_genderSelect(
GenderSelectEvent event,
Emitter<GenderState> emit,
) {
emit(state.copyWith(selectedRadioValue: event.value));
state.genderModelObj?.userRegistrationSheet.gender = event.value;
}
}

View File

@@ -9,8 +9,18 @@ part of 'gender_bloc.dart';
@immutable
abstract class GenderEvent extends Equatable {}
/// Event that is dispatched when the Gender widget is first created.
class GenderInitialEvent extends GenderEvent {
@override
List<Object?> get props => [];
}
class GenderSelectEvent extends GenderEvent {
GenderSelectEvent({required this.value});
String value;
@override
List<Object?> get props => [
value,
];
}

View File

@@ -4,16 +4,26 @@ part of 'gender_bloc.dart';
/// Represents the state of Gender in the application.
class GenderState extends Equatable {
GenderState({this.genderModelObj});
GenderState({
this.selectedRadioValue,
this.genderModelObj,
});
String? selectedRadioValue;
GenderModel? genderModelObj;
@override
List<Object?> get props => [
selectedRadioValue,
genderModelObj,
];
GenderState copyWith({GenderModel? genderModelObj}) {
GenderState copyWith({
String? selectedRadioValue,
GenderModel? genderModelObj,
}) {
return GenderState(
selectedRadioValue: selectedRadioValue ?? this.selectedRadioValue,
genderModelObj: genderModelObj ?? this.genderModelObj,
);
}

View File

@@ -1,23 +1,33 @@
import 'bloc/gender_bloc.dart';
import 'models/gender_model.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_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:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:flutter/material.dart';
class GenderScreen extends StatelessWidget {
class GenderScreen extends StatefulWidget {
const GenderScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<GenderBloc>(
create: (context) =>
GenderBloc(GenderState(genderModelObj: GenderModel()))
..add(GenderInitialEvent()),
create: (context) => GenderBloc(
GenderState(
genderModelObj: GenderModel(userRegistrationSheet: sheet),
),
)..add(GenderInitialEvent()),
child: GenderScreen());
}
@override
State<GenderScreen> createState() => _GenderScreenState();
}
class _GenderScreenState extends State<GenderScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -31,23 +41,72 @@ class GenderScreen extends StatelessWidget {
EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
_buildProgressIndicator(context),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.16,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 36.v),
Text("your_gender".tr,
style: theme.textTheme.headlineSmall),
Spacer(flex: 33),
Text(""),
SizedBox(height: 20.v),
Text(""),
RadioListTile(
title: Text('Мужской'),
value: 'male',
groupValue: state.selectedRadioValue,
onChanged: (value) {
BlocProvider.of<GenderBloc>(context)
.add(GenderSelectEvent(value: 'male'));
},
secondary: Image.asset(
'assets/images/img_male.png',
width: 40,
height: 40,
),
),
RadioListTile(
title: Text('Женский'),
value: 'female',
groupValue: state.selectedRadioValue,
onChanged: (value) {
BlocProvider.of<GenderBloc>(context)
.add(GenderSelectEvent(value: 'female'));
},
secondary: Image.asset(
'assets/images/img_female.png',
width: 40,
height: 40,
),
),
Spacer(flex: 66),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToDate(context);
}),
BlocBuilder<GenderBloc, GenderState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet =
state.genderModelObj!.userRegistrationSheet;
sheet.gender = state.selectedRadioValue!;
Navigator.pushNamed(
context,
AppRoutes.dateOfBirthScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
});
}
@@ -60,38 +119,16 @@ class GenderScreen extends StatelessWidget {
imagePath: ImageConstant.imgArrowLeft,
margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v),
onTap: () {
onTapArrowLeft(context);
NavigatorService.pushNamed(
AppRoutes.dateOfBirthScreen,
);
}),
centerTitle: true,
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildProgressIndicator(BuildContext context) {
return Container(
width: 343.h,
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 40.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Navigates to the previous screen.
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();
}
/// Navigates to the dateOfBirthScreen when the action is triggered.
navigateToDate(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.dateOfBirthScreen,
);
}
}

View File

@@ -1,16 +1,20 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [gender_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class GenderModel extends Equatable {
GenderModel() {}
UserRegistrationSheet userRegistrationSheet;
GenderModel({required this.userRegistrationSheet});
GenderModel copyWith() {
return GenderModel();
GenderModel copyWith({UserRegistrationSheet? userRegistrationSheet, gender}) {
return GenderModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -26,6 +26,8 @@ class HeightBloc extends Bloc<HeightEvent, HeightState> {
Emitter<HeightState> emit,
) {
emit(state.copyWith(selectedDropDownValue: event.value));
state.heightModelObj?.userRegistrationSheet.height =
int.tryParse(event.value.title)!;
}
List<SelectionPopupModel> fillDropdownItemList() {

View File

@@ -5,20 +5,28 @@ 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:eatvio_app/widgets/custom_drop_down.dart';
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:flutter/material.dart';
class HeightScreen extends StatelessWidget {
class HeightScreen extends StatefulWidget {
const HeightScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<HeightBloc>(
create: (context) =>
HeightBloc(HeightState(heightModelObj: HeightModel()))
..add(HeightInitialEvent()),
create: (context) => HeightBloc(HeightState(
heightModelObj: HeightModel(userRegistrationSheet: sheet)))
..add(HeightInitialEvent()),
child: HeightScreen());
}
@override
State<HeightScreen> createState() => _HeightScreenState();
}
class _HeightScreenState extends State<HeightScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -41,21 +49,61 @@ class HeightScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.35,
value: 0.55,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 39.v),
_buildTwentySix(context),
Column(children: [
Text("height_measurements".tr,
style: theme.textTheme.headlineSmall),
SizedBox(height: 174.v),
Column(children: [
Text("your_height".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 4.v),
BlocSelector<HeightBloc, HeightState, HeightModel?>(
selector: (state) => state.heightModelObj,
builder: (context, heightModelObj) {
return CustomDropDown(
icon: Container(
margin: EdgeInsets.fromLTRB(
30.h, 11.v, 17.h, 11.v),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(1.h)),
child: CustomImageView(
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "170",
items: heightModelObj?.dropdownItemList ?? [],
onChanged: (value) {
context
.read<HeightBloc>()
.add(ChangeDropDownEvent(value: value));
});
})
])
]),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToAllergies(context);
}),
BlocBuilder<HeightBloc, HeightState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet =
state.heightModelObj!.userRegistrationSheet;
Navigator.pushNamed(
context,
AppRoutes.allergiesScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
}
@@ -73,52 +121,8 @@ class HeightScreen extends StatelessWidget {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildTwentySixWidget(BuildContext context) {
return Column(children: [
Text("your_height".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 4.v),
BlocSelector<HeightBloc, HeightState, HeightModel?>(
selector: (state) => state.heightModelObj,
builder: (context, heightModelObj) {
return CustomDropDown(
icon: Container(
margin: EdgeInsets.fromLTRB(30.h, 11.v, 17.h, 11.v),
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(1.h)),
child: CustomImageView(
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "170",
items: heightModelObj?.dropdownItemList ?? [],
onChanged: (value) {
context
.read<HeightBloc>()
.add(ChangeDropDownEvent(value: value));
});
})
]);
}
/// Section Widget
Widget _buildTwentySix(BuildContext context) {
return Column(children: [
Text("height_measurements".tr, style: theme.textTheme.headlineSmall),
SizedBox(height: 174.v),
_buildTwentySixWidget(context)
]);
}
/// Navigates to the previous screen.
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();
}
/// Navigates to the allergiesScreen when the action is triggered.
navigateToAllergies(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.allergiesScreen,
);
}
}

View File

@@ -2,20 +2,25 @@
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [height_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class HeightModel extends Equatable {
HeightModel({this.dropdownItemList = const []}) {}
UserRegistrationSheet userRegistrationSheet;
HeightModel(
{this.dropdownItemList = const [], required this.userRegistrationSheet});
List<SelectionPopupModel> dropdownItemList;
HeightModel copyWith({List<SelectionPopupModel>? dropdownItemList}) {
return HeightModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
dropdownItemList: dropdownItemList ?? this.dropdownItemList,
);
}
@override
List<Object?> get props => [dropdownItemList];
List<Object?> get props => [dropdownItemList, userRegistrationSheet];
}

View File

@@ -27,6 +27,8 @@ class LanguageSelectBloc
Emitter<LanguageSelectState> emit,
) {
emit(state.copyWith(selectedDropDownValue: event.value));
state.languageSelectModelObj?.userRegistrationSheet.lang =
event.value.title;
}
List<SelectionPopupModel> fillDropdownItemList() {

View File

@@ -1,13 +1,14 @@
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'bloc/language_select_bloc.dart';
import 'models/language_select_model.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/widgets/custom_drop_down.dart';
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:flutter/material.dart';
class LanguageSelectScreen extends StatelessWidget {
const LanguageSelectScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
return BlocProvider<LanguageSelectBloc>(
create: (context) => LanguageSelectBloc(
@@ -30,7 +31,21 @@ class LanguageSelectScreen extends StatelessWidget {
height: 50.adaptSize,
width: 50.adaptSize),
SizedBox(height: 20.v),
_buildProgressIndicatorSection(context),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 20.v),
Container(
width: 262.h,
@@ -44,7 +59,10 @@ class LanguageSelectScreen extends StatelessWidget {
BlocSelector<LanguageSelectBloc, LanguageSelectState,
LanguageSelectModel?>(
selector: (state) => state.languageSelectModelObj,
builder: (context, languageSelectModelObj) {
builder: (
context,
languageSelectModelObj,
) {
return CustomDropDown(
icon: Container(
margin:
@@ -55,7 +73,7 @@ class LanguageSelectScreen extends StatelessWidget {
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "Русский".tr,
hintText: "Не выбрано".tr,
items:
languageSelectModelObj?.dropdownItemList ?? [],
onChanged: (value) {
@@ -66,41 +84,23 @@ class LanguageSelectScreen extends StatelessWidget {
}),
Spacer(flex: 63)
])),
bottomNavigationBar: _buildContinueButtonSection(context)));
}
/// Section Widget
Widget _buildProgressIndicatorSection(BuildContext context) {
return Container(
width: 343.h,
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 20.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Section Widget
Widget _buildContinueButtonSection(BuildContext context) {
return CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigteToGender(context);
});
}
/// Navigates to the genderScreen when the action is triggered.
navigteToGender(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.genderScreen,
);
bottomNavigationBar:
BlocBuilder<LanguageSelectBloc, LanguageSelectState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin:
EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet =
state.languageSelectModelObj!.userRegistrationSheet;
Navigator.pushNamed(
context,
AppRoutes.credentialsScreen,
arguments: sheet,
);
});
})));
}
}

View File

@@ -1,13 +1,41 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart';
/// This class defines the variables used in the [language_select_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class LanguageSelectModel extends Equatable {
LanguageSelectModel({this.dropdownItemList = const []}) {}
LanguageSelectModel({this.dropdownItemList = const []});
UserRegistrationSheet userRegistrationSheet = UserRegistrationSheet(
firstName: '',
lastName: '',
email: '',
password: '',
passwordConfirmation: '',
termsAccepted: false,
birthdate: DateTime.now(),
gender: '',
country: '',
city: '',
lang: '',
weight: 0,
height: 0,
chestCircumference: 0,
waistCircumference: 0,
hipCircumference: 0,
bloodPressureUp: 0,
bloodPressureDown: 0,
hasHypo: false,
hasHyper: false,
aboutAllergy: '',
aboutTakingPils: '',
aboutSportHobbies: '',
favoriteFoods: '',
unfavoriteFoods: '',
additionalInfo: '',
);
List<SelectionPopupModel> dropdownItemList;
LanguageSelectModel copyWith({List<SelectionPopupModel>? dropdownItemList}) {

View File

@@ -4,21 +4,30 @@ 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:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:flutter/material.dart';
class MedicineIntakeScreen extends StatelessWidget {
class MedicineIntakeScreen extends StatefulWidget {
const MedicineIntakeScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<MedicineIntakeBloc>(
create: (context) => MedicineIntakeBloc(
MedicineIntakeState(medicineIntakeModelObj: MedicineIntakeModel()))
create: (context) => MedicineIntakeBloc(MedicineIntakeState(
medicineIntakeModelObj:
MedicineIntakeModel(userRegistrationSheet: sheet)))
..add(MedicineIntakeInitialEvent()),
child: MedicineIntakeScreen());
}
@override
State<MedicineIntakeScreen> createState() => _MedicineIntakeScreenState();
}
class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -42,7 +51,7 @@ class MedicineIntakeScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.47,
value: 0.69,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
@@ -58,12 +67,25 @@ class MedicineIntakeScreen extends StatelessWidget {
SizedBox(height: 86.v),
_buildTextFormField(context),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToPressure(context);
}),
BlocBuilder<MedicineIntakeBloc, MedicineIntakeState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet = state
.medicineIntakeModelObj!.userRegistrationSheet;
sheet.aboutTakingPils =
state.enterInformationController!.text;
Navigator.pushNamed(
context,
AppRoutes.bloodPressureScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
@@ -106,11 +128,4 @@ class MedicineIntakeScreen extends StatelessWidget {
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();
}
/// Navigates to the bloodPressureScreen when the action is triggered.
navigateToPressure(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.bloodPressureScreen,
);
}
}

View File

@@ -1,16 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [medicine_intake_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class MedicineIntakeModel extends Equatable {
MedicineIntakeModel() {}
UserRegistrationSheet userRegistrationSheet;
MedicineIntakeModel({required this.userRegistrationSheet});
MedicineIntakeModel copyWith() {
return MedicineIntakeModel();
return MedicineIntakeModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
List<Object?> get props => [userRegistrationSheet];
}

View File

@@ -0,0 +1,22 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import '/core/app_export.dart';
import 'package:eatvio_app/presentation/name_screen/models/name_model.dart';
part 'name_event.dart';
part 'name_state.dart';
/// A bloc that manages the state of a Name according to the event that is dispatched to it.
class NameBloc extends Bloc<NameEvent, NameState> {
NameBloc(NameState initialState) : super(initialState) {
on<NameInitialEvent>(_onInitialize);
}
_onInitialize(
NameInitialEvent event,
Emitter<NameState> emit,
) async {
emit(state.copyWith(
firstNameController: TextEditingController(),
lastNameController: TextEditingController()));
}
}

View File

@@ -1,16 +1,16 @@
// ignore_for_file: must_be_immutable
part of 'schedule_bloc.dart';
part of 'name_bloc.dart';
/// Abstract class for all events that can be dispatched from the
///Schedule widget.
///Name widget.
///
/// Events must be immutable and implement the [Equatable] interface.
@immutable
abstract class ScheduleEvent extends Equatable {}
abstract class NameEvent extends Equatable {}
/// Event that is dispatched when the Schedule widget is first created.
class ScheduleInitialEvent extends ScheduleEvent {
/// Event that is dispatched when the Name widget is first created.
class NameInitialEvent extends NameEvent {
@override
List<Object?> get props => [];
}

View File

@@ -0,0 +1,36 @@
// ignore_for_file: must_be_immutable
part of 'name_bloc.dart';
/// Represents the state of Name in the application.
class NameState extends Equatable {
NameState({
this.firstNameController,
this.lastNameController,
this.nameModelObj,
});
TextEditingController? firstNameController;
TextEditingController? lastNameController;
NameModel? nameModelObj;
@override
List<Object?> get props => [
firstNameController,
lastNameController,
nameModelObj,
];
NameState copyWith({
TextEditingController? firstNameController,
TextEditingController? lastNameController,
NameModel? nameModelObj,
}) {
return NameState(
firstNameController: firstNameController ?? this.firstNameController,
lastNameController: lastNameController ?? this.lastNameController,
nameModelObj: nameModelObj ?? this.nameModelObj,
);
}
}

View File

@@ -0,0 +1,21 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [name_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class NameModel extends Equatable {
UserRegistrationSheet userRegistrationSheet;
NameModel({required this.userRegistrationSheet});
NameModel copyWith({UserRegistrationSheet? userRegistrationSheet}) {
return NameModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
);
}
@override
List<Object?> get props => [];
}

View File

@@ -0,0 +1,119 @@
import 'bloc/name_bloc.dart';
import 'models/name_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: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';
import 'package:flutter/material.dart';
class NameScreen extends StatelessWidget {
const NameScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<NameBloc>(
create: (context) => NameBloc(
NameState(
nameModelObj: NameModel(userRegistrationSheet: sheet),
),
)..add(NameInitialEvent()),
child: NameScreen());
}
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: _buildAppBar(context),
body: Container(
width: double.maxFinite,
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
Container(
height: 16.v,
width: 343.h,
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(8.h),
border: Border.all(
color: theme.colorScheme.primary, width: 1.h)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.1,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 39.v),
Text("what_is_your_name".tr,
style: theme.textTheme.headlineSmall),
SizedBox(height: 93.v),
Text("first_name".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 3.v),
BlocSelector<NameBloc, NameState, TextEditingController?>(
selector: (state) => state.firstNameController,
builder: (context, firstNameController) {
return CustomTextFormField(
controller: firstNameController,
textInputAction: TextInputAction.done);
}),
SizedBox(height: 19.v),
Text("last_name".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 5.v),
BlocSelector<NameBloc, NameState, TextEditingController?>(
selector: (state) => state.lastNameController,
builder: (context, lastNameController) {
return CustomTextFormField(
controller: lastNameController,
);
}),
SizedBox(height: 21.v),
Spacer(),
BlocBuilder<NameBloc, NameState>(builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
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,
);
});
}),
SizedBox(height: 17.v),
]))));
}
/// Section Widget
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();
}
}

View File

@@ -1,20 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import '/core/app_export.dart';
import 'package:eatvio_app/presentation/schedule_screen/models/schedule_model.dart';
part 'schedule_event.dart';
part 'schedule_state.dart';
/// A bloc that manages the state of a Schedule according to the event that is dispatched to it.
class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
ScheduleBloc(ScheduleState initialState) : super(initialState) {
on<ScheduleInitialEvent>(_onInitialize);
}
_onInitialize(
ScheduleInitialEvent event,
Emitter<ScheduleState> emit,
) async {
emit(state.copyWith(inputPlaceholderController: TextEditingController()));
}
}

View File

@@ -1,31 +0,0 @@
// ignore_for_file: must_be_immutable
part of 'schedule_bloc.dart';
/// Represents the state of Schedule in the application.
class ScheduleState extends Equatable {
ScheduleState({
this.inputPlaceholderController,
this.scheduleModelObj,
});
TextEditingController? inputPlaceholderController;
ScheduleModel? scheduleModelObj;
@override
List<Object?> get props => [
inputPlaceholderController,
scheduleModelObj,
];
ScheduleState copyWith({
TextEditingController? inputPlaceholderController,
ScheduleModel? scheduleModelObj,
}) {
return ScheduleState(
inputPlaceholderController:
inputPlaceholderController ?? this.inputPlaceholderController,
scheduleModelObj: scheduleModelObj ?? this.scheduleModelObj,
);
}
}

View File

@@ -1,16 +0,0 @@
// ignore_for_file: must_be_immutable
import 'package:equatable/equatable.dart';
/// This class defines the variables used in the [schedule_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class ScheduleModel extends Equatable {
ScheduleModel() {}
ScheduleModel copyWith() {
return ScheduleModel();
}
@override
List<Object?> get props => [];
}

View File

@@ -1,118 +0,0 @@
import 'bloc/schedule_bloc.dart';
import 'models/schedule_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:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
import 'package:flutter/material.dart';
class ScheduleScreen extends StatelessWidget {
const ScheduleScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
return BlocProvider<ScheduleBloc>(
create: (context) =>
ScheduleBloc(ScheduleState(scheduleModelObj: ScheduleModel()))
..add(ScheduleInitialEvent()),
child: ScheduleScreen());
}
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: _buildAppBar(context),
body: Container(
width: double.maxFinite,
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
child: Column(children: [
SizedBox(height: 7.v),
_buildProgressIndicator(context),
SizedBox(height: 38.v),
Text("your_schedule".tr,
style: theme.textTheme.headlineSmall),
SizedBox(height: 67.v),
_buildTextFormField(context),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToAdditional(context);
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
}
/// Section Widget
PreferredSizeWidget _buildAppBar(BuildContext context) {
return CustomAppBar(
leadingWidth: 31.h,
leading: AppbarLeadingImage(
imagePath: ImageConstant.imgArrowLeft,
margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v),
onTap: () {
onTapArrowLeft(context);
}),
centerTitle: true,
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildProgressIndicator(BuildContext context) {
return Container(
width: 343.h,
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 3.v),
decoration: AppDecoration.outlinePrimary
.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
child: Container(
height: 8.v,
width: 297.h,
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(4.h),
border:
Border.all(color: theme.colorScheme.primary, width: 1.h))));
}
/// Section Widget
Widget _buildTextFormField(BuildContext context) {
return Column(children: [
Container(
width: 324.h,
margin: EdgeInsets.symmetric(horizontal: 9.h),
child: Text("tell_your_schedule".tr,
maxLines: 3,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: CustomTextStyles.titleMediumSegoeUI)),
SizedBox(height: 12.v),
BlocSelector<ScheduleBloc, ScheduleState, TextEditingController?>(
selector: (state) => state.inputPlaceholderController,
builder: (context, inputPlaceholderController) {
return CustomTextFormField(
controller: inputPlaceholderController,
hintText: "enter_information".tr,
textInputAction: TextInputAction.done,
maxLines: 8);
})
]);
}
/// Navigates to the previous screen.
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();
}
/// Navigates to the additionalInformationScreen when the action is triggered.
navigateToAdditional(BuildContext context) {
NavigatorService.pushNamed(
AppRoutes.additionalInformationScreen,
);
}
}

View File

@@ -5,7 +5,7 @@ import 'package:equatable/equatable.dart';
/// This class defines the variables used in the [splash_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class SplashModel extends Equatable {
SplashModel() {}
SplashModel();
SplashModel copyWith() {
return SplashModel();

View File

@@ -26,6 +26,8 @@ class WeightBloc extends Bloc<WeightEvent, WeightState> {
Emitter<WeightState> emit,
) {
emit(state.copyWith(selectedDropDownValue: event.value));
state.weightModelObj?.userRegistrationSheet.weight =
int.tryParse(event.value.title)!;
}
List<SelectionPopupModel> fillDropdownItemList() {

View File

@@ -2,20 +2,25 @@
import 'package:equatable/equatable.dart';
import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
/// This class defines the variables used in the [weight_screen],
/// and is typically used to hold data that is passed between different parts of the application.
class WeightModel extends Equatable {
WeightModel({this.dropdownItemList = const []}) {}
UserRegistrationSheet userRegistrationSheet;
WeightModel(
{this.dropdownItemList = const [], required this.userRegistrationSheet});
List<SelectionPopupModel> dropdownItemList;
WeightModel copyWith({List<SelectionPopupModel>? dropdownItemList}) {
return WeightModel(
userRegistrationSheet:
userRegistrationSheet ?? this.userRegistrationSheet,
dropdownItemList: dropdownItemList ?? this.dropdownItemList,
);
}
@override
List<Object?> get props => [dropdownItemList];
List<Object?> get props => [dropdownItemList, userRegistrationSheet];
}

View File

@@ -5,20 +5,28 @@ 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:eatvio_app/widgets/custom_drop_down.dart';
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
import 'package:eatvio_app/widgets/next_step_button.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:flutter/material.dart';
class WeightScreen extends StatelessWidget {
class WeightScreen extends StatefulWidget {
const WeightScreen({Key? key}) : super(key: key);
static Widget builder(BuildContext context) {
final sheet =
ModalRoute.of(context)!.settings.arguments as UserRegistrationSheet;
return BlocProvider<WeightBloc>(
create: (context) =>
WeightBloc(WeightState(weightModelObj: WeightModel()))
..add(WeightInitialEvent()),
create: (context) => WeightBloc(WeightState(
weightModelObj: WeightModel(userRegistrationSheet: sheet)))
..add(WeightInitialEvent()),
child: WeightScreen());
}
@override
State<WeightScreen> createState() => _WeightScreenState();
}
class _WeightScreenState extends State<WeightScreen> {
@override
Widget build(BuildContext context) {
mediaQueryData = MediaQuery.of(context);
@@ -41,21 +49,61 @@ class WeightScreen extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(8.h),
child: LinearProgressIndicator(
value: 0.35,
value: 0.48,
backgroundColor: theme.colorScheme.onPrimary,
valueColor: AlwaysStoppedAnimation<Color>(
appTheme.blueA400)))),
SizedBox(height: 39.v),
_buildTwentySix(context),
Column(children: [
Text("weight_measurements".tr,
style: theme.textTheme.headlineSmall),
SizedBox(height: 174.v),
Column(children: [
Text("your_weight".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 4.v),
BlocSelector<WeightBloc, WeightState, WeightModel?>(
selector: (state) => state.weightModelObj,
builder: (context, weightModelObj) {
return CustomDropDown(
icon: Container(
margin: EdgeInsets.fromLTRB(
30.h, 11.v, 17.h, 11.v),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(1.h)),
child: CustomImageView(
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "Не выбрано",
items: weightModelObj?.dropdownItemList ?? [],
onChanged: (value) {
context
.read<WeightBloc>()
.add(ChangeDropDownEvent(value: value));
});
})
])
]),
Spacer(),
CustomOutlinedButton(
text: "continue".tr.toUpperCase(),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
navigateToHeight(context);
}),
BlocBuilder<WeightBloc, WeightState>(
builder: (context, state) {
return NextStepButton(
text: "continue".tr.toUpperCase(),
margin: EdgeInsets.only(
left: 16.h, right: 16.h, bottom: 50.v),
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
onPressed: () {
UserRegistrationSheet sheet =
state.weightModelObj!.userRegistrationSheet;
Navigator.pushNamed(
context,
AppRoutes.heightScreen,
arguments: sheet,
);
});
}),
SizedBox(height: 17.v),
Text("skip".tr, style: theme.textTheme.bodyLarge)
]))));
}
@@ -73,43 +121,6 @@ class WeightScreen extends StatelessWidget {
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio));
}
/// Section Widget
Widget _buildTwentySixWidget(BuildContext context) {
return Column(children: [
Text("your_weight".tr, style: theme.textTheme.bodyLarge),
SizedBox(height: 4.v),
BlocSelector<WeightBloc, WeightState, WeightModel?>(
selector: (state) => state.weightModelObj,
builder: (context, weightModelObj) {
return CustomDropDown(
icon: Container(
margin: EdgeInsets.fromLTRB(30.h, 11.v, 17.h, 11.v),
decoration:
BoxDecoration(borderRadius: BorderRadius.circular(1.h)),
child: CustomImageView(
imagePath: ImageConstant.imgFavorite,
height: 12.adaptSize,
width: 12.adaptSize)),
hintText: "70",
items: weightModelObj?.dropdownItemList ?? [],
onChanged: (value) {
context
.read<WeightBloc>()
.add(ChangeDropDownEvent(value: value));
});
})
]);
}
/// Section Widget
Widget _buildTwentySix(BuildContext context) {
return Column(children: [
Text("weight_measurements".tr, style: theme.textTheme.headlineSmall),
SizedBox(height: 174.v),
_buildTwentySixWidget(context)
]);
}
/// Navigates to the previous screen.
onTapArrowLeft(BuildContext context) {
NavigatorService.goBack();

View File

@@ -10,10 +10,11 @@ import 'package:eatvio_app/presentation/gender_screen/gender_screen.dart';
import 'package:eatvio_app/presentation/blood_pressure_screen/blood_pressure_screen.dart';
import 'package:eatvio_app/presentation/favorite_sports_screen/favorite_sports_screen.dart';
import 'package:eatvio_app/presentation/favorite_foods_screen/favorite_foods_screen.dart';
import 'package:eatvio_app/presentation/schedule_screen/schedule_screen.dart';
import 'package:eatvio_app/presentation/additional_information_screen/additional_information_screen.dart';
import 'package:eatvio_app/presentation/language_select_screen/language_select_screen.dart';
import 'package:eatvio_app/presentation/height_screen/height_screen.dart';
import 'package:eatvio_app/presentation/credentials_screen/credentials_screen.dart';
import 'package:eatvio_app/presentation/name_screen/name_screen.dart';
import 'package:eatvio_app/presentation/app_navigation_screen/app_navigation_screen.dart';
class AppRoutes {
@@ -50,6 +51,10 @@ class AppRoutes {
static const String languageSelectScreen = '/language_select_screen';
static const String nameScreen = '/name_screen';
static const String credentialsScreen = '/credentials_screen';
static const String appNavigationScreen = '/app_navigation_screen';
static const String initialRoute = '/initialRoute';
@@ -60,6 +65,8 @@ class AppRoutes {
bodyCircumferencesScreen: BodyCircumferencesScreen.builder,
weightScreen: WeightScreen.builder,
heightScreen: HeightScreen.builder,
nameScreen: NameScreen.builder,
credentialsScreen: CredentialsScreen.builder,
allergiesScreen: AllergiesScreen.builder,
medicineIntakeScreen: MedicineIntakeScreen.builder,
splashScreen: SplashScreen.builder,
@@ -67,7 +74,6 @@ class AppRoutes {
bloodPressureScreen: BloodPressureScreen.builder,
favoriteSportsScreen: FavoriteSportsScreen.builder,
favoriteFoodsScreen: FavoriteFoodsScreen.builder,
scheduleScreen: ScheduleScreen.builder,
additionalInformationScreen: AdditionalInformationScreen.builder,
languageSelectScreen: LanguageSelectScreen.builder,
appNavigationScreen: AppNavigationScreen.builder,

View File

@@ -1,4 +1,3 @@
import 'dart:ui';
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';

View File

@@ -1,4 +1,3 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import '../../core/app_export.dart';

View File

@@ -1,4 +1,3 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';
class BaseButton extends StatelessWidget {

View File

@@ -1,5 +1,6 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class CustomTextFormField extends StatelessWidget {
CustomTextFormField({
@@ -21,10 +22,12 @@ class CustomTextFormField extends StatelessWidget {
this.suffix,
this.suffixConstraints,
this.contentPadding,
this.inputFormatters,
this.borderDecoration,
this.fillColor,
this.filled = true,
this.validator,
this.onSaved,
}) : super(
key: key,
);
@@ -43,6 +46,8 @@ class CustomTextFormField extends StatelessWidget {
final bool? obscureText;
final List<TextInputFormatter>? inputFormatters;
final TextInputAction? textInputAction;
final TextInputType? textInputType;
@@ -71,6 +76,8 @@ class CustomTextFormField extends StatelessWidget {
final FormFieldValidator<String>? validator;
final void Function(String?)? onSaved;
@override
Widget build(BuildContext context) {
return alignment != null
@@ -94,6 +101,8 @@ class CustomTextFormField extends StatelessWidget {
maxLines: maxLines ?? 1,
decoration: decoration,
validator: validator,
onSaved: onSaved,
inputFormatters: inputFormatters,
),
);
InputDecoration get decoration => InputDecoration(

View File

@@ -2,8 +2,8 @@ import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/widgets/base_button.dart';
import 'package:flutter/material.dart';
class CustomOutlinedButton extends BaseButton {
CustomOutlinedButton({
class NextStepButton extends BaseButton {
NextStepButton({
Key? key,
this.decoration,
this.leftIcon,

View File

@@ -9,10 +9,10 @@ dependencies:
flutter_localizations:
sdk: flutter
flutter_bloc: ^8.0.0
connectivity_plus: ^2.3.6
connectivity_plus: ^5.0.2
shared_preferences: ^2.0.15
cached_network_image: ^3.2.1
flutter_svg: ^1.1.6
flutter_svg: ^2.0.9
equatable: ^2.0.0
dev_dependencies:
flutter_test: