* Extended functionalities
* Added different UIs
This commit is contained in:
93
MealPlan.Api/Controllers/RecipeManagementController.cs
Normal file
93
MealPlan.Api/Controllers/RecipeManagementController.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using MealPlan.Api.DTOs.Recipe;
|
||||
using MealPlan.Api.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MealPlan.Api.Controllers;
|
||||
|
||||
/// <summary>Endpoints for creating recipes manually and importing from Excel.</summary>
|
||||
[ApiController]
|
||||
[Route("api/recipes")]
|
||||
[Authorize]
|
||||
public class RecipeManagementController : ControllerBase
|
||||
{
|
||||
private readonly IRecipeManagementService _managementService;
|
||||
private readonly IRecipeExcelService _excelService;
|
||||
|
||||
public RecipeManagementController(
|
||||
IRecipeManagementService managementService,
|
||||
IRecipeExcelService excelService)
|
||||
{
|
||||
_managementService = managementService;
|
||||
_excelService = excelService;
|
||||
}
|
||||
|
||||
/// <summary>Creates a new recipe with ingredients and steps.</summary>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(RecipeDetailDto), StatusCodes.Status201Created)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> Create([FromBody] CreateRecipeDto dto, CancellationToken ct)
|
||||
{
|
||||
var recipe = await _managementService.CreateRecipeAsync(dto, ct);
|
||||
return CreatedAtAction(
|
||||
nameof(RecipesController.GetRecipe),
|
||||
"Recipes",
|
||||
new { id = recipe.Id },
|
||||
recipe);
|
||||
}
|
||||
|
||||
/// <summary>Updates an existing recipe (replaces ingredients and steps).</summary>
|
||||
[HttpPut("{id:int}")]
|
||||
[ProducesResponseType(typeof(RecipeDetailDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> Update(int id, [FromBody] CreateRecipeDto dto, CancellationToken ct)
|
||||
{
|
||||
var recipe = await _managementService.UpdateRecipeAsync(id, dto, ct);
|
||||
return recipe is null
|
||||
? NotFound(new { error = $"Recipe {id} was not found." })
|
||||
: Ok(recipe);
|
||||
}
|
||||
|
||||
/// <summary>Downloads an Excel template for bulk recipe import.</summary>
|
||||
[HttpGet("import/template")]
|
||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||
public IActionResult DownloadTemplate()
|
||||
{
|
||||
var bytes = _excelService.GenerateTemplate();
|
||||
return File(
|
||||
bytes,
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"DailyMeals-recipe-import-template.xlsx");
|
||||
}
|
||||
|
||||
/// <summary>Imports recipes from an uploaded .xlsx file (Recipes + Ingredients + Steps sheets).</summary>
|
||||
[HttpPost("import/excel")]
|
||||
[RequestSizeLimit(10_000_000)]
|
||||
[ProducesResponseType(typeof(RecipeImportResultDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> ImportExcel(IFormFile? file, CancellationToken ct)
|
||||
{
|
||||
if (file is null || file.Length == 0)
|
||||
{
|
||||
return BadRequest(new { error = "No file uploaded." });
|
||||
}
|
||||
|
||||
if (!file.FileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return BadRequest(new { error = "Only .xlsx files are supported." });
|
||||
}
|
||||
|
||||
await using var stream = file.OpenReadStream();
|
||||
var result = await _excelService.ImportAsync(stream, ct);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>Recalculates recipe macros from linked catalog ingredients (all active recipes).</summary>
|
||||
[HttpPost("recalculate-macros")]
|
||||
[ProducesResponseType(typeof(RecipeMacroRecalcResultDto), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> RecalculateMacros(CancellationToken ct)
|
||||
{
|
||||
var result = await _managementService.RecalculateAllMacrosFromCatalogAsync(ct);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user