Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
@@ -0,0 +1,29 @@
/*
* Copyright 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
*/
package org.mifos.mobile.core.model

import kotlinx.serialization.Serializable

@Serializable
enum class SavingStatus(val status: String) {

ACTIVE("Active"),
INACTIVE("Inactive"),
CLOSED("Closed"),
SUBMIT_AND_PENDING_APPROVAL("Submitted and pending approval"),
;

companion object {
fun fromStatus(status: String): SavingStatus {
return entries.find { it.status.equals(status, ignoreCase = true) }
?: throw IllegalArgumentException("Invalid status: $status")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
<string name="feature_savings_withdraw_request_failed_message">Request to withdraw the account is failed. Please try again </string>

<string name="feature_savings_no_accounts_found">No Savings Accounts Found</string>
<string name="feature_generic_error_server">Server issue from our side cannot proceed further, Try again after a moment</string>

</resources>
<string name="feature_generic_error_server">Server issue from our side cannot proceed further, Try again after a moment</string>



</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.collections.immutable.ImmutableList
import mifos_mobile.feature.savings_account.generated.resources.Res
import mifos_mobile.feature.savings_account.generated.resources.feature_account_action_update
import mifos_mobile.feature.savings_account.generated.resources.feature_account_details_top_bar_title
Expand Down Expand Up @@ -102,6 +101,18 @@ internal fun SavingsAccountDetailsScreen(
uiState.product,
)
}

SavingsAccountDetailsEvent.ShowTransactions -> {
navigateToSavingsAccountTransactionScreen(uiState.accountId)
}

SavingsAccountDetailsEvent.ShowCharges -> {
navigateToClientChargeScreen(ChargeType.SAVINGS.name, uiState.accountId)
}

SavingsAccountDetailsEvent.ShowQrCode -> {
navigateToQrCodeScreen(viewModel.getQrString())
}
}
}

Expand All @@ -111,13 +122,6 @@ internal fun SavingsAccountDetailsScreen(
{ viewModel.trySendAction(it) }
},
)

SavingsAccountDialogs(
dialogState = uiState.dialogState,
onAction = remember(viewModel) {
{ viewModel.trySendAction(it) }
},
)
}

@Composable
Expand Down Expand Up @@ -175,22 +179,22 @@ internal fun SavingsAccountDetailsContent(
isActive = state.isActive,
)

