forked from eatvio/eatvio_app
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:
29
assets/icons/calendar.svg
Normal file
29
assets/icons/calendar.svg
Normal 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
24
assets/icons/diets.svg
Normal 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 |
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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'),
|
||||
),
|
||||
|
||||
@@ -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/
|
||||
|
||||
Reference in New Issue
Block a user