forked from eatvio/eatvio_app
feat(recipe): drafts
This commit is contained in:
@@ -186,7 +186,22 @@ class CreateRecipeCubit extends Cubit<CreateRecipeState> {
|
||||
}
|
||||
|
||||
bool validateForDraft() {
|
||||
return validateAll();
|
||||
final isTitleValid = validateTitle();
|
||||
_clearNonTitleValidationErrors();
|
||||
return isTitleValid;
|
||||
}
|
||||
|
||||
void _clearNonTitleValidationErrors() {
|
||||
emit(state.copyWith(
|
||||
descriptionValidationError: null,
|
||||
cookingTimeValidationError: null,
|
||||
activeTimeValidationError: null,
|
||||
servingsValidationError: null,
|
||||
energyPerServingValidationError: null,
|
||||
imageValidationError: null,
|
||||
stepsValidationError: null,
|
||||
ingredientsValidationError: null,
|
||||
));
|
||||
}
|
||||
|
||||
Future<File> downloadImageAsFile(String imageUrl) async {
|
||||
|
||||
@@ -24,40 +24,42 @@ class RecipeRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<FormData> _buildFormData(RecipeModel recipe, {String state = 'active'}) async {
|
||||
Future<List> _buildStepsMap(List<Step?>? steps) async {
|
||||
final stepsMap = [];
|
||||
for (final Step? step in steps ?? []) {
|
||||
if (step != null) {
|
||||
if ((step.image == null || (step.image?.isEmpty ?? true)) && step.description != null) {
|
||||
stepsMap.add({'description_md': step.description ?? ''});
|
||||
} else if (step.image != null && (step.image?.isNotEmpty ?? false)) {
|
||||
final compressed = await ImageCompressUtility.compressFile(File(step.image ?? ''));
|
||||
final multipartFile = await MultipartFile.fromFile(compressed.path);
|
||||
stepsMap.add({
|
||||
'description_md': step.description ?? '',
|
||||
'image': multipartFile,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return stepsMap;
|
||||
}
|
||||
|
||||
Future<FormData> _buildPublishFormData(RecipeModel recipe) async {
|
||||
if (recipe.image == null || (recipe.image?.isEmpty ?? true)) {
|
||||
throw Exception('Recipe image is required');
|
||||
}
|
||||
final image = await ImageCompressUtility.compressFile(File(recipe.image ?? ''));
|
||||
final multiPartFile = await MultipartFile.fromFile(image.path);
|
||||
|
||||
final ingredientsMap = recipe.ingredients?.map((ingredient) {
|
||||
if (ingredient != null) {
|
||||
return ingredient.toJson();
|
||||
}
|
||||
}).toList() ??
|
||||
final ingredientsMap = recipe.ingredients
|
||||
?.map((i) => i?.toJson())
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.toList() ??
|
||||
[];
|
||||
|
||||
final stepsMap = [];
|
||||
for (final Step? step in recipe.steps ?? []) {
|
||||
if (step != null) {
|
||||
if ((step.image == null || (step.image?.isEmpty ?? true)) && step.description != null) {
|
||||
stepsMap.add({
|
||||
'description_md': step.description ?? "",
|
||||
});
|
||||
} else if (step.image != null && (step.image?.isNotEmpty ?? false)) {
|
||||
final image = await ImageCompressUtility.compressFile(File(step.image ?? ''));
|
||||
final multipartFile = await MultipartFile.fromFile(image.path);
|
||||
stepsMap.add({
|
||||
'description_md': step.description ?? "",
|
||||
'image': multipartFile,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
final stepsMap = await _buildStepsMap(recipe.steps);
|
||||
|
||||
final formMap = {
|
||||
'type': recipe.type,
|
||||
'state': state,
|
||||
'title': recipe.title,
|
||||
'tags[]': recipe.tags ?? [],
|
||||
'description_md': recipe.description,
|
||||
@@ -74,9 +76,41 @@ class RecipeRepository {
|
||||
return FormData.fromMap(formMap);
|
||||
}
|
||||
|
||||
Future<FormData> _buildDraftFormData(RecipeModel recipe) async {
|
||||
final ingredientsMap = recipe.ingredients
|
||||
?.map((i) => i?.toJson())
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.toList() ??
|
||||
[];
|
||||
|
||||
final stepsMap = await _buildStepsMap(recipe.steps);
|
||||
|
||||
final formMap = <String, dynamic>{
|
||||
'type': recipe.type,
|
||||
'title': recipe.title,
|
||||
'tags[]': recipe.tags ?? [],
|
||||
'description_md': recipe.description,
|
||||
'video_url': recipe.videoUrl,
|
||||
'ingredients': ingredientsMap,
|
||||
'steps': stepsMap,
|
||||
'cooking_time': recipe.totalCookingTime,
|
||||
'active_time': recipe.activeCookTime,
|
||||
'servings': recipe.servings,
|
||||
'energy_per_serving': recipe.energyPerServing,
|
||||
};
|
||||
|
||||
if (recipe.image != null && (recipe.image?.isNotEmpty ?? false)) {
|
||||
final compressed = await ImageCompressUtility.compressFile(File(recipe.image ?? ''));
|
||||
formMap['image'] = await MultipartFile.fromFile(compressed.path);
|
||||
}
|
||||
|
||||
formMap.removeWhere((k, v) => v == null || (v is String && v.isEmpty));
|
||||
return FormData.fromMap(formMap);
|
||||
}
|
||||
|
||||
Future<void> publishRecipe(RecipeModel recipe, [bool update = false, String? slug]) async {
|
||||
try {
|
||||
final formData = await _buildFormData(recipe, state: 'active');
|
||||
final formData = await _buildPublishFormData(recipe);
|
||||
if (update) {
|
||||
await recipeService.updateRecipe(slug: slug!, formData: formData);
|
||||
} else {
|
||||
@@ -90,20 +124,12 @@ class RecipeRepository {
|
||||
|
||||
Future<void> saveAsDraft(RecipeModel recipe, [bool update = false, String? slug]) async {
|
||||
try {
|
||||
final formData = await _buildFormData(recipe, state: 'archived');
|
||||
final formData = await _buildDraftFormData(recipe);
|
||||
log(formData.fields.toString());
|
||||
if (update) {
|
||||
final response = await recipeService.updateRecipe(slug: slug!, formData: formData);
|
||||
final recipeId = response.data['data']?['id'] ?? response.data['id'];
|
||||
if (recipeId != null) {
|
||||
await recipeService.draftRecipe(id: recipeId as int);
|
||||
}
|
||||
await recipeService.updateRecipe(slug: slug!, formData: formData);
|
||||
} else {
|
||||
final response = await recipeService.publishRecipe(formData: formData);
|
||||
final recipeId = response.data['data']?['id'] ?? response.data['id'];
|
||||
if (recipeId != null) {
|
||||
await recipeService.draftRecipe(id: recipeId as int);
|
||||
}
|
||||
await recipeService.createDraftedRecipe(formData: formData);
|
||||
}
|
||||
} catch (e, s) {
|
||||
await Sentry.captureException(e, stackTrace: s);
|
||||
|
||||
@@ -56,4 +56,10 @@ abstract class CreateRecipeService {
|
||||
Future<void> draftRecipe({
|
||||
@Path() required int id,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/create/drafted')
|
||||
@MultiPart()
|
||||
Future<HttpResponse<dynamic>> createDraftedRecipe({
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user