feat: Introduce user-generated content features, including recipe creation and management, and blog post creation.

This commit is contained in:
mso7nueh
2026-02-26 02:52:08 +03:00
parent 0641513ebe
commit 0b2e026d1d
5 changed files with 127 additions and 68 deletions

View File

@@ -12,6 +12,7 @@ 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';
@@ -145,8 +146,17 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
Expanded(
child: isDraft
? CustomOutlinedButton(
onPressed: () {
context.push(RecipeCreateScreen.path, extra: widget.recipe.toRecipe());
onPressed: () async {
showDialog(
context: context,
barrierColor: Colors.black12,
builder: (context) => const Center(child: CircularProgressIndicator()),
);
final fullRecipe = await context.read<MyRecipesCubit>().getRecipeById(widget.recipe.slug);
if (context.mounted) {
Navigator.pop(context); // close dialog
context.push(RecipeCreateScreen.path, extra: fullRecipe);
}
},
height: 52,
buttonStyle: ButtonStyle(
@@ -180,27 +190,6 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
],
),
),
if (!isDraft)
PopupMenuItem(
onTap: () async {
final result = await context.read<MyRecipesCubit>().draftRecipe(widget.recipe.id);
if (result) {
showSuccessToast('Рецепт перенесен в черновики');
if (context.mounted) {
context.read<MyRecipesCubit>().getMyRecipes();
}
} else {
showErrorToast('Не удалось перенести в черновики');
}
},
child: Row(
children: [
Icon(Icons.archive_outlined, size: 20, color: appTheme.black),
const SizedBox(width: 8),
const Text('В черновик', style: TextStyles.textSMedium),
],
),
),
],
child: CustomOutlinedButton(
onPressed: () {},
@@ -225,21 +214,36 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
width: double.infinity,
child: CustomOutlinedButton(
onPressed: () async {
// Publish draft
final recipeModel = widget.recipe.toRecipeModel();
final success = await context.read<MyRecipesCubit>().publishDraft(recipeModel, widget.recipe.slug);
if (success && context.mounted) {
showSuccessToast('Черновик опубликован');
context.read<MyRecipesCubit>().setDraftedState();
} else {
showErrorToast('Заполните все необходимые поля для публикации рецепта');
if (context.mounted) {
context.push(RecipeCreateScreen.path, extra: {
'recipe': widget.recipe.toRecipe(),
'autoValidate': true,
});
}
}
showDialog(
context: context,
barrierColor: Colors.black12,
builder: (context) => const Center(child: CircularProgressIndicator()),
);
final fullRecipe = await context.read<MyRecipesCubit>().getRecipeById(widget.recipe.slug);
final createCubit = sl<CreateRecipeCubit>();
await createCubit.recipeToEntity(fullRecipe);
if (context.mounted) {
Navigator.pop(context);
if (createCubit.validateAll()) {
final success = await createCubit.publishRecipe(true, widget.recipe.slug);
if (success && context.mounted) {
showSuccessToast('Черновик опубликован');
context.read<MyRecipesCubit>().setDraftedState();
} else {
showErrorToast('Не удалось опубликовать черновик');
}
} else {
showErrorToast('Заполните все необходимые поля для публикации рецепта');
if (context.mounted) {
context.push(RecipeCreateScreen.path, extra: {
'recipe': fullRecipe,
'autoValidate': true,
});
}
}
await createCubit.close();
}
},
height: 52,
buttonStyle: ButtonStyle(
@@ -252,6 +256,35 @@ class _MyRecipeWidgetState extends State<MyRecipeWidget> {
),
),
),
if (!isDraft)
Padding(
padding: const EdgeInsets.only(top: 8),
child: SizedBox(
width: double.infinity,
child: CustomOutlinedButton(
onPressed: () async {
final result = await context.read<MyRecipesCubit>().draftRecipe(widget.recipe.id);
if (result) {
showSuccessToast('Рецепт перенесен в черновики');
if (context.mounted) {
context.read<MyRecipesCubit>().getMyRecipes();
}
} else {
showErrorToast('Не удалось перенести в черновики');
}
},
height: 52,
buttonStyle: ButtonStyle(
shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))),
backgroundColor: WidgetStatePropertyAll(appTheme.lightGray0),
side: const WidgetStatePropertyAll(BorderSide.none),
),
text: 'Снять с публикации',
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.black),
),
),
),
const SizedBox(height: 16),
],
),
),