refactor(all): refactor

This commit is contained in:
alex
2024-07-09 17:50:32 +03:00
parent f79b9f03ae
commit e180ff16b6
37 changed files with 1706 additions and 1123 deletions

View File

@@ -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(

View File

@@ -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;
}
}
}
}

View File

@@ -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),
),

View File

@@ -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),
),
),
),
),
),

View 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);
}

View File

@@ -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;
}

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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())),

View File

@@ -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(

View File

@@ -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());
}
}

View File

@@ -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,

View File

@@ -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,
),
);
}
}
}

View File

@@ -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 {
// Один или несколько ключевых полей отсутствуют, обрабатываем ошибку

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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),
],
),

View File

@@ -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.

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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),
],
),

View File

@@ -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