3900-MyRecipes-backup / Server / Controllers / RecipeController.cs
RecipeController.cs
Raw
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();
        }
    }
}