Update Category model and interactions according to backend
- added expense and archiving
This commit is contained in:
parent
8817f06c3d
commit
8dd96d04ac
7 changed files with 49 additions and 82 deletions
|
@ -67,6 +67,9 @@ class AddEditCategoryActivity : AppCompatActivity(), CoroutineScope {
|
|||
menu?.findItem(R.id.action_delete)?.isVisible = true
|
||||
edit_category_name.setText(category.title)
|
||||
edit_category_amount.setText(String.format("%.02f", category.amount / 100.0f))
|
||||
expense.isChecked = category.expense
|
||||
income.isChecked = !category.expense
|
||||
archived.isChecked = category.archived
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +106,9 @@ class AddEditCategoryActivity : AppCompatActivity(), CoroutineScope {
|
|||
id = id,
|
||||
title = edit_category_name.text.toString(),
|
||||
amount = edit_category_amount.text.toLong(),
|
||||
budgetId = (budgetSpinner.selectedItem as Budget).id!!
|
||||
budgetId = (budgetSpinner.selectedItem as Budget).id!!,
|
||||
expense = expense.isChecked,
|
||||
archived = archived.isChecked
|
||||
))
|
||||
finish()
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
package com.wbrawner.budget.ui.categories
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.wbrawner.budget.R
|
||||
import com.wbrawner.budget.common.category.Category
|
||||
import com.wbrawner.budget.ui.EXTRA_CATEGORY_ID
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class CategoryAdapter(
|
||||
private val activity: Activity,
|
||||
private val data: List<Category>,
|
||||
private val viewModel: CategoryViewModel
|
||||
) : RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.list_item_category, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = data.size
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val category = data[position]
|
||||
holder.title?.text = category.title
|
||||
// TODO: Format according to budget's currency
|
||||
holder.amount?.text = String.format("${'$'}%.02f", category.amount / 100.0f)
|
||||
holder.progress?.max = category.amount.toInt()
|
||||
holder.launch {
|
||||
val balance = viewModel.getBalance(category.id!!)
|
||||
holder.progress?.isIndeterminate = false
|
||||
holder.progress?.setProgress(
|
||||
(-1 * balance).toInt(),
|
||||
true
|
||||
)
|
||||
holder.amount?.text = holder.itemView.context.getString(
|
||||
R.string.balance_remaning,
|
||||
(category.amount + balance) / 100.0f
|
||||
)
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
startActivity(
|
||||
activity,
|
||||
Intent(it.context.applicationContext, AddEditCategoryActivity::class.java)
|
||||
.apply {
|
||||
putExtra(EXTRA_CATEGORY_ID, category.id!!)
|
||||
},
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
holder.coroutineContext.cancel()
|
||||
super.onViewRecycled(holder)
|
||||
}
|
||||
|
||||
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
val title: TextView? = itemView.findViewById(R.id.category_title)
|
||||
val amount: TextView? = itemView.findViewById(R.id.category_amount)
|
||||
val progress: ProgressBar? = itemView.findViewById(R.id.category_progress)
|
||||
}
|
||||
}
|
|
@ -73,17 +73,23 @@ class CategoryViewHolder(
|
|||
name.text = category.title
|
||||
// TODO: Format according to budget's currency
|
||||
amount.text = String.format("${'$'}%.02f", category.amount / 100.0f)
|
||||
val tintColor = if (category.expense) R.color.colorTextRed else R.color.colorTextGreen
|
||||
val colorStateList = with(itemView.context) {
|
||||
android.content.res.ColorStateList.valueOf(getColor(tintColor))
|
||||
}
|
||||
progressBar.progressTintList = colorStateList
|
||||
progressBar.indeterminateTintList = colorStateList
|
||||
progressBar.max = category.amount.toInt()
|
||||
launch {
|
||||
val balance = viewModel.getBalance(category.id!!)
|
||||
val balance = viewModel.getBalance(category)
|
||||
progressBar.isIndeterminate = false
|
||||
progressBar.setProgress(
|
||||
(-1 * balance).toInt(),
|
||||
balance,
|
||||
true
|
||||
)
|
||||
amount.text = itemView.context.getString(
|
||||
R.string.balance_remaning,
|
||||
(category.amount + balance) / 100.0f
|
||||
(category.amount - balance) / 100.0f
|
||||
)
|
||||
}
|
||||
itemView.setOnClickListener {
|
||||
|
|
|
@ -49,8 +49,10 @@ class CategoryViewModel @Inject constructor(
|
|||
categoryRepo.delete(id)
|
||||
}
|
||||
|
||||
suspend fun getBalance(id: Long) = showLoader {
|
||||
categoryRepo.getBalance(id)
|
||||
suspend fun getBalance(category: Category) = showLoader {
|
||||
val balance = categoryRepo.getBalance(category.id!!)
|
||||
val multiplier = if (category.expense) -1 else 1
|
||||
return@showLoader (balance * multiplier).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,32 @@
|
|||
android:inputType="numberDecimal" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/categoryExpenseContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/expense"
|
||||
android:text="@string/type_expense"
|
||||
android:checked="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/income"
|
||||
android:text="@string/type_income"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</RadioGroup>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/archived"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/archived" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/budgetHint"
|
||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
||||
|
|
|
@ -53,4 +53,5 @@
|
|||
<string name="action_cancel">Cancel</string>
|
||||
<string name="prompt_month">Month</string>
|
||||
<string name="prompt_year">Year</string>
|
||||
<string name="archived">Archived</string>
|
||||
</resources>
|
||||
|
|
|
@ -5,7 +5,9 @@ data class Category(
|
|||
val id: Long? = null,
|
||||
val title: String,
|
||||
val description: String? = null,
|
||||
val amount: Long
|
||||
val amount: Long,
|
||||
val expense: Boolean = true,
|
||||
val archived: Boolean = false
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return title
|
||||
|
|
Loading…
Reference in a new issue