feat(profile): Replaced the diet and calendar icons, reduced the height of the bottom nav bar, added the first version of the measurements graph, added the time of the chat message and changed the design slightly

This commit is contained in:
mso7nueh
2024-08-27 16:59:37 +03:00
parent ec19861eb2
commit 7e919d8f4c
18 changed files with 1102 additions and 138 deletions

29
assets/icons/calendar.svg Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW X8 -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="500px" height="500px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 5000 5000"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#43A6F2;fill-rule:nonzero}
]]>
</style>
</defs>
<g id="Слой_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<g id="_2067874566720">
<path class="fil0" d="M5000 2768l0 1308c0,254 -103,484 -269,652 -166,168 -395,272 -647,272l-3168 0c-252,0 -481,-104 -647,-272 -166,-168 -269,-399 -269,-652l0 -2682c0,-254 108,-501 278,-682 169,-180 401,-298 653,-298l3168 0c251,0 474,117 636,296 164,182 265,430 265,684l0 1374zm-350 1308l0 -2682c0,-168 -66,-331 -174,-450 -98,-109 -231,-180 -377,-180l-3168 0c-151,0 -292,74 -398,187 -112,119 -183,279 -183,443l0 2682c0,159 64,302 167,406 102,104 244,168 399,168l3168 0c155,0 297,-64 400,-168 102,-104 166,-247 166,-406z"/>
<path class="fil0" d="M2325 175c0,-97 78,-175 175,-175 97,0 175,78 175,175l0 829c0,97 -78,175 -175,175 -97,0 -175,-78 -175,-175l0 -829z"/>
<path class="fil0" d="M1163 175c0,-97 78,-175 175,-175 96,0 175,78 175,175l0 829c0,97 -79,175 -175,175 -97,0 -175,-78 -175,-175l0 -829z"/>
<path class="fil0" d="M3487 175c0,-97 79,-175 175,-175 97,0 175,78 175,175l0 829c0,97 -78,175 -175,175 -96,0 -175,-78 -175,-175l0 -829z"/>
<path class="fil0" d="M175 1746c-96,0 -174,-78 -174,-174 0,-96 78,-174 174,-174l4650 0c96,0 174,78 174,174 0,96 -78,174 -174,174l-4650 0z"/>
<path class="fil0" d="M999 2084l406 0c85,0 163,34 219,91l1 0c56,56 91,134 91,219l0 406c0,85 -35,162 -91,219l-1 0c-56,56 -134,91 -219,91l-406 0c-85,0 -162,-35 -218,-91l-1 0c-56,-57 -91,-134 -91,-219l0 -406c0,-85 35,-163 91,-219l1 0c56,-56 133,-91 218,-91zm367 350l-327 0 0 326 327 0 0 -326z"/>
<path class="fil0" d="M2297 2084l406 0c85,0 162,35 219,91l0 0c56,56 91,134 91,219l0 406c0,85 -35,162 -91,219l0 0c-57,56 -134,91 -219,91l-406 0c-85,0 -162,-35 -219,-91l0 0c-56,-57 -91,-134 -91,-219l0 -406c0,-85 35,-163 91,-219l0 0c57,-56 134,-91 219,-91zm366 350l-326 0 0 326 326 0 0 -326z"/>
<path class="fil0" d="M3961 2434l-327 0 0 326 327 0 0 -326zm-366 -350l406 0c85,0 162,35 218,91l1 0c56,56 91,134 91,219l0 406c0,85 -35,162 -91,219l-1 0c-56,56 -133,91 -218,91l-406 0c-85,0 -163,-35 -219,-91l-1 0c-56,-57 -91,-134 -91,-219l0 -406c0,-85 35,-163 91,-219l1 0c56,-57 134,-91 219,-91z"/>
<path class="fil0" d="M999 3287l406 0c85,0 163,35 219,91l1 0c56,56 91,133 91,219l0 406c0,85 -35,162 -91,219l-1 0c-56,56 -134,91 -219,91l-406 0c-85,0 -162,-35 -218,-91l-1 0c-56,-57 -91,-134 -91,-219l0 -406c0,-86 35,-163 91,-219l1 0c56,-56 133,-91 218,-91zm367 350l-327 0 0 326 327 0 0 -326z"/>
<path class="fil0" d="M2297 3287l406 0c85,0 162,35 219,91l0 0c56,56 91,133 91,219l0 406c0,85 -35,162 -91,219l0 0c-57,56 -134,91 -219,91l-406 0c-85,0 -162,-35 -219,-91l0 0c-56,-57 -91,-134 -91,-219l0 -406c0,-86 35,-163 91,-219l0 0c57,-56 134,-91 219,-91zm366 350l-326 0 0 326 326 0 0 -326z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

