Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import mifos_mobile.feature.savings_account.generated.resources.feature_account_
import mifos_mobile.feature.savings_account.generated.resources.feature_savings_account
import mifos_mobile.feature.savings_account.generated.resources.feature_savings_account_dashboard
import mifos_mobile.feature.savings_account.generated.resources.feature_savings_account_items
import mifos_mobile.feature.savings_account.generated.resources.feature_savings_filter_pending_account
import mifos_mobile.feature.savings_account.generated.resources.feature_savings_no_accounts_found
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource
Expand All @@ -52,15 +53,14 @@ import org.mifos.mobile.core.designsystem.theme.AppColors
import org.mifos.mobile.core.designsystem.theme.DesignToken
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.designsystem.theme.MifosTypography
import org.mifos.mobile.core.model.LoanStatus
import org.mifos.mobile.core.model.SavingStatus
import org.mifos.mobile.core.ui.component.EmptyDataView
import org.mifos.mobile.core.ui.component.MifosAccountCard
import org.mifos.mobile.core.ui.component.MifosDashboardCard
import org.mifos.mobile.core.ui.component.MifosErrorComponent
import org.mifos.mobile.core.ui.component.MifosProgressIndicator
import org.mifos.mobile.core.ui.utils.EventsEffect
import org.mifos.mobile.core.ui.utils.ScreenUiState
import kotlin.collections.orEmpty

@Composable
fun SavingsAccountScreen(
Expand Down Expand Up @@ -91,29 +91,21 @@ fun SavingsAccountScreen(
EventsEffect(viewModel.eventFlow) { event ->
when (event) {
is SavingsAccountsEvent.NavigateBack -> navigateBack.invoke()

is SavingsAccountsEvent.AccountClicked -> {
onAccountClicked(Constants.SAVINGS_ACCOUNT, event.accountId)
}

is SavingsAccountsEvent.LoadingCompleted -> {
onLoadingCompleted.invoke()
}
is SavingsAccountsEvent.LoadingCompleted -> onLoadingCompleted.invoke()
}
}

SavingsAccountDialog(
dialogState = state.dialogState,
onAction = remember(viewModel) {
{ viewModel.trySendAction(it) }
},
onAction = remember(viewModel) { { viewModel.trySendAction(it) } },
)

SavingsAccountContent(
state = state,
onAction = remember(viewModel) {
{ viewModel.trySendAction(it) }
},
onAction = remember(viewModel) { { viewModel.trySendAction(it) } },
filtersClicked = filtersClicked,
)
}
Expand All @@ -131,7 +123,6 @@ internal fun SavingsAccountDialog(
isRetryEnabled = true,
)
}

null -> Unit
}
}
Expand Down Expand Up @@ -210,19 +201,7 @@ internal fun SavingsAccountContent(
)
}