if (state.isActive) {
if (state.transactionList.isNotEmpty()) {
AccountDetailsGrid(
label = "Last Transactions",
details = state.transactionList,
isActive = state.isActive,
)
}

if (state.isActive) {
SavingsAccountActions(
items = state.items,
onActionClick = {
onAction(SavingsAccountDetailsAction.OnNavigateToAction(it))
},
)
}
val visibleActions = state.savingStatus?.allowedActions ?: emptySet()

SavingsAccountActions(
visibleActions = visibleActions,
onActionClick = {
onAction(SavingsAccountDetailsAction.OnNavigateToAction(it))
},
)
}
}
else -> { }
Expand Down Expand Up @@ -290,7 +294,7 @@ internal fun AccountDetailsGrid(

@Composable
internal fun SavingsAccountActions(
items: ImmutableList<SavingsActionItems>,
visibleActions: Set<SavingsActionItems>,
onActionClick: (String) -> Unit,
) {
Column(
Expand All @@ -304,7 +308,8 @@ internal fun SavingsAccountActions(
FlowRow(
modifier = Modifier.fillMaxWidth(),
) {
items.forEach { item ->
println("Visible Actions: $visibleActions")
visibleActions.forEach { item ->
MifosActionCard(
title = item.title,
subTitle = item.subTitle,
Expand All @@ -318,24 +323,6 @@ internal fun SavingsAccountActions(
}
}

@Composable
internal fun SavingsAccountDialogs(
dialogState: SavingsAccountDetailsState.DialogState?,
onAction: (SavingsAccountDetailsAction) -> Unit,
) {
when (dialogState) {
is SavingsAccountDetailsState.DialogState.Error -> {
MifosErrorComponent(
message = dialogState.message,
onRetry = { onAction(SavingsAccountDetailsAction.OnRetry) },
isRetryEnabled = true,
)
}

null -> Unit
}
}

data class LabelValueItem(
val label: StringResource,
val value: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.runtime.Immutable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
import io.ktor.client.utils.EmptyContent.status
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.update
Expand All @@ -35,7 +36,7 @@ import org.mifos.mobile.core.common.DateHelper
import org.mifos.mobile.core.data.repository.SavingsAccountRepository
import org.mifos.mobile.core.data.util.NetworkMonitor
import org.mifos.mobile.core.datastore.UserPreferencesRepository
import org.mifos.mobile.core.model.LoanStatus
import org.mifos.mobile.core.model.SavingStatus
import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations
import org.mifos.mobile.core.model.entity.templates.account.AccountType
import org.mifos.mobile.core.qr.getAccountDetailsInString
Expand Down Expand Up @@ -227,8 +228,8 @@ internal class SavingsAccountDetailsViewModel(
}

private fun extractDetails(savings: SavingsWithAssociations) {
val isActive = savings.status?.value == LoanStatus.ACTIVE.status
val isUpdate = savings.status?.value == LoanStatus.SUBMIT_AND_PENDING_APPROVAL.status
val isActive = savings.status?.value == SavingStatus.ACTIVE.status
val isUpdate = savings.status?.value == SavingStatus.SUBMIT_AND_PENDING_APPROVAL.status

val currencyCode = savings.currency?.code
val decimalPlaces = savings.currency?.decimalPlaces
Expand Down Expand Up @@ -271,8 +272,9 @@ internal class SavingsAccountDetailsViewModel(
)
} ?: emptyList()

mutableStateFlow.update {
updateState {
it.copy(
savingStatus = SavingStatus.fromStatus(savings.status?.value ?: ""),
isActive = isActive,
isUpdatable = isUpdate,
accountId = savings.id ?: -1L,
Expand Down Expand Up @@ -308,6 +310,7 @@ internal data class SavingsAccountDetailsState(
val product: String? = "",
val displayItems: List<LabelValueItem> = emptyList(),
val transactionList: List<LabelValueItem> = emptyList(),
val savingStatus: SavingStatus? = null,
val isActive: Boolean = false,
val items: ImmutableList<SavingsActionItems>,

Expand All @@ -325,6 +328,27 @@ internal data class SavingsAccountDetailsState(
data class Error(val message: String) : DialogState
}
}
val SavingStatus.allowedActions: Set<SavingsActionItems>
get() = when (this) {
SavingStatus.ACTIVE -> setOf(
SavingsActionItems.Transactions,
SavingsActionItems.Charges,
SavingsActionItems.QrCode,
SavingsActionItems.Transfer,
)
SavingStatus.INACTIVE -> setOf(
SavingsActionItems.Transfer,
SavingsActionItems.QrCode,
)
SavingStatus.CLOSED -> setOf(
SavingsActionItems.QrCode,
SavingsActionItems.Transfer,
SavingsActionItems.Transactions,
)
SavingStatus.SUBMIT_AND_PENDING_APPROVAL -> setOf(
SavingsActionItems.QrCode,
)
}

/**
* One-time navigation or effect events for the SavingsAccountDetails screen.
Expand All @@ -338,6 +362,12 @@ sealed interface SavingsAccountDetailsEvent {

/** Trigger Update Amount */
data object UpdateAccount : SavingsAccountDetailsEvent

data object ShowTransactions : SavingsAccountDetailsEvent

data object ShowCharges : SavingsAccountDetailsEvent

data object ShowQrCode : SavingsAccountDetailsEvent
}

/**
Expand Down
Loading