diff --git a/app/src/main/java/com/onionsquad/bondoman/room/TransactionCategory.kt b/app/src/main/java/com/onionsquad/bondoman/room/TransactionCategory.kt index a49c47934f831c523c9dea980de5a3570f1b1dd0..f37764b16572f2d510b4d0c2a12c54abae909df7 100644 --- a/app/src/main/java/com/onionsquad/bondoman/room/TransactionCategory.kt +++ b/app/src/main/java/com/onionsquad/bondoman/room/TransactionCategory.kt @@ -2,5 +2,6 @@ package com.onionsquad.bondoman.room enum class TransactionCategory { INCOME, - OUTCOME + OUTCOME, + UNKNOWN } \ No newline at end of file diff --git a/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionAdapter.kt b/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..11d9bfd2ba181b7c590583959b7eafd6a14f76aa --- /dev/null +++ b/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionAdapter.kt @@ -0,0 +1,46 @@ +package com.onionsquad.bondoman.ui.transaction + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.onionsquad.bondoman.databinding.TransactionCardBinding +import com.onionsquad.bondoman.room.TransactionEntity + +class TransactionAdapter( + private val viewModel: TransactionViewModel, + private var transactionList: List<TransactionEntity> = emptyList() +) : RecyclerView.Adapter<TransactionAdapter.ViewHolder>() { + + inner class ViewHolder(private val binding: TransactionCardBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(transaction: TransactionEntity) { + binding.titleTextView.text = transaction.title + binding.amountTextView.text = transaction.amount.toString() + binding.categoryTextView.text = transaction.category.toString() + binding.dateTextView.text = transaction.date.toString() + binding.locationTextView.text = transaction.location + + binding.deleteButton.setOnClickListener { + viewModel.deleteTransaction(transaction) + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val binding = TransactionCardBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val transaction = transactionList[position] + holder.bind(transaction) + } + + override fun getItemCount(): Int { + return transactionList.size + } + + fun setTransactionList(transactionList: List<TransactionEntity>) { + this.transactionList = transactionList + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionFragment.kt b/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionFragment.kt index 4ff1ccc32f50abe95a0e0e74e85e2595bf8997e6..7af3c31b9b13576aaee461b52885ff04ae8710f7 100644 --- a/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionFragment.kt +++ b/app/src/main/java/com/onionsquad/bondoman/ui/transaction/TransactionFragment.kt @@ -7,38 +7,60 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager import com.onionsquad.bondoman.AddTransactionActivity import com.onionsquad.bondoman.databinding.FragmentTransactionBinding import com.onionsquad.bondoman.repository.TransactionRepository import com.onionsquad.bondoman.room.TransactionDatabase class TransactionFragment : Fragment() { - private var _binding: FragmentTransactionBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. private val binding get() = _binding!! private val database by lazy { TransactionDatabase.getInstance(requireContext().applicationContext) } private val repository by lazy { TransactionRepository(database.transactionDao()) } + private lateinit var transactionViewModel: TransactionViewModel + private lateinit var transactionAdapter: TransactionAdapter override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? ): View { + _binding = FragmentTransactionBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupViewModel() + setupRecyclerView() + setupClickListeners() + } + + private fun setupViewModel() { val factory = TransactionViewModelFactory(repository) - val transactionViewModel = ViewModelProvider(this, factory)[TransactionViewModel::class.java] + transactionViewModel = ViewModelProvider(this, factory)[TransactionViewModel::class.java] - _binding = FragmentTransactionBinding.inflate(inflater, container, false) + transactionViewModel.listTransactions.observe(viewLifecycleOwner) { transactionList -> + transactionAdapter.setTransactionList(transactionList) + } + } + + private fun setupRecyclerView() { + transactionAdapter = TransactionAdapter(transactionViewModel) + binding.transactionList.apply { + layoutManager = LinearLayoutManager(context) + adapter = transactionAdapter + } + } - binding.button.setOnClickListener { + private fun setupClickListeners() { + binding.addTransactionButton.setOnClickListener { val intent = Intent(activity, AddTransactionActivity::class.java) startActivity(intent) } - - return binding.root } override fun onDestroyView() { diff --git a/app/src/main/java/com/onionsquad/bondoman/util/Converters.kt b/app/src/main/java/com/onionsquad/bondoman/util/Converters.kt index eb9f90aed7e011b1929c61ffa87bda7f5b612595..ce6beddb309958907a9a4f30e9e9f53511b04ac0 100644 --- a/app/src/main/java/com/onionsquad/bondoman/util/Converters.kt +++ b/app/src/main/java/com/onionsquad/bondoman/util/Converters.kt @@ -25,6 +25,10 @@ object Converters { @TypeConverter fun toTransactionCategory(categoryString: String): TransactionCategory { - return TransactionCategory.valueOf(categoryString) + return try { + TransactionCategory.valueOf(categoryString) + } catch (e: IllegalArgumentException) { + TransactionCategory.UNKNOWN + } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 0000000000000000000000000000000000000000..8140012280ccf471ae3e11e44058ebfb0a4fa6e4 --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> +</vector> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000000000000000000000000000000000000..68a0c25ba815cfe6d897f662124ab27949e4917b --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/black" + android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/> +</vector> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000000000000000000000000000000000000..07b29ac812158f3085d22bee97750c64f4ac298f --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/black" + android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/> +</vector> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_transaction.xml b/app/src/main/res/layout/fragment_transaction.xml index 26af3dd3316b3d39d8d4a93547724bcb95a87311..ad431af9019f5407aa1dcaec30e2bf8df35d828d 100644 --- a/app/src/main/res/layout/fragment_transaction.xml +++ b/app/src/main/res/layout/fragment_transaction.xml @@ -6,15 +6,24 @@ android:layout_height="match_parent" tools:context=".ui.transaction.TransactionFragment"> - <Button - android:id="@+id/button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Button" - android:visibility="visible" + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/transactionList" + android:layout_width="0dp" + android:layout_height="0dp" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + tools:listitem="@layout/transaction_card" /> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/addTransactionButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="16dp" + android:src="@drawable/ic_add" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/transaction_card.xml b/app/src/main/res/layout/transaction_card.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a2757012d4ac15a56c0d87efaae0173f1d23bcf --- /dev/null +++ b/app/src/main/res/layout/transaction_card.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp"> + + <TextView + android:id="@+id/dateTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="16sp" + android:textStyle="bold" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="29/02/2024" /> + + <TextView + android:id="@+id/categoryTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textSize="14sp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/dateTextView" + tools:text="Pembelian" /> + + <TextView + android:id="@+id/titleTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="18sp" + android:textStyle="bold" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/categoryTextView" + tools:text="Transaction Name" /> + + <TextView + android:id="@+id/amountTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="16sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="IDR 15.000" /> + + <TextView + android:id="@+id/locationTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="14sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/amountTextView" + tools:text="Location" /> + + <ImageButton + android:id="@+id/editButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginEnd="10dp" + android:background="?attr/selectableItemBackgroundBorderless" + android:src="@drawable/ic_edit" + app:layout_constraintEnd_toStartOf="@+id/deleteButton" + app:layout_constraintTop_toBottomOf="@id/titleTextView" /> + + <ImageButton + android:id="@+id/deleteButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginTop="8dp" + android:background="?attr/selectableItemBackgroundBorderless" + android:src="@drawable/ic_delete" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/titleTextView" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file