refactor(all): refactor
This commit is contained in:
@@ -48,7 +48,6 @@ class AppRouter {
|
||||
name: 'authScreen',
|
||||
redirect: (context, state) async {
|
||||
if (await TokenStorage.haveTokenInStorage()) {
|
||||
await context.read<InitializationCubit>().runInitialization();
|
||||
return '/my-profile-screen';
|
||||
}
|
||||
return null;
|
||||
@@ -106,29 +105,31 @@ class AppRouter {
|
||||
builder: (context, state) => BloodPressureScreen.builder(context, state.extra),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'favorite-sports-screen',
|
||||
name: 'favoriteSportsScreen',
|
||||
builder: (context, state) => FavoriteSportsScreen.builder(context, state.extra),
|
||||
name: 'allergiesScreen',
|
||||
path: 'allergiesScreen',
|
||||
builder: (context, state) => AllergiesScreen.builder(context, state.extra),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'allergiesScreen',
|
||||
path: 'allergiesScreen',
|
||||
builder: (context, state) => AllergiesScreen.builder(context, state.extra),
|
||||
name: 'medicineIntakeScreen',
|
||||
path: 'medicine-intake-screen',
|
||||
builder: (context, state) => MedicineIntakeScreen.builder(context, state.extra),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'medicineIntakeScreen',
|
||||
path: 'medicine-intake-screen',
|
||||
builder: (context, state) => MedicineIntakeScreen.builder(context, state.extra),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'favoriteFoodsScreen',
|
||||
path: 'favorite-foods-screen',
|
||||
builder: (context, state) => FavoriteFoodsScreen.builder(context, state.extra),
|
||||
path: 'favorite-sports-screen',
|
||||
name: 'favoriteSportsScreen',
|
||||
builder: (context, state) => FavoriteSportsScreen.builder(context, state.extra),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'additional-information-screen',
|
||||
name: 'additionalInformationScreen',
|
||||
builder: (context, state) => AdditionalInformationScreen.builder(context, state.extra),
|
||||
name: 'favoriteFoodsScreen',
|
||||
path: 'favorite-foods-screen',
|
||||
builder: (context, state) => FavoriteFoodsScreen.builder(context, state.extra),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'additional-information-screen',
|
||||
name: 'additionalInformationScreen',
|
||||
builder: (context, state) => AdditionalInformationScreen.builder(context, state.extra),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -166,6 +167,10 @@ class AppRouter {
|
||||
GoRoute(
|
||||
path: '/my-profile-screen',
|
||||
name: 'myProfileScreen',
|
||||
redirect: (context, state) async {
|
||||
await context.read<InitializationCubit>().runInitialization();
|
||||
return null;
|
||||
},
|
||||
builder: (context, state) => MyProfileScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:eatvio_app/locator_service.dart';
|
||||
|
||||
class InitializationCubit extends Cubit<InitializationState> {
|
||||
final ChatRepository chatRepository;
|
||||
bool wasInitializated = false;
|
||||
|
||||
InitializationCubit({required this.chatRepository}) : super(const InitializationState.loading());
|
||||
|
||||
@@ -49,48 +50,51 @@ class InitializationCubit extends Cubit<InitializationState> {
|
||||
}
|
||||
|
||||
Future<void> runInitialization() async {
|
||||
try {
|
||||
await TokenStorage.haveTokenInStorage();
|
||||
final wsUrl = await chatRepository.getWebsocket();
|
||||
final options = PusherChannelsOptions.fromHost(
|
||||
scheme: 'wss',
|
||||
key: wsUrl.key,
|
||||
host: wsUrl.host,
|
||||
shouldSupplyMetadataQueries: true,
|
||||
metadata: PusherChannelsOptionsMetadata.byDefault(),
|
||||
port: 443,
|
||||
);
|
||||
final client = PusherChannelsClient.websocket(
|
||||
options: options,
|
||||
connectionErrorHandler: (exception, trace, refresh) {
|
||||
refresh();
|
||||
},
|
||||
minimumReconnectDelayDuration: const Duration(
|
||||
seconds: 1,
|
||||
),
|
||||
defaultActivityDuration: const Duration(
|
||||
seconds: 120,
|
||||
),
|
||||
activityDurationOverride: const Duration(
|
||||
seconds: 120,
|
||||
),
|
||||
waitForPongDuration: const Duration(
|
||||
seconds: 30,
|
||||
),
|
||||
);
|
||||
await client.connect();
|
||||
if (!wasInitializated) {
|
||||
wasInitializated = true;
|
||||
try {
|
||||
await TokenStorage.haveTokenInStorage();
|
||||
final wsUrl = await chatRepository.getWebsocket();
|
||||
final options = PusherChannelsOptions.fromHost(
|
||||
scheme: 'wss',
|
||||
key: wsUrl.key,
|
||||
host: wsUrl.host,
|
||||
shouldSupplyMetadataQueries: true,
|
||||
metadata: PusherChannelsOptionsMetadata.byDefault(),
|
||||
port: 443,
|
||||
);
|
||||
final client = PusherChannelsClient.websocket(
|
||||
options: options,
|
||||
connectionErrorHandler: (exception, trace, refresh) {
|
||||
refresh();
|
||||
},
|
||||
minimumReconnectDelayDuration: const Duration(
|
||||
seconds: 1,
|
||||
),
|
||||
defaultActivityDuration: const Duration(
|
||||
seconds: 120,
|
||||
),
|
||||
activityDurationOverride: const Duration(
|
||||
seconds: 120,
|
||||
),
|
||||
waitForPongDuration: const Duration(
|
||||
seconds: 30,
|
||||
),
|
||||
);
|
||||
await client.connect();
|
||||
|
||||
await subscribeNotifications(wsUrl.userId, client);
|
||||
await subscribeChatMessages(wsUrl.userId, client);
|
||||
await subscribeNotifications(wsUrl.userId, client);
|
||||
await subscribeChatMessages(wsUrl.userId, client);
|
||||
|
||||
emit(InitializationState.success(
|
||||
client: client,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(InitializationState.error(
|
||||
errorMessage: e.toString(),
|
||||
));
|
||||
rethrow;
|
||||
emit(InitializationState.success(
|
||||
client: client,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(InitializationState.error(
|
||||
errorMessage: e.toString(),
|
||||
));
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,6 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
),
|
||||
@@ -188,7 +187,6 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
hintText: 'Сообщение',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFFAEAEB2),
|
||||
),
|
||||
|
||||
@@ -42,18 +42,24 @@ class ChatSelectScreen extends StatelessWidget {
|
||||
body: NestedScrollView(
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverAppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
stretchTriggerOffset: 1,
|
||||
forceMaterialTransparency: true,
|
||||
floating: true,
|
||||
snap: true,
|
||||
title: CustomSearchView(
|
||||
controller: state.searchController,
|
||||
fillColor: Color(0xFFF0F2F5),
|
||||
hintText: "Поиск",
|
||||
hintStyle: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
sliver: SliverAppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
stretchTriggerOffset: 1,
|
||||
forceMaterialTransparency: true,
|
||||
floating: true,
|
||||
snap: true,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: CustomSearchView(
|
||||
controller: state.searchController,
|
||||
fillColor: Color(0xFFF0F2F5),
|
||||
hintText: "Поиск",
|
||||
hintStyle: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
15
lib/features/feed/models/feed_blog_post_settings_model.dart
Normal file
15
lib/features/feed/models/feed_blog_post_settings_model.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'feed_blog_post_settings_model.freezed.dart';
|
||||
part 'feed_blog_post_settings_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class FeedBlogPostSettingsModel with _$FeedBlogPostSettingsModel {
|
||||
const factory FeedBlogPostSettingsModel({
|
||||
@JsonKey(name: 'data')
|
||||
required List<FeedBlogPostModel> feedBlogPostList,
|
||||
}) = _FeedBlogPostSettingsModel;
|
||||
|
||||
factory FeedBlogPostSettingsModel.fromJson(Map<String, Object?> json) => _$FeedBlogPostSettingsModelFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
// 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 'feed_blog_post_settings_model.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');
|
||||
|
||||
FeedBlogPostSettingsModel _$FeedBlogPostSettingsModelFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return _FeedBlogPostSettingsModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$FeedBlogPostSettingsModel {
|
||||
@JsonKey(name: 'data')
|
||||
List<FeedBlogPostModel> get feedBlogPostList =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$FeedBlogPostSettingsModelCopyWith<FeedBlogPostSettingsModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $FeedBlogPostSettingsModelCopyWith<$Res> {
|
||||
factory $FeedBlogPostSettingsModelCopyWith(FeedBlogPostSettingsModel value,
|
||||
$Res Function(FeedBlogPostSettingsModel) then) =
|
||||
_$FeedBlogPostSettingsModelCopyWithImpl<$Res, FeedBlogPostSettingsModel>;
|
||||
@useResult
|
||||
$Res call({@JsonKey(name: 'data') List<FeedBlogPostModel> feedBlogPostList});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$FeedBlogPostSettingsModelCopyWithImpl<$Res,
|
||||
$Val extends FeedBlogPostSettingsModel>
|
||||
implements $FeedBlogPostSettingsModelCopyWith<$Res> {
|
||||
_$FeedBlogPostSettingsModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? feedBlogPostList = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
feedBlogPostList: null == feedBlogPostList
|
||||
? _value.feedBlogPostList
|
||||
: feedBlogPostList // ignore: cast_nullable_to_non_nullable
|
||||
as List<FeedBlogPostModel>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$FeedBlogPostSettingsModelImplCopyWith<$Res>
|
||||
implements $FeedBlogPostSettingsModelCopyWith<$Res> {
|
||||
factory _$$FeedBlogPostSettingsModelImplCopyWith(
|
||||
_$FeedBlogPostSettingsModelImpl value,
|
||||
$Res Function(_$FeedBlogPostSettingsModelImpl) then) =
|
||||
__$$FeedBlogPostSettingsModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({@JsonKey(name: 'data') List<FeedBlogPostModel> feedBlogPostList});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$FeedBlogPostSettingsModelImplCopyWithImpl<$Res>
|
||||
extends _$FeedBlogPostSettingsModelCopyWithImpl<$Res,
|
||||
_$FeedBlogPostSettingsModelImpl>
|
||||
implements _$$FeedBlogPostSettingsModelImplCopyWith<$Res> {
|
||||
__$$FeedBlogPostSettingsModelImplCopyWithImpl(
|
||||
_$FeedBlogPostSettingsModelImpl _value,
|
||||
$Res Function(_$FeedBlogPostSettingsModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? feedBlogPostList = null,
|
||||
}) {
|
||||
return _then(_$FeedBlogPostSettingsModelImpl(
|
||||
feedBlogPostList: null == feedBlogPostList
|
||||
? _value._feedBlogPostList
|
||||
: feedBlogPostList // ignore: cast_nullable_to_non_nullable
|
||||
as List<FeedBlogPostModel>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$FeedBlogPostSettingsModelImpl implements _FeedBlogPostSettingsModel {
|
||||
const _$FeedBlogPostSettingsModelImpl(
|
||||
{@JsonKey(name: 'data')
|
||||
required final List<FeedBlogPostModel> feedBlogPostList})
|
||||
: _feedBlogPostList = feedBlogPostList;
|
||||
|
||||
factory _$FeedBlogPostSettingsModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$FeedBlogPostSettingsModelImplFromJson(json);
|
||||
|
||||
final List<FeedBlogPostModel> _feedBlogPostList;
|
||||
@override
|
||||
@JsonKey(name: 'data')
|
||||
List<FeedBlogPostModel> get feedBlogPostList {
|
||||
if (_feedBlogPostList is EqualUnmodifiableListView)
|
||||
return _feedBlogPostList;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_feedBlogPostList);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FeedBlogPostSettingsModel(feedBlogPostList: $feedBlogPostList)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$FeedBlogPostSettingsModelImpl &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._feedBlogPostList, _feedBlogPostList));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(_feedBlogPostList));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$FeedBlogPostSettingsModelImplCopyWith<_$FeedBlogPostSettingsModelImpl>
|
||||
get copyWith => __$$FeedBlogPostSettingsModelImplCopyWithImpl<
|
||||
_$FeedBlogPostSettingsModelImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$FeedBlogPostSettingsModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _FeedBlogPostSettingsModel implements FeedBlogPostSettingsModel {
|
||||
const factory _FeedBlogPostSettingsModel(
|
||||
{@JsonKey(name: 'data')
|
||||
required final List<FeedBlogPostModel> feedBlogPostList}) =
|
||||
_$FeedBlogPostSettingsModelImpl;
|
||||
|
||||
factory _FeedBlogPostSettingsModel.fromJson(Map<String, dynamic> json) =
|
||||
_$FeedBlogPostSettingsModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'data')
|
||||
List<FeedBlogPostModel> get feedBlogPostList;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$FeedBlogPostSettingsModelImplCopyWith<_$FeedBlogPostSettingsModelImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'feed_blog_post_settings_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$FeedBlogPostSettingsModelImpl _$$FeedBlogPostSettingsModelImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$FeedBlogPostSettingsModelImpl(
|
||||
feedBlogPostList: (json['data'] as List<dynamic>)
|
||||
.map((e) => FeedBlogPostModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$FeedBlogPostSettingsModelImplToJson(
|
||||
_$FeedBlogPostSettingsModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'data': instance.feedBlogPostList,
|
||||
};
|
||||
@@ -8,7 +8,7 @@ class FeedRepository {
|
||||
|
||||
Future<List<FeedBlogPostModel>> getFeedBlogPostList() async {
|
||||
try {
|
||||
return (await feedService.getBlocPostList()).entries.map((entry) => entry.value).toList();
|
||||
return (await feedService.getBlocPostList()).feedBlogPostList;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_settings_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
part 'feed_service.g.dart';
|
||||
@@ -8,6 +8,6 @@ part 'feed_service.g.dart';
|
||||
abstract class FeedService {
|
||||
factory FeedService(Dio dio, {String baseUrl}) = _FeedService;
|
||||
|
||||
@GET('/feed/index')
|
||||
Future<Map<String, FeedBlogPostModel>> getBlocPostList();
|
||||
@GET('/blogPosts/index')
|
||||
Future<FeedBlogPostSettingsModel> getBlocPostList();
|
||||
}
|
||||
|
||||
@@ -19,20 +19,20 @@ class _FeedService implements FeedService {
|
||||
String? baseUrl;
|
||||
|
||||
@override
|
||||
Future<Map<String, FeedBlogPostModel>> getBlocPostList() async {
|
||||
Future<FeedBlogPostSettingsModel> getBlocPostList() async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _result = await _dio.fetch<Map<String, dynamic>>(
|
||||
_setStreamType<Map<String, FeedBlogPostModel>>(Options(
|
||||
_setStreamType<FeedBlogPostSettingsModel>(Options(
|
||||
method: 'GET',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/feed/index',
|
||||
'/blogPosts/index',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
@@ -41,8 +41,7 @@ class _FeedService implements FeedService {
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
))));
|
||||
var _value = _result.data!.map((k, dynamic v) =>
|
||||
MapEntry(k, FeedBlogPostModel.fromJson(v as Map<String, dynamic>)));
|
||||
final _value = FeedBlogPostSettingsModel.fromJson(_result.data!);
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ class MyApp extends StatelessWidget {
|
||||
BlocProvider<InitializationCubit>(create: (context) => sl<InitializationCubit>()),
|
||||
BlocProvider<NewMessagesCubit>(create: (context) => sl<NewMessagesCubit>()),
|
||||
BlocProvider<NotificationsCubit>(create: (context) => sl<NotificationsCubit>()),
|
||||
|
||||
BlocProvider<ThemeBloc>(create: (context) => ThemeBloc(ThemeState(themeType: PrefUtils().getThemeData()))),
|
||||
BlocProvider<FeedCubit>(create: (context) => sl<FeedCubit>()..loadFeedBlogPostList()),
|
||||
BlocProvider<MyProfileBloc>(create: (context) => MyProfileBloc(MyProfileState(myProfileModelObj: MyProfileModel()))..add(MyProfileInitialEvent())),
|
||||
|
||||
@@ -107,7 +107,7 @@ class AuthScreen extends StatelessWidget {
|
||||
final box = await Hive.openBox('token');
|
||||
final token = res['token'];
|
||||
box.put('token', token);
|
||||
TokenStorage.saveTokenInStorage(token);
|
||||
await TokenStorage.saveTokenInStorage(token);
|
||||
GoRouter.of(context).go('/my-profile-screen');
|
||||
} else {
|
||||
showDialog(
|
||||
|
||||
@@ -74,20 +74,16 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
waistCircumferenceController: TextEditingController(),
|
||||
hipCircumferenceController: TextEditingController(),
|
||||
weightController: TextEditingController(),
|
||||
chestCircumferenceFormController:
|
||||
currentState.chestCircumferenceFormController,
|
||||
waistCircumferenceFormController:
|
||||
currentState.waistCircumferenceFormController,
|
||||
hipCircumferenceFormController:
|
||||
currentState.hipCircumferenceFormController,
|
||||
chestCircumferenceFormController: currentState.chestCircumferenceFormController,
|
||||
waistCircumferenceFormController: currentState.waistCircumferenceFormController,
|
||||
hipCircumferenceFormController: currentState.hipCircumferenceFormController,
|
||||
firstNameFormController: currentState.firstNameFormController,
|
||||
lastNameFormController: currentState.lastNameFormController,
|
||||
countryFormController: currentState.countryFormController,
|
||||
cityFormController: currentState.cityFormController,
|
||||
heightFormController: currentState.heightFormController,
|
||||
upPressureFormController: currentState.upPressureFormController,
|
||||
downPressureFormController:
|
||||
currentState.downPressureFormController,
|
||||
downPressureFormController: currentState.downPressureFormController,
|
||||
allergiesFormController: currentState.allergiesFormController,
|
||||
pillsFormController: currentState.pillsFormController,
|
||||
favoriteFormController: currentState.favoriteFormController,
|
||||
@@ -181,8 +177,7 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
waistCircumferenceController: TextEditingController(),
|
||||
hipCircumferenceController: TextEditingController(),
|
||||
hypoFormController: data['userDetails']['has_hypo'].toString(),
|
||||
hyperFormController:
|
||||
data['userDetails']['has_hyper'].toString(),
|
||||
hyperFormController: data['userDetails']['has_hyper'].toString(),
|
||||
chestCircumferenceFormController: TextEditingController(
|
||||
text: data['userDetails']['chest_circumference']?.toString(),
|
||||
),
|
||||
@@ -201,12 +196,9 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
firstNameFormController: TextEditingController(
|
||||
text: data['userDetails']['first_name'],
|
||||
),
|
||||
lastNameFormController: TextEditingController(
|
||||
text: data['userDetails']['last_name']),
|
||||
countryFormController:
|
||||
TextEditingController(text: data['userDetails']['country']),
|
||||
cityFormController:
|
||||
TextEditingController(text: data['userDetails']['city']),
|
||||
lastNameFormController: TextEditingController(text: data['userDetails']['last_name']),
|
||||
countryFormController: TextEditingController(text: data['userDetails']['country']),
|
||||
cityFormController: TextEditingController(text: data['userDetails']['city']),
|
||||
heightFormController: TextEditingController(
|
||||
text: data['userDetails']['height']?.toString(),
|
||||
),
|
||||
@@ -234,8 +226,7 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
additionalFormController: TextEditingController(
|
||||
text: data['userDetails']['additional_info'],
|
||||
),
|
||||
dateFormController: TextEditingController(
|
||||
text: data['userDetails']['birthdate']),
|
||||
dateFormController: TextEditingController(text: data['userDetails']['birthdate']),
|
||||
selectedCity: data['userDetails']['city'],
|
||||
selectedCountry: data['userDetails']['country'],
|
||||
selectedActivity: determineActivityLevel(
|
||||
@@ -282,6 +273,7 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
var currentState = state as MyProfileLoadedState;
|
||||
|
||||
await uploadImageToServer(event.image.path, currentState.token);
|
||||
this.add(MyProfileInitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,27 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
SizedBox(height: 15.v),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 24.h,
|
||||
vertical: 12.v,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.5),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 5,
|
||||
offset: Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _buildCarousel(context, state),
|
||||
),
|
||||
SizedBox(height: 15.v),
|
||||
if (!state.plans!.isEmpty)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 24.h,
|
||||
vertical: 12.v,
|
||||
@@ -112,32 +133,13 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _buildCarousel(context, state),),
|
||||
SizedBox(height: 15.v),
|
||||
if (!state.plans!.isEmpty)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 24.h,
|
||||
vertical: 12.v,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.5),
|
||||
spreadRadius: 2,
|
||||
blurRadius: 5,
|
||||
offset: Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _buildPlans(
|
||||
context,
|
||||
state.plans?.map((plan) => plan['name']).toList(),
|
||||
state.plans?.map((plan) => plan['image']).toList(),
|
||||
state.plans?.map((plan) => plan['state']).toList(),
|
||||
),),
|
||||
child: _buildPlans(
|
||||
context,
|
||||
state.plans?.map((plan) => plan['name']).toList(),
|
||||
state.plans?.map((plan) => plan['image']).toList(),
|
||||
state.plans?.map((plan) => plan['state']).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
],
|
||||
),
|
||||
@@ -176,11 +178,9 @@ class MyProfileScreen extends StatelessWidget {
|
||||
|
||||
addImage(BuildContext context) async {
|
||||
final picker = ImagePicker();
|
||||
List<XFile>? images = await picker.pickMultiImage();
|
||||
if (images.isNotEmpty) {
|
||||
for (var image in images) {
|
||||
context.read<MyProfileBloc>().add(UploadAvatar(image));
|
||||
}
|
||||
XFile? image = await picker.pickImage(source: ImageSource.gallery);
|
||||
if (image != null) {
|
||||
context.read<MyProfileBloc>().add(UploadAvatar(image));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,8 +199,9 @@ class MyProfileScreen extends StatelessWidget {
|
||||
switch (chartType) {
|
||||
case 1: // График веса
|
||||
return GestureDetector(
|
||||
onTap: () => _editWeight(context, state),
|
||||
child: Column(children: [
|
||||
onTap: () => _editWeight(context, state),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"weight_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
@@ -213,26 +214,34 @@ class MyProfileScreen extends StatelessWidget {
|
||||
state.chartPoints?.values.map<int>((e) => e['weight']).toList().map((i) => i.toDouble()).toList() ?? [0.0, 0.0, 0.0, 0.0],
|
||||
state.chartDates,
|
||||
),
|
||||
],),);
|
||||
case 2: // График ИМТ
|
||||
return Column(children: [
|
||||
Text(
|
||||
"bodymass_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: appTheme.black900,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 50.v),
|
||||
_buildChart(
|
||||
);
|
||||
case 2: // График ИМТ
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
"bodymass_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: appTheme.black900,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 50.v),
|
||||
_buildChart(
|
||||
context,
|
||||
_bodyMassIndex(state.chartPoints?.values.map<int>((e) => e['weight']).toList().map((i) => i.toDouble()).toList() ?? [0.0, 0.0, 0.0, 0.0],
|
||||
state.userDetails?['height'].toInt() ?? 160,),
|
||||
state.chartDates,),
|
||||
],);
|
||||
_bodyMassIndex(
|
||||
state.chartPoints?.values.map<int>((e) => e['weight']).toList().map((i) => i.toDouble()).toList() ?? [0.0, 0.0, 0.0, 0.0],
|
||||
state.userDetails?['height'].toInt() ?? 160,
|
||||
),
|
||||
state.chartDates,
|
||||
),
|
||||
],
|
||||
);
|
||||
case 3: //График обхватов
|
||||
return GestureDetector(
|
||||
onTap: () => _editCircumference(context, state),
|
||||
child: Column(children: [
|
||||
onTap: () => _editCircumference(context, state),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"circumferences_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
@@ -242,7 +251,9 @@ class MyProfileScreen extends StatelessWidget {
|
||||
SizedBox(height: 30.v),
|
||||
_buildCircumferenceChart(context, state.circumferences, state.chartDates),
|
||||
_buildChartLegend(),
|
||||
],),);
|
||||
],
|
||||
),
|
||||
);
|
||||
default:
|
||||
return Text('text', style: TextStyle(fontSize: 16.0));
|
||||
}
|
||||
@@ -636,79 +647,108 @@ class MyProfileScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_buildPlans(BuildContext context, List<dynamic>? plans, List<dynamic>? imagePaths, List<dynamic>? states) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: 7.h),
|
||||
child: Column(children: [
|
||||
padding: EdgeInsets.only(left: 7.h),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 15.h),
|
||||
child: Text("plans_complete".tr, style: CustomTextStyles.titleMediumBlack.copyWith(color: appTheme.black900)),),
|
||||
padding: EdgeInsets.only(left: 15.h),
|
||||
child: Text("plans_complete".tr, style: CustomTextStyles.titleMediumBlack.copyWith(color: appTheme.black900)),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
Container(
|
||||
decoration: AppDecoration.outlineBlueGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
decoration: AppDecoration.outlineBlueGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 105.v,
|
||||
width: 343.h,
|
||||
child: Stack(alignment: Alignment.bottomCenter, children: [
|
||||
height: 105.v,
|
||||
width: 343.h,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ListView.builder(
|
||||
itemCount: plans?.length ?? 0,
|
||||
itemBuilder: (context, i) {
|
||||
String state = states?[i];
|
||||
var boxColor = appTheme.greenA700;
|
||||
switch (states?[i]) {
|
||||
case 'active':
|
||||
boxColor = appTheme.greenA700;
|
||||
break;
|
||||
case 'archived': // График ИМТ
|
||||
boxColor = appTheme.gray400;
|
||||
break;
|
||||
case 'draft':
|
||||
boxColor = appTheme.deepOrange900;
|
||||
break;
|
||||
case 'in_progress': //График обхватов
|
||||
boxColor = appTheme.lightGreen300;
|
||||
break;
|
||||
}
|
||||
return SizedBox(
|
||||
height: 40.v,
|
||||
width: 343.h,
|
||||
child: Stack(alignment: Alignment.bottomRight, children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 11.v),
|
||||
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 4.v),
|
||||
decoration: AppDecoration.fillGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 1.v),
|
||||
child: Text(plans![i], style: CustomTextStyles.titleSmallBluegray800Bold),),
|
||||
Container(
|
||||
height: 19.v,
|
||||
width: 100.h,
|
||||
decoration: BoxDecoration(color: boxColor, borderRadius: BorderRadius.circular(5.h)),),
|
||||
],),),),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 12.h),
|
||||
child: Image.network(
|
||||
dotenv.env['STORAGE_URL']! + imagePaths?[i],
|
||||
height: 25.adaptSize,
|
||||
width: 25.adaptSize,
|
||||
),),),
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: 70.h,
|
||||
margin: EdgeInsets.only(bottom: 14.h, right: 22.h),
|
||||
child: Text("$state".tr, maxLines: 3, overflow: TextOverflow.ellipsis, style: theme.textTheme.titleSmall),),),
|
||||
],),);
|
||||
},),),
|
||||
],),),
|
||||
],),),
|
||||
],),);
|
||||
alignment: Alignment.topCenter,
|
||||
child: ListView.builder(
|
||||
itemCount: plans?.length ?? 0,
|
||||
itemBuilder: (context, i) {
|
||||
String state = states?[i];
|
||||
var boxColor = appTheme.greenA700;
|
||||
switch (states?[i]) {
|
||||
case 'active':
|
||||
boxColor = appTheme.greenA700;
|
||||
break;
|
||||
case 'archived': // График ИМТ
|
||||
boxColor = appTheme.gray400;
|
||||
break;
|
||||
case 'draft':
|
||||
boxColor = appTheme.deepOrange900;
|
||||
break;
|
||||
case 'in_progress': //График обхватов
|
||||
boxColor = appTheme.lightGreen300;
|
||||
break;
|
||||
}
|
||||
return SizedBox(
|
||||
height: 40.v,
|
||||
width: 343.h,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 11.v),
|
||||
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 4.v),
|
||||
decoration: AppDecoration.fillGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 1.v),
|
||||
child: Text(plans![i], style: CustomTextStyles.titleSmallBluegray800Bold),
|
||||
),
|
||||
Container(
|
||||
height: 19.v,
|
||||
width: 100.h,
|
||||
decoration: BoxDecoration(color: boxColor, borderRadius: BorderRadius.circular(5.h)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 12.h),
|
||||
child: Image.network(
|
||||
dotenv.env['STORAGE_URL']! + imagePaths?[i],
|
||||
height: 25.adaptSize,
|
||||
width: 25.adaptSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: 70.h,
|
||||
margin: EdgeInsets.only(bottom: 14.h, right: 22.h),
|
||||
child: Text("$state".tr, maxLines: 3, overflow: TextOverflow.ellipsis, style: theme.textTheme.titleSmall),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<double> _bodyMassIndex(List<double> weightPoints, int height) {
|
||||
@@ -729,48 +769,49 @@ class MyProfileScreen extends StatelessWidget {
|
||||
title: Center(child: Text("Добавить замер")),
|
||||
|
||||
content: SizedBox(
|
||||
width: 200, // Ширина диалогового окна
|
||||
height: 300, // Высота диалогового окна
|
||||
child: ListView(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 5.v),
|
||||
child: Text("chest_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
CustomTextFormField(
|
||||
controller: state.chestCircumferenceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.v),
|
||||
child: Text("waist_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
CustomTextFormField(
|
||||
controller: state.waistCircumferenceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.v),
|
||||
child: Text("hip_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
CustomTextFormField(
|
||||
controller: state.hipCircumferenceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
],
|
||||
),),
|
||||
width: 200, // Ширина диалогового окна
|
||||
height: 300, // Высота диалогового окна
|
||||
child: ListView(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 5.v),
|
||||
child: Text("chest_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
CustomTextFormField(
|
||||
controller: state.chestCircumferenceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.v),
|
||||
child: Text("waist_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
CustomTextFormField(
|
||||
controller: state.waistCircumferenceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.v),
|
||||
child: Text("hip_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
CustomTextFormField(
|
||||
controller: state.hipCircumferenceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: onTapOk(context),
|
||||
@@ -778,10 +819,12 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
TextButton(
|
||||
onPressed: sendEditData(state, context),
|
||||
child: Text("Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),),
|
||||
child: Text(
|
||||
"Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.white,
|
||||
@@ -824,6 +867,7 @@ class MyProfileScreen extends StatelessWidget {
|
||||
// Обработка ошибок при отправке запроса
|
||||
print("Ошибка при отправке запроса: $e");
|
||||
}
|
||||
Navigator.pop(context);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -859,10 +903,12 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => saveWeight(state, context),
|
||||
child: Text("Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),),
|
||||
child: Text(
|
||||
"Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.white,
|
||||
|
||||
@@ -37,7 +37,7 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
}
|
||||
final String? recipeID = state.recipeModelObj?.recipeID;
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/show/$recipeID'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/show/$recipeID'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -47,7 +47,8 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
if (data is Map<String, dynamic>) {
|
||||
if (state is RecipeEditLoadedState) {
|
||||
var currentState = state as RecipeEditLoadedState;
|
||||
emit(currentState.copyWith(
|
||||
emit(
|
||||
currentState.copyWith(
|
||||
recipeModelObj: currentState.recipeModelObj,
|
||||
title: currentState.title,
|
||||
token: currentState.token,
|
||||
@@ -56,7 +57,9 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
video_url: currentState.video_url,
|
||||
steps: currentState.steps,
|
||||
stepDescriptions: currentState.stepDescriptions,
|
||||
tags: currentState.tags,),);
|
||||
tags: currentState.tags,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final Map<String, dynamic> defaultStep = {
|
||||
'description': '',
|
||||
@@ -75,17 +78,19 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
}
|
||||
}
|
||||
|
||||
emit(RecipeEditLoadedState(
|
||||
token: token,
|
||||
recipe: data,
|
||||
title: TextEditingController(text: data['title']),
|
||||
description: TextEditingController(text: data['description']),
|
||||
video_url: TextEditingController(text: data['video_url']),
|
||||
tagsController: TextEditingController(),
|
||||
tags: await _fetchTags(data['id']),
|
||||
stepDescriptions: stepDescriptions,
|
||||
steps: steps,
|
||||
),);
|
||||
emit(
|
||||
RecipeEditLoadedState(
|
||||
token: token,
|
||||
recipe: data,
|
||||
title: TextEditingController(text: data['title']),
|
||||
description: TextEditingController(text: data['description']),
|
||||
video_url: TextEditingController(text: data['video_url']),
|
||||
tagsController: TextEditingController(),
|
||||
tags: await _fetchTags(data['id']),
|
||||
stepDescriptions: stepDescriptions,
|
||||
steps: steps,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Один или несколько ключевых полей отсутствуют, обрабатываем ошибку
|
||||
@@ -195,7 +200,7 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
}
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/getTags/$id'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/getTags/$id'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -213,7 +218,8 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
}
|
||||
if (state is RecipeEditLoadedState) {
|
||||
var currentState = state as RecipeEditLoadedState;
|
||||
emit(currentState.copyWith(
|
||||
emit(
|
||||
currentState.copyWith(
|
||||
recipeModelObj: currentState.recipeModelObj,
|
||||
recipe: currentState.recipe,
|
||||
title: currentState.title,
|
||||
@@ -222,7 +228,9 @@ class RecipeEditBloc extends Bloc<RecipeEditEvent, RecipeEditState> {
|
||||
video_url: currentState.video_url,
|
||||
steps: currentState.steps,
|
||||
stepDescriptions: currentState.stepDescriptions,
|
||||
tags: currentState.tags,),);
|
||||
tags: currentState.tags,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/app_router.dart';
|
||||
import 'package:eatvio_app/locator_service.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '/core/app_export.dart';
|
||||
@@ -31,27 +33,29 @@ class RecipeSelectBloc extends Bloc<RecipeSelectEvent, RecipeSelectState> {
|
||||
if (token == null) {
|
||||
AppRouter.navigatorKey.currentContext?.goNamed('authScreen');
|
||||
}
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/index'),
|
||||
);
|
||||
final response = await sl<Dio>().get(dotenv.env['SERVER_ROOT']! + '/recipes/index');
|
||||
print('Got response');
|
||||
if (response.statusCode == 200) {
|
||||
print('Got 200');
|
||||
final data = jsonDecode(response.body);
|
||||
final data = response.data['data'];
|
||||
if (data is List<dynamic>) {
|
||||
print('Got List');
|
||||
if (state is RecipeSelectLoadedState) {
|
||||
print('Got loaded');
|
||||
var currentState = state as RecipeSelectLoadedState;
|
||||
emit((currentState).copyWith(
|
||||
posts: data,
|
||||
myProfileModelObj: currentState.myProfileModelObj,
|
||||
),);
|
||||
emit(
|
||||
(currentState).copyWith(
|
||||
posts: data,
|
||||
myProfileModelObj: currentState.myProfileModelObj,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
print('Got unloaded');
|
||||
emit(RecipeSelectLoadedState(
|
||||
posts: data,
|
||||
),);
|
||||
emit(
|
||||
RecipeSelectLoadedState(
|
||||
posts: data,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Один или несколько ключевых полей отсутствуют, обрабатываем ошибку
|
||||
|
||||
@@ -12,14 +12,12 @@ class RecipeSelectState extends Equatable {
|
||||
}
|
||||
|
||||
class RecipeSelectInitialState extends RecipeSelectState {
|
||||
RecipeSelectInitialState({required RecipeSelectModel myProfileModelObj})
|
||||
: super(myProfileModelObj: myProfileModelObj);
|
||||
RecipeSelectInitialState({required RecipeSelectModel myProfileModelObj}) : super(myProfileModelObj: myProfileModelObj);
|
||||
}
|
||||
|
||||
/// Represents the state of RecipeSelect in the application.
|
||||
class RecipeSelectLoadedState extends RecipeSelectState {
|
||||
RecipeSelectLoadedState({this.myProfileModelObj, this.posts})
|
||||
: super(myProfileModelObj: null);
|
||||
RecipeSelectLoadedState({this.myProfileModelObj, this.posts}) : super(myProfileModelObj: null);
|
||||
|
||||
RecipeSelectModel? myProfileModelObj;
|
||||
List<dynamic>? posts;
|
||||
|
||||
@@ -112,6 +112,7 @@ class RecipeSelectScreen extends StatelessWidget {
|
||||
|
||||
_buildRecipeList(BuildContext context, RecipeSelectLoadedState state) {
|
||||
return ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true, // Add this line
|
||||
itemCount: state.posts?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
}
|
||||
final String? recipeID = state.recipeModelObj?.recipeID;
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/show/$recipeID'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/show/$recipeID'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -47,23 +47,29 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
if (data is Map<String, dynamic>) {
|
||||
if (state is RecipeLoadedState) {
|
||||
var currentState = state as RecipeLoadedState;
|
||||
emit(currentState.copyWith(
|
||||
emit(
|
||||
currentState.copyWith(
|
||||
recipeModelObj: currentState.recipeModelObj,
|
||||
recipe: currentState.recipe,
|
||||
token: currentState.token,
|
||||
commentController: currentState.commentController,
|
||||
comments: currentState.comments,
|
||||
steps: currentState.steps,
|
||||
author: currentState.author,),);
|
||||
author: currentState.author,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(RecipeLoadedState(
|
||||
emit(
|
||||
RecipeLoadedState(
|
||||
token: token,
|
||||
recipe: data,
|
||||
steps: data['steps'],
|
||||
author: await _fetchAuthor(data['id']),
|
||||
comments: fillCommentList(await _fetchComments(data['id'])),
|
||||
tags: await _fetchTags(data['id']),
|
||||
commentController: TextEditingController(),),);
|
||||
commentController: TextEditingController(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Один или несколько ключевых полей отсутствуют, обрабатываем ошибку
|
||||
@@ -87,7 +93,7 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
}
|
||||
final int id = event.id;
|
||||
final response = await http.post(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/delete/$id'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/delete/$id'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -125,7 +131,7 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
}
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/getAuthor/$id'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/getAuthor/$id'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -141,7 +147,7 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
AppRouter.navigatorKey.currentContext?.goNamed('authScreen');
|
||||
}
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/getComments/$id'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/getComments/$id'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -159,7 +165,7 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
}
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipe/getTags/$id'),
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/recipes/getTags/$id'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
@@ -171,30 +177,35 @@ class RecipeBloc extends Bloc<RecipeEvent, RecipeState> {
|
||||
List<CommentModel> fillCommentList(List<dynamic> comments) {
|
||||
List<CommentModel> list = [];
|
||||
for (int i = 0; i < comments.length; i++) {
|
||||
list.add(CommentModel(
|
||||
list.add(
|
||||
CommentModel(
|
||||
id: comments[i]['id'].toString(),
|
||||
userImage: comments[i]['profile_photo_path'],
|
||||
username: comments[i]['name'],
|
||||
dateText: DateFormat('dd.MM').format(DateTime.parse(comments[i]['updated_at'])),
|
||||
greetingText: comments[i]['body'],),);
|
||||
greetingText: comments[i]['body'],
|
||||
),
|
||||
);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
Future<http.Response> _sendCommentData(String? token, String body, int id) async {
|
||||
String url = dotenv.env['SERVER_ROOT']! + '/recipe/createComment/$id';
|
||||
String url = dotenv.env['SERVER_ROOT']! + '/recipes/createComment/$id';
|
||||
final Map<String, dynamic> credentials = {
|
||||
'id': id,
|
||||
'body': body,
|
||||
};
|
||||
|
||||
var response = await http.post(Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,);
|
||||
var response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -20,45 +20,59 @@ class AdditionalInformationScreen extends StatelessWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<AdditionalInformationBloc>(
|
||||
create: (context) =>
|
||||
AdditionalInformationBloc(AdditionalInformationState(additionalInformationModelObj: AdditionalInformationModel(userRegistrationSheet: sheet)))
|
||||
..add(AdditionalInformationInitialEvent()),
|
||||
child: AdditionalInformationScreen(),);
|
||||
create: (context) =>
|
||||
AdditionalInformationBloc(AdditionalInformationState(additionalInformationModelObj: AdditionalInformationModel(userRegistrationSheet: sheet)))
|
||||
..add(AdditionalInformationInitialEvent()),
|
||||
child: AdditionalInformationScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return 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: 1, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
SizedBox(height: 20.v),
|
||||
SizedBox(height: 73.v),
|
||||
_buildTextFormField(context),
|
||||
Spacer(),
|
||||
BlocBuilder<AdditionalInformationBloc, AdditionalInformationState>(builder: (context, state) {
|
||||
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: (14 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.v),
|
||||
SizedBox(height: 73.v),
|
||||
_buildTextFormField(context),
|
||||
Spacer(),
|
||||
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: onTapFinish(state, context),);
|
||||
},),
|
||||
],),),);
|
||||
text: "finish".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapFinish(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapFinish(AdditionalInformationState state, BuildContext context) {
|
||||
@@ -66,8 +80,12 @@ class AdditionalInformationScreen extends StatelessWidget {
|
||||
UserRegistrationSheet sheet = state.additionalInformationModelObj!.userRegistrationSheet;
|
||||
sheet.additionalInfo = state.editTextController!.text;
|
||||
|
||||
final response = await http.post(Uri.parse(dotenv.env['SERVER_ROOT']! + '/register'),
|
||||
headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, body: jsonEncode(sheet.toJson()), encoding: utf8,);
|
||||
final response = await http.post(
|
||||
Uri.parse(dotenv.env['SERVER_ROOT']! + '/register'),
|
||||
headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
|
||||
body: jsonEncode(sheet.toJson()),
|
||||
encoding: utf8,
|
||||
);
|
||||
|
||||
var res = await jsonDecode(response.body);
|
||||
if (response.statusCode == 200) {
|
||||
@@ -84,11 +102,12 @@ class AdditionalInformationScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 31.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
onTapBack(BuildContext context) {
|
||||
@@ -100,29 +119,45 @@ class AdditionalInformationScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_buildTextFormField(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 315.v,
|
||||
width: 343.h,
|
||||
child: Stack(alignment: Alignment.center, children: [
|
||||
height: 315.v,
|
||||
width: 343.h,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 294.h,
|
||||
margin: EdgeInsets.only(left: 24.h, right: 23.h),
|
||||
child: Text("enter_additional_information".tr,
|
||||
maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: CustomTextStyles.titleMediumSegoeUI,),),
|
||||
width: 294.h,
|
||||
margin: EdgeInsets.only(left: 24.h, right: 23.h),
|
||||
child: Text(
|
||||
"enter_additional_information".tr,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: CustomTextStyles.titleMediumSegoeUI,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.v),
|
||||
BlocSelector<AdditionalInformationBloc, AdditionalInformationState, TextEditingController?>(
|
||||
selector: (state) => state.editTextController,
|
||||
builder: (context, editTextController) {
|
||||
return CustomTextFormField(
|
||||
controller: editTextController,
|
||||
hintText: "У меня крепкое здоровье, но последнее время часто утомляюсь, однако, это мне не мешает радоваться жизни",
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 8,);
|
||||
},),
|
||||
],),),
|
||||
],),);
|
||||
selector: (state) => state.editTextController,
|
||||
builder: (context, editTextController) {
|
||||
return CustomTextFormField(
|
||||
controller: editTextController,
|
||||
hintText: "У меня крепкое здоровье, но последнее время часто утомляюсь, однако, это мне не мешает радоваться жизни",
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigates to the previous screen.
|
||||
@@ -134,12 +169,13 @@ class AdditionalInformationScreen extends StatelessWidget {
|
||||
/// The dialog box contains a title and a message with the `Теперь вы можете пользоваться полным функционалом приложения`
|
||||
showErrorMessage(BuildContext context, String text) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('Ошибка'),
|
||||
content: Text(text),
|
||||
actions: [TextButton(onPressed: onTapOk(context), child: const Text('Ok'))],
|
||||
),);
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('Ошибка'),
|
||||
content: Text(text),
|
||||
actions: [TextButton(onPressed: onTapOk(context), child: const Text('Ok'))],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapOk(BuildContext context) {
|
||||
|
||||
@@ -16,8 +16,9 @@ class AllergiesScreen extends StatefulWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<AllergiesBloc>(
|
||||
create: (context) => AllergiesBloc(AllergiesState(allergiesModelObj: AllergiesModel(userRegistrationSheet: sheet)))..add(AllergiesInitialEvent()),
|
||||
child: AllergiesScreen(),);
|
||||
create: (context) => AllergiesBloc(AllergiesState(allergiesModelObj: AllergiesModel(userRegistrationSheet: sheet)))..add(AllergiesInitialEvent()),
|
||||
child: AllergiesScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -28,43 +29,58 @@ class _AllergiesScreenState extends State<AllergiesScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return 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.76, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
SizedBox(height: 22.v),
|
||||
Text("allergies_presence".tr, style: theme.textTheme.headlineSmall),
|
||||
Spacer(flex: 36),
|
||||
_buildTextFormField(context),
|
||||
Spacer(flex: 54),
|
||||
BlocBuilder<AllergiesBloc, AllergiesState>(builder: (context, state) {
|
||||
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: (10 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 22.v),
|
||||
Text("allergies_presence".tr, style: theme.textTheme.headlineSmall),
|
||||
Spacer(flex: 36),
|
||||
_buildTextFormField(context),
|
||||
Spacer(flex: 54),
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
BlocBuilder<AllergiesBloc, AllergiesState>(builder: (context, state) {
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<AllergiesBloc, AllergiesState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: onTapSkip(state, context),
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
},),
|
||||
],),),);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapSkip(AllergiesState state, BuildContext context) {
|
||||
@@ -85,11 +101,12 @@ class _AllergiesScreenState extends State<AllergiesScreen> {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 31.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
onTapBack(BuildContext context) {
|
||||
@@ -100,16 +117,23 @@ class _AllergiesScreenState extends State<AllergiesScreen> {
|
||||
|
||||
/// Section Widget
|
||||
_buildTextFormField(BuildContext context) {
|
||||
return Column(children: [
|
||||
Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<AllergiesBloc, AllergiesState, TextEditingController?>(
|
||||
return Column(
|
||||
children: [
|
||||
Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<AllergiesBloc, AllergiesState, TextEditingController?>(
|
||||
selector: (state) => state.enterInformationController,
|
||||
builder: (context, enterInformationController) {
|
||||
return CustomTextFormField(
|
||||
controller: enterInformationController, hintText: "enter_information".tr, textInputAction: TextInputAction.done, maxLines: 8,);
|
||||
},),
|
||||
],);
|
||||
controller: enterInformationController,
|
||||
hintText: "enter_information".tr,
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigates to the previous screen.
|
||||
|
||||
@@ -19,9 +19,10 @@ class BloodPressureScreen extends StatefulWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<BloodPressureBloc>(
|
||||
create: (context) =>
|
||||
BloodPressureBloc(BloodPressureState(bloodPressureModelObj: BloodPressureModel(userRegistrationSheet: sheet)))..add(BloodPressureInitialEvent()),
|
||||
child: BloodPressureScreen(),);
|
||||
create: (context) =>
|
||||
BloodPressureBloc(BloodPressureState(bloodPressureModelObj: BloodPressureModel(userRegistrationSheet: sheet)))..add(BloodPressureInitialEvent()),
|
||||
child: BloodPressureScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -33,115 +34,146 @@ class _BloodPressureScreenState extends State<BloodPressureScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: _buildAppBar(context),
|
||||
body: Container(
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 9.v),
|
||||
child: Column(children: [
|
||||
SizedBox(height: 7.v),
|
||||
Container(
|
||||
height: 16.v,
|
||||
width: 343.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h),
|
||||
// Apply padding directly to the Container
|
||||
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.62,
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: _buildAppBar(context),
|
||||
body: Container(
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 9.v),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 7.v),
|
||||
Container(
|
||||
height: 16.v,
|
||||
width: 343.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h),
|
||||
// Apply padding directly to the Container
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary,
|
||||
width: 1.h,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 21.v),
|
||||
SizedBox(
|
||||
width: 224.h,
|
||||
child: Text("your_blood_pressure".tr,
|
||||
maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: theme.textTheme.headlineSmall,),),
|
||||
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),
|
||||
SizedBox(height: 2.v),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h),
|
||||
child: BlocSelector<BloodPressureBloc, BloodPressureState, BloodPressureModel?>(
|
||||
selector: (state) => state.bloodPressureModelObj,
|
||||
builder: (context, bloodPressureModelObj) {
|
||||
return CustomDropDown(
|
||||
icon: Container(
|
||||
margin: EdgeInsets.fromLTRB(30.h, 11.v, 13.h, 11.v),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(1.h)),
|
||||
child: CustomImageView(imagePath: ImageConstant.imgFavorite, height: 12.adaptSize, width: 12.adaptSize),),
|
||||
hintText: "Не выбрано".tr,
|
||||
items: bloodPressureModelObj?.dropdownItemList ?? [],
|
||||
onChanged: onChangeHyper(context),);
|
||||
},),),
|
||||
SizedBox(height: 22.v),
|
||||
Text("do_you_have_hypertension_tendency".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 2.v),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h),
|
||||
child: BlocSelector<BloodPressureBloc, BloodPressureState, BloodPressureModel?>(
|
||||
selector: (state) => state.bloodPressureModelObj,
|
||||
builder: (context, bloodPressureModelObj) {
|
||||
return CustomDropDown(
|
||||
icon: Container(
|
||||
margin: EdgeInsets.fromLTRB(30.h, 11.v, 13.h, 11.v),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(1.h)),
|
||||
child: CustomImageView(imagePath: ImageConstant.imgFavorite, height: 12.adaptSize, width: 12.adaptSize),),
|
||||
hintText: "Не выбрано".tr,
|
||||
items: bloodPressureModelObj?.dropdownItemList ?? [],
|
||||
onChanged: onChangeHypo(context),);
|
||||
},),),
|
||||
Spacer(),
|
||||
BlocBuilder<BloodPressureBloc, BloodPressureState>(builder: (context, state) {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
child: LinearProgressIndicator(
|
||||
value: (9 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 21.v),
|
||||
SizedBox(
|
||||
width: 224.h,
|
||||
child: Text(
|
||||
"your_blood_pressure".tr,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
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),
|
||||
SizedBox(height: 2.v),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h),
|
||||
child: BlocSelector<BloodPressureBloc, BloodPressureState, BloodPressureModel?>(
|
||||
selector: (state) => state.bloodPressureModelObj,
|
||||
builder: (context, bloodPressureModelObj) {
|
||||
return CustomDropDown(
|
||||
icon: Container(
|
||||
margin: EdgeInsets.fromLTRB(30.h, 11.v, 13.h, 11.v),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(1.h)),
|
||||
child: CustomImageView(imagePath: ImageConstant.imgFavorite, height: 12.adaptSize, width: 12.adaptSize),
|
||||
),
|
||||
hintText: "Не выбрано".tr,
|
||||
items: bloodPressureModelObj?.dropdownItemList ?? [],
|
||||
onChanged: onChangeHyper(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 22.v),
|
||||
Text("do_you_have_hypertension_tendency".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 2.v),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h),
|
||||
child: BlocSelector<BloodPressureBloc, BloodPressureState, BloodPressureModel?>(
|
||||
selector: (state) => state.bloodPressureModelObj,
|
||||
builder: (context, bloodPressureModelObj) {
|
||||
return CustomDropDown(
|
||||
icon: Container(
|
||||
margin: EdgeInsets.fromLTRB(30.h, 11.v, 13.h, 11.v),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(1.h)),
|
||||
child: CustomImageView(imagePath: ImageConstant.imgFavorite, height: 12.adaptSize, width: 12.adaptSize),
|
||||
),
|
||||
hintText: "Не выбрано".tr,
|
||||
items: bloodPressureModelObj?.dropdownItemList ?? [],
|
||||
onChanged: onChangeHypo(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
BlocBuilder<BloodPressureBloc, BloodPressureState>(builder: (context, state) {
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<BloodPressureBloc, BloodPressureState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: onTapSkip(state, context),
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
},),
|
||||
],),),);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapSkip(BloodPressureState state, BuildContext context) {
|
||||
@@ -158,7 +190,7 @@ class _BloodPressureScreenState extends State<BloodPressureScreen> {
|
||||
UserRegistrationSheet sheet = state.bloodPressureModelObj!.userRegistrationSheet;
|
||||
sheet.bloodPressureUp = state.upPressureController!.text;
|
||||
sheet.bloodPressureDown = state.downPressureController!.text;
|
||||
AppRouter.navigatorKey.currentContext?.goNamed('favoriteSportsScreen', extra: sheet);
|
||||
AppRouter.navigatorKey.currentContext?.goNamed('allergiesScreen', extra: sheet);
|
||||
} else {
|
||||
String errorMessage = '';
|
||||
|
||||
@@ -204,11 +236,12 @@ class _BloodPressureScreenState extends State<BloodPressureScreen> {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
|
||||
@@ -28,62 +28,84 @@ class BodyCircumferencesScreen extends StatelessWidget {
|
||||
final digitsOnly = FilteringTextInputFormatter.digitsOnly;
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
return 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.40, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
SizedBox(height: 39.v),
|
||||
Text("initial_measurements".tr, style: theme.textTheme.headlineSmall),
|
||||
SizedBox(height: 93.v),
|
||||
Column(children: [
|
||||
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: (6 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 39.v),
|
||||
Text("initial_measurements".tr, style: theme.textTheme.headlineSmall),
|
||||
SizedBox(height: 93.v),
|
||||
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.waistCircumferenceController,
|
||||
builder: (context, waistCircumferenceController) {
|
||||
return CustomTextFormField(inputFormatters: [digitsOnly], controller: waistCircumferenceController, hintText: "60".tr);
|
||||
},),
|
||||
SizedBox(height: 21.v),
|
||||
Text("hip_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<BodyCircumferencesBloc, BodyCircumferencesState, TextEditingController?>(
|
||||
selector: (state) => state.hipCircumferenceController,
|
||||
builder: (context, hipCircumferenceController) {
|
||||
return CustomTextFormField(
|
||||
inputFormatters: [digitsOnly], controller: hipCircumferenceController, hintText: "90".tr, textInputAction: TextInputAction.done,);
|
||||
},),
|
||||
Spacer(),
|
||||
BlocBuilder<BodyCircumferencesBloc, BodyCircumferencesState>(builder: (context, state) {
|
||||
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.waistCircumferenceController,
|
||||
builder: (context, waistCircumferenceController) {
|
||||
return CustomTextFormField(inputFormatters: [digitsOnly], controller: waistCircumferenceController, hintText: "60".tr);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 21.v),
|
||||
Text("hip_circumference".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<BodyCircumferencesBloc, BodyCircumferencesState, TextEditingController?>(
|
||||
selector: (state) => state.hipCircumferenceController,
|
||||
builder: (context, hipCircumferenceController) {
|
||||
return CustomTextFormField(
|
||||
inputFormatters: [digitsOnly],
|
||||
controller: hipCircumferenceController,
|
||||
hintText: "90".tr,
|
||||
textInputAction: TextInputAction.done,
|
||||
);
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
],),),);
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapContinue(BodyCircumferencesState state, BuildContext context) {
|
||||
@@ -129,11 +151,12 @@ class BodyCircumferencesScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
|
||||
@@ -1144,45 +1144,57 @@ class CityOfLivingScreen extends StatelessWidget {
|
||||
"Ясный",
|
||||
"Яхрома",
|
||||
];
|
||||
|
||||
return Scaffold(
|
||||
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.32, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
SizedBox(height: 39.v),
|
||||
Text("place_of_living".tr, style: theme.textTheme.headlineSmall),
|
||||
Spacer(flex: 34),
|
||||
Text("country".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<CityOfLivingBloc, CityOfLivingState, CityOfLivingModel?>(
|
||||
selector: (state) => state.cityOfLivingModelObj,
|
||||
builder: (context, cityOfLivingModelObj) {
|
||||
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: "Не выбрано".tr,
|
||||
items: cityOfLivingModelObj?.dropdownItemList ?? [],
|
||||
onChanged: onDropDownChange(context),);
|
||||
},),
|
||||
SizedBox(height: 22.v),
|
||||
Text("Населенный пункт", style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 2.v),
|
||||
BlocBuilder<CityOfLivingBloc, CityOfLivingState>(builder: (context, state) {
|
||||
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: (5 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 39.v),
|
||||
Text("place_of_living".tr, style: theme.textTheme.headlineSmall),
|
||||
Spacer(flex: 34),
|
||||
Text("country".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<CityOfLivingBloc, CityOfLivingState, CityOfLivingModel?>(
|
||||
selector: (state) => state.cityOfLivingModelObj,
|
||||
builder: (context, cityOfLivingModelObj) {
|
||||
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: "Не выбрано".tr,
|
||||
items: cityOfLivingModelObj?.dropdownItemList ?? [],
|
||||
onChanged: onDropDownChange(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 22.v),
|
||||
Text("Населенный пункт", style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 2.v),
|
||||
BlocBuilder<CityOfLivingBloc, CityOfLivingState>(
|
||||
builder: (context, state) {
|
||||
return RawAutocomplete<String>(
|
||||
optionsBuilder: (TextEditingValue textEditingValue) => _options.where((String option) {
|
||||
return option.toLowerCase().startsWith(textEditingValue.text.toLowerCase());
|
||||
@@ -1228,16 +1240,23 @@ class CityOfLivingScreen extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
);
|
||||
},),
|
||||
Spacer(flex: 65),
|
||||
BlocBuilder<CityOfLivingBloc, CityOfLivingState>(builder: (context, state) {
|
||||
},
|
||||
),
|
||||
Spacer(flex: 65),
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
],),),);
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapContinue(CityOfLivingState state, BuildContext context) {
|
||||
@@ -1256,11 +1275,12 @@ class CityOfLivingScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
|
||||
@@ -27,70 +27,87 @@ class CredentialsScreen extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
return 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: 16.v),
|
||||
Text("email".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<CredentialsBloc, CredentialsState, TextEditingController?>(
|
||||
selector: (state) => state.emailController,
|
||||
builder: (context, emailController) {
|
||||
return CustomTextFormField(controller: emailController, textInputAction: TextInputAction.done);
|
||||
},),
|
||||
SizedBox(height: 22.v),
|
||||
Text("username".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<CredentialsBloc, CredentialsState, TextEditingController?>(
|
||||
selector: (state) => state.nameController,
|
||||
builder: (context, nameController) {
|
||||
return CustomTextFormField(controller: nameController, textInputAction: TextInputAction.done);
|
||||
},),
|
||||
SizedBox(height: 19.v),
|
||||
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) {
|
||||
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: (1 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 39.v),
|
||||
Text("user_registration".tr, style: theme.textTheme.headlineSmall),
|
||||
SizedBox(height: 16.v),
|
||||
Text("email".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<CredentialsBloc, CredentialsState, TextEditingController?>(
|
||||
selector: (state) => state.emailController,
|
||||
builder: (context, emailController) {
|
||||
return CustomTextFormField(controller: emailController, textInputAction: TextInputAction.done);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 22.v),
|
||||
Text("username".tr, style: theme.textTheme.bodyLarge),
|
||||
SizedBox(height: 3.v),
|
||||
BlocSelector<CredentialsBloc, CredentialsState, TextEditingController?>(
|
||||
selector: (state) => state.nameController,
|
||||
builder: (context, nameController) {
|
||||
return CustomTextFormField(controller: nameController, textInputAction: TextInputAction.done);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 19.v),
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
],),),);
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapContinue(CredentialsState state, BuildContext context) {
|
||||
|
||||
@@ -36,38 +36,53 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
return BlocBuilder<DateOfBirthBloc, DateOfBirthState>(builder: (context, state) {
|
||||
return Scaffold(
|
||||
return BlocBuilder<DateOfBirthBloc, DateOfBirthState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: _buildAppBar(context),
|
||||
body: Container(
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
|
||||
child: Column(children: [
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
|
||||
child: Column(
|
||||
children: [
|
||||
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),),),),
|
||||
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: (4 / 15).toDouble(),
|
||||
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),
|
||||
BlocBuilder<DateOfBirthBloc, DateOfBirthState>(builder: (context, state) {
|
||||
return NextStepButton(
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
],),),);
|
||||
},);
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onTapContinue(DateOfBirthState state, BuildContext context) {
|
||||
@@ -81,11 +96,12 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
@@ -97,19 +113,27 @@ class _DateOfBirthScreenState extends State<DateOfBirthScreen> {
|
||||
/// Section Widget
|
||||
_buildDateInput(BuildContext context) {
|
||||
return Container(
|
||||
width: 343.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 1.v),
|
||||
decoration: AppDecoration.outlineBlueA.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
|
||||
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
width: 343.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 1.v),
|
||||
decoration: AppDecoration.outlineBlueA.copyWith(borderRadius: BorderRadiusStyle.circleBorder8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CustomImageView(imagePath: ImageConstant.imgFavorite, height: 12.adaptSize, width: 12.adaptSize, radius: BorderRadius.circular(1.h)),
|
||||
SizedBox(height: 6.v),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: GestureDetector(
|
||||
onTap: onTapCalendar(context),
|
||||
child: Text('${selectedDate.day}.${selectedDate.month}.${selectedDate.year}', style: theme.textTheme.titleMedium),),),
|
||||
alignment: Alignment.center,
|
||||
child: GestureDetector(
|
||||
onTap: onTapCalendar(context),
|
||||
child: Text('${selectedDate.day}.${selectedDate.month}.${selectedDate.year}', style: theme.textTheme.titleMedium),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 6.v),
|
||||
],),);
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapCalendar(BuildContext context) {
|
||||
|
||||
@@ -16,9 +16,10 @@ class FavoriteFoodsScreen extends StatefulWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<FavoriteFoodsBloc>(
|
||||
create: (context) =>
|
||||
FavoriteFoodsBloc(FavoriteFoodsState(favoriteFoodsModelObj: FavoriteFoodsModel(userRegistrationSheet: sheet)))..add(FavoriteFoodsInitialEvent()),
|
||||
child: FavoriteFoodsScreen(),);
|
||||
create: (context) =>
|
||||
FavoriteFoodsBloc(FavoriteFoodsState(favoriteFoodsModelObj: FavoriteFoodsModel(userRegistrationSheet: sheet)))..add(FavoriteFoodsInitialEvent()),
|
||||
child: FavoriteFoodsScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -29,49 +30,70 @@ class _FavoriteFoodsScreenState extends State<FavoriteFoodsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return 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.90, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
SizedBox(height: 19.v),
|
||||
Container(
|
||||
width: 327.h,
|
||||
margin: EdgeInsets.only(left: 8.h, right: 7.h),
|
||||
child: Text("favorite_unfavorite_foods".tr,
|
||||
maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: theme.textTheme.headlineSmall,),),
|
||||
SizedBox(height: 13.v),
|
||||
_buildTextFormFieldFav(context),
|
||||
SizedBox(height: 12.v),
|
||||
_buildTextFormFieldUnfav(context),
|
||||
Spacer(),
|
||||
BlocBuilder<FavoriteFoodsBloc, FavoriteFoodsState>(builder: (context, state) {
|
||||
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: (13 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 19.v),
|
||||
Container(
|
||||
width: 327.h,
|
||||
margin: EdgeInsets.only(left: 8.h, right: 7.h),
|
||||
child: Text(
|
||||
"favorite_unfavorite_foods".tr,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 13.v),
|
||||
_buildTextFormFieldFav(context),
|
||||
SizedBox(height: 12.v),
|
||||
_buildTextFormFieldUnfav(context),
|
||||
Spacer(),
|
||||
BlocBuilder<FavoriteFoodsBloc, FavoriteFoodsState>(
|
||||
builder: (context, state) {
|
||||
return NextStepButton(
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 40.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),);
|
||||
},),
|
||||
BlocBuilder<FavoriteFoodsBloc, FavoriteFoodsState>(builder: (context, state) {
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 40.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<FavoriteFoodsBloc, FavoriteFoodsState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: onTapSkip(state, context),
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
},),
|
||||
],),),);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapSkip(FavoriteFoodsState state, BuildContext context) {
|
||||
@@ -93,11 +115,12 @@ class _FavoriteFoodsScreenState extends State<FavoriteFoodsScreen> {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 31.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
@@ -108,29 +131,39 @@ class _FavoriteFoodsScreenState extends State<FavoriteFoodsScreen> {
|
||||
|
||||
/// Section Widget
|
||||
_buildTextFormFieldFav(BuildContext context) {
|
||||
return Column(children: [
|
||||
Text("favorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<FavoriteFoodsBloc, FavoriteFoodsState, TextEditingController?>(
|
||||
return Column(
|
||||
children: [
|
||||
Text("favorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<FavoriteFoodsBloc, FavoriteFoodsState, TextEditingController?>(
|
||||
selector: (state) => state.favoriteFoodsController,
|
||||
builder: (context, favoriteFoodsController) {
|
||||
return CustomTextFormField(controller: favoriteFoodsController, hintText: "enter_information".tr, maxLines: 7);
|
||||
},),
|
||||
],);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Section Widget
|
||||
_buildTextFormFieldUnfav(BuildContext context) {
|
||||
return Column(children: [
|
||||
Text("unfavorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<FavoriteFoodsBloc, FavoriteFoodsState, TextEditingController?>(
|
||||
return Column(
|
||||
children: [
|
||||
Text("unfavorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<FavoriteFoodsBloc, FavoriteFoodsState, TextEditingController?>(
|
||||
selector: (state) => state.unfavoriteFoodsController,
|
||||
builder: (context, unfavoriteFoodsController) {
|
||||
return CustomTextFormField(
|
||||
controller: unfavoriteFoodsController, hintText: "enter_information".tr, textInputAction: TextInputAction.done, maxLines: 7,);
|
||||
},),
|
||||
],);
|
||||
controller: unfavoriteFoodsController,
|
||||
hintText: "enter_information".tr,
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 7,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigates to the previous screen.
|
||||
|
||||
@@ -16,9 +16,10 @@ class FavoriteSportsScreen extends StatefulWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<FavoriteSportsBloc>(
|
||||
create: (context) => FavoriteSportsBloc(FavoriteSportsState(favoriteSportsModelObj: FavoriteSportsModel(userRegistrationSheet: sheet)))
|
||||
..add(FavoriteSportsInitialEvent()),
|
||||
child: FavoriteSportsScreen(),);
|
||||
create: (context) =>
|
||||
FavoriteSportsBloc(FavoriteSportsState(favoriteSportsModelObj: FavoriteSportsModel(userRegistrationSheet: sheet)))..add(FavoriteSportsInitialEvent()),
|
||||
child: FavoriteSportsScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -29,43 +30,59 @@ class _FavoriteSportsScreenState extends State<FavoriteSportsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: _buildAppBar(context),
|
||||
body: Container(
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 5.v),
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
SizedBox(height: 20.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.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),
|
||||
BlocBuilder<FavoriteSportsBloc, FavoriteSportsState>(builder: (context, state) {
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: _buildAppBar(context),
|
||||
body: Container(
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 5.v),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 20.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: (12 / 15).toDouble(),
|
||||
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),
|
||||
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: onTapContinue(state, context),);
|
||||
},),
|
||||
BlocBuilder<FavoriteSportsBloc, FavoriteSportsState>(builder: (context, state) {
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapContinue(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<FavoriteSportsBloc, FavoriteSportsState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: onTapSkip(state, context),
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
},),
|
||||
],),),);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapSkip(FavoriteSportsState state, BuildContext context) {
|
||||
@@ -85,11 +102,12 @@ class _FavoriteSportsScreenState extends State<FavoriteSportsScreen> {
|
||||
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
@@ -100,20 +118,24 @@ class _FavoriteSportsScreenState extends State<FavoriteSportsScreen> {
|
||||
|
||||
/// Section Widget
|
||||
_buildTextFormFieldSection(BuildContext context) {
|
||||
return Column(children: [
|
||||
Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<FavoriteSportsBloc, FavoriteSportsState, TextEditingController?>(
|
||||
return Column(
|
||||
children: [
|
||||
Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<FavoriteSportsBloc, FavoriteSportsState, TextEditingController?>(
|
||||
selector: (state) => state.enterinformationController,
|
||||
builder: (context, enterinformationController) {
|
||||
return CustomTextFormField(
|
||||
controller: enterinformationController,
|
||||
hintText:
|
||||
"Я занимаюсь плаванием , почти каждый вечер прогулки на свежем воздухе, пару раз в месяц играю в волейбол. Стараюсь не сидеть на месте!",
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 8,);
|
||||
},),
|
||||
],);
|
||||
controller: enterinformationController,
|
||||
hintText:
|
||||
"Я занимаюсь плаванием , почти каждый вечер прогулки на свежем воздухе, пару раз в месяц играю в волейбол. Стараюсь не сидеть на месте!",
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
onTapArrowLeft(BuildContext context) {
|
||||
|
||||
@@ -15,12 +15,13 @@ class GenderScreen extends StatefulWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<GenderBloc>(
|
||||
create: (context) => GenderBloc(
|
||||
GenderState(
|
||||
genderModelObj: GenderModel(userRegistrationSheet: sheet),
|
||||
),
|
||||
)..add(GenderInitialEvent()),
|
||||
child: GenderScreen(),);
|
||||
create: (context) => GenderBloc(
|
||||
GenderState(
|
||||
genderModelObj: GenderModel(userRegistrationSheet: sheet),
|
||||
),
|
||||
)..add(GenderInitialEvent()),
|
||||
child: GenderScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -31,25 +32,33 @@ class _GenderScreenState extends State<GenderScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
return BlocBuilder<GenderBloc, GenderState>(builder: (context, state) {
|
||||
return Scaffold(
|
||||
return BlocBuilder<GenderBloc, GenderState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: _buildAppBar(context),
|
||||
body: Container(
|
||||
width: double.maxFinite,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.h, vertical: 9.v),
|
||||
child: Column(children: [
|
||||
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.16, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
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: (3 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 36.v),
|
||||
Text("your_gender".tr, style: theme.textTheme.headlineSmall),
|
||||
RadioListTile(
|
||||
@@ -75,15 +84,22 @@ class _GenderScreenState extends State<GenderScreen> {
|
||||
),
|
||||
),
|
||||
Spacer(flex: 66),
|
||||
BlocBuilder<GenderBloc, GenderState>(builder: (context, state) {
|
||||
return NextStepButton(
|
||||
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: onTapNext(state, context),);
|
||||
},),
|
||||
],),),);
|
||||
},);
|
||||
onPressed: onTapNext(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onTapNext(GenderState state, BuildContext context) {
|
||||
|
||||
@@ -17,8 +17,9 @@ class HeightScreen extends StatelessWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<HeightBloc>(
|
||||
create: (context) => HeightBloc(HeightState(heightModelObj: HeightModel(userRegistrationSheet: sheet)))..add(HeightInitialEvent()),
|
||||
child: HeightScreen(),);
|
||||
create: (context) => HeightBloc(HeightState(heightModelObj: HeightModel(userRegistrationSheet: sheet)))..add(HeightInitialEvent()),
|
||||
child: HeightScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -46,7 +47,7 @@ class HeightScreen extends StatelessWidget {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
child: LinearProgressIndicator(
|
||||
value: 0.55,
|
||||
value: (8 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
appTheme.blueA400,
|
||||
@@ -69,17 +70,19 @@ class HeightScreen extends StatelessWidget {
|
||||
style: theme.textTheme.bodyLarge,
|
||||
),
|
||||
SizedBox(height: 4.v),
|
||||
BlocBuilder<HeightBloc, HeightState>(builder: (context, state) {
|
||||
return CustomTextFormField(
|
||||
width: 150.h,
|
||||
textInputAction: TextInputAction.done,
|
||||
controller: state.heightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
);
|
||||
},),
|
||||
BlocBuilder<HeightBloc, HeightState>(
|
||||
builder: (context, state) {
|
||||
return CustomTextFormField(
|
||||
width: 150.h,
|
||||
textInputAction: TextInputAction.done,
|
||||
controller: state.heightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -115,11 +118,12 @@ class HeightScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
|
||||
@@ -46,7 +46,7 @@ class LanguageSelectScreen extends StatelessWidget {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
child: LinearProgressIndicator(
|
||||
value: 0,
|
||||
value: (0 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
@@ -66,28 +66,29 @@ class LanguageSelectScreen extends StatelessWidget {
|
||||
),
|
||||
Spacer(flex: 36),
|
||||
BlocSelector<LanguageSelectBloc, LanguageSelectState, LanguageSelectModel?>(
|
||||
selector: (state) => state.languageSelectModelObj,
|
||||
builder: (
|
||||
context,
|
||||
languageSelectModelObj,
|
||||
) {
|
||||
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,
|
||||
),
|
||||
selector: (state) => state.languageSelectModelObj,
|
||||
builder: (
|
||||
context,
|
||||
languageSelectModelObj,
|
||||
) {
|
||||
return CustomDropDown(
|
||||
icon: Container(
|
||||
margin: EdgeInsets.fromLTRB(30.h, 11.v, 17.h, 11.v),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(1.h),
|
||||
),
|
||||
hintText: "Не выбрано".tr,
|
||||
items: languageSelectModelObj?.dropdownItemList ?? [],
|
||||
onChanged: (value) => _onDropDownChanged(context, value),
|
||||
);
|
||||
},),
|
||||
child: CustomImageView(
|
||||
imagePath: ImageConstant.imgFavorite,
|
||||
height: 12.adaptSize,
|
||||
width: 12.adaptSize,
|
||||
),
|
||||
),
|
||||
hintText: "Не выбрано".tr,
|
||||
items: languageSelectModelObj?.dropdownItemList ?? [],
|
||||
onChanged: (value) => _onDropDownChanged(context, value),
|
||||
);
|
||||
},
|
||||
),
|
||||
Spacer(flex: 63),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -16,9 +16,10 @@ class MedicineIntakeScreen extends StatefulWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<MedicineIntakeBloc>(
|
||||
create: (context) => MedicineIntakeBloc(MedicineIntakeState(medicineIntakeModelObj: MedicineIntakeModel(userRegistrationSheet: sheet)))
|
||||
..add(MedicineIntakeInitialEvent()),
|
||||
child: MedicineIntakeScreen(),);
|
||||
create: (context) =>
|
||||
MedicineIntakeBloc(MedicineIntakeState(medicineIntakeModelObj: MedicineIntakeModel(userRegistrationSheet: sheet)))..add(MedicineIntakeInitialEvent()),
|
||||
child: MedicineIntakeScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -30,54 +31,75 @@ class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
return 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.69, backgroundColor: theme.colorScheme.onPrimary, valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),),),),
|
||||
SizedBox(height: 20.v),
|
||||
Container(
|
||||
width: 271.h,
|
||||
margin: EdgeInsets.only(left: 35.h, right: 36.h),
|
||||
child: Text("do_you_take_pills".tr,
|
||||
maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: theme.textTheme.headlineSmall,),),
|
||||
SizedBox(height: 86.v),
|
||||
_buildTextFormField(context),
|
||||
Spacer(),
|
||||
BlocBuilder<MedicineIntakeBloc, MedicineIntakeState>(builder: (context, state) {
|
||||
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: (11 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.v),
|
||||
Container(
|
||||
width: 271.h,
|
||||
margin: EdgeInsets.only(left: 35.h, right: 36.h),
|
||||
child: Text(
|
||||
"do_you_take_pills".tr,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 86.v),
|
||||
_buildTextFormField(context),
|
||||
Spacer(),
|
||||
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: onTapNext(state, context),);
|
||||
},),
|
||||
BlocBuilder<MedicineIntakeBloc, MedicineIntakeState>(builder: (context, state) {
|
||||
text: "continue".tr.toUpperCase(),
|
||||
margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v),
|
||||
buttonStyle: CustomButtonStyles.outlinePrimaryTL15,
|
||||
onPressed: onTapNext(state, context),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<MedicineIntakeBloc, MedicineIntakeState>(
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
onTap: onTapSkip(state, context),
|
||||
child: Text("skip".tr, style: theme.textTheme.bodyLarge),
|
||||
);
|
||||
},),
|
||||
],),),);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onTapSkip(MedicineIntakeState state, BuildContext context) {
|
||||
return () {
|
||||
UserRegistrationSheet sheet = state.medicineIntakeModelObj!.userRegistrationSheet;
|
||||
GoRouter.of(context).goNamed(
|
||||
'bloodPressureScreen',
|
||||
'favoriteSportsScreen',
|
||||
extra: sheet,
|
||||
);
|
||||
};
|
||||
@@ -88,7 +110,7 @@ class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
|
||||
UserRegistrationSheet sheet = state.medicineIntakeModelObj!.userRegistrationSheet;
|
||||
sheet.aboutTakingPils = state.enterInformationController!.text;
|
||||
GoRouter.of(context).goNamed(
|
||||
'bloodPressureScreen',
|
||||
'favoriteSportsScreen',
|
||||
extra: sheet,
|
||||
);
|
||||
};
|
||||
@@ -97,11 +119,12 @@ class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 31.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
@@ -112,16 +135,23 @@ class _MedicineIntakeScreenState extends State<MedicineIntakeScreen> {
|
||||
|
||||
/// Section Widget
|
||||
_buildTextFormField(BuildContext context) {
|
||||
return Column(children: [
|
||||
Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<MedicineIntakeBloc, MedicineIntakeState, TextEditingController?>(
|
||||
return Column(
|
||||
children: [
|
||||
Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI),
|
||||
SizedBox(height: 2.v),
|
||||
BlocSelector<MedicineIntakeBloc, MedicineIntakeState, TextEditingController?>(
|
||||
selector: (state) => state.enterInformationController,
|
||||
builder: (context, enterInformationController) {
|
||||
return CustomTextFormField(
|
||||
controller: enterInformationController, hintText: "enter_information".tr, textInputAction: TextInputAction.done, maxLines: 8,);
|
||||
},),
|
||||
],);
|
||||
controller: enterInformationController,
|
||||
hintText: "enter_information".tr,
|
||||
textInputAction: TextInputAction.done,
|
||||
maxLines: 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigates to the previous screen.
|
||||
|
||||
@@ -17,76 +17,95 @@ class NameScreen extends StatelessWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<NameBloc>(
|
||||
create: (context) => NameBloc(
|
||||
NameState(
|
||||
nameModelObj: NameModel(userRegistrationSheet: sheet),
|
||||
),
|
||||
)..add(NameInitialEvent()),
|
||||
child: NameScreen(),);
|
||||
create: (context) => NameBloc(
|
||||
NameState(
|
||||
nameModelObj: NameModel(userRegistrationSheet: sheet),
|
||||
),
|
||||
)..add(NameInitialEvent()),
|
||||
child: NameScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
mediaQueryData = MediaQuery.of(context);
|
||||
return 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,
|
||||
);
|
||||
},),
|
||||
Spacer(),
|
||||
BlocBuilder<NameBloc, NameState>(builder: (context, state) {
|
||||
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: (2 / 15).toDouble(),
|
||||
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,
|
||||
);
|
||||
},
|
||||
),
|
||||
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: () => _onTapNext(context, state), // Assign callback function here
|
||||
);
|
||||
},),
|
||||
],),),);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Section Widget
|
||||
_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),);
|
||||
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.
|
||||
|
||||
@@ -17,8 +17,9 @@ class WeightScreen extends StatelessWidget {
|
||||
|
||||
static Widget builder(BuildContext context, sheet) {
|
||||
return BlocProvider<WeightBloc>(
|
||||
create: (context) => WeightBloc(WeightState(weightModelObj: WeightModel(userRegistrationSheet: sheet)))..add(WeightInitialEvent()),
|
||||
child: WeightScreen(),);
|
||||
create: (context) => WeightBloc(WeightState(weightModelObj: WeightModel(userRegistrationSheet: sheet)))..add(WeightInitialEvent()),
|
||||
child: WeightScreen(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -45,7 +46,7 @@ class WeightScreen extends StatelessWidget {
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.h),
|
||||
child: LinearProgressIndicator(
|
||||
value: 0.55,
|
||||
value: (7 / 15).toDouble(),
|
||||
backgroundColor: theme.colorScheme.onPrimary,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
appTheme.blueA400,
|
||||
@@ -68,17 +69,19 @@ class WeightScreen extends StatelessWidget {
|
||||
style: theme.textTheme.bodyLarge,
|
||||
),
|
||||
SizedBox(height: 4.v),
|
||||
BlocBuilder<WeightBloc, WeightState>(builder: (context, state) {
|
||||
return CustomTextFormField(
|
||||
width: 150.h,
|
||||
textInputAction: TextInputAction.done,
|
||||
controller: state.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
);
|
||||
},),
|
||||
BlocBuilder<WeightBloc, WeightState>(
|
||||
builder: (context, state) {
|
||||
return CustomTextFormField(
|
||||
width: 150.h,
|
||||
textInputAction: TextInputAction.done,
|
||||
controller: state.weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -114,11 +117,12 @@ class WeightScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_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: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),);
|
||||
leadingWidth: 29.h,
|
||||
leading:
|
||||
AppbarLeadingImage(imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), onTap: onTapBack(context)),
|
||||
centerTitle: true,
|
||||
title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio),
|
||||
);
|
||||
}
|
||||
|
||||
Function onTapBack(BuildContext context) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import '../../core/app_export.dart';
|
||||
|
||||
/// Helper class for managing themes and colors.
|
||||
@@ -22,7 +23,8 @@ class ThemeHelper {
|
||||
//throw exception to notify given theme is not found or not generated by the generator
|
||||
if (!_supportedCustomColor.containsKey(_appTheme)) {
|
||||
throw Exception(
|
||||
"$_appTheme is not found.Make sure you have added this theme class in JSON Try running flutter pub run build_runner",);
|
||||
"$_appTheme is not found.Make sure you have added this theme class in JSON Try running flutter pub run build_runner",
|
||||
);
|
||||
}
|
||||
//return theme from map
|
||||
|
||||
@@ -34,13 +36,50 @@ class ThemeHelper {
|
||||
//throw exception to notify given theme is not found or not generated by the generator
|
||||
if (!_supportedColorScheme.containsKey(_appTheme)) {
|
||||
throw Exception(
|
||||
"$_appTheme is not found.Make sure you have added this theme class in JSON Try running flutter pub run build_runner",);
|
||||
"$_appTheme is not found.Make sure you have added this theme class in JSON Try running flutter pub run build_runner",
|
||||
);
|
||||
}
|
||||
//return theme from map
|
||||
|
||||
var colorScheme =
|
||||
_supportedColorScheme[_appTheme] ?? ColorSchemes.primaryColorScheme;
|
||||
var colorScheme = _supportedColorScheme[_appTheme] ?? ColorSchemes.primaryColorScheme;
|
||||
return ThemeData(
|
||||
textTheme: GoogleFonts.mulishTextTheme().copyWith(
|
||||
bodyLarge: TextStyle(
|
||||
color: appTheme.blueGray400,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
headlineSmall: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 24,
|
||||
),
|
||||
titleMedium: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 18,
|
||||
),
|
||||
titleSmall: TextStyle(
|
||||
color: colorScheme.onPrimary,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 15,
|
||||
),
|
||||
bodyMedium: TextStyle(
|
||||
color: appTheme.blueGray400,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14,
|
||||
),
|
||||
bodySmall: TextStyle(
|
||||
color: appTheme.gray500,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 10,
|
||||
),
|
||||
labelLarge: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
pageTransitionsTheme: PageTransitionsTheme(
|
||||
builders: {
|
||||
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
|
||||
@@ -49,7 +88,6 @@ class ThemeHelper {
|
||||
),
|
||||
visualDensity: VisualDensity.standard,
|
||||
colorScheme: colorScheme,
|
||||
textTheme: TextThemes.textTheme(colorScheme),
|
||||
scaffoldBackgroundColor: colorScheme.onPrimary,
|
||||
appBarTheme: AppBarTheme(
|
||||
systemOverlayStyle: SystemUiOverlayStyle(
|
||||
@@ -85,54 +123,6 @@ class ThemeHelper {
|
||||
ThemeData themeData() => _getThemeData();
|
||||
}
|
||||
|
||||
/// Class containing the supported text theme styles.
|
||||
class TextThemes {
|
||||
static TextTheme textTheme(ColorScheme colorScheme) => TextTheme(
|
||||
bodyLarge: TextStyle(
|
||||
color: appTheme.blueGray400,
|
||||
fontSize: 18.fSize,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
headlineSmall: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontSize: 24.fSize,
|
||||
fontFamily: 'Segoe UI',
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
titleMedium: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontSize: 18.fSize,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
titleSmall: TextStyle(
|
||||
color: colorScheme.onPrimary,
|
||||
fontSize: 15.fSize,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
bodyMedium: TextStyle(
|
||||
color: appTheme.blueGray400,
|
||||
fontSize: 14.fSize,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
bodySmall: TextStyle(
|
||||
color: appTheme.gray500,
|
||||
fontSize: 10.fSize,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
labelLarge: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 12.fSize,
|
||||
fontFamily: 'Mulish',
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Class containing the supported color schemes.
|
||||
class ColorSchemes {
|
||||
static final primaryColorScheme = ColorScheme.light(
|
||||
@@ -149,10 +139,12 @@ class ColorSchemes {
|
||||
class PrimaryColors {
|
||||
// Blue
|
||||
Color get blue400 => Color(0XFF43A6F2);
|
||||
|
||||
Color get blueA400 => Color(0XFF2F80ED);
|
||||
|
||||
// BlueGray
|
||||
Color get blueGray400 => Color(0XFF7B8794);
|
||||
|
||||
Color get black900 => Color(0XFF000000);
|
||||
|
||||
// Blue
|
||||
@@ -160,7 +152,9 @@ class PrimaryColors {
|
||||
|
||||
// BlueGray
|
||||
Color get blueGray300 => Color(0XFF9AA5B1);
|
||||
|
||||
Color get blueGray800 => Color(0XFF323F4B);
|
||||
|
||||
Color get blueGray900 => Color(0XFF2A2F4C);
|
||||
|
||||
// DeepOrange
|
||||
@@ -168,22 +162,33 @@ class PrimaryColors {
|
||||
|
||||
// Gray
|
||||
Color get gray100 => Color(0XFFF0F2F5);
|
||||
|
||||
Color get gray200 => Color(0XFFF0F0F0);
|
||||
|
||||
Color get gray400 => Color(0XFFC1C1C1);
|
||||
|
||||
Color get gray40001 => Color(0XFFC8C8C8);
|
||||
|
||||
Color get gray50 => Color(0XFFF6FAFF);
|
||||
|
||||
Color get gray500 => Color(0XFFA3A3A3);
|
||||
|
||||
Color get gray600 => Color(0XFF6D6D6D);
|
||||
|
||||
Color get gray60001 => Color(0XFF848484);
|
||||
|
||||
Color get gray60002 => Color(0XFF757575);
|
||||
|
||||
Color get gray60003 => Color(0XFF707070);
|
||||
|
||||
// Green
|
||||
Color get greenA700 => Color(0XFF019A3E);
|
||||
|
||||
Color get greenA70001 => Color(0XFF00BE13);
|
||||
|
||||
// LightGreen
|
||||
Color get lightGreen300 => Color(0XFFB2DF8A);
|
||||
|
||||
Color get lightGreenA700 => Color(0XFF18FF14);
|
||||
|
||||
// Red
|
||||
@@ -191,6 +196,7 @@ class PrimaryColors {
|
||||
|
||||
// Teal
|
||||
Color get teal100 => Color(0XFFA6CEE3);
|
||||
|
||||
Color get teal900 => Color(0XFF0B3F56);
|
||||
|
||||
// White
|
||||
@@ -200,4 +206,5 @@ class PrimaryColors {
|
||||
}
|
||||
|
||||
PrimaryColors get appTheme => ThemeHelper().themeColor();
|
||||
|
||||
ThemeData get theme => ThemeHelper().themeData();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/app_export.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:eatvio_app/widgets/custom_image_view.dart';
|
||||
|
||||
@@ -20,13 +21,12 @@ class MenuItem extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center, // Выравнивание по центру вертикально
|
||||
crossAxisAlignment: CrossAxisAlignment.center, // Выравнивание по центру вертикально
|
||||
children: <Widget>[
|
||||
CustomImageView(imagePath: icon),
|
||||
SizedBox(
|
||||
width:
|
||||
8.0,), // Добавляем небольшой отступ между иконкой и текстом
|
||||
width: 8.0,
|
||||
), // Добавляем небольшой отступ между иконкой и текстом
|
||||
Text(text),
|
||||
],
|
||||
),
|
||||
|
||||
16
pubspec.yaml
16
pubspec.yaml
@@ -44,6 +44,7 @@ dependencies:
|
||||
easy_debounce: ^2.0.3
|
||||
lazy_load_scrollview: ^1.3.0
|
||||
badges: ^3.1.2
|
||||
google_fonts: ^6.2.1
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.11
|
||||
@@ -59,17 +60,4 @@ flutter:
|
||||
assets:
|
||||
- assets/
|
||||
- assets/images/
|
||||
- .env
|
||||
fonts:
|
||||
- family: Segoe UI
|
||||
fonts:
|
||||
- asset: assets/fonts/SegoeUISemibold.ttf
|
||||
weight: 600
|
||||
- family: Mulish
|
||||
fonts:
|
||||
- asset: assets/fonts/MulishBold.ttf
|
||||
weight: 700
|
||||
- asset: assets/fonts/MulishRegular.ttf
|
||||
weight: 400
|
||||
- asset: assets/fonts/MulishSemiBold.ttf
|
||||
weight: 600
|
||||
- .env
|
||||
Reference in New Issue
Block a user