forked from eatvio/eatvio_app
feat(recipe): edit recipe
This commit is contained in:
@@ -14,7 +14,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class InfoAboutRecipeWidget extends StatefulWidget {
|
||||
const InfoAboutRecipeWidget({super.key});
|
||||
final CreateRecipeCubit createRecipeCubit;
|
||||
|
||||
const InfoAboutRecipeWidget({super.key, required this.createRecipeCubit});
|
||||
|
||||
@override
|
||||
State<InfoAboutRecipeWidget> createState() => _InfoAboutRecipeWidgetState();
|
||||
@@ -23,13 +25,19 @@ class InfoAboutRecipeWidget extends StatefulWidget {
|
||||
class _InfoAboutRecipeWidgetState extends State<InfoAboutRecipeWidget> {
|
||||
final List<SelectionPopupModel> items = TypeOfRecipe.values.map((e) => SelectionPopupModel(title: e.toString())).toList();
|
||||
late SelectionPopupModel selectedType;
|
||||
late final CreateRecipeCubit createRecipeCubit;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
selectedType = items.first;
|
||||
createRecipeCubit = context.read<CreateRecipeCubit>();
|
||||
if (widget.createRecipeCubit.state.entity.typeOfRecipe != null) {
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
if (items[i].title == widget.createRecipeCubit.state.entity.typeOfRecipe!.toString()) {
|
||||
selectedType = items[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selectedType = items.first;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -44,6 +52,7 @@ class _InfoAboutRecipeWidgetState extends State<InfoAboutRecipeWidget> {
|
||||
const Text('Название'),
|
||||
const SizedBox(height: 4),
|
||||
BlocBuilder<CreateRecipeCubit, CreateRecipeState>(
|
||||
bloc: widget.createRecipeCubit,
|
||||
buildWhen: (previous, current) => previous.titleValidationError != current.titleValidationError,
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
@@ -51,10 +60,11 @@ class _InfoAboutRecipeWidgetState extends State<InfoAboutRecipeWidget> {
|
||||
CustomTextFormField(
|
||||
hintText: 'Например: тар-тар из говядины',
|
||||
hasError: state.titleValidationError != null,
|
||||
initialValue: state.entity.title,
|
||||
onChanged: (value) {
|
||||
createRecipeCubit.replaceTitle(value);
|
||||
widget.createRecipeCubit.replaceTitle(value);
|
||||
if (state.titleValidationError != null) {
|
||||
createRecipeCubit.validateTitle();
|
||||
widget.createRecipeCubit.validateTitle();
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -78,7 +88,7 @@ class _InfoAboutRecipeWidgetState extends State<InfoAboutRecipeWidget> {
|
||||
setState(() {
|
||||
selectedType = newSelectedType;
|
||||
});
|
||||
createRecipeCubit.changeType(
|
||||
widget.createRecipeCubit.changeType(
|
||||
TypeOfRecipe.fromString(selectedType.title) ?? TypeOfRecipe.other,
|
||||
);
|
||||
},
|
||||
@@ -100,12 +110,13 @@ class _InfoAboutRecipeWidgetState extends State<InfoAboutRecipeWidget> {
|
||||
CustomTextFormField(
|
||||
hintText: 'Расскажите, почему вы выбрали именно этот рецепт? Опишите, каким будет готовое блюдо и в чём его достоинства.',
|
||||
minLines: 5,
|
||||
initialValue: state.entity.description,
|
||||
maxLines: 5,
|
||||
hasError: state.descriptionValidationError != null,
|
||||
onChanged: (value) {
|
||||
createRecipeCubit.replaceDescription(value);
|
||||
widget.createRecipeCubit.replaceDescription(value);
|
||||
if (state.descriptionValidationError != null) {
|
||||
createRecipeCubit.validateDescription();
|
||||
widget.createRecipeCubit.validateDescription();
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -148,8 +159,9 @@ class _InfoAboutRecipeWidgetState extends State<InfoAboutRecipeWidget> {
|
||||
const SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
hintText: 'Прикрепите ссылку на видео',
|
||||
initialValue: widget.createRecipeCubit.state.entity.videoUrl,
|
||||
onChanged: (value) {
|
||||
createRecipeCubit.replaceVideoUrl(value);
|
||||
widget.createRecipeCubit.replaceVideoUrl(value);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -14,6 +14,7 @@ class PortionWidget extends StatefulWidget {
|
||||
|
||||
class _PortionWidgetState extends State<PortionWidget> {
|
||||
late final CreateRecipeCubit createRecipeCubit;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -45,6 +46,7 @@ class _PortionWidgetState extends State<PortionWidget> {
|
||||
CustomTextFormField(
|
||||
hintText: '1',
|
||||
hasError: state.servingsValidationError != null,
|
||||
initialValue: state.entity.countOfPortions?.toString(),
|
||||
textInputType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
createRecipeCubit.replacePortionsCount(int.parse(value));
|
||||
@@ -77,6 +79,7 @@ class _PortionWidgetState extends State<PortionWidget> {
|
||||
CustomTextFormField(
|
||||
hintText: '100',
|
||||
hasError: state.energyPerServingValidationError != null,
|
||||
initialValue: state.entity.energyInOnePortion?.toString(),
|
||||
suffixText: 'Ккал',
|
||||
textInputType: const TextInputType.numberWithOptions(decimal: true),
|
||||
onChanged: (value) {
|
||||
|
||||
@@ -3,16 +3,16 @@ import 'dart:io';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class StepImageWidget extends StatefulWidget {
|
||||
final CreateRecipeCubit createRecipeCubit;
|
||||
final int index;
|
||||
|
||||
const StepImageWidget({
|
||||
super.key,
|
||||
required this.index,
|
||||
required this.index, required this.createRecipeCubit,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -21,12 +21,15 @@ class StepImageWidget extends StatefulWidget {
|
||||
|
||||
class _StepImageWidgetState extends State<StepImageWidget> {
|
||||
XFile? image;
|
||||
late final CreateRecipeCubit createRecipeCubit;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
createRecipeCubit = context.read<CreateRecipeCubit>();
|
||||
if (widget.createRecipeCubit.state.entity.steps.length > widget.index) {
|
||||
if (widget.createRecipeCubit.state.entity.steps[widget.index].image != null) {
|
||||
image = XFile(widget.createRecipeCubit.state.entity.steps[widget.index].image!.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -56,7 +59,7 @@ class _StepImageWidgetState extends State<StepImageWidget> {
|
||||
setState(() {
|
||||
image = null;
|
||||
});
|
||||
createRecipeCubit.replaceImageInStep(null, widget.index);
|
||||
widget.createRecipeCubit.replaceImageInStep(null, widget.index);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
@@ -84,7 +87,7 @@ class _StepImageWidgetState extends State<StepImageWidget> {
|
||||
image = await picker.pickImage(source: ImageSource.camera);
|
||||
setState(() {});
|
||||
if (image != null) {
|
||||
createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
||||
widget.createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
Navigator.of(context).pop();
|
||||
@@ -103,7 +106,7 @@ class _StepImageWidgetState extends State<StepImageWidget> {
|
||||
image = await picker.pickImage(source: ImageSource.gallery);
|
||||
setState(() {});
|
||||
if (image != null) {
|
||||
createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
||||
widget.createRecipeCubit.replaceImageInStep(File(image!.path), widget.index);
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
Navigator.of(context).pop();
|
||||
|
||||
@@ -7,24 +7,19 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class StepsWidget extends StatefulWidget {
|
||||
const StepsWidget({super.key});
|
||||
final CreateRecipeCubit createRecipeCubit;
|
||||
|
||||
const StepsWidget({super.key, required this.createRecipeCubit});
|
||||
|
||||
@override
|
||||
State<StepsWidget> createState() => _StepsWidgetState();
|
||||
}
|
||||
|
||||
class _StepsWidgetState extends State<StepsWidget> {
|
||||
late final CreateRecipeCubit createRecipeCubit;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
createRecipeCubit = context.read<CreateRecipeCubit>();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<CreateRecipeCubit, CreateRecipeState>(
|
||||
bloc: widget.createRecipeCubit,
|
||||
builder: (BuildContext context, CreateRecipeState state) {
|
||||
return Material(
|
||||
shape: RoundedRectangleBorder(
|
||||
@@ -83,10 +78,11 @@ class _StepsWidgetState extends State<StepsWidget> {
|
||||
const SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
hintText: 'Например: подготовьте ингредиенты',
|
||||
initialValue: widget.createRecipeCubit.state.entity.steps[index].description,
|
||||
maxLines: 5,
|
||||
minLines: 3,
|
||||
onChanged: (value) {
|
||||
createRecipeCubit.replaceDescriptionInStep(value, index);
|
||||
widget.createRecipeCubit.replaceDescriptionInStep(value, index);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
@@ -94,6 +90,7 @@ class _StepsWidgetState extends State<StepsWidget> {
|
||||
const SizedBox(height: 4),
|
||||
StepImageWidget(
|
||||
index: index,
|
||||
createRecipeCubit: widget.createRecipeCubit,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class TagsWidget extends StatefulWidget {
|
||||
const TagsWidget({super.key});
|
||||
@@ -10,8 +12,16 @@ class TagsWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _TagsWidgetState extends State<TagsWidget> {
|
||||
late final CreateRecipeCubit createRecipeCubit;
|
||||
final tagController = TextEditingController();
|
||||
final List<String> tags = [];
|
||||
late final List<String> tags;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
createRecipeCubit = context.read<CreateRecipeCubit>();
|
||||
tags = createRecipeCubit.state.entity.tags;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -71,6 +71,7 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
|
||||
hintText: 'Часов',
|
||||
hasError: state.cookingTimeValidationError != null,
|
||||
textInputType: TextInputType.number,
|
||||
initialValue: state.entity.totalCookHours?.toString(),
|
||||
onChanged: (value) {
|
||||
final hours = int.tryParse(value);
|
||||
if (hours == null) return;
|
||||
@@ -97,6 +98,7 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
|
||||
hintText: 'Минут',
|
||||
hasError: state.cookingTimeValidationError != null,
|
||||
textInputType: TextInputType.number,
|
||||
initialValue: state.entity.totalCookMinutes?.toString(),
|
||||
onChanged: (value) {
|
||||
final minutes = int.tryParse(value);
|
||||
if (minutes == null) return;
|
||||
@@ -156,6 +158,7 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
|
||||
CustomTextFormField(
|
||||
hintText: 'Часов',
|
||||
hasError: state.activeTimeValidationError != null,
|
||||
initialValue: state.entity.activeCookHours?.toString(),
|
||||
textInputType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
final hours = int.tryParse(value);
|
||||
@@ -183,6 +186,7 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
|
||||
CustomTextFormField(
|
||||
hintText: 'Минут',
|
||||
hasError: state.activeTimeValidationError != null,
|
||||
initialValue: state.entity.activeCookMinutes?.toString(),
|
||||
textInputType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
final minutes = int.tryParse(value);
|
||||
|
||||
Reference in New Issue
Block a user