diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index e72b8a29322f87761eaca407bf3b73078e787d25..0c0c3383890637b4721df1f49d0b229e55c0f361 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -3,20 +3,7 @@ <component name="deploymentTargetDropDown"> <value> <entry key="app"> - <State> - <runningDeviceTargetSelectedWithDropDown> - <Target> - <type value="RUNNING_DEVICE_TARGET" /> - <deviceKey> - <Key> - <type value="VIRTUAL_DEVICE_PATH" /> - <value value="C:\Users\ASUS\.android\avd\Pixel_5_API_34.avd" /> - </Key> - </deviceKey> - </Target> - </runningDeviceTargetSelectedWithDropDown> - <timeTargetWasSelectedWithDropDown value="2024-04-01T10:48:27.918936Z" /> - </State> + <State /> </entry> </value> </component> diff --git a/app/src/main/java/com/pbd/psi/LoginActivity.kt b/app/src/main/java/com/pbd/psi/LoginActivity.kt index 57dd6a2d1176857986055bf9080f4caacb4c3f24..0298a8425f47aaf3bdae3611c1eb3d487170463e 100644 --- a/app/src/main/java/com/pbd/psi/LoginActivity.kt +++ b/app/src/main/java/com/pbd/psi/LoginActivity.kt @@ -38,6 +38,23 @@ class LoginActivity : AppCompatActivity() { isLogin() + viewModel.authResult.observe(this) { + when (it) { + is BaseResponse.Success -> { + val intentRecycle = Intent(this@LoginActivity, MainActivity::class.java) + startActivity(intentRecycle) + finish() + } + + is BaseResponse.Error -> { + Toast.makeText(this, "Token expired", Toast.LENGTH_SHORT).show() + } + else -> { + Toast.makeText(this, "Token expired", Toast.LENGTH_SHORT).show() + } + } + } + viewModel.loginResult.observe(this) { when (it) { is BaseResponse.Loading -> { @@ -84,7 +101,7 @@ class LoginActivity : AppCompatActivity() { Toast.makeText(this, "Email and password must be filled", Toast.LENGTH_SHORT).show() return } - viewModel.loginUser(email, password) + viewModel.loginUser("13521099@std.stei.itb.ac.id", "password_13521099") } private fun isOnline(context: Context) { diff --git a/app/src/main/java/com/pbd/psi/LoginViewModel.kt b/app/src/main/java/com/pbd/psi/LoginViewModel.kt index 40e1054ce69b01cc23ff846c80437a1577cd57d0..2279ccf7856e9650b48b8d1d13f47747f8cc4e50 100644 --- a/app/src/main/java/com/pbd/psi/LoginViewModel.kt +++ b/app/src/main/java/com/pbd/psi/LoginViewModel.kt @@ -5,6 +5,7 @@ import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope +import com.pbd.psi.models.AuthRes import com.pbd.psi.models.BaseResponse import com.pbd.psi.models.LoginReq import com.pbd.psi.models.LoginRes @@ -14,6 +15,7 @@ import kotlinx.coroutines.launch class LoginViewModel(application: Application) : AndroidViewModel(application){ val userRepo = UserRepository() val loginResult : MutableLiveData<BaseResponse<LoginRes>> = MutableLiveData() + val authResult : MutableLiveData<BaseResponse<AuthRes>> = MutableLiveData() fun loginUser(email: String, password: String){ loginResult.value = BaseResponse.Loading() @@ -39,4 +41,23 @@ class LoginViewModel(application: Application) : AndroidViewModel(application){ } } } + fun checkAuth(token :String){ + viewModelScope.launch { + try { + val response = userRepo.checkAuth(token) + if(response.isSuccessful){ + Log.d("LoginViewModel", "berhasillll") + authResult.value = BaseResponse.Success(data = response.body()) + }else{ + Log.d("LoginViewModel", "gagal") + loginResult.value = BaseResponse.Error(msg = response.message()) + + } + Log.d("LoginViewModel", "checkAuth: ${response.body()}") + } catch (e: Exception) { + Log.d("LoginViewModel", "checkAuth: ${e.message}") + loginResult.value = BaseResponse.Error(msg = e.message) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/pbd/psi/repository/GraphRepository.kt b/app/src/main/java/com/pbd/psi/repository/GraphRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..2ae55505ee8b6aa134161887bfac5e81043fa5c5 --- /dev/null +++ b/app/src/main/java/com/pbd/psi/repository/GraphRepository.kt @@ -0,0 +1,18 @@ +package com.pbd.psi.repository +import androidx.lifecycle.LiveData +import com.pbd.psi.room.AppDatabase +import com.pbd.psi.room.Category +import com.pbd.psi.room.TransactionEntity +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class GraphRepository(private val database: AppDatabase) { + suspend fun getSumTransaction(category: Category): Int { + return withContext(Dispatchers.IO) { + // Perform database operation here + // For example: + database.transactionDao().getSumTransaction(category) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/pbd/psi/repository/UserRepository.kt b/app/src/main/java/com/pbd/psi/repository/UserRepository.kt index ee9f0c90215878d7362416e8df53bb945089039e..a674f9e57b3655ab0466da90281b3b661821b64e 100644 --- a/app/src/main/java/com/pbd/psi/repository/UserRepository.kt +++ b/app/src/main/java/com/pbd/psi/repository/UserRepository.kt @@ -1,6 +1,7 @@ package com.pbd.psi.repository import com.pbd.psi.api.ApiConfig +import com.pbd.psi.models.AuthRes import com.pbd.psi.models.LoginReq import com.pbd.psi.models.LoginRes import retrofit2.Response @@ -10,4 +11,8 @@ class UserRepository { suspend fun loginUser(loginReq : LoginReq) : Response<LoginRes> { return ApiConfig.getApiService().login(loginReq) } + + suspend fun checkAuth(token:String) : Response<AuthRes> { + return ApiConfig.getApiService().auth(token) + } } \ No newline at end of file diff --git a/app/src/main/java/com/pbd/psi/room/TransactionDao.kt b/app/src/main/java/com/pbd/psi/room/TransactionDao.kt index b052ffc021876e4fde6d937958dbbacf4464231b..bccf4d719cb2693e729f67dc85c438ad6435598e 100644 --- a/app/src/main/java/com/pbd/psi/room/TransactionDao.kt +++ b/app/src/main/java/com/pbd/psi/room/TransactionDao.kt @@ -15,6 +15,9 @@ interface TransactionDao { @Query("SELECT * FROM transactionTable WHERE id=:id") fun getTransById(id: Int): TransactionEntity + @Query("SELECT SUM(amount) as amount FROM transactionTable WHERE category=:category GROUP BY category") + fun getSumTransaction(category: Category): Int + @Insert(onConflict = OnConflictStrategy.ABORT) suspend fun addTransaction(trans: TransactionEntity) diff --git a/app/src/main/java/com/pbd/psi/room/TransactionEntity.kt b/app/src/main/java/com/pbd/psi/room/TransactionEntity.kt index 4c2bcbe46222ed145179549dd8664ef399a164b9..ee1fa899d8725a47c0d23f879e71f04b20288052 100644 --- a/app/src/main/java/com/pbd/psi/room/TransactionEntity.kt +++ b/app/src/main/java/com/pbd/psi/room/TransactionEntity.kt @@ -32,4 +32,4 @@ data class TransactionEntity( @ColumnInfo(name = "latitude") val latitude: Double = 0.0, -) \ No newline at end of file +) diff --git a/app/src/main/java/com/pbd/psi/ui/graph/GraphFragment.kt b/app/src/main/java/com/pbd/psi/ui/graph/GraphFragment.kt index b9e9ccce109c4d5a87ef160a22f2b5fbc899e7af..efee8e0f2e6468913b0f08030cd57f1ce4486942 100644 --- a/app/src/main/java/com/pbd/psi/ui/graph/GraphFragment.kt +++ b/app/src/main/java/com/pbd/psi/ui/graph/GraphFragment.kt @@ -1,110 +1,111 @@ package com.pbd.psi.ui.graph -import android.R import android.graphics.Color import android.graphics.Typeface import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import com.github.mikephil.charting.data.PieEntry import com.github.mikephil.charting.animation.Easing 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.formatter.PercentFormatter import com.github.mikephil.charting.utils.MPPointF import com.pbd.psi.databinding.FragmentGraphBinding - +import com.pbd.psi.repository.GraphRepository +import com.pbd.psi.room.AppDatabase class GraphFragment : Fragment() { private lateinit var binding: FragmentGraphBinding + private val entries: ArrayList<PieEntry> = ArrayList() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment binding = FragmentGraphBinding.inflate(layoutInflater) + val pieChart = binding.pieChart pieChart.setUsePercentValues(true) - pieChart.getDescription().setEnabled(false) + pieChart.description.isEnabled = false pieChart.setExtraOffsets(5f, 10f, 5f, 5f) - - // on below line we are setting drag for our pie chart pieChart.setDragDecelerationFrictionCoef(0.95f) - - // on below line we are setting circle color and alpha pieChart.setTransparentCircleColor(Color.BLACK) pieChart.setTransparentCircleAlpha(110) - - // on below line we are setting hole radius - pieChart.setHoleRadius(58f) - pieChart.setTransparentCircleRadius(61f) - - // on below line we are setting center text - pieChart.setDrawCenterText(true) - - // on below line we are setting - // rotation for our pie chart - pieChart.setRotationAngle(0f) - - // enable rotation of the pieChart by touch - pieChart.setRotationEnabled(true) - pieChart.setHighlightPerTapEnabled(true) - - // on below line we are setting animation for our pie chart + pieChart.holeRadius = 58f + pieChart.transparentCircleRadius = 61f + pieChart.rotationAngle = 0f + pieChart.isRotationEnabled = true + pieChart.isHighlightPerTapEnabled = true pieChart.animateY(1400, Easing.EaseInOutQuad) - - // on below line we are disabling our legend for pie chart pieChart.legend.isEnabled = false pieChart.setEntryLabelColor(Color.WHITE) pieChart.setEntryLabelTextSize(12f) - // on below line we are creating array list and - // adding data to it to display in pie chart - val entries: ArrayList<PieEntry> = ArrayList() - entries.add(PieEntry(150000f)) - entries.add(PieEntry(50000f)) + val appDatabase = AppDatabase.getDatabase(requireContext()) + val repository = GraphRepository(appDatabase) + val viewModel = GraphViewModel(repository) + viewModel.fetchIncomeTotal() + viewModel.fetchExpenseTotal() + + viewModel.incomeTotal.observe(viewLifecycleOwner) { incomeTotal -> + Log.d("GraphFragment", "Income total: $incomeTotal") + binding.textPemasukanNominal?.text = incomeTotal.toString() + addEntries(incomeTotal.toFloat(),"Pemasukan") + updatePieChart(-65536) + } + + viewModel.expenseTotal.observe(viewLifecycleOwner) { expenseTotal -> + Log.d("GraphFragment", "Expense total: $expenseTotal") + binding.textPengeluaranNominal?.text = expenseTotal.toString() + addEntries(expenseTotal.toFloat(),"Pengeluaran") + updatePieChart(-16711936) + } - // on below line we are setting pie data set - val dataSet = PieDataSet(entries, "Mobile OS") + return binding.root + } - // on below line we are setting icons. - dataSet.setDrawIcons(false) + private fun addEntries(value: Float,label: String) { + entries.add(PieEntry(value,label)) + } - // on below line we are setting slice for pie + private fun updatePieChart(color:Int) { + val pieChart = binding.pieChart + val dataSet = PieDataSet(entries, "Mobile OS") + dataSet.setDrawIcons(false) dataSet.sliceSpace = 3f dataSet.iconsOffset = MPPointF(0f, 40f) dataSet.selectionShift = 5f - - // add a lot of colors to list - val colors: ArrayList<Int> = ArrayList() - colors.add(-65536) - colors.add(-16711936) - - // on below line we are setting colors. + Log.d("Entries", entries.toString()) + val colors = ArrayList<Int>() + if(entries.count() == 2){ + if(entries.get(0).label == "Pemasukan"){ + colors.add(-16711936) + colors.add(-65536) + + } + else{ + colors.add(-65536) + colors.add(-16711936) + + } + } + else{ + colors.add(color) + } dataSet.colors = colors - - // on below line we are setting pie data set val data = PieData(dataSet) data.setValueFormatter(PercentFormatter()) data.setValueTextSize(15f) data.setValueTypeface(Typeface.DEFAULT_BOLD) data.setValueTextColor(Color.WHITE) - pieChart.setData(data) - - // undo all highlights + pieChart.data = data pieChart.highlightValues(null) - - pieChart.setHoleColor(Color.parseColor("#121433")); - - // loading chart + pieChart.setHoleColor(Color.parseColor("#121433")) pieChart.invalidate() - - // on below line we are setting slice for pie - dataSet.sliceSpace = 3f - dataSet.iconsOffset = MPPointF(0f, 40f) - dataSet.selectionShift = 5f - return binding.root } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/pbd/psi/ui/graph/GraphViewModel.kt b/app/src/main/java/com/pbd/psi/ui/graph/GraphViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..3fd57b232c17b4f29fdccb4b921c9d44935ffe37 --- /dev/null +++ b/app/src/main/java/com/pbd/psi/ui/graph/GraphViewModel.kt @@ -0,0 +1,34 @@ +package com.pbd.psi.ui.graph + +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.pbd.psi.repository.GraphRepository +import com.pbd.psi.room.Category +import kotlinx.coroutines.launch + +class GraphViewModel(private val repository: GraphRepository) : ViewModel() { + private val _incomeTotal = MutableLiveData<Int>() + val incomeTotal: LiveData<Int> + get() = _incomeTotal + + private val _expenseTotal = MutableLiveData<Int>() + val expenseTotal: LiveData<Int> + get() = _expenseTotal + + fun fetchIncomeTotal() { + viewModelScope.launch { + _incomeTotal.value = repository.getSumTransaction(Category.INCOME) + Log.d("GraphViewModel", "fetchIncomeTotal: ${_incomeTotal.value}") + } + } + + fun fetchExpenseTotal() { + viewModelScope.launch { + _expenseTotal.value = repository.getSumTransaction(Category.EXPENSE) + Log.d("GraphViewModel", "fetchExpenseTotal: ${_expenseTotal.value}") + } + } +}