Files
eatvio_app/lib/features/feed/presentation/pages/feed_screen.dart

260 lines
7.9 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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/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';
import 'package:eatvio_app/features/feed/presentation/widgets/recipes_widget.dart';
import 'package:eatvio_app/theme/theme_helper.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
class FeedScreen extends StatefulWidget {
const FeedScreen({super.key});
@override
State<FeedScreen> createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen> {
final List<String> chipsLabelList = ['Все', 'Рецепты', 'Диеты', 'Планы питания', 'Консультанты'];
int _selectedChipIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
toolbarHeight: 0,
),
backgroundColor: Colors.grey.shade200,
body: NestedScrollView(
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),
_addBlogPostButton(),
],
),
),
];
},
body: Builder(
builder: (BuildContext context) {
if (_selectedChipIndex == 0)
return _buildAllBlogPosts();
else
return _buildAllRecipes();
},
),
),
);
}
_buildAllBlogPosts() {
return RefreshIndicator(
onRefresh: () => context.read<FeedCubit>().loadFeedBlogPostList(),
child: BlocBuilder<FeedCubit, FeedState>(
builder: (BuildContext context, FeedState state) {
if (state is FeedStateLoaded) {
return ListView.separated(
padding: EdgeInsets.symmetric(vertical: 8),
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return BlogPostWidget(feedBlogPostModel: state.feedBlogPostList[index]);
},
separatorBuilder: (context, index) {
return SizedBox(height: 8);
},
itemCount: state.feedBlogPostList.length,
);
} else if (state is FeedStateError) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Text(state.errorMessage),
),
),
);
} else {
return Scaffold(
body: Center(
child: CupertinoActivityIndicator(),
),
);
}
},
),
);
}
_buildAllRecipes() {
return RefreshIndicator(
onRefresh: () => context.read<RecipesCubit>().loadRecipesList(),
child: BlocBuilder<RecipesCubit, RecipesState>(
builder: (BuildContext context, RecipesState state) {
if (state is RecipesStateLoaded) {
return ListView.separated(
padding: EdgeInsets.symmetric(vertical: 8),
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return RecipesWidget(recipes: state.recipesList[index]);
},
separatorBuilder: (context, index) {
return SizedBox(height: 8);
},
itemCount: state.recipesList.length,
);
} else if (state is RecipesStateError) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Text(state.errorMessage),
),
),
);
} else {
return Scaffold(
body: Center(
child: CupertinoActivityIndicator(),
),
);
}
},
),
);
}
_chipGroup() {
return PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, 32),
child: Align(
alignment: Alignment.centerLeft,
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16),
scrollDirection: Axis.horizontal,
child: Row(
children: [
_choiceChipWidget(0),
SizedBox(width: 8),
_choiceChipWidget(1),
SizedBox(width: 8),
_choiceChipWidget(2),
SizedBox(width: 8),
_choiceChipWidget(3),
SizedBox(width: 8),
_choiceChipWidget(4),
],
),
),
),
);
}
_addBlogPostButton() {
return InkWell(
onTap: () => GoRouter.of(context).pushNamed('blogPostCreateScreen'),
borderRadius: BorderRadius.circular(64),
child: Ink(
decoration: BoxDecoration(
color: appTheme.blueA400,
shape: BoxShape.circle,
),
child: Icon(
Icons.add_rounded,
color: appTheme.gray100,
),
width: 40,
height: 40,
),
);
}
_searchBar() {
return SizedBox(
height: 40,
width: MediaQuery.of(context).size.width - 84,
child: TextFormField(
style: TextStyle(
fontSize: 12,
),
decoration: InputDecoration(
hintText: 'Поиск',
hintStyle: TextStyle(
fontSize: 12,
color: appTheme.gray600,
fontWeight: FontWeight.w400,
),
prefixIcon: Icon(
Icons.search,
color: appTheme.gray600,
size: 16,
),
isDense: false,
contentPadding: EdgeInsets.all(8),
fillColor: appTheme.gray100,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
),
),
);
}
_choiceChipWidget(int index) {
return ChoiceChip(
selectedColor: appTheme.blueA400,
pressElevation: 0,
showCheckmark: false,
side: BorderSide.none,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
label: Text(chipsLabelList[index]),
labelStyle: TextStyle(
color: index == _selectedChipIndex ? Colors.white : appTheme.gray600,
fontWeight: FontWeight.w500,
fontSize: 12,
),
selected: _selectedChipIndex == index,
backgroundColor: appTheme.gray100,
onSelected: (bool selected) {
setState(() {
_selectedChipIndex = index;
});
},
);
}
}