24
assets/icons/diets.svg Normal file
View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW X8 -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="500px" height="500px" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 5000 5000"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#43A6F2;fill-rule:nonzero}
]]>
</style>
</defs>
<g id="Слой_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<g id="_2067876093536">
<path class="fil0" d="M3543 5000c-497,0 -841,-167 -1073,-421 -283,-312 -384,-748 -384,-1167 0,-316 76,-588 230,-782 154,-193 377,-305 673,-305 207,0 319,33 415,60 47,14 88,26 139,26 51,0 92,-12 139,-26 95,-27 208,-60 415,-60 296,0 519,112 672,305 155,194 231,466 231,782 0,419 -101,855 -385,1167 -231,254 -575,421 -1072,421zm-814 -657c168,186 428,307 814,307 386,0 646,-121 814,-307 216,-237 293,-588 293,-931 0,-238 -51,-435 -154,-565 -87,-109 -219,-172 -399,-172 -162,0 -246,24 -318,45 -75,22 -140,41 -236,41 -96,0 -161,-19 -236,-41 -72,-21 -156,-45 -318,-45 -180,0 -312,63 -399,172 -104,130 -154,327 -154,565 0,343 77,694 293,931z"/>
<path class="fil0" d="M3843 2315c227,31 385,-8 497,-111 115,-107 197,-285 262,-527 -233,21 -413,64 -536,152 -124,90 -198,241 -223,486zm733 146c-224,207 -525,267 -956,167l0 0c-79,-18 -137,-90 -135,-174 11,-456 137,-734 378,-908 227,-164 542,-216 952,-232 15,0 30,1 45,4 94,19 155,111 136,205 -88,429 -210,744 -420,938z"/>
<path class="fil0" d="M3741 2500c0,97 -78,175 -175,175 -96,0 -175,-78 -175,-175l0 -1779c0,-102 -41,-194 -109,-262 -67,-67 -160,-109 -262,-109l-2306 0c-102,0 -195,42 -262,109 -67,67 -109,160 -109,262l0 2307c0,102 42,194 109,262 67,67 160,109 262,109l1552 0c97,0 175,78 175,175 0,96 -78,175 -175,175l-1552 0c-199,0 -379,-81 -510,-212 -130,-130 -211,-311 -211,-509l0 -2307c0,-198 81,-379 211,-509 131,-131 311,-212 510,-212l2306 0c199,0 379,81 510,212 130,130 211,311 211,509l0 1779z"/>
<path class="fil0" d="M1004 1118c-77,44 -106,132 -99,220 3,42 14,84 31,121 16,35 38,65 64,87 39,35 93,48 157,20l34 -14c61,-27 122,-53 191,-75 162,-52 331,-78 497,-78 167,0 335,26 498,78 68,22 129,48 191,75l33 14c59,26 115,10 156,-28 26,-23 48,-53 63,-87 17,-35 27,-74 30,-114 5,-81 -27,-165 -113,-215 -135,-67 -276,-117 -422,-151 -146,-34 -296,-52 -448,-52 -154,0 -307,13 -453,44 -143,31 -281,80 -410,155zm-448 246c-16,-210 63,-427 273,-549 164,-94 336,-156 513,-194 173,-37 350,-52 525,-52 177,0 354,21 527,61 172,40 339,100 500,180l8 4c226,126 309,339 296,545 -5,83 -27,165 -62,240 -36,77 -85,145 -145,199 -137,124 -324,176 -528,88l-33 -14c-54,-23 -107,-46 -159,-63 -125,-40 -258,-60 -392,-60 -134,0 -267,20 -392,60 -52,17 -105,40 -158,63l-34 14c-206,90 -389,41 -525,-77 -63,-55 -113,-125 -150,-203 -35,-75 -57,-159 -64,-242z"/>
<path class="fil0" d="M1596 1577c36,89 -6,191 -95,227 -89,37 -191,-6 -228,-95l-138 -334c-37,-89 6,-191 95,-227 89,-37 191,6 228,95l138 334z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -24,7 +24,6 @@ import 'package:eatvio_app/presentation/diets/diet_select_screen/diet_select_scr
import 'package:eatvio_app/presentation/feed/blog_post_edit_screen/blog_post_edit_screen.dart';
import 'package:eatvio_app/presentation/glossary/glossary_screen/glossary_screen.dart';
import 'package:eatvio_app/presentation/plans/plan_select_screen/plan_select_screen.dart';
import 'package:eatvio_app/presentation/profile/my_profile_screen/my_profile_screen.dart';
import 'package:eatvio_app/presentation/profile/my_profile_screen/my_settings_screen.dart';
import 'package:eatvio_app/presentation/recipe/recipe_select_screen/recipe_select_screen.dart';
import 'package:flutter/material.dart';
@@ -62,7 +61,7 @@ class AppRouter {
},
routes: [
GoRoute(
pageBuilder: (context, state) => NoTransitionPage(child: MyProfileScreen()),
pageBuilder: (context, state) => NoTransitionPage(child: ProfileScreen()),
path: '/my-profile-screen',
name: 'myProfileScreen',
redirect: (context, state) async {

View File

@@ -0,0 +1,22 @@
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:flutter_bloc/flutter_bloc.dart';
class ProfileAvatarCubit extends Cubit<ProfileAvatarState> {
final ProfileRepository profileRepository;
ProfileAvatarCubit({
required this.profileRepository,
}) : super(const ProfileAvatarState.loading());
getMyProfile() async {
try {
emit(ProfileAvatarState.loaded(
profile: await profileRepository.getMyProfile(),
));
} catch (e) {
emit(ProfileAvatarState.error(errorMessage: e.toString()));
print(e);
}
}
}

View File

@@ -0,0 +1,19 @@
import 'package:eatvio_app/features/profile/models/profile_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'profile_avatar_state.freezed.dart';
@freezed
abstract class ProfileAvatarState with _$ProfileAvatarState {
const factory ProfileAvatarState() = _ProfileAvatarState;
const factory ProfileAvatarState.loading() = ProfileAvatarStateLoading;
const factory ProfileAvatarState.loaded({
required ProfileModel profile,
}) = ProfileAvatarStateLoaded;
const factory ProfileAvatarState.error({
required String errorMessage,
}) = ProfileAvatarStateError;
}

View File

@@ -0,0 +1,630 @@
// 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 'profile_avatar_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 _$ProfileAvatarState {
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ProfileModel profile) loaded,
required TResult Function(String errorMessage) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ProfileModel profile)? loaded,
TResult? Function(String errorMessage)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ProfileModel profile)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ProfileAvatarState value) $default, {
required TResult Function(ProfileAvatarStateLoading value) loading,
required TResult Function(ProfileAvatarStateLoaded value) loaded,
required TResult Function(ProfileAvatarStateError value) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ProfileAvatarState value)? $default, {
TResult? Function(ProfileAvatarStateLoading value)? loading,
TResult? Function(ProfileAvatarStateLoaded value)? loaded,
TResult? Function(ProfileAvatarStateError value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ProfileAvatarState value)? $default, {
TResult Function(ProfileAvatarStateLoading value)? loading,
TResult Function(ProfileAvatarStateLoaded value)? loaded,
TResult Function(ProfileAvatarStateError value)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProfileAvatarStateCopyWith<$Res> {
factory $ProfileAvatarStateCopyWith(
ProfileAvatarState value, $Res Function(ProfileAvatarState) then) =
_$ProfileAvatarStateCopyWithImpl<$Res, ProfileAvatarState>;
}
/// @nodoc
class _$ProfileAvatarStateCopyWithImpl<$Res, $Val extends ProfileAvatarState>
implements $ProfileAvatarStateCopyWith<$Res> {
_$ProfileAvatarStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
}
/// @nodoc
abstract class _$$ProfileAvatarStateImplCopyWith<$Res> {
factory _$$ProfileAvatarStateImplCopyWith(_$ProfileAvatarStateImpl value,
$Res Function(_$ProfileAvatarStateImpl) then) =
__$$ProfileAvatarStateImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$ProfileAvatarStateImplCopyWithImpl<$Res>
extends _$ProfileAvatarStateCopyWithImpl<$Res, _$ProfileAvatarStateImpl>
implements _$$ProfileAvatarStateImplCopyWith<$Res> {
__$$ProfileAvatarStateImplCopyWithImpl(_$ProfileAvatarStateImpl _value,
$Res Function(_$ProfileAvatarStateImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$ProfileAvatarStateImpl implements _ProfileAvatarState {
const _$ProfileAvatarStateImpl();
@override
String toString() {
return 'ProfileAvatarState()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$ProfileAvatarStateImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ProfileModel profile) loaded,
required TResult Function(String errorMessage) error,
}) {
return $default();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ProfileModel profile)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return $default?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ProfileModel profile)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ProfileAvatarState value) $default, {
required TResult Function(ProfileAvatarStateLoading value) loading,
required TResult Function(ProfileAvatarStateLoaded value) loaded,
required TResult Function(ProfileAvatarStateError value) error,
}) {
return $default(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ProfileAvatarState value)? $default, {
TResult? Function(ProfileAvatarStateLoading value)? loading,
TResult? Function(ProfileAvatarStateLoaded value)? loaded,
TResult? Function(ProfileAvatarStateError value)? error,
}) {
return $default?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ProfileAvatarState value)? $default, {
TResult Function(ProfileAvatarStateLoading value)? loading,
TResult Function(ProfileAvatarStateLoaded value)? loaded,
TResult Function(ProfileAvatarStateError value)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default(this);
}
return orElse();
}
}
abstract class _ProfileAvatarState implements ProfileAvatarState {
const factory _ProfileAvatarState() = _$ProfileAvatarStateImpl;
}
/// @nodoc
abstract class _$$ProfileAvatarStateLoadingImplCopyWith<$Res> {
factory _$$ProfileAvatarStateLoadingImplCopyWith(
_$ProfileAvatarStateLoadingImpl value,
$Res Function(_$ProfileAvatarStateLoadingImpl) then) =
__$$ProfileAvatarStateLoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$ProfileAvatarStateLoadingImplCopyWithImpl<$Res>
extends _$ProfileAvatarStateCopyWithImpl<$Res,
_$ProfileAvatarStateLoadingImpl>
implements _$$ProfileAvatarStateLoadingImplCopyWith<$Res> {
__$$ProfileAvatarStateLoadingImplCopyWithImpl(
_$ProfileAvatarStateLoadingImpl _value,
$Res Function(_$ProfileAvatarStateLoadingImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$ProfileAvatarStateLoadingImpl implements ProfileAvatarStateLoading {
const _$ProfileAvatarStateLoadingImpl();
@override
String toString() {
return 'ProfileAvatarState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ProfileAvatarStateLoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ProfileModel profile) loaded,
required TResult Function(String errorMessage) error,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ProfileModel profile)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ProfileModel profile)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ProfileAvatarState value) $default, {
required TResult Function(ProfileAvatarStateLoading value) loading,
required TResult Function(ProfileAvatarStateLoaded value) loaded,
required TResult Function(ProfileAvatarStateError value) error,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ProfileAvatarState value)? $default, {
TResult? Function(ProfileAvatarStateLoading value)? loading,
TResult? Function(ProfileAvatarStateLoaded value)? loaded,
TResult? Function(ProfileAvatarStateError value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ProfileAvatarState value)? $default, {
TResult Function(ProfileAvatarStateLoading value)? loading,
TResult Function(ProfileAvatarStateLoaded value)? loaded,
TResult Function(ProfileAvatarStateError value)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class ProfileAvatarStateLoading implements ProfileAvatarState {
const factory ProfileAvatarStateLoading() = _$ProfileAvatarStateLoadingImpl;
}
/// @nodoc
abstract class _$$ProfileAvatarStateLoadedImplCopyWith<$Res> {
factory _$$ProfileAvatarStateLoadedImplCopyWith(
_$ProfileAvatarStateLoadedImpl value,
$Res Function(_$ProfileAvatarStateLoadedImpl) then) =
__$$ProfileAvatarStateLoadedImplCopyWithImpl<$Res>;
@useResult
$Res call({ProfileModel profile});
$ProfileModelCopyWith<$Res> get profile;
}
/// @nodoc
class __$$ProfileAvatarStateLoadedImplCopyWithImpl<$Res>
extends _$ProfileAvatarStateCopyWithImpl<$Res,
_$ProfileAvatarStateLoadedImpl>
implements _$$ProfileAvatarStateLoadedImplCopyWith<$Res> {
__$$ProfileAvatarStateLoadedImplCopyWithImpl(
_$ProfileAvatarStateLoadedImpl _value,
$Res Function(_$ProfileAvatarStateLoadedImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? profile = null,
}) {
return _then(_$ProfileAvatarStateLoadedImpl(
profile: null == profile
? _value.profile
: profile // ignore: cast_nullable_to_non_nullable
as ProfileModel,
));
}
@override
@pragma('vm:prefer-inline')
$ProfileModelCopyWith<$Res> get profile {
return $ProfileModelCopyWith<$Res>(_value.profile, (value) {
return _then(_value.copyWith(profile: value));
});
}
}
/// @nodoc
class _$ProfileAvatarStateLoadedImpl implements ProfileAvatarStateLoaded {
const _$ProfileAvatarStateLoadedImpl({required this.profile});
@override
final ProfileModel profile;
@override
String toString() {
return 'ProfileAvatarState.loaded(profile: $profile)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ProfileAvatarStateLoadedImpl &&
(identical(other.profile, profile) || other.profile == profile));
}
@override
int get hashCode => Object.hash(runtimeType, profile);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ProfileAvatarStateLoadedImplCopyWith<_$ProfileAvatarStateLoadedImpl>
get copyWith => __$$ProfileAvatarStateLoadedImplCopyWithImpl<
_$ProfileAvatarStateLoadedImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ProfileModel profile) loaded,
required TResult Function(String errorMessage) error,
}) {
return loaded(profile);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ProfileModel profile)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loaded?.call(profile);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ProfileModel profile)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(profile);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ProfileAvatarState value) $default, {
required TResult Function(ProfileAvatarStateLoading value) loading,
required TResult Function(ProfileAvatarStateLoaded value) loaded,
required TResult Function(ProfileAvatarStateError value) error,
}) {
return loaded(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ProfileAvatarState value)? $default, {
TResult? Function(ProfileAvatarStateLoading value)? loading,
TResult? Function(ProfileAvatarStateLoaded value)? loaded,
TResult? Function(ProfileAvatarStateError value)? error,
}) {
return loaded?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ProfileAvatarState value)? $default, {
TResult Function(ProfileAvatarStateLoading value)? loading,
TResult Function(ProfileAvatarStateLoaded value)? loaded,
TResult Function(ProfileAvatarStateError value)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(this);
}
return orElse();
}
}
abstract class ProfileAvatarStateLoaded implements ProfileAvatarState {
const factory ProfileAvatarStateLoaded(
{required final ProfileModel profile}) = _$ProfileAvatarStateLoadedImpl;
ProfileModel get profile;
@JsonKey(ignore: true)
_$$ProfileAvatarStateLoadedImplCopyWith<_$ProfileAvatarStateLoadedImpl>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$ProfileAvatarStateErrorImplCopyWith<$Res> {
factory _$$ProfileAvatarStateErrorImplCopyWith(
_$ProfileAvatarStateErrorImpl value,
$Res Function(_$ProfileAvatarStateErrorImpl) then) =
__$$ProfileAvatarStateErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String errorMessage});
}
/// @nodoc
class __$$ProfileAvatarStateErrorImplCopyWithImpl<$Res>
extends _$ProfileAvatarStateCopyWithImpl<$Res,
_$ProfileAvatarStateErrorImpl>
implements _$$ProfileAvatarStateErrorImplCopyWith<$Res> {
__$$ProfileAvatarStateErrorImplCopyWithImpl(
_$ProfileAvatarStateErrorImpl _value,
$Res Function(_$ProfileAvatarStateErrorImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? errorMessage = null,
}) {
return _then(_$ProfileAvatarStateErrorImpl(
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$ProfileAvatarStateErrorImpl implements ProfileAvatarStateError {
const _$ProfileAvatarStateErrorImpl({required this.errorMessage});
@override
final String errorMessage;
@override
String toString() {
return 'ProfileAvatarState.error(errorMessage: $errorMessage)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ProfileAvatarStateErrorImpl &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(runtimeType, errorMessage);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ProfileAvatarStateErrorImplCopyWith<_$ProfileAvatarStateErrorImpl>
get copyWith => __$$ProfileAvatarStateErrorImplCopyWithImpl<
_$ProfileAvatarStateErrorImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(ProfileModel profile) loaded,
required TResult Function(String errorMessage) error,
}) {
return error(errorMessage);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(ProfileModel profile)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return error?.call(errorMessage);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(ProfileModel profile)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(errorMessage);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_ProfileAvatarState value) $default, {
required TResult Function(ProfileAvatarStateLoading value) loading,
required TResult Function(ProfileAvatarStateLoaded value) loaded,
required TResult Function(ProfileAvatarStateError value) error,
}) {
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_ProfileAvatarState value)? $default, {
TResult? Function(ProfileAvatarStateLoading value)? loading,
TResult? Function(ProfileAvatarStateLoaded value)? loaded,
TResult? Function(ProfileAvatarStateError value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_ProfileAvatarState value)? $default, {
TResult Function(ProfileAvatarStateLoading value)? loading,
TResult Function(ProfileAvatarStateLoaded value)? loaded,
TResult Function(ProfileAvatarStateError value)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(this);
}
return orElse();
}
}
abstract class ProfileAvatarStateError implements ProfileAvatarState {
const factory ProfileAvatarStateError({required final String errorMessage}) =
_$ProfileAvatarStateErrorImpl;
String get errorMessage;
@JsonKey(ignore: true)
_$$ProfileAvatarStateErrorImplCopyWith<_$ProfileAvatarStateErrorImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@@ -4,6 +4,8 @@ import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_state.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_cubit.dart';
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/widgets/custom_navigation_menu.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
@@ -68,119 +70,154 @@ class _BottomNavigationBarWidgetState extends State<BottomNavigationBarWidget> {
Widget build(BuildContext context) {
return Scaffold(
body: widget.child,
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
selectedFontSize: 12,
unselectedFontSize: 12,
selectedItemColor: appTheme.blueA400,
currentIndex: currentBottomNavBarIndex,
items: [
BottomNavigationBarItem(
label: '',
icon: SvgPicture.asset(
ImageConstant.imgLogo,
),
),
BottomNavigationBarItem(
label: 'Лента',
icon: SvgPicture.asset(
colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
width: 24,
height: 24,
ImageConstant.icnFeed,
),
activeIcon: SvgPicture.asset(
ImageConstant.icnFeed,
width: 24,
height: 24,
colorFilter: ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
bottomNavigationBar: SizedBox(
height: 58,
child: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
selectedFontSize: 10,
unselectedFontSize: 10,
selectedItemColor: appTheme.blueA400,
currentIndex: currentBottomNavBarIndex,
items: [
BottomNavigationBarItem(
label: '',
icon: SvgPicture.asset(
ImageConstant.imgLogo,
height: 32,
),
),
),
BottomNavigationBarItem(
label: "diary".tr,
icon: SvgPicture.asset(
colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
ImageConstant.icnDiary,
width: 24,
height: 24,
),
activeIcon: SvgPicture.asset(
ImageConstant.icnDiary,
width: 24,
height: 24,
colorFilter: ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
BottomNavigationBarItem(
label: 'Лента',
icon: Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SvgPicture.asset(
colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
width: 20,
height: 20,
ImageConstant.icnFeed,
),
),
activeIcon: Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SvgPicture.asset(
ImageConstant.icnFeed,
width: 20,
height: 20,
colorFilter: ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
),
),
),
),
),
BottomNavigationBarItem(
label: "chat".tr,
icon: BlocBuilder<NewMessagesCubit, NewMessagesState>(
builder: (BuildContext context, NewMessagesState state) {
return badges.Badge(
position: badges.BadgePosition.topEnd(),
badgeContent: Text(
(state is NewMessagesStateLoaded) ? state.messagesCount.toString() : '0',
style: TextStyle(
color: Colors.white,
BottomNavigationBarItem(
label: "diary".tr,
icon: Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SvgPicture.asset(
colorFilter: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
ImageConstant.icnDiary,
width: 20,
height: 20,
),
),
activeIcon: Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SvgPicture.asset(
ImageConstant.icnDiary,
width: 20,
height: 20,
colorFilter: ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
),
),
),
),
BottomNavigationBarItem(
label: "chat".tr,
icon: BlocBuilder<NewMessagesCubit, NewMessagesState>(
builder: (BuildContext context, NewMessagesState state) {
return badges.Badge(
position: badges.BadgePosition.topEnd(),
badgeAnimation: badges.BadgeAnimation.fade(),
badgeContent: Text(
(state is NewMessagesStateLoaded) ? state.messagesCount.toString() : '0',
style: TextStyle(
color: Colors.white,
fontSize: 8,
),
),
),
child: SvgPicture.asset(
ImageConstant.icnChat,
width: 24,
height: 24,
colorFilter: currentBottomNavBarIndex == 3
? ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
)
: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
),
);
},
),
),
BottomNavigationBarItem(
label: '',
icon: BlocBuilder<NotificationsCubit, NotificationsState>(
builder: (BuildContext context, NotificationsState state) {
return badges.Badge(
position: badges.BadgePosition.topEnd(),
badgeContent: Text(
(state is NotificationsStateLoaded) ? state.notificationsCount.toString() : '0',
style: TextStyle(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SvgPicture.asset(
ImageConstant.icnChat,
width: 20,
height: 20,
colorFilter: currentBottomNavBarIndex == 3
? ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
)
: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
),
),
),
child: SvgPicture.asset(
ImageConstant.icnBell,
colorFilter: currentBottomNavBarIndex == 4
? ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
)
: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
width: 24,
height: 24,
),
);
},
);
},
),
),
),
BottomNavigationBarItem(
label: '',
icon: Image.asset(
ImageConstant.imgEllipse1,
width: 32,
height: 32,
BottomNavigationBarItem(
label: 'Уведомления',
icon: BlocBuilder<NotificationsCubit, NotificationsState>(
builder: (BuildContext context, NotificationsState state) {
return badges.Badge(
position: badges.BadgePosition.topEnd(),
badgeAnimation: badges.BadgeAnimation.fade(),
badgeContent: Text(
(state is NotificationsStateLoaded) ? state.notificationsCount.toString() : '0',
style: TextStyle(
color: Colors.white,
fontSize: 8,
),
),
child: Padding(
padding: const EdgeInsets.only(bottom: 2),
child: SvgPicture.asset(
ImageConstant.icnBell,
colorFilter: currentBottomNavBarIndex == 4
? ColorFilter.mode(
appTheme.blueA400,
BlendMode.srcIn,
)
: ColorFilter.mode(Colors.grey, BlendMode.srcIn),
width: 20,
height: 20,
),
),
);
},
),
),
),
],
BottomNavigationBarItem(
label: '',
icon: BlocBuilder<ProfileAvatarCubit, ProfileAvatarState>(
builder: (BuildContext context, ProfileAvatarState state) {
if (state is ProfileAvatarStateLoaded && state.profile.user.profilePhotoUrl.isNotEmpty) {
return CircleAvatar(
backgroundImage: NetworkImage(state.profile.user.profilePhotoUrl),
radius: 16,
);
}
return CircleAvatar(
radius: 16,
backgroundColor: Colors.black12,
);
},
),
),
],
),
),
);
}

