From d03d7f755f74058fe58451c8d636e462d24b2554 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sun, 19 Oct 2025 06:16:05 +0530 Subject: [PATCH 01/10] Added: showBasicOptions working peoperly. --- .../composeResources/values/strings.xml | 7 + .../SavingsAccountDetailsScreen.kt | 158 ++++++++++++++++++ .../SavingsAccountDetailsViewModel.kt | 61 +++++++ 3 files changed, 226 insertions(+) diff --git a/feature/savings-account/src/commonMain/composeResources/values/strings.xml b/feature/savings-account/src/commonMain/composeResources/values/strings.xml index 2575acd2f2..51a05fa0bd 100644 --- a/feature/savings-account/src/commonMain/composeResources/values/strings.xml +++ b/feature/savings-account/src/commonMain/composeResources/values/strings.xml @@ -97,4 +97,11 @@ No Savings Accounts Found Server issue from our side cannot proceed further, Try again after a moment + Transactions + Charges + QR Code + Transaction Info + Account Options + Transaction Information + \ No newline at end of file diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 5eaac79fe7..6fef4cfff4 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -11,6 +11,7 @@ package org.mifos.mobile.feature.savingsaccount.savingsAccountDetails import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row @@ -22,10 +23,14 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -33,11 +38,18 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.collections.immutable.ImmutableList import mifos_mobile.feature.savings_account.generated.resources.Res import mifos_mobile.feature.savings_account.generated.resources.feature_account_action_update import mifos_mobile.feature.savings_account.generated.resources.feature_account_details_top_bar_title +import mifos_mobile.feature.savings_account.generated.resources.feature_savings_account_options_title +import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_charges +import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_qr_code +import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_transaction_info +import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_transactions import mifos_mobile.feature.savings_account.generated.resources.feature_savings_status_label +import mifos_mobile.feature.savings_account.generated.resources.feature_transaction_info_title import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.ui.tooling.preview.Preview @@ -102,6 +114,18 @@ internal fun SavingsAccountDetailsScreen( uiState.product, ) } + + SavingsAccountDetailsEvent.ShowTransactions -> { + navigateToSavingsAccountTransactionScreen(uiState.accountId) + } + + SavingsAccountDetailsEvent.ShowCharges -> { + navigateToClientChargeScreen(ChargeType.SAVINGS.name, uiState.accountId) + } + + SavingsAccountDetailsEvent.ShowQrCode -> { + navigateToQrCodeScreen(viewModel.getQrString()) + } } } @@ -114,6 +138,7 @@ internal fun SavingsAccountDetailsScreen( SavingsAccountDialogs( dialogState = uiState.dialogState, + transactionList = uiState.transactionList, onAction = remember(viewModel) { { viewModel.trySendAction(it) } }, @@ -138,6 +163,85 @@ internal fun SavingsAccountDetailsContent( ) } }, + actions = { + Box { + IconButton(onClick = { onAction(SavingsAccountDetailsAction.ToggleMenu) }) { + Icon( + imageVector = MifosIcons.MoreVert, + contentDescription = stringResource(Res.string.feature_savings_account_options_title), + ) + } + + // Dropdown menu + DropdownMenu( + expanded = state.isMenuExpanded, + onDismissRequest = { onAction(SavingsAccountDetailsAction.DismissMenu) }, + ) { + // Transactions option + DropdownMenuItem( + text = { Text(stringResource(Res.string.feature_savings_menu_transactions)) }, + onClick = { + onAction(SavingsAccountDetailsAction.OnTransactionsClick) + onAction(SavingsAccountDetailsAction.DismissMenu) + }, + enabled = state.isActive, + leadingIcon = { + Icon( + imageVector = MifosIcons.TransactionHistory, + contentDescription = null, + ) + }, + ) + + // Charges option + DropdownMenuItem( + text = { Text(stringResource(Res.string.feature_savings_menu_charges)) }, + onClick = { + onAction(SavingsAccountDetailsAction.OnChargesClick) + onAction(SavingsAccountDetailsAction.DismissMenu) + }, + leadingIcon = { + Icon( + imageVector = MifosIcons.Receipt, + contentDescription = null, + ) + }, + ) + + // QR Code option + DropdownMenuItem( + text = { Text(stringResource(Res.string.feature_savings_menu_qr_code)) }, + onClick = { + onAction(SavingsAccountDetailsAction.OnQrCodeClick) + onAction(SavingsAccountDetailsAction.DismissMenu) + }, + enabled = state.accountNumber != null, + leadingIcon = { + Icon( + imageVector = MifosIcons.QrCode, + contentDescription = null, + ) + }, + ) + + // Transaction Info option + DropdownMenuItem( + text = { Text(stringResource(Res.string.feature_savings_menu_transaction_info)) }, + onClick = { + onAction(SavingsAccountDetailsAction.OnTransactionInfoClick) + onAction(SavingsAccountDetailsAction.DismissMenu) + }, + enabled = state.transactionList.isNotEmpty(), + leadingIcon = { + Icon( + imageVector = MifosIcons.Info, + contentDescription = null, + ) + }, + ) + } + } + }, ) { when (state.uiState) { is ScreenUiState.Error -> { @@ -318,9 +422,56 @@ internal fun SavingsAccountActions( } } +@Composable +private fun TransactionInfoDialog( + transactionItems: List, + onDismiss: () -> Unit, +) { + androidx.compose.material3.AlertDialog( + onDismissRequest = onDismiss, + title = { + Text( + text = stringResource(Res.string.feature_transaction_info_title), + style = MaterialTheme.typography.titleLarge, + ) + }, + text = { + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(DesignToken.spacing.medium), + ) { + transactionItems.forEach { item -> + Column( + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = stringResource(item.label), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Text( + text = item.value, + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurface, + ) + } + } + } + }, + confirmButton = { + TextButton(onClick = onDismiss) { + Text("Close") + } + }, + ) +} + @Composable internal fun SavingsAccountDialogs( dialogState: SavingsAccountDetailsState.DialogState?, + transactionList: List, onAction: (SavingsAccountDetailsAction) -> Unit, ) { when (dialogState) { @@ -332,6 +483,13 @@ internal fun SavingsAccountDialogs( ) } + is SavingsAccountDetailsState.DialogState.TransactionInfo -> { + TransactionInfoDialog( + transactionItems = transactionList, + onDismiss = { onAction(SavingsAccountDetailsAction.DismissDialog) }, + ) + } + null -> Unit } } diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt index 6496e2dbb1..d3ca8ea24d 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt @@ -118,6 +118,21 @@ internal class SavingsAccountDetailsViewModel( SavingsAccountDetailsAction.OnUpdateAccount -> sendEvent( SavingsAccountDetailsEvent.UpdateAccount, ) + + SavingsAccountDetailsAction.OnTransactionsClick -> handleTransactionsClick() + + SavingsAccountDetailsAction.OnChargesClick -> handleChargesClick() + + SavingsAccountDetailsAction.OnQrCodeClick -> handleQrCodeClick() + + SavingsAccountDetailsAction.OnTransactionInfoClick -> handleTransactionInfoClick() + + SavingsAccountDetailsAction.ToggleMenu -> { + updateState { it.copy(isMenuExpanded = !it.isMenuExpanded) } + } + SavingsAccountDetailsAction.DismissMenu -> { + updateState { it.copy(isMenuExpanded = false) } + } } } @@ -130,6 +145,28 @@ internal class SavingsAccountDetailsViewModel( mutableStateFlow.update(update) } + private fun handleTransactionsClick() { + if (state.isActive) { + sendEvent(SavingsAccountDetailsEvent.ShowTransactions) + } + } + + private fun handleChargesClick() { + sendEvent(SavingsAccountDetailsEvent.ShowCharges) + } + + private fun handleQrCodeClick() { + if (state.accountNumber != null) { + sendEvent(SavingsAccountDetailsEvent.ShowQrCode) + } + } + + private fun handleTransactionInfoClick() { + if (state.transactionList.isNotEmpty()) { + updateState { it.copy(dialogState = SavingsAccountDetailsState.DialogState.TransactionInfo) } + } + } + /** * Handles changes in network connectivity. * @@ -297,6 +334,7 @@ internal class SavingsAccountDetailsViewModel( * @property isActive True if the account is active. * @property items List of quick action items (Deposit, Transfer, etc.) * @property isUpdatable user can update only when status is submit and pending approval + * @property isMenuExpanded True if the menu is expanded. * @property dialogState State representing dialogs like error, loading, etc. */ @Immutable @@ -313,6 +351,8 @@ internal data class SavingsAccountDetailsState( val isUpdatable: Boolean = false, + val isMenuExpanded: Boolean = false, + val dialogState: DialogState? = null, val networkStatus: Boolean = false, val uiState: ScreenUiState? = ScreenUiState.Loading, @@ -323,6 +363,9 @@ internal data class SavingsAccountDetailsState( sealed interface DialogState { /** Shown when an error occurs. */ data class Error(val message: String) : DialogState + + /** Shown when displaying transaction info. */ + data object TransactionInfo : DialogState } } @@ -338,6 +381,12 @@ sealed interface SavingsAccountDetailsEvent { /** Trigger Update Amount */ data object UpdateAccount : SavingsAccountDetailsEvent + + data object ShowTransactions : SavingsAccountDetailsEvent + + data object ShowCharges : SavingsAccountDetailsEvent + + data object ShowQrCode : SavingsAccountDetailsEvent } /** @@ -362,6 +411,18 @@ sealed interface SavingsAccountDetailsAction { /** Action to observe network status */ data class ReceiveNetworkStatus(val isOnline: Boolean) : SavingsAccountDetailsAction + data object OnTransactionsClick : SavingsAccountDetailsAction + + data object OnChargesClick : SavingsAccountDetailsAction + + data object OnQrCodeClick : SavingsAccountDetailsAction + + data object OnTransactionInfoClick : SavingsAccountDetailsAction + + data object ToggleMenu : SavingsAccountDetailsAction + + data object DismissMenu : SavingsAccountDetailsAction + /** * Internal-only actions such as results from repository calls. */ From 8bfd6c9c9958a52deca0368610ff67937f474368 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sun, 19 Oct 2025 15:59:27 +0530 Subject: [PATCH 02/10] Update:some changes in the trasectionInfo. --- .../SavingsAccountDetailsScreen.kt | 63 +++---------------- .../SavingsAccountDetailsViewModel.kt | 2 +- 2 files changed, 11 insertions(+), 54 deletions(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 6fef4cfff4..f376df7a07 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -30,7 +30,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -38,7 +37,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.collections.immutable.ImmutableList import mifos_mobile.feature.savings_account.generated.resources.Res import mifos_mobile.feature.savings_account.generated.resources.feature_account_action_update @@ -63,6 +61,7 @@ import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.designsystem.theme.MifosTypography import org.mifos.mobile.core.model.enums.ChargeType import org.mifos.mobile.core.ui.component.MifosActionCard +import org.mifos.mobile.core.ui.component.MifosAlertDialog import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosLabelValueCard import org.mifos.mobile.core.ui.component.MifosPoweredCard @@ -138,7 +137,7 @@ internal fun SavingsAccountDetailsScreen( SavingsAccountDialogs( dialogState = uiState.dialogState, - transactionList = uiState.transactionList, + transectionInfo = uiState.transactionList, onAction = remember(viewModel) { { viewModel.trySendAction(it) } }, @@ -422,56 +421,10 @@ internal fun SavingsAccountActions( } } -@Composable -private fun TransactionInfoDialog( - transactionItems: List, - onDismiss: () -> Unit, -) { - androidx.compose.material3.AlertDialog( - onDismissRequest = onDismiss, - title = { - Text( - text = stringResource(Res.string.feature_transaction_info_title), - style = MaterialTheme.typography.titleLarge, - ) - }, - text = { - Column( - modifier = Modifier - .fillMaxWidth() - .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(DesignToken.spacing.medium), - ) { - transactionItems.forEach { item -> - Column( - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringResource(item.label), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - Text( - text = item.value, - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSurface, - ) - } - } - } - }, - confirmButton = { - TextButton(onClick = onDismiss) { - Text("Close") - } - }, - ) -} - @Composable internal fun SavingsAccountDialogs( dialogState: SavingsAccountDetailsState.DialogState?, - transactionList: List, + transectionInfo: List, onAction: (SavingsAccountDetailsAction) -> Unit, ) { when (dialogState) { @@ -484,9 +437,13 @@ internal fun SavingsAccountDialogs( } is SavingsAccountDetailsState.DialogState.TransactionInfo -> { - TransactionInfoDialog( - transactionItems = transactionList, - onDismiss = { onAction(SavingsAccountDetailsAction.DismissDialog) }, + MifosAlertDialog( + onDismissRequest = { onAction(SavingsAccountDetailsAction.DismissDialog) }, + dialogTitle =stringResource(Res.string.feature_transaction_info_title), + dialogText = transectionInfo.joinToString("\n ") { "${it.label}: ${it.value}" }, + confirmationText ="Close", + dismissText = "", + onConfirmation = { onAction(SavingsAccountDetailsAction.DismissDialog) }, ) } diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt index d3ca8ea24d..6eb37e94e7 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt @@ -308,7 +308,7 @@ internal class SavingsAccountDetailsViewModel( ) } ?: emptyList() - mutableStateFlow.update { + updateState { it.copy( isActive = isActive, isUpdatable = isUpdate, From 8b48dfd0b63b8321718a7fc21cdfe63708fedb9f Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sun, 19 Oct 2025 16:01:36 +0530 Subject: [PATCH 03/10] Update:some changes in the trasectionInfo. --- .../savingsAccountDetails/SavingsAccountDetailsScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index f376df7a07..859f99e4b1 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -439,9 +439,9 @@ internal fun SavingsAccountDialogs( is SavingsAccountDetailsState.DialogState.TransactionInfo -> { MifosAlertDialog( onDismissRequest = { onAction(SavingsAccountDetailsAction.DismissDialog) }, - dialogTitle =stringResource(Res.string.feature_transaction_info_title), + dialogTitle = stringResource(Res.string.feature_transaction_info_title), dialogText = transectionInfo.joinToString("\n ") { "${it.label}: ${it.value}" }, - confirmationText ="Close", + confirmationText = "Close", dismissText = "", onConfirmation = { onAction(SavingsAccountDetailsAction.DismissDialog) }, ) From 541e63a0657ed8a243bc9cfa6070e7769c079314 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Fri, 24 Oct 2025 22:15:31 +0530 Subject: [PATCH 04/10] Update: added all the functionality properly --- .../mifos/mobile/core/model/SavingStatus.kt | 29 ++++ .../SavingsAccountDetailsScreen.kt | 152 ++---------------- .../SavingsAccountDetailsViewModel.kt | 85 ++++------ 3 files changed, 68 insertions(+), 198 deletions(-) create mode 100644 core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/SavingStatus.kt diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/SavingStatus.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/SavingStatus.kt new file mode 100644 index 0000000000..9d9416977e --- /dev/null +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/SavingStatus.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.model + +import kotlinx.serialization.Serializable + +@Serializable +enum class SavingStatus(val status: String) { + + ACTIVE("Active"), + INACTIVE("Inactive"), + CLOSED("Closed"), + SUBMIT_AND_PENDING_APPROVAL("Submitted and pending approval"), + ; + + companion object { + fun fromStatus(status: String): SavingStatus { + return entries.find { it.status.equals(status, ignoreCase = true) } + ?: throw IllegalArgumentException("Invalid status: $status") + } + } +} diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 859f99e4b1..47d6a93a9d 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -11,7 +11,6 @@ package org.mifos.mobile.feature.savingsaccount.savingsAccountDetails import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row @@ -23,10 +22,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.DropdownMenu -import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -37,17 +33,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import kotlinx.collections.immutable.ImmutableList import mifos_mobile.feature.savings_account.generated.resources.Res import mifos_mobile.feature.savings_account.generated.resources.feature_account_action_update import mifos_mobile.feature.savings_account.generated.resources.feature_account_details_top_bar_title -import mifos_mobile.feature.savings_account.generated.resources.feature_savings_account_options_title -import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_charges -import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_qr_code -import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_transaction_info -import mifos_mobile.feature.savings_account.generated.resources.feature_savings_menu_transactions import mifos_mobile.feature.savings_account.generated.resources.feature_savings_status_label -import mifos_mobile.feature.savings_account.generated.resources.feature_transaction_info_title import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.ui.tooling.preview.Preview @@ -61,7 +50,6 @@ import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.designsystem.theme.MifosTypography import org.mifos.mobile.core.model.enums.ChargeType import org.mifos.mobile.core.ui.component.MifosActionCard -import org.mifos.mobile.core.ui.component.MifosAlertDialog import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosLabelValueCard import org.mifos.mobile.core.ui.component.MifosPoweredCard @@ -134,14 +122,6 @@ internal fun SavingsAccountDetailsScreen( { viewModel.trySendAction(it) } }, ) - - SavingsAccountDialogs( - dialogState = uiState.dialogState, - transectionInfo = uiState.transactionList, - onAction = remember(viewModel) { - { viewModel.trySendAction(it) } - }, - ) } @Composable @@ -162,85 +142,6 @@ internal fun SavingsAccountDetailsContent( ) } }, - actions = { - Box { - IconButton(onClick = { onAction(SavingsAccountDetailsAction.ToggleMenu) }) { - Icon( - imageVector = MifosIcons.MoreVert, - contentDescription = stringResource(Res.string.feature_savings_account_options_title), - ) - } - - // Dropdown menu - DropdownMenu( - expanded = state.isMenuExpanded, - onDismissRequest = { onAction(SavingsAccountDetailsAction.DismissMenu) }, - ) { - // Transactions option - DropdownMenuItem( - text = { Text(stringResource(Res.string.feature_savings_menu_transactions)) }, - onClick = { - onAction(SavingsAccountDetailsAction.OnTransactionsClick) - onAction(SavingsAccountDetailsAction.DismissMenu) - }, - enabled = state.isActive, - leadingIcon = { - Icon( - imageVector = MifosIcons.TransactionHistory, - contentDescription = null, - ) - }, - ) - - // Charges option - DropdownMenuItem( - text = { Text(stringResource(Res.string.feature_savings_menu_charges)) }, - onClick = { - onAction(SavingsAccountDetailsAction.OnChargesClick) - onAction(SavingsAccountDetailsAction.DismissMenu) - }, - leadingIcon = { - Icon( - imageVector = MifosIcons.Receipt, - contentDescription = null, - ) - }, - ) - - // QR Code option - DropdownMenuItem( - text = { Text(stringResource(Res.string.feature_savings_menu_qr_code)) }, - onClick = { - onAction(SavingsAccountDetailsAction.OnQrCodeClick) - onAction(SavingsAccountDetailsAction.DismissMenu) - }, - enabled = state.accountNumber != null, - leadingIcon = { - Icon( - imageVector = MifosIcons.QrCode, - contentDescription = null, - ) - }, - ) - - // Transaction Info option - DropdownMenuItem( - text = { Text(stringResource(Res.string.feature_savings_menu_transaction_info)) }, - onClick = { - onAction(SavingsAccountDetailsAction.OnTransactionInfoClick) - onAction(SavingsAccountDetailsAction.DismissMenu) - }, - enabled = state.transactionList.isNotEmpty(), - leadingIcon = { - Icon( - imageVector = MifosIcons.Info, - contentDescription = null, - ) - }, - ) - } - } - }, ) { when (state.uiState) { is ScreenUiState.Error -> { @@ -278,7 +179,7 @@ internal fun SavingsAccountDetailsContent( isActive = state.isActive, ) - if (state.isActive) { + if (state.transactionList.isNotEmpty()) { AccountDetailsGrid( label = "Last Transactions", details = state.transactionList, @@ -286,14 +187,14 @@ internal fun SavingsAccountDetailsContent( ) } - if (state.isActive) { - SavingsAccountActions( - items = state.items, - onActionClick = { - onAction(SavingsAccountDetailsAction.OnNavigateToAction(it)) - }, - ) - } + val visibleActions = state.savingStatus?.allowedActions ?: emptySet() + + SavingsAccountActions( + visibleActions = visibleActions, + onActionClick = { + onAction(SavingsAccountDetailsAction.OnNavigateToAction(it)) + }, + ) } } else -> { } @@ -393,7 +294,7 @@ internal fun AccountDetailsGrid( @Composable internal fun SavingsAccountActions( - items: ImmutableList, + visibleActions: Set, onActionClick: (String) -> Unit, ) { Column( @@ -407,7 +308,8 @@ internal fun SavingsAccountActions( FlowRow( modifier = Modifier.fillMaxWidth(), ) { - items.forEach { item -> + println("Visible Actions: $visibleActions") + visibleActions.forEach { item -> MifosActionCard( title = item.title, subTitle = item.subTitle, @@ -421,36 +323,6 @@ internal fun SavingsAccountActions( } } -@Composable -internal fun SavingsAccountDialogs( - dialogState: SavingsAccountDetailsState.DialogState?, - transectionInfo: List, - onAction: (SavingsAccountDetailsAction) -> Unit, -) { - when (dialogState) { - is SavingsAccountDetailsState.DialogState.Error -> { - MifosErrorComponent( - message = dialogState.message, - onRetry = { onAction(SavingsAccountDetailsAction.OnRetry) }, - isRetryEnabled = true, - ) - } - - is SavingsAccountDetailsState.DialogState.TransactionInfo -> { - MifosAlertDialog( - onDismissRequest = { onAction(SavingsAccountDetailsAction.DismissDialog) }, - dialogTitle = stringResource(Res.string.feature_transaction_info_title), - dialogText = transectionInfo.joinToString("\n ") { "${it.label}: ${it.value}" }, - confirmationText = "Close", - dismissText = "", - onConfirmation = { onAction(SavingsAccountDetailsAction.DismissDialog) }, - ) - } - - null -> Unit - } -} - data class LabelValueItem( val label: StringResource, val value: String, diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt index 6eb37e94e7..be6282f822 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.Immutable import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute +import io.ktor.client.utils.EmptyContent.status import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.update @@ -35,7 +36,7 @@ import org.mifos.mobile.core.common.DateHelper import org.mifos.mobile.core.data.repository.SavingsAccountRepository import org.mifos.mobile.core.data.util.NetworkMonitor import org.mifos.mobile.core.datastore.UserPreferencesRepository -import org.mifos.mobile.core.model.LoanStatus +import org.mifos.mobile.core.model.SavingStatus import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations import org.mifos.mobile.core.model.entity.templates.account.AccountType import org.mifos.mobile.core.qr.getAccountDetailsInString @@ -118,21 +119,6 @@ internal class SavingsAccountDetailsViewModel( SavingsAccountDetailsAction.OnUpdateAccount -> sendEvent( SavingsAccountDetailsEvent.UpdateAccount, ) - - SavingsAccountDetailsAction.OnTransactionsClick -> handleTransactionsClick() - - SavingsAccountDetailsAction.OnChargesClick -> handleChargesClick() - - SavingsAccountDetailsAction.OnQrCodeClick -> handleQrCodeClick() - - SavingsAccountDetailsAction.OnTransactionInfoClick -> handleTransactionInfoClick() - - SavingsAccountDetailsAction.ToggleMenu -> { - updateState { it.copy(isMenuExpanded = !it.isMenuExpanded) } - } - SavingsAccountDetailsAction.DismissMenu -> { - updateState { it.copy(isMenuExpanded = false) } - } } } @@ -145,28 +131,6 @@ internal class SavingsAccountDetailsViewModel( mutableStateFlow.update(update) } - private fun handleTransactionsClick() { - if (state.isActive) { - sendEvent(SavingsAccountDetailsEvent.ShowTransactions) - } - } - - private fun handleChargesClick() { - sendEvent(SavingsAccountDetailsEvent.ShowCharges) - } - - private fun handleQrCodeClick() { - if (state.accountNumber != null) { - sendEvent(SavingsAccountDetailsEvent.ShowQrCode) - } - } - - private fun handleTransactionInfoClick() { - if (state.transactionList.isNotEmpty()) { - updateState { it.copy(dialogState = SavingsAccountDetailsState.DialogState.TransactionInfo) } - } - } - /** * Handles changes in network connectivity. * @@ -264,8 +228,8 @@ internal class SavingsAccountDetailsViewModel( } private fun extractDetails(savings: SavingsWithAssociations) { - val isActive = savings.status?.value == LoanStatus.ACTIVE.status - val isUpdate = savings.status?.value == LoanStatus.SUBMIT_AND_PENDING_APPROVAL.status + val isActive = savings.status?.value == SavingStatus.ACTIVE.status + val isUpdate = savings.status?.value == SavingStatus.SUBMIT_AND_PENDING_APPROVAL.status val currencyCode = savings.currency?.code val decimalPlaces = savings.currency?.decimalPlaces @@ -310,6 +274,7 @@ internal class SavingsAccountDetailsViewModel( updateState { it.copy( + savingStatus = SavingStatus.fromStatus(savings.status?.value ?: ""), isActive = isActive, isUpdatable = isUpdate, accountId = savings.id ?: -1L, @@ -334,7 +299,6 @@ internal class SavingsAccountDetailsViewModel( * @property isActive True if the account is active. * @property items List of quick action items (Deposit, Transfer, etc.) * @property isUpdatable user can update only when status is submit and pending approval - * @property isMenuExpanded True if the menu is expanded. * @property dialogState State representing dialogs like error, loading, etc. */ @Immutable @@ -346,13 +310,12 @@ internal data class SavingsAccountDetailsState( val product: String? = "", val displayItems: List = emptyList(), val transactionList: List = emptyList(), + val savingStatus: SavingStatus? = null, val isActive: Boolean = false, val items: ImmutableList, val isUpdatable: Boolean = false, - val isMenuExpanded: Boolean = false, - val dialogState: DialogState? = null, val networkStatus: Boolean = false, val uiState: ScreenUiState? = ScreenUiState.Loading, @@ -363,11 +326,29 @@ internal data class SavingsAccountDetailsState( sealed interface DialogState { /** Shown when an error occurs. */ data class Error(val message: String) : DialogState - - /** Shown when displaying transaction info. */ - data object TransactionInfo : DialogState } } +val SavingStatus.allowedActions: Set + get() = when (this) { + SavingStatus.ACTIVE -> setOf( + SavingsActionItems.Transactions, + SavingsActionItems.Charges, + SavingsActionItems.QrCode, + SavingsActionItems.Transfer, + ) + SavingStatus.INACTIVE -> setOf( + SavingsActionItems.Transfer, + SavingsActionItems.QrCode, + ) + SavingStatus.CLOSED -> setOf( + SavingsActionItems.QrCode, + SavingsActionItems.Transfer, + SavingsActionItems.Transactions, + ) + SavingStatus.SUBMIT_AND_PENDING_APPROVAL -> setOf( + SavingsActionItems.QrCode, + ) + } /** * One-time navigation or effect events for the SavingsAccountDetails screen. @@ -411,18 +392,6 @@ sealed interface SavingsAccountDetailsAction { /** Action to observe network status */ data class ReceiveNetworkStatus(val isOnline: Boolean) : SavingsAccountDetailsAction - data object OnTransactionsClick : SavingsAccountDetailsAction - - data object OnChargesClick : SavingsAccountDetailsAction - - data object OnQrCodeClick : SavingsAccountDetailsAction - - data object OnTransactionInfoClick : SavingsAccountDetailsAction - - data object ToggleMenu : SavingsAccountDetailsAction - - data object DismissMenu : SavingsAccountDetailsAction - /** * Internal-only actions such as results from repository calls. */ From bd97235babf4652331e620317380fe368f9c658a Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Fri, 24 Oct 2025 22:52:52 +0530 Subject: [PATCH 05/10] Update: added all the functionality properly --- .../commonMain/composeResources/values/strings.xml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/feature/savings-account/src/commonMain/composeResources/values/strings.xml b/feature/savings-account/src/commonMain/composeResources/values/strings.xml index 51a05fa0bd..bc4ab64ce4 100644 --- a/feature/savings-account/src/commonMain/composeResources/values/strings.xml +++ b/feature/savings-account/src/commonMain/composeResources/values/strings.xml @@ -95,13 +95,8 @@ Request to withdraw the account is failed. Please try again No Savings Accounts Found - Server issue from our side cannot proceed further, Try again after a moment - - Transactions - Charges - QR Code - Transaction Info - Account Options - Transaction Information + Server issue from our side cannot proceed further, Try again after a moment - \ No newline at end of file + + + \ No newline at end of file From 78927f71261a6253d8b70b71c5d901b1b3e93588 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sat, 25 Oct 2025 20:22:28 +0530 Subject: [PATCH 06/10] update --- .../SavingsAccountDetailsScreen.kt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 47d6a93a9d..16bd211fb4 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -80,12 +80,15 @@ internal fun SavingsAccountDetailsScreen( event.route == Constants.CHARGES -> { navigateToClientChargeScreen(ChargeType.SAVINGS.name, uiState.accountId) } + event.route == Constants.TRANSFER -> { navigateToTransferScreen(uiState.accountId) } + event.route == Constants.TRANSACTIONS -> { navigateToSavingsAccountTransactionScreen(uiState.accountId) } + event.route == Constants.QR_CODE -> { navigateToQrCodeScreen(viewModel.getQrString()) } @@ -101,17 +104,8 @@ internal fun SavingsAccountDetailsScreen( uiState.product, ) } + else -> { - SavingsAccountDetailsEvent.ShowTransactions -> { - navigateToSavingsAccountTransactionScreen(uiState.accountId) - } - - SavingsAccountDetailsEvent.ShowCharges -> { - navigateToClientChargeScreen(ChargeType.SAVINGS.name, uiState.accountId) - } - - SavingsAccountDetailsEvent.ShowQrCode -> { - navigateToQrCodeScreen(viewModel.getQrString()) } } } From 1ac0315a950a74f10f4ecbdaa47a8209dac4e2e3 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sat, 25 Oct 2025 20:29:24 +0530 Subject: [PATCH 07/10] update --- .../savingsAccountDetails/SavingsAccountDetailsScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 16bd211fb4..1177850760 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -105,7 +105,6 @@ internal fun SavingsAccountDetailsScreen( ) } else -> { - } } } From 395451f4bde065a9db97b64a0d6182419f522cd1 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sat, 25 Oct 2025 22:13:22 +0530 Subject: [PATCH 08/10] reolved issue --- .../savingsAccountDetails/SavingsAccountDetailsScreen.kt | 2 -- .../savingsAccountDetails/SavingsAccountDetailsViewModel.kt | 6 ------ 2 files changed, 8 deletions(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 1177850760..4c99bb8ac1 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -104,8 +104,6 @@ internal fun SavingsAccountDetailsScreen( uiState.product, ) } - else -> { - } } } diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt index be6282f822..58dca0473c 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt @@ -362,12 +362,6 @@ sealed interface SavingsAccountDetailsEvent { /** Trigger Update Amount */ data object UpdateAccount : SavingsAccountDetailsEvent - - data object ShowTransactions : SavingsAccountDetailsEvent - - data object ShowCharges : SavingsAccountDetailsEvent - - data object ShowQrCode : SavingsAccountDetailsEvent } /** From 75efe25b87f00a15fce739c9fe5fdc5261eefc2e Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sat, 25 Oct 2025 22:27:36 +0530 Subject: [PATCH 09/10] reolved issue --- .../savingsAccountDetails/SavingsAccountDetailsScreen.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 4c99bb8ac1..8b22ec9fab 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -299,8 +299,7 @@ internal fun SavingsAccountActions( FlowRow( modifier = Modifier.fillMaxWidth(), ) { - println("Visible Actions: $visibleActions") - visibleActions.forEach { item -> + visibleActions.forEach { item -> MifosActionCard( title = item.title, subTitle = item.subTitle, From 06f7d98f193aa4d4248b34844638d04cb0dd0ad2 Mon Sep 17 00:00:00 2001 From: Wizcoderr Date: Sat, 25 Oct 2025 22:31:13 +0530 Subject: [PATCH 10/10] reolved issue --- .../savingsAccountDetails/SavingsAccountDetailsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt index 8b22ec9fab..84ac892587 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsScreen.kt @@ -299,7 +299,7 @@ internal fun SavingsAccountActions( FlowRow( modifier = Modifier.fillMaxWidth(), ) { - visibleActions.forEach { item -> + visibleActions.forEach { item -> MifosActionCard( title = item.title, subTitle = item.subTitle,