diff --git a/app/src/androidTest/java/com/example/bondoman/databases/TransactionDatabaseTest.kt b/app/src/androidTest/java/com/example/bondoman/databases/TransactionDatabaseTest.kt index 8b8618e6488873c0c731b64cda5a88494cee0335..8767eda895e803308d75fe3233ee7ee35fae817e 100644 --- a/app/src/androidTest/java/com/example/bondoman/databases/TransactionDatabaseTest.kt +++ b/app/src/androidTest/java/com/example/bondoman/databases/TransactionDatabaseTest.kt @@ -4,10 +4,11 @@ import android.content.Context import androidx.room.Room import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.example.bondoman.dataaccess.TransactionDao -import com.example.bondoman.models.Transaction -import com.example.bondoman.models.TransactionCategory -import com.example.bondoman.repositories.TransactionRepository +import com.example.bondoman.data.dataaccess.TransactionDao +import com.example.bondoman.data.databases.TransactionDatabase +import com.example.bondoman.data.models.Transaction +import com.example.bondoman.data.models.TransactionCategory +import com.example.bondoman.data.repositories.TransactionRepository import kotlinx.coroutines.runBlocking import org.junit.After import org.junit.Before @@ -47,7 +48,7 @@ class TransactionDatabaseTest { val transaction1 = Transaction( - name = "Transaction 1", + title = "Transaction 1", owner = user, category = TransactionCategory.EARNINGS, amount = 100.0, @@ -55,7 +56,7 @@ class TransactionDatabaseTest { val transaction2 = Transaction( - name = "Transaction 2", + title = "Transaction 2", owner = user, category = TransactionCategory.EARNINGS, amount = 200.0, @@ -63,7 +64,7 @@ class TransactionDatabaseTest { val transaction3 = Transaction( - name = "Transaction 3", + title = "Transaction 3", owner = user, category = TransactionCategory.EXPENSE, amount = 100.0, @@ -78,7 +79,7 @@ class TransactionDatabaseTest { val transaction1FromDB = repository.getById(1) assert(transaction1FromDB != null) - assert(transaction1FromDB!!.name == transaction1.name) + assert(transaction1FromDB!!.title == transaction1.title) assert(transaction1FromDB.category == transaction1.category) assert(transaction1FromDB.amount == transaction1.amount) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8d7d0d3e505c86511cfcbc2399da76ebbc7cb2be..bba3e321a3861f73ac47f7d6bd7001208eb8b38e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ android:maxSdkVersion="28" /> <application + android:name=".MainApplication" android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" @@ -18,11 +19,10 @@ android:supportsRtl="true" android:theme="@style/Theme.BondoMan"> <activity - android:name=".activities.MainActivity" - android:exported="true"> - </activity> + android:name=".views.activities.MainActivity" + android:exported="true"></activity> <activity - android:name=".activities.LoginActivity" + android:name=".views.activities.LoginActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/app/src/main/java/com/example/bondoman/MainApplication.kt b/app/src/main/java/com/example/bondoman/MainApplication.kt new file mode 100644 index 0000000000000000000000000000000000000000..ba1311aaa4be2bafbfe761de781e88089cf347bf --- /dev/null +++ b/app/src/main/java/com/example/bondoman/MainApplication.kt @@ -0,0 +1,15 @@ +package com.example.bondoman + +import android.app.Application +import com.example.bondoman.cores.containers.AppContainer +import com.example.bondoman.cores.containers.DefaultAppContainer +import com.example.bondoman.data.databases.TransactionDatabase + +class MainApplication : Application() { + lateinit var container: AppContainer + override fun onCreate() { + super.onCreate() + val database = TransactionDatabase.getInstance(applicationContext) + container = DefaultAppContainer(database) + } +} diff --git a/app/src/main/java/com/example/bondoman/components/DateInputComponent.kt b/app/src/main/java/com/example/bondoman/components/DateInputComponent.kt deleted file mode 100644 index eb282fd8c398d9fcbd1f0e93d4864fbea7419082..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/components/DateInputComponent.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.example.bondoman.components - -import android.content.Context -import android.util.AttributeSet -import android.widget.LinearLayout -import androidx.appcompat.app.AppCompatActivity -import com.example.bondoman.R -import com.example.bondoman.fragments.DatePickerFragment -import com.google.android.material.button.MaterialButton -import com.google.android.material.textview.MaterialTextView - -class DateInputComponent - @JvmOverloads - constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - ) : LinearLayout(context, attrs, defStyleAttr) { - companion object { - const val FRAGMENT_TAG = "datePicker" - } - - private val labelTextView: MaterialTextView - private val button: MaterialButton - private var onDatePickedListener: ((year: Int, month: Int, day: Int) -> Unit)? = null - - init { - inflate(context, R.layout.component_date_input, this) - - labelTextView = findViewById(R.id.date_input_component_label) - button = findViewById(R.id.date_input_button) - - // Load attributes - val attributes = context.obtainStyledAttributes(attrs, R.styleable.DateInputComponent) - val labelText = attributes.getString(R.styleable.DateInputComponent_dateInputLabel) ?: "" - attributes.recycle() - - // Set label text and hint - labelTextView.text = labelText - - if (context is AppCompatActivity) { - button.setOnClickListener { - val datePickerFragment = DatePickerFragment() - datePickerFragment.setOnDatePicked { year, month, day -> - setText("$year/${month + 1}/$day") - onDatePickedListener?.invoke(year, month, day) - } - datePickerFragment.show(context.supportFragmentManager, FRAGMENT_TAG) - } - } - } - - fun setText(text: String) { - button.text = text - } - - fun setOnDatePicked(listener: (year: Int, month: Int, day: Int) -> Unit) { - onDatePickedListener = listener - } - } diff --git a/app/src/main/java/com/example/bondoman/components/DialogComponent.kt b/app/src/main/java/com/example/bondoman/components/DialogComponent.kt deleted file mode 100644 index 03ac65c928ea79378140c6f79ec3ff669a1e5eaa..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/components/DialogComponent.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.example.bondoman.components - -import android.content.Context -import android.util.AttributeSet -import android.widget.LinearLayout -import androidx.core.content.ContextCompat -import com.example.bondoman.R -import com.google.android.material.button.MaterialButton -import com.google.android.material.textview.MaterialTextView - -class DialogComponent - @JvmOverloads - constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - ) : LinearLayout(context, attrs, defStyleAttr) { - companion object { - enum class ButtonType(val value: Int) { - POSITIVE_BUTTON(1), - NEUTRAL_BUTTON(0), - NEGATIVE_BUTTON(-1), - } - - val buttonTypeMap = - mapOf( - 1 to ButtonType.POSITIVE_BUTTON, - 0 to ButtonType.NEUTRAL_BUTTON, - -1 to ButtonType.NEGATIVE_BUTTON, - ) - - val buttonBackgroundColorMap = - mapOf( - ButtonType.POSITIVE_BUTTON to R.color.teal_200, - ButtonType.NEUTRAL_BUTTON to R.color.zinc_600, - ButtonType.NEGATIVE_BUTTON to R.color.rose_200, - ) - - val buttonTextColorMap = - mapOf( - ButtonType.POSITIVE_BUTTON to R.color.zinc_900, - ButtonType.NEUTRAL_BUTTON to R.color.zinc_300, - ButtonType.NEGATIVE_BUTTON to R.color.zinc_900, - ) - } - - private val textView: MaterialTextView - private val firstButton: MaterialButton - private val secondButton: MaterialButton - - init { - inflate(context, R.layout.component_dialog, this) - - textView = findViewById(R.id.dialog_text) - firstButton = findViewById(R.id.dialog_first_button) - secondButton = findViewById(R.id.dialog_second_button) - - // Load attributes - val attributes = context.obtainStyledAttributes(attrs, R.styleable.DialogComponent) - val text = attributes.getString(R.styleable.DialogComponent_dialogText) ?: "" - val firstButtonTypeOrdinal = attributes.getInt(R.styleable.DialogComponent_dialogFirstButtonType, ButtonType.NEUTRAL_BUTTON.ordinal) - val secondButtonTypeOrdinal = attributes.getInt(R.styleable.DialogComponent_dialogSecondButtonType, ButtonType.POSITIVE_BUTTON.ordinal) - val firstButtonText = attributes.getString(R.styleable.DialogComponent_firstButtonText) ?: "" - val secondButtonText = attributes.getString(R.styleable.DialogComponent_secondButtonText) ?: "" - - attributes.recycle() - - // Set label text - setText(text) - - // Set button types - setFirstButtonType(buttonTypeMap[firstButtonTypeOrdinal]!!) - setSecondButtonType(buttonTypeMap[secondButtonTypeOrdinal]!!) - - // set button text - setFirstButtonText(firstButtonText) - setSecondButtonText(secondButtonText) - } - - fun setText(text: String) { - textView.text = text - } - - fun setFirstButtonText(text: String) { - firstButton.text = text - } - - fun setSecondButtonText(text: String) { - secondButton.text = text - } - - fun setFirstButtonOnClickListener(listener: () -> Unit) { - firstButton.setOnClickListener { listener() } - } - - fun setSecondButtonOnClickListener(listener: () -> Unit) { - secondButton.setOnClickListener { listener() } - } - - fun setFirstButtonType(type: ButtonType) { - firstButton.setBackgroundColor(ContextCompat.getColor(context, buttonBackgroundColorMap[type]!!)) - firstButton.setTextColor(ContextCompat.getColor(context, buttonTextColorMap[type]!!)) - } - - fun setSecondButtonType(type: ButtonType) { - secondButton.setBackgroundColor(ContextCompat.getColor(context, buttonBackgroundColorMap[type]!!)) - secondButton.setTextColor(ContextCompat.getColor(context, buttonTextColorMap[type]!!)) - } - } diff --git a/app/src/main/java/com/example/bondoman/components/SettingButtonComponent.kt b/app/src/main/java/com/example/bondoman/components/SettingButtonComponent.kt deleted file mode 100644 index 19caa50f2d3ad29487d4c197833197d99bd5c64d..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/components/SettingButtonComponent.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.example.bondoman.components - -import android.animation.ArgbEvaluator -import android.animation.ObjectAnimator -import android.content.Context -import android.util.AttributeSet -import android.widget.ImageView -import android.widget.LinearLayout -import androidx.constraintlayout.widget.ConstraintLayout -import com.example.bondoman.R -import com.google.android.material.textview.MaterialTextView - -class SettingButtonComponent - @JvmOverloads - constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - ) : LinearLayout(context, attrs, defStyleAttr) { - private val layout: ConstraintLayout - private val icon: ImageView - private val title: MaterialTextView - private val subtitle: MaterialTextView - - init { - inflate(context, R.layout.component_setting_button, this) - - layout = findViewById(R.id.setting_button_layout) - icon = findViewById(R.id.setting_button_icon) - title = findViewById(R.id.setting_button_title) - subtitle = findViewById(R.id.setting_button_subtitle) - - // Load attributes - val attributes = context.obtainStyledAttributes(attrs, R.styleable.SettingButtonComponent) - val icon = attributes.getDrawable(R.styleable.SettingButtonComponent_settingButtonIcon) - val title = attributes.getString(R.styleable.SettingButtonComponent_settingButtonTitle) ?: "" - val subtitle = attributes.getString(R.styleable.SettingButtonComponent_settingButtonSubtitle) ?: "" - - // Set values - this.icon.setImageDrawable(icon) - this.title.text = title - this.subtitle.text = subtitle - - // On Click Listener - layout.setOnClickListener { - // Change the background color of the layout - layout.setBackgroundColor(resources.getColor(R.color.button_pressed_color, null)) - - // Animate the background color to slowly fade back to the original color for 1s - val fadeBackAnimator = - ObjectAnimator.ofArgb( - layout, - "backgroundColor", - resources.getColor(R.color.button_pressed_color, null), - resources.getColor(R.color.button_default_color, null), - ) - fadeBackAnimator.duration = 500 // 1 second - fadeBackAnimator.setEvaluator(ArgbEvaluator()) - fadeBackAnimator.start() - } - - attributes.recycle() - } - } diff --git a/app/src/main/java/com/example/bondoman/components/TextInputComponent.kt b/app/src/main/java/com/example/bondoman/components/TextInputComponent.kt deleted file mode 100644 index 6261cc85994babbac3d81eaabbfd2cb88c80c5c6..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/components/TextInputComponent.kt +++ /dev/null @@ -1,98 +0,0 @@ -package com.example.bondoman.components - -import android.content.Context -import android.text.Editable -import android.text.TextWatcher -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.LinearLayout -import com.example.bondoman.R -import com.google.android.material.textfield.TextInputEditText -import com.google.android.material.textview.MaterialTextView - -class TextInputComponent - @JvmOverloads - constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - ) : LinearLayout(context, attrs, defStyleAttr) { - private val labelTextView: MaterialTextView - private val inputEditText: TextInputEditText - private var beforeTextChangedListener: ((text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? = null - private var onTextChangedListener: ((text: CharSequence?, start: Int, before: Int, count: Int) -> Unit)? = null - private var afterTextChangedListener: ((text: Editable?) -> Unit)? = null - - init { - LayoutInflater.from(context).inflate(R.layout.component_text_input, this, true) - - labelTextView = findViewById(R.id.text_input_component_label) - inputEditText = findViewById(R.id.text_input_component_field) - - // Load attributes - val attributes = context.obtainStyledAttributes(attrs, R.styleable.TextInputComponent) - val labelText = attributes.getString(R.styleable.TextInputComponent_textInputLabel) ?: "" - val hint = attributes.getString(R.styleable.TextInputComponent_textInputHint) ?: "" - attributes.recycle() - - // Set label text and hint - labelTextView.text = labelText - inputEditText.hint = hint - - // Set up text watcher - inputEditText.addTextChangedListener( - object : TextWatcher { - override fun beforeTextChanged( - s: CharSequence?, - start: Int, - count: Int, - after: Int, - ) { - beforeTextChangedListener?.invoke(s, start, count, after) - } - - override fun onTextChanged( - s: CharSequence?, - start: Int, - before: Int, - count: Int, - ) { - onTextChangedListener?.invoke(s, start, before, count) - } - - override fun afterTextChanged(s: Editable?) { - afterTextChangedListener?.invoke(s) - } - }, - ) - } - - fun setText(text: String) { - inputEditText.setText(text) - } - - fun getText(): String { - return inputEditText.text.toString() - } - - fun disable() { - inputEditText.isEnabled = false - } - - fun enable() { - inputEditText.isEnabled = true - } - - // Setter methods for text change listeners - fun setBeforeTextChangedListener(listener: (text: CharSequence?, start: Int, count: Int, after: Int) -> Unit) { - beforeTextChangedListener = listener - } - - fun setOnTextChangedListener(listener: (text: CharSequence?, start: Int, before: Int, count: Int) -> Unit) { - onTextChangedListener = listener - } - - fun setAfterTextChangedListener(listener: (text: Editable?) -> Unit) { - afterTextChangedListener = listener - } - } diff --git a/app/src/main/java/com/example/bondoman/cores/containers/AppContainer.kt b/app/src/main/java/com/example/bondoman/cores/containers/AppContainer.kt new file mode 100644 index 0000000000000000000000000000000000000000..36eca093cff0f51b2ded4b2321b4dfba4daa0215 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/cores/containers/AppContainer.kt @@ -0,0 +1,7 @@ +package com.example.bondoman.cores.containers + +import com.example.bondoman.data.repositories.TransactionRepository + +interface AppContainer { + val transactionRepository: TransactionRepository +} diff --git a/app/src/main/java/com/example/bondoman/cores/containers/DefaultAppContainer.kt b/app/src/main/java/com/example/bondoman/cores/containers/DefaultAppContainer.kt new file mode 100644 index 0000000000000000000000000000000000000000..e81973fe9b82869bd571984c32e4890e4f67eb69 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/cores/containers/DefaultAppContainer.kt @@ -0,0 +1,14 @@ +package com.example.bondoman.cores.containers + +import com.example.bondoman.data.dataaccess.TransactionDao +import com.example.bondoman.data.databases.TransactionDatabase +import com.example.bondoman.data.repositories.TransactionRepository + +class DefaultAppContainer(database: TransactionDatabase) : AppContainer { + private val transactionDao: TransactionDao by lazy { + database.transactionDao() + } + override val transactionRepository: TransactionRepository by lazy { + TransactionRepository(transactionDao) + } +} diff --git a/app/src/main/java/com/example/bondoman/data/dataaccess/TransactionDao.kt b/app/src/main/java/com/example/bondoman/data/dataaccess/TransactionDao.kt new file mode 100644 index 0000000000000000000000000000000000000000..d56240a0513bd9139d8fc7785f10af93fe18f3b8 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/data/dataaccess/TransactionDao.kt @@ -0,0 +1,30 @@ +package com.example.bondoman.data.dataaccess + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query +import com.example.bondoman.data.models.Transaction + +@Dao +interface TransactionDao { + @Query("SELECT * FROM transactions WHERE owner = :owner ORDER BY date DESC") + suspend fun getAll(owner: String): List<Transaction> + + @Query("SELECT * FROM transactions WHERE id = :id and owner = :owner") + suspend fun getById(id: Long, owner: String): Transaction? + + @Insert + suspend fun insert(vararg transaction: Transaction) + + @Query("UPDATE transactions SET title = :title, amount = :amount, location = :location WHERE id = :id and owner = :owner") + suspend fun update( + id: Long, + owner: String, + title: String, + amount: Double, + location: String? + ) + + @Query("DELETE FROM transactions WHERE id = :id and owner = :owner") + suspend fun delete(id: Long, owner: String) +} diff --git a/app/src/main/java/com/example/bondoman/databases/TransactionDatabase.kt b/app/src/main/java/com/example/bondoman/data/databases/TransactionDatabase.kt similarity index 87% rename from app/src/main/java/com/example/bondoman/databases/TransactionDatabase.kt rename to app/src/main/java/com/example/bondoman/data/databases/TransactionDatabase.kt index eb58d14f60726c2717b6223b3c23c5cf336c2ab5..5342476215aac278a22739538a6e6c61abf43081 100644 --- a/app/src/main/java/com/example/bondoman/databases/TransactionDatabase.kt +++ b/app/src/main/java/com/example/bondoman/data/databases/TransactionDatabase.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.databases +package com.example.bondoman.data.databases import android.content.Context import androidx.room.Database @@ -6,8 +6,8 @@ import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverter import androidx.room.TypeConverters -import com.example.bondoman.dataaccess.TransactionDao -import com.example.bondoman.models.Transaction +import com.example.bondoman.data.dataaccess.TransactionDao +import com.example.bondoman.data.models.Transaction import java.util.Date class DateConverter { diff --git a/app/src/main/java/com/example/bondoman/models/ParcelableBitmap.kt b/app/src/main/java/com/example/bondoman/data/models/ParcelableBitmap.kt similarity index 80% rename from app/src/main/java/com/example/bondoman/models/ParcelableBitmap.kt rename to app/src/main/java/com/example/bondoman/data/models/ParcelableBitmap.kt index 448c2ffcc5f48c65b340554eb9e78c0351dc9bb7..ad581c2cbc0c403f0e1ff01a516225514fe991b2 100644 --- a/app/src/main/java/com/example/bondoman/models/ParcelableBitmap.kt +++ b/app/src/main/java/com/example/bondoman/data/models/ParcelableBitmap.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.models +package com.example.bondoman.data.models import android.graphics.Bitmap import android.os.Parcelable diff --git a/app/src/main/java/com/example/bondoman/models/Transaction.kt b/app/src/main/java/com/example/bondoman/data/models/Transaction.kt similarity index 51% rename from app/src/main/java/com/example/bondoman/models/Transaction.kt rename to app/src/main/java/com/example/bondoman/data/models/Transaction.kt index ab856fea373b2f2270a63ac008522d96d28006bc..9defafbf4ad24445b24e21302f57a8059758fc9c 100644 --- a/app/src/main/java/com/example/bondoman/models/Transaction.kt +++ b/app/src/main/java/com/example/bondoman/data/models/Transaction.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.models +package com.example.bondoman.data.models import androidx.room.Entity import androidx.room.PrimaryKey @@ -13,10 +13,20 @@ enum class TransactionCategory { data class Transaction( @PrimaryKey(autoGenerate = true) val id: Long = 0L, - val name: String, + val title: String, val owner: String, val category: TransactionCategory, val amount: Double, val date: Date = Date(), val location: String? = null -) +) { + init { + require(title.isNotEmpty()) { "Transaction " } + require(amount > 0 && amount <= MAX_AMOUNT) { "Amount cannot exceed $MAX_AMOUNT" } + require(location == null || location.isNotEmpty()) { "Location cannot be blank" } + } + + companion object { + const val MAX_AMOUNT = Double.MAX_VALUE + } +} diff --git a/app/src/main/java/com/example/bondoman/data/repositories/TransactionRepository.kt b/app/src/main/java/com/example/bondoman/data/repositories/TransactionRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..c49d6e90812b449fc20cdddda5927a9a0fc8f0f4 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/data/repositories/TransactionRepository.kt @@ -0,0 +1,22 @@ +package com.example.bondoman.data.repositories + +import com.example.bondoman.data.dataaccess.TransactionDao +import com.example.bondoman.data.models.Transaction + +class TransactionRepository(private val transactionDao: TransactionDao) { + suspend fun getAll(owner: String) = transactionDao.getAll(owner) + + suspend fun getById(id: Long, owner: String) = transactionDao.getById(id, owner) + + suspend fun insert(vararg transaction: Transaction) = transactionDao.insert(*transaction) + + suspend fun update( + id: Long, + owner: String, + title: String, + amount: Double, + location: String? + ) = transactionDao.update(id, owner, title, amount, location) + + suspend fun delete(id: Long, owner: String) = transactionDao.delete(id, owner) +} diff --git a/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt b/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..59d1f86f417fa77dee98bb7d2934dbe5ee364bba --- /dev/null +++ b/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModel.kt @@ -0,0 +1,49 @@ +package com.example.bondoman.data.viewmodels.transaction + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.example.bondoman.data.models.Transaction +import com.example.bondoman.data.models.TransactionCategory +import com.example.bondoman.data.repositories.TransactionRepository + +class TransactionViewModel(transactionRepository: TransactionRepository, userNim: String) : + ViewModel() { + // TODO: add nim attribute + private val currentUserNim = MutableLiveData(userNim) + private fun insertTransaction( + title: String, + category: TransactionCategory, + amount: Double, + location: String? + ) { + val newTransaction = Transaction( + title = title, + owner = currentUserNim.value!!, + amount = amount, + category = category, + location = location + ) + } + + private fun updateTransaction( + id: Long, + nim: String, + title: String, + amount: Double, + location: String + ) { + + + } + + private fun insertTransaction( + id: Long, + nim: String, + title: String, + amount: Double, + location: String + ) { + + + } +} diff --git a/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModelFactory.kt b/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModelFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..59197483c85a5c0b0d75ac6fa63844517de1eac1 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/data/viewmodels/transaction/TransactionViewModelFactory.kt @@ -0,0 +1,16 @@ +package com.example.bondoman.data.viewmodels.transaction + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.bondoman.MainApplication + + +class TransactionViewModelFactory( + private val application: MainApplication, + private val userNim: String +) : ViewModelProvider.Factory { + override fun <T : ViewModel> create(modelClass: Class<T>): T { + @Suppress("UNCHECKED_CAST") + return TransactionViewModel(application.container.transactionRepository, userNim) as T + } +} diff --git a/app/src/main/java/com/example/bondoman/dataaccess/TransactionDao.kt b/app/src/main/java/com/example/bondoman/dataaccess/TransactionDao.kt deleted file mode 100644 index 4ab0f95b03a878b703f4097a644d7dbde171b49d..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/dataaccess/TransactionDao.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.bondoman.dataaccess - -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.Query -import androidx.room.Update -import com.example.bondoman.models.Transaction - -@Dao -interface TransactionDao { - @Query("SELECT * FROM transactions WHERE owner = :owner ORDER BY date DESC") - suspend fun getAll(owner: String): List<Transaction> - - @Query("SELECT * FROM transactions WHERE id = :id") - suspend fun getById(id: Long): Transaction? - - @Insert - suspend fun insert(vararg transaction: Transaction) - - @Update - suspend fun update(vararg transaction: Transaction) - - @Delete - suspend fun delete(vararg transaction: Transaction) -} diff --git a/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt b/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt deleted file mode 100644 index 54ea6fb76e0599c7280bb6dd1ad0f26b9f7679e4..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.bondoman.repositories - -import com.example.bondoman.dataaccess.TransactionDao -import com.example.bondoman.models.Transaction - -class TransactionRepository(private val transactionDao: TransactionDao) { - suspend fun getAll(owner: String) = transactionDao.getAll(owner) - - suspend fun getById(id: Long) = transactionDao.getById(id) - - suspend fun insert(vararg transaction: Transaction) = transactionDao.insert(*transaction) - - suspend fun update(vararg transaction: Transaction) = transactionDao.update(*transaction) - - suspend fun delete(vararg transaction: Transaction) = transactionDao.delete(*transaction) -} diff --git a/app/src/main/java/com/example/bondoman/activities/LoginActivity.kt b/app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt similarity index 95% rename from app/src/main/java/com/example/bondoman/activities/LoginActivity.kt rename to app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt index 7feae77a40b079290bfd877161cca5eaf2dd3549..50c81c7ec02312f436d734471eb7ec6cba911c90 100644 --- a/app/src/main/java/com/example/bondoman/activities/LoginActivity.kt +++ b/app/src/main/java/com/example/bondoman/views/activities/LoginActivity.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.activities +package com.example.bondoman.views.activities import android.content.Intent import android.os.Bundle diff --git a/app/src/main/java/com/example/bondoman/activities/MainActivity.kt b/app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt similarity index 84% rename from app/src/main/java/com/example/bondoman/activities/MainActivity.kt rename to app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt index 73b6a1044e41d60f35c40635606b7c992fb183fb..137f9867e12c54b700fe0152593ed74e633863d7 100644 --- a/app/src/main/java/com/example/bondoman/activities/MainActivity.kt +++ b/app/src/main/java/com/example/bondoman/views/activities/MainActivity.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.activities +package com.example.bondoman.views.activities import android.os.Bundle import android.view.View @@ -9,10 +9,14 @@ import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.setupWithNavController +import com.example.bondoman.MainApplication import com.example.bondoman.R -import com.example.bondoman.utils.interfaces.ParentActivityService +import com.example.bondoman.data.viewmodels.transaction.TransactionViewModel +import com.example.bondoman.data.viewmodels.transaction.TransactionViewModelFactory +import com.example.bondoman.views.utils.interfaces.ParentActivityService import com.google.android.material.bottomnavigation.BottomNavigationView import eightbitlab.com.blurview.BlurView @@ -25,6 +29,8 @@ class MainActivity : AppCompatActivity(), ParentActivityService { private var currentFragmentId: Int? = null + private lateinit var transactionViewModel: TransactionViewModel + private fun setCurrentFragment(fragment: Fragment) { supportFragmentManager.beginTransaction().apply { replace(R.id.fragment_container, fragment) @@ -94,8 +100,14 @@ class MainActivity : AppCompatActivity(), ParentActivityService { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + // initialize viewmodel + val factory = TransactionViewModelFactory(application as MainApplication, "13521148") + transactionViewModel = ViewModelProvider(this, factory)[TransactionViewModel::class.java] + + // initialize fragment id tracking currentFragmentId = null + // initialize components mainLayout = findViewById(R.id.main) backButton = mainLayout.findViewById(R.id.back_button) headerText = mainLayout.findViewById(R.id.header_text) diff --git a/app/src/main/java/com/example/bondoman/adapters/TransactionListAdapter.kt b/app/src/main/java/com/example/bondoman/views/adapters/TransactionListAdapter.kt similarity index 80% rename from app/src/main/java/com/example/bondoman/adapters/TransactionListAdapter.kt rename to app/src/main/java/com/example/bondoman/views/adapters/TransactionListAdapter.kt index 91d53d218fe53adbd4cbafb401e638633dc98c39..1c50eab373a6c96792155eea7203e1f782a958ca 100644 --- a/app/src/main/java/com/example/bondoman/adapters/TransactionListAdapter.kt +++ b/app/src/main/java/com/example/bondoman/views/adapters/TransactionListAdapter.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.adapters +package com.example.bondoman.views.adapters import android.view.LayoutInflater import android.view.View @@ -8,9 +8,12 @@ import android.widget.TextView import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.example.bondoman.R -import com.example.bondoman.utils.interfaces.TransactionClickListener +import com.example.bondoman.views.utils.interfaces.TransactionClickListener -class TransactionListAdapter(private val dataList: List<Int>, private val clickListener: TransactionClickListener) : +class TransactionListAdapter( + private val dataList: List<Int>, + private val clickListener: TransactionClickListener +) : RecyclerView.Adapter<TransactionListAdapter.ViewHolder>() { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val iconImageView: ImageView = itemView.findViewById(R.id.transaction_icon_image) @@ -37,7 +40,12 @@ class TransactionListAdapter(private val dataList: List<Int>, private val clickL ) { val item = dataList[position] holder.iconImageView.setImageResource(R.drawable.ic_coins) - holder.iconImageView.setBackgroundColor(ContextCompat.getColor(holder.itemView.context, R.color.teal_200)) + holder.iconImageView.setBackgroundColor( + ContextCompat.getColor( + holder.itemView.context, + R.color.teal_200 + ) + ) holder.dateTextView.text = "30 Mar 2026" holder.amountTextView.text = "-Rp9.000.000.000.000.000" holder.titleTextView.text = "Ethereum to the earth’s core" diff --git a/app/src/main/java/com/example/bondoman/views/components/DateInputComponent.kt b/app/src/main/java/com/example/bondoman/views/components/DateInputComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..e223e53e1f6e2389604720f98dc960e171941cec --- /dev/null +++ b/app/src/main/java/com/example/bondoman/views/components/DateInputComponent.kt @@ -0,0 +1,60 @@ +package com.example.bondoman.views.components + +import android.content.Context +import android.util.AttributeSet +import android.widget.LinearLayout +import androidx.appcompat.app.AppCompatActivity +import com.example.bondoman.R +import com.example.bondoman.views.fragments.DatePickerFragment +import com.google.android.material.button.MaterialButton +import com.google.android.material.textview.MaterialTextView + +class DateInputComponent +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : LinearLayout(context, attrs, defStyleAttr) { + companion object { + const val FRAGMENT_TAG = "datePicker" + } + + private val labelTextView: MaterialTextView + private val button: MaterialButton + private var onDatePickedListener: ((year: Int, month: Int, day: Int) -> Unit)? = null + + init { + inflate(context, R.layout.component_date_input, this) + + labelTextView = findViewById(R.id.date_input_component_label) + button = findViewById(R.id.date_input_button) + + // Load attributes + val attributes = context.obtainStyledAttributes(attrs, R.styleable.DateInputComponent) + val labelText = attributes.getString(R.styleable.DateInputComponent_dateInputLabel) ?: "" + attributes.recycle() + + // Set label text and hint + labelTextView.text = labelText + + if (context is AppCompatActivity) { + button.setOnClickListener { + val datePickerFragment = DatePickerFragment() + datePickerFragment.setOnDatePicked { year, month, day -> + setText("$year/${month + 1}/$day") + onDatePickedListener?.invoke(year, month, day) + } + datePickerFragment.show(context.supportFragmentManager, FRAGMENT_TAG) + } + } + } + + fun setText(text: String) { + button.text = text + } + + fun setOnDatePicked(listener: (year: Int, month: Int, day: Int) -> Unit) { + onDatePickedListener = listener + } +} diff --git a/app/src/main/java/com/example/bondoman/views/components/DialogComponent.kt b/app/src/main/java/com/example/bondoman/views/components/DialogComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..e563fbfb77dc9648cda13557cd6bb48f18cc4be0 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/views/components/DialogComponent.kt @@ -0,0 +1,127 @@ +package com.example.bondoman.views.components + +import android.content.Context +import android.util.AttributeSet +import android.widget.LinearLayout +import androidx.core.content.ContextCompat +import com.example.bondoman.R +import com.google.android.material.button.MaterialButton +import com.google.android.material.textview.MaterialTextView + +class DialogComponent +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : LinearLayout(context, attrs, defStyleAttr) { + companion object { + enum class ButtonType(val value: Int) { + POSITIVE_BUTTON(1), + NEUTRAL_BUTTON(0), + NEGATIVE_BUTTON(-1), + } + + val buttonTypeMap = + mapOf( + 1 to ButtonType.POSITIVE_BUTTON, + 0 to ButtonType.NEUTRAL_BUTTON, + -1 to ButtonType.NEGATIVE_BUTTON, + ) + + val buttonBackgroundColorMap = + mapOf( + ButtonType.POSITIVE_BUTTON to R.color.teal_200, + ButtonType.NEUTRAL_BUTTON to R.color.zinc_600, + ButtonType.NEGATIVE_BUTTON to R.color.rose_200, + ) + + val buttonTextColorMap = + mapOf( + ButtonType.POSITIVE_BUTTON to R.color.zinc_900, + ButtonType.NEUTRAL_BUTTON to R.color.zinc_300, + ButtonType.NEGATIVE_BUTTON to R.color.zinc_900, + ) + } + + private val textView: MaterialTextView + private val firstButton: MaterialButton + private val secondButton: MaterialButton + + init { + inflate(context, R.layout.component_dialog, this) + + textView = findViewById(R.id.dialog_text) + firstButton = findViewById(R.id.dialog_first_button) + secondButton = findViewById(R.id.dialog_second_button) + + // Load attributes + val attributes = context.obtainStyledAttributes(attrs, R.styleable.DialogComponent) + val text = attributes.getString(R.styleable.DialogComponent_dialogText) ?: "" + val firstButtonTypeOrdinal = attributes.getInt( + R.styleable.DialogComponent_dialogFirstButtonType, + ButtonType.NEUTRAL_BUTTON.ordinal + ) + val secondButtonTypeOrdinal = attributes.getInt( + R.styleable.DialogComponent_dialogSecondButtonType, + ButtonType.POSITIVE_BUTTON.ordinal + ) + val firstButtonText = + attributes.getString(R.styleable.DialogComponent_firstButtonText) ?: "" + val secondButtonText = + attributes.getString(R.styleable.DialogComponent_secondButtonText) ?: "" + + attributes.recycle() + + // Set label text + setText(text) + + // Set button types + setFirstButtonType(buttonTypeMap[firstButtonTypeOrdinal]!!) + setSecondButtonType(buttonTypeMap[secondButtonTypeOrdinal]!!) + + // set button text + setFirstButtonText(firstButtonText) + setSecondButtonText(secondButtonText) + } + + fun setText(text: String) { + textView.text = text + } + + fun setFirstButtonText(text: String) { + firstButton.text = text + } + + fun setSecondButtonText(text: String) { + secondButton.text = text + } + + fun setFirstButtonOnClickListener(listener: () -> Unit) { + firstButton.setOnClickListener { listener() } + } + + fun setSecondButtonOnClickListener(listener: () -> Unit) { + secondButton.setOnClickListener { listener() } + } + + fun setFirstButtonType(type: ButtonType) { + firstButton.setBackgroundColor( + ContextCompat.getColor( + context, + buttonBackgroundColorMap[type]!! + ) + ) + firstButton.setTextColor(ContextCompat.getColor(context, buttonTextColorMap[type]!!)) + } + + fun setSecondButtonType(type: ButtonType) { + secondButton.setBackgroundColor( + ContextCompat.getColor( + context, + buttonBackgroundColorMap[type]!! + ) + ) + secondButton.setTextColor(ContextCompat.getColor(context, buttonTextColorMap[type]!!)) + } +} diff --git a/app/src/main/java/com/example/bondoman/views/components/SettingButtonComponent.kt b/app/src/main/java/com/example/bondoman/views/components/SettingButtonComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..a7fe74b605ebd4212d1d36bc676ff7744ba94317 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/views/components/SettingButtonComponent.kt @@ -0,0 +1,66 @@ +package com.example.bondoman.views.components + +import android.animation.ArgbEvaluator +import android.animation.ObjectAnimator +import android.content.Context +import android.util.AttributeSet +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.constraintlayout.widget.ConstraintLayout +import com.example.bondoman.R +import com.google.android.material.textview.MaterialTextView + +class SettingButtonComponent +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : LinearLayout(context, attrs, defStyleAttr) { + private val layout: ConstraintLayout + private val icon: ImageView + private val title: MaterialTextView + private val subtitle: MaterialTextView + + init { + inflate(context, R.layout.component_setting_button, this) + + layout = findViewById(R.id.setting_button_layout) + icon = findViewById(R.id.setting_button_icon) + title = findViewById(R.id.setting_button_title) + subtitle = findViewById(R.id.setting_button_subtitle) + + // Load attributes + val attributes = context.obtainStyledAttributes(attrs, R.styleable.SettingButtonComponent) + val icon = attributes.getDrawable(R.styleable.SettingButtonComponent_settingButtonIcon) + val title = + attributes.getString(R.styleable.SettingButtonComponent_settingButtonTitle) ?: "" + val subtitle = + attributes.getString(R.styleable.SettingButtonComponent_settingButtonSubtitle) ?: "" + + // Set values + this.icon.setImageDrawable(icon) + this.title.text = title + this.subtitle.text = subtitle + + // On Click Listener + layout.setOnClickListener { + // Change the background color of the layout + layout.setBackgroundColor(resources.getColor(R.color.button_pressed_color, null)) + + // Animate the background color to slowly fade back to the original color for 1s + val fadeBackAnimator = + ObjectAnimator.ofArgb( + layout, + "backgroundColor", + resources.getColor(R.color.button_pressed_color, null), + resources.getColor(R.color.button_default_color, null), + ) + fadeBackAnimator.duration = 500 // 1 second + fadeBackAnimator.setEvaluator(ArgbEvaluator()) + fadeBackAnimator.start() + } + + attributes.recycle() + } +} diff --git a/app/src/main/java/com/example/bondoman/views/components/TextInputComponent.kt b/app/src/main/java/com/example/bondoman/views/components/TextInputComponent.kt new file mode 100644 index 0000000000000000000000000000000000000000..339cd337b1683a1443334306219f6c5636296446 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/views/components/TextInputComponent.kt @@ -0,0 +1,100 @@ +package com.example.bondoman.views.components + +import android.content.Context +import android.text.Editable +import android.text.TextWatcher +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.example.bondoman.R +import com.google.android.material.textfield.TextInputEditText +import com.google.android.material.textview.MaterialTextView + +class TextInputComponent +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : LinearLayout(context, attrs, defStyleAttr) { + private val labelTextView: MaterialTextView + private val inputEditText: TextInputEditText + private var beforeTextChangedListener: ((text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? = + null + private var onTextChangedListener: ((text: CharSequence?, start: Int, before: Int, count: Int) -> Unit)? = + null + private var afterTextChangedListener: ((text: Editable?) -> Unit)? = null + + init { + LayoutInflater.from(context).inflate(R.layout.component_text_input, this, true) + + labelTextView = findViewById(R.id.text_input_component_label) + inputEditText = findViewById(R.id.text_input_component_field) + + // Load attributes + val attributes = context.obtainStyledAttributes(attrs, R.styleable.TextInputComponent) + val labelText = attributes.getString(R.styleable.TextInputComponent_textInputLabel) ?: "" + val hint = attributes.getString(R.styleable.TextInputComponent_textInputHint) ?: "" + attributes.recycle() + + // Set label text and hint + labelTextView.text = labelText + inputEditText.hint = hint + + // Set up text watcher + inputEditText.addTextChangedListener( + object : TextWatcher { + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int, + ) { + beforeTextChangedListener?.invoke(s, start, count, after) + } + + override fun onTextChanged( + s: CharSequence?, + start: Int, + before: Int, + count: Int, + ) { + onTextChangedListener?.invoke(s, start, before, count) + } + + override fun afterTextChanged(s: Editable?) { + afterTextChangedListener?.invoke(s) + } + }, + ) + } + + fun setText(text: String) { + inputEditText.setText(text) + } + + fun getText(): String { + return inputEditText.text.toString() + } + + fun disable() { + inputEditText.isEnabled = false + } + + fun enable() { + inputEditText.isEnabled = true + } + + // Setter methods for text change listeners + fun setBeforeTextChangedListener(listener: (text: CharSequence?, start: Int, count: Int, after: Int) -> Unit) { + beforeTextChangedListener = listener + } + + fun setOnTextChangedListener(listener: (text: CharSequence?, start: Int, before: Int, count: Int) -> Unit) { + onTextChangedListener = listener + } + + fun setAfterTextChangedListener(listener: (text: Editable?) -> Unit) { + afterTextChangedListener = listener + } +} diff --git a/app/src/main/java/com/example/bondoman/decorators/DividerItemDecorator.kt b/app/src/main/java/com/example/bondoman/views/decorators/DividerItemDecorator.kt similarity index 94% rename from app/src/main/java/com/example/bondoman/decorators/DividerItemDecorator.kt rename to app/src/main/java/com/example/bondoman/views/decorators/DividerItemDecorator.kt index 6a9b9e08346b821a6d65dcbb784106ea8f029419..a925349c5c55136fc83c0c817830b5804d928fe7 100644 --- a/app/src/main/java/com/example/bondoman/decorators/DividerItemDecorator.kt +++ b/app/src/main/java/com/example/bondoman/views/decorators/DividerItemDecorator.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.decorators +package com.example.bondoman.views.decorators import android.graphics.Canvas import android.graphics.drawable.Drawable diff --git a/app/src/main/java/com/example/bondoman/fragments/DatePickerFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/DatePickerFragment.kt similarity index 90% rename from app/src/main/java/com/example/bondoman/fragments/DatePickerFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/DatePickerFragment.kt index 4c647e0af30a8a04913d0dc1575f439656ceb48e..c07f92341a74f8bf411f689dd707e662f695d938 100644 --- a/app/src/main/java/com/example/bondoman/fragments/DatePickerFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/DatePickerFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.app.DatePickerDialog import android.app.Dialog @@ -32,7 +32,12 @@ class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener negativeButton.setTextColor(ContextCompat.getColor(requireContext(), R.color.zinc_300)) // change background - dialog.datePicker.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.bg_main)) + dialog.datePicker.setBackgroundColor( + ContextCompat.getColor( + requireContext(), + R.color.bg_main + ) + ) return dialog } diff --git a/app/src/main/java/com/example/bondoman/fragments/GraphFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/GraphFragment.kt similarity index 96% rename from app/src/main/java/com/example/bondoman/fragments/GraphFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/GraphFragment.kt index 3d92ebcbe768803b7aefdf9e0bd5a9ba7c6a73c4..acb9f6d867c6d0b22d50cfeed3e4cf7e7418cc93 100644 --- a/app/src/main/java/com/example/bondoman/fragments/GraphFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/GraphFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater @@ -117,10 +117,6 @@ class GraphFragment : Fragment() { pieChart.invalidate() } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, diff --git a/app/src/main/java/com/example/bondoman/fragments/ScanReceiptFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/ScanReceiptFragment.kt similarity index 95% rename from app/src/main/java/com/example/bondoman/fragments/ScanReceiptFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/ScanReceiptFragment.kt index 7f5898e5730cc927f03c4ba59738bfa0ce38e979..327053b6c52c508b228bacb6704c10bbd45a569f 100644 --- a/app/src/main/java/com/example/bondoman/fragments/ScanReceiptFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/ScanReceiptFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.content.pm.PackageManager import android.os.Bundle @@ -42,10 +42,6 @@ class ScanReceiptFragment : Fragment() { } } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -108,7 +104,7 @@ class ScanReceiptFragment : Fragment() { } private fun allPermissionsGranted() = - Companion.REQUIRED_PERMISSIONS.all { + REQUIRED_PERMISSIONS.all { ContextCompat.checkSelfPermission( requireActivity().baseContext, it, diff --git a/app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt similarity index 97% rename from app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt index 124cd00dd1e73d9c91da3aeca35e0bc4e14fe19a..81729bfb67239922f5b520dabafa3ef1b979fdc5 100644 --- a/app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/SettingsFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/com/example/bondoman/fragments/TransactionAddFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/TransactionAddFragment.kt similarity index 80% rename from app/src/main/java/com/example/bondoman/fragments/TransactionAddFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/TransactionAddFragment.kt index bba929ab409627f61e2ac9781c0fae6d288ccea6..66b8f91bbe01a86f9855975401476c3a890036f3 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TransactionAddFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/TransactionAddFragment.kt @@ -1,11 +1,11 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.example.bondoman.R -import com.example.bondoman.components.TextInputComponent +import com.example.bondoman.views.components.TextInputComponent class TransactionAddFragment : TransactionFormFragment() { companion object { @@ -21,10 +21,6 @@ class TransactionAddFragment : TransactionFormFragment() { return HEADER_TEXT } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, diff --git a/app/src/main/java/com/example/bondoman/fragments/TransactionFormFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/TransactionFormFragment.kt similarity index 78% rename from app/src/main/java/com/example/bondoman/fragments/TransactionFormFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/TransactionFormFragment.kt index befaf1192bd3d502ed63ffcb22bfe1b81531ace6..7d2d6ef72e04bb166f7e827074ce350705a17221 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TransactionFormFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/TransactionFormFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater @@ -8,8 +8,8 @@ import android.widget.ArrayAdapter import android.widget.AutoCompleteTextView import androidx.fragment.app.Fragment import com.example.bondoman.R -import com.example.bondoman.utils.interfaces.ParentActivityService -import com.example.bondoman.utils.interfaces.SecondaryFragment +import com.example.bondoman.views.utils.interfaces.ParentActivityService +import com.example.bondoman.views.utils.interfaces.SecondaryFragment abstract class TransactionFormFragment : Fragment(), SecondaryFragment { private lateinit var parentActivityService: ParentActivityService @@ -29,9 +29,11 @@ abstract class TransactionFormFragment : Fragment(), SecondaryFragment { val view = inflater.inflate(R.layout.fragment_transaction_form, container, false) // set category dropdown adapter - val autoCompleteTextView = view.findViewById<AutoCompleteTextView>(R.id.transaction_form_auto_complete) + val autoCompleteTextView = + view.findViewById<AutoCompleteTextView>(R.id.transaction_form_auto_complete) val categories = resources.getStringArray(R.array.transaction_categories) - val dropdownAdapter = ArrayAdapter(requireContext(), R.layout.component_dropdown_item, categories) + val dropdownAdapter = + ArrayAdapter(requireContext(), R.layout.component_dropdown_item, categories) autoCompleteTextView.setAdapter(dropdownAdapter) autoCompleteTextView.onFocusChangeListener = diff --git a/app/src/main/java/com/example/bondoman/fragments/TransactionListFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/TransactionListFragment.kt similarity index 92% rename from app/src/main/java/com/example/bondoman/fragments/TransactionListFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/TransactionListFragment.kt index 1da578b57aafccc713197ab1d996bddcca5836e1..845f628596ee48ccdf45efa07f7a752d09c58dd8 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TransactionListFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/TransactionListFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater @@ -12,11 +12,11 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ItemDecoration import com.example.bondoman.R -import com.example.bondoman.adapters.TransactionListAdapter -import com.example.bondoman.components.DialogComponent -import com.example.bondoman.decorators.DividerItemDecorator -import com.example.bondoman.utils.interfaces.ParentActivityService -import com.example.bondoman.utils.interfaces.TransactionClickListener +import com.example.bondoman.views.adapters.TransactionListAdapter +import com.example.bondoman.views.components.DialogComponent +import com.example.bondoman.views.decorators.DividerItemDecorator +import com.example.bondoman.views.utils.interfaces.ParentActivityService +import com.example.bondoman.views.utils.interfaces.TransactionClickListener import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback import eightbitlab.com.blurview.BlurView diff --git a/app/src/main/java/com/example/bondoman/fragments/TransactionUpdateFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/TransactionUpdateFragment.kt similarity index 77% rename from app/src/main/java/com/example/bondoman/fragments/TransactionUpdateFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/TransactionUpdateFragment.kt index 4e9d278e028828b96db55ee331fffb89568cd3ff..11830c8386e643dcb814c4cf19d25686be3e6343 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TransactionUpdateFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/TransactionUpdateFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater @@ -6,8 +6,8 @@ import android.view.View import android.view.ViewGroup import android.widget.AutoCompleteTextView import com.example.bondoman.R -import com.example.bondoman.components.TextInputComponent -import com.example.bondoman.utils.interfaces.ParentActivityService +import com.example.bondoman.views.components.TextInputComponent +import com.example.bondoman.views.utils.interfaces.ParentActivityService import com.google.android.material.textfield.TextInputLayout class TransactionUpdateFragment : TransactionFormFragment() { @@ -41,11 +41,13 @@ class TransactionUpdateFragment : TransactionFormFragment() { val view = super.onCreateView(inflater, container, savedInstanceState)!! // configure category dropdown - val textInputLayout = view.findViewById<TextInputLayout>(R.id.transaction_form_category_dropdown) + val textInputLayout = + view.findViewById<TextInputLayout>(R.id.transaction_form_category_dropdown) textInputLayout.hint = getString(R.string.hint_category) textInputLayout.endIconDrawable = null - val autoCompleteTextView = textInputLayout.findViewById<AutoCompleteTextView>(R.id.transaction_form_auto_complete) + val autoCompleteTextView = + textInputLayout.findViewById<AutoCompleteTextView>(R.id.transaction_form_auto_complete) autoCompleteTextView.dropDownHeight = 0 // configure date input diff --git a/app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/TwibbonFragment.kt similarity index 98% rename from app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/TwibbonFragment.kt index 980a936ea2eae3389644a529b2ece5c2bb6d3054..3414479cfaf178714f641c5b55d41c3864bb8eed 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/TwibbonFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.content.ContentValues import android.content.pm.PackageManager @@ -25,8 +25,8 @@ import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController +import com.example.bondoman.data.models.ParcelableBitmap import com.example.bondoman.databinding.FragmentTwibbonBinding -import com.example.bondoman.models.ParcelableBitmap import java.io.OutputStream class TwibbonFragment : Fragment() { diff --git a/app/src/main/java/com/example/bondoman/fragments/TwibbonPreviewFragment.kt b/app/src/main/java/com/example/bondoman/views/fragments/TwibbonPreviewFragment.kt similarity index 88% rename from app/src/main/java/com/example/bondoman/fragments/TwibbonPreviewFragment.kt rename to app/src/main/java/com/example/bondoman/views/fragments/TwibbonPreviewFragment.kt index b5eb07d63809c0bd2d86b0cb488011dfa404054d..1e51a4e58e5cfff8ee83f10b1e04b72c994d8a58 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TwibbonPreviewFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/fragments/TwibbonPreviewFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.fragments +package com.example.bondoman.views.fragments import android.os.Bundle import android.view.LayoutInflater @@ -13,10 +13,6 @@ import com.example.bondoman.databinding.FragmentTwibbonPreviewBinding class TwibbonPreviewFragment : Fragment() { private val args by navArgs<TwibbonPreviewFragmentArgs>() - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, diff --git a/app/src/main/java/com/example/bondoman/utils/interfaces/ParentActivityService.kt b/app/src/main/java/com/example/bondoman/views/utils/interfaces/ParentActivityService.kt similarity index 90% rename from app/src/main/java/com/example/bondoman/utils/interfaces/ParentActivityService.kt rename to app/src/main/java/com/example/bondoman/views/utils/interfaces/ParentActivityService.kt index f1cf67befe7ac9c316c8cc9d1bbf5603a27a187c..70162e7888cb4fc93b0154c8c54c7ed17aa95b37 100644 --- a/app/src/main/java/com/example/bondoman/utils/interfaces/ParentActivityService.kt +++ b/app/src/main/java/com/example/bondoman/views/utils/interfaces/ParentActivityService.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.utils.interfaces +package com.example.bondoman.views.utils.interfaces import android.view.View import android.view.ViewGroup.LayoutParams diff --git a/app/src/main/java/com/example/bondoman/utils/interfaces/SecondaryFragment.kt b/app/src/main/java/com/example/bondoman/views/utils/interfaces/SecondaryFragment.kt similarity index 54% rename from app/src/main/java/com/example/bondoman/utils/interfaces/SecondaryFragment.kt rename to app/src/main/java/com/example/bondoman/views/utils/interfaces/SecondaryFragment.kt index 404103727d5569aafd8989a18ce5664ff2922e3c..c8b77329769bce19094a33f11e7b81be5ad7dedd 100644 --- a/app/src/main/java/com/example/bondoman/utils/interfaces/SecondaryFragment.kt +++ b/app/src/main/java/com/example/bondoman/views/utils/interfaces/SecondaryFragment.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.utils.interfaces +package com.example.bondoman.views.utils.interfaces interface SecondaryFragment { fun getHeaderText(): String diff --git a/app/src/main/java/com/example/bondoman/utils/interfaces/TransactionClickListener.kt b/app/src/main/java/com/example/bondoman/views/utils/interfaces/TransactionClickListener.kt similarity index 56% rename from app/src/main/java/com/example/bondoman/utils/interfaces/TransactionClickListener.kt rename to app/src/main/java/com/example/bondoman/views/utils/interfaces/TransactionClickListener.kt index f11efa5f345cd9e97ef41d63080cab3f5b497812..2fa6dc13d9c1f53bc2c9ded5203622dc8aa52d3e 100644 --- a/app/src/main/java/com/example/bondoman/utils/interfaces/TransactionClickListener.kt +++ b/app/src/main/java/com/example/bondoman/views/utils/interfaces/TransactionClickListener.kt @@ -1,4 +1,4 @@ -package com.example.bondoman.utils.interfaces +package com.example.bondoman.views.utils.interfaces interface TransactionClickListener { fun onItemClick(item: Int) diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 988dd65d4b52796585aedfc44b3ee04a340f6fb7..f9097bfa1027d483ee30aaea5876ab83d4d170db 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -1,13 +1,12 @@ <?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:id="@+id/login_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/bg_main" - tools:context=".activities.LoginActivity"> + tools:context=".views.activities.LoginActivity"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" @@ -47,7 +46,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:passwordToggleEnabled="true" > + app:passwordToggleEnabled="true"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/password_text_input" diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a862a8fc34f9324e33b80c64b2e45d732132f533..9d643d617cc56076fc61161834b60e9404572743 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,7 +6,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/bg_main" - tools:context=".activities.MainActivity"> + tools:context=".views.activities.MainActivity"> <ImageButton android:id="@+id/back_button" @@ -77,9 +77,7 @@ android:id="@+id/dialog_parent" android:layout_width="match_parent" android:layout_height="match_parent" - app:blurOverlayColor="@color/blur"> - - </eightbitlab.com.blurview.BlurView> + app:blurOverlayColor="@color/blur" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/main_guideline1" diff --git a/app/src/main/res/layout/component_delete_transaction_dialog.xml b/app/src/main/res/layout/component_delete_transaction_dialog.xml index 825f3f4e3c3792a81c6883520188d32e23c901fb..efd3e8c365092e7f78e5e04d6899b88f4daa38aa 100644 --- a/app/src/main/res/layout/component_delete_transaction_dialog.xml +++ b/app/src/main/res/layout/component_delete_transaction_dialog.xml @@ -1,12 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> -<com.example.bondoman.components.DialogComponent - xmlns:android="http://schemas.android.com/apk/res/android" +<com.example.bondoman.views.components.DialogComponent xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" + app:dialogFirstButtonType="neutral" + app:dialogSecondButtonType="negative" app:dialogText="@string/text_delete_transaction_dialog" app:firstButtonText="@string/text_first_button_delete_transaction_dialog" - app:secondButtonText="@string/text_second_button_delete_transaction_dialog" - app:dialogFirstButtonType="neutral" - app:dialogSecondButtonType="negative"> -</com.example.bondoman.components.DialogComponent> + app:secondButtonText="@string/text_second_button_delete_transaction_dialog"></com.example.bondoman.views.components.DialogComponent> diff --git a/app/src/main/res/layout/fragment_graph.xml b/app/src/main/res/layout/fragment_graph.xml index 664324b67e00c342ef4c76a734467fd7b3868353..05f24c55b0d326da90711fb382cedba706cb7a38 100644 --- a/app/src/main/res/layout/fragment_graph.xml +++ b/app/src/main/res/layout/fragment_graph.xml @@ -4,132 +4,147 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> + <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/bg_main" android:padding="20dp" - tools:context=".fragments.GraphFragment"> - <com.example.bondoman.components.DateInputComponent + tools:context=".views.fragments.GraphFragment"> + + <com.example.bondoman.views.components.DateInputComponent android:id="@+id/graph_date_begin_input" - android:layout_height="wrap_content" android:layout_width="0dp" + android:layout_height="wrap_content" app:dateInputLabel="@string/text_date_begin_label" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/graph_guideline_1" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toLeftOf="@id/graph_minus_icon"/> + app:layout_constraintRight_toLeftOf="@id/graph_minus_icon" + app:layout_constraintTop_toTopOf="parent" /> + <ImageView android:id="@+id/graph_minus_icon" android:layout_width="24dp" android:layout_height="24dp" android:layout_marginHorizontal="10dp" - android:src="@drawable/ic_minus" android:contentDescription="@string/desc_separator_icon" - app:tint="@color/zinc_300" - app:layout_constraintTop_toTopOf="parent" + android:src="@drawable/ic_minus" app:layout_constraintBottom_toTopOf="@id/graph_guideline_1" app:layout_constraintLeft_toRightOf="@id/graph_date_begin_input" - app:layout_constraintRight_toLeftOf="@id/graph_end_begin_input"/> - <com.example.bondoman.components.DateInputComponent + app:layout_constraintRight_toLeftOf="@id/graph_end_begin_input" + app:layout_constraintTop_toTopOf="parent" + app:tint="@color/zinc_300" /> + + <com.example.bondoman.views.components.DateInputComponent android:id="@+id/graph_end_begin_input" - android:layout_height="wrap_content" android:layout_width="0dp" + android:layout_height="wrap_content" app:dateInputLabel="@string/text_date_end_label" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/graph_guideline_1" app:layout_constraintLeft_toRightOf="@id/graph_minus_icon" - app:layout_constraintRight_toRightOf="parent"/> + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + <com.github.mikephil.charting.charts.PieChart android:id="@+id/graph_pie_chart" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginVertical="50dp" + app:layout_constraintBottom_toTopOf="@id/graph_guideline_3" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toBottomOf="@id/graph_guideline_2" - app:layout_constraintBottom_toTopOf="@id/graph_guideline_3"/> + app:layout_constraintTop_toBottomOf="@id/graph_guideline_2" /> + <TextView - android:textAppearance="@style/TextAppearance.TransactionDetail.Category" - android:theme="@style/incomeCategoryBackground" android:layout_width="wrap_content" android:layout_height="19dp" + android:background="@drawable/bg_full_border" + android:gravity="center" android:paddingHorizontal="6dp" android:paddingVertical="2dp" android:text="@string/text_income_transaction_category" - android:gravity="center" - android:background="@drawable/bg_full_border" + android:textAppearance="@style/TextAppearance.TransactionDetail.Category" + android:theme="@style/incomeCategoryBackground" + app:layout_constraintBottom_toTopOf="@id/graph_guideline_4" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintTop_toBottomOf="@id/graph_guideline_3" - app:layout_constraintBottom_toTopOf="@id/graph_guideline_4"/> + app:layout_constraintTop_toBottomOf="@id/graph_guideline_3" /> + <TextView - android:textAppearance="@style/TextAppearance.Graph.Amount" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="@string/dummy_transaction_amount" android:ellipsize="end" android:maxLines="1" + android:text="@string/dummy_transaction_amount" android:textAlignment="viewEnd" + android:textAppearance="@style/TextAppearance.Graph.Amount" + app:layout_constraintBottom_toTopOf="@id/graph_guideline_4" app:layout_constraintLeft_toRightOf="@id/graph_guideline_6" app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toBottomOf="@id/graph_guideline_3" - app:layout_constraintBottom_toTopOf="@id/graph_guideline_4"/> + app:layout_constraintTop_toBottomOf="@id/graph_guideline_3" /> + <TextView - android:textAppearance="@style/TextAppearance.TransactionDetail.Category" - android:theme="@style/outcomeCategoryBackground" android:layout_width="wrap_content" android:layout_height="19dp" + android:background="@drawable/bg_full_border" + android:gravity="center" android:paddingHorizontal="6dp" android:paddingVertical="2dp" android:text="@string/text_outcome_transaction_category" - android:gravity="center" - android:background="@drawable/bg_full_border" + android:textAppearance="@style/TextAppearance.TransactionDetail.Category" + android:theme="@style/outcomeCategoryBackground" + app:layout_constraintBottom_toTopOf="@id/graph_guideline_5" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintTop_toBottomOf="@id/graph_guideline_4" - app:layout_constraintBottom_toTopOf="@id/graph_guideline_5"/> + app:layout_constraintTop_toBottomOf="@id/graph_guideline_4" /> + <TextView - android:textAppearance="@style/TextAppearance.Graph.Amount" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="@string/dummy_transaction_amount" android:ellipsize="end" android:maxLines="1" + android:text="@string/dummy_transaction_amount" android:textAlignment="viewEnd" + android:textAppearance="@style/TextAppearance.Graph.Amount" + app:layout_constraintBottom_toTopOf="@id/graph_guideline_5" app:layout_constraintLeft_toRightOf="@id/graph_guideline_6" app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toBottomOf="@id/graph_guideline_4" - app:layout_constraintBottom_toTopOf="@id/graph_guideline_5"/> + app:layout_constraintTop_toBottomOf="@id/graph_guideline_4" /> + <androidx.constraintlayout.widget.Guideline android:id="@+id/graph_guideline_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="80dp" /> + <androidx.constraintlayout.widget.Guideline android:id="@+id/graph_guideline_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="100dp" /> + <androidx.constraintlayout.widget.Guideline android:id="@+id/graph_guideline_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="430dp" /> + <androidx.constraintlayout.widget.Guideline android:id="@+id/graph_guideline_4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="489dp" /> + <androidx.constraintlayout.widget.Guideline android:id="@+id/graph_guideline_5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="548dp" /> + <androidx.constraintlayout.widget.Guideline android:id="@+id/graph_guideline_6" android:layout_width="wrap_content" diff --git a/app/src/main/res/layout/fragment_scan_receipt.xml b/app/src/main/res/layout/fragment_scan_receipt.xml index 2f454d0bcffb075e736940323f30203434801080..3bd5cd62eec46f09c5db2f4d219934ad41f40616 100644 --- a/app/src/main/res/layout/fragment_scan_receipt.xml +++ b/app/src/main/res/layout/fragment_scan_receipt.xml @@ -1,49 +1,49 @@ <?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" - xmlns:app="http://schemas.android.com/apk/res-auto" - tools:context=".fragments.ScanReceiptFragment" > + tools:context=".views.fragments.ScanReceiptFragment"> <androidx.camera.view.PreviewView android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHeight_percent="0.85" /> + app:layout_constraintHeight_percent="0.85" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> <ImageButton android:id="@+id/receipt_capture_button" - android:theme="@style/teal200RoundBackground" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/bg_full_border" - android:src="@drawable/ic_camera" android:contentDescription="@string/capture" android:elevation="2dp" - app:layout_constraintTop_toBottomOf="@id/camera_preview" + android:src="@drawable/ic_camera" + android:theme="@style/teal200RoundBackground" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/camera_preview" app:tint="@color/zinc_800" /> <ImageButton android:id="@+id/gallery_button" - android:theme="@style/transparentRoundBackground" android:layout_width="30dp" android:layout_height="30dp" - android:elevation="2dp" - android:src="@drawable/ic_library_photo" - android:background="@drawable/bg_full_border" android:layout_marginStart="20dp" - android:scaleType="fitCenter" + android:background="@drawable/bg_full_border" android:contentDescription="@string/gallery" + android:elevation="2dp" + android:scaleType="fitCenter" + android:src="@drawable/ic_library_photo" + android:theme="@style/transparentRoundBackground" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/camera_preview" - app:layout_constraintBottom_toBottomOf="parent" app:tint="@color/zinc_300" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 32fb251ec2352a2a2351a27d1d26f0d062def171..ade46d95ae936bf6b97053106330e0f1c14ad5da 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -5,56 +5,52 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - tools:context=".fragments.SettingsFragment"> + tools:context=".views.fragments.SettingsFragment"> - <com.example.bondoman.components.SettingButtonComponent + <com.example.bondoman.views.components.SettingButtonComponent android:id="@+id/export_report_button" android:layout_width="match_parent" android:layout_height="wrap_content" app:settingButtonIcon="@drawable/ic_file_export" - app:settingButtonTitle="Export report" - app:settingButtonSubtitle="Save an xlsx file containing your transaction report in your device"> - </com.example.bondoman.components.SettingButtonComponent> + app:settingButtonSubtitle="Save an xlsx file containing your transaction report in your device" + app:settingButtonTitle="Export report"></com.example.bondoman.views.components.SettingButtonComponent> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/zinc_700" /> - <com.example.bondoman.components.SettingButtonComponent + <com.example.bondoman.views.components.SettingButtonComponent android:id="@+id/send_report_button" android:layout_width="match_parent" android:layout_height="wrap_content" app:settingButtonIcon="@drawable/ic_send" app:settingButtonSubtitle="Send an xlsx file containing your transaction report to your email" - app:settingButtonTitle="Send report as a file"> - </com.example.bondoman.components.SettingButtonComponent> + app:settingButtonTitle="Send report as a file"></com.example.bondoman.views.components.SettingButtonComponent> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/zinc_700" /> - <com.example.bondoman.components.SettingButtonComponent + <com.example.bondoman.views.components.SettingButtonComponent android:id="@+id/randomize_transaction_button" android:layout_width="match_parent" android:layout_height="wrap_content" app:settingButtonIcon="@drawable/ic_arrows_shuffle" - app:settingButtonTitle="Randomize transaction" - app:settingButtonSubtitle="Send a broadcast to create transaction fragment and automatically filled the title and amount fields"> - </com.example.bondoman.components.SettingButtonComponent> + app:settingButtonSubtitle="Send a broadcast to create transaction fragment and automatically filled the title and amount fields" + app:settingButtonTitle="Randomize transaction"></com.example.bondoman.views.components.SettingButtonComponent> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/zinc_700" /> - <com.example.bondoman.components.SettingButtonComponent + <com.example.bondoman.views.components.SettingButtonComponent android:id="@+id/logout_button" android:layout_width="match_parent" android:layout_height="wrap_content" app:settingButtonIcon="@drawable/ic_logout" - app:settingButtonTitle="Logout" - app:settingButtonSubtitle="Logout from the application"> - </com.example.bondoman.components.SettingButtonComponent> + app:settingButtonSubtitle="Logout from the application" + app:settingButtonTitle="Logout"></com.example.bondoman.views.components.SettingButtonComponent> </LinearLayout> diff --git a/app/src/main/res/layout/fragment_transaction_form.xml b/app/src/main/res/layout/fragment_transaction_form.xml index 3ac3cf1eceb51c2eeee43764e56334f9df454d9f..54b16b8645e7806e11779edccdf0dc8d0d81b1d2 100644 --- a/app/src/main/res/layout/fragment_transaction_form.xml +++ b/app/src/main/res/layout/fragment_transaction_form.xml @@ -3,92 +3,101 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:padding="20dp" - android:orientation="vertical" android:divider="@drawable/shape_form_divider" + android:orientation="vertical" + android:padding="20dp" android:showDividers="middle"> + <com.google.android.material.textfield.TextInputLayout - style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu" android:id="@+id/transaction_form_category_dropdown" + style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu" android:layout_width="match_parent" android:layout_height="wrap_content" - android:theme="@style/transactionFormFieldBackground" android:background="@drawable/bg_full_border" - app:endIconDrawable="@drawable/ic_chevron_down" - app:hintTextColor="@color/teal_200" - app:cursorColor="@color/teal_200" + android:theme="@style/transactionFormFieldBackground" app:boxStrokeColor="@color/teal_200" - app:endIconTint="@color/zinc_300"> + app:cursorColor="@color/teal_200" + app:endIconDrawable="@drawable/ic_chevron_down" + app:endIconTint="@color/zinc_300" + app:hintTextColor="@color/teal_200"> + <AutoCompleteTextView android:id="@+id/transaction_form_auto_complete" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="44dp" - android:textAppearance="@style/TextAppearance.TransactionForm.Input" android:background="@android:color/transparent" android:hint="@string/dummy_category_dropdown_placeholder" - android:inputType="none"/> + android:inputType="none" + android:minHeight="44dp" + android:textAppearance="@style/TextAppearance.TransactionForm.Input" /> </com.google.android.material.textfield.TextInputLayout> - <com.example.bondoman.components.TextInputComponent + <com.example.bondoman.views.components.TextInputComponent android:id="@+id/transaction_form_date" android:layout_width="match_parent" android:layout_height="wrap_content" - app:textInputLabel="Date"/> - <com.example.bondoman.components.TextInputComponent + app:textInputLabel="Date" /> + + <com.example.bondoman.views.components.TextInputComponent android:id="@+id/transaction_form_title" android:layout_width="match_parent" android:layout_height="wrap_content" - app:textInputLabel="Title"/> - <com.example.bondoman.components.TextInputComponent + app:textInputLabel="Title" /> + + <com.example.bondoman.views.components.TextInputComponent android:id="@+id/transaction_form_amount" android:layout_width="match_parent" android:layout_height="wrap_content" - app:textInputLabel="Amount (Rp)"/> + app:textInputLabel="Amount (Rp)" /> + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@drawable/shape_text_input_divider" android:orientation="vertical" android:showDividers="middle"> + <TextView android:id="@+id/text_input_component_label" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.TransactionForm.Input" - android:text="@string/label_transaction_form_location"/> + android:text="@string/label_transaction_form_location" + android:textAppearance="@style/TextAppearance.TransactionForm.Input" /> + <com.google.android.material.textfield.TextInputEditText android:id="@+id/text_input_component_field" android:layout_width="match_parent" android:layout_height="39dp" - android:padding="10dp" android:background="@drawable/bg_full_border" - android:theme="@style/transactionFormFieldBackground" android:hint="@string/hint_transaction_form_location" + android:padding="10dp" android:textAppearance="@style/TextAppearance.TransactionForm.Input" + android:textColor="@color/zinc_300" android:textColorHint="@color/zinc_500" - android:textColor="@color/zinc_300"/> + android:theme="@style/transactionFormFieldBackground" /> + <TextView - android:theme="@style/TextAppearance.TransactionForm.ChangeLocationText" - android:layout_gravity="end" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_gravity="end" android:clickable="true" - android:text="@string/text_change_location"/> - </LinearLayout> + android:text="@string/text_change_location" + android:theme="@style/TextAppearance.TransactionForm.ChangeLocationText" /> + </LinearLayout> + <com.google.android.material.button.MaterialButton - android:insetTop="0dp" - android:insetBottom="0dp" android:layout_width="match_parent" android:layout_height="44dp" - android:text="@string/text_save_button" - android:textAppearance="@style/TextAppearance.TransactionDetail.EditButton" - android:textColor="@color/zinc_900" android:backgroundTint="@color/teal_200" android:gravity="center" + android:insetTop="0dp" + android:insetBottom="0dp" android:outlineSpotShadowColor="@android:color/transparent" - app:iconGravity="textStart" - app:iconTint="@color/zinc_900" + android:text="@string/text_save_button" + android:textAppearance="@style/TextAppearance.TransactionDetail.EditButton" + android:textColor="@color/zinc_900" + app:cornerRadius="5dp" app:icon="@drawable/ic_device_floppy" - app:cornerRadius="5dp" /> + app:iconGravity="textStart" + app:iconTint="@color/zinc_900" /> </LinearLayout> diff --git a/app/src/main/res/layout/fragment_twibbon.xml b/app/src/main/res/layout/fragment_twibbon.xml index d17716eab0c95196b546f4c1cca7b5b2833901e6..380939fe17e1c24eb5f358e8e47ee72f86abe28a 100644 --- a/app/src/main/res/layout/fragment_twibbon.xml +++ b/app/src/main/res/layout/fragment_twibbon.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".fragments.TwibbonFragment"> + tools:context=".views.fragments.TwibbonFragment"> <androidx.camera.view.PreviewView android:id="@+id/camera_preview" diff --git a/app/src/main/res/layout/fragment_twibbon_preview.xml b/app/src/main/res/layout/fragment_twibbon_preview.xml index b2c343ff7ef05e738aa8a07b5dfe3337dd3d6365..aed87e56e3a4139d42fd641d5b6b81a3a4c00994 100644 --- a/app/src/main/res/layout/fragment_twibbon_preview.xml +++ b/app/src/main/res/layout/fragment_twibbon_preview.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:padding="15dp" - tools:context=".fragments.TwibbonPreviewFragment"> + tools:context=".views.fragments.TwibbonPreviewFragment"> <com.google.android.material.imageview.ShapeableImageView android:id="@+id/twibbon_result" diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 059ae7a60451a3b747aa6e616ea021b1fe75386c..2355fed619328e35ceaa2cc072d18834fbbd75e4 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -7,7 +7,7 @@ <fragment android:id="@+id/twibbonPreviewFragment" - android:name="com.example.bondoman.fragments.TwibbonPreviewFragment" + android:name="com.example.bondoman.views.fragments.TwibbonPreviewFragment" android:label="@string/menu_title_camera" tools:layout="@layout/fragment_twibbon_preview"> <action @@ -15,28 +15,28 @@ app:destination="@id/twibbonFragment" /> <argument android:name="twibbonResult" - app:argType="com.example.bondoman.models.ParcelableBitmap" /> + app:argType="com.example.bondoman.data.models.ParcelableBitmap" /> </fragment> <fragment android:id="@+id/transactionListFragment" - android:name="com.example.bondoman.fragments.TransactionListFragment" + android:name="com.example.bondoman.views.fragments.TransactionListFragment" android:label="@string/menu_title_transactions" /> <fragment android:id="@+id/transactionAddFragment" - android:name="com.example.bondoman.fragments.TransactionAddFragment" + android:name="com.example.bondoman.views.fragments.TransactionAddFragment" android:label="@string/menu_title_new_transaction" /> <fragment android:id="@+id/transactionUpdateFragment" - android:name="com.example.bondoman.fragments.TransactionUpdateFragment" + android:name="com.example.bondoman.views.fragments.TransactionUpdateFragment" android:label="@string/menu_title_edit_transaction" /> <fragment android:id="@+id/settingsFragment" - android:name="com.example.bondoman.fragments.SettingsFragment" + android:name="com.example.bondoman.views.fragments.SettingsFragment" android:label="@string/menu_title_settings" tools:layout="@layout/fragment_settings" /> <fragment android:id="@+id/twibbonFragment" - android:name="com.example.bondoman.fragments.TwibbonFragment" + android:name="com.example.bondoman.views.fragments.TwibbonFragment" android:label="@string/menu_title_camera" tools:layout="@layout/fragment_twibbon"> <action @@ -45,11 +45,11 @@ </fragment> <fragment android:id="@+id/scanReceiptFragment" - android:name="com.example.bondoman.fragments.ScanReceiptFragment" + android:name="com.example.bondoman.views.fragments.ScanReceiptFragment" android:label="@string/menu_title_scan" tools:layout="@layout/fragment_scan_receipt" /> <fragment android:id="@+id/graphFragment" - android:name="com.example.bondoman.fragments.GraphFragment" + android:name="com.example.bondoman.views.fragments.GraphFragment" android:label="@string/menu_title_charts" /> </navigation> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 55f897b0f6928cc93b2298eb94e89d664135bc67..3467f575c96b2f362f42c643e5742a5bc4944449 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -120,7 +120,6 @@ <item name="android:textColorHint">@color/zinc_300</item> <item name="android:textColorLink">@color/zinc_300</item> </style> - <style name="TextAppearance.Dialog" parent="@android:style/TextAppearance"> <item name="android:textSize">16sp</item> <item name="android:fontFamily">@font/inter</item> @@ -235,7 +234,6 @@ <item name="backgroundColor">@color/rose_200</item> <item name="borderRadius">4dp</item> </style> - <style name="dialogBackground"> <item name="backgroundColor">@color/bg_main</item> <item name="borderRadius">5dp</item>