View File

@@ -1,8 +1,7 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:dismissible_page/dismissible_page.dart';
import 'package:eatvio_app/core/constants/constants.dart';
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
import 'package:eatvio_app/theme/app_decoration.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
@@ -29,12 +28,17 @@ class ChatBubbleWidget extends StatelessWidget {
child: DecoratedBox(
decoration: BoxDecoration(
color: isCurrentUser ? Color(0xFF7F9CF5) : Colors.white,
borderRadius: BorderRadiusStyle.circleBorder17,
borderRadius: mediaData.length > 0
? BorderRadius.circular(24)
: BorderRadius.horizontal(
left: isCurrentUser ? Radius.circular(32) : Radius.circular(16),
right: isCurrentUser ? Radius.circular(16) : Radius.circular(24),
),
),
child: Padding(
padding: const EdgeInsets.all(12),
padding: mediaData.length > 0 ? EdgeInsets.all(8) : EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: isCurrentUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
if (mediaData.isNotEmpty)
CustomScrollView(
@@ -86,7 +90,7 @@ class ChatBubbleWidget extends StatelessWidget {
tag: baseUrl + '/storage/' + '${mediaData[index]}',
transitionOnUserGestures: true,
child: ClipRRect(
borderRadius: BorderRadiusStyle.roundedBorder8,
borderRadius: BorderRadius.circular(16),
child: CachedNetworkImage(
imageUrl: baseUrl + '/storage/' + '${mediaData[index]}',
),
@@ -103,10 +107,17 @@ class ChatBubbleWidget extends StatelessWidget {
if (text.isNotEmpty)
Text(
text,
style: TextStyle(
color: isCurrentUser ? Colors.white : Color(0xFF323F4B),
),
style: TextStyle(color: isCurrentUser ? Colors.white : Color(0xFF323F4B), height: 1),
),
SizedBox(height: 4),
Text(
DateTime.parse(sendTime).format('hh:mm'),
style: TextStyle(
color: isCurrentUser ? Colors.white.withOpacity(0.4) : Color(0xFF323F4B).withOpacity(0.4),
height: 1,
fontSize: 10,
),
),
],
),
),

View File

@@ -1,5 +1,4 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_select_cubit/chat_select_cubit.dart';
import 'package:flutter/material.dart';
class ChatSearchBarWidget extends StatelessWidget {

View File

@@ -30,4 +30,20 @@ class ProfileCubit extends Cubit<ProfileState> {
print(e);
}
}
addCircumference({
required int chestCircumference,
required int waistCircumference,
required int hipCircumference,
}) async {
try {
await profileRepository.addCircumference(
chestCircumference: chestCircumference,
waistCircumference: waistCircumference,
hipCircumference: hipCircumference,
);
} catch (e) {
emit(ProfileState.error(errorMessage: e.toString()));
}
}
}

View File

@@ -1,46 +1,84 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/profile/models/profile_model.dart';
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart';
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_state.dart';
import 'package:eatvio_app/locator_service.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class ProfileScreen extends StatelessWidget {
final Author author;
class ProfileScreen extends StatefulWidget {
final Author? author;
const ProfileScreen({super.key, required this.author});
const ProfileScreen({super.key, this.author});
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
List<Circumference> chartData = [];
@override
Widget build(BuildContext context) {
return BlocProvider<ProfileCubit>(
create: (BuildContext context) => sl<ProfileCubit>()..getProfileBySlug(author.authorSlug),
create: (BuildContext context) {
if (widget.author == null)
return sl<ProfileCubit>()..getMyProfile();
else
return sl<ProfileCubit>()..getProfileBySlug(widget.author!.authorSlug);
},
child: BlocBuilder<ProfileCubit, ProfileState>(
builder: (BuildContext context, ProfileState state) {
if (state is ProfileStateLoaded) {
chartData = state.profile.circumferences;
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
state.profile.user.name,
style: TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.w400,
height: 1,
),
),
centerTitle: false,
title: Text(state.profile.user.name),
),
body: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
Padding(
padding: const EdgeInsets.only(left: 16, bottom: 32),
child: CircleAvatar(
maxRadius: 128,
minRadius: 128,
radius: 32,
backgroundImage: NetworkImage(state.profile.user.profilePhotoUrl),
),
),
SfCartesianChart(
margin: EdgeInsets.zero,
enableAxisAnimation: true,
enableSideBySideSeriesPlacement: true,
legend: const Legend(
isVisible: true,
opacity: 0.7,
position: LegendPosition.bottom,
),
plotAreaBorderWidth: 0,
trackballBehavior: TrackballBehavior(
enable: true,
activationMode: ActivationMode.singleTap,
),
primaryXAxis: DateTimeAxis(
dateFormat: DateFormat.MMMd('ru'),
axisLine: AxisLine(
width: 1,
),
),
primaryYAxis: NumericAxis(
labelFormat: '{value} см',
axisLine: AxisLine(
width: 1,
),
majorTickLines: MajorTickLines(size: 0),
),
series: _getSplineAreaSeries(),
tooltipBehavior: TooltipBehavior(enable: true),
),
],
),
),
@@ -67,4 +105,64 @@ class ProfileScreen extends StatelessWidget {
),
);
}
List<CartesianSeries<Circumference, DateTime>> _getSplineAreaSeries() {
final Color seriesColor1 = Colors.red;
final Color seriesColor2 = Colors.blue;
final Color seriesColor3 = Colors.green;
return <CartesianSeries<Circumference, DateTime>>[
SplineSeries<Circumference, DateTime>(
markerSettings: MarkerSettings(
isVisible: true,
color: seriesColor1,
height: 12,
width: 12,
),
dataLabelSettings: DataLabelSettings(
labelAlignment: ChartDataLabelAlignment.top,
isVisible: true,
),
dataSource: chartData,
color: seriesColor1,
name: 'Грудь',
xValueMapper: (Circumference value, int index) => value.createdAt,
yValueMapper: (Circumference value, int index) => value.chestCircumference,
),
SplineSeries<Circumference, DateTime>(
markerSettings: MarkerSettings(
isVisible: true,
color: seriesColor2,
height: 12,
width: 12,
),
dataLabelSettings: DataLabelSettings(
labelAlignment: ChartDataLabelAlignment.top,
isVisible: true,
),
dataSource: chartData,
color: seriesColor2,
name: 'Талия',
xValueMapper: (Circumference value, int index) => value.createdAt,
yValueMapper: (Circumference value, int index) => value.waistCircumference,
),
SplineSeries<Circumference, DateTime>(
markerSettings: MarkerSettings(
isVisible: true,
color: seriesColor3,
height: 12,
width: 12,
),
dataLabelSettings: DataLabelSettings(
labelAlignment: ChartDataLabelAlignment.top,
isVisible: true,
),
dataSource: chartData,
color: seriesColor3,
name: 'Бёдра',
xValueMapper: (Circumference value, int index) => value.createdAt,
yValueMapper: (Circumference value, int index) => value.hipCircumference,
),
];
}
}

