using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using System.Security.Claims; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using MyRecipes2.Server.Data; using MyRecipes2.Server.Models; using MyRecipes2.Shared; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace MyRecipes2.Server.Controllers { [ApiController] public class RecipeController : ControllerBase { private readonly ApplicationDbContext dbContext; public RecipeController(ApplicationDbContext dbContext) { this.dbContext = dbContext; } public static RecipeDto CreateRecipeDto(Recipe recipe) { RecipeDto result = new RecipeDto(); result.Id = recipe.Id; result.CreatedDateTime = recipe.CreatedDateTime; result.LastModified = recipe.LastModified; result.Name = recipe.Name; result.Author = recipe.CreatedBy.UserName; result.Author_id = recipe.CreatedBy.Id; result.Calories = recipe.Ingredients.Aggregate("0", (total, current) => (Convert.ToDouble(total) + Convert.ToDouble(current.Calories)).ToString()); ; result.Ingredients = new List<IngredientDto>(); result.ImageId = recipe.Image?.Id; if (recipe.Image != null) { result.ImageUrl = $"/Image/{result.ImageId}"; } if (recipe.CreatedBy.Image == null) { result.AuthorImageUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktcGVyc29uLWNpcmNsZSIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNMTEgNmEzIDMgMCAxIDEtNiAwIDMgMyAwIDAgMSA2IDB6Ii8+CiAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMCA4YTggOCAwIDEgMSAxNiAwQTggOCAwIDAgMSAwIDh6bTgtN2E3IDcgMCAwIDAtNS40NjggMTEuMzdDMy4yNDIgMTEuMjI2IDQuODA1IDEwIDggMTBzNC43NTcgMS4yMjUgNS40NjggMi4zN0E3IDcgMCAwIDAgOCAxeiIvPgo8L3N2Zz4="; } else { result.AuthorImageUrl = $"/Image/{recipe.CreatedBy.Image.Id}"; } for (int i = 0; i < recipe.Ingredients.Count; i++) { var ing = recipe.Ingredients[i]; var ingDTO = new IngredientDto(); ingDTO.Name = ing.Name; ingDTO.Quantity = ing.Quantity; ingDTO.Unit = ing.Unit; ingDTO.Calories = ing.Calories; result.Ingredients.Add(ingDTO); } result.Likes = recipe.Likes == null ? 0 : recipe.Likes.Count; result.Estimated_Cost = recipe.Estimated_Cost; result.Comments = recipe.Comments .OrderByDescending(x => x.CreatedDateTime) .Select(c => { var cDTO = new CommentDto(); cDTO.Text = c.Text; cDTO.Time = c.CreatedDateTime.ToString(); cDTO.User = c.CreatedBy?.UserName; return cDTO; }).ToList(); result.Method = new List<string>(); for (int i = 0; i < recipe.Method.Count; i++) { MethodStep m = recipe.Method[i]; result.Method.Add(m.Text); } result.MealTypes = recipe.RecipeMealTypes.Select(x => { MealTypeDto res = new MealTypeDto(); res.Id = x.MealType.Id; res.Name = x.MealType.Name; return res; }).ToList(); result.Likes = recipe.Likes.Count(); return result; } [HttpGet] [Route("[controller]/{recipeId}")] public RecipeDto Get(int recipeId) { Recipe recipe = dbContext.Recipes .Where(x => x.Id == recipeId) .Include(x => x.CreatedBy) .ThenInclude(u => u.Image) .Include(x => x.Ingredients) .Include(x => x.Comments) .Include(a => a.Comments) .ThenInclude(c => c.CreatedBy) .Include(x => x.Image) .Include(x => x.Method) .Include(x => x.Likes) .Include(x => x.RecipeMealTypes) .ThenInclude(rmt => rmt.MealType) .First(); return CreateRecipeDto(recipe); } [HttpDelete] [Route("[controller]/{recipeId}")] public void Delete(int recipeId) { Recipe recipe = dbContext.Recipes .Include(r => r.Image) .Include(r => r.Ingredients) .Include(r => r.Method) .Include(r => r.Likes) .Include(r => r.Comments) .Include(x => x.RecipeMealTypes) .ThenInclude(rmt => rmt.MealType) .Where(x => x.Id == recipeId).First(); dbContext.Recipes.Remove(recipe); dbContext.SaveChanges(); } //Controller for recipe list [HttpGet] [Route("[controller]/MyRecipes/{userId}")] public List<RecipeDto> GetUserRecipies(String userId) { Recipe[] RecipeListDb = dbContext.Recipes .Include(u => u.CreatedBy) .Where(u => u.CreatedBy.Id == userId) .ToArray(); List<RecipeDto> ResultList = new List<RecipeDto>(); foreach (var recipe in RecipeListDb) { ResultList.Add(Get(recipe.Id)); } return ResultList; } [HttpGet] [Route("[controller]/home")] public List<RecipeDto> GetHomeRecipies() { List<Recipe> recipes = dbContext.Recipes .Take(8) .Include(x => x.CreatedBy) .ThenInclude(u => u.Image) .Include(x => x.Ingredients) .Include(x => x.Comments) .Include(a => a.Comments) .ThenInclude(c => c.CreatedBy) .Include(x => x.Image) .Include(x => x.Method) .Include(x => x.Likes) .Include(x => x.RecipeMealTypes) .ThenInclude(rmt => rmt.MealType) .ToList(); return recipes.Select(x => CreateRecipeDto(x)).ToList(); } [HttpPost] [Route("[controller]")] public int Post(CreateRecipeRequestDto request) { Recipe recipe = new Recipe(); recipe.Name = request.Name; var curTime = DateTime.UtcNow; recipe.CreatedDateTime = curTime; recipe.LastModified = curTime; recipe.Comments = new List<Comment>(); recipe.CreatedBy = dbContext.Users.Where(x => x.Id == request.CreatedById).First(); if (request.ImageId != null) { recipe.Image = dbContext.Images.Where(x => x.Id == request.ImageId).First(); } recipe.Ingredients = request.Ingredients.Select(x => { Ingredient ingredient = new(); ingredient.Name = x.Name; ingredient.Quantity = x.Quantity; ingredient.Unit = x.Unit; ingredient.Calories = x.Calories; return ingredient; }).ToList(); recipe.Method = request.Method.Select(x => { MethodStep step = new(); step.Text = x; return step; }).ToList(); recipe.RecipeMealTypes = dbContext .MealTypes .Where(x => request.MealTypes.Select(y => y.Id) .Contains(x.Id)) .ToList() .Select(mt => { RecipeMealType rmt = new(); rmt.MealType = mt; return rmt; }) .ToList(); Console.WriteLine("last modified: " + recipe.LastModified); dbContext.Recipes.Add(recipe); dbContext.SaveChanges(); return recipe.Id; } [HttpPut] [Route("[controller]/{recipeId}")] public void Put(int recipeId, CreateRecipeRequestDto request) { Recipe recipe = dbContext.Recipes .Where(x => x.Id == recipeId) .Include(x => x.Ingredients) .Include(x => x.Image) .Include(x => x.Method) .Include(x => x.RecipeMealTypes) .First(); recipe.Name = request.Name; if (request.ImageId != null) { recipe.Image = dbContext.Images.Where(x => x.Id == request.ImageId).First(); } recipe.Ingredients = request.Ingredients.Select(x => { Ingredient ingredient = new(); ingredient.Name = x.Name; ingredient.Quantity = x.Quantity; ingredient.Unit = x.Unit; ingredient.Calories = x.Calories; return ingredient; }).ToList(); recipe.Method = request.Method.Select(x => { MethodStep step = new(); step.Text = x; return step; }).ToList(); recipe.RecipeMealTypes = dbContext .MealTypes .Where(x => request.MealTypes.Select(y => y.Id) .Contains(x.Id)) .ToList() .Select(mt => { RecipeMealType rmt = new(); rmt.MealType = mt; return rmt; }) .ToList(); recipe.LastModified = DateTime.UtcNow; dbContext.SaveChanges(); } [HttpPost] [Route("[controller]/search")] public List<RecipeDto> Search(RecipeSearchRequestDto request) { List<Recipe> recipes = dbContext.Recipes .Include(x => x.Ingredients) .Include(x => x.Image) .Include(x => x.Method) .Include(x => x.RecipeMealTypes) .ThenInclude(rmt => rmt.MealType) .Where(x => (string.IsNullOrWhiteSpace(request.NameSearchString) || x.Name.Contains(request.NameSearchString)) && (string.IsNullOrWhiteSpace(request.MethodSearchString) || x.Method.Any(m => m.Text.Contains(request.MethodSearchString))) && (string.IsNullOrWhiteSpace(request.IngredientSearchString) || x.Ingredients.Any(i => i.Name.Contains(request.IngredientSearchString))) && (string.IsNullOrWhiteSpace(request.MealTypeSearchString) || x.RecipeMealTypes.Any(i => i.MealType.Name == request.MealTypeSearchString)) ) .ToList(); List<RecipeDto> result = new List<RecipeDto>(); foreach (var recipe in recipes) { result.Add(Get(recipe.Id)); } return result; } public static int RecipeSimilarity(Recipe target, Recipe search) { List<Ingredient> targetIngredients = target.Ingredients.ToList(); List<Ingredient> searchIngredients = search.Ingredients.ToList(); List<string> targetList = targetIngredients.Select(x => x.Name).ToList(); int result = 0; foreach (Ingredient searchIngredient in searchIngredients) { if (targetList.Any(x => x.Contains(searchIngredient.Name, StringComparison.CurrentCultureIgnoreCase))) { result++; } } return result; } [HttpGet] [Route("[controller]/related/{recipeId}")] public List<RecipeDto> GetRelated(int recipeId) { Recipe target = dbContext.Recipes .Where(x => x.Id == recipeId) .Include(x => x.Ingredients) .First(); List<Recipe> relaited = dbContext.Recipes .Include(x => x.Ingredients) .Where(x => x.Id != recipeId) .ToList() .Where(x => RecipeSimilarity(target, x) > 0) .OrderByDescending(x => RecipeSimilarity(target, x)) .Take(4) .ToList(); return relaited.Select(x => Get(x.Id)).ToList(); } [HttpGet] [Route("[controller]/LikedRecipes/{userId}")] public List<RecipeDto> GetLikedRecipes(string userId) { List<Recipe> likedRecipes = dbContext.Likes .Where(x => x.LikedBy.Id == userId) .Include(x => x.Recipe) .Select(x => x.Recipe) .ToList(); return likedRecipes.Select(x => Get(x.Id)).ToList(); } } }