diff --git a/app/src/main/java/pbd/tubes/exe_android/ui/chart/ChartFragment.kt b/app/src/main/java/pbd/tubes/exe_android/ui/chart/ChartFragment.kt index f7df11c3e83efe7508d43145307174276c23effe..691ed45b47d16e1c0934c5943286228ba534a998 100644 --- a/app/src/main/java/pbd/tubes/exe_android/ui/chart/ChartFragment.kt +++ b/app/src/main/java/pbd/tubes/exe_android/ui/chart/ChartFragment.kt @@ -44,6 +44,7 @@ class ChartFragment : Fragment() { pieChart.setTransparentCircleColor(Color.WHITE) pieChart.description = null + //TODO(Specify legend) viewModel.fetchTotalByCategory() viewModel.nominalSumByCategory?.observe(viewLifecycleOwner){ val dataArrayList = viewModel.dataToArrayList() diff --git a/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsFragment.kt b/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsFragment.kt index 1bcdc193d4104b8c7e7f576d3ee027b214aff197..b5814b9d70cda7b5c23a3444ae4aace0247f52eb 100644 --- a/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsFragment.kt @@ -8,6 +8,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import pbd.tubes.exe_android.LoginActivity @@ -46,6 +47,7 @@ class SettingsFragment : Fragment() { R.id.xls_choice -> viewModel.saveXLS() R.id.xlsx_choice -> viewModel.saveXLSX() } + Toast.makeText(requireContext(), "File is saved", Toast.LENGTH_SHORT).show() } return root } diff --git a/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsViewModel.kt b/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsViewModel.kt index ba51a6db424c8a4bfbaf2113516a21cad23923f9..e8f9f1c7593dafe223c2812ab7a00d44a01f6280 100644 --- a/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/pbd/tubes/exe_android/ui/settings/SettingsViewModel.kt @@ -1,5 +1,6 @@ package pbd.tubes.exe_android.ui.settings +import android.os.Environment import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel @@ -9,40 +10,32 @@ import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.CreationExtras import kotlinx.coroutines.launch import org.apache.poi.hssf.usermodel.HSSFWorkbook -import org.apache.poi.ss.usermodel.FillPatternType -import org.apache.poi.ss.usermodel.IndexedColors import org.apache.poi.xssf.usermodel.XSSFWorkbook import pbd.tubes.exe_android.BondomanApp import pbd.tubes.exe_android.data.database.TransactionsRepository import pbd.tubes.exe_android.models.Transaction -import kotlin.io.path.createTempFile -import kotlin.io.path.outputStream +import java.io.File +import java.io.FileOutputStream class SettingsViewModel( private val transactionsRepository: TransactionsRepository ) : ViewModel() { var transactionList: LiveData<List<Transaction>>? = null + + //TODO(Format date, DateFormatter java library causes crash) fun saveXLSX(){ val workbook = XSSFWorkbook() val workSheet = workbook.createSheet("Daftar Transaksi") - val cellStyle = workbook.createCellStyle() - cellStyle.fillForegroundColor = IndexedColors.YELLOW.getIndex() - cellStyle.fillPattern = FillPatternType.SOLID_FOREGROUND - val firstRow = workSheet - .createRow(0) - firstRow.rowStyle = cellStyle - - val headers = arrayListOf("Tanggal", "Kategori Transaksi", "Nominal Transaksi", "Nama Transaksi", "Lokasi") - var headersItr = 0 - for (i in firstRow.cellIterator()) { - firstRow.createCell(i.columnIndex) - i.setCellValue(headers[headersItr]) - headersItr++ - } - for (i in transactionList!!.value!!.indices+1){ - val row = workSheet.createRow(i) + var row = workSheet.createRow(0) + row.createCell(0).setCellValue("Tanggal") + row.createCell(1).setCellValue("Kategori Transaksi") + row.createCell(2).setCellValue("Nominal Transaksi") + row.createCell(3).setCellValue("Nama Transaksi") + row.createCell(4).setCellValue("Lokasi") + for (i in transactionList!!.value!!.indices){ + row = workSheet.createRow(i+1) row.createCell(0).setCellValue(transactionList!!.value!![i].date) row.createCell(1).setCellValue(transactionList!!.value!![i].category.toString()) row.createCell(2).setCellValue(transactionList!!.value!![i].nominal) @@ -50,33 +43,29 @@ class SettingsViewModel( row.createCell(4).setCellValue(transactionList!!.value!![i].lokasi) } - //TODO(selecting path from user) - //TODO(testing if data is correct) - val tempFile = createTempFile("daftar_transaksi_", ".xlsx") - workbook.write(tempFile.outputStream()) +// val tempFile = createTempFile("daftar_transaksi_", ".xlsx") + val directory = File(Environment.getExternalStorageDirectory(), "Download") + if (!directory.exists()) { + directory.mkdirs() + } + val file = File(directory, "daftar_transaksi.xlsx") + + FileOutputStream(file).use {workbook.write(it)} workbook.close() Log.d("MyApp", "xlsx saved") } fun saveXLS(){ val workbook = HSSFWorkbook() val workSheet = workbook.createSheet("Daftar Transaksi") -// val cellStyle = workbook.createCellStyle() -// cellStyle.fillForegroundColor = IndexedColors.YELLOW.getIndex() -// cellStyle.fillPattern = FillPatternType.SOLID_FOREGROUND - val firstRow = workSheet - .createRow(0) -// firstRow.setRowStyle(cellStyle) - val headers = arrayListOf("Tanggal", "Kategori Transaksi", "Nominal Transaksi", "Nama Transaksi", "Lokasi") - var headersItr = 0 - for (i in firstRow.cellIterator()) { - firstRow.createCell(i.columnIndex) - i.setCellValue(headers[headersItr]) - headersItr++ - } - - for (i in transactionList!!.value!!.indices+1){ - val row = workSheet.createRow(i) + var row = workSheet.createRow(0) + row.createCell(0).setCellValue("Tanggal") + row.createCell(1).setCellValue("Kategori Transaksi") + row.createCell(2).setCellValue("Nominal Transaksi") + row.createCell(3).setCellValue("Nama Transaksi") + row.createCell(4).setCellValue("Lokasi") + for (i in transactionList!!.value!!.indices){ + row = workSheet.createRow(i+1) row.createCell(0).setCellValue(transactionList!!.value!![i].date) row.createCell(1).setCellValue(transactionList!!.value!![i].category.toString()) row.createCell(2).setCellValue(transactionList!!.value!![i].nominal) @@ -84,10 +73,15 @@ class SettingsViewModel( row.createCell(4).setCellValue(transactionList!!.value!![i].lokasi) } - //TODO(selecting path from user) - //TODO(testing if data is correct) - val tempFile = createTempFile("daftar_transaksi_", ".xls") - workbook.write(tempFile.outputStream()) +// val tempFile = createTempFile("daftar_transaksi_", ".xls") + + val directory = File(Environment.getExternalStorageDirectory(), "Download") + if (!directory.exists()) { + directory.mkdirs() + } + val file = File(directory, "daftar_transaksi.xls") + + FileOutputStream(file).use {workbook.write(it)} workbook.close() Log.d("MyApp", "xls saved") } diff --git a/app/src/main/java/pbd/tubes/exe_android/ui/transactions/AddTransactionFragment.kt b/app/src/main/java/pbd/tubes/exe_android/ui/transactions/AddTransactionFragment.kt index 62fc655220aaa0e7eaa10ea69951bb07e9f836f6..026838875e13cb5e6e0aca4e4da20457837d2bc6 100644 --- a/app/src/main/java/pbd/tubes/exe_android/ui/transactions/AddTransactionFragment.kt +++ b/app/src/main/java/pbd/tubes/exe_android/ui/transactions/AddTransactionFragment.kt @@ -34,34 +34,13 @@ class AddTransactionFragment : Fragment() { val viewModel: AddTransactionViewModel by viewModels(factoryProducer = { AddTransactionViewModel.Factory }) val transactionName: TextInputLayout = binding.transactionNameInputLayout - var userInteractedWithName = false - transactionName.editText?.setOnFocusChangeListener { _, hasFocus -> - // When the TextInputLayout gains focus, set userInteracted flag to true - userInteractedWithName = hasFocus - } viewModel.trName.observe(viewLifecycleOwner) { transactionName.editText?.setText(it) - if (userInteractedWithName) { - // Enable error if location is empty or invalid (replace with your condition) - val nameError = if (it.isNullOrEmpty()) "Name is required" else null - transactionName.error = nameError - transactionName.isErrorEnabled = nameError != null - } } val transactionNominal: TextInputLayout = binding.transactionNominalInputLayout - var userInteractedWithNominal = false - transactionNominal.editText?.setOnFocusChangeListener { _, hasFocus -> - // When the TextInputLayout gains focus, set userInteracted flag to true - userInteractedWithNominal = hasFocus - } viewModel.trNominal.observe(viewLifecycleOwner) { transactionNominal.editText?.setText(it) - if (userInteractedWithNominal) { - val nominalError = if (it.isNullOrEmpty()) "Nominal is required" else null - transactionNominal.error = nominalError - transactionNominal.isErrorEnabled = nominalError != null - } } val transactionCategoryPemasukan: RadioButton = binding.radioPemasukan @@ -74,18 +53,8 @@ class AddTransactionFragment : Fragment() { } val transactionLocation: TextInputLayout = binding.transactionLocationInputLayout - var userInteractedWithLoc = false - transactionLocation.editText?.setOnFocusChangeListener { _, hasFocus -> - // When the TextInputLayout gains focus, set userInteracted flag to true - userInteractedWithLoc = hasFocus - } viewModel.trLocation.observe(viewLifecycleOwner) { transactionLocation.editText?.setText(it) - if (userInteractedWithLoc) { - val locationError = if (it.isNullOrEmpty()) "Location is required" else null - transactionLocation.error = locationError - transactionLocation.isErrorEnabled = locationError != null - } } fun chooseCategory() : TransactionCategory? { @@ -98,10 +67,6 @@ class AddTransactionFragment : Fragment() { } binding.submitButton.setOnClickListener{ - // TODO(Handling null input values) -// if (!transactionCategoryPemasukan.isChecked && !transactionCategoryPembelian.isChecked){ -// // tell user to input -// } viewLifecycleOwner.lifecycleScope.launch { try { viewModel.submitTransaction( @@ -116,7 +81,7 @@ class AddTransactionFragment : Fragment() { findNavController().navigate(R.id.navigation_transactions) } catch (e : NullPointerException) { Toast.makeText(requireContext(), - "Error! $e", + "Error! Please fill in all fields", Toast.LENGTH_SHORT).show() Log.e("NULL", "Input has null") }