From f04fb670545a4d7751e2cfb3ff376a8ce2fdd16b Mon Sep 17 00:00:00 2001 From: kalpesh Date: Sun, 31 Aug 2025 01:26:55 +0530 Subject: [PATCH 01/13] bare bone ui structure for the Recurring Deposit Account feature. --- .../RecurringDepositAccountRoute.kt | 4 + .../RecurringDepositAccountScreen.kt | 204 ++++++++++++++++++ .../RecurringDepositAccountViewModel.kt | 49 +++++ .../mifos/feature/client/di/ClientModule.kt | 2 + .../client/savingsAccounts/SavingsAccounts.kt | 1 + 5 files changed, 260 insertions(+) create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt new file mode 100644 index 00000000000..f7e317ffa68 --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt @@ -0,0 +1,4 @@ +package com.mifos.feature.client.clientRecurringDepositAccount + +class RecurringDepositAccountRoute { +} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt new file mode 100644 index 00000000000..7faf38cf14f --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt @@ -0,0 +1,204 @@ +package com.mifos.feature.client.clientRecurringDepositAccount + +import androidclient.feature.client.generated.resources.Res +import androidclient.feature.client.generated.resources.client_savings_item +import androidclient.feature.client.generated.resources.feature_client_dialog_action_ok +import androidclient.feature.client.generated.resources.filter +import androidclient.feature.client.generated.resources.search +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +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 +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.mifos.core.designsystem.component.MifosCircularProgress +import com.mifos.core.designsystem.component.MifosScaffold +import com.mifos.core.designsystem.theme.DesignToken +import com.mifos.core.designsystem.theme.MifosTypography +import com.mifos.core.ui.components.MifosActionsSavingsListingComponent +import com.mifos.core.ui.components.MifosEmptyCard +import com.mifos.core.ui.components.MifosErrorComponent +import com.mifos.core.ui.components.MifosProgressIndicator +import com.mifos.core.ui.util.EventsEffect +import com.mifos.feature.client.clientGeneral.ClientProfileGeneralState +import com.mifos.feature.client.savingsAccounts.SavingsAccountAction +import com.mifos.feature.client.savingsAccounts.SavingsAccountState +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource +import org.koin.compose.viewmodel.koinViewModel + + +@Composable +fun RecurringDepositAccountScreen( + navigateBack: () -> Unit, + modifier: Modifier = Modifier, + viewModel: RecurringDepositAccountViewModel = koinViewModel() +){ + val state by viewModel.stateFlow.collectAsStateWithLifecycle() + + EventsEffect(viewModel.eventFlow) { event -> + + when(event) { + is RecurringDepositAccountActions.ApproveAccount -> TODO() + RecurringDepositAccountEvent.onApproveAccount -> TODO() + RecurringDepositAccountEvent.onNavigateBack -> navigateBack + is RecurringDepositAccountEvent.onViewAccount -> TODO() + } + } + + RecurringDepositAccountDialog( + state, + onAction = remember(viewModel) { + {action-> viewModel.trySendAction(action) } + }, + ) + + RecurringDepositAccountScaffold( + state = state, + modifier = modifier, + onAction = remember(viewModel) { { viewModel.trySendAction(it) } }, + ) + +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun RecurringDepositAccountDialog( + state: RecurringDepositAccountState, + onAction: (RecurringDepositAccountActions) -> Unit, +) { + when (state.dialogState) { + is RecurringDepositAccountState.DialogState.Error -> { + AlertDialog( + title = { Text("Error") }, + text = { Text(text = state.dialogState.message) }, + confirmButton = { + TextButton( + onClick = { onAction.invoke(RecurringDepositAccountActions.CloseDialog) }, + ) { + Text(stringResource(Res.string.feature_client_dialog_action_ok)) + } + }, + onDismissRequest = {}, + ) + } + + RecurringDepositAccountState.DialogState.Loading -> MifosCircularProgress() + + else -> null + } +} + +@Composable +fun RecurringDepositAccountScaffold( + state: RecurringDepositAccountState, + modifier: Modifier = Modifier, + onAction: (RecurringDepositAccountActions) -> Unit +){ + MifosScaffold( + onBackPressed = {}, + modifier, + ) { paddingValues -> + + Column( + Modifier.fillMaxSize() + .padding(paddingValues) + ) { + + RecurringDepositAccountHeader( + "", + onSearch = {} + ) + + if (state.recurringDepositAccounts.isEmpty()) { + MifosEmptyCard(msg = "Click Here To View Filled State. ") + } else { + LazyColumn { + items(state.recurringDepositAccounts){ + MifosActionsSavingsListingComponent( + "1", + "", + "", + "", + emptyList() + ){ + + } + } + } + + } + } + + } + +} + + +@Composable +fun RecurringDepositAccountHeader( + totalItem: String, + modifier: Modifier = Modifier, + onSearch: () -> Unit +) { + Row( + modifier = modifier.fillMaxWidth() + .wrapContentHeight(), + ) { + Column { + Text( + text = "Recurring Deposit Accounts", + style = MifosTypography.titleMedium, + ) + + Text( + text = totalItem + " " + stringResource(Res.string.client_savings_item), + style = MifosTypography.labelMedium, + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier.wrapContentSize() + ) { + IconButton( + onClick = { + + }, + ) { + Icon( + painter = painterResource(Res.drawable.search), + contentDescription = null, + ) + } + + Spacer(modifier = Modifier.padding(DesignToken.padding.largeIncreased)) + + IconButton( + onClick = { }, + ) { + Icon( + painter = painterResource(Res.drawable.filter), + contentDescription = null, + ) + } + } + + } +} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt new file mode 100644 index 00000000000..ffde9e95315 --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -0,0 +1,49 @@ +package com.mifos.feature.client.clientRecurringDepositAccount + +import com.mifos.core.ui.util.BaseViewModel +import com.mifos.feature.client.clientGeneral.ClientProfileGeneralState + + +class RecurringDepositAccountViewModel( + +) : BaseViewModel( + initialState = RecurringDepositAccountState() + ){ + + override fun handleAction(action: RecurringDepositAccountActions) { + TODO("Not yet implemented") + } + +} + + +data class RecurringDepositAccountState( + val recurringDepositAccounts: List = emptyList(), + val dialogState: DialogState? = null, + val networkConnection: Boolean = false, +){ + sealed interface DialogState { + data class Error(val message: String) : DialogState + data object Loading : DialogState + } +} + +sealed class RecurringDepositAccountActions { + data object NavigateBack : RecurringDepositAccountActions() + data class ViewAccount(val accountId: Int) : RecurringDepositAccountActions() + data class ApproveAccount(val accountId: Int): RecurringDepositAccountEvent() + data object Refresh : RecurringDepositAccountActions() + data object ToggleFilter : RecurringDepositAccountActions() + data object ToggleSearch : RecurringDepositAccountActions() + data object Search : RecurringDepositAccountActions() + data class UpdateSearch(val query: String) : RecurringDepositAccountActions() + data object CloseDialog: RecurringDepositAccountActions() +} + +sealed class RecurringDepositAccountEvent { + data object onNavigateBack : RecurringDepositAccountEvent() + data class onViewAccount(val accountId: Int) : RecurringDepositAccountEvent() + data object onApproveAccount : RecurringDepositAccountEvent() +} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt index fb68e803fa4..45f7a0b913a 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt @@ -20,6 +20,7 @@ import com.mifos.feature.client.clientGeneral.ClientProfileGeneralViewmodel import com.mifos.feature.client.clientIdentifiers.ClientIdentifiersViewModel import com.mifos.feature.client.clientPinpoint.PinPointClientViewModel import com.mifos.feature.client.clientProfile.ClientProfileViewModel +import com.mifos.feature.client.clientRecurringDepositAccount.RecurringDepositAccountViewModel import com.mifos.feature.client.clientSignature.SignatureViewModel import com.mifos.feature.client.clientStaff.ClientStaffViewModel import com.mifos.feature.client.clientSurveyList.SurveyListViewModel @@ -54,5 +55,6 @@ val ClientModule = module { viewModelOf(::UpdateDefaultAccountViewModel) viewModelOf(::ClientClosureViewModel) viewModelOf(::SavingsAccountsViewModel) + viewModelOf(::RecurringDepositAccountViewModel) viewModelOf(::ClientCollateralViewModel) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt index 230ee157791..c2f878c5ee2 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt @@ -55,6 +55,7 @@ import com.mifos.core.ui.components.MifosSearchBar import com.mifos.core.ui.util.EventsEffect import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview import org.koin.compose.viewmodel.koinViewModel @Composable From 6ffcd9c02a9ca134191f9ad9a2ce2fff6201c98c Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 15:35:53 +0530 Subject: [PATCH 02/13] navigation and viewmodel setup. --- .../room/entities/accounts/ClientAccounts.kt | 1 + .../domain/useCases/CreateChargesUseCase.kt | 1 - .../core/network/services/ClientService.kt | 2 +- .../composeResources/values/strings.xml | 2 + .../RecurringDepositAccountRoute.kt | 4 - .../RecurringDepositAccountScreen.kt | 204 ----------- .../RecurringDepositAccountViewModel.kt | 49 --- .../mifos/feature/client/di/ClientModule.kt | 2 +- .../client/navigation/ClientNavigation.kt | 10 + .../RecurringDepositAccountRoute.kt | 36 ++ .../RecurringDepositAccountScreen.kt | 318 ++++++++++++++++++ .../RecurringDepositAccountViewModel.kt | 162 +++++++++ 12 files changed, 531 insertions(+), 260 deletions(-) delete mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt delete mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt delete mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt diff --git a/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/ClientAccounts.kt b/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/ClientAccounts.kt index 730a1ccf806..8ecc36c5096 100644 --- a/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/ClientAccounts.kt +++ b/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/ClientAccounts.kt @@ -19,6 +19,7 @@ data class ClientAccounts( var loanAccounts: List = emptyList(), var savingsAccounts: List = emptyList(), + ) : Parcelable { private fun getSavingsAccounts(wantRecurring: Boolean): List { val result: MutableList = ArrayList() diff --git a/core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateChargesUseCase.kt b/core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateChargesUseCase.kt index 6993bf36d76..6a7c6585f57 100644 --- a/core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateChargesUseCase.kt +++ b/core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateChargesUseCase.kt @@ -20,7 +20,6 @@ import kotlinx.coroutines.flow.flow class CreateChargesUseCase( private val repository: ChargeDialogRepository, ) { - operator fun invoke( clientId: Int, payload: ChargesPayload, diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt index f81bae337f1..310714d946c 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt @@ -284,7 +284,7 @@ interface ClientService { @Body payload: ProposeTransferRequest, ): HttpResponse - @POST("clients/{clientId}?command=updateSavingsAccount") + @POST("clients/{clientId}?command=updateSavingsdaAccount") suspend fun updateSavingsAccount( @Path("clientId") clientId: Int, @Body payload: UpdateSavingsAccountRequest, diff --git a/feature/client/src/commonMain/composeResources/values/strings.xml b/feature/client/src/commonMain/composeResources/values/strings.xml index 5628c42d83c..9622affae61 100644 --- a/feature/client/src/commonMain/composeResources/values/strings.xml +++ b/feature/client/src/commonMain/composeResources/values/strings.xml @@ -252,6 +252,8 @@ Collateral Data Check or update the account notes + + Recurring Deposit Accounts Gender diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt deleted file mode 100644 index f7e317ffa68..00000000000 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountRoute.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.mifos.feature.client.clientRecurringDepositAccount - -class RecurringDepositAccountRoute { -} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt deleted file mode 100644 index 7faf38cf14f..00000000000 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountScreen.kt +++ /dev/null @@ -1,204 +0,0 @@ -package com.mifos.feature.client.clientRecurringDepositAccount - -import androidclient.feature.client.generated.resources.Res -import androidclient.feature.client.generated.resources.client_savings_item -import androidclient.feature.client.generated.resources.feature_client_dialog_action_ok -import androidclient.feature.client.generated.resources.filter -import androidclient.feature.client.generated.resources.search -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -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 -import androidx.compose.ui.Modifier -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.mifos.core.designsystem.component.MifosCircularProgress -import com.mifos.core.designsystem.component.MifosScaffold -import com.mifos.core.designsystem.theme.DesignToken -import com.mifos.core.designsystem.theme.MifosTypography -import com.mifos.core.ui.components.MifosActionsSavingsListingComponent -import com.mifos.core.ui.components.MifosEmptyCard -import com.mifos.core.ui.components.MifosErrorComponent -import com.mifos.core.ui.components.MifosProgressIndicator -import com.mifos.core.ui.util.EventsEffect -import com.mifos.feature.client.clientGeneral.ClientProfileGeneralState -import com.mifos.feature.client.savingsAccounts.SavingsAccountAction -import com.mifos.feature.client.savingsAccounts.SavingsAccountState -import org.jetbrains.compose.resources.painterResource -import org.jetbrains.compose.resources.stringResource -import org.koin.compose.viewmodel.koinViewModel - - -@Composable -fun RecurringDepositAccountScreen( - navigateBack: () -> Unit, - modifier: Modifier = Modifier, - viewModel: RecurringDepositAccountViewModel = koinViewModel() -){ - val state by viewModel.stateFlow.collectAsStateWithLifecycle() - - EventsEffect(viewModel.eventFlow) { event -> - - when(event) { - is RecurringDepositAccountActions.ApproveAccount -> TODO() - RecurringDepositAccountEvent.onApproveAccount -> TODO() - RecurringDepositAccountEvent.onNavigateBack -> navigateBack - is RecurringDepositAccountEvent.onViewAccount -> TODO() - } - } - - RecurringDepositAccountDialog( - state, - onAction = remember(viewModel) { - {action-> viewModel.trySendAction(action) } - }, - ) - - RecurringDepositAccountScaffold( - state = state, - modifier = modifier, - onAction = remember(viewModel) { { viewModel.trySendAction(it) } }, - ) - -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun RecurringDepositAccountDialog( - state: RecurringDepositAccountState, - onAction: (RecurringDepositAccountActions) -> Unit, -) { - when (state.dialogState) { - is RecurringDepositAccountState.DialogState.Error -> { - AlertDialog( - title = { Text("Error") }, - text = { Text(text = state.dialogState.message) }, - confirmButton = { - TextButton( - onClick = { onAction.invoke(RecurringDepositAccountActions.CloseDialog) }, - ) { - Text(stringResource(Res.string.feature_client_dialog_action_ok)) - } - }, - onDismissRequest = {}, - ) - } - - RecurringDepositAccountState.DialogState.Loading -> MifosCircularProgress() - - else -> null - } -} - -@Composable -fun RecurringDepositAccountScaffold( - state: RecurringDepositAccountState, - modifier: Modifier = Modifier, - onAction: (RecurringDepositAccountActions) -> Unit -){ - MifosScaffold( - onBackPressed = {}, - modifier, - ) { paddingValues -> - - Column( - Modifier.fillMaxSize() - .padding(paddingValues) - ) { - - RecurringDepositAccountHeader( - "", - onSearch = {} - ) - - if (state.recurringDepositAccounts.isEmpty()) { - MifosEmptyCard(msg = "Click Here To View Filled State. ") - } else { - LazyColumn { - items(state.recurringDepositAccounts){ - MifosActionsSavingsListingComponent( - "1", - "", - "", - "", - emptyList() - ){ - - } - } - } - - } - } - - } - -} - - -@Composable -fun RecurringDepositAccountHeader( - totalItem: String, - modifier: Modifier = Modifier, - onSearch: () -> Unit -) { - Row( - modifier = modifier.fillMaxWidth() - .wrapContentHeight(), - ) { - Column { - Text( - text = "Recurring Deposit Accounts", - style = MifosTypography.titleMedium, - ) - - Text( - text = totalItem + " " + stringResource(Res.string.client_savings_item), - style = MifosTypography.labelMedium, - ) - } - - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier.wrapContentSize() - ) { - IconButton( - onClick = { - - }, - ) { - Icon( - painter = painterResource(Res.drawable.search), - contentDescription = null, - ) - } - - Spacer(modifier = Modifier.padding(DesignToken.padding.largeIncreased)) - - IconButton( - onClick = { }, - ) { - Icon( - painter = painterResource(Res.drawable.filter), - contentDescription = null, - ) - } - } - - } -} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt deleted file mode 100644 index ffde9e95315..00000000000 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientRecurringDepositAccount/RecurringDepositAccountViewModel.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.mifos.feature.client.clientRecurringDepositAccount - -import com.mifos.core.ui.util.BaseViewModel -import com.mifos.feature.client.clientGeneral.ClientProfileGeneralState - - -class RecurringDepositAccountViewModel( - -) : BaseViewModel( - initialState = RecurringDepositAccountState() - ){ - - override fun handleAction(action: RecurringDepositAccountActions) { - TODO("Not yet implemented") - } - -} - - -data class RecurringDepositAccountState( - val recurringDepositAccounts: List = emptyList(), - val dialogState: DialogState? = null, - val networkConnection: Boolean = false, -){ - sealed interface DialogState { - data class Error(val message: String) : DialogState - data object Loading : DialogState - } -} - -sealed class RecurringDepositAccountActions { - data object NavigateBack : RecurringDepositAccountActions() - data class ViewAccount(val accountId: Int) : RecurringDepositAccountActions() - data class ApproveAccount(val accountId: Int): RecurringDepositAccountEvent() - data object Refresh : RecurringDepositAccountActions() - data object ToggleFilter : RecurringDepositAccountActions() - data object ToggleSearch : RecurringDepositAccountActions() - data object Search : RecurringDepositAccountActions() - data class UpdateSearch(val query: String) : RecurringDepositAccountActions() - data object CloseDialog: RecurringDepositAccountActions() -} - -sealed class RecurringDepositAccountEvent { - data object onNavigateBack : RecurringDepositAccountEvent() - data class onViewAccount(val accountId: Int) : RecurringDepositAccountEvent() - data object onApproveAccount : RecurringDepositAccountEvent() -} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt index 45f7a0b913a..5e90aaa7b76 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt @@ -20,7 +20,7 @@ import com.mifos.feature.client.clientGeneral.ClientProfileGeneralViewmodel import com.mifos.feature.client.clientIdentifiers.ClientIdentifiersViewModel import com.mifos.feature.client.clientPinpoint.PinPointClientViewModel import com.mifos.feature.client.clientProfile.ClientProfileViewModel -import com.mifos.feature.client.clientRecurringDepositAccount.RecurringDepositAccountViewModel +import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountViewModel import com.mifos.feature.client.clientSignature.SignatureViewModel import com.mifos.feature.client.clientStaff.ClientStaffViewModel import com.mifos.feature.client.clientSurveyList.SurveyListViewModel diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt index 9bdad65cd8b..70eb5944c73 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt @@ -48,6 +48,9 @@ import com.mifos.feature.client.clientUpdateDefaultAccount.navigateToUpdateDefau import com.mifos.feature.client.clientUpdateDefaultAccount.updateDefaultAccountDestination import com.mifos.feature.client.clientsList.ClientListScreen import com.mifos.feature.client.createNewClient.CreateNewClientScreen +import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountEvent +import com.mifos.feature.client.recurringDepositAccount.clientRecurringDepositAccountDestination +import com.mifos.feature.client.recurringDepositAccount.navigateToRecurringDepositAccountRoute import com.mifos.feature.client.savingsAccounts.navigateToClientSavingsAccountsRoute import com.mifos.feature.client.savingsAccounts.savingsAccountsDestination import com.mifos.room.entities.accounts.savings.SavingAccountDepositTypeEntity @@ -136,6 +139,13 @@ fun NavGraphBuilder.clientNavGraph( savingAccounts = { clientId -> navController.navigateToClientSavingsAccountsRoute(clientId) }, + recurringDepositAccounts = {clientId-> + navController.navigateToRecurringDepositAccountRoute(clientId) + } + ) + + clientRecurringDepositAccountDestination( + navigateBack = navController::popBackStack ) clientProfileDetailsDestination( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt new file mode 100644 index 00000000000..44f4260f257 --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt @@ -0,0 +1,36 @@ +package com.mifos.feature.client.recurringDepositAccount + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import kotlinx.serialization.Serializable + +@Serializable +data class RecurringDepositAccountRoute( + val clientId: Int = -1 +) + + +fun NavGraphBuilder.clientRecurringDepositAccountDestination( + navigateBack: () -> Unit, + onApproveAccount: (Int) -> Unit ={}, + onViewAccount: (Int) -> Unit ={}, +){ + composable{ + RecurringDepositAccountScreen( + navigateBack = navigateBack, + onApproveAccount = { + onApproveAccount(it) + }, + onViewAccount = { + onViewAccount(it) + } + ) + } +} + +fun NavController.navigateToRecurringDepositAccountRoute( + clientId: Int, +) { + this.navigate(RecurringDepositAccountRoute(clientId = clientId)) +} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt new file mode 100644 index 00000000000..ee9a70b3c9d --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -0,0 +1,318 @@ +package com.mifos.feature.client.recurringDepositAccount + +import androidclient.feature.client.generated.resources.Res +import androidclient.feature.client.generated.resources.client_profile_recurring_deposit_account_title +import androidclient.feature.client.generated.resources.client_savings_item +import androidclient.feature.client.generated.resources.client_savings_not_avilable +import androidclient.feature.client.generated.resources.client_savings_pending_approval +import androidclient.feature.client.generated.resources.feature_client_dialog_action_ok +import androidclient.feature.client.generated.resources.filter +import androidclient.feature.client.generated.resources.search +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +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 +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.mifos.core.common.utils.DateHelper +import com.mifos.core.designsystem.component.MifosCircularProgress +import com.mifos.core.designsystem.component.MifosScaffold +import com.mifos.core.designsystem.theme.DesignToken +import com.mifos.core.designsystem.theme.MifosTypography +import com.mifos.core.ui.components.Actions +import com.mifos.core.ui.components.MifosActionsSavingsListingComponent +import com.mifos.core.ui.components.MifosEmptyCard +import com.mifos.core.ui.components.MifosSearchBar +import com.mifos.core.ui.util.EventsEffect +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource +import org.koin.compose.viewmodel.koinViewModel + + +@Composable +fun RecurringDepositAccountScreen( + navigateBack: () -> Unit, + modifier: Modifier = Modifier, + onApproveAccount: (Int) -> Unit = {}, + onViewAccount: (Int) -> Unit = {}, + viewModel: RecurringDepositAccountViewModel = koinViewModel(), +) { + val state by viewModel.stateFlow.collectAsStateWithLifecycle() + + EventsEffect(viewModel.eventFlow) { event -> + when (event) { + is RecurringDepositAccountEvent.onApproveAccount -> { + onApproveAccount(event.accountId) + } + + RecurringDepositAccountEvent.onNavigateBack -> navigateBack + is RecurringDepositAccountEvent.onViewAccount -> { + onViewAccount(event.accountId) + } + } + } + + val action: (RecurringDepositAccountAction) -> Unit = remember(viewModel) { + { + when (it) { + RecurringDepositAccountAction.CloseDialog -> { + viewModel.trySendAction(RecurringDepositAccountAction.CloseDialog) + } + + RecurringDepositAccountAction.NavigateBack -> { + viewModel.trySendAction(RecurringDepositAccountAction.NavigateBack) + } + + RecurringDepositAccountAction.Refresh -> { + viewModel.trySendAction(RecurringDepositAccountAction.Refresh) + } + + is RecurringDepositAccountAction.Search -> { + viewModel.trySendAction( + RecurringDepositAccountAction.Search(it.query), + ) + } + + RecurringDepositAccountAction.ToggleFilter -> { + viewModel.trySendAction(RecurringDepositAccountAction.ToggleFilter) + } + + RecurringDepositAccountAction.ToggleSearch -> { + viewModel.trySendAction(RecurringDepositAccountAction.ToggleSearch) + } + + is RecurringDepositAccountAction.UpdateSearch -> { + viewModel.trySendAction( + RecurringDepositAccountAction.UpdateSearch(it.query), + ) + } + + is RecurringDepositAccountAction.ViewAccount -> { + viewModel.trySendAction( + RecurringDepositAccountAction.ViewAccount(it.accountId), + ) + } + + is RecurringDepositAccountAction.ApproveAccount -> { + viewModel.trySendAction( + RecurringDepositAccountAction.ApproveAccount(it.accountId), + ) + } + } + } + } + + + RecurringDepositAccountDialog( + state, + onCloseDialog = { + action(RecurringDepositAccountAction.CloseDialog) + }, + ) + + RecurringDepositAccountScaffold( + state = state, + onNavigateBack = navigateBack, + modifier = modifier, + onSearchClick = { + action(RecurringDepositAccountAction.Search(it)) + }, + onToggleFilter = { action(RecurringDepositAccountAction.ToggleFilter) }, + onToggleSearch = { action(RecurringDepositAccountAction.ToggleSearch) }, + onViewAccount = { + action(RecurringDepositAccountAction.ViewAccount(accountId = state.clientId)) + }, + onApproveAccount = { + action(RecurringDepositAccountAction.ApproveAccount(accountId = state.clientId)) + }, + ) + +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun RecurringDepositAccountDialog( + state: RecurringDepositAccountState, + onCloseDialog: () -> Unit, +) { + when (state.dialogState) { + is RecurringDepositAccountState.DialogState.Error -> { + AlertDialog( + title = { Text("Error") }, + text = { Text(text = state.dialogState.message) }, + confirmButton = { + TextButton( + onClick = onCloseDialog, + ) { + Text(stringResource(Res.string.feature_client_dialog_action_ok)) + } + }, + onDismissRequest = {}, + ) + } + + RecurringDepositAccountState.DialogState.Loading -> MifosCircularProgress() + + else -> null + } +} + +@Composable +internal fun RecurringDepositAccountScaffold( + state: RecurringDepositAccountState, + onNavigateBack: () -> Unit, + modifier: Modifier = Modifier, + onSearchClick: (String) -> Unit = {}, + onUpdateSearch: (String) -> Unit = {}, + onToggleFilter: () -> Unit = {}, + onToggleSearch: () -> Unit = {}, + onViewAccount: () -> Unit = {}, + onApproveAccount: () -> Unit = {}, +) { + MifosScaffold( + onBackPressed = onNavigateBack, + modifier = modifier, + title = "", + ) { paddingValues -> + + Column( + Modifier.fillMaxSize() + .padding(paddingValues) + .padding( + vertical = DesignToken.padding.extraLarge, + horizontal = DesignToken.padding.large, + ), + ) { + val notAvailableText = stringResource(Res.string.client_savings_not_avilable) + RecurringDepositAccountHeader( + state.recurringDepositAccounts.size.toString(), + onToggleSearch = onToggleSearch, + onToggleFilter = onToggleFilter, + ) + + // todo implement search bar functionality + if (state.isSearchBarActive) { + MifosSearchBar( + query = state.searchText, + onQueryChange = { + onUpdateSearch(it) + }, + onSearchClick = { + onSearchClick(it) + }, + onBackClick = onToggleSearch, + ) + } + + Spacer(modifier = Modifier.height(DesignToken.padding.large)) + + if (state.recurringDepositAccounts.isEmpty()) { + MifosEmptyCard(msg = "Click Here To View Filled State. ") + } else { + LazyColumn { + items(state.recurringDepositAccounts) { recurringDeposit -> + MifosActionsSavingsListingComponent( + recurringDeposit.accountNo ?: notAvailableText, + recurringDeposit.productName ?: notAvailableText, + if (recurringDeposit.status?.submittedAndPendingApproval == true) { + stringResource(Res.string.client_savings_pending_approval) + } else if (recurringDeposit.lastActiveTransactionDate != null) { + DateHelper.getDateAsString(recurringDeposit.lastActiveTransactionDate!!) + } else { + notAvailableText + }, + recurringDeposit.accountBalance?.toString() ?: notAvailableText, + if (recurringDeposit.status?.submittedAndPendingApproval == true) { + listOf( + Actions.ViewAccount, + Actions.ApproveAccount, + ) + } else { + listOf( + Actions.ViewAccount, + ) + }, + ) { actions -> + when (actions) { + Actions.ViewAccount -> onApproveAccount + Actions.ApproveAccount -> onViewAccount + else -> null + } + + } + } + } + + } + } + + } + +} + + +@Composable +internal fun RecurringDepositAccountHeader( + totalItem: String, + modifier: Modifier = Modifier, + onToggleFilter: () -> Unit = {}, + onToggleSearch: () -> Unit = {}, +) { + Row( + modifier = modifier.fillMaxWidth() + .wrapContentHeight(), + ) { + Column { + Text( + text = stringResource(Res.string.client_profile_recurring_deposit_account_title), + style = MifosTypography.titleMedium, + ) + + Text( + text = totalItem + " " + stringResource(Res.string.client_savings_item), + style = MifosTypography.labelMedium, + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + Row( + Modifier, + horizontalArrangement = Arrangement.spacedBy(DesignToken.padding.largeIncreased), + ) { + Icon( + painter = painterResource(Res.drawable.search), + contentDescription = null, + modifier = Modifier.clickable { + onToggleSearch.invoke() + }, + ) + + Icon( + painter = painterResource(Res.drawable.filter), + contentDescription = null, + modifier = Modifier.clickable { + onToggleFilter.invoke() + }, + ) + } + + } +} \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt new file mode 100644 index 00000000000..d4e84a6a92e --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -0,0 +1,162 @@ +package com.mifos.feature.client.recurringDepositAccount + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.navigation.toRoute +import com.mifos.core.common.utils.DataState +import com.mifos.core.domain.useCases.GetClientDetailsUseCase +import com.mifos.core.ui.util.BaseViewModel +import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountEvent.* +import com.mifos.room.entities.accounts.savings.SavingsAccountEntity +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch + + +class RecurringDepositAccountViewModel( + savedStateHandle: SavedStateHandle, + private val getClientDetailsUseCase: GetClientDetailsUseCase, +) : BaseViewModel( + initialState = RecurringDepositAccountState() +){ + + val route = savedStateHandle.toRoute() + + init { + getRecurringDepositAccounts() + } + + override fun handleAction(action: RecurringDepositAccountAction) { + when(action){ + RecurringDepositAccountAction.CloseDialog -> { + mutableStateFlow.update { + it.copy(dialogState = null) + } + } + is RecurringDepositAccountAction.NavigateBack -> { + sendEvent(RecurringDepositAccountEvent.onNavigateBack) + } + is RecurringDepositAccountAction.Refresh -> { + getRecurringDepositAccounts() + } + is RecurringDepositAccountAction.Search -> { + getRecurringDepositAccounts() + } + is RecurringDepositAccountAction.ToggleFilter -> { + mutableStateFlow.update { + it.copy( + isFilterDialogOpen = true + ) + } + } + is RecurringDepositAccountAction.ToggleSearch -> { + mutableStateFlow.update { + it.copy( + isSearchBarActive = true, + ) + } + } + is RecurringDepositAccountAction.UpdateSearch -> { + mutableStateFlow.update { + it.copy( + searchText = action.query, + ) + } + } + is RecurringDepositAccountAction.ViewAccount -> { + sendEvent( + onViewAccount(action.accountId) + ) + } + + is RecurringDepositAccountAction.ApproveAccount -> { + sendEvent( + onApproveAccount(action.accountId) + ) + } + } + } + + private fun getRecurringDepositAccounts() { + viewModelScope.launch { + getClientDetailsUseCase.invoke(route.clientId).collect { result-> + when(result){ + is DataState.Error -> { + mutableStateFlow.update { + it.copy(dialogState = RecurringDepositAccountState.DialogState.Error(result.message)) + } + } + is DataState.Loading -> { + mutableStateFlow.update { + it.copy(dialogState = RecurringDepositAccountState.DialogState.Loading) + } + } + is DataState.Success -> { + val recurringDepositAccount = result.data.clientAccounts?.savingsAccounts?.let { + it.filter {accountEntity -> + accountEntity.depositType?.isRecurring==true + }.apply { + // Todo modify search accordingly + searchRecurringDepositAccounts(state.searchText, this) + } + } ?: emptyList() + + mutableStateFlow.update { + it.copy( + dialogState = null, + clientId = route.clientId, + recurringDepositAccounts = recurringDepositAccount + ) + } + } + } + } + } + } + + private fun searchRecurringDepositAccounts( + query: String, + recurringDepositAccounts: List + ): List { + if(query.isNotBlank()) { + return recurringDepositAccounts.filter { accountEntity -> + accountEntity.accountNo.toString().contains(state.searchText.trim()) + } + } + return recurringDepositAccounts + } +} + + +data class RecurringDepositAccountState( + val clientId: Int = -1, + val recurringDepositAccounts: List = emptyList(), + val searchText: String = "", + val dialogState: DialogState? = null, + val isSearchBarActive: Boolean = false, + val isFilterDialogOpen: Boolean = false, +){ + sealed interface DialogState { + data class Error(val message: String) : DialogState + data object Loading : DialogState + } +} + +sealed class RecurringDepositAccountAction { + data object NavigateBack : RecurringDepositAccountAction() + data class ViewAccount(val accountId: Int) : RecurringDepositAccountAction() + data class ApproveAccount(val accountId: Int): RecurringDepositAccountAction() + data object Refresh : RecurringDepositAccountAction() + data object ToggleFilter : RecurringDepositAccountAction() + data object ToggleSearch : RecurringDepositAccountAction() + data class Search(val query: String) : RecurringDepositAccountAction() + data class UpdateSearch(val query: String) : RecurringDepositAccountAction() + data object CloseDialog: RecurringDepositAccountAction() +} + +sealed class RecurringDepositAccountEvent { + data object onNavigateBack : RecurringDepositAccountEvent() + data class onViewAccount(val accountId: Int) : RecurringDepositAccountEvent() + data class onApproveAccount(val accountId: Int) : RecurringDepositAccountEvent() +} \ No newline at end of file From da34a52a4daeb16d18f79bcfa146b800decdd878 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 17:57:02 +0530 Subject: [PATCH 03/13] added some parameters to SavingsAccountEntity and GetClientsSavingsAccounts and GetClientsClientIdAccountMapper to fetch some values. Also added color to the MifosActionsListingCardComponent and removed account number label. --- .../accounts/savings/SavingsAccountEntity.kt | 2 + .../GetClientsClientIdAccountMapper.kt | 3 ++ .../model/GetClientsSavingsAccounts.kt | 2 + .../MifosActionsListingCardComponent.kt | 20 ++++--- .../ui/components/MifosListingComponent.kt | 15 +++++- .../ClientProfileGeneralScreen.kt | 21 ++++++-- .../ClientProfileGeneralViewmodel.kt | 22 +++++--- .../RecurringDepositAccountScreen.kt | 54 +++++++++---------- .../RecurringDepositAccountViewModel.kt | 9 ++-- .../client/savingsAccounts/SavingsAccounts.kt | 3 +- .../SavingsAccountsViewModel.kt | 5 ++ 11 files changed, 101 insertions(+), 55 deletions(-) diff --git a/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/savings/SavingsAccountEntity.kt b/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/savings/SavingsAccountEntity.kt index 223daa9972a..a3593e8623c 100644 --- a/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/savings/SavingsAccountEntity.kt +++ b/core/database/src/commonMain/kotlin/com/mifos/room/entities/accounts/savings/SavingsAccountEntity.kt @@ -71,6 +71,8 @@ data class SavingsAccountEntity( val productId: Int? = null, + val shortProductName: String? = null, + val productName: String? = null, @ColumnInfo(index = true, name = INHERIT_FIELD_NAME, typeAffinity = UNDEFINED, collate = UNSPECIFIED, defaultValue = VALUE_UNSPECIFIED) diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/GetClientsClientIdAccountMapper.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/GetClientsClientIdAccountMapper.kt index 676293ed411..cc6436238c7 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/GetClientsClientIdAccountMapper.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/GetClientsClientIdAccountMapper.kt @@ -39,7 +39,9 @@ object GetClientsClientIdAccountMapper : SavingsAccountEntity( id = it.id?.toInt(), accountNo = it.accountNo, + accountBalance = it.accountBalance, productId = it.productId?.toInt(), + shortProductName = it.shortProductName, productName = it.productName, depositType = it.depositType?.let { deposit -> SavingAccountDepositTypeEntity( @@ -115,6 +117,7 @@ object GetClientsClientIdAccountMapper : GetClientsSavingsAccounts( id = it.id?.toLong(), accountNo = it.accountNo, + accountBalance = it.accountBalance, productId = it.productId?.toLong(), productName = it.productName, depositType = GetClientsSavingsAccountsDepositType( diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientsSavingsAccounts.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientsSavingsAccounts.kt index 86a2d977e18..c7913858e9d 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientsSavingsAccounts.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientsSavingsAccounts.kt @@ -29,6 +29,8 @@ data class GetClientsSavingsAccounts( val accountNo: String? = null, + val accountBalance: Double? = null, + val currency: GetClientsSavingsAccountsCurrency? = null, val depositType: GetClientsSavingsAccountsDepositType? = null, diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt index f68e41e1567..88bb8a332ee 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt @@ -28,12 +28,12 @@ import androidclient.core.ui.generated.resources.core_ui_original_loan import androidclient.core.ui.generated.resources.core_ui_outstanding import androidclient.core.ui.generated.resources.core_ui_paid import androidclient.core.ui.generated.resources.core_ui_quantity -import androidclient.core.ui.generated.resources.core_ui_savings_product import androidclient.core.ui.generated.resources.core_ui_status import androidclient.core.ui.generated.resources.core_ui_total_collateral_value import androidclient.core.ui.generated.resources.core_ui_total_value import androidclient.core.ui.generated.resources.core_ui_type import androidclient.core.ui.generated.resources.core_ui_waived +import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -353,6 +353,7 @@ fun MifosActionsLoanListingComponent( fun MifosActionsSavingsListingComponent( accountNo: String, savingsProduct: String, + savingsProductName: String, lastActive: String, balance: String, menuList: List, @@ -368,15 +369,16 @@ fun MifosActionsSavingsListingComponent( modifier = Modifier.padding(DesignToken.padding.large), ) { MifosListingRowItem( - key = stringResource(Res.string.core_ui_account_no), + key = "", value = accountNo, - keyStyle = MifosTypography.titleSmallEmphasized, - valueStyle = MifosTypography.titleSmall, + valueStyle = MifosTypography.titleSmallEmphasized, ) Spacer(Modifier.height(DesignToken.padding.large)) MifosListingRowItem( - key = stringResource(Res.string.core_ui_savings_product), - value = savingsProduct, + key = savingsProduct, + value = savingsProductName, + keyStyle = MifosTypography.titleSmallEmphasized, + valueStyle = MifosTypography.titleSmall, ) Spacer(Modifier.height(DesignToken.padding.medium)) Column( @@ -401,11 +403,12 @@ fun MifosActionsSavingsListingComponent( bottomStart = DesignToken.padding.medium, bottomEnd = DesignToken.padding.medium, ), + color = MaterialTheme.colorScheme.surfaceContainer ) { Column( modifier = Modifier.padding( vertical = DesignToken.padding.small, - ), + ) ) { menuList.map { menuItem -> Row( @@ -601,7 +604,8 @@ fun PreviewMifosActionsSavingsListingComponent() { MaterialTheme { MifosActionsSavingsListingComponent( accountNo = "SV9876", - savingsProduct = "Regular Savings", + savingsProduct = "Savings Product", + savingsProductName = "Wallet", lastActive = "2025-08-15", balance = "$1200", menuList = listOf( diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt index 6f5f410aa32..2ffd249b6c3 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt @@ -61,6 +61,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.mifos.core.designsystem.theme.AppColors import com.mifos.core.designsystem.theme.DesignToken @@ -116,10 +117,20 @@ fun MifosListingRowItem( MifosListingRowItem( keyContent = { if (key.isNotBlank()) { - Text(text = "$key:", style = keyStyle) + Text( + text = "$key:", style = keyStyle, + maxLines =1, + overflow = TextOverflow.Clip, + ) } }, - valueContent = { Text(text = value, style = valueStyle.copy(color = valueColor)) }, + valueContent = { + Text( + text = value, style = valueStyle.copy(color = valueColor), + overflow = TextOverflow.Clip, + maxLines = 1 + ) + }, ) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt index ca1178e0574..47146531f8b 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt @@ -18,6 +18,7 @@ import androidclient.feature.client.generated.resources.client_performance_histo import androidclient.feature.client.generated.resources.client_profile_general_header_actions import androidclient.feature.client.generated.resources.client_profile_general_header_linked_accounts import androidclient.feature.client.generated.resources.client_profile_general_header_performance_history +import androidclient.feature.client.generated.resources.client_savings_not_avilable import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -239,28 +240,38 @@ fun PerformanceHistoryCard(state: ClientProfileGeneralState) { val performanceHistory = state.performanceHistory PerformanceHistoryRows( stringResource(Res.string.client_performance_history_loan_cycle_count_label), - "${performanceHistory.loanCyclesCount}", + performanceHistory.loanCyclesCount?.toString()?: + stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_active_loans_count_label), - "${performanceHistory.activeLoans}", + performanceHistory.activeLoans?.toString() ?: + stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_last_loan_amount_label), - "${state.currency} ${performanceHistory.lastLoanAmount}", + + performanceHistory.lastLoanAmount?.let{ + state.currency +" "+ it.toString() + } ?: + stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_active_savings_label), - "${performanceHistory.activeSavingsCount}", + performanceHistory.activeSavingsCount?.toString() ?: + stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_total_savings_label), - "${state.currency} ${performanceHistory.lastLoanAmount}", + performanceHistory.totalSaving?.let{ + state.currency +" "+ it.toString() + } ?: + stringResource(Res.string.client_savings_not_avilable), ) } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt index a4d0c5d27a4..5bda576025b 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt @@ -17,6 +17,7 @@ import com.mifos.core.data.util.NetworkMonitor import com.mifos.core.domain.useCases.GetClientDetailsUseCase import com.mifos.core.ui.util.BaseViewModel import com.mifos.feature.client.clientGeneral.ClientProfileGeneralEvent.OnActionClick +import com.mifos.room.entities.accounts.savings.SavingAccountDepositTypeEntity import com.mifos.room.entities.client.ClientEntity import com.mifos.room.entities.zipmodels.ClientAndClientAccounts import kotlinx.coroutines.flow.update @@ -58,11 +59,16 @@ internal class ClientProfileGeneralViewmodel( val activeSavingsCount = savingAccounts?.count { it.status?.active == true } ?: 0 val totalSaving = - savingAccounts?.filter { it.status?.active == true }?.sumOf { it.accountBalance ?: 0.0 } - ?: 0.0 + savingAccounts?.filter { + it.status?.active == true && + it.depositType?.serverType!= SavingAccountDepositTypeEntity.ServerTypes.RECURRING && + it.status?.closed == false + }?.sumOf { + it.accountBalance ?: 0.0 + } // TODO: No function yet created for calculating this value. - val lastLoanAmount = 0.0 + val lastLoanAmount = null return ClientProfileGeneralState.PerformanceHistory( loanCyclesCount = loanCyclesCount, @@ -148,11 +154,11 @@ data class ClientProfileGeneralState( } data class PerformanceHistory( - var loanCyclesCount: Int = 0, - var activeLoans: Int = 0, - var lastLoanAmount: Double = 0.0, - var activeSavingsCount: Int = 0, - var totalSaving: Double = 0.0, + var loanCyclesCount: Int? = null, + var activeLoans: Int? = null, + var lastLoanAmount: Double? = null, + var activeSavingsCount: Int? = null, + var totalSaving: Double? = null, ) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index ee9a70b3c9d..e4e19276f83 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -148,7 +149,7 @@ fun RecurringDepositAccountScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun RecurringDepositAccountDialog( +internal fun RecurringDepositAccountDialog( state: RecurringDepositAccountState, onCloseDialog: () -> Unit, ) { @@ -221,7 +222,7 @@ internal fun RecurringDepositAccountScaffold( ) } - Spacer(modifier = Modifier.height(DesignToken.padding.large)) + Spacer(modifier = Modifier.height(DesignToken.padding.largeIncreasedExtra)) if (state.recurringDepositAccounts.isEmpty()) { MifosEmptyCard(msg = "Click Here To View Filled State. ") @@ -229,17 +230,18 @@ internal fun RecurringDepositAccountScaffold( LazyColumn { items(state.recurringDepositAccounts) { recurringDeposit -> MifosActionsSavingsListingComponent( - recurringDeposit.accountNo ?: notAvailableText, - recurringDeposit.productName ?: notAvailableText, - if (recurringDeposit.status?.submittedAndPendingApproval == true) { + accountNo = recurringDeposit.accountNo ?: notAvailableText, + savingsProduct = "Recurring Deposit Product", + savingsProductName = recurringDeposit.shortProductName ?: notAvailableText, + lastActive = if (recurringDeposit.status?.submittedAndPendingApproval == true) { stringResource(Res.string.client_savings_pending_approval) } else if (recurringDeposit.lastActiveTransactionDate != null) { DateHelper.getDateAsString(recurringDeposit.lastActiveTransactionDate!!) } else { notAvailableText }, - recurringDeposit.accountBalance?.toString() ?: notAvailableText, - if (recurringDeposit.status?.submittedAndPendingApproval == true) { + balance = recurringDeposit.accountBalance?.toString() ?: notAvailableText, + menuList = if (recurringDeposit.status?.submittedAndPendingApproval == true) { listOf( Actions.ViewAccount, Actions.ApproveAccount, @@ -264,7 +266,6 @@ internal fun RecurringDepositAccountScaffold( } } - } @@ -293,26 +294,23 @@ internal fun RecurringDepositAccountHeader( Spacer(modifier = Modifier.weight(1f)) - Row( - Modifier, - horizontalArrangement = Arrangement.spacedBy(DesignToken.padding.largeIncreased), - ) { - Icon( - painter = painterResource(Res.drawable.search), - contentDescription = null, - modifier = Modifier.clickable { - onToggleSearch.invoke() - }, - ) - - Icon( - painter = painterResource(Res.drawable.filter), - contentDescription = null, - modifier = Modifier.clickable { - onToggleFilter.invoke() - }, - ) - } + Icon( + painter = painterResource(Res.drawable.search), + contentDescription = null, + modifier = Modifier.clickable { + onToggleSearch.invoke() + }, + ) + + Spacer(modifier = Modifier.width(DesignToken.spacing.largeIncreased)) + + Icon( + painter = painterResource(Res.drawable.filter), + contentDescription = null, + modifier = Modifier.clickable { + onToggleFilter.invoke() + }, + ) } } \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt index d4e84a6a92e..51363302ced 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -7,6 +7,7 @@ import com.mifos.core.common.utils.DataState import com.mifos.core.domain.useCases.GetClientDetailsUseCase import com.mifos.core.ui.util.BaseViewModel import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountEvent.* +import com.mifos.room.entities.accounts.savings.SavingAccountDepositTypeEntity import com.mifos.room.entities.accounts.savings.SavingsAccountEntity import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -35,7 +36,7 @@ class RecurringDepositAccountViewModel( } } is RecurringDepositAccountAction.NavigateBack -> { - sendEvent(RecurringDepositAccountEvent.onNavigateBack) + sendEvent(onNavigateBack) } is RecurringDepositAccountAction.Refresh -> { getRecurringDepositAccounts() @@ -95,7 +96,9 @@ class RecurringDepositAccountViewModel( is DataState.Success -> { val recurringDepositAccount = result.data.clientAccounts?.savingsAccounts?.let { it.filter {accountEntity -> - accountEntity.depositType?.isRecurring==true + accountEntity.depositType?.serverType == + SavingAccountDepositTypeEntity.ServerTypes.RECURRING && + accountEntity.status?.closed == false }.apply { // Todo modify search accordingly searchRecurringDepositAccounts(state.searchText, this) @@ -130,7 +133,7 @@ class RecurringDepositAccountViewModel( data class RecurringDepositAccountState( - val clientId: Int = -1, + val clientId: Int = -1, val recurringDepositAccounts: List = emptyList(), val searchText: String = "", val dialogState: DialogState? = null, diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt index c2f878c5ee2..50a28881123 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt @@ -124,7 +124,8 @@ fun SavingsAccountsScreen( items(state.savingsAccounts) { savings -> MifosActionsSavingsListingComponent( accountNo = savings.accountNo.toString(), - savingsProduct = savings.productName.toString(), + savingsProduct = "Savings Product: ", + savingsProductName = savings.productName.toString(), // todo modify with currency symbol when not getting null from api, currently getting null balance = if (savings.accountBalance != null) { savings.accountBalance.toString() diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt index c6f1097e925..1b50235f216 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt @@ -14,6 +14,7 @@ import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.mifos.core.data.repository.ClientDetailsRepository import com.mifos.core.ui.util.BaseViewModel +import com.mifos.room.entities.accounts.savings.SavingAccountDepositTypeEntity import com.mifos.room.entities.accounts.savings.SavingsAccountEntity import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -83,6 +84,10 @@ internal class SavingsAccountsViewModel( // Todo modify search accordingly val savingsAccounts = repository.getClientAccounts(route.clientId) .savingsAccounts + .filter {accountEntity -> + accountEntity.depositType?.serverType == SavingAccountDepositTypeEntity.ServerTypes.SAVINGS && + accountEntity.status?.closed == false + } .filter { it.accountNo?.contains(state.searchText.trim()) == true } mutableStateFlow.update { From f1097f7786989c5770a541d32090a89ed5090056 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 18:27:08 +0530 Subject: [PATCH 04/13] added some parameters to SavingsAccountEntity and GetClientsSavingsAccounts and GetClientsClientIdAccountMapper to fetch some values. Also added color to the MifosActionsListingCardComponent and removed account number label. --- .../components/MifosActionsListingCardComponent.kt | 14 ++++++++------ .../commonMain/composeResources/values/strings.xml | 7 +++++++ .../RecurringDepositAccountScreen.kt | 8 ++++---- .../client/savingsAccounts/SavingsAccounts.kt | 3 ++- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt index f267346b297..f56f1447b97 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt @@ -377,6 +377,7 @@ fun MifosActionsLoanListingComponent( fun MifosActionsSavingsListingComponent( accountNo: String, savingsProduct: String, + savingsProductName: String, lastActive: String, balance: String, menuList: List, @@ -392,15 +393,14 @@ fun MifosActionsSavingsListingComponent( modifier = Modifier.padding(DesignToken.padding.large), ) { MifosListingRowItem( - key = stringResource(Res.string.core_ui_account_no), + key = "", value = accountNo, - keyStyle = MifosTypography.titleSmallEmphasized, - valueStyle = MifosTypography.titleSmall, + valueStyle = MifosTypography.titleSmallEmphasized, ) Spacer(Modifier.height(DesignToken.padding.large)) MifosListingRowItem( - key = stringResource(Res.string.core_ui_savings_product), - value = savingsProduct, + key = savingsProduct, + value = savingsProductName, ) Spacer(Modifier.height(DesignToken.padding.medium)) Column( @@ -425,6 +425,7 @@ fun MifosActionsSavingsListingComponent( bottomStart = DesignToken.padding.medium, bottomEnd = DesignToken.padding.medium, ), + color = MaterialTheme.colorScheme.surfaceContainer ) { Column( modifier = Modifier.padding( @@ -627,7 +628,8 @@ fun PreviewMifosActionsSavingsListingComponent() { MaterialTheme { MifosActionsSavingsListingComponent( accountNo = "SV9876", - savingsProduct = "Regular Savings", + savingsProduct = "Savings Product", + savingsProductName = "Wallet", lastActive = "2025-08-15", balance = "$1200", menuList = listOf( diff --git a/feature/client/src/commonMain/composeResources/values/strings.xml b/feature/client/src/commonMain/composeResources/values/strings.xml index d8503069083..6982cf49dfa 100644 --- a/feature/client/src/commonMain/composeResources/values/strings.xml +++ b/feature/client/src/commonMain/composeResources/values/strings.xml @@ -223,6 +223,13 @@ Notes Check or update note accounts + Click Here To View Filled State. + + + Savings Products + Fixed Deposit Products + Recurring Deposit Products + Shares Products Performance History diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index e4e19276f83..d766f6c2571 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -1,6 +1,8 @@ package com.mifos.feature.client.recurringDepositAccount import androidclient.feature.client.generated.resources.Res +import androidclient.feature.client.generated.resources.client_product_recurring_deposit_account +import androidclient.feature.client.generated.resources.client_empty_card_message import androidclient.feature.client.generated.resources.client_profile_recurring_deposit_account_title import androidclient.feature.client.generated.resources.client_savings_item import androidclient.feature.client.generated.resources.client_savings_not_avilable @@ -9,7 +11,6 @@ import androidclient.feature.client.generated.resources.feature_client_dialog_ac import androidclient.feature.client.generated.resources.filter import androidclient.feature.client.generated.resources.search import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -30,7 +31,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.mifos.core.common.utils.DateHelper import com.mifos.core.designsystem.component.MifosCircularProgress @@ -225,13 +225,13 @@ internal fun RecurringDepositAccountScaffold( Spacer(modifier = Modifier.height(DesignToken.padding.largeIncreasedExtra)) if (state.recurringDepositAccounts.isEmpty()) { - MifosEmptyCard(msg = "Click Here To View Filled State. ") + MifosEmptyCard(msg = stringResource(Res.string.client_empty_card_message)) } else { LazyColumn { items(state.recurringDepositAccounts) { recurringDeposit -> MifosActionsSavingsListingComponent( accountNo = recurringDeposit.accountNo ?: notAvailableText, - savingsProduct = "Recurring Deposit Product", + savingsProduct = stringResource(Res.string.client_product_recurring_deposit_account), savingsProductName = recurringDeposit.shortProductName ?: notAvailableText, lastActive = if (recurringDeposit.status?.submittedAndPendingApproval == true) { stringResource(Res.string.client_savings_pending_approval) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt index 50a28881123..77f8dc013a4 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt @@ -10,6 +10,7 @@ package com.mifos.feature.client.savingsAccounts import androidclient.feature.client.generated.resources.Res +import androidclient.feature.client.generated.resources.client_product_saving_account import androidclient.feature.client.generated.resources.client_savings_item import androidclient.feature.client.generated.resources.client_savings_not_avilable import androidclient.feature.client.generated.resources.client_savings_pending_approval @@ -124,7 +125,7 @@ fun SavingsAccountsScreen( items(state.savingsAccounts) { savings -> MifosActionsSavingsListingComponent( accountNo = savings.accountNo.toString(), - savingsProduct = "Savings Product: ", + savingsProduct = stringResource(Res.string.client_product_saving_account), savingsProductName = savings.productName.toString(), // todo modify with currency symbol when not getting null from api, currently getting null balance = if (savings.accountBalance != null) { From 54f3dc6288d98dd02b5f6cf7a573e99cd71f58a6 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 18:53:26 +0530 Subject: [PATCH 05/13] typo fix --- .../kotlin/com/mifos/core/network/services/ClientService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt b/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt index 310714d946c..f81bae337f1 100644 --- a/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt +++ b/core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt @@ -284,7 +284,7 @@ interface ClientService { @Body payload: ProposeTransferRequest, ): HttpResponse - @POST("clients/{clientId}?command=updateSavingsdaAccount") + @POST("clients/{clientId}?command=updateSavingsAccount") suspend fun updateSavingsAccount( @Path("clientId") clientId: Int, @Body payload: UpdateSavingsAccountRequest, From 849428a49ac6f0cb80166839c877258b726fe28a Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 19:01:07 +0530 Subject: [PATCH 06/13] spotless fixes applied. --- .../MifosActionsListingCardComponent.kt | 3 +- .../ui/components/MifosListingComponent.kt | 12 ++-- .../ClientProfileGeneralScreen.kt | 28 ++++----- .../ClientProfileGeneralViewmodel.kt | 4 +- .../mifos/feature/client/di/ClientModule.kt | 2 +- .../client/navigation/ClientNavigation.kt | 7 +-- .../RecurringDepositAccountRoute.kt | 24 +++++--- .../RecurringDepositAccountScreen.kt | 27 +++++---- .../RecurringDepositAccountViewModel.kt | 60 +++++++++++-------- .../client/savingsAccounts/SavingsAccounts.kt | 1 - .../SavingsAccountsViewModel.kt | 4 +- 11 files changed, 94 insertions(+), 78 deletions(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt index f56f1447b97..8c235f52ef2 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt @@ -27,7 +27,6 @@ import androidclient.core.ui.generated.resources.core_ui_original_loan import androidclient.core.ui.generated.resources.core_ui_outstanding import androidclient.core.ui.generated.resources.core_ui_paid import androidclient.core.ui.generated.resources.core_ui_quantity -import androidclient.core.ui.generated.resources.core_ui_savings_product import androidclient.core.ui.generated.resources.core_ui_status import androidclient.core.ui.generated.resources.core_ui_total_collateral_value import androidclient.core.ui.generated.resources.core_ui_total_value @@ -425,7 +424,7 @@ fun MifosActionsSavingsListingComponent( bottomStart = DesignToken.padding.medium, bottomEnd = DesignToken.padding.medium, ), - color = MaterialTheme.colorScheme.surfaceContainer + color = MaterialTheme.colorScheme.surfaceContainer, ) { Column( modifier = Modifier.padding( diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt index 945dc2d40b1..377fca3ee39 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt @@ -120,19 +120,21 @@ fun MifosListingRowItem( keyContent = { if (key.isNotBlank()) { Text( - text = "$key:", style = keyStyle, - maxLines =1, + text = "$key:", + style = keyStyle, + maxLines = 1, overflow = TextOverflow.Clip, ) } }, valueContent = { Text( - text = value, style = valueStyle.copy(color = valueColor), + text = value, + style = valueStyle.copy(color = valueColor), overflow = TextOverflow.Clip, - maxLines = 1 + maxLines = 1, ) - }, + }, ) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt index 47146531f8b..e6affe178f7 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralScreen.kt @@ -240,38 +240,38 @@ fun PerformanceHistoryCard(state: ClientProfileGeneralState) { val performanceHistory = state.performanceHistory PerformanceHistoryRows( stringResource(Res.string.client_performance_history_loan_cycle_count_label), - performanceHistory.loanCyclesCount?.toString()?: - stringResource(Res.string.client_savings_not_avilable), + performanceHistory.loanCyclesCount?.toString() + ?: stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_active_loans_count_label), - performanceHistory.activeLoans?.toString() ?: - stringResource(Res.string.client_savings_not_avilable), + performanceHistory.activeLoans?.toString() + ?: stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_last_loan_amount_label), - performanceHistory.lastLoanAmount?.let{ - state.currency +" "+ it.toString() - } ?: - stringResource(Res.string.client_savings_not_avilable), + performanceHistory.lastLoanAmount?.let { + state.currency + " " + it.toString() + } + ?: stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_active_savings_label), - performanceHistory.activeSavingsCount?.toString() ?: - stringResource(Res.string.client_savings_not_avilable), + performanceHistory.activeSavingsCount?.toString() + ?: stringResource(Res.string.client_savings_not_avilable), ) PerformanceHistoryRows( stringResource(Res.string.client_performance_history_total_savings_label), - performanceHistory.totalSaving?.let{ - state.currency +" "+ it.toString() - } ?: - stringResource(Res.string.client_savings_not_avilable), + performanceHistory.totalSaving?.let { + state.currency + " " + it.toString() + } + ?: stringResource(Res.string.client_savings_not_avilable), ) } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt index 5bda576025b..1d5926b9bd1 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientGeneral/ClientProfileGeneralViewmodel.kt @@ -61,8 +61,8 @@ internal class ClientProfileGeneralViewmodel( val totalSaving = savingAccounts?.filter { it.status?.active == true && - it.depositType?.serverType!= SavingAccountDepositTypeEntity.ServerTypes.RECURRING && - it.status?.closed == false + it.depositType?.serverType != SavingAccountDepositTypeEntity.ServerTypes.RECURRING && + it.status?.closed == false }?.sumOf { it.accountBalance ?: 0.0 } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt index 77a0266e523..1c92f262204 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt @@ -22,7 +22,6 @@ import com.mifos.feature.client.clientIdentifiers.ClientIdentifiersViewModel import com.mifos.feature.client.clientIdentitiesList.ClientIdentitiesListViewModel import com.mifos.feature.client.clientPinpoint.PinPointClientViewModel import com.mifos.feature.client.clientProfile.ClientProfileViewModel -import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountViewModel import com.mifos.feature.client.clientSignature.SignatureViewModel import com.mifos.feature.client.clientStaff.ClientStaffViewModel import com.mifos.feature.client.clientSurveyList.SurveyListViewModel @@ -31,6 +30,7 @@ import com.mifos.feature.client.clientTransfer.ClientTransferViewModel import com.mifos.feature.client.clientUpdateDefaultAccount.UpdateDefaultAccountViewModel import com.mifos.feature.client.clientsList.ClientListViewModel import com.mifos.feature.client.createNewClient.CreateNewClientViewModel +import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountViewModel import com.mifos.feature.client.savingsAccounts.SavingsAccountsViewModel import com.mifos.feature.client.syncClientDialog.SyncClientsDialogViewModel import org.koin.core.module.dsl.viewModelOf diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt index 22a6b7f7bd0..37aa0fe0ec6 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt @@ -51,7 +51,6 @@ import com.mifos.feature.client.clientUpdateDefaultAccount.navigateToUpdateDefau import com.mifos.feature.client.clientUpdateDefaultAccount.updateDefaultAccountDestination import com.mifos.feature.client.clientsList.ClientListScreen import com.mifos.feature.client.createNewClient.CreateNewClientScreen -import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountEvent import com.mifos.feature.client.recurringDepositAccount.clientRecurringDepositAccountDestination import com.mifos.feature.client.recurringDepositAccount.navigateToRecurringDepositAccountRoute import com.mifos.feature.client.savingsAccounts.navigateToClientSavingsAccountsRoute @@ -142,13 +141,13 @@ fun NavGraphBuilder.clientNavGraph( savingAccounts = { clientId -> navController.navigateToClientSavingsAccountsRoute(clientId) }, - recurringDepositAccounts = {clientId-> + recurringDepositAccounts = { clientId -> navController.navigateToRecurringDepositAccountRoute(clientId) - } + }, ) clientRecurringDepositAccountDestination( - navigateBack = navController::popBackStack + navigateBack = navController::popBackStack, ) clientProfileDetailsDestination( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt index 44f4260f257..674bebfeaf8 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt @@ -1,3 +1,12 @@ +/* + * 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/android-client/blob/master/LICENSE.md + */ package com.mifos.feature.client.recurringDepositAccount import androidx.navigation.NavController @@ -7,16 +16,15 @@ import kotlinx.serialization.Serializable @Serializable data class RecurringDepositAccountRoute( - val clientId: Int = -1 + val clientId: Int = -1, ) - fun NavGraphBuilder.clientRecurringDepositAccountDestination( navigateBack: () -> Unit, - onApproveAccount: (Int) -> Unit ={}, - onViewAccount: (Int) -> Unit ={}, -){ - composable{ + onApproveAccount: (Int) -> Unit = {}, + onViewAccount: (Int) -> Unit = {}, +) { + composable { RecurringDepositAccountScreen( navigateBack = navigateBack, onApproveAccount = { @@ -24,7 +32,7 @@ fun NavGraphBuilder.clientRecurringDepositAccountDestination( }, onViewAccount = { onViewAccount(it) - } + }, ) } } @@ -33,4 +41,4 @@ fun NavController.navigateToRecurringDepositAccountRoute( clientId: Int, ) { this.navigate(RecurringDepositAccountRoute(clientId = clientId)) -} \ No newline at end of file +} diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index d766f6c2571..c99cd1e6f2e 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -1,8 +1,17 @@ +/* + * 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/android-client/blob/master/LICENSE.md + */ package com.mifos.feature.client.recurringDepositAccount import androidclient.feature.client.generated.resources.Res -import androidclient.feature.client.generated.resources.client_product_recurring_deposit_account import androidclient.feature.client.generated.resources.client_empty_card_message +import androidclient.feature.client.generated.resources.client_product_recurring_deposit_account import androidclient.feature.client.generated.resources.client_profile_recurring_deposit_account_title import androidclient.feature.client.generated.resources.client_savings_item import androidclient.feature.client.generated.resources.client_savings_not_avilable @@ -46,7 +55,6 @@ import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel - @Composable fun RecurringDepositAccountScreen( navigateBack: () -> Unit, @@ -59,12 +67,12 @@ fun RecurringDepositAccountScreen( EventsEffect(viewModel.eventFlow) { event -> when (event) { - is RecurringDepositAccountEvent.onApproveAccount -> { + is RecurringDepositAccountEvent.OnApproveAccount -> { onApproveAccount(event.accountId) } - RecurringDepositAccountEvent.onNavigateBack -> navigateBack - is RecurringDepositAccountEvent.onViewAccount -> { + RecurringDepositAccountEvent.OnNavigateBack -> navigateBack + is RecurringDepositAccountEvent.OnViewAccount -> { onViewAccount(event.accountId) } } @@ -120,7 +128,6 @@ fun RecurringDepositAccountScreen( } } - RecurringDepositAccountDialog( state, onCloseDialog = { @@ -144,7 +151,6 @@ fun RecurringDepositAccountScreen( action(RecurringDepositAccountAction.ApproveAccount(accountId = state.clientId)) }, ) - } @OptIn(ExperimentalMaterial3Api::class) @@ -257,18 +263,14 @@ internal fun RecurringDepositAccountScaffold( Actions.ApproveAccount -> onViewAccount else -> null } - } } } - } } - } } - @Composable internal fun RecurringDepositAccountHeader( totalItem: String, @@ -311,6 +313,5 @@ internal fun RecurringDepositAccountHeader( onToggleFilter.invoke() }, ) - } -} \ No newline at end of file +} diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt index 51363302ced..99df639909f 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -1,3 +1,12 @@ +/* + * 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/android-client/blob/master/LICENSE.md + */ package com.mifos.feature.client.recurringDepositAccount import androidx.lifecycle.SavedStateHandle @@ -6,21 +15,21 @@ import androidx.navigation.toRoute import com.mifos.core.common.utils.DataState import com.mifos.core.domain.useCases.GetClientDetailsUseCase import com.mifos.core.ui.util.BaseViewModel -import com.mifos.feature.client.recurringDepositAccount.RecurringDepositAccountEvent.* import com.mifos.room.entities.accounts.savings.SavingAccountDepositTypeEntity import com.mifos.room.entities.accounts.savings.SavingsAccountEntity import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch - class RecurringDepositAccountViewModel( savedStateHandle: SavedStateHandle, private val getClientDetailsUseCase: GetClientDetailsUseCase, -) : BaseViewModel( - initialState = RecurringDepositAccountState() -){ + RecurringDepositAccountAction, + >( + initialState = RecurringDepositAccountState(), +) { val route = savedStateHandle.toRoute() @@ -29,14 +38,14 @@ class RecurringDepositAccountViewModel( } override fun handleAction(action: RecurringDepositAccountAction) { - when(action){ + when (action) { RecurringDepositAccountAction.CloseDialog -> { mutableStateFlow.update { it.copy(dialogState = null) } } is RecurringDepositAccountAction.NavigateBack -> { - sendEvent(onNavigateBack) + sendEvent(RecurringDepositAccountEvent.OnNavigateBack) } is RecurringDepositAccountAction.Refresh -> { getRecurringDepositAccounts() @@ -47,7 +56,7 @@ class RecurringDepositAccountViewModel( is RecurringDepositAccountAction.ToggleFilter -> { mutableStateFlow.update { it.copy( - isFilterDialogOpen = true + isFilterDialogOpen = true, ) } } @@ -67,13 +76,13 @@ class RecurringDepositAccountViewModel( } is RecurringDepositAccountAction.ViewAccount -> { sendEvent( - onViewAccount(action.accountId) + RecurringDepositAccountEvent.OnViewAccount(action.accountId), ) } is RecurringDepositAccountAction.ApproveAccount -> { sendEvent( - onApproveAccount(action.accountId) + RecurringDepositAccountEvent.OnApproveAccount(action.accountId), ) } } @@ -81,8 +90,8 @@ class RecurringDepositAccountViewModel( private fun getRecurringDepositAccounts() { viewModelScope.launch { - getClientDetailsUseCase.invoke(route.clientId).collect { result-> - when(result){ + getClientDetailsUseCase.invoke(route.clientId).collect { result -> + when (result) { is DataState.Error -> { mutableStateFlow.update { it.copy(dialogState = RecurringDepositAccountState.DialogState.Error(result.message)) @@ -95,10 +104,10 @@ class RecurringDepositAccountViewModel( } is DataState.Success -> { val recurringDepositAccount = result.data.clientAccounts?.savingsAccounts?.let { - it.filter {accountEntity -> + it.filter { accountEntity -> accountEntity.depositType?.serverType == SavingAccountDepositTypeEntity.ServerTypes.RECURRING && - accountEntity.status?.closed == false + accountEntity.status?.closed == false }.apply { // Todo modify search accordingly searchRecurringDepositAccounts(state.searchText, this) @@ -109,7 +118,7 @@ class RecurringDepositAccountViewModel( it.copy( dialogState = null, clientId = route.clientId, - recurringDepositAccounts = recurringDepositAccount + recurringDepositAccounts = recurringDepositAccount, ) } } @@ -120,9 +129,9 @@ class RecurringDepositAccountViewModel( private fun searchRecurringDepositAccounts( query: String, - recurringDepositAccounts: List + recurringDepositAccounts: List, ): List { - if(query.isNotBlank()) { + if (query.isNotBlank()) { return recurringDepositAccounts.filter { accountEntity -> accountEntity.accountNo.toString().contains(state.searchText.trim()) } @@ -131,7 +140,6 @@ class RecurringDepositAccountViewModel( } } - data class RecurringDepositAccountState( val clientId: Int = -1, val recurringDepositAccounts: List = emptyList(), @@ -139,7 +147,7 @@ data class RecurringDepositAccountState( val dialogState: DialogState? = null, val isSearchBarActive: Boolean = false, val isFilterDialogOpen: Boolean = false, -){ +) { sealed interface DialogState { data class Error(val message: String) : DialogState data object Loading : DialogState @@ -149,17 +157,17 @@ data class RecurringDepositAccountState( sealed class RecurringDepositAccountAction { data object NavigateBack : RecurringDepositAccountAction() data class ViewAccount(val accountId: Int) : RecurringDepositAccountAction() - data class ApproveAccount(val accountId: Int): RecurringDepositAccountAction() + data class ApproveAccount(val accountId: Int) : RecurringDepositAccountAction() data object Refresh : RecurringDepositAccountAction() data object ToggleFilter : RecurringDepositAccountAction() data object ToggleSearch : RecurringDepositAccountAction() data class Search(val query: String) : RecurringDepositAccountAction() data class UpdateSearch(val query: String) : RecurringDepositAccountAction() - data object CloseDialog: RecurringDepositAccountAction() + data object CloseDialog : RecurringDepositAccountAction() } sealed class RecurringDepositAccountEvent { - data object onNavigateBack : RecurringDepositAccountEvent() - data class onViewAccount(val accountId: Int) : RecurringDepositAccountEvent() - data class onApproveAccount(val accountId: Int) : RecurringDepositAccountEvent() -} \ No newline at end of file + data object OnNavigateBack : RecurringDepositAccountEvent() + data class OnViewAccount(val accountId: Int) : RecurringDepositAccountEvent() + data class OnApproveAccount(val accountId: Int) : RecurringDepositAccountEvent() +} diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt index 77f8dc013a4..36d594776c6 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt @@ -56,7 +56,6 @@ import com.mifos.core.ui.components.MifosSearchBar import com.mifos.core.ui.util.EventsEffect import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource -import org.jetbrains.compose.ui.tooling.preview.Preview import org.koin.compose.viewmodel.koinViewModel @Composable diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt index 1b50235f216..f69ce016020 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt @@ -84,9 +84,9 @@ internal class SavingsAccountsViewModel( // Todo modify search accordingly val savingsAccounts = repository.getClientAccounts(route.clientId) .savingsAccounts - .filter {accountEntity -> + .filter { accountEntity -> accountEntity.depositType?.serverType == SavingAccountDepositTypeEntity.ServerTypes.SAVINGS && - accountEntity.status?.closed == false + accountEntity.status?.closed == false } .filter { it.accountNo?.contains(state.searchText.trim()) == true } From 63b57729a45587fc224030314b8117cc75040436 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 19:44:24 +0530 Subject: [PATCH 07/13] added gap between lists items and removed action function from the RecurringDepositAccountScreen --- .../RecurringDepositAccountScreen.kt | 114 +++++------------- .../client/savingsAccounts/SavingsAccounts.kt | 4 +- 2 files changed, 32 insertions(+), 86 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index c99cd1e6f2e..95b20e40390 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -78,78 +78,15 @@ fun RecurringDepositAccountScreen( } } - val action: (RecurringDepositAccountAction) -> Unit = remember(viewModel) { - { - when (it) { - RecurringDepositAccountAction.CloseDialog -> { - viewModel.trySendAction(RecurringDepositAccountAction.CloseDialog) - } - - RecurringDepositAccountAction.NavigateBack -> { - viewModel.trySendAction(RecurringDepositAccountAction.NavigateBack) - } - - RecurringDepositAccountAction.Refresh -> { - viewModel.trySendAction(RecurringDepositAccountAction.Refresh) - } - - is RecurringDepositAccountAction.Search -> { - viewModel.trySendAction( - RecurringDepositAccountAction.Search(it.query), - ) - } - - RecurringDepositAccountAction.ToggleFilter -> { - viewModel.trySendAction(RecurringDepositAccountAction.ToggleFilter) - } - - RecurringDepositAccountAction.ToggleSearch -> { - viewModel.trySendAction(RecurringDepositAccountAction.ToggleSearch) - } - - is RecurringDepositAccountAction.UpdateSearch -> { - viewModel.trySendAction( - RecurringDepositAccountAction.UpdateSearch(it.query), - ) - } - - is RecurringDepositAccountAction.ViewAccount -> { - viewModel.trySendAction( - RecurringDepositAccountAction.ViewAccount(it.accountId), - ) - } - - is RecurringDepositAccountAction.ApproveAccount -> { - viewModel.trySendAction( - RecurringDepositAccountAction.ApproveAccount(it.accountId), - ) - } - } - } - } - RecurringDepositAccountDialog( state, - onCloseDialog = { - action(RecurringDepositAccountAction.CloseDialog) - }, + onAction = remember(viewModel) { { viewModel.trySendAction(it) } }, ) RecurringDepositAccountScaffold( state = state, - onNavigateBack = navigateBack, modifier = modifier, - onSearchClick = { - action(RecurringDepositAccountAction.Search(it)) - }, - onToggleFilter = { action(RecurringDepositAccountAction.ToggleFilter) }, - onToggleSearch = { action(RecurringDepositAccountAction.ToggleSearch) }, - onViewAccount = { - action(RecurringDepositAccountAction.ViewAccount(accountId = state.clientId)) - }, - onApproveAccount = { - action(RecurringDepositAccountAction.ApproveAccount(accountId = state.clientId)) - }, + onAction = remember(viewModel) { { viewModel.trySendAction(it) } }, ) } @@ -157,7 +94,7 @@ fun RecurringDepositAccountScreen( @Composable internal fun RecurringDepositAccountDialog( state: RecurringDepositAccountState, - onCloseDialog: () -> Unit, + onAction: (RecurringDepositAccountAction) -> Unit, ) { when (state.dialogState) { is RecurringDepositAccountState.DialogState.Error -> { @@ -166,7 +103,9 @@ internal fun RecurringDepositAccountDialog( text = { Text(text = state.dialogState.message) }, confirmButton = { TextButton( - onClick = onCloseDialog, + onClick = { + onAction(RecurringDepositAccountAction.CloseDialog) + }, ) { Text(stringResource(Res.string.feature_client_dialog_action_ok)) } @@ -184,17 +123,13 @@ internal fun RecurringDepositAccountDialog( @Composable internal fun RecurringDepositAccountScaffold( state: RecurringDepositAccountState, - onNavigateBack: () -> Unit, modifier: Modifier = Modifier, - onSearchClick: (String) -> Unit = {}, - onUpdateSearch: (String) -> Unit = {}, - onToggleFilter: () -> Unit = {}, - onToggleSearch: () -> Unit = {}, - onViewAccount: () -> Unit = {}, - onApproveAccount: () -> Unit = {}, + onAction: (RecurringDepositAccountAction) -> Unit, ) { MifosScaffold( - onBackPressed = onNavigateBack, + onBackPressed = { + onAction(RecurringDepositAccountAction.NavigateBack) + }, modifier = modifier, title = "", ) { paddingValues -> @@ -210,8 +145,12 @@ internal fun RecurringDepositAccountScaffold( val notAvailableText = stringResource(Res.string.client_savings_not_avilable) RecurringDepositAccountHeader( state.recurringDepositAccounts.size.toString(), - onToggleSearch = onToggleSearch, - onToggleFilter = onToggleFilter, + onToggleSearch = { + onAction(RecurringDepositAccountAction.ToggleSearch) + }, + onToggleFilter = { + onAction(RecurringDepositAccountAction.ToggleFilter) + }, ) // todo implement search bar functionality @@ -219,12 +158,13 @@ internal fun RecurringDepositAccountScaffold( MifosSearchBar( query = state.searchText, onQueryChange = { - onUpdateSearch(it) - }, + onAction(RecurringDepositAccountAction.Search(it)) }, onSearchClick = { - onSearchClick(it) + onAction(RecurringDepositAccountAction.Search(it)) + }, + onBackClick = { + onAction(RecurringDepositAccountAction.ToggleSearch) }, - onBackClick = onToggleSearch, ) } @@ -259,11 +199,19 @@ internal fun RecurringDepositAccountScaffold( }, ) { actions -> when (actions) { - Actions.ViewAccount -> onApproveAccount - Actions.ApproveAccount -> onViewAccount + Actions.ViewAccount -> { + onAction( + RecurringDepositAccountAction.ViewAccount(state.clientId) + ) + } + Actions.ApproveAccount -> { + RecurringDepositAccountAction.ApproveAccount(state.clientId) + } else -> null } } + + Spacer(modifier = Modifier.height(DesignToken.spacing.small)) } } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt index 36d594776c6..12c5ce59acb 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt @@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.AlertDialog @@ -40,7 +39,6 @@ import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -168,7 +166,7 @@ fun SavingsAccountsScreen( }, ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(DesignToken.spacing.small)) } } } From 04d69a6ffcec70b0afed31f10f1c2c8facb5ad06 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 19:49:04 +0530 Subject: [PATCH 08/13] using MifosListingRowItemHeader in the MifosActionListingCardComponent --- .../ui/components/MifosActionsListingCardComponent.kt | 8 ++++---- .../RecurringDepositAccountScreen.kt | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt index 8c235f52ef2..dfb200d4eac 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt @@ -391,11 +391,11 @@ fun MifosActionsSavingsListingComponent( Column( modifier = Modifier.padding(DesignToken.padding.large), ) { - MifosListingRowItem( - key = "", - value = accountNo, - valueStyle = MifosTypography.titleSmallEmphasized, + MifosListingRowItemHeader( + text = accountNo, + keyStyle = MifosTypography.titleSmallEmphasized, ) + Spacer(Modifier.height(DesignToken.padding.large)) MifosListingRowItem( key = savingsProduct, diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index 95b20e40390..5e65f78bbb3 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -158,7 +158,8 @@ internal fun RecurringDepositAccountScaffold( MifosSearchBar( query = state.searchText, onQueryChange = { - onAction(RecurringDepositAccountAction.Search(it)) }, + onAction(RecurringDepositAccountAction.Search(it)) + }, onSearchClick = { onAction(RecurringDepositAccountAction.Search(it)) }, @@ -201,7 +202,7 @@ internal fun RecurringDepositAccountScaffold( when (actions) { Actions.ViewAccount -> { onAction( - RecurringDepositAccountAction.ViewAccount(state.clientId) + RecurringDepositAccountAction.ViewAccount(state.clientId), ) } Actions.ApproveAccount -> { From a0092d9470a69bb553ae14d1680663525db24214 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 19:54:20 +0530 Subject: [PATCH 09/13] calling navigateBack function. --- .../recurringDepositAccount/RecurringDepositAccountScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index 5e65f78bbb3..df73f4fa3e0 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -71,7 +71,7 @@ fun RecurringDepositAccountScreen( onApproveAccount(event.accountId) } - RecurringDepositAccountEvent.OnNavigateBack -> navigateBack + RecurringDepositAccountEvent.OnNavigateBack -> navigateBack() is RecurringDepositAccountEvent.OnViewAccount -> { onViewAccount(event.accountId) } From 6675d8b813562d40e3d2e3a1f4922e68829effb7 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 20:20:31 +0530 Subject: [PATCH 10/13] changed data types. --- .../RecurringDepositAccountRoute.kt | 4 ++-- .../RecurringDepositAccountScreen.kt | 18 +++++++++++------- .../RecurringDepositAccountViewModel.kt | 12 ++++++------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt index 674bebfeaf8..09572ef756c 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt @@ -21,8 +21,8 @@ data class RecurringDepositAccountRoute( fun NavGraphBuilder.clientRecurringDepositAccountDestination( navigateBack: () -> Unit, - onApproveAccount: (Int) -> Unit = {}, - onViewAccount: (Int) -> Unit = {}, + onApproveAccount: (String) -> Unit = {}, + onViewAccount: (String) -> Unit = {}, ) { composable { RecurringDepositAccountScreen( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index df73f4fa3e0..513e8f55a3c 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -59,8 +59,8 @@ import org.koin.compose.viewmodel.koinViewModel fun RecurringDepositAccountScreen( navigateBack: () -> Unit, modifier: Modifier = Modifier, - onApproveAccount: (Int) -> Unit = {}, - onViewAccount: (Int) -> Unit = {}, + onApproveAccount: (String) -> Unit = {}, + onViewAccount: (String) -> Unit = {}, viewModel: RecurringDepositAccountViewModel = koinViewModel(), ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() @@ -68,12 +68,12 @@ fun RecurringDepositAccountScreen( EventsEffect(viewModel.eventFlow) { event -> when (event) { is RecurringDepositAccountEvent.OnApproveAccount -> { - onApproveAccount(event.accountId) + onApproveAccount(event.accountNumber) } RecurringDepositAccountEvent.OnNavigateBack -> navigateBack() is RecurringDepositAccountEvent.OnViewAccount -> { - onViewAccount(event.accountId) + onViewAccount(event.accountNumber) } } } @@ -158,7 +158,7 @@ internal fun RecurringDepositAccountScaffold( MifosSearchBar( query = state.searchText, onQueryChange = { - onAction(RecurringDepositAccountAction.Search(it)) + onAction(RecurringDepositAccountAction.UpdateSearch(it)) }, onSearchClick = { onAction(RecurringDepositAccountAction.Search(it)) @@ -202,11 +202,15 @@ internal fun RecurringDepositAccountScaffold( when (actions) { Actions.ViewAccount -> { onAction( - RecurringDepositAccountAction.ViewAccount(state.clientId), + RecurringDepositAccountAction.ViewAccount( + recurringDeposit.accountNo?: "" + ), ) } Actions.ApproveAccount -> { - RecurringDepositAccountAction.ApproveAccount(state.clientId) + RecurringDepositAccountAction.ApproveAccount( + recurringDeposit.accountNo?: "" + ) } else -> null } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt index 99df639909f..98682fddf08 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -76,13 +76,13 @@ class RecurringDepositAccountViewModel( } is RecurringDepositAccountAction.ViewAccount -> { sendEvent( - RecurringDepositAccountEvent.OnViewAccount(action.accountId), + RecurringDepositAccountEvent.OnViewAccount(action.accountNumber), ) } is RecurringDepositAccountAction.ApproveAccount -> { sendEvent( - RecurringDepositAccountEvent.OnApproveAccount(action.accountId), + RecurringDepositAccountEvent.OnApproveAccount(action.accountNumber), ) } } @@ -156,8 +156,8 @@ data class RecurringDepositAccountState( sealed class RecurringDepositAccountAction { data object NavigateBack : RecurringDepositAccountAction() - data class ViewAccount(val accountId: Int) : RecurringDepositAccountAction() - data class ApproveAccount(val accountId: Int) : RecurringDepositAccountAction() + data class ViewAccount(val accountNumber: String) : RecurringDepositAccountAction() + data class ApproveAccount(val accountNumber: String) : RecurringDepositAccountAction() data object Refresh : RecurringDepositAccountAction() data object ToggleFilter : RecurringDepositAccountAction() data object ToggleSearch : RecurringDepositAccountAction() @@ -168,6 +168,6 @@ sealed class RecurringDepositAccountAction { sealed class RecurringDepositAccountEvent { data object OnNavigateBack : RecurringDepositAccountEvent() - data class OnViewAccount(val accountId: Int) : RecurringDepositAccountEvent() - data class OnApproveAccount(val accountId: Int) : RecurringDepositAccountEvent() + data class OnViewAccount(val accountNumber: String) : RecurringDepositAccountEvent() + data class OnApproveAccount(val accountNumber: String) : RecurringDepositAccountEvent() } From 6378cf66c00e71521e2f342953a58ee43cad8e59 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 20:43:44 +0530 Subject: [PATCH 11/13] removed default parameters. --- .../client/navigation/ClientNavigation.kt | 2 + .../RecurringDepositAccountRoute.kt | 4 +- .../RecurringDepositAccountScreen.kt | 10 ++-- .../RecurringDepositAccountViewModel.kt | 46 +++++++++++-------- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt index 37aa0fe0ec6..74fe99498a9 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt @@ -148,6 +148,8 @@ fun NavGraphBuilder.clientNavGraph( clientRecurringDepositAccountDestination( navigateBack = navController::popBackStack, + {}, + {} ) clientProfileDetailsDestination( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt index 09572ef756c..b2caf8bdf7e 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountRoute.kt @@ -21,8 +21,8 @@ data class RecurringDepositAccountRoute( fun NavGraphBuilder.clientRecurringDepositAccountDestination( navigateBack: () -> Unit, - onApproveAccount: (String) -> Unit = {}, - onViewAccount: (String) -> Unit = {}, + onApproveAccount: (String) -> Unit, + onViewAccount: (String) -> Unit, ) { composable { RecurringDepositAccountScreen( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index 513e8f55a3c..19f5059a57f 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -58,9 +58,9 @@ import org.koin.compose.viewmodel.koinViewModel @Composable fun RecurringDepositAccountScreen( navigateBack: () -> Unit, + onApproveAccount: (String) -> Unit, + onViewAccount: (String) -> Unit, modifier: Modifier = Modifier, - onApproveAccount: (String) -> Unit = {}, - onViewAccount: (String) -> Unit = {}, viewModel: RecurringDepositAccountViewModel = koinViewModel(), ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() @@ -225,11 +225,11 @@ internal fun RecurringDepositAccountScaffold( } @Composable -internal fun RecurringDepositAccountHeader( +private fun RecurringDepositAccountHeader( totalItem: String, + onToggleFilter: () -> Unit, modifier: Modifier = Modifier, - onToggleFilter: () -> Unit = {}, - onToggleSearch: () -> Unit = {}, + onToggleSearch: () -> Unit, ) { Row( modifier = modifier.fillMaxWidth() diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt index 98682fddf08..5f943209300 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -23,13 +23,11 @@ import kotlinx.coroutines.launch class RecurringDepositAccountViewModel( savedStateHandle: SavedStateHandle, private val getClientDetailsUseCase: GetClientDetailsUseCase, -) : BaseViewModel< - RecurringDepositAccountState, - RecurringDepositAccountEvent, - RecurringDepositAccountAction, - >( - initialState = RecurringDepositAccountState(), -) { +) : BaseViewModel + (initialState = RecurringDepositAccountState()) +{ val route = savedStateHandle.toRoute() @@ -44,15 +42,19 @@ class RecurringDepositAccountViewModel( it.copy(dialogState = null) } } + is RecurringDepositAccountAction.NavigateBack -> { sendEvent(RecurringDepositAccountEvent.OnNavigateBack) } + is RecurringDepositAccountAction.Refresh -> { getRecurringDepositAccounts() } + is RecurringDepositAccountAction.Search -> { getRecurringDepositAccounts() } + is RecurringDepositAccountAction.ToggleFilter -> { mutableStateFlow.update { it.copy( @@ -60,6 +62,7 @@ class RecurringDepositAccountViewModel( ) } } + is RecurringDepositAccountAction.ToggleSearch -> { mutableStateFlow.update { it.copy( @@ -67,6 +70,7 @@ class RecurringDepositAccountViewModel( ) } } + is RecurringDepositAccountAction.UpdateSearch -> { mutableStateFlow.update { it.copy( @@ -74,6 +78,7 @@ class RecurringDepositAccountViewModel( ) } } + is RecurringDepositAccountAction.ViewAccount -> { sendEvent( RecurringDepositAccountEvent.OnViewAccount(action.accountNumber), @@ -94,25 +99,30 @@ class RecurringDepositAccountViewModel( when (result) { is DataState.Error -> { mutableStateFlow.update { - it.copy(dialogState = RecurringDepositAccountState.DialogState.Error(result.message)) + it.copy( + dialogState = RecurringDepositAccountState.DialogState.Error( + result.message + ) + ) } } + is DataState.Loading -> { mutableStateFlow.update { it.copy(dialogState = RecurringDepositAccountState.DialogState.Loading) } } + is DataState.Success -> { - val recurringDepositAccount = result.data.clientAccounts?.savingsAccounts?.let { - it.filter { accountEntity -> - accountEntity.depositType?.serverType == - SavingAccountDepositTypeEntity.ServerTypes.RECURRING && - accountEntity.status?.closed == false - }.apply { - // Todo modify search accordingly - searchRecurringDepositAccounts(state.searchText, this) - } - } ?: emptyList() + val recurringDepositAccount = + result.data.clientAccounts?.savingsAccounts?.let { + it.filter { accountEntity -> + accountEntity.depositType?.serverType == SavingAccountDepositTypeEntity.ServerTypes.RECURRING && accountEntity.status?.closed == false + }.apply { + // Todo modify search accordingly + searchRecurringDepositAccounts(state.searchText, this) + } + } ?: emptyList() mutableStateFlow.update { it.copy( From d1c691695a442f508eebfaa3db22b3a7f7e33c13 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 20:47:50 +0530 Subject: [PATCH 12/13] added network monitor option. --- .../RecurringDepositAccountViewModel.kt | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt index 5f943209300..0e1022381a1 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -13,6 +13,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.mifos.core.common.utils.DataState +import com.mifos.core.data.util.NetworkMonitor import com.mifos.core.domain.useCases.GetClientDetailsUseCase import com.mifos.core.ui.util.BaseViewModel import com.mifos.room.entities.accounts.savings.SavingAccountDepositTypeEntity @@ -22,6 +23,7 @@ import kotlinx.coroutines.launch class RecurringDepositAccountViewModel( savedStateHandle: SavedStateHandle, + private val networkMonitor: NetworkMonitor, private val getClientDetailsUseCase: GetClientDetailsUseCase, ) : BaseViewModel() init { - getRecurringDepositAccounts() + checkNetworkAndGetLoanAccounts() } override fun handleAction(action: RecurringDepositAccountAction) { @@ -48,11 +50,11 @@ class RecurringDepositAccountViewModel( } is RecurringDepositAccountAction.Refresh -> { - getRecurringDepositAccounts() + checkNetworkAndGetLoanAccounts() } is RecurringDepositAccountAction.Search -> { - getRecurringDepositAccounts() + checkNetworkAndGetLoanAccounts() } is RecurringDepositAccountAction.ToggleFilter -> { @@ -93,6 +95,22 @@ class RecurringDepositAccountViewModel( } } + private fun checkNetworkAndGetLoanAccounts() { + viewModelScope.launch { + networkMonitor.isOnline.collect { isConnected -> + when (isConnected) { + true -> getRecurringDepositAccounts() + false -> { + mutableStateFlow.update { + it.copy(dialogState = RecurringDepositAccountState + .DialogState.Error("No internet connection, Try Again")) + } + } + } + } + } + } + private fun getRecurringDepositAccounts() { viewModelScope.launch { getClientDetailsUseCase.invoke(route.clientId).collect { result -> From 198b800a67e922c46581964ee6219c3f8a03b577 Mon Sep 17 00:00:00 2001 From: kalpesh Date: Mon, 1 Sep 2025 21:00:08 +0530 Subject: [PATCH 13/13] spotless fix. --- .../client/navigation/ClientNavigation.kt | 2 +- .../RecurringDepositAccountScreen.kt | 4 ++-- .../RecurringDepositAccountViewModel.kt | 21 +++++++++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt index 74fe99498a9..4581cc4ea44 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt @@ -149,7 +149,7 @@ fun NavGraphBuilder.clientNavGraph( clientRecurringDepositAccountDestination( navigateBack = navController::popBackStack, {}, - {} + {}, ) clientProfileDetailsDestination( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt index 19f5059a57f..e170e0c4a78 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt @@ -203,13 +203,13 @@ internal fun RecurringDepositAccountScaffold( Actions.ViewAccount -> { onAction( RecurringDepositAccountAction.ViewAccount( - recurringDeposit.accountNo?: "" + recurringDeposit.accountNo ?: "", ), ) } Actions.ApproveAccount -> { RecurringDepositAccountAction.ApproveAccount( - recurringDeposit.accountNo?: "" + recurringDeposit.accountNo ?: "", ) } else -> null diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt index 0e1022381a1..ecfbb5d8229 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt @@ -25,11 +25,12 @@ class RecurringDepositAccountViewModel( savedStateHandle: SavedStateHandle, private val networkMonitor: NetworkMonitor, private val getClientDetailsUseCase: GetClientDetailsUseCase, -) : BaseViewModel - (initialState = RecurringDepositAccountState()) -{ +) : BaseViewModel< + RecurringDepositAccountState, + RecurringDepositAccountEvent, + RecurringDepositAccountAction, + > + (initialState = RecurringDepositAccountState()) { val route = savedStateHandle.toRoute() @@ -102,8 +103,10 @@ class RecurringDepositAccountViewModel( true -> getRecurringDepositAccounts() false -> { mutableStateFlow.update { - it.copy(dialogState = RecurringDepositAccountState - .DialogState.Error("No internet connection, Try Again")) + it.copy( + dialogState = RecurringDepositAccountState + .DialogState.Error("No internet connection, Try Again"), + ) } } } @@ -119,8 +122,8 @@ class RecurringDepositAccountViewModel( mutableStateFlow.update { it.copy( dialogState = RecurringDepositAccountState.DialogState.Error( - result.message - ) + result.message, + ), ) } }