View File

@@ -21,4 +21,22 @@ class ProfileRepository {
rethrow;
}
}
Future<Circumference> addCircumference({
required int chestCircumference,
required int waistCircumference,
required int hipCircumference,
}) async {
try {
return (await profileService.addCircumference(
chestCircumference: chestCircumference,
waistCircumference: waistCircumference,
hipCircumference: hipCircumference,
))
.values
.first;
} catch (e) {
rethrow;
}
}
}

View File

@@ -15,4 +15,11 @@ abstract class ProfileService {
@GET('/api/profile/index')
Future<ProfileModel> getMyProfile();
@POST('/api/profile/addCircumference')
Future<Map<String, Circumference>> addCircumference({
@Part(name: 'chest_circumference') required int chestCircumference,
@Part(name: 'waist_circumference') required int waistCircumference,
@Part(name: 'hip_circumference') required int hipCircumference,
});
}

View File

@@ -87,6 +87,56 @@ class _ProfileService implements ProfileService {
return _value;
}
@override
Future<Map<String, Circumference>> addCircumference({
required int chestCircumference,
required int waistCircumference,
required int hipCircumference,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = FormData();
_data.fields.add(MapEntry(
'chest_circumference',
chestCircumference.toString(),
));
_data.fields.add(MapEntry(
'waist_circumference',
waistCircumference.toString(),
));
_data.fields.add(MapEntry(
'hip_circumference',
hipCircumference.toString(),
));
final _options = _setStreamType<Map<String, Circumference>>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/profile/addCircumference',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late Map<String, Circumference> _value;
try {
_value = _result.data!.map((k, dynamic v) =>
MapEntry(k, Circumference.fromJson(v as Map<String, dynamic>)));
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
}
return _value;
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||

View File

@@ -3,6 +3,7 @@ import 'package:eatvio_app/core/constants/constants.dart';
import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.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/notifications_cubit/notifications_cubit.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
import 'package:eatvio_app/features/calendar/presentation/bloc/calendar_cubit.dart';
import 'package:eatvio_app/features/calendar/repositories/calendar_repository.dart';
import 'package:eatvio_app/features/calendar/services/calendar_service.dart';
@@ -45,6 +46,7 @@ Future<void> init() async {
sl.registerFactory<DiaryBloc>(() => DiaryBloc(diaryRepository: sl()));
sl.registerFactory<CalendarCubit>(() => CalendarCubit(calendarRepository: sl()));
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl()));
sl.registerFactory<ProfileAvatarCubit>(() => ProfileAvatarCubit(profileRepository: sl()));
sl.registerFactory<RecipeCreateCubit>(() => RecipeCreateCubit(recipeRepository: sl()));
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl()));
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl()));

