diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt index 83c5844..68ae3a9 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt @@ -77,54 +77,125 @@ class DashboardFragment : Fragment() { private fun updateBalances(accounts: List) { val hide = viewModel.hideAmounts.value ?: false + + val nonCreditAccounts = accounts.filter { it.profileType != "BML_CREDIT" } + val creditAccounts = accounts.filter { it.profileType == "BML_CREDIT" } + if (hide) { binding.tvMvrBalance.text = "MVR ••••••" binding.tvUsdBalance.text = "USD ••••••" + if (creditAccounts.isNotEmpty()) { + binding.rowCreditCards.visibility = View.VISIBLE + val hasMvrCredit = creditAccounts.any { it.currencyName.equals("MVR", ignoreCase = true) } + val hasUsdCredit = creditAccounts.any { it.currencyName.equals("USD", ignoreCase = true) } + binding.cardMvrCredit.visibility = if (hasMvrCredit) View.VISIBLE else View.GONE + binding.cardUsdCredit.visibility = if (hasUsdCredit) View.VISIBLE else View.GONE + binding.tvMvrCredit.text = "MVR ••••••" + binding.tvUsdCredit.text = "USD ••••••" + } else { + binding.rowCreditCards.visibility = View.GONE + } return } - val mvrTotal = accounts + + val mvrTotal = nonCreditAccounts .filter { it.currencyName.equals("MVR", ignoreCase = true) } .sumOf { it.availableBalance.replace(",", "").toDoubleOrNull() ?: 0.0 } - val usdTotal = accounts + val usdTotal = nonCreditAccounts .filter { it.currencyName.equals("USD", ignoreCase = true) } .sumOf { it.availableBalance.replace(",", "").toDoubleOrNull() ?: 0.0 } binding.tvMvrBalance.text = "MVR %,.2f".format(mvrTotal) binding.tvUsdBalance.text = "USD %,.2f".format(usdTotal) + + val mvrCredit = creditAccounts + .filter { it.currencyName.equals("MVR", ignoreCase = true) } + .sumOf { it.availableBalance.replace(",", "").toDoubleOrNull() ?: 0.0 } + val usdCredit = creditAccounts + .filter { it.currencyName.equals("USD", ignoreCase = true) } + .sumOf { it.availableBalance.replace(",", "").toDoubleOrNull() ?: 0.0 } + + if (creditAccounts.isNotEmpty()) { + binding.rowCreditCards.visibility = View.VISIBLE + binding.cardMvrCredit.visibility = if (mvrCredit > 0) View.VISIBLE else View.GONE + binding.cardUsdCredit.visibility = if (usdCredit > 0) View.VISIBLE else View.GONE + binding.tvMvrCredit.text = "MVR %,.2f".format(mvrCredit) + binding.tvUsdCredit.text = "USD %,.2f".format(usdCredit) + } else { + binding.rowCreditCards.visibility = View.GONE + } } + private val expandedLimits = mutableSetOf() + private fun updateForeignLimits(entries: List) { val hide = viewModel.hideAmounts.value ?: false binding.containerForeignLimits.removeAllViews() + var cardIndex = 0 for (entry in entries) { for (limit in entry.limits) { + val idx = cardIndex++ val card = ItemForeignLimitBinding.inflate(layoutInflater, binding.containerForeignLimits, false) - card.tvLimitUserName.text = entry.userName.ifBlank { "BML" } - card.tvLimitType.text = limit.type - if (hide) { - card.tvLimitGeneral.text = "USD ••••••" - card.tvLimitMedical.text = "USD ••••••" - card.tvLimitAtm.text = if (!limit.isAtmEnabled) "USD •••••• · Disabled" else "USD ••••••" - card.tvLimitEcom.text = "USD ••••••" - card.tvLimitPos.text = if (!limit.isPosEnabled) "USD •••••• · Disabled" else "USD ••••••" - } else { - card.tvLimitGeneral.text = "USD %,.0f / %,.0f".format(limit.generalRemaining, limit.generalCap) - card.tvLimitMedical.text = "USD %,.0f".format(limit.medicalRemaining) - card.tvLimitAtm.text = if (!limit.isAtmEnabled) - "USD %,.0f / %,.0f · Disabled".format(limit.atmRemaining, limit.atmLimit) - else - "USD %,.0f / %,.0f".format(limit.atmRemaining, limit.atmLimit) - card.tvLimitEcom.text = "USD %,.0f / %,.0f".format(limit.ecomRemaining, limit.ecomLimit) - card.tvLimitPos.text = if (!limit.isPosEnabled) - "USD %,.0f / %,.0f · Disabled".format(limit.posRemaining, limit.posLimit) - else - "USD %,.0f / %,.0f".format(limit.posRemaining, limit.posLimit) + bindLimitCard(card, entry.userName, limit, hide, idx in expandedLimits) + card.root.setOnClickListener { + if (idx in expandedLimits) expandedLimits.remove(idx) else expandedLimits.add(idx) + updateForeignLimits(entries) } binding.containerForeignLimits.addView(card.root) } } } + private fun bindLimitCard( + card: ItemForeignLimitBinding, + userName: String, + limit: BmlForeignLimit, + hide: Boolean, + expanded: Boolean + ) { + card.tvLimitUserName.text = userName.ifBlank { "BML" } + card.tvLimitType.text = limit.type + + // ECOM (always visible) + card.tvLimitEcom.text = if (hide) "USD ••••••" + else "USD %,.2f / %,.0f".format(limit.ecomRemaining, limit.ecomLimit) + card.progressEcom.progress = if (hide || limit.ecomLimit <= 0) 0 + else ((limit.ecomRemaining / limit.ecomLimit) * 100).toInt().coerceIn(0, 100) + + // General (always visible) + card.tvLimitGeneral.text = if (hide) "USD ••••••" + else "USD %,.2f / %,.0f".format(limit.generalRemaining, limit.generalCap) + card.progressGeneral.progress = if (hide || limit.generalCap <= 0) 0 + else ((limit.generalRemaining / limit.generalCap) * 100).toInt().coerceIn(0, 100) + + // Expanded section + val detailsVisible = if (expanded) View.VISIBLE else View.GONE + card.dividerLimitDetails.visibility = detailsVisible + card.detailsGroup.visibility = detailsVisible + + if (expanded) { + // ATM + if (!limit.isAtmEnabled) card.tvAtmLabel.append(" (Disabled)") + card.tvLimitAtm.text = if (hide) "USD ••••••" + else "USD %,.2f / %,.0f".format(limit.atmRemaining, limit.atmLimit) + card.progressAtm.progress = if (hide || limit.atmLimit <= 0) 0 + else ((limit.atmRemaining / limit.atmLimit) * 100).toInt().coerceIn(0, 100) + + // POS + if (!limit.isPosEnabled) card.tvPosLabel.append(" (Disabled)") + card.tvLimitPos.text = if (hide) "USD ••••••" + else "USD %,.2f / %,.0f".format(limit.posRemaining, limit.posLimit) + card.progressPos.progress = if (hide || limit.posLimit <= 0) 0 + else ((limit.posRemaining / limit.posLimit) * 100).toInt().coerceIn(0, 100) + + // Medical + card.tvLimitMedical.text = if (hide) "USD ••••••" + else "USD %,.2f / %,.0f".format(limit.medicalRemaining, limit.totalLimit) + card.progressMedical.progress = if (hide || limit.totalLimit <= 0) 0 + else ((limit.medicalRemaining / limit.totalLimit) * 100).toInt().coerceIn(0, 100) + } + } + private fun updatePendingFinances() { val hide = viewModel.hideAmounts.value ?: false val mibTotal = (viewModel.financing.value ?: emptyList()).sumOf { it.outstandingAmount } diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index 5f40184..b2c3167 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -97,6 +97,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:padding="20dp"> + android:gravity="center_vertical" + android:layout_marginBottom="16dp"> + android:textColor="?attr/colorOnSecondaryContainer" /> - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginBottom="4dp"> - + + + + android:orientation="horizontal" + android:layout_marginBottom="4dp"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 05ca83c..da55d86 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -95,6 +95,8 @@ Quick Actions MVR Total USD Total + MVR Available Credit + USD Available Credit Card Support Transfer PayMV QR