diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ae17573a4275ed155862c7f7b7c2ee8167d46274..e849b22f2e7d0bda3833c6832feec52961bb57df 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,7 @@ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application + android:name=".BondomanApp" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" diff --git a/app/src/main/java/com/example/bondoman/BondomanApp.kt b/app/src/main/java/com/example/bondoman/BondomanApp.kt new file mode 100644 index 0000000000000000000000000000000000000000..e8231b8f7e97e31027b557ce5064a0b4eefc7ecb --- /dev/null +++ b/app/src/main/java/com/example/bondoman/BondomanApp.kt @@ -0,0 +1,23 @@ +package com.example.bondoman + +import android.app.Application +import android.content.IntentFilter +import com.example.bondoman.database.AppDatabase +import com.example.bondoman.ui.transaction.RandomBroadcastReceiver + +class BondomanApp : Application() { + private val randomReceiver = RandomBroadcastReceiver() + + override fun onCreate() { + super.onCreate() + AppDatabase.getInstance(this) + + val filter = IntentFilter(ACTION_RANDOM_TRANSACTION) + registerReceiver(randomReceiver, filter) + } + + // Global statics should be here + companion object{ + const val ACTION_RANDOM_TRANSACTION = "com.example.bondoman.ACTION_RANDOM_TRANSACTION" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/MainActivity.kt b/app/src/main/java/com/example/bondoman/MainActivity.kt index 50b229fc12a1fbf6a7c6746a21eab7f02d5fbe2d..db3b0685d8c76466c2eb2d28cb5796449b35a432 100644 --- a/app/src/main/java/com/example/bondoman/MainActivity.kt +++ b/app/src/main/java/com/example/bondoman/MainActivity.kt @@ -9,7 +9,6 @@ import com.example.bondoman.ui.login.LoginActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?){ super.onCreate(savedInstanceState) - supportActionBar?.hide() splashScreen() val intent: Intent = if(loginCheck()){ diff --git a/app/src/main/java/com/example/bondoman/api/RetrofitClient.kt b/app/src/main/java/com/example/bondoman/api/RetrofitClient.kt index 16488c067467c8100c9b3edd2732bb78a077ff5d..5eb00ecb247693ae93f97448892c469934ea5437 100644 --- a/app/src/main/java/com/example/bondoman/api/RetrofitClient.kt +++ b/app/src/main/java/com/example/bondoman/api/RetrofitClient.kt @@ -1,6 +1,5 @@ package com.example.bondoman.api -import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory diff --git a/app/src/main/java/com/example/bondoman/database/entity/TransactionEntity.kt b/app/src/main/java/com/example/bondoman/database/entity/TransactionEntity.kt index 18a45f6864304040944084fc86772aa8a64b705e..e21f2dae908b0d72aaa162fb57a3865921e2ba5c 100644 --- a/app/src/main/java/com/example/bondoman/database/entity/TransactionEntity.kt +++ b/app/src/main/java/com/example/bondoman/database/entity/TransactionEntity.kt @@ -10,16 +10,16 @@ data class TransactionEntity ( val id: Int, @ColumnInfo(name = "title") - val title: String, + var title: String, @ColumnInfo(name = "category") - val category: String, + var category: String, @ColumnInfo(name = "amount") - val amount: Int, + var amount: Int, @ColumnInfo(name = "location") - val location: String, + var location: String, @ColumnInfo(name = "timestamp") val timestamp: String, diff --git a/app/src/main/java/com/example/bondoman/types/placeholder b/app/src/main/java/com/example/bondoman/types/placeholder deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/src/main/java/com/example/bondoman/types/util/ExcelUtil.kt b/app/src/main/java/com/example/bondoman/types/util/ExcelUtil.kt index ccb59d1923ccb51578d4ca035f364b56129ff77d..ef89d93c1e157f2805e72381cd765b159531d954 100644 --- a/app/src/main/java/com/example/bondoman/types/util/ExcelUtil.kt +++ b/app/src/main/java/com/example/bondoman/types/util/ExcelUtil.kt @@ -30,9 +30,6 @@ class ExcelUtil(val context: Context) { ) + ext ) - if(transactionList == null) - throw Error(context.getString(R.string.settings_toast_uninitialized_viewmodel)) - val workbook = XSSFWorkbook() val workSheet = workbook.createSheet("Transactions") diff --git a/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt b/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt index 977cb9f97daa38f9a1943c81ef8cfbd68a64962a..121ebf8ed37bd761c53d10da5a403117b381a7c3 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt @@ -6,9 +6,8 @@ import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModelProvider import androidx.navigation.findNavController -import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController +import androidx.viewbinding.ViewBinding import com.example.bondoman.R import com.example.bondoman.database.AppDatabase import com.example.bondoman.database.repository.TransactionRepository @@ -20,12 +19,10 @@ import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.navigation.NavigationView class HubActivity : AppCompatActivity() { - private lateinit var portrait_binding: ActivityHubBinding - private lateinit var landscape_binding: ActivityHubLandscapeBinding + private lateinit var viewBinding: ViewBinding lateinit var transactionViewModel: TransactionViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - supportActionBar?.hide() // Initialize database val database = AppDatabase.getInstance(this) @@ -37,46 +34,24 @@ class HubActivity : AppCompatActivity() { // Initialize navbar and fragments val orientation = resources.configuration.orientation if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - landscape_binding = ActivityHubLandscapeBinding.inflate(layoutInflater) - setContentView(landscape_binding.root) + viewBinding = ActivityHubLandscapeBinding.inflate(layoutInflater) + setContentView(viewBinding.root) // Initialize header - landscape_binding.headerContentLandscape.navBackButton.visibility = View.GONE + (viewBinding as ActivityHubLandscapeBinding).headerContentLandscape.navBackButton.visibility = View.GONE - - val navView: NavigationView = landscape_binding.navViewLandscape + val navView: NavigationView = (viewBinding as ActivityHubLandscapeBinding).navViewLandscape val navController = findNavController(R.id.nav_host_fragment_activity_main) - val appBarConfiguration = AppBarConfiguration( - setOf( - R.id.hub_nav_transaction, - R.id.hub_nav_scan, - R.id.hub_nav_twibbon, - R.id.hub_nav_stats, - R.id.hub_nav_settings, - ) - ) - setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) } else { - portrait_binding = ActivityHubBinding.inflate(layoutInflater) - setContentView(portrait_binding.root) + viewBinding = ActivityHubBinding.inflate(layoutInflater) + setContentView(viewBinding.root) // Initialize header - portrait_binding.headerContent.navBackButton.visibility = View.GONE - + (viewBinding as ActivityHubBinding).headerContent.navBackButton.visibility = View.GONE - val navView: BottomNavigationView = portrait_binding.navView + val navView: BottomNavigationView = (viewBinding as ActivityHubBinding).navView val navController = findNavController(R.id.nav_host_fragment_activity_main) - val appBarConfiguration = AppBarConfiguration( - setOf( - R.id.hub_nav_transaction, - R.id.hub_nav_scan, - R.id.hub_nav_twibbon, - R.id.hub_nav_stats, - R.id.hub_nav_settings, - ) - ) - setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) } } diff --git a/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt index b72183be51bdee01e57afc1287389e7fadc3f19c..75766a8695ab6b1820f13982e33e1d3109fc8bf9 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt @@ -5,6 +5,7 @@ import android.app.Dialog import android.content.DialogInterface import android.os.Bundle import androidx.fragment.app.DialogFragment +import com.example.bondoman.R class ExcelDialogFragment : DialogFragment() { internal lateinit var listener: ExcelDialogListener @@ -19,9 +20,9 @@ class ExcelDialogFragment : DialogFragment() { return activity?.let { val builder = AlertDialog.Builder(it) builder - .setTitle("Excel format") - .setPositiveButton("Confirm", DialogInterface.OnClickListener { _, index -> listener.onExcelDialogPositiveClick(this)}) - .setNegativeButton("Cancel", DialogInterface.OnClickListener { _, index -> listener.onExcelDialogNegativeClick(this)}) + .setTitle(R.string.excel_dialog_label) + .setPositiveButton(R.string.excel_dialog_positive, DialogInterface.OnClickListener { _, _ -> listener.onExcelDialogPositiveClick(this)}) + .setNegativeButton(R.string.excel_dialog_negative, DialogInterface.OnClickListener { _, _ -> listener.onExcelDialogNegativeClick(this)}) .setSingleChoiceItems( arrayOf(".xlsx", ".xls"), 0 ) { _, index -> listener.onExcelDialogChoiceClick(this, index) } diff --git a/app/src/main/java/com/example/bondoman/ui/hub/settings/SettingsFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/settings/SettingsFragment.kt index 906a8b5551658fcea854f37b6d3d0b468d2aca5a..058bbb542c755e0c1aa1e9fcb47b77e3dd19b178 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/settings/SettingsFragment.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/settings/SettingsFragment.kt @@ -17,6 +17,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import com.example.bondoman.BondomanApp import com.example.bondoman.R import com.example.bondoman.databinding.FragmentSettingsBinding import com.example.bondoman.types.enums.ExcelTypes @@ -47,6 +48,7 @@ class SettingsFragment : Fragment(), ExcelDialogFragment.ExcelDialogListener { binding = FragmentSettingsBinding.inflate(inflater, container, false) binding.buttonSaveTransaction.setOnClickListener(::onSaveTransactionClick) binding.buttonSendTransaction.setOnClickListener(::onSendTransactionClick) + binding.buttonRandomTransaction.setOnClickListener(::onRandomTransactionClick) binding.buttonLogout.setOnClickListener(::onLogoutClick) excelUtil = ExcelUtil(requireContext()) @@ -162,6 +164,12 @@ class SettingsFragment : Fragment(), ExcelDialogFragment.ExcelDialogListener { excelDialog.show(parentFragmentManager, "excel") } + + private fun onRandomTransactionClick(view: View){ + val intent = Intent(BondomanApp.ACTION_RANDOM_TRANSACTION) + requireContext().sendBroadcast(intent) + } + //TODO: Implement private fun onLogoutClick(view: View){ val intent = Intent(requireContext(), LoginActivity::class.java) diff --git a/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..9259d4b088f5a410cd53e75f3668ba48bd599af7 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt @@ -0,0 +1,28 @@ +package com.example.bondoman.ui.hub.transaction + +import android.app.AlertDialog +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import androidx.fragment.app.DialogFragment +import com.example.bondoman.R + +class DeleteConfirmDialogFragment : DialogFragment() { + internal lateinit var listener: DeleteConfirmDialogListener + + interface DeleteConfirmDialogListener{ + fun onDeleteDialogPositiveClick(dialog: DialogFragment) + fun onDeleteDialogNegativeClick(dialog: DialogFragment) + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + return activity?.let { + val builder = AlertDialog.Builder(it) + builder + .setTitle(R.string.delete_confirm_dialog_label) + .setPositiveButton(R.string.delete_confirm_dialog_positive, DialogInterface.OnClickListener { _, _ -> listener.onDeleteDialogPositiveClick(this)}) + .setNegativeButton(R.string.delete_confirm_dialog_negative, DialogInterface.OnClickListener { _, _ -> listener.onDeleteDialogNegativeClick(this)}) + builder.create() + } ?: throw IllegalStateException("Activity cannot be null") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt index 2328853577e845518dbbcd365bf21841e442be32..3512b5429264953e9cf056488e3d76391a0a0bc8 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt @@ -1,28 +1,36 @@ package com.example.bondoman.ui.hub.transaction -import android.app.Activity +import android.content.Context import android.content.Intent import android.net.Uri import android.view.LayoutInflater import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.RecyclerView +import com.example.bondoman.R import com.example.bondoman.database.entity.TransactionEntity import com.example.bondoman.databinding.ItemTransactionBinding -import java.text.DecimalFormat +import com.example.bondoman.ui.transaction.TransactionActivity +import com.example.bondoman.viewmodel.transaction.TransactionViewModel import java.text.NumberFormat -import java.util.Currency import java.util.Locale class TransactionAdapter( - private val ctx: Activity, + private val context: Context, + private val fragmentManager: FragmentManager, + private val viewModel: TransactionViewModel, private val tsList: List<TransactionEntity> -): RecyclerView.Adapter<TransactionAdapter.ViewHolder>() { +): RecyclerView.Adapter<TransactionAdapter.ViewHolder>(), DeleteConfirmDialogFragment.DeleteConfirmDialogListener { inner class ViewHolder(val view: ItemTransactionBinding): RecyclerView.ViewHolder(view.root) + private lateinit var transaction: TransactionEntity private lateinit var binding: ItemTransactionBinding + private val deleteConfirmDialog: DeleteConfirmDialogFragment = DeleteConfirmDialogFragment() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - binding = ItemTransactionBinding.inflate(LayoutInflater.from(ctx), parent, false) + binding = ItemTransactionBinding.inflate(LayoutInflater.from(context), parent, false) + deleteConfirmDialog.listener = this return ViewHolder(binding) } @@ -44,12 +52,27 @@ class TransactionAdapter( val gmapsIntentUri = Uri.parse("geo:46.414382,10.013988") val mapIntent = Intent(Intent.ACTION_VIEW, gmapsIntentUri) mapIntent.setPackage("com.google.android.apps.maps") - ctx.startActivity(mapIntent) + context.startActivity(mapIntent) } - // TODO: edit fragment btnEdit.setOnClickListener { + val intent = Intent(context, TransactionActivity::class.java) + intent.putExtra(TransactionActivity.KEY_ACTION, TransactionActivity.ACTION_EDIT) + // TODO: Consider serializing or just pass the id and read it from the transaction page. Might offer better performance though + intent.putExtra(TransactionActivity.KEY_TRANSACTION_ID, tsList[position].id) + intent.putExtra(TransactionActivity.KEY_TITLE, tsList[position].title) + intent.putExtra(TransactionActivity.KEY_AMOUNT, tsList[position].amount) + intent.putExtra(TransactionActivity.KEY_CATEGORY, context.resources.getStringArray(R.array.category_choices).indexOf(tsList[position].category)) + intent.putExtra(TransactionActivity.KEY_LOCATION, tsList[position].location) + intent.putExtra(TransactionActivity.KEY_TIMESTAMP, tsList[position].timestamp) + + context.startActivity(intent) + } + + btnDelete.setOnClickListener { + transaction = tsList[position] + deleteConfirmDialog.show(fragmentManager, "delete") } } } @@ -57,4 +80,13 @@ class TransactionAdapter( override fun getItemCount(): Int { return tsList.size } + + override fun onDeleteDialogPositiveClick(dialog: DialogFragment) { + viewModel.delete(transaction) + deleteConfirmDialog.dismiss() + } + + override fun onDeleteDialogNegativeClick(dialog: DialogFragment) { + deleteConfirmDialog.dismiss() + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt index 8b5847da8f26bc642dd5da28e117ff3d38653ab4..860e0025e60c6081c3b6568e2d59ac4691b50d4b 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt @@ -2,7 +2,6 @@ package com.example.bondoman.ui.hub.transaction import android.content.Intent import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -11,17 +10,12 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import com.example.bondoman.R -import com.example.bondoman.database.entity.TransactionEntity import com.example.bondoman.databinding.FragmentTransactionBinding import com.example.bondoman.ui.hub.HubActivity import com.example.bondoman.ui.transaction.TransactionActivity import com.example.bondoman.viewmodel.transaction.TransactionViewModel -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale -import kotlin.math.log -class TransactionFragment : Fragment() { +class TransactionFragment : Fragment(){ private lateinit var binding: FragmentTransactionBinding private lateinit var tsViewModel: TransactionViewModel @@ -47,7 +41,7 @@ class TransactionFragment : Fragment() { } tsViewModel.list.observe(viewLifecycleOwner) { tsList -> - val adapter = TransactionAdapter(requireActivity(), tsList) + val adapter = TransactionAdapter(requireContext(), this.parentFragmentManager, tsViewModel, tsList) binding.rvTransaction.adapter = adapter } } diff --git a/app/src/main/java/com/example/bondoman/ui/login/LoginActivity.kt b/app/src/main/java/com/example/bondoman/ui/login/LoginActivity.kt index 8928f33fbbbadce653e959bc74312e9de4f37322..f9f4a8bf108683c892a488ad9c9726f927a650d4 100644 --- a/app/src/main/java/com/example/bondoman/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/example/bondoman/ui/login/LoginActivity.kt @@ -11,7 +11,6 @@ class LoginActivity : AppCompatActivity() { private lateinit var binding: ActivityLoginBinding override fun onCreate(savedInstanceState: Bundle?){ super.onCreate(savedInstanceState) - supportActionBar?.hide() binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) diff --git a/app/src/main/java/com/example/bondoman/ui/transaction/RandomBroadcastReceiver.kt b/app/src/main/java/com/example/bondoman/ui/transaction/RandomBroadcastReceiver.kt new file mode 100644 index 0000000000000000000000000000000000000000..3f9b6161955c3212b435e03c73a1ae960cbdd970 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/ui/transaction/RandomBroadcastReceiver.kt @@ -0,0 +1,19 @@ +package com.example.bondoman.ui.transaction + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent + +class RandomBroadcastReceiver : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + + //TODO: Randomizer + val randomIntent = Intent(context, TransactionActivity::class.java) + randomIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + randomIntent.putExtra(TransactionActivity.KEY_TITLE, "apa") + randomIntent.putExtra(TransactionActivity.KEY_AMOUNT, 0) + randomIntent.putExtra(TransactionActivity.KEY_CATEGORY, TransactionActivity.CATEGORY_INCOME) + randomIntent.putExtra(TransactionActivity.KEY_LOCATION, "Ada di mana") + context?.startActivity(randomIntent) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt b/app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt index 5c95c10e7ea50389c9e12dcf86ada64549687265..4d0029ef2cc597299266642286dccd45d09f76bd 100644 --- a/app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt +++ b/app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt @@ -1,6 +1,5 @@ package com.example.bondoman.ui.transaction -import android.content.Intent import android.os.Bundle import android.view.View import android.widget.TextView @@ -21,10 +20,12 @@ import java.util.Locale class TransactionActivity : AppCompatActivity() { private lateinit var binding: ActivityTransactionBinding + private lateinit var transactionViewModel: TransactionViewModel + private var actionCode: Int = 0 + private var transactionId: Int = 0 override fun onCreate(savedInstanceState: Bundle?){ super.onCreate(savedInstanceState) - supportActionBar?.hide() binding = ActivityTransactionBinding.inflate(layoutInflater) setContentView(binding.root) @@ -33,55 +34,101 @@ class TransactionActivity : AppCompatActivity() { val database = AppDatabase.getInstance(this) val transactionRepo = TransactionRepository(database.transactionDao) val transactionModelFactory = TransactionViewModelFactory(transactionRepo) - val transactionViewModel = ViewModelProvider(this, transactionModelFactory)[TransactionViewModel::class.java] + transactionViewModel = ViewModelProvider(this, transactionModelFactory)[TransactionViewModel::class.java] // Initialize header binding.header.navTitle.text = getString(R.string.hub_nav_transaction) val backButton = binding.header.navBackButton + val submitButton = binding.submitButton backButton.setOnClickListener(::onBackClick) + submitButton.setOnClickListener(::onSubmitClick) - // Initialize category dropdown - val spinner = binding.categoryInput - spinner.setSelection(0, true); - (spinner.selectedView as TextView).setTextColor(ContextCompat.getColor(this, R.color.black)) + // Initialize initial values + val titleInitial = intent.getStringExtra(KEY_TITLE) + val amountInitial = intent.getIntExtra(KEY_AMOUNT, 0) + val categoryInitial = intent.getIntExtra(KEY_CATEGORY, 0) + val locationInitial = intent.getStringExtra(KEY_LOCATION) - // Initialize category dropdown - val submitButton = binding.submitButton + binding.titleInput.setText(titleInitial) + binding.amountInput.setText(amountInitial.toString()) + binding.categoryInput.setSelection(categoryInitial, true) + binding.locationInput.setText(locationInitial) - // Create on click - submitButton.setOnClickListener { - val title = binding.titleInput.text.toString() - val category = binding.categoryInput.selectedItem.toString() - val amount = binding.amountInput.text.toString() + // Initialize category dropdown color + (binding.categoryInput.selectedView as TextView).setTextColor(ContextCompat.getColor(this, R.color.black)) - if (title.isEmpty()){ - Toast.makeText(this, getString(R.string.transaction_add_toast_error_title), Toast.LENGTH_SHORT).show() - } - else if (amount.isEmpty()){ - Toast.makeText(this, getString(R.string.transaction_add_toast_error_amount), Toast.LENGTH_SHORT).show() - } - else{ - transactionViewModel.insert( - TransactionEntity( - id = 0, - title = title, - category = category, - amount = amount.toInt(), - // TODO: Location - location = binding.locationInput.text.toString(), - timestamp = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) - ) - ) - Toast.makeText(this, getString(R.string.transaction_add_toast_success), Toast.LENGTH_SHORT).show() -// TODO: Delete, this is for testing purposes -// transactionViewModel.deleteAll() - onBackPressed() - } - } + actionCode = intent.getIntExtra(KEY_ACTION, 0) + transactionId = intent.getIntExtra(KEY_TRANSACTION_ID, 0) + + if(actionCode == ACTION_EDIT) binding.categoryInput.isEnabled = false } // Header back button private fun onBackClick(view: View) { onBackPressed() } + + private fun onSubmitClick(view: View){ + val title = binding.titleInput.text.toString() + val category = binding.categoryInput.selectedItem.toString() + val amount = binding.amountInput.text.toString() + // TODO: Location + val location = binding.locationInput.text.toString() + + if (title.isEmpty()){ + Toast.makeText(this, getString(R.string.transaction_add_toast_error_title), Toast.LENGTH_SHORT).show() + } + else if (amount.isEmpty()){ + Toast.makeText(this, getString(R.string.transaction_add_toast_error_amount), Toast.LENGTH_SHORT).show() + } + else{ + when (actionCode){ + ACTION_ADD ->{ + transactionViewModel.insert( + TransactionEntity( + id = 0, + title = title, + category = category, + amount = amount.toInt(), + location = location, + timestamp = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) + ) + ) + Toast.makeText(this, getString(R.string.transaction_add_toast_success), Toast.LENGTH_SHORT).show() + } + + ACTION_EDIT ->{ + transactionViewModel.update( + TransactionEntity( + id = intent.getIntExtra(KEY_TRANSACTION_ID, 0), + title = title, + category = category, + amount = amount.toInt(), + location = location, + timestamp = intent.getStringExtra(KEY_TIMESTAMP)!! + ) + ) + Toast.makeText(this, getString(R.string.transaction_edit_toast_success), Toast.LENGTH_SHORT).show() + } + } + onBackPressed() + } + } + + companion object{ + const val KEY_TITLE = "Title" + const val KEY_AMOUNT = "Amount" + const val KEY_CATEGORY = "Category" + const val KEY_LOCATION = "Location" + + const val KEY_ACTION = "Action" + const val KEY_TRANSACTION_ID = "TransactionId" + const val KEY_TIMESTAMP = "Timestamp" + + const val ACTION_ADD = 0 + const val ACTION_EDIT = 1 + + const val CATEGORY_INCOME = 0 + const val CATEGORY_EXPENSES = 1 + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 3b1e043043ae68e95c3e61728b62767d7ea0154e..76c0fba574571cf1cf6bce1811063c147be50790 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -10,19 +10,21 @@ android:id="@+id/button_save_transaction" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/settings_save_transaction" android:layout_marginHorizontal="40dp" android:layout_marginTop="40dp" android:backgroundTint="@color/gray" - android:textColor="@color/black" - android:textSize="18sp" android:fontFamily="sans-serif" + android:text="@string/settings_save_transaction" android:textAlignment="viewStart" android:textAllCaps="false" + android:textColor="@color/black" + android:textSize="18sp" + app:cornerRadius="0dp" + app:layout_constraintBottom_toTopOf="@+id/button_send_transaction" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:cornerRadius="0dp" /> + app:layout_constraintTop_toTopOf="parent" /> <com.google.android.material.button.MaterialButton android:id="@+id/button_send_transaction" @@ -38,11 +40,32 @@ android:textColor="@color/black" android:textSize="18sp" app:cornerRadius="0dp" + app:layout_constraintBottom_toTopOf="@+id/button_random_transaction" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.2" + app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button_save_transaction" /> + <com.google.android.material.button.MaterialButton + android:id="@+id/button_random_transaction" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="40dp" + android:layout_marginTop="15dp" + android:backgroundTint="@color/gray" + android:fontFamily="sans-serif" + android:text="@string/settings_random_transaction" + android:textAlignment="viewStart" + android:textAllCaps="false" + android:textColor="@color/black" + android:textSize="18sp" + app:cornerRadius="0dp" + app:layout_constraintBottom_toTopOf="@+id/button_logout" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/button_send_transaction" /> + <com.google.android.material.button.MaterialButton android:id="@+id/button_logout" android:layout_width="match_parent" @@ -58,9 +81,9 @@ android:textSize="18sp" app:cornerRadius="0dp" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.35" + app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/button_send_transaction" /> + app:layout_constraintTop_toBottomOf="@+id/button_random_transaction" /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/item_transaction.xml b/app/src/main/res/layout/item_transaction.xml index 6ef9e046736fb1e94f83b86a674a3048c07ef00d..8dd0443b684ba7f0a717cf57337aac2dd57a6e86 100644 --- a/app/src/main/res/layout/item_transaction.xml +++ b/app/src/main/res/layout/item_transaction.xml @@ -76,6 +76,16 @@ app:layout_constraintEnd_toStartOf="@+id/btnEdit" app:layout_constraintTop_toBottomOf="@+id/tvAmount" /> + <Button + android:id="@+id/btnDelete" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Delete" + android:backgroundTint="@color/red" + app:layout_constraintBottom_toBottomOf="@+id/btnLocation" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@+id/btnLocation" /> + <ImageView android:id="@+id/locationIcon" android:layout_width="16dp" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 689ef937c221b062ef0e4f5f6e160ed5e7a40e4d..2352c58d7b48af769db20cd4a5cb62a285835f23 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,9 +25,12 @@ <string name="transaction_add_toast_error_title">Please enter a title</string> <string name="transaction_add_toast_error_amount">Please enter an amount</string> <string name="transaction_add_toast_success">Transaction saved successfully</string> + <string name="transaction_edit_toast_success">Transaction edited successfully</string> + <string name="transaction_edit_toast_error_non">Transaction edited failed because transaction does not exist</string> <string name="settings_save_transaction">Save transaction list</string> <string name="settings_send_transaction">Send transaction list</string> + <string name="settings_random_transaction">Generate random transaction</string> <string name="settings_logout">Log out</string> <string name="email_subject">Bondoman: Transaction Data</string> @@ -39,10 +42,13 @@ <string name="save_toast_success">File saved</string> <string name="settings_toast_uninitialized_viewmodel">Error: Data Unavailable</string> - <string-array name="category_choices"> - <item>Income</item> - <item>Expenses</item> - </string-array> + <string name="excel_dialog_label">Choose excel format</string> + <string name="excel_dialog_positive">Confirm</string> + <string name="excel_dialog_negative">Cancel</string> + + <string name="delete_confirm_dialog_label">Are you sure to delete this transaction?</string> + <string name="delete_confirm_dialog_positive">Confirm</string> + <string name="delete_confirm_dialog_negative">Cancel</string> <string name="scan_nota">Scan Nota</string> <string name="take_photo">Take Photo</string> @@ -54,4 +60,9 @@ <string name="twibbon_add_toast_success">Successfully saved twibbon</string> <string name="twibbon_add_toast_failed">Failed to save twibbon</string> + + <string-array name="category_choices"> + <item>Income</item> + <item>Expenses</item> + </string-array> </resources> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index f1776cdc99f8db6413d29e9bc32f6ba427cc688a..53c454ef290773897ca1ff0bc6e0de1c9400b71c 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,6 +1,6 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> - <style name="Theme.BondoMan" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> + <style name="Theme.BondoMan" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/purple_500</item> <item name="colorPrimaryVariant">@color/purple_700</item>