From 14cf727e2202ced4816e6e453a5994e17aac797a Mon Sep 17 00:00:00 2001 From: Jeas0001 Date: Tue, 13 May 2025 12:13:07 +0200 Subject: [PATCH 1/4] Made it possible to set a multiplier on recipeadd --- .../API/BusinessLogic/ShoppingListLogic.cs | 49 ++++++++++--------- .../API/Controllers/ShoppingListController.cs | 4 +- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/backend/API/BusinessLogic/ShoppingListLogic.cs b/backend/API/BusinessLogic/ShoppingListLogic.cs index bcadc5c..dd61249 100644 --- a/backend/API/BusinessLogic/ShoppingListLogic.cs +++ b/backend/API/BusinessLogic/ShoppingListLogic.cs @@ -111,38 +111,41 @@ namespace API.BusinessLogic } // Adds an entire recipes ingredients to the shoppinglist - public async Task AddRecipeToShoppingList(int userId, int recipeId) + public async Task AddRecipeToShoppingList(int userId, int recipeId, int multiplier) { var user = await _dbAccess.ReadShoppingList(userId); var recipe = await _recipeDBAccess.ReadRecipe(recipeId); var ingredients = recipe.Ingredients; - - foreach (var ingredient in ingredients) + + for (int i = 0; i < multiplier; i++) { - List shoppingList = user.ShoppingList; - - if (shoppingList.Any(s => s.Name == ingredient.Name)) + foreach (var ingredient in ingredients) { - ShoppingListItem item = shoppingList.Where(s => s.Name == ingredient.Name).FirstOrDefault(); - shoppingList.Remove(item); + List shoppingList = user.ShoppingList; - ShoppingListItemDTO listItemDTO = new ShoppingListItemDTO(); - listItemDTO.Name = ingredient.Name; - listItemDTO.Amount = ingredient.Amount; - listItemDTO.Unit = ingredient.Unit; - listItemDTO.Checked = false; + if (shoppingList.Any(s => s.Name == ingredient.Name)) + { + ShoppingListItem item = shoppingList.Where(s => s.Name == ingredient.Name).FirstOrDefault(); + shoppingList.Remove(item); - user.ShoppingList.Add(await UnitAdjustmentSameName(listItemDTO, item)); - } - else - { - ShoppingListItem newItem = new ShoppingListItem(); - newItem.Name = ingredient.Name; - newItem.Amount = ingredient.Amount; - newItem.Unit = ingredient.Unit; - newItem.Checked = false; + ShoppingListItemDTO listItemDTO = new ShoppingListItemDTO(); + listItemDTO.Name = ingredient.Name; + listItemDTO.Amount = ingredient.Amount; + listItemDTO.Unit = ingredient.Unit; + listItemDTO.Checked = false; - user.ShoppingList.Add(await UnitAdjustment(newItem)); + user.ShoppingList.Add(await UnitAdjustmentSameName(listItemDTO, item)); + } + else + { + ShoppingListItem newItem = new ShoppingListItem(); + newItem.Name = ingredient.Name; + newItem.Amount = ingredient.Amount; + newItem.Unit = ingredient.Unit; + newItem.Checked = false; + + user.ShoppingList.Add(await UnitAdjustment(newItem)); + } } } diff --git a/backend/API/Controllers/ShoppingListController.cs b/backend/API/Controllers/ShoppingListController.cs index ddeb6c1..e4c049c 100644 --- a/backend/API/Controllers/ShoppingListController.cs +++ b/backend/API/Controllers/ShoppingListController.cs @@ -100,12 +100,12 @@ namespace API.Controllers /// returns a okobjectresult with a boolean that is true if it fails it returns a confliftobjectresult with a message of why it failed [Authorize] [HttpPost("recipeadd")] - public async Task AddARecipesItems(int recipeId) + public async Task AddARecipesItems(int recipeId, int multiplier = 1) { var claims = HttpContext.User.Claims; string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value; int userId = Convert.ToInt32(userIdString); - return await _shoppingListLogic.AddRecipeToShoppingList(userId, recipeId); + return await _shoppingListLogic.AddRecipeToShoppingList(userId, recipeId, multiplier); } } } From 4772c0ef2639fcb2043e9e59dcd832e9383c176b Mon Sep 17 00:00:00 2001 From: Reimar Date: Tue, 13 May 2025 12:41:10 +0200 Subject: [PATCH 2/4] Create recipe fragment --- .../easyeat/ui/dishes/RecipeFragment.kt | 54 +++++++++++++++++++ .../src/main/res/layout/fragment_recipe.xml | 48 +++++++++++++++++ app/app/src/main/res/values-night/styles.xml | 6 +++ app/app/src/main/res/values/strings.xml | 2 + app/app/src/main/res/values/styles.xml | 6 +++ 5 files changed, 116 insertions(+) create mode 100644 app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/RecipeFragment.kt create mode 100644 app/app/src/main/res/layout/fragment_recipe.xml create mode 100644 app/app/src/main/res/values-night/styles.xml create mode 100644 app/app/src/main/res/values/styles.xml diff --git a/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/RecipeFragment.kt b/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/RecipeFragment.kt new file mode 100644 index 0000000..2639315 --- /dev/null +++ b/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/RecipeFragment.kt @@ -0,0 +1,54 @@ +package tech.mercantec.easyeat.ui.dishes + +import android.os.Bundle +import android.text.Html +import android.text.Html.FROM_HTML_MODE_LEGACY +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import kotlinx.serialization.json.Json +import tech.mercantec.easyeat.R +import tech.mercantec.easyeat.models.Recipe + +class RecipeFragment : Fragment() { + private var recipe: Recipe? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + arguments?.let { args -> + recipe = args.getString("RECIPE")?.let { Json.decodeFromString(it) } + } + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?, + ): View? { + val binding = inflater.inflate(R.layout.fragment_recipe, container, false) + + recipe?.let { recipe -> + binding.findViewById(R.id.title).text = recipe.name + + binding.findViewById(R.id.ingredients).text = + Html.fromHtml( + "
    " + + recipe.ingredients.map { "
  • ${it.amount} ${it.unit} ${it.name}
  • " } + + "