Row(
horizontalArrangement = Arrangement.spacedBy(DesignToken.spacing.largeIncreased),
) {
// TODO : un-implemented feature,
// commenting because user won't feels its good ,uncomment and implement it
// Icon(
// modifier = Modifier
// .clickable {}
// .size(20.dp),
// imageVector = MifosIcons.SearchNew,
// contentDescription =
// stringResource(Res.string.content_description_search),
// )
Row(horizontalArrangement = Arrangement.spacedBy(DesignToken.spacing.largeIncreased)) {
Icon(
modifier = Modifier
.clickable { filtersClicked() }
Expand Down Expand Up @@ -254,38 +233,41 @@ internal fun SavingsAccountContent(
)
}
} else {
val accounts = state.savingsAccount.orEmpty()
LazyColumn(
modifier = Modifier
.fillMaxSize()
.weight(1f),
) {
item {
Spacer(modifier = Modifier.height(DesignToken.spacing.small))
}
items(state.savingsAccount.orEmpty()) { account ->
item { Spacer(modifier = Modifier.height(DesignToken.spacing.small)) }

items(accounts) { account ->
val color = when (account.status?.value) {
LoanStatus.ACTIVE.status -> AppColors.customEnable
LoanStatus.SUBMIT_AND_PENDING_APPROVAL.status -> AppColors.customYellow
LoanStatus.WITHDRAWN.status, LoanStatus.MATURED.status ->
MaterialTheme.colorScheme.error
SavingStatus.ACTIVE.status -> AppColors.customEnable
SavingStatus.SUBMIT_AND_PENDING_APPROVAL.status -> AppColors.customYellow
SavingStatus.INACTIVE.status -> MaterialTheme.colorScheme.error
else -> MaterialTheme.colorScheme.onSurface
}

val accountStatus = if (account.status?.active == true) {
CurrencyFormatter.format(
account.accountBalance,
account.currency?.code,
account.currency?.decimalPlaces,
)
} else {
if (account.status?.value == SavingStatus.SUBMIT_AND_PENDING_APPROVAL.status) {
stringResource(Res.string.feature_savings_filter_pending_account)
} else {
account.status?.value ?: ""
}
}

MifosAccountCard(
accountId = account.id,
accountNumber = account.accountNo,
accountType = account.productName,
accountStatus = (
if (account.status?.active == true) {
CurrencyFormatter.format(
account.accountBalance,
account.currency?.code,
account.currency?.decimalPlaces,
)
} else {
account.status?.value ?: ""
}
),
accountStatus = accountStatus,
accountStatusColor = color,
onAccountClick = {
onAction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import org.mifos.mobile.core.common.DataState
import org.mifos.mobile.core.data.repository.AccountsRepository
import org.mifos.mobile.core.data.util.NetworkMonitor
import org.mifos.mobile.core.datastore.UserPreferencesRepository
import org.mifos.mobile.core.model.SavingStatus
import org.mifos.mobile.core.model.entity.accounts.savings.SavingAccount
import org.mifos.mobile.core.model.entity.client.ClientAccounts
import org.mifos.mobile.core.ui.utils.BaseViewModel
import org.mifos.mobile.core.ui.utils.ScreenUiState
import org.mifos.mobile.core.ui.utils.ScreenUiState.Network
import org.mifos.mobile.feature.savingsaccount.utils.FilterUtil
import kotlin.collections.orEmpty

Expand Down Expand Up @@ -55,9 +55,7 @@ class SavingsAccountViewmodel(
observeNetwork()
}

/**
* Observes the network connectivity status and updates state accordingly.
*/
/** Observes the network connectivity status and updates state accordingly. */
private fun observeNetwork() {
viewModelScope.launch {
networkMonitor.isOnline
Expand Down Expand Up @@ -140,9 +138,9 @@ class SavingsAccountViewmodel(
}

/**
* Retries the data fetching process. If the network is unavailable, it shows
* a network error dialog. Otherwise, it triggers the `loadAccounts` `fetchClient`,
* `fetchLonPurpose` function.
* A helper function to update the mutable state flow.
*
* @param update A lambda function that takes the current state and returns a new state.
Comment on lines +141 to +143
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix incorrect documentation.

The KDoc describes updateState but is placed above the retry() function. This appears to be a copy-paste error from lines 101-104.

Apply this diff to correct the documentation:

-    /**
-     * A helper function to update the mutable state flow.
-     *
-     * @param update A lambda function that takes the current state and returns a new state.
-     */
+    /**
+     * Retries loading accounts based on network status.
+     * Shows network error if offline, otherwise reloads accounts.
+     */
     private fun retry() {
🤖 Prompt for AI Agents
In
feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccount/SavingsAccountViewmodel.kt
around lines 141-143, the KDoc that documents updateState was mistakenly left
above the retry() function; move that KDoc block to directly above the
updateState declaration (where lines ~101-104 originally referenced) and replace
the KDoc above retry() with a short, accurate comment describing retry()’s
purpose (e.g., triggers a retry of the last operation or refreshes state).
Ensure the moved KDoc matches the updateState signature and the new retry() KDoc
matches retry() behavior.

*/
private fun retry() {
viewModelScope.launch {
Expand All @@ -155,17 +153,15 @@ class SavingsAccountViewmodel(
}

/**
* Toggles visibility of the total savings amount in UI.
*/
* Toggles visibility of total savings amount in UI.
* */
private fun handleAmountVisible() {
mutableStateFlow.update {
it.copy(isAmountVisible = !state.isAmountVisible)
}
}

/**
* Dismisses any active dialog in the UI.
*/
/** Dismisses any active dialog. */
private fun handleDismissDialog() {
mutableStateFlow.update {
it.copy(dialogState = null)
Expand Down Expand Up @@ -230,9 +226,10 @@ class SavingsAccountViewmodel(
is DataState.Success -> {
val allSavings = dataState.data.savingsAccounts.orEmpty()
val filtered = filterAccounts(selectedFilters, allSavings)
val sortedAccounts = sortAccountsByStatus(filtered)
updateState {
it.copy(
decimals = filtered.firstOrNull()?.currency?.decimalPlaces ?: 2,
decimals = sortedAccounts.firstOrNull()?.currency?.decimalPlaces ?: 2,
)
}

Expand All @@ -242,12 +239,12 @@ class SavingsAccountViewmodel(

updateState {
val isEmptyAccounts = allSavings.isEmpty()
val isFilteredEmpty = filtered.isEmpty()
val isFilteredEmpty = sortedAccounts.isEmpty()

it.copy(
items = filtered.size,
items = sortedAccounts.size,
isFilteredEmpty = isFilteredEmpty,
savingsAccount = filtered,
savingsAccount = sortedAccounts,
originalAccounts = allSavings,
selectedFilters = selectedFilters,
currency = allSavings.firstOrNull()?.currency?.displaySymbol,
Expand All @@ -262,6 +259,7 @@ class SavingsAccountViewmodel(
}
}


/**
* Filters the accounts based on the selected filters (status).
*
Expand All @@ -280,15 +278,20 @@ class SavingsAccountViewmodel(
} else {
accounts
}

return filteredByStatus.distinct()
}


/**
* Calculates the total savings balance and updates state.
*
* @param accounts List of [SavingAccount] to compute totals from.
*/
private fun sortAccountsByStatus(accounts: List<SavingAccount>): List<SavingAccount> {
return accounts.sortedWith(compareBy { state.statusOrder.indexOf(it.status?.value) })
}

/** Calculates total savings balance and updates state. */
private fun getTotalSavingAmount(accounts: List<SavingAccount>?) {
var amount = 0.0
var items = 0
Expand Down Expand Up @@ -352,6 +355,14 @@ data class SavingsAccountState(
val uiState: ScreenUiState? = ScreenUiState.Loading,

val networkStatus: Boolean = false,

/** Order of statuses for consistent sorting */
val statusOrder: List<String> = listOf(
SavingStatus.ACTIVE.status,
SavingStatus.SUBMIT_AND_PENDING_APPROVAL.status,
SavingStatus.CLOSED.status,
SavingStatus.INACTIVE.status,
),
) {

/**
Expand Down
Loading