feature(registration): new registration flow

This commit is contained in:
mso7nueh
2024-07-11 14:49:50 +03:00
parent c3f7853d0e
commit aacba077b7
23 changed files with 2176 additions and 1967 deletions

View File

@@ -0,0 +1,10 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_state.dart';
import 'package:eatvio_app/presentation/registration/language_select_screen/models/language_select_model.dart';
class RegistrationCubit extends Cubit<RegistrationState> {
RegistrationCubit() : super(RegistrationState.loaded(sheet: LanguageSelectModel().userRegistrationSheet));
updateSheet(UserRegistrationSheet sheet) => emit(RegistrationState.loaded(sheet: sheet));
}

View File

@@ -0,0 +1,13 @@
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'registration_state.freezed.dart';
@freezed
abstract class RegistrationState with _$RegistrationState {
const factory RegistrationState() = _RegistrationState;
const factory RegistrationState.loaded({
required UserRegistrationSheet sheet,
}) = RegistrationStateLoaded;
}

View File

@@ -0,0 +1,315 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'registration_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$RegistrationState {
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function(UserRegistrationSheet sheet) loaded,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function(UserRegistrationSheet sheet)? loaded,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function(UserRegistrationSheet sheet)? loaded,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_RegistrationState value) $default, {
required TResult Function(RegistrationStateLoaded value) loaded,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_RegistrationState value)? $default, {
TResult? Function(RegistrationStateLoaded value)? loaded,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_RegistrationState value)? $default, {
TResult Function(RegistrationStateLoaded value)? loaded,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $RegistrationStateCopyWith<$Res> {
factory $RegistrationStateCopyWith(
RegistrationState value, $Res Function(RegistrationState) then) =
_$RegistrationStateCopyWithImpl<$Res, RegistrationState>;
}
/// @nodoc
class _$RegistrationStateCopyWithImpl<$Res, $Val extends RegistrationState>
implements $RegistrationStateCopyWith<$Res> {
_$RegistrationStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
}
/// @nodoc
abstract class _$$RegistrationStateImplCopyWith<$Res> {
factory _$$RegistrationStateImplCopyWith(_$RegistrationStateImpl value,
$Res Function(_$RegistrationStateImpl) then) =
__$$RegistrationStateImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$RegistrationStateImplCopyWithImpl<$Res>
extends _$RegistrationStateCopyWithImpl<$Res, _$RegistrationStateImpl>
implements _$$RegistrationStateImplCopyWith<$Res> {
__$$RegistrationStateImplCopyWithImpl(_$RegistrationStateImpl _value,
$Res Function(_$RegistrationStateImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$RegistrationStateImpl implements _RegistrationState {
const _$RegistrationStateImpl();
@override
String toString() {
return 'RegistrationState()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$RegistrationStateImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function(UserRegistrationSheet sheet) loaded,
}) {
return $default();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function(UserRegistrationSheet sheet)? loaded,
}) {
return $default?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function(UserRegistrationSheet sheet)? loaded,
required TResult orElse(),
}) {
if ($default != null) {
return $default();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_RegistrationState value) $default, {
required TResult Function(RegistrationStateLoaded value) loaded,
}) {
return $default(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_RegistrationState value)? $default, {
TResult? Function(RegistrationStateLoaded value)? loaded,
}) {
return $default?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_RegistrationState value)? $default, {
TResult Function(RegistrationStateLoaded value)? loaded,
required TResult orElse(),
}) {
if ($default != null) {
return $default(this);
}
return orElse();
}
}
abstract class _RegistrationState implements RegistrationState {
const factory _RegistrationState() = _$RegistrationStateImpl;
}
/// @nodoc
abstract class _$$RegistrationStateLoadedImplCopyWith<$Res> {
factory _$$RegistrationStateLoadedImplCopyWith(
_$RegistrationStateLoadedImpl value,
$Res Function(_$RegistrationStateLoadedImpl) then) =
__$$RegistrationStateLoadedImplCopyWithImpl<$Res>;
@useResult
$Res call({UserRegistrationSheet sheet});
}
/// @nodoc
class __$$RegistrationStateLoadedImplCopyWithImpl<$Res>
extends _$RegistrationStateCopyWithImpl<$Res, _$RegistrationStateLoadedImpl>
implements _$$RegistrationStateLoadedImplCopyWith<$Res> {
__$$RegistrationStateLoadedImplCopyWithImpl(
_$RegistrationStateLoadedImpl _value,
$Res Function(_$RegistrationStateLoadedImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? sheet = null,
}) {
return _then(_$RegistrationStateLoadedImpl(
sheet: null == sheet
? _value.sheet
: sheet // ignore: cast_nullable_to_non_nullable
as UserRegistrationSheet,
));
}
}
/// @nodoc
class _$RegistrationStateLoadedImpl implements RegistrationStateLoaded {
const _$RegistrationStateLoadedImpl({required this.sheet});
@override
final UserRegistrationSheet sheet;
@override
String toString() {
return 'RegistrationState.loaded(sheet: $sheet)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$RegistrationStateLoadedImpl &&
(identical(other.sheet, sheet) || other.sheet == sheet));
}
@override
int get hashCode => Object.hash(runtimeType, sheet);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$RegistrationStateLoadedImplCopyWith<_$RegistrationStateLoadedImpl>
get copyWith => __$$RegistrationStateLoadedImplCopyWithImpl<
_$RegistrationStateLoadedImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function(UserRegistrationSheet sheet) loaded,
}) {
return loaded(sheet);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function(UserRegistrationSheet sheet)? loaded,
}) {
return loaded?.call(sheet);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function(UserRegistrationSheet sheet)? loaded,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(sheet);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_RegistrationState value) $default, {
required TResult Function(RegistrationStateLoaded value) loaded,
}) {
return loaded(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_RegistrationState value)? $default, {
TResult? Function(RegistrationStateLoaded value)? loaded,
}) {
return loaded?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_RegistrationState value)? $default, {
TResult Function(RegistrationStateLoaded value)? loaded,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(this);
}
return orElse();
}
}
abstract class RegistrationStateLoaded implements RegistrationState {
const factory RegistrationStateLoaded(
{required final UserRegistrationSheet sheet}) =
_$RegistrationStateLoadedImpl;
UserRegistrationSheet get sheet;
@JsonKey(ignore: true)
_$$RegistrationStateLoadedImplCopyWith<_$RegistrationStateLoadedImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,201 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/core/utils/image_constant.dart';
import 'package:eatvio_app/data/models/userRegistrationModel/user_registration_model.dart';
import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_cubit.dart';
import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_state.dart';
import 'package:eatvio_app/presentation/registration/additional_information_screen/additional_information_screen.dart';
import 'package:eatvio_app/presentation/registration/allergies_screen/allergies_screen.dart';
import 'package:eatvio_app/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart';
import 'package:eatvio_app/presentation/registration/body_circumferences_screen/body_circumferences_screen.dart';
import 'package:eatvio_app/presentation/registration/city_of_living_screen/city_of_living_screen.dart';
import 'package:eatvio_app/presentation/registration/credentials_screen/bloc/credentials_bloc.dart';
import 'package:eatvio_app/presentation/registration/credentials_screen/credentials_screen.dart';
import 'package:eatvio_app/presentation/registration/date_of_birth_screen/date_of_birth_screen.dart';
import 'package:eatvio_app/presentation/registration/favorite_foods_screen/favorite_foods_screen.dart';
import 'package:eatvio_app/presentation/registration/favorite_sports_screen/favorite_sports_screen.dart';
import 'package:eatvio_app/presentation/registration/gender_screen/gender_screen.dart';
import 'package:eatvio_app/presentation/registration/height_screen/height_screen.dart';
import 'package:eatvio_app/presentation/registration/language_select_screen/bloc/language_select_bloc.dart';
import 'package:eatvio_app/presentation/registration/language_select_screen/language_select_screen.dart';
import 'package:eatvio_app/presentation/registration/language_select_screen/models/language_select_model.dart';
import 'package:eatvio_app/presentation/registration/medicine_intake_screen/medicine_intake_screen.dart';
import 'package:eatvio_app/presentation/registration/name_screen/name_screen.dart';
import 'package:eatvio_app/presentation/registration/weight_screen/weight_screen.dart';
import 'package:eatvio_app/theme/theme_helper.dart';
import 'package:eatvio_app/widgets/app_bar/appbar_title_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class RegistrationScreen extends StatefulWidget {
const RegistrationScreen({super.key});
@override
State<RegistrationScreen> createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
double progressValue = 1 / 15;
int step = 1;
final pageController = PageController();
_showPopDialog() {
showDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
content: Text('Отменить регистрацию? Заполненные данные не будут сохранены.'),
actions: [
CupertinoDialogAction(
onPressed: () {
Navigator.pop(context);
GoRouter.of(context).pop();
},
child: Text('Да'),
),
CupertinoDialogAction(
onPressed: () {
Navigator.pop(context);
},
isDefaultAction: true,
child: Text('Нет'),
)
],
),
);
}
@override
Widget build(BuildContext context) {
return BlocProvider<RegistrationCubit>(
create: (BuildContext context) => RegistrationCubit(),
child: BlocBuilder<RegistrationCubit, RegistrationState>(
builder: (BuildContext context, RegistrationState state) {
(state as RegistrationStateLoaded);
return PopScope(
canPop: false,
onPopInvoked: (_) => _showPopDialog(),
child: Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Row(
children: [
Container(
height: 48,
width: MediaQuery.of(context).size.width * 0.2,
padding: EdgeInsets.only(left: 16, right: 4),
child: FloatingActionButton.extended(
heroTag: 'backButtonRegistration',
highlightElevation: 0,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
backgroundColor: Color(0xFFEAF2FD),
onPressed: () {
if (pageController.page == 0) _showPopDialog();
setState(() {
pageController.previousPage(
duration: const Duration(milliseconds: 350),
curve: Curves.easeInOut,
);
});
},
label: Icon(
Icons.arrow_back_ios_new_rounded,
color: appTheme.blueA400,
),
),
),
Container(
height: 48,
width: MediaQuery.of(context).size.width * 0.8,
padding: EdgeInsets.only(left: 4, right: 16),
child: FloatingActionButton.extended(
heroTag: 'nextButtonRegistration',
highlightElevation: 0,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
backgroundColor: appTheme.blueA400,
onPressed: () {
setState(() {
pageController.nextPage(
duration: const Duration(milliseconds: 350),
curve: Curves.easeInOut,
);
});
},
label: Text(
'Продолжить',
style: theme.textTheme.titleSmall,
),
),
),
],
),
appBar: AppBar(
automaticallyImplyLeading: true,
centerTitle: true,
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
actions: [
Padding(
padding: const EdgeInsets.only(right: 16),
child: Text('шаг $step из 15'),
),
],
bottom: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, 32),
child: Padding(
padding: const EdgeInsets.all(16),
child: TweenAnimationBuilder<double>(
duration: const Duration(milliseconds: 350),
curve: Curves.easeInOut,
tween: Tween<double>(
begin: 0,
end: progressValue,
),
builder: (context, value, _) => LinearProgressIndicator(
value: value,
borderRadius: BorderRadius.circular(16),
minHeight: 8,
backgroundColor: Colors.grey.shade100,
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
),
),
),
),
),
body: PageView(
physics: NeverScrollableScrollPhysics(),
controller: pageController,
onPageChanged: (index) {
setState(() {
step = index + 1;
progressValue = step / 15;
});
},
children: [
LanguageSelectScreen.builder(context),
CredentialsScreen.builder(context, state.sheet),
NameScreen.builder(context, state.sheet),
GenderScreen.builder(context, state.sheet),
DateOfBirthScreen.builder(context, state.sheet),
CityOfLivingScreen.builder(context, state.sheet),
BodyCircumferencesScreen.builder(context, state.sheet),
WeightScreen.builder(context, state.sheet),
HeightScreen.builder(context, state.sheet),
BloodPressureScreen.builder(context, state.sheet),
AllergiesScreen.builder(context, state.sheet),
MedicineIntakeScreen.builder(context, state.sheet),
FavoriteSportsScreen.builder(context, state.sheet),
FavoriteFoodsScreen.builder(context, state.sheet),
AdditionalInformationScreen.builder(context, state.sheet),
],
),
),
);
},
),
);
}
}