diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0089e4fbb12a612f9ec58933fead21efc8ec8fdd..50b7aba200fb672329fb4a183e5b5c837d32f3f5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,6 +78,8 @@ dependencies { implementation("androidx.room:room-ktx:$roomVersion") ksp("androidx.room:room-compiler:$roomVersion") + implementation("com.github.PhilJay:MPAndroidChart:v3.1.0") + testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") @@ -89,4 +91,5 @@ dependencies { implementation("androidx.activity:activity-ktx:1.8.2") + } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoyap/ui/graph/GraphFragment.kt b/app/src/main/java/com/example/bondoyap/ui/graph/GraphFragment.kt index 2699f7ae6afc2649b643b34422251ea4a54e62db..cec599938bae4f26cc961e1b11f7d2623883cf55 100644 --- a/app/src/main/java/com/example/bondoyap/ui/graph/GraphFragment.kt +++ b/app/src/main/java/com/example/bondoyap/ui/graph/GraphFragment.kt @@ -1,5 +1,6 @@ package com.example.bondoyap.ui.graph +import android.content.res.Configuration import androidx.fragment.app.viewModels import android.os.Bundle import androidx.fragment.app.Fragment @@ -7,7 +8,18 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.lifecycle.Observer import com.example.bondoyap.R +import com.example.bondoyap.ui.transactions.TransactionsApplication +import com.example.bondoyap.ui.transactions.TransactionsViewModel +import com.example.bondoyap.ui.transactions.TransactionsViewModelFactory +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.data.PieData +import com.github.mikephil.charting.data.PieDataSet +import com.github.mikephil.charting.data.PieEntry +import com.github.mikephil.charting.utils.ColorTemplate class GraphFragment : Fragment() { @@ -15,7 +27,11 @@ class GraphFragment : Fragment() { fun newInstance() = GraphFragment() } - private val viewModel: GraphViewModel by viewModels() + private val transactionsViewModel: TransactionsViewModel by viewModels { + TransactionsViewModelFactory((requireContext().applicationContext as TransactionsApplication).repository) + } + + private lateinit var pieChart: PieChart override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -27,15 +43,54 @@ class GraphFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - val root = inflater.inflate(R.layout.fragment_graph, container, false) + pieChart = root.findViewById(R.id.pieChart) + + transactionsViewModel.pemasukanCount.observe(viewLifecycleOwner, Observer { pemasukanCount -> + transactionsViewModel.pengeluaranCount.observe(viewLifecycleOwner, Observer { pengeluaranCount -> + val entries = listOf( + PieEntry(pemasukanCount.toFloat(), "Pemasukan"), + PieEntry(pengeluaranCount.toFloat(), "Pengeluaran") + ) + + val colors = mutableListOf<Int>() + colors.add(ContextCompat.getColor(requireContext(), R.color.green)) + colors.add(ContextCompat.getColor(requireContext(), R.color.red)) + + val pieDataSet = PieDataSet(entries, "") + pieDataSet.colors = colors - val textView: TextView = root.findViewById(R.id.text_graph) + val pieData = PieData(pieDataSet) - viewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } + pieChart.data = pieData + pieChart.description.isEnabled = false + + val legend = pieChart.legend + val orientation = resources.configuration.orientation + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT + legend.verticalAlignment = Legend.LegendVerticalAlignment.CENTER + } else { + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + } + legend.setDrawInside(false) + + if (isDarkTheme()) { + legend.textColor = ContextCompat.getColor(requireContext(), R.color.white) + } else { + legend.textColor = ContextCompat.getColor(requireContext(), R.color.black) + } + + pieChart.invalidate() + }) + }) return root } + + private fun isDarkTheme(): Boolean { + val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + return currentNightMode == Configuration.UI_MODE_NIGHT_YES + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt index e5d26b61b11d09aaef1e41fdfcbbf6cb3f35bbd0..2e06e88c972e779c7b3017a534f00cb5f6fdf083 100644 --- a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt +++ b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt @@ -15,6 +15,8 @@ class TransactionsViewModel( private val repository: TransactionsRepository ): ViewModel() { val allTransactions: LiveData<List<Transactions>> = repository.allTransactions.asLiveData() + val pemasukanCount: LiveData<Int> = repository.getPemasukanCount().asLiveData() + val pengeluaranCount: LiveData<Int> = repository.getPengeluaranCount().asLiveData() fun upsert(transactions: Transactions) = viewModelScope.launch { repository.upsert(transactions) diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsDao.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsDao.kt index a6701873192e576ebe17d6f2b8ed31706c7cac85..f02276d8cd7b09c5d5008953cd3602e30006d5b0 100644 --- a/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsDao.kt +++ b/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsDao.kt @@ -26,4 +26,10 @@ interface TransactionsDao { @Query("DELETE FROM transactions") suspend fun deleteAllTransactions() + + @Query("SELECT COUNT(transactions.id) FROM transactions WHERE transactions.is_pemasukan = 1") + fun getPemasukanCount(): Flow<Int> + + @Query("SELECT COUNT(transactions.id) FROM transactions WHERE transactions.is_pemasukan = 0") + fun getPengeluaranCount(): Flow<Int> } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsRepository.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsRepository.kt index 752e4e908bbf87e6eb62ca6ad7551a7ff0071359..43b83a602b22ef3f4ccfa1e889d357f7dbce1bc0 100644 --- a/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsRepository.kt +++ b/app/src/main/java/com/example/bondoyap/ui/transactions/data/TransactionsRepository.kt @@ -28,4 +28,12 @@ class TransactionsRepository(private val transactionsDao: TransactionsDao) { suspend fun deleteAllTransactions() { transactionsDao.deleteAllTransactions() } + + fun getPemasukanCount(): Flow<Int> { + return transactionsDao.getPemasukanCount() + } + + fun getPengeluaranCount(): Flow<Int> { + return transactionsDao.getPengeluaranCount() + } } \ No newline at end of file diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..37aba8c28c124c445dcfff4c0f11adb05d4dc31f --- /dev/null +++ b/app/src/main/res/layout-land/activity_main.xml @@ -0,0 +1,30 @@ +<?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" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <com.google.android.material.bottomnavigation.BottomNavigationView + android:id="@+id/nav_view" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:background="?android:attr/windowBackground" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:menu="@menu/bottom_nav_menu" /> + + <fragment + android:id="@+id/nav_host_fragment_activity_main" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="0dp" + android:layout_height="0dp" + app:defaultNavHost="true" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/nav_view" + app:navGraph="@navigation/mobile_navigation" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout-land/fragment_graph.xml b/app/src/main/res/layout-land/fragment_graph.xml new file mode 100644 index 0000000000000000000000000000000000000000..e84b522c8852d3f09ae5c6e2f0ba0fedd872aad7 --- /dev/null +++ b/app/src/main/res/layout-land/fragment_graph.xml @@ -0,0 +1,35 @@ +<?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="match_parent" + tools:context=".ui.graph.GraphFragment"> + + <com.github.mikephil.charting.charts.PieChart + android:id="@+id/pieChart" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + + + <TextView + android:id="@+id/legendTextView" + android:layout_width="wrap_content" + android:layout_height="0dp" + android:textAlignment="center" + android:layout_marginEnd="16dp" + app:layout_constraintTop_toTopOf="@id/pieChart" + app:layout_constraintBottom_toBottomOf="@id/pieChart" + app:layout_constraintStart_toEndOf="@id/pieChart" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintHorizontal_bias="1.0" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/fragment_graph.xml b/app/src/main/res/layout/fragment_graph.xml index 54053eed4448bd44ec27178a235b2435bc7e12f4..9190a62c7ca86d85080f31eeab40675ecd34d1ae 100644 --- a/app/src/main/res/layout/fragment_graph.xml +++ b/app/src/main/res/layout/fragment_graph.xml @@ -1,22 +1,29 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<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="match_parent" tools:context=".ui.graph.GraphFragment"> + <com.github.mikephil.charting.charts.PieChart + android:id="@+id/pieChart" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintDimensionRatio="1:1" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/legendTextView" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + <TextView - android:id="@+id/text_graph" - android:layout_width="match_parent" + android:id="@+id/legendTextView" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" + app:layout_constraintTop_toBottomOf="@id/pieChart" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file + app:layout_constraintEnd_toEndOf="parent"/> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 5b69a31ff5fc8b40517d0e5624620e080be37343..dca02c2d4e6b6474144e731710b897d7d6b9a0a2 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -8,5 +8,6 @@ <color name="black">#FF000000</color> <color name="white">#FFFFFFFF</color> <color name="red">#FF0000</color> + <color name="green">#50C878</color> <color name="ic_launcher_background">#f6bc2b</color> </resources> \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 3d01cb6670d2d2430a91c8c0f2a15f4e2e8082de..d616139ee998bbb11fee000a8d87a8f75fc9c2e6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,6 +10,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven(url = "https://jitpack.io") } }