", + FROM_HTML_MODE_LEGACY + ) + + binding.findViewById(R.id.directions).text = + Html.fromHtml( + "
    " + + recipe.directions.map { "
  • ${it}
  • " } + + "
", + FROM_HTML_MODE_LEGACY + ) + } + + return binding + } +} \ No newline at end of file diff --git a/app/app/src/main/res/layout/fragment_recipe.xml b/app/app/src/main/res/layout/fragment_recipe.xml new file mode 100644 index 0000000..8b66e2d --- /dev/null +++ b/app/app/src/main/res/layout/fragment_recipe.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + diff --git a/app/app/src/main/res/values-night/styles.xml b/app/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..4aa21da --- /dev/null +++ b/app/app/src/main/res/values-night/styles.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/app/src/main/res/values/strings.xml b/app/app/src/main/res/values/strings.xml index e7d5584..367630e 100644 --- a/app/app/src/main/res/values/strings.xml +++ b/app/app/src/main/res/values/strings.xml @@ -47,6 +47,8 @@ Generate recipe with AI Name of dish Generate + Ingredients + Directions g diff --git a/app/app/src/main/res/values/styles.xml b/app/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..560b559 --- /dev/null +++ b/app/app/src/main/res/values/styles.xml @@ -0,0 +1,6 @@ + + + + From 1c085a4262c0445bfbe6859a572793e38e1f93b3 Mon Sep 17 00:00:00 2001 From: Reimar Date: Tue, 13 May 2025 12:59:18 +0200 Subject: [PATCH 3/4] Finish generating recipe, refactor directions property and request helpers --- app/app/src/main/AndroidManifest.xml | 2 +- .../tech/mercantec/easyeat/helpers/auth.kt | 32 ++----------------- .../tech/mercantec/easyeat/helpers/dishes.kt | 19 +++++++++++ .../mercantec/easyeat/models/CreateRecipe.kt | 24 -------------- .../tech/mercantec/easyeat/models/recipe.kt | 5 ++- .../easyeat/ui/dishes/CreateDishActivity.kt | 18 ++++------- .../easyeat/ui/dishes/DishesFragment.kt | 6 ++-- ...IActivity.kt => GenerateRecipeActivity.kt} | 28 ++++++++-------- .../easyeat/ui/dishes/InstructionsAdapter.kt | 9 +++--- ..._form.xml => activity_generate_recipe.xml} | 0 10 files changed, 52 insertions(+), 91 deletions(-) delete mode 100644 app/app/src/main/java/tech/mercantec/easyeat/models/CreateRecipe.kt rename app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/{CreateDishAIActivity.kt => GenerateRecipeActivity.kt} (66%) rename app/app/src/main/res/layout/{create_dish_ai_form.xml => activity_generate_recipe.xml} (100%) diff --git a/app/app/src/main/AndroidManifest.xml b/app/app/src/main/AndroidManifest.xml index 10e464a..e1e0150 100644 --- a/app/app/src/main/AndroidManifest.xml +++ b/app/app/src/main/AndroidManifest.xml @@ -45,7 +45,7 @@ android:exported="false" /> (ctx, "POST", "/api/User/login", request) - with (ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) { + with(ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) { putInt("user-id", response.id) putString("username", response.userName) putString("auth-token", response.token) @@ -30,7 +25,7 @@ fun login(ctx: Context, email: String, password: String) { } fun logout(ctx: Context) { - with (ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) { + with(ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) { remove("user-id") remove("username") remove("auth-token") @@ -114,26 +109,3 @@ fun changePassword(ctx: Context, oldPassword: String, newPassword: String) { return requestJson(ctx, "PUT", "/api/User/change-password", request) } - -@Serializable -data class CreateRecipeRequest(val name: String, val description: String, val directions: List, val ingredients: List) - -fun createRecipe(ctx: Context, recipe: CreateRecipe) { - val request = CreateRecipeRequest(recipe.name, recipe.description, recipe.directions, recipe.ingredients) - - requestJson(ctx, "POST", "/api/recipe/create", request) -} - -@Serializable -data class GetAllRecipesResponse(val id: Int, val name: String, val description: String) - -fun getAllRecipies(ctx: Context): List { - return requestJson>(ctx, "GET", "/api/Recipe/getall", null) -} - -@Serializable -data class RecipeDetailsResponse(val id: Int, val name: String, val description: String, val directions: List, val ingredients: List) - -fun getRecipeDetails(ctx: Context, id: Int): RecipeDetailsResponse { - return requestJson(ctx, "GET", "/api/Recipe/get/$id", null) -} diff --git a/app/app/src/main/java/tech/mercantec/easyeat/helpers/dishes.kt b/app/app/src/main/java/tech/mercantec/easyeat/helpers/dishes.kt index e0aa866..4a7a599 100644 --- a/app/app/src/main/java/tech/mercantec/easyeat/helpers/dishes.kt +++ b/app/app/src/main/java/tech/mercantec/easyeat/helpers/dishes.kt @@ -2,6 +2,7 @@ package tech.mercantec.easyeat.helpers import android.content.Context import kotlinx.serialization.Serializable +import tech.mercantec.easyeat.models.Ingredient import tech.mercantec.easyeat.models.Recipe @Serializable @@ -10,3 +11,21 @@ data class GenerateRecipeRequest(val dish: String, val language: String, val num fun generateRecipeWithAI(ctx: Context, title: String, language: String): Recipe { return requestJson(ctx, "POST", "/api/Recipe/chatbot", GenerateRecipeRequest(title, language, 1, arrayOf())) } + +fun createRecipe(ctx: Context, recipe: Recipe) { + requestJson(ctx, "POST", "/api/recipe/create", recipe) +} + +@Serializable +data class GetAllRecipesResponse(val id: Int, val name: String, val description: String) + +fun getAllRecipes(ctx: Context): List { + return requestJson>(ctx, "GET", "/api/Recipe/getall", null) +} + +@Serializable +data class RecipeDetailsResponse(val id: Int, val name: String, val description: String, val directions: List, val ingredients: List) + +fun getRecipeDetails(ctx: Context, id: Int): RecipeDetailsResponse { + return requestJson(ctx, "GET", "/api/Recipe/get/$id", null) +} diff --git a/app/app/src/main/java/tech/mercantec/easyeat/models/CreateRecipe.kt b/app/app/src/main/java/tech/mercantec/easyeat/models/CreateRecipe.kt deleted file mode 100644 index 782f449..0000000 --- a/app/app/src/main/java/tech/mercantec/easyeat/models/CreateRecipe.kt +++ /dev/null @@ -1,24 +0,0 @@ -package tech.mercantec.easyeat.models - -import kotlinx.serialization.Serializable - -@Serializable -data class CreateRecipe( - val name: String, - val description: String, - val directions: List, - val ingredients: List -) - -@Serializable -data class CreateDirection( - val instructions: String -) - - -@Serializable -data class CreateIngredient( - val amount: Double?, - val unit: String?, - val name: String -) \ No newline at end of file diff --git a/app/app/src/main/java/tech/mercantec/easyeat/models/recipe.kt b/app/app/src/main/java/tech/mercantec/easyeat/models/recipe.kt index 86e5796..2ee35ed 100644 --- a/app/app/src/main/java/tech/mercantec/easyeat/models/recipe.kt +++ b/app/app/src/main/java/tech/mercantec/easyeat/models/recipe.kt @@ -2,10 +2,9 @@ package tech.mercantec.easyeat.models import kotlinx.serialization.Serializable - @Serializable data class Recipe( - val id: Int, + val id: Int? = null, val name: String, val description: String, val directions: List, @@ -14,7 +13,7 @@ data class Recipe( @Serializable data class Ingredient( - val id: Int, + val id: Int? = null, val amount: Double?, val unit: String?, val name: String diff --git a/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/CreateDishActivity.kt b/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/CreateDishActivity.kt index 2ece5a7..b5cf99f 100644 --- a/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/CreateDishActivity.kt +++ b/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/CreateDishActivity.kt @@ -2,9 +2,7 @@ package tech.mercantec.easyeat.ui.dishes import android.app.Activity import android.app.ProgressDialog -import android.content.Context import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.widget.ArrayAdapter import android.widget.Button @@ -14,15 +12,11 @@ import android.widget.LinearLayout import android.widget.Spinner import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContentProviderCompat.requireContext import tech.mercantec.easyeat.R import tech.mercantec.easyeat.helpers.ApiRequestException -import tech.mercantec.easyeat.helpers.changePassword import tech.mercantec.easyeat.helpers.createRecipe -import tech.mercantec.easyeat.helpers.request -import tech.mercantec.easyeat.models.CreateDirection -import tech.mercantec.easyeat.models.CreateIngredient -import tech.mercantec.easyeat.models.CreateRecipe +import tech.mercantec.easyeat.models.Ingredient +import tech.mercantec.easyeat.models.Recipe import kotlin.concurrent.thread class CreateDishActivity : AppCompatActivity() { @@ -53,7 +47,7 @@ class CreateDishActivity : AppCompatActivity() { .map { line -> line.trim() } .filter { it.isNotEmpty() } - val recipe = CreateRecipe( + val recipe = Recipe( name = findViewById(R.id.dishName).text.toString().trim(), description = findViewById(R.id.dishDescription).text.toString().trim(), directions = directions, @@ -107,8 +101,8 @@ class CreateDishActivity : AppCompatActivity() { ingredientContainer.addView(ingredientRow) } - private fun collectIngredients(): List { - val ingredients = mutableListOf() + private fun collectIngredients(): List { + val ingredients = mutableListOf() for (i in 0 until ingredientContainer.childCount) { val ingredientView = ingredientContainer.getChildAt(i) @@ -125,7 +119,7 @@ class CreateDishActivity : AppCompatActivity() { // Optional: Only add non-empty rows if (element.isNotEmpty() && amount.isNotEmpty()) { - ingredients.add(CreateIngredient(name = element, amount = amount.toDouble(), unit = unit)) + ingredients.add(Ingredient(name = element, amount = amount.toDouble(), unit = unit)) } } diff --git a/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/DishesFragment.kt b/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/DishesFragment.kt index 4e1a301..93e06c7 100644 --- a/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/DishesFragment.kt +++ b/app/app/src/main/java/tech/mercantec/easyeat/ui/dishes/DishesFragment.kt @@ -15,7 +15,7 @@ import tech.mercantec.easyeat.R import tech.mercantec.easyeat.databinding.FragmentDishesBinding import tech.mercantec.easyeat.helpers.ApiRequestException import tech.mercantec.easyeat.helpers.GetAllRecipesResponse -import tech.mercantec.easyeat.helpers.getAllRecipies +import tech.mercantec.easyeat.helpers.getAllRecipes import tech.mercantec.easyeat.models.DishListItem import kotlin.concurrent.thread @@ -52,7 +52,7 @@ class DishesFragment : Fragment() { } dialogView.findViewById