View File

@@ -3,6 +3,7 @@ import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.dart';
import 'package:eatvio_app/core/initialization_cubit/initialization_state.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/notifications_cubit/notifications_cubit.dart';
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
import 'package:eatvio_app/features/calendar/presentation/bloc/calendar_cubit.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chat_select_cubit/chat_select_cubit.dart';
import 'package:eatvio_app/features/diary/presentation/bloc/diary_bloc.dart';
@@ -42,6 +43,7 @@ class MyApp extends StatelessWidget {
BlocProvider<InitializationCubit>(create: (context) => sl<InitializationCubit>()),
BlocProvider<NewMessagesCubit>(create: (context) => sl<NewMessagesCubit>()),
BlocProvider<NotificationsCubit>(create: (context) => sl<NotificationsCubit>()),
BlocProvider<ProfileAvatarCubit>(create: (context) => sl<ProfileAvatarCubit>()..getMyProfile()),
BlocProvider<FeedCubit>(create: (context) => sl<FeedCubit>()..loadFeedBlogPostList()),
BlocProvider<RecipesCubit>(create: (context) => sl<RecipesCubit>()..loadRecipesList()),
BlocProvider<DietsCubit>(create: (context) => sl<DietsCubit>()..loadDiets()),

View File

@@ -24,7 +24,7 @@ class CustomNavigationMenu extends StatelessWidget {
onTap: () => GoRouter.of(context).push('/recipe-select-screen'),
),
MenuItem(
icon: ImageConstant.icnVeggies,
icon: 'assets/icons/diets.svg',
text: 'Мои диеты',
onTap: () => GoRouter.of(context).push('/diet-select-screen'),
),
@@ -34,7 +34,7 @@ class CustomNavigationMenu extends StatelessWidget {
onTap: () => GoRouter.of(context).push('/plan-select-screen'),
),
MenuItem(
icon: ImageConstant.icnPlans,
icon: 'assets/icons/calendar.svg',
text: 'Календарь',
onTap: () => GoRouter.of(context).push('/calendar-screen'),
),

View File

@@ -42,7 +42,7 @@ dependencies:
badges: ^3.1.2
google_fonts: ^6.2.1
location: ^6.0.2
syncfusion_flutter_charts: ^26.2.10
syncfusion_flutter_charts: ^26.2.11
table_calendar: ^3.1.2
flutter_keyboard_visibility: ^6.0.0
share_plus: ^10.0.0
@@ -65,3 +65,4 @@ flutter:
- assets/
- assets/images/
- assets/audio/
- assets/icons/