forked from eatvio/eatvio_app
feat: implement recipe drafting functionality and refactor MyRecipesTab to be stateless
This commit is contained in:
@@ -12,6 +12,8 @@ import 'package:eatvio_app/features/recipe/presentation/cubit/my_recipes_cubit/m
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:eatvio_app/core/widgets/markdown_html_widget.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
@@ -99,11 +101,7 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
|
||||
? '${widget.recipe.description.substring(0, 200)}...'
|
||||
: widget.recipe.description;
|
||||
|
||||
return MarkdownHtmlWidget(
|
||||
markdownText: description,
|
||||
fontSize: TextStyles.textSMedium.fontSize ?? 14,
|
||||
textColor: appTheme.black,
|
||||
);
|
||||
return MarkdownHtmlWidget(markdownText: description, fontSize: TextStyles.textSMedium.fontSize ?? 14, textColor: appTheme.black);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -126,7 +124,13 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
|
||||
return;
|
||||
}
|
||||
showSuccessToast('Рецепт удален');
|
||||
if (context.mounted) context.read<MyRecipesCubit>().getMyRecipes();
|
||||
if (context.mounted) {
|
||||
if (isDraft) {
|
||||
context.read<MyRecipesCubit>().setDraftedState();
|
||||
} else {
|
||||
context.read<MyRecipesCubit>().getMyRecipes();
|
||||
}
|
||||
}
|
||||
},
|
||||
text: 'Удалить',
|
||||
height: 52,
|
||||
@@ -140,30 +144,83 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: CustomOutlinedButton(
|
||||
onPressed: () async {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
uri: Uri.parse('${sl<AppConfig>().baseUrl}/ru/recipe/${widget.recipe.slug}'),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
child: PopupMenuButton<int>(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
offset: const Offset(0, 50),
|
||||
itemBuilder: (context) => [
|
||||
if (!isDraft)
|
||||
PopupMenuItem(
|
||||
onTap: () async {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
uri: Uri.parse('${sl<AppConfig>().baseUrl}/ru/recipe/${widget.recipe.slug}'),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.share, size: 20, color: appTheme.black),
|
||||
const SizedBox(width: 8),
|
||||
Text(S.of(context).share, style: TextStyles.textSMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
height: 52,
|
||||
width: 52,
|
||||
buttonStyle: ButtonStyle(
|
||||
shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||
if (widget.recipe.state == 'active' || isDraft)
|
||||
PopupMenuItem(
|
||||
onTap: () {
|
||||
context.push(RecipeCreateScreen.path, extra: widget.recipe);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.edit, size: 20, color: appTheme.black),
|
||||
const SizedBox(width: 8),
|
||||
Text(S.of(context).edit, style: TextStyles.textSMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
child: CustomOutlinedButton(
|
||||
onPressed: () {},
|
||||
height: 52,
|
||||
width: 52,
|
||||
buttonStyle: ButtonStyle(
|
||||
shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||
),
|
||||
text: isDraft ? '...' : s.share,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
),
|
||||
text: s.share,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (isDraft)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// Publish draft
|
||||
context.read<CreateRecipeCubit>().publishRecipe(true, widget.recipe.slug).then((success) {
|
||||
if (success) {
|
||||
context.read<MyRecipesCubit>().setDraftedState();
|
||||
}
|
||||
});
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: appTheme.blueA400,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
),
|
||||
child: Text('Опубликовать', style: TextStyles.textSMedium.copyWith(color: Colors.white)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -172,6 +229,8 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
|
||||
);
|
||||
}
|
||||
|
||||
bool get isDraft => widget.recipe.state == 'drafted';
|
||||
|
||||
Container _iconButton(String iconPath, [String? text]) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
@@ -192,4 +251,3 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,30 +4,21 @@ import 'package:eatvio_app/core/widgets/animated_option_button.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class MyRecipesTab extends StatefulWidget {
|
||||
const MyRecipesTab({super.key, this.additionalOnTap});
|
||||
class MyRecipesTab extends StatelessWidget {
|
||||
const MyRecipesTab({
|
||||
super.key,
|
||||
required this.selectedIndex,
|
||||
required this.onTabChanged,
|
||||
});
|
||||
|
||||
final void Function()? additionalOnTap;
|
||||
|
||||
@override
|
||||
State<MyRecipesTab> createState() => _MyRecipesTabState();
|
||||
}
|
||||
|
||||
class _MyRecipesTabState extends State<MyRecipesTab> {
|
||||
final List<String> tabTitles = [];
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
final s = S.of(context);
|
||||
if (tabTitles.isEmpty) {
|
||||
tabTitles.add(s.published);
|
||||
tabTitles.add(s.drafted);
|
||||
}
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
final int selectedIndex;
|
||||
final ValueChanged<int> onTabChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
final tabTitles = [s.published, s.drafted];
|
||||
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
@@ -44,18 +35,14 @@ class _MyRecipesTabState extends State<MyRecipesTab> {
|
||||
children: [
|
||||
...List.generate(
|
||||
2,
|
||||
(index) =>
|
||||
Expanded(
|
||||
child: AnimatedOptionButton(
|
||||
textStyle: TextStyles.textSMedium,
|
||||
isSelected: false, // state.selectedStateIndex == index,
|
||||
text: tabTitles[index],
|
||||
onTap: () {
|
||||
widget.additionalOnTap?.call();
|
||||
// context.read<MyPlansCubit>().changeSelectedStateIndex(index);
|
||||
},
|
||||
),
|
||||
),
|
||||
(index) => Expanded(
|
||||
child: AnimatedOptionButton(
|
||||
textStyle: TextStyles.textSMedium,
|
||||
isSelected: selectedIndex == index,
|
||||
text: tabTitles[index],
|
||||
onTap: () => onTabChanged(index),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user