Files
eatvio_app/lib/features/feed/presentation/widgets/blog_post_widget.dart

252 lines
9.8 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:dismissible_page/dismissible_page.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/utils/date_time_utils.dart';
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:go_router/go_router.dart';
import 'package:share_plus/share_plus.dart';
class BlogPostWidget extends StatefulWidget {
final FeedBlogPostModel feedBlogPostModel;
const BlogPostWidget({super.key, required this.feedBlogPostModel});
@override
State<BlogPostWidget> createState() => _BlogPostWidgetState();
}
class _BlogPostWidgetState extends State<BlogPostWidget> {
late bool isLiked;
late int totalLikes;
@override
void initState() {
isLiked = widget.feedBlogPostModel.wasLikedByMe;
totalLikes = widget.feedBlogPostModel.totalLikes;
super.initState();
}
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () => GoRouter.of(context).pushNamed(
'blogPostScreen',
extra: widget.feedBlogPostModel,
),
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
CircleAvatar(
radius: 20,
backgroundColor: Colors.black12,
foregroundImage: NetworkImage(
widget.feedBlogPostModel.author.authorProfileIcon,
),
),
SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.feedBlogPostModel.author.authorName,
style: TextStyle(
height: 1,
color: Colors.black87,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 4),
Text(
calculateDifference(
widget.feedBlogPostModel.createdAt,
),
style: TextStyle(
height: 1,
color: Colors.black45,
),
),
],
),
const Spacer(),
InkWell(
onTap: () {
Fluttertoast.showToast(msg: 'ща доделаем');
},
borderRadius: BorderRadius.circular(8),
child: Ink(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: appTheme.gray200,
),
child: Text(
'Подписаться',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
),
if (widget.feedBlogPostModel.title.isNotEmpty || widget.feedBlogPostModel.description.isNotEmpty) SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
widget.feedBlogPostModel.title,
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
),
if (widget.feedBlogPostModel.title.isNotEmpty && widget.feedBlogPostModel.description.isNotEmpty) SizedBox(height: 8),
if (widget.feedBlogPostModel.description.isNotEmpty)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Html(
data: widget.feedBlogPostModel.description.length > 200
? widget.feedBlogPostModel.description.substring(0, 200)
: widget.feedBlogPostModel.description,
style: {
"*": Style(
color: Colors.black87,
),
},
),
),
if (widget.feedBlogPostModel.description.length > 200)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
'Читать полностью...',
style: TextStyle(
height: 1,
color: appTheme.blueA400,
decoration: TextDecoration.underline,
),
),
),
if (widget.feedBlogPostModel.title.isNotEmpty || widget.feedBlogPostModel.description.isNotEmpty) SizedBox(height: 8),
GestureDetector(
onTap: () {
context.pushTransparentRoute(
rootNavigator: true,
PhotoViewScreen(
imageUrls: [baseUrl + '/storage/' + widget.feedBlogPostModel.image],
index: 0,
),
);
},
child: Hero(
tag: baseUrl + '/storage/' + widget.feedBlogPostModel.image,
child: CachedNetworkImage(
fit: BoxFit.fitWidth,
width: MediaQuery.of(context).size.width,
imageUrl: baseUrl + '/storage/' + widget.feedBlogPostModel.image,
errorWidget: (context, str, object) => SizedBox.shrink(),
),
),
),
SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
FeedIconButton(
icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
text: totalLikes.toString(),
iconColor: isLiked ? Colors.red.withOpacity(0.8) : null,
backgroundColor: isLiked ? Colors.red.withOpacity(0.1) : null,
textColor: isLiked ? Colors.red.withOpacity(0.8) : null,
onTap: () async {
setState(() {
isLiked = !isLiked;
isLiked ? totalLikes++ : totalLikes--;
});
isLiked
? await context.read<FeedCubit>().likePost(widget.feedBlogPostModel.id)
: await context.read<FeedCubit>().unlikedPost(widget.feedBlogPostModel.id);
await context.read<FeedCubit>().loadFeedBlogPostList();
},
),
SizedBox(width: 8),
FeedIconButton(
svgIcon: SvgPicture.asset(
'assets/icons/comment.svg',
height: 20,
width: 20,
colorFilter: ColorFilter.mode(
appTheme.gray600,
BlendMode.srcIn,
),
),
text: widget.feedBlogPostModel.totalComments.toString(),
onTap: () => GoRouter.of(context).pushNamed(
'blogPostScreen',
extra: widget.feedBlogPostModel,
),
),
SizedBox(width: 8),
FeedIconButton(
svgIcon: SvgPicture.asset(
height: 20,
width: 20,
'assets/icons/share.svg',
colorFilter: ColorFilter.mode(appTheme.gray600, BlendMode.srcIn),
),
onTap: () => Share.shareUri(
Uri.parse(
baseUrl + '/ru/blog_post/' + widget.feedBlogPostModel.id.toString(),
),
),
),
Spacer(),
Icon(
Icons.visibility_rounded,
size: 16,
color: appTheme.gray500,
),
SizedBox(width: 4),
Text(
widget.feedBlogPostModel.totalViews.toString(),
style: TextStyle(
fontSize: 12,
color: appTheme.gray500,
fontWeight: FontWeight.w400,
),
),
],
),
),
SizedBox(height: 8),
],
),
),
);
}
}