user details created

This commit is contained in:
Username1548
2024-12-25 17:51:50 +07:00
parent 0c981b0068
commit 3521a58c2f
23 changed files with 1382 additions and 220 deletions

View File

@@ -41,6 +41,7 @@ import 'package:eatvio_app/features/settings/presentation/pages/physical_activit
import 'package:eatvio_app/features/settings/presentation/pages/physical_form_screen.dart';
import 'package:eatvio_app/features/settings/presentation/pages/pressure_screen.dart';
import 'package:eatvio_app/features/settings/presentation/pages/settings_screen.dart';
import 'package:eatvio_app/features/user_details/presentation/user_details_screen.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
@@ -294,6 +295,13 @@ class AppRouter {
name: MyPlansScreen.name,
builder: (context, state) => MyPlansScreen(),
),
GoRoute(
path: UserDetailsScreen.path,
name: UserDetailsScreen.name,
builder: (context, state) => UserDetailsScreen(
slug: state.extra as String,
),
),
],
);
}

View File

@@ -61,6 +61,7 @@ import 'package:eatvio_app/features/registration/services/registration_service.d
import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart';
import 'package:eatvio_app/features/settings/repositories/service_repository.dart';
import 'package:eatvio_app/features/settings/services/settings_service.dart';
import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart';
import 'package:get_it/get_it.dart';
import 'package:eatvio_app/features/profile/presentation/bloc/plans_cubit/plans_cubit.dart' as profilePlans;
@@ -98,6 +99,7 @@ Future<void> init() async {
sl.registerFactory<CreateRecipeCubit>(() => CreateRecipeCubit());
sl.registerFactory<MyDietsCubit>(() => MyDietsCubit(myDietsRepository: sl()));
sl.registerFactory<MyPlansCubit>(() => MyPlansCubit(myPlansRepository: sl()));
sl.registerFactory<UserDetailsCubit>(() => UserDetailsCubit(profileRepository: sl()));
// Repository
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));

View File

@@ -2,4 +2,13 @@ extension Capitalization on String {
String capitalize() {
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
}
}
String parseGender() {
if (this == 'male') {
return 'Мужской';
} else if (this == 'female') {
return 'Женский';
}
return this;
}
}

View File

