updates to editrecipe

This commit is contained in:
LilleBRG 2025-05-14 11:58:49 +02:00
parent 5c924026ed
commit 4a935514cf
13 changed files with 196 additions and 18 deletions

View File

@ -3,6 +3,7 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id("kotlin-parcelize")
id("org.jetbrains.kotlin.plugin.serialization")
}

View File

@ -52,6 +52,10 @@
android:name=".ui.dishes.DishDetailsActivity"
android:exported="false" />
<activity
android:name=".ui.dishes.EditDishActivity"
android:exported="false" />
<activity
android:name=".ui.profile.ChangePasswordActivity"
android:exported="false" />

View File

@ -112,11 +112,7 @@ fun changePassword(ctx: Context, oldPassword: String, newPassword: String) {
return requestJson<ChangePasswordRequest, Unit>(ctx, "PUT", "/api/User/change-password", request)
}
@Serializable
data class ShoppingListAddRecipeRequest(val multiplier: String)
fun AddRecipeToShoppingList(ctx: Context, id: Int, multiplier: String): Boolean {
fun AddRecipeToShoppingList(ctx: Context, id: Int, multiplier: String) {
val request = ShoppingListAddRecipeRequest(multiplier)
return requestJson<ShoppingListAddRecipeRequest, Unit>(ctx, "POST", "/api/ShoppingList/recipeadd/$id", request)
return requestJson<String, Boolean>(ctx, "POST", "/api/ShoppingList/recipeadd/$id", multiplier)
}

View File

@ -16,6 +16,10 @@ fun createRecipe(ctx: Context, recipe: Recipe) {
requestJson<Recipe, Boolean>(ctx, "POST", "/api/recipe/create", recipe)
}
fun updateRecipe(ctx: Context, id: Int, recipe: Recipe) {
requestJson<Recipe, Boolean>(ctx, "PUT", "/api/recipe/edit/$id", recipe)
}
@Serializable
data class GetAllRecipesResponse(val id: Int, val name: String, val description: String)
@ -24,9 +28,9 @@ fun getAllRecipes(ctx: Context): List<GetAllRecipesResponse> {
}
@Serializable
data class RecipeDetailsResponse(val id: Int, val name: String, val description: String, val directions: List<String>, val ingredients: List<Ingredient>)
data class RecipeDetailsResponse(val recipe: Recipe)
fun getRecipeDetails(ctx: Context, id: Int): RecipeDetailsResponse {
return requestJson<Unit, RecipeDetailsResponse>(ctx, "GET", "/api/Recipe/get/$id", null)
fun getRecipeDetails(ctx: Context, id: Int): Recipe {
return requestJson<Unit, Recipe>(ctx, "GET", "/api/Recipe/get/$id", null)
}

View File

@ -2,6 +2,7 @@ package tech.mercantec.easyeat.models
import kotlinx.serialization.Serializable
@Serializable
data class Recipe(
val id: Int? = null,

View File

@ -25,7 +25,7 @@ class CreateDishActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_create_dish_form)
setContentView(R.layout.activity_dish_form)
ingredientContainer = findViewById(R.id.ingredientContainer)
val addButton: Button = findViewById(R.id.addIngredientButton)
@ -84,7 +84,7 @@ class CreateDishActivity : AppCompatActivity() {
private fun addIngredientRow() {
val inflater = LayoutInflater.from(this)
val ingredientRow = inflater.inflate(R.layout.activity_create_dish_ingredient_row, null)
val ingredientRow = inflater.inflate(R.layout.activity_dish_ingredient_row, null)
val spinnerMeasurements = ingredientRow.findViewById<Spinner>(R.id.measurementsDropDown)
spinnerMeasurements.adapter = ArrayAdapter(
this,

View File

@ -2,17 +2,17 @@ package tech.mercantec.easyeat.ui.dishes
import android.app.Activity
import android.app.ProgressDialog
import android.content.Intent
import android.os.Bundle
import android.text.Html
import android.util.Log
import android.view.View
import android.view.ViewGroup
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Toast
import tech.mercantec.easyeat.R
import tech.mercantec.easyeat.helpers.ApiRequestException
import tech.mercantec.easyeat.helpers.RecipeDetailsResponse
import tech.mercantec.easyeat.helpers.getRecipeDetails
import kotlin.concurrent.thread
import android.widget.EditText
@ -22,6 +22,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doAfterTextChanged
import tech.mercantec.easyeat.helpers.AddRecipeToShoppingList
import tech.mercantec.easyeat.models.Ingredient
import tech.mercantec.easyeat.models.Recipe
class DishDetailsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -39,7 +40,7 @@ class DishDetailsActivity : AppCompatActivity() {
}
thread {
val recipe: RecipeDetailsResponse
val recipe: Recipe
try {
recipe = getRecipeDetails(this, dishId)
} catch (e: ApiRequestException) {
@ -143,13 +144,21 @@ class DishDetailsActivity : AppCompatActivity() {
}
runOnUiThread {
Toast.makeText(this, "Password changed successfully", Toast.LENGTH_LONG).show()
Toast.makeText(this, "Recipe ingredients added to shopping", Toast.LENGTH_LONG).show()
}
setResult(Activity.RESULT_OK)
finish()
}
}
val editRecipeBtn: Button = findViewById(R.id.editRecipeBtn)
editRecipeBtn.setOnClickListener {
val jsonRecipe = Json.encodeToString(recipe) // convert Recipe to JSON string
val intent = Intent(this, EditDishActivity::class.java)
intent.putExtra("recipe_json", jsonRecipe) // put as string
startActivity(intent)
}
}
}

View File

@ -0,0 +1,154 @@
package tech.mercantec.easyeat.ui.dishes
import android.app.Activity
import android.app.ProgressDialog
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.Spinner
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import tech.mercantec.easyeat.R
import tech.mercantec.easyeat.helpers.ApiRequestException
import tech.mercantec.easyeat.helpers.createRecipe
import tech.mercantec.easyeat.helpers.updateRecipe
import tech.mercantec.easyeat.models.Ingredient
import tech.mercantec.easyeat.models.Recipe
import kotlin.concurrent.thread
class EditDishActivity : AppCompatActivity() {
private lateinit var ingredientContainer: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dish_form)
val recipe: Recipe? = intent.getStringExtra("recipe_json")?.let {
try {
Json.decodeFromString<Recipe>(it)
} catch (e: Exception) {
null
}
}
val dishName = findViewById<EditText>(R.id.dishName)
val dishDescription = findViewById<EditText>(R.id.dishDescription)
val instructions = findViewById<EditText>(R.id.instructions)
val saveButton = findViewById<Button>(R.id.saveDishButton)
ingredientContainer = findViewById(R.id.ingredientContainer)
// Populate UI
dishName.setText(recipe?.name)
dishDescription.setText(recipe?.description)
instructions.setText(recipe?.directions?.joinToString("\n"))
for (ingredient in recipe?.ingredients!!) {
addIngredientRow(ingredient)
}
findViewById<Button>(R.id.addIngredientButton).setOnClickListener {
addIngredientRow()
}
saveButton.setOnClickListener {
saveButton.setOnClickListener {
val ingredientList = collectIngredients()
val instructions = findViewById<EditText>(R.id.instructions).text.toString().trim()
val directions: List<String> = instructions
.split("\n")
.map { line -> line.trim() }
.filter { it.isNotEmpty() }
val updatedRecipe = Recipe(
name = findViewById<EditText>(R.id.dishName).text.toString().trim(),
description = findViewById<EditText>(R.id.dishDescription).text.toString().trim(),
directions = directions,
ingredients = ingredientList
)
val progressDialog = ProgressDialog(this)
progressDialog.setMessage("Loading...")
progressDialog.show()
thread {
try {
updateRecipe(this, recipe.id!!, updatedRecipe)
} catch (e: ApiRequestException) {
runOnUiThread {
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
}
return@thread
} finally {
runOnUiThread {
progressDialog.hide()
}
}
runOnUiThread {
Toast.makeText(this, "Password changed successfully", Toast.LENGTH_LONG).show()
}
setResult(Activity.RESULT_OK)
finish()
}
}
}
}
private fun addIngredientRow(ingredient: Ingredient? = null) {
val inflater = LayoutInflater.from(this)
val ingredientRow = inflater.inflate(R.layout.activity_dish_ingredient_row, null)
val nameField = ingredientRow.findViewById<EditText>(R.id.ingredientNameEditText)
val amountField = ingredientRow.findViewById<EditText>(R.id.ingredientAmountEditText)
val unitSpinner = ingredientRow.findViewById<Spinner>(R.id.measurementsDropDown)
unitSpinner.adapter = ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
listOf("g", "kg", "ml", "l", "tsp", "tbsp", "cup", "pcs", "pinch", "dash")
)
if (ingredient != null) {
nameField.setText(ingredient.name)
amountField.setText(ingredient.amount.toString())
unitSpinner.setSelection((unitSpinner.adapter as ArrayAdapter<String>).getPosition(ingredient.unit))
}
ingredientRow.findViewById<ImageButton>(R.id.removeButton).setOnClickListener {
ingredientContainer.removeView(ingredientRow)
}
ingredientContainer.addView(ingredientRow)
}
private fun collectIngredients(): List<Ingredient> {
val ingredients = mutableListOf<Ingredient>()
for (i in 0 until ingredientContainer.childCount) {
val ingredientView = ingredientContainer.getChildAt(i)
// Find views inside this ingredient row
val ingredientEditText = ingredientView.findViewById<EditText>(R.id.ingredientNameEditText)
val amountEditText = ingredientView.findViewById<EditText>(R.id.ingredientAmountEditText)
val spinner = ingredientView.findViewById<Spinner>(R.id.measurementsDropDown)
val element = ingredientEditText.text.toString().trim()
val amount = amountEditText.text.toString().trim()
val unit = spinner.selectedItem.toString()
// Optional: Only add non-empty rows
if (element.isNotEmpty() && amount.isNotEmpty()) {
ingredients.add(Ingredient(name = element, amount = amount.toDouble(), unit = unit))
}
}
return ingredients
}
}

View File

@ -9,7 +9,15 @@
android:layout_height="wrap_content"
android:padding="30sp"
android:orientation="vertical">
<Button
android:id="@+id/editRecipeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:backgroundTint="@color/cyan"
android:text="@string/edit_recipe"
android:tint="@android:color/white"
/>
<TextView
android:id="@+id/dishDetailName"
android:layout_width="match_parent"

View File

@ -56,6 +56,7 @@
<string name="instructions_label">Instructions</string>
<string name="increment_multiplier_desc">Increment portion count</string>
<string name="decrement_multiplier_desc">Decrement portion size</string>
<string name="edit_recipe">Edit Recipe</string>
<string-array name="units">
<item></item>
<item>g</item>

View File

@ -111,7 +111,7 @@ namespace API.BusinessLogic
foreach (var item in recipes)
{
if (item.Name == recipe.Name)
if (item.Name == recipe.Name && item.Name != dish.Name)
{
return new ConflictObjectResult(new { message = "Recipe name is already in use." });
}