Improve transaction/category editing/creation
This commit is contained in:
parent
f4bf721b43
commit
408dda40d9
3 changed files with 114 additions and 67 deletions
|
@ -36,12 +36,16 @@ class CategoryDetailsFragment : Fragment() {
|
|||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
|
||||
inflater.inflate(R.layout.fragment_category_details, container, false)
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? =
|
||||
inflater.inflate(R.layout.fragment_category_details, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
activity?.title = arguments?.getString(EXTRA_CATEGORY_NAME)
|
||||
viewModel.state.observe(viewLifecycleOwner, Observer { state ->
|
||||
viewModel.state.observe(viewLifecycleOwner, { state ->
|
||||
when (state) {
|
||||
is AsyncState.Loading -> {
|
||||
categoryDetails.visibility = View.GONE
|
||||
|
@ -52,7 +56,8 @@ class CategoryDetailsFragment : Fragment() {
|
|||
progressBar.visibility = View.GONE
|
||||
val category = state.data.category
|
||||
activity?.title = category.title
|
||||
val tintColor = if (category.expense) R.color.colorTextRed else R.color.colorTextGreen
|
||||
val tintColor =
|
||||
if (category.expense) R.color.colorTextRed else R.color.colorTextGreen
|
||||
val colorStateList = with(view.context) {
|
||||
android.content.res.ColorStateList.valueOf(getColor(tintColor))
|
||||
}
|
||||
|
@ -60,8 +65,8 @@ class CategoryDetailsFragment : Fragment() {
|
|||
categoryProgress.max = category.amount.toInt()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
categoryProgress.setProgress(
|
||||
state.data.balance.toInt(),
|
||||
true
|
||||
state.data.balance.toInt(),
|
||||
true
|
||||
)
|
||||
} else {
|
||||
categoryProgress.progress = state.data.balance.toInt()
|
||||
|
@ -86,14 +91,15 @@ class CategoryDetailsFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
childFragmentManager.beginTransaction()
|
||||
.replace(R.id.transactionsFragmentContainer, transactionsFragment)
|
||||
.commit()
|
||||
.replace(R.id.transactionsFragmentContainer, transactionsFragment)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
is AsyncState.Error -> {
|
||||
categoryDetails.visibility = View.VISIBLE
|
||||
progressBar.visibility = View.GONE
|
||||
Toast.makeText(view.context, "Failed to load context", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(view.context, "Failed to load context", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
is AsyncState.Exit -> {
|
||||
findNavController().navigateUp()
|
||||
|
@ -106,7 +112,7 @@ class CategoryDetailsFragment : Fragment() {
|
|||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == R.id.action_edit) {
|
||||
val bundle = Bundle().apply {
|
||||
putLong(EXTRA_CATEGORY_ID, arguments?.getLong(EXTRA_CATEGORY_ID) ?: -1)
|
||||
putString(EXTRA_CATEGORY_ID, arguments?.getString(EXTRA_CATEGORY_ID))
|
||||
}
|
||||
findNavController().navigate(R.id.addEditCategoryActivity, bundle)
|
||||
} else if (item.itemId == android.R.id.home) {
|
||||
|
|
|
@ -46,15 +46,24 @@ class CategoryFormActivity : AppCompatActivity() {
|
|||
setTitle(state.data.titleRes)
|
||||
menu?.findItem(R.id.action_delete)?.isVisible = state.data.showDeleteButton
|
||||
edit_category_name.setText(category.title)
|
||||
edit_category_amount.setText(String.format("%.02f", (category.amount.toBigDecimal() / 100.toBigDecimal()).toFloat()))
|
||||
edit_category_amount.setText(
|
||||
String.format(
|
||||
"%.02f",
|
||||
(category.amount.toBigDecimal() / 100.toBigDecimal()).toFloat()
|
||||
)
|
||||
)
|
||||
expense.isChecked = category.expense
|
||||
income.isChecked = !category.expense
|
||||
archived.isChecked = category.archived
|
||||
budgetSpinner.adapter = ArrayAdapter<Budget>(
|
||||
this@CategoryFormActivity,
|
||||
android.R.layout.simple_list_item_1,
|
||||
state.data.budgets
|
||||
budgetSpinner.adapter = ArrayAdapter(
|
||||
this@CategoryFormActivity,
|
||||
android.R.layout.simple_list_item_1,
|
||||
state.data.budgets
|
||||
)
|
||||
val budget = state.data.budgets.firstOrNull { it.id == category.budgetId }
|
||||
?: viewModel.budgetRepository.currentBudget.value
|
||||
budgetSpinner.setSelection(state.data.budgets.indexOf(budget))
|
||||
|
||||
}
|
||||
is AsyncState.Error -> {
|
||||
// TODO: Show error message
|
||||
|
@ -86,8 +95,8 @@ class CategoryFormActivity : AppCompatActivity() {
|
|||
upIntent == null -> throw IllegalStateException("No Parent Activity Intent")
|
||||
NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot -> {
|
||||
TaskStackBuilder.create(this)
|
||||
.addNextIntentWithParentStack(upIntent)
|
||||
.startActivities()
|
||||
.addNextIntentWithParentStack(upIntent)
|
||||
.startActivities()
|
||||
}
|
||||
else -> {
|
||||
NavUtils.navigateUpTo(this, upIntent)
|
||||
|
@ -96,14 +105,16 @@ class CategoryFormActivity : AppCompatActivity() {
|
|||
}
|
||||
R.id.action_save -> {
|
||||
if (!validateFields()) return true
|
||||
viewModel.saveCategory(Category(
|
||||
viewModel.saveCategory(
|
||||
Category(
|
||||
id = id,
|
||||
title = edit_category_name.text.toString(),
|
||||
amount = edit_category_amount.text.toLong(),
|
||||
budgetId = (budgetSpinner.selectedItem as Budget).id!!,
|
||||
expense = expense.isChecked,
|
||||
archived = archived.isChecked
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
viewModel.deleteCategoryById(this@CategoryFormActivity.id!!)
|
||||
|
|
|
@ -29,6 +29,7 @@ import kotlinx.coroutines.launch
|
|||
import java.math.BigDecimal
|
||||
import java.util.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.math.max
|
||||
|
||||
class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
|
@ -52,59 +53,82 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
|||
val accounts = viewModel.getAccounts().toTypedArray()
|
||||
setCategories()
|
||||
budgetSpinner.adapter = ArrayAdapter<Budget>(
|
||||
this@TransactionFormActivity,
|
||||
android.R.layout.simple_list_item_1,
|
||||
accounts
|
||||
this@TransactionFormActivity,
|
||||
android.R.layout.simple_list_item_1,
|
||||
accounts
|
||||
)
|
||||
container_edit_transaction_type.setOnCheckedChangeListener { _, _ ->
|
||||
this@TransactionFormActivity.launch {
|
||||
val budget = budgetSpinner.selectedItem as Budget
|
||||
setCategories(viewModel.getCategories(budget.id!!, edit_transaction_type_expense.isChecked))
|
||||
setCategories(
|
||||
viewModel.getCategories(
|
||||
budget.id!!,
|
||||
edit_transaction_type_expense.isChecked
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
budgetSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
}
|
||||
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>?,
|
||||
view: View?,
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
this@TransactionFormActivity.launch {
|
||||
val budget = budgetSpinner.selectedItem as Budget
|
||||
setCategories(viewModel.getCategories(budget.id!!, edit_transaction_type_expense.isChecked))
|
||||
setCategories(
|
||||
viewModel.getCategories(
|
||||
budget.id!!,
|
||||
edit_transaction_type_expense.isChecked
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
val budgetIndex = if (transaction?.budgetId != null) {
|
||||
accounts.indexOfFirst { it.id == transaction?.budgetId }
|
||||
} else {
|
||||
accounts.indexOfFirst { it.id == viewModel.budgetRepository.currentBudget.value?.id }
|
||||
}
|
||||
budgetSpinner.setSelection(max(0, budgetIndex))
|
||||
loadTransaction()
|
||||
transactionDate.setOnClickListener {
|
||||
val currentDate = DateFormat.getDateFormat(this@TransactionFormActivity)
|
||||
.parse(transactionDate.text.toString()) ?: Date()
|
||||
.parse(transactionDate.text.toString()) ?: Date()
|
||||
MaterialDatePicker.Builder.datePicker()
|
||||
.setSelection(currentDate.time)
|
||||
.setTheme(R.style.DateTimePickerDialogTheme)
|
||||
.build()
|
||||
.also { picker ->
|
||||
picker.addOnPositiveButtonClickListener {
|
||||
transactionDate.text = DateFormat.getDateFormat(this@TransactionFormActivity)
|
||||
.format(Date(it))
|
||||
}
|
||||
.setSelection(currentDate.time)
|
||||
.setTheme(R.style.DateTimePickerDialogTheme)
|
||||
.build()
|
||||
.also { picker ->
|
||||
picker.addOnPositiveButtonClickListener {
|
||||
transactionDate.text =
|
||||
DateFormat.getDateFormat(this@TransactionFormActivity)
|
||||
.format(Date(it))
|
||||
}
|
||||
.show(supportFragmentManager, null)
|
||||
}
|
||||
.show(supportFragmentManager, null)
|
||||
}
|
||||
transactionTime.setOnClickListener {
|
||||
val currentDate = DateFormat.getTimeFormat(this@TransactionFormActivity)
|
||||
.parse(transactionTime.text.toString()) ?: Date()
|
||||
.parse(transactionTime.text.toString()) ?: Date()
|
||||
TimePickerDialog(
|
||||
this@TransactionFormActivity,
|
||||
{ _, hourOfDay, minute ->
|
||||
val newTime = Date().apply {
|
||||
hours = hourOfDay
|
||||
minutes = minute
|
||||
}
|
||||
transactionTime.text = DateFormat.getTimeFormat(this@TransactionFormActivity)
|
||||
.format(newTime)
|
||||
},
|
||||
currentDate.hours,
|
||||
currentDate.minutes,
|
||||
DateFormat.is24HourFormat(this@TransactionFormActivity)
|
||||
this@TransactionFormActivity,
|
||||
{ _, hourOfDay, minute ->
|
||||
val newTime = Date().apply {
|
||||
hours = hourOfDay
|
||||
minutes = minute
|
||||
}
|
||||
transactionTime.text =
|
||||
DateFormat.getTimeFormat(this@TransactionFormActivity)
|
||||
.format(newTime)
|
||||
},
|
||||
currentDate.hours,
|
||||
currentDate.minutes,
|
||||
DateFormat.is24HourFormat(this@TransactionFormActivity)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
@ -145,11 +169,15 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
|||
|
||||
private fun setCategories(categories: List<Category> = emptyList()) {
|
||||
val adapter = ArrayAdapter<Category>(
|
||||
this@TransactionFormActivity,
|
||||
android.R.layout.simple_list_item_1
|
||||
this@TransactionFormActivity,
|
||||
android.R.layout.simple_list_item_1
|
||||
)
|
||||
adapter.add(
|
||||
Category(
|
||||
title = getString(R.string.uncategorized),
|
||||
amount = 0, budgetId = ""
|
||||
)
|
||||
)
|
||||
adapter.add(Category(title = getString(R.string.uncategorized),
|
||||
amount = 0, budgetId = ""))
|
||||
adapter.addAll(categories)
|
||||
edit_transaction_category.adapter = adapter
|
||||
transaction?.categoryId?.let {
|
||||
|
@ -177,21 +205,22 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
|||
R.id.action_save -> {
|
||||
val date = GregorianCalendar.getInstance().apply {
|
||||
DateFormat.getDateFormat(this@TransactionFormActivity)
|
||||
.parse(transactionDate.text.toString())
|
||||
?.let {
|
||||
time = it
|
||||
}
|
||||
.parse(transactionDate.text.toString())
|
||||
?.let {
|
||||
time = it
|
||||
}
|
||||
DateFormat.getTimeFormat(this@TransactionFormActivity)
|
||||
.parse(transactionTime.text.toString())
|
||||
?.let { GregorianCalendar.getInstance().apply { time = it } }
|
||||
?.let {
|
||||
set(Calendar.HOUR_OF_DAY, it.get(Calendar.HOUR_OF_DAY))
|
||||
set(Calendar.MINUTE, it.get(Calendar.MINUTE))
|
||||
}
|
||||
.parse(transactionTime.text.toString())
|
||||
?.let { GregorianCalendar.getInstance().apply { time = it } }
|
||||
?.let {
|
||||
set(Calendar.HOUR_OF_DAY, it.get(Calendar.HOUR_OF_DAY))
|
||||
set(Calendar.MINUTE, it.get(Calendar.MINUTE))
|
||||
}
|
||||
}
|
||||
val categoryId = (edit_transaction_category.selectedItem as? Category)?.id
|
||||
launch {
|
||||
viewModel.saveTransaction(Transaction(
|
||||
viewModel.saveTransaction(
|
||||
Transaction(
|
||||
id = id,
|
||||
budgetId = (budgetSpinner.selectedItem as Budget).id!!,
|
||||
title = edit_transaction_title.text.toString(),
|
||||
|
@ -201,7 +230,8 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
|||
expense = edit_transaction_type_expense.isChecked,
|
||||
categoryId = categoryId,
|
||||
createdBy = viewModel.currentUserId!!
|
||||
))
|
||||
)
|
||||
)
|
||||
onNavigateUp()
|
||||
}
|
||||
}
|
||||
|
@ -217,14 +247,14 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
|
|||
|
||||
override fun onNavigateUp(): Boolean {
|
||||
val upIntent: Intent = NavUtils.getParentActivityIntent(this)
|
||||
?: throw IllegalStateException("No Parent Activity Intent")
|
||||
?: throw IllegalStateException("No Parent Activity Intent")
|
||||
|
||||
upIntent.putExtra(MainActivity.EXTRA_OPEN_FRAGMENT, TransactionListFragment.TAG_FRAGMENT)
|
||||
when {
|
||||
NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot -> {
|
||||
TaskStackBuilder.create(this)
|
||||
.addNextIntentWithParentStack(upIntent)
|
||||
.startActivities()
|
||||
.addNextIntentWithParentStack(upIntent)
|
||||
.startActivities()
|
||||
}
|
||||
else -> {
|
||||
finish()
|
||||
|
|
Loading…
Reference in a new issue