@@ -80,20 +80,20 @@ class CustomTextFormField extends StatelessWidget {
final TextAlignVertical? textAlignVertical;
final bool hasError;
final bool enabled;
// final TextAlign
final bool readOnly;
@override
Widget build(BuildContext context) {
return Align(
alignment: alignment ?? Alignment.center,
child: TextFormField(
child: TextFormField(
enabled: enabled,
readOnly: readOnly,
textAlignVertical: textAlignVertical,
expands: expands,
minLines: minLines,
maxLength: maxLength,
onChanged: onChanged,
onChanged: onChanged,
controller: controller,
focusNode: focusNode ?? null,
autofocus: autofocus,

View File

@@ -1,4 +1,5 @@
import 'package:badges/badges.dart' as badges;
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/utils/image_constant.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_state.dart';
@@ -6,6 +7,8 @@ import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/noti
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_state.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart';
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
import 'package:eatvio_app/features/user_details/presentation/user_details_screen.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
@@ -28,7 +31,7 @@ class BottomNavigationBarWidget extends StatefulWidget {
}
class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
void _onItemTapped(int index) {
void _onItemTapped(int index) async {
if (currentBottomNavBarIndex != index) {
setState(() {
currentBottomNavBarIndex = index;

View File

@@ -12,9 +12,12 @@ class ChatSelectCubit extends Cubit<ChatSelectState> {
getChatRooms({String? query}) async {
emit(ChatSelectState.loading());
try {
emit(ChatSelectState.loaded(
chatRooms: (await chatRepository.getChatRoomPreviews(query: query)),
),);
final chatRooms = await chatRepository.getChatRoomPreviews(query: query);
emit(
ChatSelectState.loaded(
chatRooms: chatRooms,
),
);
} catch (e) {
emit(
ChatSelectState.error(errorMessage: e.toString()),

View File

@@ -190,7 +190,10 @@ class _DietPreviewScreenState extends State<DietPreviewScreen> {
actions: [
PortalTarget(
visible: isMoreOptionsVisible,
portalFollower: MoreOptions(disableActions: true, id: widget.diet.id),
portalFollower: MoreOptions(
disableActions: true,
path: 'diet/${widget.diet.id}',
),
anchor: Aligned(
shiftToWithinBound: AxisFlag(x: true, y: true),
follower: Alignment.topRight,

View File

@@ -151,7 +151,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
BookmarkButton(
isFavorite: dietState.diet.isFavorite,
onTap: () {
if (dietState.diet.isFavorite) {
if (dietState.diet.isFavorite) {
dietsCubit.removeFromFavorite(widget.diet.id, widget.index);
} else {
dietsCubit.addToFavorite(widget.diet.id, widget.index);
@@ -291,7 +291,9 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
actions: [
PortalTarget(
visible: isMoreOptionsVisible,
portalFollower: MoreOptions(id: widget.diet.id),
portalFollower: MoreOptions(
path: 'diet/${widget.diet.id}',
),
anchor: Aligned(
shiftToWithinBound: AxisFlag(x: true, y: true),
follower: Alignment.topRight,

View File

@@ -12,8 +12,8 @@ import 'package:go_router/go_router.dart';
import 'package:share_plus/share_plus.dart';
class MoreOptions extends StatelessWidget {
const MoreOptions({super.key, required this.id, this.disableActions});
final int id;
const MoreOptions({super.key, this.disableActions, required this.path});
final String path;
final bool? disableActions;
@override
Widget build(BuildContext context) {
@@ -26,10 +26,12 @@ class MoreOptions extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap:disableActions == true ? null : () {
Clipboard.setData(ClipboardData(text: baseUrl + '/ru/diet/' + id.toString()));
showInfoToast(s.link_was_copied);
},
onTap: disableActions == true
? null
: () {
Clipboard.setData(ClipboardData(text: '$baseUrl/ru/$path'));
showInfoToast(s.link_was_copied);
},
child: Row(
children: [
Text(
@@ -48,11 +50,13 @@ class MoreOptions extends StatelessWidget {
child: CustomDivider(),
),
GestureDetector(
onTap: disableActions == true ? null : () => Share.shareUri(
Uri.parse(
baseUrl + '/ru/diet/' + id.toString(),
),
),
onTap: disableActions == true
? null
: () => Share.shareUri(
Uri.parse(
'$baseUrl/ru/$path',
),
),
child: Row(
children: [
Text(
@@ -71,9 +75,11 @@ class MoreOptions extends StatelessWidget {
child: CustomDivider(),
),
GestureDetector(
onTap: disableActions == true ? null : () {
context.push('complainingScreen');
},
onTap: disableActions == true
? null
: () {
context.push('complainingScreen');
},
child: Row(
children: [
Text(

View File

@@ -292,7 +292,9 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
actions: [
PortalTarget(
visible: isMoreOptionsVisible,
portalFollower: MoreOptions(id: widget.plan.id),
portalFollower: MoreOptions(
path: 'plan/${widget.plan.id}',
),
anchor: Aligned(
shiftToWithinBound: AxisFlag(x: true, y: true),
follower: Alignment.topRight,

View File

@@ -276,7 +276,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
height: 378,
child: PageView.builder(
itemBuilder: (BuildContext context, int index) {
return PlanWidget(plan: state.plansList[index], index: index,);
return PlanWidget(
plan: state.plansList[index],
index: index,
);
},
onPageChanged: (bullet) {
setState(() {
@@ -1097,7 +1100,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
);
}
_charts() {
_charts() {
return Material(
color: Colors.white,
borderRadius: BorderRadius.circular(16),

View File

@@ -8,12 +8,12 @@ import 'package:syncfusion_flutter_charts/charts.dart';
class CircumferenceChartWidget extends StatefulWidget {
final List<CircumferenceModel> circumferencePoints;
final ProfileCubit profileCubit;
final ProfileCubit? profileCubit;
const CircumferenceChartWidget({
super.key,
required this.circumferencePoints,
required this.profileCubit,
this.profileCubit,
});
@override
@@ -171,117 +171,118 @@ class _CircumferenceChartWidgetState extends State<CircumferenceChartWidget> {
series: _getSplineSeries(),
tooltipBehavior: TooltipBehavior(enable: true),
),
FloatingActionButton.small(
heroTag: 'addCircumference',
onPressed: () {
if (widget.circumferencePoints.isNotEmpty) {
chest = widget.circumferencePoints.last.chestCircumference;
waist = widget.circumferencePoints.last.waistCircumference;
hip = widget.circumferencePoints.last.hipCircumference;
chestController = FixedExtentScrollController(initialItem: chest - 20);
waistController = FixedExtentScrollController(initialItem: waist - 20);
hipController = FixedExtentScrollController(initialItem: hip - 20);
} else {
chestController = FixedExtentScrollController();
waistController = FixedExtentScrollController();
hipController = FixedExtentScrollController();
}
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: chestController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
chest = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
if (widget.profileCubit != null)
FloatingActionButton.small(
heroTag: 'addCircumference',
onPressed: () {
if (widget.circumferencePoints.isNotEmpty) {
chest = widget.circumferencePoints.last.chestCircumference;
waist = widget.circumferencePoints.last.waistCircumference;
hip = widget.circumferencePoints.last.hipCircumference;
chestController = FixedExtentScrollController(initialItem: chest - 20);
waistController = FixedExtentScrollController(initialItem: waist - 20);
hipController = FixedExtentScrollController(initialItem: hip - 20);
} else {
chestController = FixedExtentScrollController();
waistController = FixedExtentScrollController();
hipController = FixedExtentScrollController();
}
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: chestController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
chest = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
),
),
),
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: waistController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
waist = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: waistController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
waist = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
),
),
),
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: hipController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
hip = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: hipController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
hip = value;
},
children: [
for (int i = 20; i < 200; i++) Text('$i'),
],
),
),
),
],
),
),
InkWell(
onTap: () {
widget.profileCubit.addCircumference(
chestCircumference: chest + 20,
waistCircumference: waist + 20,
hipCircumference: hip + 20,
);
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
],
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
InkWell(
onTap: () {
widget.profileCubit?.addCircumference(
chestCircumference: chest + 20,
waistCircumference: waist + 20,
hipCircumference: hip + 20,
);
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
),
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
),
),
),
],
),
],

View File

@@ -8,12 +8,12 @@ import 'package:syncfusion_flutter_charts/charts.dart';
class WeightChartWidget extends StatefulWidget {
final List<WeightModel> weightPoints;
final ProfileCubit profileCubit;
final ProfileCubit? profileCubit;
const WeightChartWidget({
super.key,
required this.weightPoints,
required this.profileCubit,
this.profileCubit,
});
@override
@@ -111,99 +111,100 @@ class _WeightChartWidgetState extends State<WeightChartWidget> {
series: _getSplineSeries(),
tooltipBehavior: TooltipBehavior(enable: true),
),
FloatingActionButton.small(
heroTag: 'addWeight',
onPressed: () {
if (widget.weightPoints.isNotEmpty) {
try {
weightKilo = int.parse(widget.weightPoints.last.weight.toString().split('.')[0]);
weightGrams = int.parse(widget.weightPoints.last.weight.toString().split('.')[1][0]);
} catch (e) {
weightGrams = 0;
if (widget.profileCubit != null)
FloatingActionButton.small(
heroTag: 'addWeight',
onPressed: () {
if (widget.weightPoints.isNotEmpty) {
try {
weightKilo = int.parse(widget.weightPoints.last.weight.toString().split('.')[0]);
weightGrams = int.parse(widget.weightPoints.last.weight.toString().split('.')[1][0]);
} catch (e) {
weightGrams = 0;
}
weightKiloController = FixedExtentScrollController(initialItem: weightKilo - 20);
weightGramsController = FixedExtentScrollController(initialItem: weightGrams);
} else {
weightKiloController = FixedExtentScrollController();
weightGramsController = FixedExtentScrollController();
}
weightKiloController = FixedExtentScrollController(initialItem: weightKilo - 20);
weightGramsController = FixedExtentScrollController(initialItem: weightGrams);
} else {
weightKiloController = FixedExtentScrollController();
weightGramsController = FixedExtentScrollController();
}
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightKiloController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightKilo = value + 20;
},
children: [
for (int i = 20; i < 300; i++) Text('$i'),
],
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) {
return Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightKiloController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightKilo = value + 20;
},
children: [
for (int i = 20; i < 300; i++) Text('$i'),
],
),
),
),
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightGramsController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightGrams = value;
},
children: [
for (int i = 0; i < 10; i++) Text('$i'),
],
Expanded(
child: CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
scrollController: weightGramsController,
itemExtent: 24,
onSelectedItemChanged: (int value) {
weightGrams = value;
},
children: [
for (int i = 0; i < 10; i++) Text('$i'),
],
),
),
),
],
),
),
InkWell(
onTap: () {
widget.profileCubit.addWeight(weight: double.parse('$weightKilo.$weightGrams'));
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
],
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
InkWell(
onTap: () {
widget.profileCubit?.addWeight(weight: double.parse('$weightKilo.$weightGrams'));
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(16),
child: Ink(
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: appTheme.blueA400,
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: Text(
'Сохранить',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
),
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
],
);
},
);
},
backgroundColor: appTheme.blueA400,
shape: CircleBorder(),
child: Icon(
Icons.add,
color: Colors.white,
),
),
),
],
),
],

View File

@@ -0,0 +1,41 @@
import 'dart:developer';
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_state.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class UserDetailsCubit extends Cubit<UserDetailsState> {
final ProfileRepository profileRepository;
UserDetailsCubit({required this.profileRepository}) : super(UserDetailsState());
void getUserDetails(String slug) async {
try {
final profileDetails = await profileRepository.getProfileDetailsBySlug(slug);
emit(state.copyWith(profileDetails: profileDetails, isLoading: false));
getChartData(slug: slug);
} catch (e) {
log(e.toString());
emit(state.copyWith(error: e.toString(), isLoading: false));
}
}
void getChartData({
String period = '1',
required String slug,
}) async {
try {
final weightPoints = await profileRepository.getWeight(period: period);
final circumferencePoints = await profileRepository.getCircumferences(period: period);
emit(
state.copyWith(
weightPoints: weightPoints,
circumferencePoints: circumferencePoints,
),
);
} catch (e, stackTrace) {
log(e.toString(), stackTrace: stackTrace);
emit(state.copyWith(error: e.toString(), isLoading: false));
}
}
}

View File

@@ -0,0 +1,17 @@
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
import 'package:eatvio_app/features/profile/models/profile_model.dart';
import 'package:eatvio_app/features/profile/models/weight_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user_details_state.freezed.dart';
@freezed
class UserDetailsState with _$UserDetailsState {
factory UserDetailsState({
@Default(false) bool isLoading,
String? error,
ProfileDetailsModel? profileDetails,
List<WeightModel>? weightPoints,
List<CircumferenceModel>? circumferencePoints,
}) = _UserDetailsState;
}

View File

@@ -0,0 +1,278 @@
// 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 'user_details_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$UserDetailsState {
bool get isLoading => throw _privateConstructorUsedError;
String? get error => throw _privateConstructorUsedError;
ProfileDetailsModel? get profileDetails => throw _privateConstructorUsedError;
List<WeightModel>? get weightPoints => throw _privateConstructorUsedError;
List<CircumferenceModel>? get circumferencePoints =>
throw _privateConstructorUsedError;
/// Create a copy of UserDetailsState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$UserDetailsStateCopyWith<UserDetailsState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserDetailsStateCopyWith<$Res> {
factory $UserDetailsStateCopyWith(
UserDetailsState value, $Res Function(UserDetailsState) then) =
_$UserDetailsStateCopyWithImpl<$Res, UserDetailsState>;
@useResult
$Res call(
{bool isLoading,
String? error,
ProfileDetailsModel? profileDetails,
List<WeightModel>? weightPoints,
List<CircumferenceModel>? circumferencePoints});
$ProfileDetailsModelCopyWith<$Res>? get profileDetails;
}
/// @nodoc
class _$UserDetailsStateCopyWithImpl<$Res, $Val extends UserDetailsState>
implements $UserDetailsStateCopyWith<$Res> {
_$UserDetailsStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UserDetailsState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isLoading = null,
Object? error = freezed,
Object? profileDetails = freezed,
Object? weightPoints = freezed,
Object? circumferencePoints = freezed,
}) {
return _then(_value.copyWith(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
error: freezed == error
? _value.error
: error // ignore: cast_nullable_to_non_nullable
as String?,
profileDetails: freezed == profileDetails
? _value.profileDetails
: profileDetails // ignore: cast_nullable_to_non_nullable
as ProfileDetailsModel?,
weightPoints: freezed == weightPoints
? _value.weightPoints
: weightPoints // ignore: cast_nullable_to_non_nullable
as List<WeightModel>?,
circumferencePoints: freezed == circumferencePoints
? _value.circumferencePoints
: circumferencePoints // ignore: cast_nullable_to_non_nullable
as List<CircumferenceModel>?,
) as $Val);
}
/// Create a copy of UserDetailsState
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ProfileDetailsModelCopyWith<$Res>? get profileDetails {
if (_value.profileDetails == null) {
return null;
}
return $ProfileDetailsModelCopyWith<$Res>(_value.profileDetails!, (value) {
return _then(_value.copyWith(profileDetails: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$UserDetailsStateImplCopyWith<$Res>
implements $UserDetailsStateCopyWith<$Res> {
factory _$$UserDetailsStateImplCopyWith(_$UserDetailsStateImpl value,
$Res Function(_$UserDetailsStateImpl) then) =
__$$UserDetailsStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{bool isLoading,
String? error,
ProfileDetailsModel? profileDetails,
List<WeightModel>? weightPoints,
List<CircumferenceModel>? circumferencePoints});
@override
$ProfileDetailsModelCopyWith<$Res>? get profileDetails;
}
/// @nodoc
class __$$UserDetailsStateImplCopyWithImpl<$Res>
extends _$UserDetailsStateCopyWithImpl<$Res, _$UserDetailsStateImpl>
implements _$$UserDetailsStateImplCopyWith<$Res> {
__$$UserDetailsStateImplCopyWithImpl(_$UserDetailsStateImpl _value,
$Res Function(_$UserDetailsStateImpl) _then)
: super(_value, _then);
/// Create a copy of UserDetailsState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? isLoading = null,
Object? error = freezed,
Object? profileDetails = freezed,
Object? weightPoints = freezed,
Object? circumferencePoints = freezed,
}) {
return _then(_$UserDetailsStateImpl(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
error: freezed == error
? _value.error
: error // ignore: cast_nullable_to_non_nullable
as String?,
profileDetails: freezed == profileDetails
? _value.profileDetails
: profileDetails // ignore: cast_nullable_to_non_nullable
as ProfileDetailsModel?,
weightPoints: freezed == weightPoints
? _value._weightPoints
: weightPoints // ignore: cast_nullable_to_non_nullable
as List<WeightModel>?,
circumferencePoints: freezed == circumferencePoints
? _value._circumferencePoints
: circumferencePoints // ignore: cast_nullable_to_non_nullable
as List<CircumferenceModel>?,
));
}
}
/// @nodoc
class _$UserDetailsStateImpl implements _UserDetailsState {
_$UserDetailsStateImpl(
{this.isLoading = false,
this.error,
this.profileDetails,
final List<WeightModel>? weightPoints,
final List<CircumferenceModel>? circumferencePoints})
: _weightPoints = weightPoints,
_circumferencePoints = circumferencePoints;
@override
@JsonKey()
final bool isLoading;
@override
final String? error;
@override
final ProfileDetailsModel? profileDetails;
final List<WeightModel>? _weightPoints;
@override
List<WeightModel>? get weightPoints {
final value = _weightPoints;
if (value == null) return null;
if (_weightPoints is EqualUnmodifiableListView) return _weightPoints;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
}
final List<CircumferenceModel>? _circumferencePoints;
@override
List<CircumferenceModel>? get circumferencePoints {
final value = _circumferencePoints;
if (value == null) return null;
if (_circumferencePoints is EqualUnmodifiableListView)
return _circumferencePoints;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
}
@override
String toString() {
return 'UserDetailsState(isLoading: $isLoading, error: $error, profileDetails: $profileDetails, weightPoints: $weightPoints, circumferencePoints: $circumferencePoints)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserDetailsStateImpl &&
(identical(other.isLoading, isLoading) ||
other.isLoading == isLoading) &&
(identical(other.error, error) || other.error == error) &&
(identical(other.profileDetails, profileDetails) ||
other.profileDetails == profileDetails) &&
const DeepCollectionEquality()
.equals(other._weightPoints, _weightPoints) &&
const DeepCollectionEquality()
.equals(other._circumferencePoints, _circumferencePoints));
}
@override
int get hashCode => Object.hash(
runtimeType,
isLoading,
error,
profileDetails,
const DeepCollectionEquality().hash(_weightPoints),
const DeepCollectionEquality().hash(_circumferencePoints));
/// Create a copy of UserDetailsState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$UserDetailsStateImplCopyWith<_$UserDetailsStateImpl> get copyWith =>
__$$UserDetailsStateImplCopyWithImpl<_$UserDetailsStateImpl>(
this, _$identity);
}
abstract class _UserDetailsState implements UserDetailsState {
factory _UserDetailsState(
{final bool isLoading,
final String? error,
final ProfileDetailsModel? profileDetails,
final List<WeightModel>? weightPoints,
final List<CircumferenceModel>? circumferencePoints}) =
_$UserDetailsStateImpl;
@override
bool get isLoading;
@override
String? get error;
@override
ProfileDetailsModel? get profileDetails;
@override
List<WeightModel>? get weightPoints;
@override
List<CircumferenceModel>? get circumferencePoints;
/// Create a copy of UserDetailsState
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$UserDetailsStateImplCopyWith<_$UserDetailsStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,520 @@
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/utils/date_time_utils.dart';
import 'package:eatvio_app/core/utils/string_extentions.dart';
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/more_options.dart';
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
import 'package:eatvio_app/features/profile/models/weight_model.dart';
import 'package:eatvio_app/features/profile/presentation/widgets/circumference_chart_widget.dart';
import 'package:eatvio_app/features/profile/presentation/widgets/imt_chart_widget.dart';
import 'package:eatvio_app/features/profile/presentation/widgets/weight_chart_widget.dart';
import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart';
import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_state.dart';
import 'package:eatvio_app/features/user_details/presentation/widgets/expandable_bouble.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_svg/svg.dart';
class UserDetailsScreen extends StatelessWidget {
final String slug;
const UserDetailsScreen({super.key, required this.slug});
static const name = 'userDetailsScreen';
static const path = '/user-details-screen';
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => sl<UserDetailsCubit>()..getUserDetails(slug),
child: UserDetailsContent(
slug: slug,
),
);
}
}
class UserDetailsContent extends StatefulWidget {
const UserDetailsContent({super.key, required this.slug});
final String slug;
@override
State<UserDetailsContent> createState() => _UserDetailsContentState();
}
class _UserDetailsContentState extends State<UserDetailsContent> {
final List<String> chipsLabelList = ['Вес', 'Замеры', 'ИМТ'];
final List<String> chipsIntervalLabelList = ['1М', '3М', '6М', '1Г', 'ВСЁ ВРЕМЯ'];
final List<String> chipsIntervalList = ['1', '3', '6', '12', 'all'];
List<WeightModel> weightPoints = [];
List<CircumferenceModel> circumferencePoints = [];
int _selectedChipIndex = 0;
int _selectedIntervalChipIndex = 0;
bool isMoreOptionsVisible = false;
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<UserDetailsCubit, UserDetailsState>(
builder: (context, state) {
final profileDetails = state.profileDetails;
if (profileDetails != null && state.isLoading == false) {
weightPoints = state.weightPoints ?? [];
circumferencePoints = state.circumferencePoints ?? [];
return Scaffold(
backgroundColor: appTheme.gray100,
appBar: AppBar(
centerTitle: true,
title: Text(
'${s.user_data} ${profileDetails.firstName} ${profileDetails.lastName}',
maxLines: 2,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
actions: [
PortalTarget(
visible: isMoreOptionsVisible,
portalFollower: MoreOptions(
path: 'profile/${widget.slug}',
),
anchor: Aligned(
shiftToWithinBound: AxisFlag(x: true, y: true),
follower: Alignment.topRight,
target: Alignment.bottomRight,
),
child: IconButton(
onPressed: () {
setState(() {
isMoreOptionsVisible = !isMoreOptionsVisible;
});
},
icon: SvgPicture.asset(
'assets/icons/more_button.svg',
width: 20,
height: 20,
),
),
),
],
),
body: SingleChildScrollView(
controller: ScrollController()
..addListener(() {
setState(() {
isMoreOptionsVisible = false;
});
}),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
spacing: 12,
children: [
SizedBox.shrink(),
_charts(),
ExpandableBouble(
initiallyExpanded: true,
title: s.general_info,
children: [
Text(
s.date_of_birth,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: DateTime.parse(profileDetails.birthdate).format('dd.MM.yyyy')),
),
SizedBox(height: 16),
Text(
s.sex,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.gender.parseGender()),
),
SizedBox(height: 16),
],
),
ExpandableBouble(
title: s.physical_fitness,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.height,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.height.toString()),
),
],
),
),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.weight,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.weight.toStringAsFixed(0)),
),
],
),
),
],
),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.chest_circumference,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.chestCircumference.toString()),
),
],
),
),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.waist_circumference,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.waistCircumference.toString()),
),
],
),
),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.hip_circumference,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.hipCircumference.toString()),
),
],
),
),
],
),
SizedBox(height: 16),
],
),
ExpandableBouble(
title: s.pressure,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.upper,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.bloodPressureUp.toString()),
),
],
),
),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.lower,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.bloodPressureDown.toStringAsFixed(0)),
),
],
),
),
],
),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.has_hypo,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.hasHypo.toString()),
),
],
),
),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.has_hyper,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.hasHyper.toString()),
),
],
),
),
],
),
SizedBox(height: 16),
],
),
ExpandableBouble(
title: s.other_info,
children: [
Text(
s.has_alergy,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.aboutAlergy),
),
SizedBox(height: 16),
Text(
s.takes_pills,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.aboutTakingPils),
),
SizedBox(height: 16),
Text(
s.sport_hobbies,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.aboutSportHobbies),
),
SizedBox(height: 16),
Text(
s.liked_groceries,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.favoriteFoods),
),
SizedBox(height: 16),
Text(
s.not_liked_groceries,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
CustomTextFormField(
readOnly: true,
controller: TextEditingController(text: profileDetails.unfavoriteFoods),
),
SizedBox(height: 16),
Text(
s.additional_information,
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 4),
SizedBox(
height: 112,
child: CustomTextFormField(
readOnly: true,
maxLength: 1000,
maxLines: null,
minLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
controller: TextEditingController(text: profileDetails.additionalInfo),
),
),
SizedBox(height: 16),
],
),
],
),
),
);
} else {
return Scaffold(
body: Loader(),
);
}
},
);
}
_charts() {
return Material(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16),
scrollDirection: Axis.horizontal,
child: Row(
children: [
_choiceChipWidget(0),
SizedBox(width: 8),
_choiceChipWidget(1),
SizedBox(width: 8),
_choiceChipWidget(2),
],
),
),
Builder(
builder: (context) {
switch (_selectedChipIndex) {
case 0:
return WeightChartWidget(
weightPoints: weightPoints,
);
case 1:
return CircumferenceChartWidget(
circumferencePoints: circumferencePoints,
);
case 2:
return ImtChartWidget(
weightPoints: weightPoints,
);
default:
return SizedBox.shrink();
}
},
),
SizedBox(height: 8),
Row(
children: [
SizedBox(width: 16),
_choiceIntervalChipWidget(0),
SizedBox(width: 8),
_choiceIntervalChipWidget(1),
SizedBox(width: 8),
_choiceIntervalChipWidget(2),
SizedBox(width: 8),
_choiceIntervalChipWidget(3),
SizedBox(width: 8),
_choiceIntervalChipWidget(4),
],
),
SizedBox(height: 8),
],
),
);
}
_choiceIntervalChipWidget(int index) {
return ChoiceChip(
selectedColor: Colors.grey.withValues(alpha: 0.1),
pressElevation: 0,
showCheckmark: false,
side: BorderSide.none,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
label: Text(chipsIntervalLabelList[index]),
labelStyle: TextStyle(
color: appTheme.gray600,
fontWeight: FontWeight.w500,
fontSize: 12,
),
selected: _selectedIntervalChipIndex == index,
onSelected: (bool selected) {
context.read<UserDetailsCubit>().getChartData(period: chipsIntervalList[index], slug: widget.slug);
setState(() {
_selectedIntervalChipIndex = index;
});
},
);
}
_choiceChipWidget(int index) {
return ChoiceChip(
selectedColor: appTheme.blueA400,
pressElevation: 0,
showCheckmark: false,
side: BorderSide.none,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
label: Text(chipsLabelList[index]),
labelStyle: TextStyle(
color: index == _selectedChipIndex ? Colors.white : appTheme.gray600,
fontWeight: FontWeight.w500,
fontSize: 12,
),
selected: _selectedChipIndex == index,
backgroundColor: appTheme.gray100,
onSelected: (bool selected) {
setState(() {
_selectedChipIndex = index;
});
},
);
}
}

