diet creation scrren is done

This commit is contained in:
Username1548
2024-12-11 19:15:25 +07:00
parent 2e0a8c559f
commit 2f168a2f35
63 changed files with 3113 additions and 633 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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