Merge branch 'master' of git.reim.ar:ReiMerc/easyeat
This commit is contained in:
commit
bd486fa9f7
@ -45,7 +45,7 @@
|
|||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.dishes.CreateDishAIActivity"
|
android:name=".ui.dishes.GenerateRecipeActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
@ -3,11 +3,8 @@ package tech.mercantec.easyeat.helpers
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import tech.mercantec.easyeat.models.CreateDirection
|
|
||||||
import tech.mercantec.easyeat.models.CreateIngredient
|
|
||||||
import tech.mercantec.easyeat.models.CreateRecipe
|
|
||||||
import tech.mercantec.easyeat.models.Direction
|
|
||||||
import tech.mercantec.easyeat.models.Ingredient
|
import tech.mercantec.easyeat.models.Ingredient
|
||||||
|
import tech.mercantec.easyeat.models.Recipe
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class LoginRequest(val emailUsr: String, val password: String)
|
data class LoginRequest(val emailUsr: String, val password: String)
|
||||||
@ -20,7 +17,7 @@ fun login(ctx: Context, email: String, password: String) {
|
|||||||
|
|
||||||
val response = requestJson<LoginRequest, LoginResponse>(ctx, "POST", "/api/User/login", request)
|
val response = requestJson<LoginRequest, LoginResponse>(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)
|
putInt("user-id", response.id)
|
||||||
putString("username", response.userName)
|
putString("username", response.userName)
|
||||||
putString("auth-token", response.token)
|
putString("auth-token", response.token)
|
||||||
@ -30,7 +27,7 @@ fun login(ctx: Context, email: String, password: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun logout(ctx: Context) {
|
fun logout(ctx: Context) {
|
||||||
with (ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) {
|
with(ctx.getSharedPreferences("easyeat", Context.MODE_PRIVATE).edit()) {
|
||||||
remove("user-id")
|
remove("user-id")
|
||||||
remove("username")
|
remove("username")
|
||||||
remove("auth-token")
|
remove("auth-token")
|
||||||
@ -116,24 +113,10 @@ fun changePassword(ctx: Context, oldPassword: String, newPassword: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CreateRecipeRequest(val name: String, val description: String, val directions: List<CreateDirection>, val ingredients: List<CreateIngredient>)
|
data class ShoppingListAddRecipeRequest(val id: Int, val multiplier: Int)
|
||||||
|
|
||||||
fun createRecipe(ctx: Context, recipe: CreateRecipe) {
|
fun AddRecipeToShoppingList(ctx: Context, id: Int, multiplier: Int) {
|
||||||
val request = CreateRecipeRequest(recipe.name, recipe.description, recipe.directions, recipe.ingredients)
|
val request = ShoppingListAddRecipeRequest(id, multiplier)
|
||||||
|
|
||||||
requestJson<CreateRecipeRequest, Boolean>(ctx, "POST", "/api/recipe/create", request)
|
return requestJson<ShoppingListAddRecipeRequest, Unit>(ctx, "POST", "/api/ShoppingList/recipeadd", request)
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class GetAllRecipesResponse(val id: Int, val name: String, val description: String)
|
|
||||||
|
|
||||||
fun getAllRecipies(ctx: Context): List<GetAllRecipesResponse> {
|
|
||||||
return requestJson<Unit, List<GetAllRecipesResponse>>(ctx, "GET", "/api/Recipe/getall", null)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class RecipeDetailsResponse(val id: Int, val name: String, val description: String, val directions: List<Direction>, val ingredients: List<Ingredient>)
|
|
||||||
|
|
||||||
fun getRecipeDetails(ctx: Context, id: Int): RecipeDetailsResponse {
|
|
||||||
return requestJson<Unit, RecipeDetailsResponse>(ctx, "GET", "/api/Recipe/get/$id", null)
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package tech.mercantec.easyeat.helpers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import tech.mercantec.easyeat.models.Ingredient
|
||||||
import tech.mercantec.easyeat.models.Recipe
|
import tech.mercantec.easyeat.models.Recipe
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -10,3 +11,22 @@ data class GenerateRecipeRequest(val dish: String, val language: String, val num
|
|||||||
fun generateRecipeWithAI(ctx: Context, title: String, language: String): Recipe {
|
fun generateRecipeWithAI(ctx: Context, title: String, language: String): Recipe {
|
||||||
return requestJson<GenerateRecipeRequest, Recipe>(ctx, "POST", "/api/Recipe/chatbot", GenerateRecipeRequest(title, language, 1, arrayOf()))
|
return requestJson<GenerateRecipeRequest, Recipe>(ctx, "POST", "/api/Recipe/chatbot", GenerateRecipeRequest(title, language, 1, arrayOf()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createRecipe(ctx: Context, recipe: Recipe) {
|
||||||
|
requestJson<Recipe, Boolean>(ctx, "POST", "/api/recipe/create", recipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GetAllRecipesResponse(val id: Int, val name: String, val description: String)
|
||||||
|
|
||||||
|
fun getAllRecipes(ctx: Context): List<GetAllRecipesResponse> {
|
||||||
|
return requestJson<Unit, List<GetAllRecipesResponse>>(ctx, "GET", "/api/Recipe/getall", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RecipeDetailsResponse(val id: Int, val name: String, val description: String, val directions: List<String>, val ingredients: List<Ingredient>)
|
||||||
|
|
||||||
|
fun getRecipeDetails(ctx: Context, id: Int): RecipeDetailsResponse {
|
||||||
|
return requestJson<Unit, RecipeDetailsResponse>(ctx, "GET", "/api/Recipe/get/$id", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,12 @@ fun getShoppingList(ctx: Context): Array<ShoppingListItem> {
|
|||||||
return requestJson<Unit, Array<ShoppingListItem>>(ctx, "GET", "/api/ShoppingList/get", null)
|
return requestJson<Unit, Array<ShoppingListItem>>(ctx, "GET", "/api/ShoppingList/get", null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
fun addShoppingItem(ctx: Context, item: ShoppingListItem): ShoppingListItem {
|
||||||
data class AddShoppingItemRequest(val name: String, val amount: Double?, val unit: String?, val checked: Boolean)
|
return requestJson<ShoppingListItem, ShoppingListItem>(ctx, "POST", "/api/ShoppingList/add", item)
|
||||||
|
}
|
||||||
|
|
||||||
fun addShoppingItem(ctx: Context, name: String, amount: Double?, unit: String?): ShoppingListItem {
|
fun editShoppingItem(ctx: Context, old: ShoppingListItem, new: ShoppingListItem) {
|
||||||
val request = AddShoppingItemRequest(name, amount, unit, false)
|
requestJson<ShoppingListItem, Boolean>(ctx, "PUT", "/api/ShoppingList/update?itemId=${old.id}", new)
|
||||||
|
|
||||||
return requestJson<AddShoppingItemRequest, ShoppingListItem>(ctx, "POST", "/api/ShoppingList/add", request)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleShoppingItemChecked(ctx: Context, item: ShoppingListItem) {
|
fun toggleShoppingItemChecked(ctx: Context, item: ShoppingListItem) {
|
||||||
|
@ -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<CreateDirection>,
|
|
||||||
val ingredients: List<CreateIngredient>
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class CreateDirection(
|
|
||||||
val instructions: String
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class CreateIngredient(
|
|
||||||
val amount: Double?,
|
|
||||||
val unit: String?,
|
|
||||||
val name: String
|
|
||||||
)
|
|
@ -3,4 +3,10 @@ package tech.mercantec.easyeat.models
|
|||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ShoppingListItem(val id: Int, var name: String, var amount: Double?, var unit: String?, var checked: Boolean)
|
data class ShoppingListItem(
|
||||||
|
var id: Int? = null,
|
||||||
|
var name: String,
|
||||||
|
var amount: Double?,
|
||||||
|
var unit: String?,
|
||||||
|
var checked: Boolean = false,
|
||||||
|
)
|
||||||
|
@ -2,10 +2,9 @@ package tech.mercantec.easyeat.models
|
|||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Recipe(
|
data class Recipe(
|
||||||
val id: Int,
|
val id: Int? = null,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
val directions: List<String>,
|
val directions: List<String>,
|
||||||
@ -14,7 +13,7 @@ data class Recipe(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Ingredient(
|
data class Ingredient(
|
||||||
val id: Int,
|
val id: Int? = null,
|
||||||
val amount: Double?,
|
val amount: Double?,
|
||||||
val unit: String?,
|
val unit: String?,
|
||||||
val name: String
|
val name: String
|
||||||
|
@ -2,9 +2,7 @@ package tech.mercantec.easyeat.ui.dishes
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
@ -14,15 +12,11 @@ import android.widget.LinearLayout
|
|||||||
import android.widget.Spinner
|
import android.widget.Spinner
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContentProviderCompat.requireContext
|
|
||||||
import tech.mercantec.easyeat.R
|
import tech.mercantec.easyeat.R
|
||||||
import tech.mercantec.easyeat.helpers.ApiRequestException
|
import tech.mercantec.easyeat.helpers.ApiRequestException
|
||||||
import tech.mercantec.easyeat.helpers.changePassword
|
|
||||||
import tech.mercantec.easyeat.helpers.createRecipe
|
import tech.mercantec.easyeat.helpers.createRecipe
|
||||||
import tech.mercantec.easyeat.helpers.request
|
import tech.mercantec.easyeat.models.Ingredient
|
||||||
import tech.mercantec.easyeat.models.CreateDirection
|
import tech.mercantec.easyeat.models.Recipe
|
||||||
import tech.mercantec.easyeat.models.CreateIngredient
|
|
||||||
import tech.mercantec.easyeat.models.CreateRecipe
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class CreateDishActivity : AppCompatActivity() {
|
class CreateDishActivity : AppCompatActivity() {
|
||||||
@ -53,7 +47,7 @@ class CreateDishActivity : AppCompatActivity() {
|
|||||||
.map { line -> line.trim() }
|
.map { line -> line.trim() }
|
||||||
.filter { it.isNotEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
|
|
||||||
val recipe = CreateRecipe(
|
val recipe = Recipe(
|
||||||
name = findViewById<EditText>(R.id.dishName).text.toString().trim(),
|
name = findViewById<EditText>(R.id.dishName).text.toString().trim(),
|
||||||
description = findViewById<EditText>(R.id.dishDescription).text.toString().trim(),
|
description = findViewById<EditText>(R.id.dishDescription).text.toString().trim(),
|
||||||
directions = directions,
|
directions = directions,
|
||||||
@ -107,8 +101,8 @@ class CreateDishActivity : AppCompatActivity() {
|
|||||||
ingredientContainer.addView(ingredientRow)
|
ingredientContainer.addView(ingredientRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectIngredients(): List<CreateIngredient> {
|
private fun collectIngredients(): List<Ingredient> {
|
||||||
val ingredients = mutableListOf<CreateIngredient>()
|
val ingredients = mutableListOf<Ingredient>()
|
||||||
|
|
||||||
for (i in 0 until ingredientContainer.childCount) {
|
for (i in 0 until ingredientContainer.childCount) {
|
||||||
val ingredientView = ingredientContainer.getChildAt(i)
|
val ingredientView = ingredientContainer.getChildAt(i)
|
||||||
@ -125,7 +119,7 @@ class CreateDishActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
// Optional: Only add non-empty rows
|
// Optional: Only add non-empty rows
|
||||||
if (element.isNotEmpty() && amount.isNotEmpty()) {
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
package tech.mercantec.easyeat.ui.dishes
|
package tech.mercantec.easyeat.ui.dishes
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.text.Html
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import tech.mercantec.easyeat.R
|
import tech.mercantec.easyeat.R
|
||||||
@ -9,14 +16,21 @@ import tech.mercantec.easyeat.helpers.ApiRequestException
|
|||||||
import tech.mercantec.easyeat.helpers.RecipeDetailsResponse
|
import tech.mercantec.easyeat.helpers.RecipeDetailsResponse
|
||||||
import tech.mercantec.easyeat.helpers.getRecipeDetails
|
import tech.mercantec.easyeat.helpers.getRecipeDetails
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import android.widget.ListView
|
import android.widget.EditText
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.widget.doAfterTextChanged
|
||||||
|
import tech.mercantec.easyeat.helpers.AddRecipeToShoppingList
|
||||||
|
import tech.mercantec.easyeat.models.Ingredient
|
||||||
|
|
||||||
class DishDetailsActivity : AppCompatActivity() {
|
class DishDetailsActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_dish_details)
|
setContentView(R.layout.activity_dish_details)
|
||||||
|
|
||||||
|
val ingredientsContainer = findViewById<LinearLayout>(R.id.ingredients)
|
||||||
|
val multiplierEditText = findViewById<EditText>(R.id.ingredient_multiplier)
|
||||||
|
|
||||||
val dishId = intent.getIntExtra("dish_id", -1)
|
val dishId = intent.getIntExtra("dish_id", -1)
|
||||||
if (dishId == -1) {
|
if (dishId == -1) {
|
||||||
Toast.makeText(this, "No dish ID provided", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "No dish ID provided", Toast.LENGTH_SHORT).show()
|
||||||
@ -35,20 +49,108 @@ class DishDetailsActivity : AppCompatActivity() {
|
|||||||
return@thread
|
return@thread
|
||||||
}
|
}
|
||||||
Log.i("DISH", recipe.ingredients.toString())
|
Log.i("DISH", recipe.ingredients.toString())
|
||||||
|
val instructionsLayout = findViewById<LinearLayout>(R.id.instructions)
|
||||||
|
|
||||||
|
// Example data: recipe.ingredients and recipe.directions
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
// Set title and description
|
|
||||||
findViewById<TextView>(R.id.dishDetailName).text = recipe.name
|
findViewById<TextView>(R.id.dishDetailName).text = recipe.name
|
||||||
findViewById<TextView>(R.id.dishDetailDescription).text = recipe.description
|
findViewById<TextView>(R.id.dishDetailDescription).text = recipe.description
|
||||||
|
|
||||||
// Set up the ingredient list
|
// Populate Instructions (if directions are strings)
|
||||||
val ingredientListView = findViewById<ListView>(R.id.dishDetailIngredients)
|
recipe.directions.forEachIndexed { index, direction ->
|
||||||
val ingredientAdapter = IngredientAdapter(this, recipe.ingredients)
|
val textView = TextView(this).apply {
|
||||||
ingredientListView.adapter = ingredientAdapter
|
text = "${index + 1}. $direction"
|
||||||
|
textSize = 18f
|
||||||
val instructionsListView = findViewById<ListView>(R.id.dishDetailInstructions)
|
setPadding(0, 8, 0, 8)
|
||||||
val instructionsAdapter = InstructionsAdapter(this, recipe.directions)
|
|
||||||
instructionsListView.adapter = instructionsAdapter
|
|
||||||
}
|
}
|
||||||
|
instructionsLayout.addView(textView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayIngredients(ingredients: List<Ingredient>, multiplier: Int, container: LinearLayout) {
|
||||||
|
container.removeAllViews() // clear previous views
|
||||||
|
|
||||||
|
for (ingredient in ingredients) {
|
||||||
|
val row = TextView(this)
|
||||||
|
val amount = (ingredient.amount ?: 0.0) * multiplier
|
||||||
|
val amountStr = amount.toBigDecimal().stripTrailingZeros().toPlainString()
|
||||||
|
|
||||||
|
row.text = Html.fromHtml("• ${ingredient.name}: $amountStr ${ingredient.unit ?: ""}", Html.FROM_HTML_MODE_LEGACY)
|
||||||
|
row.textSize = 18f
|
||||||
|
row.setPadding(0, 8, 0, 8)
|
||||||
|
container.addView(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
val nameView = findViewById<TextView>(R.id.dishDetailName)
|
||||||
|
val descView = findViewById<TextView>(R.id.dishDetailDescription)
|
||||||
|
|
||||||
|
nameView.text = recipe.name
|
||||||
|
descView.text = recipe.description
|
||||||
|
|
||||||
|
// Default multiplier
|
||||||
|
var multiplier = 1
|
||||||
|
|
||||||
|
// Initial display
|
||||||
|
displayIngredients(recipe.ingredients, multiplier, ingredientsContainer)
|
||||||
|
|
||||||
|
// Listen for user input changes
|
||||||
|
multiplierEditText.doAfterTextChanged {
|
||||||
|
multiplier = it.toString().toIntOrNull() ?: 1
|
||||||
|
displayIngredients(recipe.ingredients, multiplier, ingredientsContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
findViewById<ImageButton>(R.id.increment_multiplier).setOnClickListener {
|
||||||
|
multiplier++
|
||||||
|
multiplierEditText.setText(multiplier.toString(), TextView.BufferType.EDITABLE)
|
||||||
|
|
||||||
|
displayIngredients(recipe.ingredients, multiplier, ingredientsContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
findViewById<ImageButton>(R.id.decrement_multiplier).setOnClickListener {
|
||||||
|
if (multiplier <= 1) return@setOnClickListener
|
||||||
|
|
||||||
|
multiplier--
|
||||||
|
multiplierEditText.setText(multiplier.toString(), TextView.BufferType.EDITABLE)
|
||||||
|
|
||||||
|
displayIngredients(recipe.ingredients, multiplier, ingredientsContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can do the same for directions if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
val saveButton: Button = findViewById(R.id.addDishToShoppingList)
|
||||||
|
saveButton.setOnClickListener {
|
||||||
|
val progressDialog = ProgressDialog(this)
|
||||||
|
progressDialog.setMessage("Loading...")
|
||||||
|
progressDialog.show()
|
||||||
|
thread {
|
||||||
|
try {
|
||||||
|
val multiplierEditText = findViewById<EditText>(R.id.ingredient_multiplier)
|
||||||
|
val multiplierText = multiplierEditText.text.toString()
|
||||||
|
AddRecipeToShoppingList(this, dishId, multiplierText.toIntOrNull() ?: 1)
|
||||||
|
} 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Button
|
import android.widget.PopupMenu
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
@ -15,8 +15,9 @@ import tech.mercantec.easyeat.R
|
|||||||
import tech.mercantec.easyeat.databinding.FragmentDishesBinding
|
import tech.mercantec.easyeat.databinding.FragmentDishesBinding
|
||||||
import tech.mercantec.easyeat.helpers.ApiRequestException
|
import tech.mercantec.easyeat.helpers.ApiRequestException
|
||||||
import tech.mercantec.easyeat.helpers.GetAllRecipesResponse
|
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 tech.mercantec.easyeat.models.DishListItem
|
||||||
|
import tech.mercantec.easyeat.models.Recipe
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class DishesFragment : Fragment() {
|
class DishesFragment : Fragment() {
|
||||||
@ -36,28 +37,31 @@ class DishesFragment : Fragment() {
|
|||||||
loadRecipes()
|
loadRecipes()
|
||||||
|
|
||||||
binding.addDish.setOnClickListener {
|
binding.addDish.setOnClickListener {
|
||||||
val dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.create_dish_modal_dialog, null)
|
val popup = PopupMenu(requireActivity(), it)
|
||||||
|
|
||||||
val dialog = android.app.AlertDialog.Builder(requireContext())
|
popup.apply {
|
||||||
.setView(dialogView)
|
menuInflater.inflate(R.menu.create_dish_menu, menu)
|
||||||
.setCancelable(true) // tap outside to dismiss
|
|
||||||
.create()
|
|
||||||
|
|
||||||
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
|
setOnMenuItemClickListener {
|
||||||
|
when (it.itemId) {
|
||||||
dialogView.findViewById<Button>(R.id.createManualBtn).setOnClickListener {
|
R.id.create_manually -> {
|
||||||
val intent = Intent(requireContext(), CreateDishActivity::class.java)
|
val intent = Intent(requireContext(), CreateDishActivity::class.java)
|
||||||
createDishLauncher.launch(intent)
|
createDishLauncher.launch(intent)
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogView.findViewById<Button>(R.id.createAIBtn).setOnClickListener {
|
true
|
||||||
val intent = Intent(requireContext(), CreateDishAIActivity::class.java)
|
}
|
||||||
|
R.id.create_with_ai -> {
|
||||||
|
val intent = Intent(requireContext(), GenerateRecipeActivity::class.java)
|
||||||
createDishLauncher.launch(intent)
|
createDishLauncher.launch(intent)
|
||||||
dialog.dismiss()
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.show()
|
show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -68,7 +72,7 @@ class DishesFragment : Fragment() {
|
|||||||
thread {
|
thread {
|
||||||
val recipes: List<GetAllRecipesResponse>
|
val recipes: List<GetAllRecipesResponse>
|
||||||
try {
|
try {
|
||||||
recipes = getAllRecipies(requireContext())
|
recipes = getAllRecipes(requireContext())
|
||||||
} catch (e: ApiRequestException) {
|
} catch (e: ApiRequestException) {
|
||||||
activity?.runOnUiThread {
|
activity?.runOnUiThread {
|
||||||
Toast.makeText(requireContext(), e.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(requireContext(), e.message, Toast.LENGTH_LONG).show()
|
||||||
|
@ -4,20 +4,20 @@ import android.app.ProgressDialog
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import tech.mercantec.easyeat.R
|
import tech.mercantec.easyeat.R
|
||||||
import tech.mercantec.easyeat.helpers.ApiRequestException
|
import tech.mercantec.easyeat.helpers.ApiRequestException
|
||||||
import tech.mercantec.easyeat.helpers.GenerateRecipeResponse
|
import tech.mercantec.easyeat.helpers.createRecipe
|
||||||
import tech.mercantec.easyeat.helpers.generateRecipeWithAI
|
import tech.mercantec.easyeat.helpers.generateRecipeWithAI
|
||||||
|
import tech.mercantec.easyeat.models.Recipe
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class CreateDishAIActivity : AppCompatActivity() {
|
class GenerateRecipeActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.create_dish_ai_form)
|
setContentView(R.layout.activity_generate_recipe)
|
||||||
|
|
||||||
findViewById<Button>(R.id.generate).setOnClickListener {
|
findViewById<Button>(R.id.generate).setOnClickListener {
|
||||||
val name = findViewById<EditText>(R.id.dish_title).text.toString()
|
val name = findViewById<EditText>(R.id.dish_title).text.toString()
|
||||||
@ -27,21 +27,25 @@ class CreateDishAIActivity : AppCompatActivity() {
|
|||||||
progressDialog.show()
|
progressDialog.show()
|
||||||
|
|
||||||
thread {
|
thread {
|
||||||
val response: GenerateRecipeResponse
|
// val response: GenerateRecipeResponse
|
||||||
try {
|
try {
|
||||||
response = generateRecipeWithAI(this, name, Locale.getDefault().displayLanguage)
|
val recipe = generateRecipeWithAI(this, name, Locale.getDefault().displayLanguage)
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
progressDialog.setMessage("Saving...")
|
||||||
|
}
|
||||||
|
|
||||||
|
createRecipe(this, recipe)
|
||||||
|
|
||||||
|
finish()
|
||||||
} catch (e: ApiRequestException) {
|
} catch (e: ApiRequestException) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
return@thread
|
|
||||||
} finally {
|
} finally {
|
||||||
|
runOnUiThread {
|
||||||
progressDialog.hide()
|
progressDialog.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
runOnUiThread {
|
|
||||||
Toast.makeText(this, response.toString(), Toast.LENGTH_LONG).show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,19 +7,18 @@ import android.view.ViewGroup
|
|||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import tech.mercantec.easyeat.R
|
import tech.mercantec.easyeat.R
|
||||||
import tech.mercantec.easyeat.models.Direction
|
|
||||||
|
|
||||||
class InstructionsAdapter (context: Context, instructions: List<Direction>)
|
class InstructionsAdapter (context: Context, instructions: List<String>)
|
||||||
: ArrayAdapter<Direction>(context, 0, instructions) {
|
: ArrayAdapter<String>(context, R.layout.activity_dish_details_instructions_list_item, instructions) {
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||||
val ingredient = getItem(position)
|
val instruction = getItem(position)
|
||||||
val view = convertView ?: LayoutInflater.from(context)
|
val view = convertView ?: LayoutInflater.from(context)
|
||||||
.inflate(R.layout.activity_dish_details_instructions_list_item, parent, false)
|
.inflate(R.layout.activity_dish_details_instructions_list_item, parent, false)
|
||||||
|
|
||||||
val nameView = view.findViewById<TextView>(R.id.instructionText)
|
val nameView = view.findViewById<TextView>(R.id.instructionText)
|
||||||
|
|
||||||
nameView.text = ingredient?.instruktions ?: ""
|
nameView.text = instruction
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -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<Recipe>(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<TextView>(R.id.title).text = recipe.name
|
||||||
|
|
||||||
|
binding.findViewById<TextView>(R.id.ingredients).text =
|
||||||
|
Html.fromHtml(
|
||||||
|
"<ul>" +
|
||||||
|
recipe.ingredients.map { "<li>${it.amount} ${it.unit} ${it.name}</li>" } +
|
||||||
|
"</ul>",
|
||||||
|
FROM_HTML_MODE_LEGACY
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.findViewById<TextView>(R.id.directions).text =
|
||||||
|
Html.fromHtml(
|
||||||
|
"<ul>" +
|
||||||
|
recipe.directions.map { "<li>${it}</li>" } +
|
||||||
|
"</ul>",
|
||||||
|
FROM_HTML_MODE_LEGACY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return binding
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import android.widget.ArrayAdapter
|
|||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
import android.widget.Spinner
|
import android.widget.Spinner
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import tech.mercantec.easyeat.R
|
import tech.mercantec.easyeat.R
|
||||||
@ -16,6 +17,7 @@ import tech.mercantec.easyeat.databinding.FragmentShoppingListBinding
|
|||||||
import tech.mercantec.easyeat.helpers.ApiRequestException
|
import tech.mercantec.easyeat.helpers.ApiRequestException
|
||||||
import tech.mercantec.easyeat.helpers.addShoppingItem
|
import tech.mercantec.easyeat.helpers.addShoppingItem
|
||||||
import tech.mercantec.easyeat.helpers.deleteShoppingItem
|
import tech.mercantec.easyeat.helpers.deleteShoppingItem
|
||||||
|
import tech.mercantec.easyeat.helpers.editShoppingItem
|
||||||
import tech.mercantec.easyeat.helpers.getShoppingList
|
import tech.mercantec.easyeat.helpers.getShoppingList
|
||||||
import tech.mercantec.easyeat.helpers.toggleShoppingItemChecked
|
import tech.mercantec.easyeat.helpers.toggleShoppingItemChecked
|
||||||
import tech.mercantec.easyeat.models.ShoppingListItem
|
import tech.mercantec.easyeat.models.ShoppingListItem
|
||||||
@ -87,8 +89,35 @@ class ShoppingListFragment : Fragment() {
|
|||||||
val popup = PopupMenu(requireActivity(), view)
|
val popup = PopupMenu(requireActivity(), view)
|
||||||
popup.apply {
|
popup.apply {
|
||||||
menuInflater.inflate(R.menu.shopping_item_context_menu, menu)
|
menuInflater.inflate(R.menu.shopping_item_context_menu, menu)
|
||||||
|
|
||||||
setOnMenuItemClickListener {
|
setOnMenuItemClickListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
|
R.id.edit_shopping_item -> {
|
||||||
|
showEditDialog(item) { dialog, newItem ->
|
||||||
|
thread {
|
||||||
|
try {
|
||||||
|
editShoppingItem(requireContext(), item, newItem)
|
||||||
|
} catch (e: ApiRequestException) {
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
return@thread
|
||||||
|
} finally {
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
val adapter = binding.shoppingList.adapter as ShoppingItemAdapter
|
||||||
|
|
||||||
|
adapter.remove(item)
|
||||||
|
adapter.insert(newItem, position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
R.id.remove_shopping_item -> {
|
R.id.remove_shopping_item -> {
|
||||||
(parent.adapter as ShoppingItemAdapter).remove(item)
|
(parent.adapter as ShoppingItemAdapter).remove(item)
|
||||||
|
|
||||||
@ -107,6 +136,7 @@ class ShoppingListFragment : Fragment() {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,24 +146,11 @@ class ShoppingListFragment : Fragment() {
|
|||||||
|
|
||||||
// Show new item dialog when clicking add
|
// Show new item dialog when clicking add
|
||||||
binding.addToShoppingList.setOnClickListener {
|
binding.addToShoppingList.setOnClickListener {
|
||||||
val view = requireActivity().layoutInflater.inflate(R.layout.dialog_add_to_shopping_list, null)
|
showEditDialog(null) { dialog, item ->
|
||||||
|
|
||||||
val dialog = AlertDialog.Builder(activity)
|
|
||||||
.setView(view)
|
|
||||||
.setPositiveButton(R.string.add_label) { dialog, id ->
|
|
||||||
val dialog = dialog as AlertDialog
|
|
||||||
|
|
||||||
val amount = view.findViewById<EditText>(R.id.amount).text.toString().toDouble()
|
|
||||||
val unit = view.findViewById<Spinner>(R.id.unit_selector).selectedItem.toString().ifEmpty { null }
|
|
||||||
val name = view.findViewById<EditText>(R.id.name).text.toString()
|
|
||||||
|
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
|
|
||||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).isEnabled = false
|
|
||||||
|
|
||||||
thread {
|
thread {
|
||||||
val item: ShoppingListItem
|
val newItem: ShoppingListItem
|
||||||
try {
|
try {
|
||||||
item = addShoppingItem(requireContext(), name, amount, unit)
|
newItem = addShoppingItem(requireContext(), item)
|
||||||
} catch (e: ApiRequestException) {
|
} catch (e: ApiRequestException) {
|
||||||
activity?.runOnUiThread {
|
activity?.runOnUiThread {
|
||||||
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
||||||
@ -149,19 +166,44 @@ class ShoppingListFragment : Fragment() {
|
|||||||
activity?.runOnUiThread {
|
activity?.runOnUiThread {
|
||||||
val adapter = binding.shoppingList.adapter as ShoppingItemAdapter
|
val adapter = binding.shoppingList.adapter as ShoppingItemAdapter
|
||||||
|
|
||||||
for (i in 0 ..< adapter.count) {
|
for (i in 0..<adapter.count) {
|
||||||
if (adapter.getItem(i)?.id == item.id) {
|
if (adapter.getItem(i)?.id == newItem.id) {
|
||||||
adapter.remove(adapter.getItem(i))
|
adapter.remove(adapter.getItem(i))
|
||||||
adapter.insert(item, i)
|
adapter.insert(newItem, i)
|
||||||
|
|
||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.insert(item, adapter.count)
|
adapter.insert(newItem, adapter.count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showEditDialog(item: ShoppingListItem?, onSave: (dialog: AlertDialog, item: ShoppingListItem) -> Unit) {
|
||||||
|
val view = requireActivity().layoutInflater.inflate(R.layout.dialog_edit_shopping_item, null)
|
||||||
|
|
||||||
|
val dialog = AlertDialog.Builder(activity)
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton(R.string.add_label) { dialog, id ->
|
||||||
|
val dialog = dialog as AlertDialog
|
||||||
|
|
||||||
|
val amount = view.findViewById<EditText>(R.id.amount).text.toString().toDouble()
|
||||||
|
val unit = view.findViewById<Spinner>(R.id.unit_selector).selectedItem.toString()
|
||||||
|
.ifEmpty { null }
|
||||||
|
val name = view.findViewById<EditText>(R.id.name).text.toString()
|
||||||
|
|
||||||
|
onSave(dialog, ShoppingListItem(item?.id, name, amount, unit, item?.checked ?: false))
|
||||||
|
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).isEnabled = false
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
.setNegativeButton(R.string.cancel_label) { dialog, _ ->
|
.setNegativeButton(R.string.cancel_label) { dialog, _ ->
|
||||||
dialog.cancel()
|
dialog.cancel()
|
||||||
}
|
}
|
||||||
@ -169,12 +211,23 @@ class ShoppingListFragment : Fragment() {
|
|||||||
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
val adapter = ArrayAdapter.createFromResource(requireContext(), R.array.units, android.R.layout.simple_spinner_item)
|
val adapter = ArrayAdapter.createFromResource(
|
||||||
|
requireContext(),
|
||||||
|
R.array.units,
|
||||||
|
android.R.layout.simple_spinner_item
|
||||||
|
)
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
|
||||||
dialog.findViewById<Spinner>(R.id.unit_selector).adapter = adapter
|
dialog.findViewById<Spinner>(R.id.unit_selector).adapter = adapter
|
||||||
}
|
|
||||||
|
|
||||||
return binding.root
|
// Pre-fill dialog inputs with current item if applicable
|
||||||
|
item?.let { item ->
|
||||||
|
view.findViewById<EditText>(R.id.amount).setText(item.amount?.toBigDecimal()?.stripTrailingZeros()?.toPlainString(), TextView.BufferType.EDITABLE)
|
||||||
|
view.findViewById<Spinner>(R.id.unit_selector).setSelection(adapter.getPosition(item.unit))
|
||||||
|
view.findViewById<EditText>(R.id.name).setText(item.name, TextView.BufferType.EDITABLE)
|
||||||
|
|
||||||
|
view.findViewById<TextView>(R.id.title).text = resources.getString(R.string.edit_shopping_item_label)
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).text = resources.getString(R.string.save_label)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,5 +6,5 @@
|
|||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M280,840Q247,840 223.5,816.5Q200,793 200,760L200,240L160,240L160,160L360,160L360,120L600,120L600,160L800,160L800,240L760,240L760,760Q760,793 736.5,816.5Q713,840 680,840L280,840ZM360,680L440,680L440,320L360,320L360,680ZM520,680L600,680L600,320L520,320L520,680Z"/>
|
android:pathData="M480,600L280,400L680,400L480,600Z"/>
|
||||||
</vector>
|
</vector>
|
10
app/app/src/main/res/drawable/ic_arrow_drop_up_24px.xml
Normal file
10
app/app/src/main/res/drawable/ic_arrow_drop_up_24px.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M280,560L480,360L680,560L280,560Z"/>
|
||||||
|
</vector>
|
@ -43,7 +43,9 @@
|
|||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/ingredientAmountEditText"
|
android:id="@+id/ingredientAmountEditText"
|
||||||
android:layout_width="173dp"
|
android:layout_width="173dp"
|
||||||
android:layout_height="48dp" />
|
android:layout_height="48dp"
|
||||||
|
android:inputType="numberDecimal"
|
||||||
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Measurement field -->
|
<!-- Measurement field -->
|
||||||
|
@ -1,58 +1,125 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="409dp"
|
android:layout_height="match_parent">
|
||||||
android:layout_height="729dp"
|
|
||||||
tools:layout_editor_absoluteX="1dp"
|
|
||||||
tools:layout_editor_absoluteY="1dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:padding="30sp"
|
||||||
>
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/dishDetailName"
|
android:id="@+id/dishDetailName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textAlignment="center"
|
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold"
|
||||||
|
style="@style/HighContrastText"
|
||||||
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/dishDetailDescription"
|
android:id="@+id/dishDetailDescription"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textAlignment="center" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginVertical="20dp"
|
|
||||||
android:textSize="25sp"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:text="Ingredients"/>
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/dishDetailIngredients"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:labelFor="@id/ingredient_multiplier"
|
||||||
|
android:text="@string/portions_label"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ingredient_multiplier"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="number"
|
||||||
|
android:text="1"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/decrement_multiplier"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/ic_arrow_drop_down_24px"
|
||||||
|
android:contentDescription="@string/decrement_multiplier_desc"
|
||||||
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/increment_multiplier"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/ic_arrow_drop_up_24px"
|
||||||
|
android:contentDescription="@string/increment_multiplier_desc"
|
||||||
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginVertical="20dp"
|
android:layout_marginVertical="20dp"
|
||||||
android:textSize="25sp"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Instructions"/>
|
android:textSize="18sp"
|
||||||
|
android:text="@string/ingredients_label"
|
||||||
|
style="@style/HighContrastText"
|
||||||
|
/>
|
||||||
|
|
||||||
<ListView
|
<LinearLayout
|
||||||
android:id="@+id/dishDetailInstructions"
|
android:id="@+id/ingredients"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginVertical="20dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="@string/instructions_label"
|
||||||
|
style="@style/HighContrastText"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/instructions"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/addDishToShoppingList"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:backgroundTint="@color/cyan"
|
||||||
|
android:text="@string/add_ingredients_to_shopping_list"
|
||||||
|
android:tint="@android:color/white"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/dialog_root"
|
|
||||||
android:layout_width="250dp"
|
|
||||||
android:layout_height="400dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/rounded_background"
|
|
||||||
android:padding="0dp"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:text="@string/create_dish"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textSize="30sp"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/createManualBtn"
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/manually" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="#CCCCCC" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/createAIBtn"
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/search_for_dishes" />
|
|
||||||
</LinearLayout>
|
|
48
app/app/src/main/res/layout/fragment_recipe.xml
Normal file
48
app/app/src/main/res/layout/fragment_recipe.xml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="30dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:textSize="24sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/ingredients_label"
|
||||||
|
style="@style/HighContrastText"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ingredients"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/directions_label"
|
||||||
|
style="@style/HighContrastText"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/directions"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
11
app/app/src/main/res/menu/create_dish_menu.xml
Normal file
11
app/app/src/main/res/menu/create_dish_menu.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/create_manually"
|
||||||
|
android:title="@string/create_manually_label"
|
||||||
|
/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/create_with_ai"
|
||||||
|
android:title="@string/create_ai_label"
|
||||||
|
/>
|
||||||
|
</menu>
|
@ -1,8 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/edit_shopping_item"
|
||||||
|
android:title="@string/edit_label"
|
||||||
|
/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/remove_shopping_item"
|
android:id="@+id/remove_shopping_item"
|
||||||
android:icon="@drawable/ic_delete_24px"
|
|
||||||
android:title="@string/delete_label"
|
android:title="@string/delete_label"
|
||||||
/>
|
/>
|
||||||
</menu>
|
</menu>
|
||||||
|
6
app/app/src/main/res/values-night/styles.xml
Normal file
6
app/app/src/main/res/values-night/styles.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="HighContrastText" parent="TextAppearance.AppCompat">
|
||||||
|
<item name="android:textColor">@color/white</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
@ -8,5 +8,6 @@
|
|||||||
<item name="colorSurface">@color/dark_cyan</item>
|
<item name="colorSurface">@color/dark_cyan</item>
|
||||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<item name="android:colorBackground">@color/black</item>
|
<item name="android:colorBackground">@color/black</item>
|
||||||
|
<item name="android:windowBackground">@color/black</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
<string name="Instructions">Instructions</string>
|
<string name="Instructions">Instructions</string>
|
||||||
<string name="cancel_label">Cancel</string>
|
<string name="cancel_label">Cancel</string>
|
||||||
<string name="add_shopping_item_label">Add shopping item</string>
|
<string name="add_shopping_item_label">Add shopping item</string>
|
||||||
|
<string name="edit_shopping_item_label">Edit shopping item</string>
|
||||||
<string name="ingredient_amount_label">Amount</string>
|
<string name="ingredient_amount_label">Amount</string>
|
||||||
<string name="ingredient_amount_hint">500</string>
|
<string name="ingredient_amount_hint">500</string>
|
||||||
<string name="ingredient_name_label">Name</string>
|
<string name="ingredient_name_label">Name</string>
|
||||||
@ -40,13 +41,21 @@
|
|||||||
<string name="logout_label">Log out</string>
|
<string name="logout_label">Log out</string>
|
||||||
<string name="checked_desc">Checked</string>
|
<string name="checked_desc">Checked</string>
|
||||||
<string name="delete_label">Delete</string>
|
<string name="delete_label">Delete</string>
|
||||||
|
<string name="edit_label">Edit</string>
|
||||||
<string name="empty_shopping_list">Your shopping list is empty</string>
|
<string name="empty_shopping_list">Your shopping list is empty</string>
|
||||||
<string name="search_for_dishes">Search For Dishes</string>
|
|
||||||
<string name="manually">Manually</string>
|
|
||||||
<string name="create_dish">Create Dish</string>
|
<string name="create_dish">Create Dish</string>
|
||||||
<string name="ai_generate_recipe_title">Generate recipe with AI</string>
|
<string name="ai_generate_recipe_title">Generate recipe with AI</string>
|
||||||
<string name="dish_title_label">Name of dish</string>
|
<string name="dish_title_label">Name of dish</string>
|
||||||
<string name="generate_recipe_label">Generate</string>
|
<string name="generate_recipe_label">Generate</string>
|
||||||
|
<string name="add_ingredients_to_shopping_list">Add ingredients to Shopping List</string>
|
||||||
|
<string name="ingredients_label">Ingredients</string>
|
||||||
|
<string name="directions_label">Directions</string>
|
||||||
|
<string name="create_manually_label">Create manually</string>
|
||||||
|
<string name="create_ai_label">Generate recipe using AI</string>
|
||||||
|
<string name="portions_label">Portions</string>
|
||||||
|
<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-array name="units">
|
<string-array name="units">
|
||||||
<item></item>
|
<item></item>
|
||||||
<item>g</item>
|
<item>g</item>
|
||||||
|
6
app/app/src/main/res/values/styles.xml
Normal file
6
app/app/src/main/res/values/styles.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="HighContrastText" parent="TextAppearance.AppCompat">
|
||||||
|
<item name="android:textColor">@color/black</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
Loading…
Reference in New Issue
Block a user