diff --git a/app/build.gradle b/app/build.gradle index c31f073..45ad451 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,6 +34,7 @@ dependencies { implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'com.android.support:design:27.1.1' + implementation "com.android.support:support-emoji-bundled:27.1.1" def room_version = "1.1.1" def lifecycle_version = "1.1.1" // ViewModel and LiveData diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8e5da0f..bbb6957 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionActivity.kt b/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionActivity.kt index 550fe5a..98731cd 100644 --- a/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionActivity.kt +++ b/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionActivity.kt @@ -1,8 +1,9 @@ package com.wbrawner.myallowance.addedittransaction +import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders -import android.support.v7.app.AppCompatActivity import android.os.Bundle +import android.support.v7.app.AppCompatActivity import android.view.Menu import android.view.MenuItem import com.wbrawner.myallowance.R @@ -15,20 +16,54 @@ import java.util.* class AddEditTransactionActivity : AppCompatActivity() { lateinit var viewModel: TransactionViewModel lateinit var type: TransactionType + var id: Int? = null var date: Date = Date() + var menu: Menu? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_add_edit_transaction) + setSupportActionBar(action_bar) supportActionBar?.setDisplayHomeAsUpEnabled(true) viewModel = ViewModelProviders.of(this).get(TransactionViewModel::class.java) - type = TransactionType.valueOf(intent?.extras?.getString(EXTRA_TYPE, "EXPENSE")?: "EXPENSE") - setTitle(type.addTitle) + if (intent?.hasExtra(EXTRA_TYPE) == true) { + type = TransactionType.valueOf(intent?.extras?.getString(EXTRA_TYPE, "EXPENSE") + ?: "EXPENSE") + setTitle(type.addTitle) + return + } else if (intent?.hasExtra(EXTRA_TRANSACTION_ID) != true) { + finish() + return + } + + viewModel.getTransaction(intent!!.extras!!.getInt(EXTRA_TRANSACTION_ID)) + .observe(this, Observer { transaction -> + if (transaction == null) { + menu?.findItem(R.id.action_delete)?.isVisible = false + return@Observer + } + id = transaction.id + type = transaction.type + setTitle(type.editTitle) + menu?.findItem(R.id.action_delete)?.isVisible = true + edit_transaction_title.setText(transaction.title) + edit_transaction_description.setText(transaction.description) + edit_transaction_amount.setText(String.format("%.02f", transaction.amount)) + val field = Calendar.getInstance() + field.time = transaction.date + val year = field.get(Calendar.YEAR) + val month = field.get(Calendar.MONTH) + val day = field.get(Calendar.DAY_OF_MONTH) + edit_transaction_date.updateDate(year, month, day) + }) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.menu_add_edit, menu) + if (id != null) { + menu?.findItem(R.id.action_delete)?.isVisible = true + } return true } @@ -41,7 +76,7 @@ class AddEditTransactionActivity : AppCompatActivity() { cal.set(field.year, field.month, field.dayOfMonth) viewModel.saveTransaction(Transaction( - id = null, + id = id, title = edit_transaction_title.text.toString(), date = cal.time, description = edit_transaction_description.text.toString(), @@ -50,6 +85,10 @@ class AddEditTransactionActivity : AppCompatActivity() { )) finish() } + R.id.action_delete -> { + viewModel.deleteTransactionById(this@AddEditTransactionActivity.id!!) + finish() + } } return true } diff --git a/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionDialog.kt b/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionDialog.kt deleted file mode 100644 index ac75a0f..0000000 --- a/app/src/main/java/com/wbrawner/myallowance/addedittransaction/AddEditTransactionDialog.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.wbrawner.myallowance.addedittransaction - -import android.content.Context -import android.support.v7.app.AlertDialog - -class AddEditTransactionDialog(context: Context) : AlertDialog(context) { - -} \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/myallowance/data/TransactionDao.kt b/app/src/main/java/com/wbrawner/myallowance/data/TransactionDao.kt index e244a1b..511d398 100644 --- a/app/src/main/java/com/wbrawner/myallowance/data/TransactionDao.kt +++ b/app/src/main/java/com/wbrawner/myallowance/data/TransactionDao.kt @@ -2,6 +2,7 @@ package com.wbrawner.myallowance.data import android.arch.lifecycle.LiveData import android.arch.persistence.room.Dao +import android.arch.persistence.room.Delete import android.arch.persistence.room.Insert import android.arch.persistence.room.OnConflictStrategy.REPLACE import android.arch.persistence.room.Query @@ -22,4 +23,10 @@ interface TransactionDao { @Query("SELECT (SELECT TOTAL(amount) from `Transaction` WHERE type = 'INCOME') - (SELECT TOTAL(amount) from `Transaction` WHERE type = 'EXPENSE')") fun getBalance(): LiveData + + @Delete + fun delete(transaction: Transaction) + + @Query("DELETE FROM `Transaction` WHERE id = :id") + fun deleteById(id: Int) } \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/myallowance/data/TransactionRepository.kt b/app/src/main/java/com/wbrawner/myallowance/data/TransactionRepository.kt index 363bed4..8e43232 100644 --- a/app/src/main/java/com/wbrawner/myallowance/data/TransactionRepository.kt +++ b/app/src/main/java/com/wbrawner/myallowance/data/TransactionRepository.kt @@ -1,10 +1,8 @@ package com.wbrawner.myallowance.data import android.arch.lifecycle.LiveData -import android.arch.lifecycle.MutableLiveData import android.os.Handler import android.os.HandlerThread -import java.util.* class TransactionRepository(val dao: TransactionDao) { val handler: Handler @@ -53,5 +51,15 @@ class TransactionRepository(val dao: TransactionDao) { } + fun delete(transaction: Transaction) { + handler.post { dao.delete(transaction) } + } + + + fun deleteById(id: Int) { + handler.post { dao.deleteById(id) } + } + + fun getCurrentBalance(): LiveData = dao.getBalance() } \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/myallowance/data/TransactionType.kt b/app/src/main/java/com/wbrawner/myallowance/data/TransactionType.kt index b979836..f7c7272 100644 --- a/app/src/main/java/com/wbrawner/myallowance/data/TransactionType.kt +++ b/app/src/main/java/com/wbrawner/myallowance/data/TransactionType.kt @@ -1,10 +1,29 @@ package com.wbrawner.myallowance.data +import android.support.annotation.ColorRes import android.support.annotation.StringRes import com.wbrawner.myallowance.R import java.io.Serializable -enum class TransactionType(@StringRes val title: Int, @StringRes val addTitle: Int) : Serializable { - INCOME(R.string.title_income, R.string.title_add_income), - EXPENSE(R.string.title_expenses, R.string.title_add_expense); +enum class TransactionType( + @StringRes val title: Int, + @StringRes val addTitle: Int, + @StringRes val editTitle: Int, + @StringRes val noDataText: Int, + @ColorRes val textColor: Int +) : Serializable { + INCOME( + R.string.title_income, + R.string.title_add_income, + R.string.title_edit_income, + R.string.income_no_data, + R.color.colorTextGreen + ), + EXPENSE( + R.string.title_expenses, + R.string.title_add_expense, + R.string.title_edit_expense, + R.string.expenses_no_data, + R.color.colorTextRed + ); } diff --git a/app/src/main/java/com/wbrawner/myallowance/overview/OverviewFragment.kt b/app/src/main/java/com/wbrawner/myallowance/overview/OverviewFragment.kt index bb9d80f..f3c59fe 100644 --- a/app/src/main/java/com/wbrawner/myallowance/overview/OverviewFragment.kt +++ b/app/src/main/java/com/wbrawner/myallowance/overview/OverviewFragment.kt @@ -62,6 +62,6 @@ class OverviewFragment : Fragment() { companion object { const val TAG_FRAGMENT = "overview" - const val TITLE_FRAGMENT = R.string.title_dashboard + const val TITLE_FRAGMENT = R.string.app_name } } \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionAdapter.kt b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionAdapter.kt index 379d30c..49df7b4 100644 --- a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionAdapter.kt +++ b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionAdapter.kt @@ -1,12 +1,17 @@ package com.wbrawner.myallowance.transactions +import android.content.Intent +import android.support.v4.content.ContextCompat.startActivity import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import com.wbrawner.myallowance.R +import com.wbrawner.myallowance.addedittransaction.AddEditTransactionActivity +import com.wbrawner.myallowance.addedittransaction.AddEditTransactionActivity.Companion.EXTRA_TRANSACTION_ID import com.wbrawner.myallowance.data.Transaction +import java.text.SimpleDateFormat class TransactionAdapter(private val data: List) : RecyclerView.Adapter() { @@ -21,11 +26,27 @@ class TransactionAdapter(private val data: List) override fun onBindViewHolder(holder: ViewHolder, position: Int) { val transaction = data[position] holder.title.text = transaction.title + holder.date.text = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT).format(transaction.date) holder.amount.text = String.format("${'$'}%.02f", transaction.amount) + val context = holder.itemView.context + holder.amount.setTextColor( + context.resources.getColor(transaction.type.textColor, context.theme) + ) + holder.itemView.setOnClickListener { + startActivity( + it.context.applicationContext, + Intent(it.context.applicationContext, AddEditTransactionActivity::class.java) + .apply { + putExtra(EXTRA_TRANSACTION_ID, transaction.id) + }, + null + ) + } } inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { val title = itemView.findViewById(R.id.transaction_title) + val date = itemView.findViewById(R.id.transaction_date) val amount = itemView.findViewById(R.id.transaction_amount) } } \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListActivity.kt b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListActivity.kt index 3be3d42..439f758 100644 --- a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListActivity.kt +++ b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListActivity.kt @@ -1,8 +1,10 @@ package com.wbrawner.myallowance.transactions -import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.support.annotation.StringRes +import android.support.text.emoji.EmojiCompat +import android.support.text.emoji.bundled.BundledEmojiCompatConfig +import android.support.v7.app.AppCompatActivity import com.wbrawner.myallowance.R import com.wbrawner.myallowance.data.TransactionType import com.wbrawner.myallowance.overview.OverviewFragment @@ -11,7 +13,9 @@ import kotlinx.android.synthetic.main.activity_transaction_list.* class TransactionListActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + EmojiCompat.init(BundledEmojiCompatConfig(this)) setContentView(R.layout.activity_transaction_list) + setSupportActionBar(action_bar) menu_main.setOnNavigationItemSelectedListener { item -> when (item.itemId) { diff --git a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListFragment.kt b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListFragment.kt index 560f411..ea823ac 100644 --- a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListFragment.kt +++ b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionListFragment.kt @@ -4,8 +4,8 @@ import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders import android.content.Intent import android.os.Bundle -import android.support.annotation.StringRes import android.support.design.widget.FloatingActionButton +import android.support.text.emoji.widget.EmojiTextView import android.support.v4.app.Fragment import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView @@ -17,7 +17,6 @@ import com.wbrawner.myallowance.addedittransaction.AddEditTransactionActivity import com.wbrawner.myallowance.addedittransaction.AddEditTransactionActivity.Companion.EXTRA_TYPE import com.wbrawner.myallowance.data.Transaction import com.wbrawner.myallowance.data.TransactionType -import java.io.Serializable class TransactionListFragment : Fragment() { lateinit var viewModel: TransactionViewModel @@ -41,16 +40,28 @@ class TransactionListFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_transaction_list, container, false) val recyclerView = view.findViewById(R.id.list_transactions) + val fab = view.findViewById(R.id.fab_add_transaction) recyclerView.layoutManager = LinearLayoutManager(activity) viewModel.getTransactionsByType(20, type) .observe(this, Observer> { data -> - if (data == null) { + val noDataView = view.findViewById(R.id.transaction_list_no_data) + if (data == null || data.isEmpty()) { recyclerView.adapter = null + noDataView?.setText(type.noDataText) + recyclerView?.visibility = View.GONE + noDataView?.visibility = View.VISIBLE } else { recyclerView.adapter = TransactionAdapter(data) + recyclerView.visibility = View.VISIBLE + noDataView.visibility = View.GONE } }) - view.findViewById(R.id.fab_add_transaction).setOnClickListener { + recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) { + if (dy > 0) fab.hide() else fab.show() + } + }) + fab.setOnClickListener { startActivity( Intent(activity, AddEditTransactionActivity::class.java).apply { this.putExtra(EXTRA_TYPE, this@TransactionListFragment.type.name) diff --git a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionViewModel.kt b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionViewModel.kt index 9317a45..52bd025 100644 --- a/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionViewModel.kt +++ b/app/src/main/java/com/wbrawner/myallowance/transactions/TransactionViewModel.kt @@ -21,4 +21,8 @@ class TransactionViewModel(application: Application): AndroidViewModel(applicati fun getCurrentBalance(): LiveData = transactionRepo.getCurrentBalance() fun saveTransaction(transaction: Transaction) = transactionRepo.save(transaction) + + fun deleteTransaction(transaction: Transaction) = transactionRepo.delete(transaction) + + fun deleteTransactionById(id: Int) = transactionRepo.deleteById(id) } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_save_white_24dp.xml b/app/src/main/res/drawable/ic_save_white_24dp.xml index a7a81a2..a7c45be 100644 --- a/app/src/main/res/drawable/ic_save_white_24dp.xml +++ b/app/src/main/res/drawable/ic_save_white_24dp.xml @@ -4,6 +4,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/layout/activity_add_edit_transaction.xml b/app/src/main/res/layout/activity_add_edit_transaction.xml index b2a43cb..5ca5e08 100644 --- a/app/src/main/res/layout/activity_add_edit_transaction.xml +++ b/app/src/main/res/layout/activity_add_edit_transaction.xml @@ -1,79 +1,97 @@ - + android:layout_height="match_parent"> - + android:layout_height="?attr/actionBarSize" + android:elevation="4dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + - - - - - - - - - - - - - - + android:padding="16dp"> - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_transaction_list.xml b/app/src/main/res/layout/activity_transaction_list.xml index 3cf6cc1..7ff04c2 100644 --- a/app/src/main/res/layout/activity_transaction_list.xml +++ b/app/src/main/res/layout/activity_transaction_list.xml @@ -6,11 +6,20 @@ android:layout_height="match_parent" tools:context=".transactions.TransactionListActivity"> + + diff --git a/app/src/main/res/layout/fragment_overview.xml b/app/src/main/res/layout/fragment_overview.xml index a976e13..85f952c 100644 --- a/app/src/main/res/layout/fragment_overview.xml +++ b/app/src/main/res/layout/fragment_overview.xml @@ -1,7 +1,6 @@ @@ -28,7 +27,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/overview_current_balance_label" /> - + android:layout_gravity="fill_vertical|center_horizontal" /> + + - + android:layout_height="wrap_content" + android:padding="16dp"> + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_add_edit.xml b/app/src/main/res/menu/menu_add_edit.xml index eab1791..92d5076 100644 --- a/app/src/main/res/menu/menu_add_edit.xml +++ b/app/src/main/res/menu/menu_add_edit.xml @@ -6,4 +6,9 @@ android:icon="@drawable/ic_save_white_24dp" app:showAsAction="ifRoom|withText" android:title="@string/action_save" /> + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 2a61c1d..6f8a63c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,8 +1,8 @@ #3F51B5 - #303F9F - #FF4081 + #3F51B5 + #3F51B5 #FF000000 #388e3c #d32f2f diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c28cef3..e72e63c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ My Allowance + Allowance Title Add Income Add Expense @@ -11,6 +12,11 @@ Income Dashboard Current Balance - Add some transactions to see an overview of your spending here + 📈\nAdd some transactions to see an overview of your spending here Save + Delete + Edit Income + Edit Expense + 🌳\nGet to work! Money doesn\'t grow on trees after all + 🤔\nAre you sure you haven\'t spent any money? diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index cd855c9..cb6f836 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,11 +1,13 @@ -