mirror of
https://github.com/openMF/mifos-mobile.git
synced 2026-02-06 11:26:51 +00:00
Merge branch 'development' into ttifc
# Conflicts: # core/network/src/main/java/org/mifos/mobile/core/network/BaseURL.kt # fastlane-config/android_config.rb
This commit is contained in:
commit
fdf2aba89f
@ -26,10 +26,13 @@ import org.mifos.library.passcode.navigateToPasscodeScreen
|
||||
import org.mifos.mobile.HomeActivity
|
||||
import org.mifos.mobile.R
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.enums.AccountType
|
||||
import org.mifos.mobile.core.model.enums.ChargeType
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.feature.about.navigation.aboutUsNavGraph
|
||||
import org.mifos.mobile.feature.about.navigation.navigateToAboutUsScreen
|
||||
import org.mifos.mobile.feature.account.navigation.ClientAccountsNavigation
|
||||
import org.mifos.mobile.feature.account.navigation.clientAccountsNavGraph
|
||||
import org.mifos.mobile.feature.account.navigation.navigateToClientAccountsScreen
|
||||
import org.mifos.mobile.feature.auth.navigation.authenticationNavGraph
|
||||
@ -47,6 +50,7 @@ import org.mifos.mobile.feature.help.navigation.navigateToHelpScreen
|
||||
import org.mifos.mobile.feature.home.navigation.HomeDestinations
|
||||
import org.mifos.mobile.feature.home.navigation.HomeNavigation
|
||||
import org.mifos.mobile.feature.home.navigation.homeNavGraph
|
||||
import org.mifos.mobile.feature.home.navigation.navigateToHomeScreen
|
||||
import org.mifos.mobile.feature.loan.navigation.loanNavGraph
|
||||
import org.mifos.mobile.feature.loan.navigation.navigateToLoanApplication
|
||||
import org.mifos.mobile.feature.loan.navigation.navigateToLoanDetailScreen
|
||||
@ -157,7 +161,23 @@ fun MifosNavHost(
|
||||
},
|
||||
)
|
||||
|
||||
transferProcessNavGraph(navigateBack = navController::popBackStack)
|
||||
transferProcessNavGraph(
|
||||
navigateBack = navController::popBackStack,
|
||||
onTransferSuccessNavigate = { destination ->
|
||||
when (destination) {
|
||||
TransferSuccessDestination.HOME -> navController.navigateToHomeScreen()
|
||||
TransferSuccessDestination.LOAN_ACCOUNT -> navController.navigateToClientAccountsScreen(
|
||||
AccountType.LOAN,
|
||||
ClientAccountsNavigation.ClientAccountsBase.route,
|
||||
)
|
||||
|
||||
TransferSuccessDestination.SAVINGS_ACCOUNT -> navController.navigateToClientAccountsScreen(
|
||||
AccountType.SAVINGS,
|
||||
ClientAccountsNavigation.ClientAccountsBase.route,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
beneficiaryNavGraph(
|
||||
navController = navController,
|
||||
@ -211,7 +231,11 @@ fun handleHomeNavigation(
|
||||
}
|
||||
|
||||
HomeDestinations.RECENT_TRANSACTIONS -> navController.navigateToRecentTransaction()
|
||||
HomeDestinations.CHARGES -> navController.navigateToClientChargeScreen(ChargeType.CLIENT, -1L)
|
||||
HomeDestinations.CHARGES -> navController.navigateToClientChargeScreen(
|
||||
ChargeType.CLIENT,
|
||||
-1L,
|
||||
)
|
||||
|
||||
HomeDestinations.THIRD_PARTY_TRANSFER -> navController.navigateToThirdPartyTransfer()
|
||||
HomeDestinations.SETTINGS -> navController.navigateToSettings()
|
||||
HomeDestinations.ABOUT_US -> navController.navigateToAboutUsScreen()
|
||||
@ -228,6 +252,8 @@ fun handleHomeNavigation(
|
||||
HomeDestinations.TRANSFER -> navController.navigateToSavingsMakeTransfer(
|
||||
accountId = 1,
|
||||
transferType = TRANSFER_PAY_TO,
|
||||
transferTarget = TransferType.SELF,
|
||||
transferSuccessDestination = TransferSuccessDestination.HOME,
|
||||
)
|
||||
|
||||
HomeDestinations.BENEFICIARIES -> navController.navigateToBeneficiaryListScreen()
|
||||
|
||||
@ -28,6 +28,8 @@ object Constants {
|
||||
const val TRANSACTIONS = "transactions"
|
||||
const val DFRAG_DATE_PICKER = "Date Picker"
|
||||
const val TRANSFER_TYPE = "transfer_type"
|
||||
const val TRANSFER_TARGET = "transfer_target"
|
||||
const val TRANSFER_SUCCESS_DESTINATION = "transfer_success_destination"
|
||||
const val TRANSFER_QUICK = "transfer_quick"
|
||||
const val TRANSFER_PAY_TO = "transfer_pay_to"
|
||||
const val TRANSFER_PAY_FROM = "transfer_pay_from"
|
||||
|
||||
@ -29,5 +29,5 @@ interface BeneficiaryRepository {
|
||||
|
||||
suspend fun deleteBeneficiary(beneficiaryId: Long?): Flow<ResponseBody>
|
||||
|
||||
suspend fun beneficiaryList(): Flow<List<Beneficiary>>
|
||||
fun beneficiaryList(): Flow<List<Beneficiary>>
|
||||
}
|
||||
|
||||
@ -39,5 +39,5 @@ interface SavingsAccountRepository {
|
||||
payload: SavingsAccountWithdrawPayload?,
|
||||
): Flow<ResponseBody>
|
||||
|
||||
fun accountTransferTemplate(accountId: Long?, accountType: Long?): Flow<AccountOptionsTemplate>
|
||||
fun accountTransferTemplate(): Flow<AccountOptionsTemplate>
|
||||
}
|
||||
|
||||
@ -14,5 +14,5 @@ import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTempla
|
||||
|
||||
interface ThirdPartyTransferRepository {
|
||||
|
||||
suspend fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate>
|
||||
fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate>
|
||||
}
|
||||
|
||||
@ -29,8 +29,6 @@ interface TransferRepository {
|
||||
transferDescription: String?,
|
||||
dateFormat: String = "dd MMMM yyyy",
|
||||
locale: String = "en",
|
||||
fromAccountNumber: String?,
|
||||
toAccountNumber: String?,
|
||||
transferType: TransferType?,
|
||||
): Flow<ResponseBody>
|
||||
}
|
||||
|
||||
@ -9,9 +9,13 @@
|
||||
*/
|
||||
package org.mifos.mobile.core.data.repositoryImpl
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import okhttp3.ResponseBody
|
||||
import org.mifos.mobile.core.common.network.Dispatcher
|
||||
import org.mifos.mobile.core.common.network.MifosDispatchers
|
||||
import org.mifos.mobile.core.data.repository.BeneficiaryRepository
|
||||
import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary
|
||||
import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryPayload
|
||||
@ -22,6 +26,8 @@ import javax.inject.Inject
|
||||
|
||||
class BeneficiaryRepositoryImp @Inject constructor(
|
||||
private val dataManager: DataManager,
|
||||
@Dispatcher(MifosDispatchers.IO)
|
||||
private val ioDispatcher: CoroutineDispatcher,
|
||||
) : BeneficiaryRepository {
|
||||
|
||||
override suspend fun beneficiaryTemplate(): Flow<BeneficiaryTemplate> {
|
||||
@ -51,9 +57,9 @@ class BeneficiaryRepositoryImp @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun beneficiaryList(): Flow<List<Beneficiary>> {
|
||||
override fun beneficiaryList(): Flow<List<Beneficiary>> {
|
||||
return flow {
|
||||
emit(dataManager.beneficiaryList())
|
||||
}
|
||||
}.flowOn(ioDispatcher)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,9 +9,13 @@
|
||||
*/
|
||||
package org.mifos.mobile.core.data.repositoryImpl
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import okhttp3.ResponseBody
|
||||
import org.mifos.mobile.core.common.network.Dispatcher
|
||||
import org.mifos.mobile.core.common.network.MifosDispatchers
|
||||
import org.mifos.mobile.core.data.repository.SavingsAccountRepository
|
||||
import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload
|
||||
import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountUpdatePayload
|
||||
@ -24,6 +28,8 @@ import javax.inject.Inject
|
||||
|
||||
class SavingsAccountRepositoryImp @Inject constructor(
|
||||
private val dataManager: DataManager,
|
||||
@Dispatcher(MifosDispatchers.IO)
|
||||
private val ioDispatcher: CoroutineDispatcher,
|
||||
) : SavingsAccountRepository {
|
||||
|
||||
override suspend fun getSavingsWithAssociations(
|
||||
@ -69,17 +75,9 @@ class SavingsAccountRepositoryImp @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun accountTransferTemplate(
|
||||
accountId: Long?,
|
||||
accountType: Long?,
|
||||
): Flow<AccountOptionsTemplate> {
|
||||
override fun accountTransferTemplate(): Flow<AccountOptionsTemplate> {
|
||||
return flow {
|
||||
emit(
|
||||
dataManager.accountTransferTemplate(
|
||||
accountId = accountType,
|
||||
accountType = accountType,
|
||||
),
|
||||
)
|
||||
}
|
||||
emit(dataManager.accountTransferTemplate())
|
||||
}.flowOn(ioDispatcher)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,12 @@
|
||||
*/
|
||||
package org.mifos.mobile.core.data.repositoryImpl
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.mifos.mobile.core.common.network.Dispatcher
|
||||
import org.mifos.mobile.core.common.network.MifosDispatchers
|
||||
import org.mifos.mobile.core.data.repository.ThirdPartyTransferRepository
|
||||
import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate
|
||||
import org.mifos.mobile.core.network.DataManager
|
||||
@ -18,11 +22,13 @@ import javax.inject.Inject
|
||||
|
||||
class ThirdPartyTransferRepositoryImp @Inject constructor(
|
||||
private val dataManager: DataManager,
|
||||
@Dispatcher(MifosDispatchers.IO)
|
||||
private val ioDispatcher: CoroutineDispatcher,
|
||||
) : ThirdPartyTransferRepository {
|
||||
|
||||
override suspend fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate> {
|
||||
override fun thirdPartyTransferTemplate(): Flow<AccountOptionsTemplate> {
|
||||
return flow {
|
||||
emit(dataManager.thirdPartyTransferTemplate())
|
||||
}
|
||||
}.flowOn(ioDispatcher)
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,8 +35,6 @@ class TransferRepositoryImp @Inject constructor(
|
||||
transferDescription: String?,
|
||||
dateFormat: String,
|
||||
locale: String,
|
||||
fromAccountNumber: String?,
|
||||
toAccountNumber: String?,
|
||||
transferType: TransferType?,
|
||||
): Flow<ResponseBody> {
|
||||
val transferPayload = TransferPayload().apply {
|
||||
@ -53,8 +51,6 @@ class TransferRepositoryImp @Inject constructor(
|
||||
this.transferDescription = transferDescription
|
||||
this.dateFormat = dateFormat
|
||||
this.locale = locale
|
||||
this.fromAccountNumber = fromAccountNumber
|
||||
this.toAccountNumber = toAccountNumber
|
||||
}
|
||||
return flow {
|
||||
emit(
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.entity
|
||||
|
||||
enum class TransferSuccessDestination {
|
||||
SAVINGS_ACCOUNT,
|
||||
LOAN_ACCOUNT,
|
||||
HOME,
|
||||
}
|
||||
@ -80,7 +80,6 @@ data class LoanAccount(
|
||||
parcel.readString(),
|
||||
parcel.readParcelable(Timeline::class.java.classLoader),
|
||||
)
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeLong(loanProductId)
|
||||
parcel.writeString(externalId)
|
||||
|
||||
@ -44,10 +44,8 @@ data class TransferPayload(
|
||||
|
||||
var locale: String = "en",
|
||||
|
||||
@Transient
|
||||
var fromAccountNumber: String? = null,
|
||||
|
||||
@Transient
|
||||
var toAccountNumber: String? = null,
|
||||
|
||||
) : Parcelable
|
||||
|
||||
@ -22,8 +22,4 @@ data class AccountOptionsTemplate(
|
||||
var fromAccountOptions: List<AccountOption> = ArrayList(),
|
||||
|
||||
var toAccountOptions: List<AccountOption> = ArrayList(),
|
||||
|
||||
var fromAccountTypeOptions: List<AccountType> = ArrayList(),
|
||||
|
||||
var toAccountTypeOptions: List<AccountType> = ArrayList(),
|
||||
) : Parcelable
|
||||
|
||||
@ -110,11 +110,8 @@ class DataManager @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun accountTransferTemplate(
|
||||
accountId: Long?,
|
||||
accountType: Long?,
|
||||
): AccountOptionsTemplate =
|
||||
baseApiManager.savingAccountsListApi.accountTransferTemplate(accountId, accountType)
|
||||
suspend fun accountTransferTemplate(): AccountOptionsTemplate =
|
||||
baseApiManager.savingAccountsListApi.accountTransferTemplate()
|
||||
|
||||
suspend fun makeTransfer(transferPayload: TransferPayload?): ResponseBody {
|
||||
return baseApiManager.savingAccountsListApi.makeTransfer(transferPayload)
|
||||
|
||||
@ -33,10 +33,7 @@ interface SavingAccountsListService {
|
||||
): SavingsWithAssociations
|
||||
|
||||
@GET(ApiEndPoints.ACCOUNT_TRANSFER + "/template")
|
||||
suspend fun accountTransferTemplate(
|
||||
@Query("fromAccountId") accountId: Long?,
|
||||
@Query("fromAccountType") accountType: Long?,
|
||||
): AccountOptionsTemplate
|
||||
suspend fun accountTransferTemplate(): AccountOptionsTemplate
|
||||
|
||||
@POST(ApiEndPoints.ACCOUNT_TRANSFER)
|
||||
suspend fun makeTransfer(@Body transferPayload: TransferPayload?): ResponseBody
|
||||
|
||||
@ -55,9 +55,10 @@ internal fun ClientAccountsScreen(
|
||||
val context = LocalContext.current
|
||||
|
||||
var isDialogActive by rememberSaveable { mutableStateOf(false) }
|
||||
var currentPage by rememberSaveable { mutableIntStateOf(0) }
|
||||
|
||||
val accountType by viewModel.accountType.collectAsStateWithLifecycle()
|
||||
|
||||
var currentPage by rememberSaveable { mutableIntStateOf(accountType?.ordinal ?: 0) }
|
||||
val filterList by viewModel.filterList.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(key1 = accountType) {
|
||||
|
||||
@ -19,8 +19,17 @@ import org.mifos.mobile.core.common.Constants
|
||||
import org.mifos.mobile.core.model.enums.AccountType
|
||||
import org.mifos.mobile.feature.account.clientAccount.screens.ClientAccountsScreen
|
||||
|
||||
fun NavController.navigateToClientAccountsScreen(accountType: AccountType = AccountType.SAVINGS) {
|
||||
navigate(ClientAccountsNavigation.ClientAccountsScreen.passArguments(accountType = accountType))
|
||||
fun NavController.navigateToClientAccountsScreen(
|
||||
accountType: AccountType = AccountType.SAVINGS,
|
||||
popUpToDestination: String? = null,
|
||||
) {
|
||||
navigate(ClientAccountsNavigation.ClientAccountsScreen.passArguments(accountType = accountType)) {
|
||||
if (popUpToDestination != null) {
|
||||
popUpTo(
|
||||
popUpToDestination,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun NavGraphBuilder.clientAccountsNavGraph(
|
||||
|
||||
@ -24,8 +24,10 @@ import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
|
||||
import org.mifos.mobile.core.common.Network
|
||||
import org.mifos.mobile.core.designsystem.components.MifosScaffold
|
||||
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations
|
||||
import org.mifos.mobile.core.model.enums.ChargeType
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.core.ui.component.EmptyDataView
|
||||
import org.mifos.mobile.core.ui.component.MifosProgressIndicator
|
||||
import org.mifos.mobile.core.ui.component.NoInternet
|
||||
@ -43,7 +45,13 @@ internal fun LoanAccountDetailScreen(
|
||||
viewRepaymentSchedule: (Long) -> Unit,
|
||||
viewTransactions: (Long) -> Unit,
|
||||
viewQr: (String) -> Unit,
|
||||
makePayment: (accountId: Long, outstandingBalance: Double?, transferType: String) -> Unit,
|
||||
makePayment: (
|
||||
accountId: Long,
|
||||
outstandingBalance: Double?,
|
||||
transferType: String,
|
||||
transferTarget: TransferType,
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: LoanAccountsDetailViewModel = hiltViewModel(),
|
||||
) {
|
||||
@ -68,6 +76,8 @@ internal fun LoanAccountDetailScreen(
|
||||
loanId,
|
||||
viewModel.loanWithAssociations?.summary?.totalOutstanding,
|
||||
TRANSFER_PAY_TO,
|
||||
TransferType.SELF,
|
||||
TransferSuccessDestination.LOAN_ACCOUNT,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@ -16,8 +16,10 @@ import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.navigation
|
||||
import androidx.navigation.navArgument
|
||||
import org.mifos.mobile.core.common.Constants
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.enums.ChargeType
|
||||
import org.mifos.mobile.core.model.enums.LoanState
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.feature.loan.loanAccount.LoanAccountDetailScreen
|
||||
import org.mifos.mobile.feature.loan.loanAccountApplication.LoanApplicationScreen
|
||||
import org.mifos.mobile.feature.loan.loanAccountSummary.LoanAccountSummaryScreen
|
||||
@ -62,7 +64,13 @@ fun NavGraphBuilder.loanNavGraph(
|
||||
viewGuarantor: (Long) -> Unit,
|
||||
viewCharges: (ChargeType, Long) -> Unit,
|
||||
viewQr: (String) -> Unit,
|
||||
makePayment: (accountId: Long, outstandingBalance: Double?, transferType: String) -> Unit,
|
||||
makePayment: (
|
||||
accountId: Long,
|
||||
outstandingBalance: Double?,
|
||||
transferType: String,
|
||||
transferTarget: TransferType,
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
) -> Unit,
|
||||
) {
|
||||
navigation(
|
||||
startDestination = LoanNavigation.LoanDetail.route,
|
||||
@ -138,7 +146,13 @@ fun NavGraphBuilder.loanDetailRoute(
|
||||
viewRepaymentSchedule: (Long) -> Unit,
|
||||
viewTransactions: (Long) -> Unit,
|
||||
viewQr: (String) -> Unit,
|
||||
makePayment: (accountId: Long, outstandingBalance: Double?, transferType: String) -> Unit,
|
||||
makePayment: (
|
||||
accountId: Long,
|
||||
outstandingBalance: Double?,
|
||||
transferType: String,
|
||||
transferTarget: TransferType,
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
) -> Unit,
|
||||
) {
|
||||
composable(
|
||||
route = LoanNavigation.LoanDetail.route,
|
||||
|
||||
@ -21,7 +21,10 @@ import org.mifos.mobile.core.common.Constants.OUTSTANDING_BALANCE
|
||||
import org.mifos.mobile.core.common.Constants.SAVINGS_ID
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_FROM
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_TARGET
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
|
||||
import org.mifos.mobile.core.model.enums.ChargeType
|
||||
import org.mifos.mobile.core.model.enums.SavingsAccountState
|
||||
@ -36,12 +39,16 @@ fun NavController.navigateToSavingsMakeTransfer(
|
||||
accountId: Long,
|
||||
outstandingBalance: Double? = null,
|
||||
transferType: String,
|
||||
transferTarget: TransferType,
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
) {
|
||||
navigate(
|
||||
SavingsNavigation.SavingsMakeTransfer.passArguments(
|
||||
accountId,
|
||||
(outstandingBalance ?: 0.0).toString(),
|
||||
transferType,
|
||||
accountId = accountId,
|
||||
outstandingBalance = (outstandingBalance ?: 0.0).toString(),
|
||||
transferType = transferType,
|
||||
transferTarget = transferTarget,
|
||||
transferSuccessDestination = transferSuccessDestination,
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -63,7 +70,7 @@ fun NavGraphBuilder.savingsNavGraph(
|
||||
navController: NavController,
|
||||
viewQrCode: (String) -> Unit,
|
||||
viewCharges: (ChargeType, Long) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
|
||||
callHelpline: () -> Unit,
|
||||
) {
|
||||
navigation(
|
||||
@ -76,12 +83,16 @@ fun NavGraphBuilder.savingsNavGraph(
|
||||
navController.navigateToSavingsMakeTransfer(
|
||||
accountId = it,
|
||||
transferType = TRANSFER_PAY_TO,
|
||||
transferTarget = TransferType.TPT,
|
||||
transferSuccessDestination = TransferSuccessDestination.SAVINGS_ACCOUNT,
|
||||
)
|
||||
},
|
||||
makeTransfer = {
|
||||
navController.navigateToSavingsMakeTransfer(
|
||||
accountId = it,
|
||||
transferType = TRANSFER_PAY_FROM,
|
||||
transferTarget = TransferType.TPT,
|
||||
transferSuccessDestination = TransferSuccessDestination.SAVINGS_ACCOUNT,
|
||||
)
|
||||
},
|
||||
navigateBack = navController::popBackStack,
|
||||
@ -203,7 +214,7 @@ fun NavGraphBuilder.savingsWithdraw(
|
||||
|
||||
fun NavGraphBuilder.savingsMakeTransfer(
|
||||
navigateBack: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
|
||||
) {
|
||||
composable(
|
||||
route = SavingsNavigation.SavingsMakeTransfer.route,
|
||||
@ -215,6 +226,10 @@ fun NavGraphBuilder.savingsMakeTransfer(
|
||||
defaultValue = null
|
||||
},
|
||||
navArgument(name = TRANSFER_TYPE) { type = NavType.StringType },
|
||||
navArgument(name = TRANSFER_TARGET) { type = NavType.StringType },
|
||||
navArgument(name = TRANSFER_SUCCESS_DESTINATION) {
|
||||
type = NavType.EnumType(TransferSuccessDestination::class.java)
|
||||
},
|
||||
),
|
||||
) {
|
||||
SavingsMakeTransferScreen(
|
||||
|
||||
@ -13,8 +13,12 @@ import org.mifos.mobile.core.common.Constants.ACCOUNT_ID
|
||||
import org.mifos.mobile.core.common.Constants.OUTSTANDING_BALANCE
|
||||
import org.mifos.mobile.core.common.Constants.SAVINGS_ACCOUNT_STATE
|
||||
import org.mifos.mobile.core.common.Constants.SAVINGS_ID
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_TARGET
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.enums.SavingsAccountState
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
|
||||
const val SAVINGS_NAVIGATION_ROUTE_BASE = "savings_route"
|
||||
const val SAVINGS_DETAIL_SCREEN_ROUTE = "savings_detail_screen_route"
|
||||
@ -60,14 +64,26 @@ sealed class SavingsNavigation(val route: String) {
|
||||
}
|
||||
|
||||
data object SavingsMakeTransfer : SavingsNavigation(
|
||||
route = "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/{$ACCOUNT_ID}/{$OUTSTANDING_BALANCE}/{$TRANSFER_TYPE}",
|
||||
route = "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/" +
|
||||
"{$ACCOUNT_ID}/" +
|
||||
"{$OUTSTANDING_BALANCE}/" +
|
||||
"{$TRANSFER_TYPE}/" +
|
||||
"{$TRANSFER_TARGET}/" +
|
||||
"{$TRANSFER_SUCCESS_DESTINATION}",
|
||||
) {
|
||||
fun passArguments(
|
||||
accountId: Long,
|
||||
outstandingBalance: String? = null,
|
||||
transferType: String,
|
||||
transferTarget: TransferType,
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
): String {
|
||||
return "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/$accountId/$outstandingBalance/$transferType"
|
||||
return "$SAVINGS_MAKE_TRANSFER_SCREEN_ROUTE/" +
|
||||
"$accountId/" +
|
||||
"$outstandingBalance/" +
|
||||
"$transferType/" +
|
||||
"${transferTarget.name}/" +
|
||||
transferSuccessDestination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +112,9 @@ internal fun SavingsMakeTransferContent(
|
||||
R.string.one -> PayToStepContent(
|
||||
modifier = processModifier,
|
||||
processState = payToStepState,
|
||||
toAccountOptions = uiData.accountOptionsTemplate.fromAccountOptions,
|
||||
toAccountOptions = uiData.toAccountOptions
|
||||
.filter { it.accountType?.value == "Loan Account" }
|
||||
.distinctBy { it.accountId },
|
||||
prefilledAccount = payToAccount,
|
||||
onContinueClick = {
|
||||
payToAccount = it
|
||||
@ -123,7 +125,8 @@ internal fun SavingsMakeTransferContent(
|
||||
R.string.two -> PayFromStep(
|
||||
modifier = processModifier,
|
||||
processState = payFromStepState,
|
||||
fromAccountOptions = uiData.accountOptionsTemplate.fromAccountOptions,
|
||||
fromAccountOptions = uiData.fromAccountOptions.distinctBy { it.accountNo }
|
||||
.filter { it.accountNo != payToAccount?.accountNo },
|
||||
prefilledAccount = payFromAccount,
|
||||
onContinueClick = {
|
||||
payFromAccount = it
|
||||
@ -260,7 +263,6 @@ private fun EnterAmountStep(
|
||||
showAmountError = false
|
||||
amountError = when {
|
||||
amount.text.trim() == "" -> R.string.enter_amount
|
||||
amount.text.contains(".") -> R.string.invalid_amount
|
||||
amount.text.toDoubleOrNull() == 0.0 -> R.string.amount_greater_than_zero
|
||||
else -> null
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
@ -23,6 +24,7 @@ import org.mifos.mobile.core.common.Constants
|
||||
import org.mifos.mobile.core.common.Network
|
||||
import org.mifos.mobile.core.designsystem.components.MifosScaffold
|
||||
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.core.ui.component.MifosErrorComponent
|
||||
@ -34,27 +36,32 @@ import org.mifos.mobile.feature.savings.R
|
||||
internal fun SavingsMakeTransferScreen(
|
||||
onCancelledClicked: () -> Unit,
|
||||
navigateBack: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: SavingsMakeTransferViewModel = hiltViewModel(),
|
||||
) {
|
||||
val uiState = viewModel.savingsMakeTransferUiState.collectAsStateWithLifecycle()
|
||||
val uiData = viewModel.savingsMakeTransferUiData.collectAsStateWithLifecycle()
|
||||
val transferSuccessDestination by
|
||||
viewModel.transferSuccessDestination.collectAsStateWithLifecycle()
|
||||
|
||||
SavingsMakeTransferScreen(
|
||||
navigateBack = navigateBack,
|
||||
onCancelledClicked = onCancelledClicked,
|
||||
uiState = uiState.value,
|
||||
uiData = uiData.value,
|
||||
modifier = modifier,
|
||||
reviewTransfer = { reviewTransfer(it, TransferType.SELF) },
|
||||
reviewTransfer = {
|
||||
reviewTransfer(
|
||||
it,
|
||||
TransferType.SELF,
|
||||
transferSuccessDestination,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SavingsMakeTransferScreen(
|
||||
uiState: SavingsMakeTransferUiState,
|
||||
uiData: SavingsMakeTransferUiData,
|
||||
navigateBack: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@ -63,10 +70,16 @@ private fun SavingsMakeTransferScreen(
|
||||
val context = LocalContext.current
|
||||
|
||||
MifosScaffold(
|
||||
topBarTitleResId = if (uiData.transferType == Constants.TRANSFER_PAY_TO) {
|
||||
R.string.deposit
|
||||
} else {
|
||||
R.string.transfer
|
||||
topBarTitleResId = when (uiState) {
|
||||
is SavingsMakeTransferUiState.ShowUI -> {
|
||||
if (uiState.data.transferType == Constants.TRANSFER_PAY_TO) {
|
||||
R.string.deposit
|
||||
} else {
|
||||
R.string.transfer
|
||||
}
|
||||
}
|
||||
|
||||
else -> R.string.transfer
|
||||
},
|
||||
navigateBack = navigateBack,
|
||||
modifier = modifier,
|
||||
@ -76,16 +89,17 @@ private fun SavingsMakeTransferScreen(
|
||||
.padding(it)
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
SavingsMakeTransferContent(
|
||||
uiData = uiData,
|
||||
reviewTransfer = reviewTransfer,
|
||||
onCancelledClicked = onCancelledClicked,
|
||||
)
|
||||
|
||||
when (uiState) {
|
||||
is SavingsMakeTransferUiState.ShowUI -> Unit
|
||||
is SavingsMakeTransferUiState.ShowUI -> {
|
||||
SavingsMakeTransferContent(
|
||||
uiData = uiState.data,
|
||||
reviewTransfer = reviewTransfer,
|
||||
onCancelledClicked = onCancelledClicked,
|
||||
)
|
||||
}
|
||||
|
||||
is SavingsMakeTransferUiState.Loading -> MifosProgressIndicatorOverlay()
|
||||
is SavingsMakeTransferUiState.Loading ->
|
||||
MifosProgressIndicatorOverlay()
|
||||
|
||||
is SavingsMakeTransferUiState.Error -> {
|
||||
MifosErrorComponent(
|
||||
@ -104,7 +118,9 @@ internal class SavingsMakeTransferUiStatesPreviews :
|
||||
PreviewParameterProvider<SavingsMakeTransferUiState> {
|
||||
override val values: Sequence<SavingsMakeTransferUiState>
|
||||
get() = sequenceOf(
|
||||
SavingsMakeTransferUiState.ShowUI,
|
||||
SavingsMakeTransferUiState.ShowUI(
|
||||
data = SavingsMakeTransferUiData(),
|
||||
),
|
||||
SavingsMakeTransferUiState.Error(""),
|
||||
SavingsMakeTransferUiState.Loading,
|
||||
)
|
||||
@ -122,7 +138,6 @@ private fun SavingsMakeTransferContentPreview(
|
||||
onCancelledClicked = { },
|
||||
reviewTransfer = { },
|
||||
uiState = savingsMakeTransferUIState,
|
||||
uiData = SavingsMakeTransferUiData(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@ import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
@ -22,83 +21,106 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import org.mifos.mobile.core.common.Constants
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO
|
||||
import org.mifos.mobile.core.data.repository.SavingsAccountRepository
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.templates.account.AccountOption
|
||||
import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.core.network.Result
|
||||
import org.mifos.mobile.core.network.asResult
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class SavingsMakeTransferViewModel @Inject constructor(
|
||||
private val savingsAccountRepositoryImp: SavingsAccountRepository,
|
||||
savingsAccountRepositoryImp: SavingsAccountRepository,
|
||||
// thirdPartyTransferRepository: ThirdPartyTransferRepository,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel() {
|
||||
|
||||
val accountId = savedStateHandle.getStateFlow(key = Constants.ACCOUNT_ID, initialValue = -1L)
|
||||
private val accountId =
|
||||
savedStateHandle.getStateFlow(key = Constants.ACCOUNT_ID, initialValue = -1L)
|
||||
|
||||
private val transferType: StateFlow<String> = savedStateHandle.getStateFlow(
|
||||
key = Constants.TRANSFER_TYPE,
|
||||
initialValue = TRANSFER_PAY_TO,
|
||||
)
|
||||
|
||||
private val transferTarget: StateFlow<String> = savedStateHandle.getStateFlow(
|
||||
key = Constants.TRANSFER_TARGET,
|
||||
initialValue = TransferType.TPT.name,
|
||||
)
|
||||
|
||||
val transferSuccessDestination: StateFlow<TransferSuccessDestination> = savedStateHandle.getStateFlow(
|
||||
key = Constants.TRANSFER_SUCCESS_DESTINATION,
|
||||
initialValue = TransferSuccessDestination.SAVINGS_ACCOUNT,
|
||||
)
|
||||
|
||||
private val outstandingBalance: StateFlow<Double?> = savedStateHandle.getStateFlow<String?>(
|
||||
key = Constants.OUTSTANDING_BALANCE,
|
||||
initialValue = null,
|
||||
).map { balanceString ->
|
||||
balanceString?.toDoubleOrNull() ?: 0.0
|
||||
balanceString?.toDoubleOrNull()
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = 0.0,
|
||||
initialValue = null,
|
||||
)
|
||||
|
||||
private val _savingsMakeTransferUiData = MutableStateFlow(SavingsMakeTransferUiData())
|
||||
val savingsMakeTransferUiData: StateFlow<SavingsMakeTransferUiData> get() = _savingsMakeTransferUiData
|
||||
|
||||
val savingsMakeTransferUiState = accountId
|
||||
.flatMapLatest { id ->
|
||||
savingsAccountRepositoryImp.accountTransferTemplate(accountId = id, accountType = 2L)
|
||||
val savingsMakeTransferUiState: StateFlow<SavingsMakeTransferUiState> =
|
||||
transferTarget.flatMapLatest { target ->
|
||||
savingsAccountRepositoryImp.accountTransferTemplate()
|
||||
// when (target) {
|
||||
// TransferType.TPT.name -> thirdPartyTransferRepository.thirdPartyTransferTemplate()
|
||||
// else -> savingsAccountRepositoryImp.accountTransferTemplate()
|
||||
// }
|
||||
}
|
||||
.asResult()
|
||||
.map { result ->
|
||||
when (result) {
|
||||
is Result.Success ->
|
||||
SavingsMakeTransferUiState.ShowUI
|
||||
.also {
|
||||
_savingsMakeTransferUiData.value = _savingsMakeTransferUiData.value
|
||||
.copy(
|
||||
accountOptionsTemplate = result.data,
|
||||
transferType = transferType.value,
|
||||
outstandingBalance = if (outstandingBalance.value == 0.0) {
|
||||
null
|
||||
} else {
|
||||
outstandingBalance.value
|
||||
},
|
||||
accountId = accountId.value,
|
||||
)
|
||||
}
|
||||
.asResult()
|
||||
.map { result ->
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
SavingsMakeTransferUiState.ShowUI(
|
||||
data = SavingsMakeTransferUiData(
|
||||
accountId = accountId.value,
|
||||
transferType = transferType.value,
|
||||
outstandingBalance = outstandingBalance.value,
|
||||
fromAccountOptions = result.data.fromAccountOptions,
|
||||
toAccountOptions = result.data.toAccountOptions,
|
||||
// fromAccountOptionPrefilled = result.data.fromAccountOptions.find {
|
||||
// accountId.value == it.accountId?.toLong()
|
||||
// },
|
||||
toAccountOptionPrefilled = result.data.toAccountOptions.find {
|
||||
accountId.value == it.accountId?.toLong()
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is Result.Loading -> SavingsMakeTransferUiState.Loading
|
||||
is Result.Error -> SavingsMakeTransferUiState.Error(result.exception.message)
|
||||
is Result.Loading -> {
|
||||
SavingsMakeTransferUiState.Loading
|
||||
}
|
||||
|
||||
is Result.Error -> {
|
||||
SavingsMakeTransferUiState.Error(result.exception.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = SavingsMakeTransferUiState.Loading,
|
||||
)
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = SavingsMakeTransferUiState.Loading,
|
||||
)
|
||||
}
|
||||
|
||||
internal sealed class SavingsMakeTransferUiState {
|
||||
data object Loading : SavingsMakeTransferUiState()
|
||||
data class Error(val errorMessage: String?) : SavingsMakeTransferUiState()
|
||||
data object ShowUI : SavingsMakeTransferUiState()
|
||||
data class ShowUI(val data: SavingsMakeTransferUiData) : SavingsMakeTransferUiState()
|
||||
}
|
||||
|
||||
internal data class SavingsMakeTransferUiData(
|
||||
var accountId: Long? = null,
|
||||
var transferType: String? = null,
|
||||
var outstandingBalance: Double? = null,
|
||||
var accountOptionsTemplate: AccountOptionsTemplate = AccountOptionsTemplate(),
|
||||
var fromAccountOptions: List<AccountOption> = ArrayList(),
|
||||
var toAccountOptions: List<AccountOption> = ArrayList(),
|
||||
var toAccountOptionPrefilled: AccountOption? = null,
|
||||
var fromAccountOptionPrefilled: AccountOption? = null,
|
||||
)
|
||||
|
||||
@ -56,7 +56,7 @@ import org.mifos.mobile.core.ui.utils.DevicePreviews
|
||||
|
||||
@Composable
|
||||
internal fun ThirdPartyTransferContent(
|
||||
accountOption: List<AccountOption>,
|
||||
fromAccountOption: List<AccountOption>,
|
||||
toAccountOption: List<AccountOption>,
|
||||
beneficiaryList: List<Beneficiary>,
|
||||
navigateBack: () -> Unit,
|
||||
@ -112,7 +112,7 @@ internal fun ThirdPartyTransferContent(
|
||||
) { stepModifier ->
|
||||
when (step.second) {
|
||||
R.string.one -> PayFromStep(
|
||||
fromAccountOptions = accountOption,
|
||||
fromAccountOptions = fromAccountOption,
|
||||
processState = payFromStepState,
|
||||
onContinueClick = {
|
||||
payFromAccount = it
|
||||
@ -399,7 +399,7 @@ private fun RemarkStep(
|
||||
private fun ThirdPartyTransferContentPreview() {
|
||||
MifosMobileTheme {
|
||||
ThirdPartyTransferContent(
|
||||
accountOption = listOf(),
|
||||
fromAccountOption = listOf(),
|
||||
toAccountOption = listOf(),
|
||||
beneficiaryList = listOf(),
|
||||
navigateBack = {},
|
||||
|
||||
@ -23,6 +23,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.mifos.mobile.core.common.Network
|
||||
import org.mifos.mobile.core.designsystem.components.MifosScaffold
|
||||
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.core.ui.component.MifosErrorComponent
|
||||
@ -33,19 +34,17 @@ import org.mifos.mobile.core.ui.utils.DevicePreviews
|
||||
internal fun ThirdPartyTransferScreen(
|
||||
navigateBack: () -> Unit,
|
||||
addBeneficiary: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: ThirdPartyTransferViewModel = hiltViewModel(),
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
val uiData by viewModel.thirdPartyTransferUiData.collectAsStateWithLifecycle()
|
||||
|
||||
ThirdPartyTransferScreen(
|
||||
uiState = uiState,
|
||||
uiData = uiData,
|
||||
navigateBack = navigateBack,
|
||||
addBeneficiary = addBeneficiary,
|
||||
reviewTransfer = { reviewTransfer(it, TransferType.TPT) },
|
||||
reviewTransfer = { reviewTransfer(it, TransferType.TPT, TransferSuccessDestination.HOME) },
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
@ -53,7 +52,6 @@ internal fun ThirdPartyTransferScreen(
|
||||
@Composable
|
||||
private fun ThirdPartyTransferScreen(
|
||||
uiState: ThirdPartyTransferUiState,
|
||||
uiData: ThirdPartyTransferUiData,
|
||||
navigateBack: () -> Unit,
|
||||
addBeneficiary: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload) -> Unit,
|
||||
@ -69,9 +67,9 @@ private fun ThirdPartyTransferScreen(
|
||||
when (uiState) {
|
||||
is ThirdPartyTransferUiState.ShowUI -> {
|
||||
ThirdPartyTransferContent(
|
||||
accountOption = uiData.fromAccountDetail,
|
||||
toAccountOption = uiData.toAccountOption,
|
||||
beneficiaryList = uiData.beneficiaries,
|
||||
fromAccountOption = uiState.data.fromAccountDetail,
|
||||
toAccountOption = uiState.data.toAccountOption,
|
||||
beneficiaryList = uiState.data.beneficiaries,
|
||||
navigateBack = navigateBack,
|
||||
addBeneficiary = addBeneficiary,
|
||||
reviewTransfer = reviewTransfer,
|
||||
@ -99,7 +97,7 @@ internal class SavingsMakeTransferUiStatesPreviews :
|
||||
PreviewParameterProvider<ThirdPartyTransferUiState> {
|
||||
override val values: Sequence<ThirdPartyTransferUiState>
|
||||
get() = sequenceOf(
|
||||
ThirdPartyTransferUiState.ShowUI,
|
||||
ThirdPartyTransferUiState.ShowUI(data = ThirdPartyTransferUiData()),
|
||||
ThirdPartyTransferUiState.Error(""),
|
||||
ThirdPartyTransferUiState.Loading,
|
||||
)
|
||||
@ -114,7 +112,6 @@ private fun ThirdPartyTransferScreenPreview(
|
||||
MifosMobileTheme {
|
||||
ThirdPartyTransferScreen(
|
||||
uiState = thirdPartyTransferUiState,
|
||||
uiData = ThirdPartyTransferUiData(),
|
||||
navigateBack = {},
|
||||
addBeneficiary = {},
|
||||
reviewTransfer = {},
|
||||
|
||||
@ -12,12 +12,11 @@ package org.mifos.mobile.feature.third.party.transfer
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import org.mifos.mobile.core.data.repository.BeneficiaryRepository
|
||||
import org.mifos.mobile.core.data.repository.ThirdPartyTransferRepository
|
||||
import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary
|
||||
@ -27,51 +26,42 @@ import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class ThirdPartyTransferViewModel @Inject constructor(
|
||||
private val transferRepository: ThirdPartyTransferRepository,
|
||||
private val beneficiaryRepository: BeneficiaryRepository,
|
||||
transferRepository: ThirdPartyTransferRepository,
|
||||
beneficiaryRepository: BeneficiaryRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
private val mUiState = MutableStateFlow<ThirdPartyTransferUiState>(Loading)
|
||||
val uiState = mUiState.asStateFlow()
|
||||
|
||||
private val _thirdPartyTransferUiData = MutableStateFlow(ThirdPartyTransferUiData())
|
||||
val thirdPartyTransferUiData = _thirdPartyTransferUiData.asStateFlow()
|
||||
|
||||
init {
|
||||
fetchTemplate()
|
||||
}
|
||||
|
||||
private fun fetchTemplate() {
|
||||
viewModelScope.launch {
|
||||
combine(
|
||||
transferRepository.thirdPartyTransferTemplate(),
|
||||
beneficiaryRepository.beneficiaryList(),
|
||||
) { templateResult, beneficiariesResult ->
|
||||
_thirdPartyTransferUiData.update {
|
||||
it.copy(
|
||||
fromAccountDetail = templateResult.fromAccountOptions,
|
||||
toAccountOption = templateResult.toAccountOptions,
|
||||
beneficiaries = beneficiariesResult,
|
||||
)
|
||||
}
|
||||
}.catch {
|
||||
mUiState.value =
|
||||
ThirdPartyTransferUiState.Error(errorMessage = it.message)
|
||||
}.collect {
|
||||
mUiState.value = ThirdPartyTransferUiState.ShowUI
|
||||
}
|
||||
}
|
||||
}
|
||||
// in third part transfer is possible from savings to savings/loan
|
||||
// cause of that we filter fromAccount only have saings.
|
||||
val uiState: StateFlow<ThirdPartyTransferUiState> =
|
||||
combine(
|
||||
transferRepository.thirdPartyTransferTemplate(),
|
||||
beneficiaryRepository.beneficiaryList(),
|
||||
) { templateResult, beneficiariesResult ->
|
||||
ThirdPartyTransferUiState.ShowUI(
|
||||
ThirdPartyTransferUiData(
|
||||
fromAccountDetail = templateResult.fromAccountOptions
|
||||
.filter { it.accountType?.value == "Savings Account" },
|
||||
toAccountOption = templateResult.toAccountOptions,
|
||||
beneficiaries = beneficiariesResult,
|
||||
),
|
||||
)
|
||||
}.catch {
|
||||
ThirdPartyTransferUiState.Error(errorMessage = it.message)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = Loading,
|
||||
)
|
||||
}
|
||||
|
||||
internal sealed class ThirdPartyTransferUiState {
|
||||
data object Loading : ThirdPartyTransferUiState()
|
||||
data class Error(val errorMessage: String?) : ThirdPartyTransferUiState()
|
||||
data object ShowUI : ThirdPartyTransferUiState()
|
||||
data class ShowUI(val data: ThirdPartyTransferUiData) : ThirdPartyTransferUiState()
|
||||
}
|
||||
|
||||
internal data class ThirdPartyTransferUiData(
|
||||
val fromAccountDetail: List<AccountOption> = listOf(),
|
||||
val toAccountOption: List<AccountOption> = listOf(),
|
||||
val beneficiaries: List<Beneficiary> = listOf(),
|
||||
val fromAccountDetail: List<AccountOption> = emptyList(),
|
||||
val toAccountOption: List<AccountOption> = emptyList(),
|
||||
val beneficiaries: List<Beneficiary> = emptyList(),
|
||||
)
|
||||
|
||||
@ -13,6 +13,7 @@ import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.navigation
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.feature.third.party.transfer.ThirdPartyTransferScreen
|
||||
@ -24,7 +25,7 @@ fun NavController.navigateToThirdPartyTransfer() {
|
||||
fun NavGraphBuilder.thirdPartyTransferNavGraph(
|
||||
navigateBack: () -> Unit,
|
||||
addBeneficiary: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
|
||||
) {
|
||||
navigation(
|
||||
startDestination = ThirdPartyTransferNavigation.ThirdPartyTransferScreen.route,
|
||||
@ -41,7 +42,7 @@ fun NavGraphBuilder.thirdPartyTransferNavGraph(
|
||||
fun NavGraphBuilder.thirdPartyTransferRoute(
|
||||
navigateBack: () -> Unit,
|
||||
addBeneficiary: () -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType) -> Unit,
|
||||
reviewTransfer: (ReviewTransferPayload, TransferType, TransferSuccessDestination) -> Unit,
|
||||
) {
|
||||
composable(
|
||||
route = ThirdPartyTransferNavigation.ThirdPartyTransferScreen.route,
|
||||
|
||||
@ -41,29 +41,31 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.mifos.mobile.core.common.Network
|
||||
import org.mifos.mobile.core.designsystem.components.MifosButton
|
||||
import org.mifos.mobile.core.designsystem.components.MifosScaffold
|
||||
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.TransferPayload
|
||||
import org.mifos.mobile.core.ui.component.MifosErrorComponent
|
||||
import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay
|
||||
import org.mifos.mobile.core.ui.utils.DevicePreviews
|
||||
|
||||
@Composable
|
||||
internal fun TransferProcessScreen(
|
||||
navigateBack: () -> Unit,
|
||||
onTransferSuccessNavigate: (TransferSuccessDestination) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: TransferProcessViewModel = hiltViewModel(),
|
||||
) {
|
||||
val uiState by viewModel.transferUiState.collectAsStateWithLifecycle()
|
||||
val payload by viewModel.transferPayload.collectAsStateWithLifecycle()
|
||||
val transferSuccessDestination by viewModel.transferSuccessDestination.collectAsStateWithLifecycle()
|
||||
|
||||
TransferProcessScreen(
|
||||
uiState = uiState,
|
||||
transfer = viewModel::makeTransfer,
|
||||
payload = payload,
|
||||
navigateBack = navigateBack,
|
||||
onTransferSuccess = { onTransferSuccessNavigate(transferSuccessDestination) },
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
@ -74,6 +76,7 @@ private fun TransferProcessScreen(
|
||||
payload: TransferPayload?,
|
||||
transfer: () -> Unit,
|
||||
navigateBack: () -> Unit,
|
||||
onTransferSuccess: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@ -103,11 +106,11 @@ private fun TransferProcessScreen(
|
||||
R.string.transferred_successfully,
|
||||
Toast.LENGTH_SHORT,
|
||||
).show()
|
||||
navigateBack()
|
||||
onTransferSuccess()
|
||||
}
|
||||
|
||||
is TransferProcessUiState.Error -> {
|
||||
MifosErrorComponent(isNetworkConnected = Network.isConnected(context))
|
||||
Toast.makeText(context, uiState.errorMessage, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
is TransferProcessUiState.Initial -> Unit
|
||||
@ -172,7 +175,7 @@ private fun TransferProcessContent(
|
||||
)
|
||||
|
||||
Text(
|
||||
text = payload?.fromAccountNumber.toString(),
|
||||
text = payload?.toAccountNumber.toString(),
|
||||
modifier = Modifier.padding(top = 4.dp, bottom = 2.dp),
|
||||
)
|
||||
|
||||
@ -273,6 +276,7 @@ private fun TransferProcessScreenPreview(
|
||||
),
|
||||
transfer = {},
|
||||
navigateBack = {},
|
||||
onTransferSuccess = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,8 +23,10 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.mifos.mobile.core.common.Constants.PAYLOAD
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
|
||||
import org.mifos.mobile.core.data.repository.TransferRepository
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.TransferPayload
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
import org.mifos.mobile.feature.transfer.process.TransferProcessUiState.Initial
|
||||
@ -48,6 +50,11 @@ internal class TransferProcessViewModel @Inject constructor(
|
||||
initialValue = null,
|
||||
)
|
||||
|
||||
val transferSuccessDestination = savedStateHandle.getStateFlow(
|
||||
key = TRANSFER_SUCCESS_DESTINATION,
|
||||
initialValue = TransferSuccessDestination.SAVINGS_ACCOUNT,
|
||||
)
|
||||
|
||||
val transferPayload: StateFlow<TransferPayload?> = transferPayloadString
|
||||
.map { jsonString ->
|
||||
jsonString?.let {
|
||||
@ -77,8 +84,6 @@ internal class TransferProcessViewModel @Inject constructor(
|
||||
transferDescription = payload.transferDescription,
|
||||
dateFormat = payload.dateFormat,
|
||||
locale = payload.locale,
|
||||
fromAccountNumber = payload.fromAccountNumber,
|
||||
toAccountNumber = payload.toAccountNumber,
|
||||
transferType = transferType.value,
|
||||
).catch { e ->
|
||||
_transferUiState.value = TransferProcessUiState.Error(e.message)
|
||||
|
||||
@ -19,6 +19,7 @@ import com.google.gson.Gson
|
||||
import org.mifos.mobile.core.common.Constants
|
||||
import org.mifos.mobile.core.common.utils.DateHelper
|
||||
import org.mifos.mobile.core.common.utils.getTodayFormatted
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload
|
||||
import org.mifos.mobile.core.model.entity.payload.TransferPayload
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
@ -28,17 +29,20 @@ import org.mifos.mobile.feature.transfer.process.TransferProcessScreen
|
||||
fun NavController.navigateToTransferProcessScreen(
|
||||
transferPayload: ReviewTransferPayload,
|
||||
transferType: TransferType,
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
) {
|
||||
navigate(
|
||||
TransferProcessNavigation.TransferProcessScreen.passArguments(
|
||||
transferType = transferType,
|
||||
payload = transferPayload.convertToTransferPayloadString(),
|
||||
transferSuccessDestination = transferSuccessDestination,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun NavGraphBuilder.transferProcessNavGraph(
|
||||
navigateBack: () -> Unit,
|
||||
onTransferSuccessNavigate: (TransferSuccessDestination) -> Unit = {},
|
||||
) {
|
||||
navigation(
|
||||
startDestination = TransferProcessNavigation.TransferProcessScreen.route,
|
||||
@ -46,12 +50,14 @@ fun NavGraphBuilder.transferProcessNavGraph(
|
||||
) {
|
||||
transferProcessScreenRoute(
|
||||
navigateBack = navigateBack,
|
||||
onTransferSuccessNavigate = onTransferSuccessNavigate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun NavGraphBuilder.transferProcessScreenRoute(
|
||||
navigateBack: () -> Unit,
|
||||
onTransferSuccessNavigate: (TransferSuccessDestination) -> Unit = {},
|
||||
) {
|
||||
composable(
|
||||
route = TransferProcessNavigation.TransferProcessScreen.route,
|
||||
@ -60,10 +66,14 @@ private fun NavGraphBuilder.transferProcessScreenRoute(
|
||||
navArgument(name = Constants.TRANSFER_TYPE) {
|
||||
type = NavType.EnumType(TransferType::class.java)
|
||||
},
|
||||
navArgument(name = Constants.TRANSFER_SUCCESS_DESTINATION) {
|
||||
type = NavType.EnumType(TransferSuccessDestination::class.java)
|
||||
},
|
||||
),
|
||||
) {
|
||||
TransferProcessScreen(
|
||||
navigateBack = navigateBack,
|
||||
onTransferSuccessNavigate = onTransferSuccessNavigate,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -75,10 +85,12 @@ private fun ReviewTransferPayload.convertToTransferPayloadString(): String {
|
||||
fromClientId = payload.payFromAccount?.clientId
|
||||
fromAccountType = payload.payFromAccount?.accountType?.id
|
||||
fromOfficeId = payload.payFromAccount?.officeId
|
||||
toOfficeId = payload.payFromAccount?.officeId
|
||||
fromAccountNumber = payload.payFromAccount?.accountNo
|
||||
toOfficeId = payload.payToAccount?.officeId
|
||||
toAccountId = payload.payToAccount?.accountId
|
||||
toClientId = payload.payToAccount?.clientId
|
||||
toAccountType = payload.payToAccount?.accountType?.id
|
||||
toAccountNumber = payload.payToAccount?.accountNo
|
||||
transferDate = DateHelper.getSpecificFormat(DateHelper.FORMAT_MMMM, getTodayFormatted())
|
||||
transferAmount = payload.amount.toDoubleOrNull()
|
||||
transferDescription = payload.review
|
||||
|
||||
@ -10,7 +10,9 @@
|
||||
package org.mifos.mobile.feature.transfer.process.navigation
|
||||
|
||||
import org.mifos.mobile.core.common.Constants.PAYLOAD
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_SUCCESS_DESTINATION
|
||||
import org.mifos.mobile.core.common.Constants.TRANSFER_TYPE
|
||||
import org.mifos.mobile.core.model.entity.TransferSuccessDestination
|
||||
import org.mifos.mobile.core.model.enums.TransferType
|
||||
|
||||
// Constants for Routes
|
||||
@ -24,11 +26,12 @@ internal sealed class TransferProcessNavigation(val route: String) {
|
||||
)
|
||||
|
||||
data object TransferProcessScreen : TransferProcessNavigation(
|
||||
route = "$TRANSFER_PROCESS_SCREEN_ROUTE/{$PAYLOAD}/{$TRANSFER_TYPE}",
|
||||
route = "$TRANSFER_PROCESS_SCREEN_ROUTE/{$PAYLOAD}/{$TRANSFER_TYPE}/{$TRANSFER_SUCCESS_DESTINATION}",
|
||||
) {
|
||||
fun passArguments(
|
||||
payload: String,
|
||||
transferType: TransferType,
|
||||
) = "$TRANSFER_PROCESS_SCREEN_ROUTE/$payload/$transferType"
|
||||
transferSuccessDestination: TransferSuccessDestination,
|
||||
) = "$TRANSFER_PROCESS_SCREEN_ROUTE/$payload/$transferType/$transferSuccessDestination"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user