forked from eatvio/eatvio_app
301 lines
11 KiB
Dart
301 lines
11 KiB
Dart
import 'package:eatvio_app/data/models/selectionPopupModel/selection_popup_model.dart';
|
||
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
|
||
import 'package:eatvio_app/features/recipes/models/recipe_model.dart';
|
||
import 'package:eatvio_app/features/recipes/presentation/bloc/recipe_create_state.dart';
|
||
import 'package:eatvio_app/features/recipes/reporitories/recipe_repository.dart';
|
||
import 'package:eatvio_app/features/recipes/models/product.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||
import 'package:image_picker/image_picker.dart';
|
||
|
||
class RecipeCreateCubit extends Cubit<RecipeCreateState> {
|
||
final RecipeRepository recipeRepository;
|
||
|
||
RecipeCreateCubit({required this.recipeRepository}) : super(const RecipeCreateState.loading());
|
||
|
||
loadRecipeById(String recipeID) async {
|
||
emit(const RecipeCreateStateLoading());
|
||
try {
|
||
final RecipeModel recipe = await recipeRepository.getRecipe(recipeID);
|
||
final List<SelectionPopupModel> types = [
|
||
SelectionPopupModel(title: 'Первые блюда', value: 'first_meals'),
|
||
SelectionPopupModel(title: 'Вторые блюда', value: 'second_meals'),
|
||
SelectionPopupModel(title: 'Cалаты', value: 'salads'),
|
||
SelectionPopupModel(title: 'Перекусы/закуски', value: 'snacks'),
|
||
SelectionPopupModel(title: 'Сладости', value: 'sweets'),
|
||
SelectionPopupModel(title: 'Напитки', value: 'drinks'),
|
||
SelectionPopupModel(title: 'Прочее', value: 'other'),
|
||
];
|
||
final List<SelectionPopupModel> cookingTimes = [
|
||
SelectionPopupModel(title: '10 минут', value: 10),
|
||
SelectionPopupModel(title: '20 минут', value: 20),
|
||
SelectionPopupModel(title: '30 минут', value: 30),
|
||
SelectionPopupModel(title: '1 час', value: 60),
|
||
SelectionPopupModel(title: '2 часа', value: 120),
|
||
SelectionPopupModel(title: '10 дней', value: 14400),
|
||
];
|
||
final List<SelectionPopupModel> statuses = [
|
||
SelectionPopupModel(title: 'Активна', value: 'active'),
|
||
SelectionPopupModel(title: 'Неактивна', value: 'inactive'),
|
||
];
|
||
final selectedType = types.firstWhere(
|
||
(type) => type.value == recipe.type,
|
||
orElse: () => types[0],
|
||
);
|
||
|
||
final selectedCookingTime = cookingTimes.firstWhere(
|
||
(time) => time.value == recipe.cooking_time,
|
||
orElse: () => cookingTimes[0],
|
||
);
|
||
|
||
final selectedStatus = statuses.firstWhere(
|
||
(status) => status.value == recipe.state,
|
||
orElse: () => statuses[0],
|
||
);
|
||
|
||
final stepControllers = recipe.steps?.map((step) {
|
||
return TextEditingController(text: step?.description);
|
||
}).toList();
|
||
|
||
final stepImages = recipe.steps?.map((step) {
|
||
return step?.image != null ? XFile(step!.image!) : null;
|
||
}).toList();
|
||
|
||
final ingredients = recipe.ingredients?.map((ingredient) {
|
||
return Ingredient(
|
||
name: ingredient!.name,
|
||
portion: ingredient.portion,
|
||
unit: ingredient.unit,
|
||
);
|
||
}).toList();
|
||
|
||
emit(RecipeCreateState.loaded(
|
||
picker: ImagePicker(),
|
||
recipeImage: XFile(recipe.image!),
|
||
titleController: TextEditingController(text: recipe.title),
|
||
productNameController: TextEditingController(),
|
||
ingredientController: TextEditingController(),
|
||
stepDescriptionController: TextEditingController(text: recipe.description),
|
||
youtubeLinkController: TextEditingController(text: recipe.video_url),
|
||
stepControllers: stepControllers ?? [],
|
||
stepImages: stepImages ?? [],
|
||
autocompleteList: [],
|
||
ingredients: ingredients ?? [],
|
||
numberOfSteps: 1,
|
||
ingredientAsItems: false,
|
||
types: types,
|
||
cookingTimes: cookingTimes,
|
||
statuses: statuses,
|
||
selectedType: selectedType,
|
||
selectedCookingTime: selectedCookingTime,
|
||
selectedStatus: selectedStatus,),);
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
loadRecipeCreate() {
|
||
emit(const RecipeCreateStateLoading());
|
||
try {
|
||
final List<SelectionPopupModel> types = [
|
||
SelectionPopupModel(title: 'Первые блюда', value: 'first_meals'),
|
||
SelectionPopupModel(title: 'Вторые блюда', value: 'second_meals'),
|
||
SelectionPopupModel(title: 'Cалаты', value: 'salads'),
|
||
SelectionPopupModel(title: 'Перекусы/закуски', value: 'snacks'),
|
||
SelectionPopupModel(title: 'Сладости', value: 'sweets'),
|
||
SelectionPopupModel(title: 'Напитки', value: 'drinks'),
|
||
SelectionPopupModel(title: 'Прочее', value: 'other'),
|
||
];
|
||
final List<SelectionPopupModel> cookingTimes = [
|
||
SelectionPopupModel(title: '10 минут', value: 10),
|
||
SelectionPopupModel(title: '20 минут', value: 20),
|
||
SelectionPopupModel(title: '30 минут', value: 30),
|
||
SelectionPopupModel(title: '1 час', value: 60),
|
||
SelectionPopupModel(title: '2 часа', value: 120),
|
||
SelectionPopupModel(title: '10 дней', value: 14400),
|
||
];
|
||
final List<SelectionPopupModel> statuses = [
|
||
SelectionPopupModel(title: 'Активна', value: 'active'),
|
||
SelectionPopupModel(title: 'Неактивна', value: 'inactive'),
|
||
];
|
||
emit(RecipeCreateState.loaded(
|
||
picker: ImagePicker(),
|
||
titleController: TextEditingController(),
|
||
productNameController: TextEditingController(),
|
||
ingredientController: TextEditingController(),
|
||
stepDescriptionController: TextEditingController(),
|
||
youtubeLinkController: TextEditingController(),
|
||
stepControllers: [TextEditingController()],
|
||
stepImages: [null],
|
||
autocompleteList: [],
|
||
ingredients: [],
|
||
numberOfSteps: 1,
|
||
ingredientAsItems: false,
|
||
types: types,
|
||
cookingTimes: cookingTimes,
|
||
statuses: statuses,
|
||
selectedType: types[0],
|
||
selectedCookingTime: cookingTimes[0],
|
||
selectedStatus: statuses[0],),);
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
publishRecipe(RecipeModel recipe) async {
|
||
await recipeRepository.publishRecipe(recipe);
|
||
}
|
||
|
||
editRecipe(RecipeModel recipe, String id) async {
|
||
await recipeRepository.editRecipe(recipe, id);
|
||
}
|
||
|
||
uploadRecipeImage(XFile? pickedFile) {
|
||
try {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
var updatedState = currentState.copyWith(
|
||
recipeImage: pickedFile,
|
||
);
|
||
emit(updatedState);
|
||
}
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
uploadStepImage(XFile? pickedFile, int stepNumber) {
|
||
try {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
|
||
var updatedStepImages = List<XFile?>.from(currentState.stepImages);
|
||
|
||
if (stepNumber >= 0 && stepNumber < updatedStepImages.length) {
|
||
updatedStepImages[stepNumber] = pickedFile;
|
||
}
|
||
|
||
var updatedState = currentState.copyWith(
|
||
stepImages: updatedStepImages,
|
||
);
|
||
|
||
emit(updatedState);
|
||
}
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
switchUnits(bool value) {
|
||
try {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
var updatedState = currentState.copyWith(ingredientAsItems: value);
|
||
emit(updatedState);
|
||
}
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
addIngredient(Ingredient ingredient) {
|
||
try {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
|
||
bool ingredientExists = currentState.ingredients.any((existingIngredient) => existingIngredient.name == ingredient.name);
|
||
|
||
if (ingredientExists) {
|
||
emit(RecipeCreateState.error(errorMessage: 'Ингредиент уже существует.'));
|
||
return;
|
||
}
|
||
|
||
List<Ingredient> newIngredients = List<Ingredient>.from(currentState.ingredients);
|
||
newIngredients.add(ingredient);
|
||
|
||
var updatedState = currentState.copyWith(ingredients: newIngredients);
|
||
emit(updatedState);
|
||
}
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
addStep() {
|
||
try {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
List<XFile?> newStepImages = List<XFile?>.from(currentState.stepImages);
|
||
newStepImages.add(null);
|
||
List<TextEditingController> newStepControllers = List<TextEditingController>.from(currentState.stepControllers);
|
||
newStepControllers.add(TextEditingController());
|
||
var updatedState = currentState.copyWith(stepImages: newStepImages, stepControllers: newStepControllers, numberOfSteps: currentState.numberOfSteps + 1);
|
||
emit(updatedState);
|
||
}
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
removeStep() {
|
||
try {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
List<XFile?> newStepImages = List<XFile?>.from(currentState.stepImages);
|
||
newStepImages.removeLast();
|
||
List<TextEditingController> newStepControllers = List<TextEditingController>.from(currentState.stepControllers);
|
||
newStepControllers.removeLast();
|
||
var updatedState = currentState.copyWith(stepImages: newStepImages, stepControllers: newStepControllers, numberOfSteps: currentState.numberOfSteps - 1);
|
||
emit(updatedState);
|
||
}
|
||
} catch (e) {
|
||
emit(RecipeCreateState.error(errorMessage: e.toString()));
|
||
}
|
||
}
|
||
|
||
inputProduct(String input) async {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
|
||
final Map<String, List<Product>> productNutritionalValues = await recipeRepository.inputProduct(input);
|
||
|
||
var updatedState = currentState.copyWith(
|
||
productNameController: TextEditingController(text: input),
|
||
autocompleteList: productNutritionalValues['product_nutritional_value'] ?? [],
|
||
);
|
||
|
||
emit(updatedState);
|
||
}
|
||
}
|
||
|
||
changeType(SelectionPopupModel type) {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
RecipeCreateStateLoaded updatedState = currentState.copyWith(
|
||
selectedType: type,
|
||
);
|
||
emit(updatedState);
|
||
}
|
||
}
|
||
|
||
changeStatus(SelectionPopupModel status) {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
RecipeCreateStateLoaded updatedState = currentState.copyWith(
|
||
selectedStatus: status,
|
||
);
|
||
emit(updatedState);
|
||
}
|
||
}
|
||
|
||
changeCookingTime(SelectionPopupModel cookingTime) {
|
||
if (state is RecipeCreateStateLoaded) {
|
||
var currentState = state as RecipeCreateStateLoaded;
|
||
RecipeCreateStateLoaded updatedState = currentState.copyWith(
|
||
selectedCookingTime: cookingTime,
|
||
);
|
||
emit(updatedState);
|
||
}
|
||
}
|
||
}
|