Merge branch 'feature/Create-Recipe' into 'develop'

Create-Recipe

See merge request francesco.damico/francescos.recipes.world!14
This commit is contained in:
Christian Hunziker
2025-05-07 08:06:28 +00:00
26 changed files with 1438 additions and 273 deletions
@@ -6,7 +6,7 @@
{
Task<Instruction> GetInstructionAsync(Guid instructionId);
Task<Instruction> CreateInstructionToRecipeAsync(Guid recipeId, string description);
Task<Instruction> CreateInstructionAsync(Guid recipeId, string description, IFormFile? photo);
Task RemoveInstructionFromRecipeAsync(Guid recipeId, Guid instructionId);
@@ -2,6 +2,7 @@
{
using Francesco.Recipes.World.Data;
using Francesco.Recipes.World.Models.BackendModels.Instruction;
using Francesco.Recipes.World.Models.BackendModels.MediaFile;
using Francesco.Recipes.World.Repositories.Recipe;
using Microsoft.EntityFrameworkCore;
@@ -22,7 +23,7 @@
return instruction ?? throw new InvalidDataException($"Instruction {instructionId} not found.");
}
public async Task<Instruction> CreateInstructionToRecipeAsync(Guid recipeId, string description)
public async Task<Instruction> CreateInstructionAsync(Guid recipeId, string description, IFormFile? photo)
{
if (string.IsNullOrWhiteSpace(description))
{
@@ -38,8 +39,11 @@
throw new ArgumentException("Recipe not found.", nameof(recipeId));
}
var nextNumber = recipe.Instructions?.Max(i => i.Number) ?? 0;
nextNumber++;
var nextNumber = 1;
if (recipe.Instructions != null && recipe.Instructions.Any())
{
nextNumber = recipe.Instructions.Max(i => i.Number) + 1;
}
var newInstruction = new Instruction
{
@@ -52,6 +56,24 @@
_context.Instructions.Add(newInstruction);
await _context.SaveChangesAsync();
if (photo != null && photo.Length > 0)
{
using var memoryStream = new MemoryStream();
await photo.CopyToAsync(memoryStream);
var instructionImage = new MediaFile
{
FileName = photo.FileName,
MimeType = photo.ContentType,
Data = memoryStream.ToArray(),
Instruction = newInstruction,
Recipe = null,
};
_context.Add(instructionImage);
await _context.SaveChangesAsync();
}
return newInstruction;
}
@@ -88,6 +110,7 @@
public async Task<List<Instruction>> GetInstructionsOfRecipeAsync(Guid recipeId)
{
var instructions = await _context.Instructions
.Include(i => i.MediaFiles)
.Where(i => i.Recipe.Id == recipeId)
.OrderBy(i => i.Number)
.ToListAsync();
@@ -64,6 +64,7 @@
MimeType = photo.ContentType,
Data = memoryStream.ToArray(),
Instruction = instruction,
Recipe = null,
};
_context.Add(instructionImage);
@@ -73,44 +74,52 @@
public async Task UploadRecipeMediaAsync(Guid recipeId, IFormFile mediaFile)
{
if (mediaFile == null)
if (mediaFile == null || mediaFile.Length == 0)
{
throw new ArgumentNullException(nameof(mediaFile));
return;
}
var recipe = await _recipeRepository.GetRecipeAsync(recipeId);
var isImage = mediaFile.ContentType.StartsWith("image/");
var isVideo = mediaFile.ContentType.StartsWith("video/");
if (!isImage && !isVideo)
try
{
throw new InvalidOperationException("Only image or video files are allowed.");
var recipe = await _recipeRepository.GetRecipeAsync(recipeId);
var isImage = mediaFile.ContentType.StartsWith("image/");
var isVideo = mediaFile.ContentType.StartsWith("video/");
if (!isImage && !isVideo)
{
throw new InvalidOperationException("Only image or video files are allowed.");
}
if (isImage)
{
await RemoveExistingMediaAsync(recipe, "image/");
}
else
{
await RemoveExistingMediaAsync(recipe, "video/");
}
using var memoryStream = new MemoryStream();
await mediaFile.CopyToAsync(memoryStream);
var newMedia = new MediaFile
{
Id = Guid.NewGuid(),
FileName = mediaFile.FileName,
MimeType = mediaFile.ContentType,
Data = memoryStream.ToArray(),
Recipe = recipe,
Instruction = null,
};
_context.MediaFiles.Add(newMedia);
await _context.SaveChangesAsync();
}
if (isImage)
catch (Exception ex)
{
await RemoveExistingMediaAsync(recipe, "image/");
throw new InvalidOperationException("An error occurred while uploading the media file.", ex);
}
else
{
await RemoveExistingMediaAsync(recipe, "video/");
}
using var memoryStream = new MemoryStream();
await mediaFile.CopyToAsync(memoryStream);
var newMedia = new MediaFile
{
Id = Guid.NewGuid(),
FileName = mediaFile.FileName,
MimeType = mediaFile.ContentType,
Data = memoryStream.ToArray(),
Recipe = recipe,
};
_context.MediaFiles.Add(newMedia);
await _context.SaveChangesAsync();
}
private async Task RemoveExistingMediaAsync(Recipe recipe, string mediaTypePrefix)
@@ -9,7 +9,7 @@
Task<Recipe?> GetRecipeByIdAsync(Guid id);
Task AddOrCreateIngredientToRecipeAsync(Guid recipeId, string ingredientName, int quantity, Guid unitId);
Task CreateRecipeIngredientAsync(Guid recipeId, string ingredientName, int quantity, Guid unitId);
Task RemoveIngredientFromRecipeAsync(Guid recipeId, Guid ingredientId);
@@ -41,7 +41,7 @@
.FirstOrDefaultAsync(r => r.Id == recipeId);
}
public async Task AddOrCreateIngredientToRecipeAsync(Guid recipeId, string ingredientName, int quantity, Guid unitId)
public async Task CreateRecipeIngredientAsync(Guid recipeId, string ingredientName, int quantity, Guid unitId)
{
var recipe = await GetRecipeAsync(recipeId);
var unit = await _unitRepository.GetUnitByIdAsync(unitId);
@@ -8,6 +8,6 @@
Task<Unit> AddUnitAsync(string name, string symbol);
Task<IEnumerable<Unit>> GetAllUnitsAsync();
Task<List<Unit>> GetAllUnitsAsync();
}
}
@@ -35,7 +35,7 @@
return unit;
}
public async Task<IEnumerable<Unit>> GetAllUnitsAsync()
public async Task<List<Unit>> GetAllUnitsAsync()
{
return await _context.Units.ToListAsync();
}