diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/id/ajikamaludin/wallet/data/Transaction.kt b/app/src/main/java/id/ajikamaludin/wallet/data/Transaction.kt
index ea5618e..3663d8b 100644
--- a/app/src/main/java/id/ajikamaludin/wallet/data/Transaction.kt
+++ b/app/src/main/java/id/ajikamaludin/wallet/data/Transaction.kt
@@ -3,8 +3,6 @@ package id.ajikamaludin.wallet.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import java.text.NumberFormat
-
@Entity(tableName = "transactions")
data class Transaction(
@@ -18,6 +16,4 @@ data class Transaction(
val type: Int,
@ColumnInfo(name = "created_at", defaultValue = "CURRENT_TIMESTAMP")
val createdAt: String,
-) {
- fun getFormattedAmount(): String = NumberFormat.getCurrencyInstance().format(amount)
-}
\ No newline at end of file
+)
\ No newline at end of file
diff --git a/app/src/main/java/id/ajikamaludin/wallet/database/TransactionDao.kt b/app/src/main/java/id/ajikamaludin/wallet/database/TransactionDao.kt
index 81991fe..5ce979a 100644
--- a/app/src/main/java/id/ajikamaludin/wallet/database/TransactionDao.kt
+++ b/app/src/main/java/id/ajikamaludin/wallet/database/TransactionDao.kt
@@ -1,6 +1,5 @@
package id.ajikamaludin.wallet.database
-import android.content.ClipData
import androidx.room.*
import id.ajikamaludin.wallet.ITEM_EXPENSE
import id.ajikamaludin.wallet.ITEM_INCOME
@@ -28,4 +27,7 @@ interface TransactionDao {
@Query("SELECT SUM(amount) FROM transactions WHERE type = $ITEM_EXPENSE")
fun getTotalExpense(): Flow
+ @Query("SELECT * FROM transactions WHERE id = :id")
+ fun getTransaction(id: Long): Flow
+
}
\ No newline at end of file
diff --git a/app/src/main/java/id/ajikamaludin/wallet/ui/AddTransactionFragment.kt b/app/src/main/java/id/ajikamaludin/wallet/ui/AddTransactionFragment.kt
index 3f9995f..a6e46d5 100644
--- a/app/src/main/java/id/ajikamaludin/wallet/ui/AddTransactionFragment.kt
+++ b/app/src/main/java/id/ajikamaludin/wallet/ui/AddTransactionFragment.kt
@@ -1,18 +1,24 @@
package id.ajikamaludin.wallet.ui
+import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
import android.widget.ArrayAdapter
-import android.widget.AutoCompleteTextView
+import android.widget.TextView
import androidx.fragment.app.activityViewModels
-import com.google.android.material.snackbar.Snackbar
+import androidx.navigation.fragment.findNavController
+import androidx.navigation.fragment.navArgs
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import id.ajikamaludin.wallet.ITEM_EXPENSE
+import id.ajikamaludin.wallet.ITEM_INCOME
import id.ajikamaludin.wallet.R
import id.ajikamaludin.wallet.WalletApplication
+import id.ajikamaludin.wallet.data.Transaction
import id.ajikamaludin.wallet.databinding.FragmentAddTransactionBinding
-import id.ajikamaludin.wallet.databinding.FragmentTransactionListBinding
class AddTransactionFragment : Fragment() {
@@ -24,6 +30,9 @@ class AddTransactionFragment : Fragment() {
private var _binding: FragmentAddTransactionBinding? = null
private val binding get() = _binding!!
+ lateinit var transaction: Transaction
+ private val navigationArgs: AddTransactionFragmentArgs by navArgs()
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@@ -35,13 +44,118 @@ class AddTransactionFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+
+ // force select list
val items = listOf(getString(R.string.income), getString(R.string.expense))
val adapter = ArrayAdapter(requireContext(), R.layout.item_type, items)
- (binding.itemType as? AutoCompleteTextView)?.setAdapter(adapter)
+ binding.itemType.let {
+ it.setAdapter(adapter)
+ it.setText(getString(R.string.income), false)
+ }
+ binding.deleteAction.visibility = View.INVISIBLE
+
+ val id = navigationArgs.id
+ if(id > 0) {
+ viewModel.retrieveTransaction(id).observe(this.viewLifecycleOwner) { selectedTransaction ->
+ transaction = selectedTransaction
+ bind(transaction)
+ }
+ binding.deleteAction.visibility = View.VISIBLE
+ binding.deleteAction.setOnClickListener {
+ showConfirmationDialog()
+ }
+ } else {
+ binding.saveAction.setOnClickListener {
+ addNewItem()
+ }
+ }
+ }
+
+ private fun isEntryValid(): Boolean {
+ return viewModel.isEntryValid(
+ binding.itemAmount.text.toString(),
+ binding.itemDescription.text.toString(),
+ binding.itemType.text.toString()
+ )
+ }
+
+ private fun addNewItem() {
+ if (isEntryValid()) {
+ val modelType = getTransactionType()
+ viewModel.addTransaction(
+ binding.itemAmount.text.toString(),
+ binding.itemDescription.text.toString(),
+ modelType
+ )
+ val action = AddTransactionFragmentDirections.actionAddTransactionFragmentToTransactionListFragment()
+ findNavController().navigate(action)
+ } else {
+ binding.itemAmount.error = "Amount required"
+ }
+ }
+
+ private fun showConfirmationDialog() {
+ MaterialAlertDialogBuilder(requireContext())
+ .setTitle(getString(android.R.string.dialog_alert_title))
+ .setMessage(getString(R.string.delete_question))
+ .setCancelable(false)
+ .setNegativeButton(getString(R.string.no)) { _, _ -> }
+ .setPositiveButton(getString(R.string.yes)) { _, _ ->
+ deleteItem()
+ }
+ .show()
+ }
+
+ private fun deleteItem() {
+ viewModel.deleteTransaction(transaction)
+ findNavController().navigateUp()
+ }
+
+ private fun bind(transaction: Transaction) {
+ binding.apply {
+ itemAmount.setText(transaction.amount.toString(), TextView.BufferType.SPANNABLE)
+ itemDescription.setText(transaction.description, TextView.BufferType.SPANNABLE)
+ when(transaction.type) {
+ ITEM_INCOME -> itemType.setText(getString(R.string.income), TextView.BufferType.SPANNABLE)
+ else -> itemType.setText(getString(R.string.expense), TextView.BufferType.SPANNABLE)
+ }
+
+ saveAction.setOnClickListener { updateItem() }
+ }
+ }
- binding.saveAction.setOnClickListener {
- Snackbar.make(this, binding.itemType.text, Snackbar.LENGTH_SHORT)
+ private fun updateItem() {
+ if (isEntryValid()) {
+ val modelType = getTransactionType()
+ viewModel.update(
+ this.navigationArgs.id,
+ binding.itemAmount.text.toString(),
+ binding.itemDescription.text.toString(),
+ modelType,
+ transaction.createdAt
+ )
+ val action = AddTransactionFragmentDirections.actionAddTransactionFragmentToTransactionListFragment()
+ findNavController().navigate(action)
+ } else {
+ binding.itemAmount.error = "Amount required"
}
}
+ private fun getTransactionType(): Int {
+ val modelType = when(binding.itemType.text.toString()) {
+ getString(R.string.income) -> ITEM_INCOME
+ else -> ITEM_EXPENSE
+ }
+
+ return modelType
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ val inputMethodManager = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as
+ InputMethodManager
+ inputMethodManager.hideSoftInputFromWindow(requireActivity().currentFocus?.windowToken, 0)
+ _binding = null
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionListFragment.kt b/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionListFragment.kt
index e0b6afa..2f26dd2 100644
--- a/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionListFragment.kt
+++ b/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionListFragment.kt
@@ -8,9 +8,7 @@ import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
-import id.ajikamaludin.wallet.R
import id.ajikamaludin.wallet.WalletApplication
-import id.ajikamaludin.wallet.database.TransactionDao
import id.ajikamaludin.wallet.databinding.FragmentTransactionListBinding
class TransactionListFragment: Fragment() {
diff --git a/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionViewModel.kt b/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionViewModel.kt
index 84a2f81..2165172 100644
--- a/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionViewModel.kt
+++ b/app/src/main/java/id/ajikamaludin/wallet/ui/TransactionViewModel.kt
@@ -3,12 +3,78 @@ package id.ajikamaludin.wallet.ui
import androidx.lifecycle.*
import id.ajikamaludin.wallet.data.Transaction
import id.ajikamaludin.wallet.database.TransactionDao
+import kotlinx.coroutines.launch
+import java.text.SimpleDateFormat
+import java.util.*
class TransactionViewModel(private val transactionDao: TransactionDao): ViewModel() {
val transactions: LiveData> = transactionDao.getTransactions().asLiveData()
val amount: LiveData = transactionDao.getTotalAmount().asLiveData()
val expense: LiveData = transactionDao.getTotalExpense().asLiveData()
val income: LiveData = transactionDao.getTotalIncome().asLiveData()
+
+ private fun insertTransaction(transaction: Transaction) {
+ viewModelScope.launch {
+ transactionDao.insert(transaction)
+ }
+ }
+
+ private fun getNewTransactionEntry(amount: String, description: String, type: Int): Transaction {
+ val current = Date()
+
+ val formatter = SimpleDateFormat("dd-M-yyyy hh:mm", Locale.US)
+ val formatted = formatter.format(current)
+
+ return Transaction(
+ amount = amount.toDouble(),
+ description = description,
+ type = type,
+ createdAt = formatted
+ )
+ }
+
+ fun addTransaction(amount: String, description: String, type: Int) {
+ val newTransaction = getNewTransactionEntry(amount, description, type)
+ insertTransaction(newTransaction)
+ }
+
+ fun isEntryValid(amount: String, description: String, type: String): Boolean {
+ if(amount.isBlank() || type.isBlank()) {
+ return false
+ }
+ return true
+ }
+
+ fun retrieveTransaction(id: Long): LiveData {
+ return transactionDao.getTransaction(id).asLiveData()
+ }
+
+ private fun getUpdatedTransactionEntry(id: Long, amount: String, description: String, type: Int, createdAt: String): Transaction {
+ return Transaction(
+ id = id,
+ amount = amount.toDouble(),
+ description = description,
+ type = type,
+ createdAt = createdAt
+ )
+ }
+
+ private fun updateTransaction(transaction: Transaction){
+ viewModelScope.launch {
+ transactionDao.update(transaction)
+ }
+ }
+
+ fun update(id:Long, amount: String, description: String, type: Int, createdAt: String){
+ val transaction = getUpdatedTransactionEntry(id, amount, description, type, createdAt)
+ updateTransaction(transaction)
+ }
+
+ fun deleteTransaction(transaction: Transaction) {
+ viewModelScope.launch {
+ transactionDao.delete(transaction)
+ }
+ }
}
class TransactionViewModelFactory(private val transactionDao: TransactionDao) : ViewModelProvider.Factory {
diff --git a/app/src/main/res/layout/fragment_add_transaction.xml b/app/src/main/res/layout/fragment_add_transaction.xml
index 8cb4a10..2795ddf 100644
--- a/app/src/main/res/layout/fragment_add_transaction.xml
+++ b/app/src/main/res/layout/fragment_add_transaction.xml
@@ -74,6 +74,17 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/item_type_label" />
+
+
diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml
index 68ce55b..51b24b3 100644
--- a/app/src/main/res/values-in-rID/strings.xml
+++ b/app/src/main/res/values-in-rID/strings.xml
@@ -4,8 +4,8 @@
Hello blank fragment
Buat Transaksi
Saldo
- Pengeluaran
- Pemasukan
+ Pengeluaran
+ Pemasukan
Simpan
Jumlah
Deskripsi
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 1ac0e9a..c5d93a5 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -16,5 +16,5 @@
#63a4ff
#004ba0
- #1976d2
+ #d32f2f
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 29f8194..c1864e8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4,10 +4,14 @@
Hello blank fragment
Create Transaction
Balance
- Expense
- Income
+ Expense
+ Income
Save
Amount
Description
Type
+ Delete
+ Are you sure ?
+ no
+ Yes
\ No newline at end of file
diff --git a/app/src/main/res/values/style.xml b/app/src/main/res/values/style.xml
index 2185fb1..0d42528 100644
--- a/app/src/main/res/values/style.xml
+++ b/app/src/main/res/values/style.xml
@@ -14,4 +14,7 @@
- @style/TextAppearance.MaterialComponents.Subtitle1
+
\ No newline at end of file