forked from eatvio/eatvio_app
360 lines
15 KiB
Dart
360 lines
15 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
import 'package:eatvio_app/core/enums/complained_content.dart';
|
|
import 'package:eatvio_app/core/enums/product_type.dart';
|
|
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
|
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
|
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
|
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
|
import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
|
import 'package:eatvio_app/core/widgets/info_row.dart';
|
|
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
|
|
import 'package:eatvio_app/core/widgets/cpfc_container.dart';
|
|
import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart';
|
|
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
|
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
|
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
import 'package:eatvio_app/generated/l10n.dart';
|
|
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
|
|
class DietPreviewScreen extends StatefulWidget {
|
|
final Diet diet;
|
|
late final List<int> selectedIndexes;
|
|
static const name = 'createDietScreenPreview';
|
|
static const path = '/create-diet-screen/preview';
|
|
DietPreviewScreen({super.key, required this.diet}) {
|
|
selectedIndexes = List.generate(diet.dailySchedule.length, (_) => 0);
|
|
}
|
|
|
|
@override
|
|
State<DietPreviewScreen> createState() => _DietPreviewScreenState();
|
|
}
|
|
|
|
class _DietPreviewScreenState extends State<DietPreviewScreen> {
|
|
final ScrollController scrollController = ScrollController();
|
|
final textEditingController = TextEditingController();
|
|
bool isMoreOptionsVisible = false;
|
|
late final Uint8List imageData;
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
imageData = base64.decode(widget.diet.image);
|
|
scrollController.addListener(() {
|
|
if (isMoreOptionsVisible) {
|
|
setState(() {
|
|
isMoreOptionsVisible = false;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final s = S.of(context);
|
|
return Scaffold(
|
|
backgroundColor: appTheme.gray100,
|
|
resizeToAvoidBottomInset: true,
|
|
bottomSheet: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.1))),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: BookmarkButton(
|
|
isFavorite: widget.diet.isFavorite,
|
|
onTap: () {},
|
|
width: 52,
|
|
height: 52,
|
|
size: 24,
|
|
shape: BoxShape.circle,
|
|
color: appTheme.gray50,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
child: SizedBox(
|
|
child: TextFormField(
|
|
textCapitalization: TextCapitalization.sentences,
|
|
onChanged: (_) {
|
|
setState(() {});
|
|
},
|
|
controller: textEditingController,
|
|
maxLines: 5,
|
|
minLines: 1,
|
|
keyboardType: TextInputType.multiline,
|
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
|
decoration: InputDecoration(
|
|
isDense: true,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
hintText: s.comment.capitalize(),
|
|
hintStyle: TextStyles.textMMedium.copyWith(color: appTheme.lightGray600),
|
|
filled: true,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
GestureDetector(
|
|
onTap: () {},
|
|
child: Container(
|
|
decoration: BoxDecoration(color: textEditingController.text.length > 2 ? appTheme.blueA400 : appTheme.gray50, shape: BoxShape.circle),
|
|
height: 32,
|
|
width: 32,
|
|
child: Icon(Icons.send_rounded, size: 18, color: textEditingController.text.length > 2 ? appTheme.whiteA700 : appTheme.black),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
appBar: AppBar(
|
|
centerTitle: true,
|
|
title: Text(
|
|
widget.diet.name,
|
|
maxLines: 2,
|
|
textAlign: TextAlign.center,
|
|
overflow: TextOverflow.ellipsis,
|
|
softWrap: true,
|
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
|
),
|
|
actions: [
|
|
CustomPopup(
|
|
isAuthor: widget.diet.author.authorIsMe,
|
|
path: 'diet/${widget.diet.slug}',
|
|
complainedContentType: ComplainedContent.diet,
|
|
userSlug: widget.diet.author.authorSlug,
|
|
),
|
|
const SizedBox(width: 16),
|
|
],
|
|
),
|
|
body: SingleChildScrollView(
|
|
controller: scrollController,
|
|
padding: const EdgeInsets.only(bottom: 160),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const SizedBox(height: 8),
|
|
MainBackgroundBouble(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Stack(
|
|
children: [
|
|
Image.memory(imageData, height: 300, width: MediaQuery.sizeOf(context).width, fit: BoxFit.fill),
|
|
// CachedNetworkImage(
|
|
// imageUrl: baseUrl + '/storage/' + widget.diet.image,
|
|
// ),
|
|
Positioned(
|
|
bottom: 16,
|
|
left: 0,
|
|
right: 0,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
InfoBouble(
|
|
backgroundColor: appTheme.whiteA700,
|
|
children: [
|
|
SvgPicture.asset('assets/icons/eye.svg', width: 18, height: 12),
|
|
const SizedBox(width: 8),
|
|
Text(widget.diet.totalViews.toString(), style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
|
],
|
|
),
|
|
const SizedBox(width: 12),
|
|
GestureDetector(
|
|
onTap: () {},
|
|
child: InfoBouble(
|
|
backgroundColor: appTheme.whiteA700,
|
|
children: [
|
|
SvgPicture.asset(
|
|
'assets/icons/heart.svg',
|
|
width: 14,
|
|
height: 12,
|
|
colorFilter: widget.diet.wasLikedByMe ? ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn) : null,
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(widget.diet.totalLikes.toString(), style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
InfoBouble(
|
|
backgroundColor: appTheme.whiteA700,
|
|
children: [
|
|
SvgPicture.asset('assets/icons/comment2.svg', width: 13, height: 12),
|
|
const SizedBox(width: 8),
|
|
Text(widget.diet.totalComments.toString(), style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Text(s.about_diet, style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)),
|
|
),
|
|
const SizedBox(height: 12),
|
|
InfoRow(diet: widget.diet, type: ProductType.diet),
|
|
ExpandableText(text: widget.diet.details),
|
|
const SizedBox(height: 20),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: AuthorCard(author: widget.diet.author, title: s.diet_author),
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
MainBackgroundBouble(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
|
child: Center(
|
|
child: Text(
|
|
'${s.diet_plan}(${widget.diet.duration.toString()} ${getDayForm(widget.diet.duration, s)})',
|
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
ListView.builder(
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
shrinkWrap: true,
|
|
itemBuilder: (context, index) {
|
|
return _dayOfPlan(widget.diet.dailySchedule[index + 1] ?? {}, index, s);
|
|
},
|
|
itemCount: widget.diet.dailySchedule.length,
|
|
),
|
|
MainBackgroundBouble(
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
alignment: Alignment.centerLeft,
|
|
child: Text('0 ${getCommentForm(widget.diet.totalComments, s)}', style: TextStyles.textMMedium.copyWith(color: appTheme.gray500)),
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Padding _dayOfPlan(Map<int, Map<int, DailySchedule>> day, int dayNumber, S s) {
|
|
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: 16, vertical: 8),
|
|
label: Text((index + 1).toString()),
|
|
labelStyle: TextStyles.textXSSemibold.copyWith(color: index == widget.selectedIndexes[dayNumber] ? Colors.white : appTheme.gray600),
|
|
selected: widget.selectedIndexes[dayNumber] == index,
|
|
backgroundColor: appTheme.gray100,
|
|
onSelected: (bool selected) {
|
|
setState(() {
|
|
widget.selectedIndexes[dayNumber] = index;
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|
child: MainBackgroundBouble(
|
|
padding: const EdgeInsets.only(top: 16),
|
|
child: Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('${s.day} ${dayNumber + 1}', style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)),
|
|
const Padding(padding: EdgeInsets.symmetric(vertical: 12), child: CustomDivider()),
|
|
Text(s.meal, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [choiceChipWidget(0), choiceChipWidget(1), choiceChipWidget(2), choiceChipWidget(3), choiceChipWidget(4)],
|
|
),
|
|
const SizedBox(height: 8),
|
|
ListView.builder(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemBuilder: (context, index) => _daily(day[widget.selectedIndexes[dayNumber] + 1]?[index + 1], s),
|
|
itemCount: day[widget.selectedIndexes[dayNumber] + 1]?.length ?? 0,
|
|
),
|
|
const SizedBox(height: 8),
|
|
],
|
|
),
|
|
),
|
|
CpfcContainer(
|
|
calories: widget.diet.dailyNutrition[dayNumber].energy,
|
|
proteins: widget.diet.dailyNutrition[dayNumber].proteins,
|
|
fats: widget.diet.dailyNutrition[dayNumber].fats,
|
|
carbohydrates: widget.diet.dailyNutrition[dayNumber].carbohydrates,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
SingleChildRenderObjectWidget _daily(DailySchedule? daily, S s) {
|
|
if (daily == null) return const SizedBox.shrink();
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 12),
|
|
child: Row(
|
|
children: [
|
|
SizedBox(
|
|
width: MediaQuery.sizeOf(context).width * 0.6,
|
|
child: Text(daily.name, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
|
),
|
|
const Spacer(),
|
|
Text('${daily.quantity} ${getLocalizedMeasurementUnits(s, daily.portion)}', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|