forked from eatvio/eatvio_app
diet creation scrren is done
This commit is contained in:
@@ -27,6 +27,9 @@ class CommentsCubit extends Cubit<CommentsState> {
|
||||
case CommentSourceType.recipe:
|
||||
emit(CommentsState.loaded(comment: await feedRepository.getRecipesComments(id: id)));
|
||||
break;
|
||||
case CommentSourceType.plan:
|
||||
emit(CommentsState.loaded(comment: await feedRepository.getPlansComments(slug: id)));
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
emit(CommentsState.error(errorMessage: e.toString()));
|
||||
@@ -62,6 +65,13 @@ class CommentsCubit extends Cubit<CommentsState> {
|
||||
parentCommentId: parentCommentId,
|
||||
);
|
||||
break;
|
||||
case CommentSourceType.plan:
|
||||
await feedRepository.sendPlansComment(
|
||||
slug: id,
|
||||
commentText: commentText,
|
||||
parentCommentId: parentCommentId,
|
||||
);
|
||||
break;
|
||||
}
|
||||
getComments(id, commentSourceType);
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_state.dart';
|
||||
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||
|
||||
@@ -30,7 +32,9 @@ class PlansCubit extends Cubit<PlansState> {
|
||||
isLoading: false,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
} catch (e, stackTrace) {
|
||||
log(e.toString());
|
||||
log(stackTrace.toString());
|
||||
emit(state.copyWith(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/profile_cubit/profile_state.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class FeedProfileCubit extends Cubit<ProfileState> {
|
||||
final ProfileRepository profileRepository;
|
||||
FeedProfileCubit({required this.profileRepository}) : super(ProfileState(profile: null));
|
||||
|
||||
Future<void> getProfile() async {
|
||||
try {
|
||||
final profile = await profileRepository.getMyProfile();
|
||||
emit(state.copyWith(profile: profile));
|
||||
} catch (e, stackTrace) {
|
||||
log(e.toString(), stackTrace: stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'profile_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class ProfileState with _$ProfileState {
|
||||
|
||||
factory ProfileState({
|
||||
ProfileModel? profile,
|
||||
}) = _ProfileState;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// 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_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 _$ProfileState {
|
||||
ProfileModel? get profile => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ProfileState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ProfileStateCopyWith<ProfileState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ProfileStateCopyWith<$Res> {
|
||||
factory $ProfileStateCopyWith(
|
||||
ProfileState value, $Res Function(ProfileState) then) =
|
||||
_$ProfileStateCopyWithImpl<$Res, ProfileState>;
|
||||
@useResult
|
||||
$Res call({ProfileModel? profile});
|
||||
|
||||
$ProfileModelCopyWith<$Res>? get profile;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ProfileStateCopyWithImpl<$Res, $Val extends ProfileState>
|
||||
implements $ProfileStateCopyWith<$Res> {
|
||||
_$ProfileStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ProfileState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? profile = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
profile: freezed == profile
|
||||
? _value.profile
|
||||
: profile // ignore: cast_nullable_to_non_nullable
|
||||
as ProfileModel?,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of ProfileState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ProfileModelCopyWith<$Res>? get profile {
|
||||
if (_value.profile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ProfileModelCopyWith<$Res>(_value.profile!, (value) {
|
||||
return _then(_value.copyWith(profile: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ProfileStateImplCopyWith<$Res>
|
||||
implements $ProfileStateCopyWith<$Res> {
|
||||
factory _$$ProfileStateImplCopyWith(
|
||||
_$ProfileStateImpl value, $Res Function(_$ProfileStateImpl) then) =
|
||||
__$$ProfileStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({ProfileModel? profile});
|
||||
|
||||
@override
|
||||
$ProfileModelCopyWith<$Res>? get profile;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ProfileStateImplCopyWithImpl<$Res>
|
||||
extends _$ProfileStateCopyWithImpl<$Res, _$ProfileStateImpl>
|
||||
implements _$$ProfileStateImplCopyWith<$Res> {
|
||||
__$$ProfileStateImplCopyWithImpl(
|
||||
_$ProfileStateImpl _value, $Res Function(_$ProfileStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ProfileState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? profile = freezed,
|
||||
}) {
|
||||
return _then(_$ProfileStateImpl(
|
||||
profile: freezed == profile
|
||||
? _value.profile
|
||||
: profile // ignore: cast_nullable_to_non_nullable
|
||||
as ProfileModel?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ProfileStateImpl implements _ProfileState {
|
||||
_$ProfileStateImpl({this.profile});
|
||||
|
||||
@override
|
||||
final ProfileModel? profile;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProfileState(profile: $profile)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ProfileStateImpl &&
|
||||
(identical(other.profile, profile) || other.profile == profile));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, profile);
|
||||
|
||||
/// Create a copy of ProfileState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ProfileStateImplCopyWith<_$ProfileStateImpl> get copyWith =>
|
||||
__$$ProfileStateImplCopyWithImpl<_$ProfileStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _ProfileState implements ProfileState {
|
||||
factory _ProfileState({final ProfileModel? profile}) = _$ProfileStateImpl;
|
||||
|
||||
@override
|
||||
ProfileModel? get profile;
|
||||
|
||||
/// Create a copy of ProfileState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ProfileStateImplCopyWith<_$ProfileStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cub
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/profile_cubit/profile_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/profile_cubit/profile_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/blog_post_widget.dart';
|
||||
@@ -92,79 +94,94 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
floatingActionButton: _selectedChipIndex == 1
|
||||
? FloatingActionButton.small(
|
||||
heroTag: 'recipesTagsFilter',
|
||||
backgroundColor: appTheme.blueA400,
|
||||
shape: CircleBorder(),
|
||||
child: Icon(
|
||||
Icons.filter_list_rounded,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: () async {
|
||||
await showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
context: context,
|
||||
builder: (context) => TagsModalWidget(
|
||||
recipesCubit: recipesCubit,
|
||||
),
|
||||
);
|
||||
recipesCubit.loadRecipesList();
|
||||
},
|
||||
)
|
||||
: null,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: NestedScrollView(
|
||||
controller: switch (_selectedChipIndex) {
|
||||
0 => blogPostsScrollController,
|
||||
1 => recipesScrollController,
|
||||
2 => dietsScrollController,
|
||||
3 => plansScrollController,
|
||||
_ => blogPostsScrollController
|
||||
},
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverAppBar(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.white,
|
||||
automaticallyImplyLeading: false,
|
||||
stretchTriggerOffset: 1,
|
||||
floating: true,
|
||||
snap: true,
|
||||
scrolledUnderElevation: 0,
|
||||
bottom: _chipGroup(),
|
||||
title: Row(
|
||||
children: [
|
||||
_searchBar(),
|
||||
SizedBox(width: 12),
|
||||
_addItemButton(feedCubit),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
body: Builder(
|
||||
builder: (BuildContext context) {
|
||||
if (_selectedChipIndex == 0) {
|
||||
return _buildAllBlogPosts();
|
||||
} else if (_selectedChipIndex == 1) {
|
||||
return _buildAllRecipes();
|
||||
} else if (_selectedChipIndex == 2) {
|
||||
return _buildDiets();
|
||||
} else if (_selectedChipIndex == 3) {
|
||||
return _buildPlans();
|
||||
} else {
|
||||
return Center(child: Text(chipsLabelList[_selectedChipIndex]));
|
||||
}
|
||||
return BlocProvider(
|
||||
create: (context) => sl<FeedProfileCubit>()..getProfile(),
|
||||
child: Scaffold(
|
||||
floatingActionButton: _selectedChipIndex == 1
|
||||
? FloatingActionButton.small(
|
||||
heroTag: 'recipesTagsFilter',
|
||||
backgroundColor: appTheme.blueA400,
|
||||
shape: CircleBorder(),
|
||||
child: Icon(
|
||||
Icons.filter_list_rounded,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: () async {
|
||||
await showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
context: context,
|
||||
builder: (context) => TagsModalWidget(
|
||||
recipesCubit: recipesCubit,
|
||||
),
|
||||
);
|
||||
recipesCubit.loadRecipesList();
|
||||
},
|
||||
)
|
||||
: null,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: NestedScrollView(
|
||||
controller: switch (_selectedChipIndex) {
|
||||
0 => blogPostsScrollController,
|
||||
1 => recipesScrollController,
|
||||
2 => dietsScrollController,
|
||||
3 => plansScrollController,
|
||||
_ => blogPostsScrollController
|
||||
},
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
BlocBuilder<FeedProfileCubit, ProfileState>(
|
||||
builder: (context, state) {
|
||||
return SliverAppBar(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.white,
|
||||
automaticallyImplyLeading: false,
|
||||
stretchTriggerOffset: 1,
|
||||
floating: true,
|
||||
snap: true,
|
||||
scrolledUnderElevation: 0,
|
||||
bottom: _chipGroup(),
|
||||
title: Row(
|
||||
children: [
|
||||
_searchBar(),
|
||||
SizedBox(width: 12),
|
||||
switch (_selectedChipIndex) {
|
||||
2 => _addItemButton(
|
||||
onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null,
|
||||
),
|
||||
3 => _addItemButton(
|
||||
onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null,
|
||||
),
|
||||
_ => _addItemButton()
|
||||
},
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
},
|
||||
body: Builder(
|
||||
builder: (BuildContext context) {
|
||||
if (_selectedChipIndex == 0) {
|
||||
return _buildAllBlogPosts();
|
||||
} else if (_selectedChipIndex == 1) {
|
||||
return _buildAllRecipes();
|
||||
} else if (_selectedChipIndex == 2) {
|
||||
return _buildDiets();
|
||||
} else if (_selectedChipIndex == 3) {
|
||||
return _buildPlans();
|
||||
} else {
|
||||
return Center(child: Text(chipsLabelList[_selectedChipIndex]));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -435,20 +452,12 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
_addItemButton(FeedCubit feedCubit) {
|
||||
_addItemButton({void Function()? onTap}) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
switch (_selectedChipIndex) {
|
||||
case 2:
|
||||
GoRouter.of(context).pushNamed(CreateDietScreen.name);
|
||||
break;
|
||||
case 3:
|
||||
GoRouter.of(context).pushNamed(CreatePlanScreen.name);
|
||||
break;
|
||||
default:
|
||||
onTap: onTap ??
|
||||
() {
|
||||
GoRouter.of(context).pushNamed('blogPostCreateScreen');
|
||||
}
|
||||
},
|
||||
},
|
||||
borderRadius: BorderRadius.circular(64),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
|
||||
@@ -88,7 +88,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
if (!state.feedBlogPostList[widget.index].author.isEntitySubscribedByMe && !state.feedBlogPostList[widget.index].author.authorIsMe)
|
||||
if (!(state.feedBlogPostList[widget.index].author.isEntitySubscribedByMe ?? false) && !state.feedBlogPostList[widget.index].author.authorIsMe)
|
||||
SubscribeButtonWidget(
|
||||
slug: state.feedBlogPostList[widget.index].author.authorSlug,
|
||||
),
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
enum CommentSourceType { blogPost, recipe, diet }
|
||||
enum CommentSourceType { blogPost, recipe, diet, plan }
|
||||
|
||||
class CommentsWidget extends StatefulWidget {
|
||||
final String id;
|
||||
|
||||
@@ -75,7 +75,7 @@ class _DietsWidgetState extends State<DietsWidget> {
|
||||
bottom: 16,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: DietInfoRow(
|
||||
child: InfoRow(
|
||||
diet: widget.diet,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
|
||||
@@ -19,7 +19,10 @@ class PlanWidget extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'aboutPlanScreen',
|
||||
extra: planModel,
|
||||
extra: {
|
||||
'plan': planModel,
|
||||
'navigateToComments': false,
|
||||
},
|
||||
),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
|
||||
Reference in New Issue
Block a user