diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryAdapter.kt b/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryAdapter.kt index 5f22493..faf01bd 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryAdapter.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryAdapter.kt @@ -34,6 +34,7 @@ class AccountHistoryAdapter( private val iconUrlCache = mutableMapOf() var onImageNeeded: ((counterpartyName: String) -> Unit)? = null var onIconUrlNeeded: ((url: String) -> Unit)? = null + var onTransferClick: ((MibAccount) -> Unit)? = null fun updateImage(counterpartyName: String, bitmap: Bitmap) { imageCache[counterpartyName] = bitmap @@ -164,6 +165,7 @@ class AccountHistoryAdapter( } else { b.llHeaderBlocked.visibility = View.GONE } + b.btnHeaderTransfer.setOnClickListener { onTransferClick?.invoke(acc) } } private fun friendlyType(raw: String): String { diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt index dd4611e..91fcbbd 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import sh.sar.basedbank.BasedBankApp +import sh.sar.basedbank.R import sh.sar.basedbank.api.bml.BmlLoginFlow import sh.sar.basedbank.api.fahipay.FahipayLoginFlow import sh.sar.basedbank.api.mib.MibAccount @@ -82,6 +83,9 @@ class AccountHistoryFragment : Fragment() { adapter = AccountHistoryAdapter(account) adapter.onImageNeeded = { name -> loadContactImage(name) } adapter.onIconUrlNeeded = { url -> loadMerchantIcon(url) } + adapter.onTransferClick = { acc -> + (activity as? HomeActivity)?.navigateTo(R.id.nav_transfer, TransferFragment.newInstanceFrom(acc)) + } binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) binding.recyclerView.adapter = adapter binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/AccountsAdapter.kt b/app/src/main/java/sh/sar/basedbank/ui/home/AccountsAdapter.kt index 1eaa108..5c597cf 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/AccountsAdapter.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/AccountsAdapter.kt @@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView import sh.sar.basedbank.api.mib.MibAccount import sh.sar.basedbank.databinding.ItemAccountBinding import sh.sar.basedbank.databinding.ItemCardBinding -import sh.sar.basedbank.databinding.ItemProfileHeaderBinding +import sh.sar.basedbank.databinding.ItemDateHeaderBinding class AccountsAdapter( accounts: List, @@ -21,7 +21,7 @@ class AccountsAdapter( ) : RecyclerView.Adapter() { private sealed class Item { - data class SectionTitle(val label: String, val chip: String) : Item() + data class SectionTitle(val label: String) : Item() data class Account(val account: MibAccount) : Item() data class Card(val account: MibAccount) : Item() } @@ -35,19 +35,40 @@ class AccountsAdapter( } private fun buildItems(accounts: List): List = buildList { - val regular = accounts.filter { it.profileType != "BML_PREPAID" } - val prepaid = accounts.filter { it.profileType == "BML_PREPAID" } + val nonPrepaid = accounts.filter { it.profileType != "BML_PREPAID" } + val prepaid = accounts.filter { it.profileType == "BML_PREPAID" } - if (regular.isNotEmpty()) { - add(Item.SectionTitle("Accounts", "")) - regular.forEach { add(Item.Account(it)) } + // Group non-prepaid accounts by their derived section title, preserving order + val groups = LinkedHashMap>() + for (acc in nonPrepaid) { + val title = sectionTitle(acc) + groups.getOrPut(title) { mutableListOf() }.add(acc) } + for ((title, group) in groups) { + add(Item.SectionTitle(title)) + group.forEach { add(Item.Account(it)) } + } + if (prepaid.isNotEmpty()) { - add(Item.SectionTitle("Cards", "BML")) + add(Item.SectionTitle("Cards · Bank of Maldives")) prepaid.forEach { add(Item.Card(it)) } } } + private fun sectionTitle(account: MibAccount): String { + val profileLabel = when (account.profileType) { + "0" -> "Personal" + "1" -> "Business" + else -> account.profileName + } + val bank = when { + account.profileType.startsWith("BML") -> "Bank of Maldives" + account.profileType == "FAHIPAY" -> "Fahipay" + else -> "Maldives Islamic Bank" + } + return if (profileLabel.isNotBlank()) "$profileLabel · $bank" else bank + } + override fun getItemViewType(position: Int) = when (items[position]) { is Item.SectionTitle -> TYPE_HEADER is Item.Account -> TYPE_ACCOUNT @@ -57,7 +78,7 @@ class AccountsAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) return when (viewType) { - TYPE_HEADER -> SectionViewHolder(ItemProfileHeaderBinding.inflate(inflater, parent, false)) + TYPE_HEADER -> SectionViewHolder(ItemDateHeaderBinding.inflate(inflater, parent, false)) TYPE_CARD -> CardViewHolder(ItemCardBinding.inflate(inflater, parent, false)) else -> AccountViewHolder(ItemAccountBinding.inflate(inflater, parent, false)) } @@ -73,16 +94,10 @@ class AccountsAdapter( override fun getItemCount() = items.size - private inner class SectionViewHolder(private val binding: ItemProfileHeaderBinding) : + private inner class SectionViewHolder(private val binding: ItemDateHeaderBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(item: Item.SectionTitle) { - binding.tvProfileName.text = item.label - if (item.chip.isNotEmpty()) { - binding.tvProfileType.text = item.chip - binding.tvProfileType.visibility = View.VISIBLE - } else { - binding.tvProfileType.visibility = View.GONE - } + binding.tvDateHeader.text = item.label } } @@ -91,18 +106,8 @@ class AccountsAdapter( fun bind(account: MibAccount) { binding.tvAccountName.text = account.accountBriefName binding.tvAccountNumber.text = account.accountNumber - binding.tvPillBank.text = when { - account.profileType.startsWith("BML") -> "BML" - account.profileType == "FAHIPAY" -> "FP" - else -> null - } - binding.tvPillType.text = friendlyAccountType(account.accountTypeName) - binding.tvPillProfile.text = when (account.profileType) { - "0" -> "Personal" - "1" -> "Business" - else -> account.profileName - } - binding.tvBalance.text = "${account.currencyName} ${account.availableBalance}" + binding.tvPillType.text = friendlyAccountType(account.accountTypeName) + binding.tvBalance.text = "${account.currencyName} ${account.availableBalance}" binding.root.setOnClickListener { onAccountClick(account) } binding.root.setOnLongClickListener { copyToClipboard(it.context, account.accountNumber) diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt index a5e098f..36fda74 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt @@ -158,7 +158,7 @@ class ContactsFragment : Fragment() { colorHex = contact.bankColor, imageHash = contact.customerImgHash ) - (requireActivity() as HomeActivity).showWithBackStack(fragment) + (requireActivity() as HomeActivity).navigateTo(R.id.nav_transfer, fragment) } private fun confirmDelete(contact: MibBeneficiary) { diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt index 93e3365..f50ebb4 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt @@ -199,18 +199,19 @@ class HomeActivity : AppCompatActivity() { } } - fun navigateTo(itemId: Int) { - when (itemId) { - R.id.nav_dashboard -> show(DashboardFragment()) - R.id.nav_accounts -> show(AccountsFragment()) - R.id.nav_contacts -> show(ContactsFragment()) - R.id.nav_transfer -> show(TransferFragment()) - R.id.nav_transfer_history -> show(TransferHistoryFragment()) - R.id.nav_finances -> show(FinancingFragment()) - R.id.nav_otp -> show(OtpFragment()) - R.id.nav_settings -> show(SettingsFragment()) - else -> Toast.makeText(this, R.string.work_in_progress, Toast.LENGTH_SHORT).show() + fun navigateTo(itemId: Int, fragment: Fragment? = null) { + val dest = fragment ?: when (itemId) { + R.id.nav_dashboard -> DashboardFragment() + R.id.nav_accounts -> AccountsFragment() + R.id.nav_contacts -> ContactsFragment() + R.id.nav_transfer -> TransferFragment() + R.id.nav_transfer_history -> TransferHistoryFragment() + R.id.nav_finances -> FinancingFragment() + R.id.nav_otp -> OtpFragment() + R.id.nav_settings -> SettingsFragment() + else -> { Toast.makeText(this, R.string.work_in_progress, Toast.LENGTH_SHORT).show(); return } } + show(dest) binding.navigationView.setCheckedItem(itemId) val bottomNavIds = setOf(R.id.nav_dashboard, R.id.nav_accounts, R.id.nav_contacts, R.id.nav_transfer, R.id.nav_more) if (binding.bottomNavigation.visibility == View.VISIBLE && itemId in bottomNavIds) { diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt index 815c3db..ff4a37e 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt @@ -93,6 +93,11 @@ class TransferFragment : Fragment() { private const val ARG_SUBTITLE = "contact_subtitle" private const val ARG_COLOR = "contact_color" private const val ARG_IMAGE_HASH = "contact_image_hash" + private const val ARG_FROM_ACCOUNT = "from_account" + + fun newInstanceFrom(account: MibAccount) = TransferFragment().apply { + arguments = Bundle().apply { putString(ARG_FROM_ACCOUNT, account.accountNumber) } + } fun newInstance( accountNumber: String, @@ -171,6 +176,16 @@ class TransferFragment : Fragment() { updateAmountPrefix(picked) showFromCard(picked) } + + val fromNumber = arguments?.getString(ARG_FROM_ACCOUNT) + if (fromNumber != null && selectedAccount == null) { + val match = accounts.firstOrNull { it.accountNumber == fromNumber } + if (match != null) { + selectedAccount = match + updateAmountPrefix(match) + showFromCard(match) + } + } } } diff --git a/app/src/main/res/layout/item_account.xml b/app/src/main/res/layout/item_account.xml index 12acb7a..a11332e 100644 --- a/app/src/main/res/layout/item_account.xml +++ b/app/src/main/res/layout/item_account.xml @@ -1,20 +1,16 @@ - + android:orientation="vertical"> @@ -43,7 +39,7 @@ - + - - - - - - - - @@ -111,4 +77,10 @@ - + + + diff --git a/app/src/main/res/layout/item_account_history_header.xml b/app/src/main/res/layout/item_account_history_header.xml index edde46f..2866877 100644 --- a/app/src/main/res/layout/item_account_history_header.xml +++ b/app/src/main/res/layout/item_account_history_header.xml @@ -92,6 +92,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" + android:gravity="center_vertical" android:layout_marginTop="16dp"> + + diff --git a/app/src/main/res/layout/item_card.xml b/app/src/main/res/layout/item_card.xml index a8e4830..67e85aa 100644 --- a/app/src/main/res/layout/item_card.xml +++ b/app/src/main/res/layout/item_card.xml @@ -1,20 +1,16 @@ - + android:orientation="vertical"> @@ -89,4 +85,10 @@ - + + +