View File

@@ -0,0 +1,34 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
import 'package:flutter/material.dart';
class ExpandableBouble extends StatelessWidget {
const ExpandableBouble({super.key, required this.title, required this.children, this.initiallyExpanded = false});
final String title;
final List<Widget> children;
final bool initiallyExpanded;
@override
Widget build(BuildContext context) {
return AnimatedSize(
duration: Duration(seconds: 1),
child: MainBackgroundBouble(
child: Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: initiallyExpanded,
expandedCrossAxisAlignment: CrossAxisAlignment.start,
expandedAlignment: Alignment.bottomLeft,
tilePadding: EdgeInsets.symmetric(horizontal: 16),
childrenPadding: EdgeInsets.symmetric(horizontal: 16),
title: Text(
title,
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
children: children,
),
),
),
);
}
}

View File

@@ -150,8 +150,16 @@ class MessageLookup extends MessageLookupByLibrary {
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
"general_info":
MessageLookupByLibrary.simpleMessage("Общая информация"),
"gr": MessageLookupByLibrary.simpleMessage("гр"),
"grams": MessageLookupByLibrary.simpleMessage("гр"),
"has_alergy": MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
"has_hyper":
MessageLookupByLibrary.simpleMessage("Склонность к гипертонии"),
"has_hypo":
MessageLookupByLibrary.simpleMessage("Склонность к гипотонии"),
"height": MessageLookupByLibrary.simpleMessage("Рост"),
"height_measurements":
MessageLookupByLibrary.simpleMessage("Замер роста"),
"hide": MessageLookupByLibrary.simpleMessage("Свернуть"),
@@ -173,9 +181,12 @@ class MessageLookup extends MessageLookupByLibrary {
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
"light_type_desc": MessageLookupByLibrary.simpleMessage(
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
"liked_groceries":
MessageLookupByLibrary.simpleMessage("Любимые продукты"),
"link_was_copied":
MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"),
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
"lower": MessageLookupByLibrary.simpleMessage("Нижнее"),
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
@@ -202,6 +213,8 @@ class MessageLookup extends MessageLookupByLibrary {
"no": MessageLookupByLibrary.simpleMessage("Нет"),
"no_account":
MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
"not_liked_groceries":
MessageLookupByLibrary.simpleMessage("Не любимые продукты"),
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
"option": MessageLookupByLibrary.simpleMessage("Опция"),
"option_content":
@@ -217,6 +230,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Опция подразумевает создание индивидуальной диеты"),
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
"other_info": MessageLookupByLibrary.simpleMessage("Прочая информация"),
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
"password_confirmation":
MessageLookupByLibrary.simpleMessage("Подтвердите пароль"),
@@ -231,6 +245,8 @@ class MessageLookup extends MessageLookupByLibrary {
"personal_diet_state":
MessageLookupByLibrary.simpleMessage("Персональная"),
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
"physical_fitness":
MessageLookupByLibrary.simpleMessage("Физическая форма"),
"place_of_living":
MessageLookupByLibrary.simpleMessage("Место проживания"),
"plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"),
@@ -246,6 +262,7 @@ class MessageLookup extends MessageLookupByLibrary {
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
"preferred_language":
MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"),
"pressure": MessageLookupByLibrary.simpleMessage("Давление"),
"pressure_empty": MessageLookupByLibrary.simpleMessage(
"Все показатели давления обязательны к заполнению"),
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
@@ -263,14 +280,19 @@ class MessageLookup extends MessageLookupByLibrary {
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
"sex": MessageLookupByLibrary.simpleMessage("Пол"),
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
"sport_hobbies":
MessageLookupByLibrary.simpleMessage("Спортивные увлечения"),
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
"takes_pills":
MessageLookupByLibrary.simpleMessage("Принимает лекарства"),
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
@@ -281,8 +303,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
"up_pressure": MessageLookupByLibrary.simpleMessage(
"Верхние показатели давления:"),
"upper": MessageLookupByLibrary.simpleMessage("Верхнее"),
"user_authorization":
MessageLookupByLibrary.simpleMessage("Аутентификация"),
"user_data":
MessageLookupByLibrary.simpleMessage("Данные пользователя"),
"user_registration":
MessageLookupByLibrary.simpleMessage("Регистрация пользователя"),
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),

View File

@@ -88,7 +88,9 @@ class MessageLookup extends MessageLookupByLibrary {
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
"day": MessageLookupByLibrary.simpleMessage("День"),
"days": MessageLookupByLibrary.simpleMessage("дней"),
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
@@ -102,6 +104,7 @@ class MessageLookup extends MessageLookupByLibrary {
"down_pressure":
MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"),
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
"eating_behavior":
MessageLookupByLibrary.simpleMessage("Пищевое поведение"),
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
@@ -109,6 +112,7 @@ class MessageLookup extends MessageLookupByLibrary {
"eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage(
"Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;"),
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
"email": MessageLookupByLibrary.simpleMessage("Элетронная почта"),
"email_empty": MessageLookupByLibrary.simpleMessage(
"Необходимо ввести адрес электронной почты"),
@@ -142,6 +146,7 @@ class MessageLookup extends MessageLookupByLibrary {
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
"from": MessageLookupByLibrary.simpleMessage("от"),
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
@@ -187,6 +192,8 @@ class MessageLookup extends MessageLookupByLibrary {
"msg_something_went_wrong":
MessageLookupByLibrary.simpleMessage("Что то пошло не так!"),
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
"my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"),
"my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"),
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
"name_empty": MessageLookupByLibrary.simpleMessage(
"Имя пользователя обязательно для заполнения"),
@@ -220,6 +227,7 @@ class MessageLookup extends MessageLookupByLibrary {
"password_short": MessageLookupByLibrary.simpleMessage(
"В пароле должно быть минимум 6 символов"),
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
"personal_diet_state":
MessageLookupByLibrary.simpleMessage("Персональная"),
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
@@ -242,11 +250,15 @@ class MessageLookup extends MessageLookupByLibrary {
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
"Все показатели давления должны быть числами"),
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
"price": MessageLookupByLibrary.simpleMessage("Цена"),
"price_explanation": MessageLookupByLibrary.simpleMessage(
"Разница в ценах, это комиссия Итвио"),
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
"removeFromActive":
MessageLookupByLibrary.simpleMessage("Снять с публикации"),
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
@@ -261,6 +273,7 @@ class MessageLookup extends MessageLookupByLibrary {
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
"unfavorite_foods":
MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
@@ -268,6 +281,8 @@ class MessageLookup extends MessageLookupByLibrary {
"Верхние показатели давления:"),
"user_authorization":
MessageLookupByLibrary.simpleMessage("Аутентификация"),
"user_data":
MessageLookupByLibrary.simpleMessage("Данные пользователя"),
"user_registration":
MessageLookupByLibrary.simpleMessage("Регистрация пользователя"),
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),

View File

@@ -2169,6 +2169,166 @@ class S {
args: [],
);
}
/// `Данные пользователя`
String get user_data {
return Intl.message(
'Данные пользователя',
name: 'user_data',
desc: '',
args: [],
);
}
/// `Общая информация`
String get general_info {
return Intl.message(
'Общая информация',
name: 'general_info',
desc: '',
args: [],
);
}
/// `Пол`
String get sex {
return Intl.message(
'Пол',
name: 'sex',
desc: '',
args: [],
);
}
/// `Физическая форма`
String get physical_fitness {
return Intl.message(
'Физическая форма',
name: 'physical_fitness',
desc: '',
args: [],
);
}
/// `Рост`
String get height {
return Intl.message(
'Рост',
name: 'height',
desc: '',
args: [],
);
}
/// `Давление`
String get pressure {
return Intl.message(
'Давление',
name: 'pressure',
desc: '',
args: [],
);
}
/// `Верхнее`
String get upper {
return Intl.message(
'Верхнее',
name: 'upper',
desc: '',
args: [],
);
}
/// `Нижнее`
String get lower {
return Intl.message(
'Нижнее',
name: 'lower',
desc: '',
args: [],
);
}
/// `Склонность к гипотонии`
String get has_hypo {
return Intl.message(
'Склонность к гипотонии',
name: 'has_hypo',
desc: '',
args: [],
);
}
/// `Склонность к гипертонии`
String get has_hyper {
return Intl.message(
'Склонность к гипертонии',
name: 'has_hyper',
desc: '',
args: [],
);
}
/// `Прочая информация`
String get other_info {
return Intl.message(
'Прочая информация',
name: 'other_info',
desc: '',
args: [],
);
}
/// `Наличие аллергии`
String get has_alergy {
return Intl.message(
'Наличие аллергии',
name: 'has_alergy',
desc: '',
args: [],
);
}
/// `Принимает лекарства`
String get takes_pills {
return Intl.message(
'Принимает лекарства',
name: 'takes_pills',
desc: '',
args: [],
);
}
/// `Спортивные увлечения`
String get sport_hobbies {
return Intl.message(
'Спортивные увлечения',
name: 'sport_hobbies',
desc: '',
args: [],
);
}
/// `Любимые продукты`
String get liked_groceries {
return Intl.message(
'Любимые продукты',
name: 'liked_groceries',
desc: '',
args: [],
);
}
/// `Не любимые продукты`
String get not_liked_groceries {
return Intl.message(
'Не любимые продукты',
name: 'not_liked_groceries',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@@ -210,5 +210,21 @@
"diet": "Диета",
"deleted": "Удалена",
"my_plans": "Мои планы",
"from": "от"
"from": "от",
"user_data": "Данные пользователя",
"general_info": "Общая информация",
"sex": "Пол",
"physical_fitness": "Физическая форма",
"height": "Рост",
"pressure": "Давление",
"upper": "Верхнее",
"lower": "Нижнее",
"has_hypo": "Склонность к гипотонии",
"has_hyper": "Склонность к гипертонии",
"other_info": "Прочая информация",
"has_alergy": "Наличие аллергии",
"takes_pills": "Принимает лекарства",
"sport_hobbies": "Спортивные увлечения",
"liked_groceries": "Любимые продукты",
"not_liked_groceries": "Не любимые продукты"
}

View File

@@ -197,5 +197,18 @@
"wellness_type": "Улучшение самочувствия",
"wellness_type_desc": "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
"eating_behavior_type": "Формирование пищевого поведения",
"eating_behavior_type_desc": "Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;"
"eating_behavior_type_desc": "Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;",
"price": "Цена",
"my_diets": "Мои диеты",
"published": "Опубликованные",
"drafted": "Черновики",
"personal": "Персональные",
"edit": "Редактировать",
"toOffer": "Предложить",
"removeFromActive": "Снять с публикации",
"diet": "Диета",
"deleted": "Удалена",
"my_plans": "Мои планы",
"from": "от",
"user_data": "Данные пользователя"
}