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 97f595de630..4ae4e27133b 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
@@ -105,8 +105,20 @@ fun MifosListingRowItem(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
- keyContent()
- valueContent()
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Box(
+ modifier = Modifier.weight(1f),
+ contentAlignment = Alignment.CenterStart,
+ ) { keyContent() }
+
+ Box(
+ modifier = Modifier.weight(1f),
+ contentAlignment = Alignment.CenterEnd,
+ ) { valueContent() }
+ }
}
}
diff --git a/feature/loan/src/commonMain/composeResources/values/strings.xml b/feature/loan/src/commonMain/composeResources/values/strings.xml
index f48f13c71dc..1e204ebc21d 100644
--- a/feature/loan/src/commonMain/composeResources/values/strings.xml
+++ b/feature/loan/src/commonMain/composeResources/values/strings.xml
@@ -220,4 +220,45 @@
Amount
Type
Collected On
+
+
+ On principal payment
+ On interest payment
+ On Arrears Aging
+ Enable installment level Delinquency
+ Recalculate Interest
+ Days in month
+ Principal
+ Loan Term
+ Number of Repayments
+ First Repayment Date
+ Interest Charged From
+ Repaid Every
+ Nominal Interest Rate
+ Is Equal Amortization
+ Amortization
+ Interest Calculation Period
+ Calculate interest for exact days in partial
+ Arrears tolerance
+ Interest free period
+ Repayment strategy
+ Installment Amount
+ Balloon Repayment Amount
+ Product Name
+ Loan Officer
+ External ID
+ Submitted Date
+ Expected Disbursement
+ Loan Purpose
+ Is Savings Linked
+ Yes
+ No
+ Terms
+ Moratorium
+ Details
+ Charges
+ View
+ Active Charges
+
+
\ No newline at end of file
diff --git a/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt
index 52d879e137f..79781d436cd 100644
--- a/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt
+++ b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt
@@ -136,9 +136,10 @@ private fun NewLoanAccountScaffold(
}
},
Step(stringResource(Res.string.step_preview)) {
- PreviewPage {
- onAction(NewLoanAccountAction.NextStep)
- }
+ PreviewPage(
+ state = state,
+ onAction = onAction,
+ )
},
)
diff --git a/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountViewModel.kt b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountViewModel.kt
index d7b6a0cc143..a22cbfd31e7 100644
--- a/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountViewModel.kt
+++ b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountViewModel.kt
@@ -12,14 +12,17 @@ package com.mifos.feature.loan.newLoanAccount
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
+import co.touchlab.kermit.Logger
import com.mifos.core.common.utils.DataState
import com.mifos.core.common.utils.DateHelper
import com.mifos.core.data.repository.ClientDetailsRepository
import com.mifos.core.data.util.NetworkMonitor
+import com.mifos.core.domain.useCases.CreateLoanAccountUseCase
import com.mifos.core.domain.useCases.GetAllLoanUseCase
import com.mifos.core.domain.useCases.GetLoansAccountTemplateUseCase
import com.mifos.core.model.objects.organisations.LoanProducts
import com.mifos.core.network.model.CollateralItem
+import com.mifos.core.network.model.LoansPayload
import com.mifos.core.ui.util.BaseViewModel
import com.mifos.core.ui.util.TextFieldsValidator
import com.mifos.feature.loan.newLoanAccount.NewLoanAccountState.DialogState
@@ -35,6 +38,7 @@ internal class NewLoanAccountViewModel(
private val repo: ClientDetailsRepository,
private val getLoansAccountTemplateUseCase: GetLoansAccountTemplateUseCase,
private val networkMonitor: NetworkMonitor,
+ private val loanUseCase: CreateLoanAccountUseCase,
val savedStateHandle: SavedStateHandle,
) :
BaseViewModel(
@@ -71,9 +75,13 @@ internal class NewLoanAccountViewModel(
is NewLoanAccountAction.OnLoanPurposeChange -> handleLoanPurposeChange(action)
- is NewLoanAccountAction.OnExpectedDisbursementDateChange -> handleExpectedDisbursementDateChange(action)
+ is NewLoanAccountAction.OnExpectedDisbursementDateChange -> handleExpectedDisbursementDateChange(
+ action,
+ )
- is NewLoanAccountAction.OnExpectedDisbursementDatePick -> handleExpectedDisbursementDatePick(action)
+ is NewLoanAccountAction.OnExpectedDisbursementDatePick -> handleExpectedDisbursementDatePick(
+ action,
+ )
is NewLoanAccountAction.OnSubmissionDateChange -> handleSubmissionDateChange(action)
@@ -81,27 +89,41 @@ internal class NewLoanAccountViewModel(
is NewLoanAccountAction.OnLinkSavingsChange -> handleLinkSavingsChange(action)
- is NewLoanAccountAction.OnStandingInstructionsChange -> handleStandingInstructionsChange(action)
+ is NewLoanAccountAction.OnStandingInstructionsChange -> handleStandingInstructionsChange(
+ action,
+ )
is NewLoanAccountAction.OnDetailsSubmit -> handleOnDetailsSubmit()
- is NewLoanAccountAction.Internal.OnReceivingLoanAccounts -> handleAllLoansResponse(action.loans)
+ is NewLoanAccountAction.Internal.OnReceivingLoanAccounts -> handleAllLoansResponse(
+ action.loans,
+ )
- is NewLoanAccountAction.Internal.OnReceivingLoanTemplate -> handleLoanTemplateResponse(action.template)
+ is NewLoanAccountAction.Internal.OnReceivingLoanTemplate -> handleLoanTemplateResponse(
+ action.template,
+ )
- is NewLoanAccountAction.OnFirstRepaymentDateChange -> handleFirstRepaymentDateChange(action)
+ is NewLoanAccountAction.OnFirstRepaymentDateChange -> handleFirstRepaymentDateChange(
+ action,
+ )
is NewLoanAccountAction.OnFirstRepaymentDatePick -> handleFirstRepaymentDatePick(action)
- is NewLoanAccountAction.OnInterestChargedFromChange -> handleInterestChargedFromChange(action)
+ is NewLoanAccountAction.OnInterestChargedFromChange -> handleInterestChargedFromChange(
+ action,
+ )
- is NewLoanAccountAction.OnInterestChargedFromDatePick -> handleInterestChargedFromDatePick(action)
+ is NewLoanAccountAction.OnInterestChargedFromDatePick -> handleInterestChargedFromDatePick(
+ action,
+ )
is NewLoanAccountAction.OnNoOfRepaymentsChange -> handleNoOfRepaymentsChange(action)
is NewLoanAccountAction.OnPrincipalAmountChange -> handlePrincipalAmountChange(action)
- is NewLoanAccountAction.OnTermFrequencyIndexChange -> handleTermFrequencyIndexChange(action)
+ is NewLoanAccountAction.OnTermFrequencyIndexChange -> handleTermFrequencyIndexChange(
+ action,
+ )
is NewLoanAccountAction.OnRepaidEveryChange -> handleRepaidEveryChange(action)
@@ -109,33 +131,59 @@ internal class NewLoanAccountViewModel(
is NewLoanAccountAction.OnSelectedOnIndexChange -> handleSelectedOnIndexChange(action)
- is NewLoanAccountAction.OnNominalInterestRateChange -> handleNominalInterestRateChange(action)
+ is NewLoanAccountAction.OnNominalInterestRateChange -> handleNominalInterestRateChange(
+ action,
+ )
- is NewLoanAccountAction.OnNominalFrequencyIndexChange -> handleNominalFrequencyIndexChange(action)
+ is NewLoanAccountAction.OnNominalFrequencyIndexChange -> handleNominalFrequencyIndexChange(
+ action,
+ )
- is NewLoanAccountAction.OnNominalMethodIndexChange -> handleNominalMethodIndexChange(action)
+ is NewLoanAccountAction.OnNominalMethodIndexChange -> handleNominalMethodIndexChange(
+ action,
+ )
- is NewLoanAccountAction.OnNominalAmortizationIndexChange -> handleNominalAmortizationIndexChange(action)
+ is NewLoanAccountAction.OnNominalAmortizationIndexChange -> handleNominalAmortizationIndexChange(
+ action,
+ )
- is NewLoanAccountAction.OnEqualAmortizationCheckChange -> handleEqualAmortizationCheckChange(action)
+ is NewLoanAccountAction.OnEqualAmortizationCheckChange -> handleEqualAmortizationCheckChange(
+ action,
+ )
- is NewLoanAccountAction.OnRepaymentStrategyIndexChange -> handleRepaymentStrategyIndexChange(action)
+ is NewLoanAccountAction.OnRepaymentStrategyIndexChange -> handleRepaymentStrategyIndexChange(
+ action,
+ )
- is NewLoanAccountAction.OnBalloonRepaymentAmountChange -> handleBalloonRepaymentAmountChange(action)
+ is NewLoanAccountAction.OnBalloonRepaymentAmountChange -> handleBalloonRepaymentAmountChange(
+ action,
+ )
- is NewLoanAccountAction.OnInterestCalculationPeriodIndexChange -> handleInterestCalculationPeriodIndexChange(action)
+ is NewLoanAccountAction.OnInterestCalculationPeriodIndexChange -> handleInterestCalculationPeriodIndexChange(
+ action,
+ )
- is NewLoanAccountAction.OnInterestPartialPeriodCheckChange -> handleInterestPartialPeriodCheckChange(action)
+ is NewLoanAccountAction.OnInterestPartialPeriodCheckChange -> handleInterestPartialPeriodCheckChange(
+ action,
+ )
is NewLoanAccountAction.OnArrearsToleranceChange -> handleArrearsToleranceChange(action)
- is NewLoanAccountAction.OnInterestFreePeriodChange -> handleInterestFreePeriodChange(action)
+ is NewLoanAccountAction.OnInterestFreePeriodChange -> handleInterestFreePeriodChange(
+ action,
+ )
- is NewLoanAccountAction.OnMoratoriumGraceOnInterestPaymentChange -> handleMoratoriumGraceOnInterestPaymentChange(action)
+ is NewLoanAccountAction.OnMoratoriumGraceOnInterestPaymentChange -> handleMoratoriumGraceOnInterestPaymentChange(
+ action,
+ )
- is NewLoanAccountAction.OnMoratoriumGraceOnPrincipalPaymentChange -> handleMoratoriumGraceOnPrincipalPaymentChange(action)
+ is NewLoanAccountAction.OnMoratoriumGraceOnPrincipalPaymentChange -> handleMoratoriumGraceOnPrincipalPaymentChange(
+ action,
+ )
- is NewLoanAccountAction.OnMoratoriumOnArrearsAgeingChange -> handleMoratoriumOnArrearsAgeingChange(action)
+ is NewLoanAccountAction.OnMoratoriumOnArrearsAgeingChange -> handleMoratoriumOnArrearsAgeingChange(
+ action,
+ )
is NewLoanAccountAction.DismissDialog -> handleDismissAddCollateralDialog()
@@ -143,9 +191,13 @@ internal class NewLoanAccountViewModel(
is NewLoanAccountAction.AddCollateralToList -> handleAddCollateralToList()
- is NewLoanAccountAction.OnCollateralQuantityChanged -> handleCollateralQuantityChanged(action)
+ is NewLoanAccountAction.OnCollateralQuantityChanged -> handleCollateralQuantityChanged(
+ action,
+ )
- is NewLoanAccountAction.SelectedCollateralIndexChange -> handleSelectedCollateralIndexChange(action)
+ is NewLoanAccountAction.SelectedCollateralIndexChange -> handleSelectedCollateralIndexChange(
+ action,
+ )
is NewLoanAccountAction.HideCollaterals -> handleHideCollaterals()
@@ -153,7 +205,9 @@ internal class NewLoanAccountViewModel(
is NewLoanAccountAction.AddChargeToList -> handleAddChargeToList()
- is NewLoanAccountAction.OnChooseChargeIndexChange -> handleChooseChargeIndexChange(action)
+ is NewLoanAccountAction.OnChooseChargeIndexChange -> handleChooseChargeIndexChange(
+ action,
+ )
is NewLoanAccountAction.ShowAddChargeDialog -> handleShowAddChargeDialog()
@@ -172,6 +226,67 @@ internal class NewLoanAccountViewModel(
is NewLoanAccountAction.EditChargeDialog -> handleEditChargeDialog(action.index)
is NewLoanAccountAction.EditCharge -> handleEditCharge(action.index)
+
+ NewLoanAccountAction.GotoPreviousStep -> {}
+
+ NewLoanAccountAction.SubmitLoanApplication -> submitLoanApplication()
+ }
+ }
+
+ private fun submitLoanApplication() {
+ viewModelScope.launch {
+ val payload = LoansPayload(
+ loanOfficerId = state.loanOfficerIndex,
+ principal = state.principalAmount,
+ clientId = state.clientId,
+ allowPartialPeriodInterestCalcualtion = state.isCheckedInterestPartialPeriod,
+ amortizationType = state.nominalAmortizationIndex,
+ dateFormat = DateHelper.SHORT_MONTH,
+ interestCalculationPeriodType = state.interestCalculationPeriodIndex,
+ interestRatePerPeriod = state.nominalInterestRate,
+ interestType = state.nominalInterestMethodIndex,
+ loanTermFrequency = state.termFrequencyIndex,
+ loanTermFrequencyType = state.termFrequencyIndex,
+ loanType = "individual",
+ locale = "en",
+ numberOfRepayments = state.noOfRepayments,
+ productId = state.loanProductSelected,
+ repaymentEvery = state.repaidEvery,
+ repaymentFrequencyDayOfWeekType = state.selectedDayIndex,
+ repaymentFrequencyNthDayType = state.selectedOnIndex,
+ repaymentFrequencyType = state.repaymentStrategyIndex,
+ expectedDisbursementDate = state.expectedDisbursementDate,
+ submittedOnDate = state.submissionDate,
+ loanPurposeId = state.loanPurposeIndex,
+ fundId = state.fundIndex,
+ linkAccountId = state.linkSavingsIndex,
+ )
+
+ loanUseCase(payload).collect { dataState ->
+ when (dataState) {
+ is DataState.Error -> {
+ mutableStateFlow.update {
+ it.copy(
+ dialogState = NewLoanAccountState.DialogState.Error(dataState.message),
+ isLoading = false,
+ )
+ }
+ }
+
+ DataState.Loading -> {
+ mutableStateFlow.update {
+ it.copy(
+ isLoading = true,
+ )
+ }
+ }
+
+ is DataState.Success -> {
+ Logger.d("DebugTtt success")
+ sendEvent(NewLoanAccountEvent.Finish)
+ }
+ }
+ }
}
}
@@ -623,6 +738,7 @@ internal class NewLoanAccountViewModel(
)
}
}
+
else -> Unit
}
}
@@ -698,6 +814,7 @@ internal class NewLoanAccountViewModel(
data class NewLoanAccountState
@OptIn(ExperimentalTime::class)
constructor(
+ val isLoading: Boolean = false,
val networkConnection: Boolean = false,
val clientId: Int,
val productLoans: List = emptyList(),
@@ -713,9 +830,13 @@ constructor(
val loanOfficerIndex: Int = -1,
val loanPurposeIndex: Int = -1,
val fundIndex: Int = -1,
- val submissionDate: String = DateHelper.getDateAsStringFromLong(Clock.System.now().toEpochMilliseconds()),
+ val submissionDate: String = DateHelper.getDateAsStringFromLong(
+ Clock.System.now().toEpochMilliseconds(),
+ ),
val showSubmissionDatePick: Boolean = false,
- val expectedDisbursementDate: String = DateHelper.getDateAsStringFromLong(Clock.System.now().toEpochMilliseconds()),
+ val expectedDisbursementDate: String = DateHelper.getDateAsStringFromLong(
+ Clock.System.now().toEpochMilliseconds(),
+ ),
val showExpectedDisbursementDatePick: Boolean = false,
val linkSavingsIndex: Int = -1,
val isCheckedStandingInstructions: Boolean = false,
@@ -724,8 +845,12 @@ constructor(
val principalAmountText: String = "",
val noOfRepayments: Int = 0,
val termFrequencyIndex: Int = -1,
- val firstRepaymentDate: String = DateHelper.getDateAsStringFromLong(Clock.System.now().toEpochMilliseconds()),
- val interestChargedFromDate: String = DateHelper.getDateAsStringFromLong(Clock.System.now().toEpochMilliseconds()),
+ val firstRepaymentDate: String = DateHelper.getDateAsStringFromLong(
+ Clock.System.now().toEpochMilliseconds(),
+ ),
+ val interestChargedFromDate: String = DateHelper.getDateAsStringFromLong(
+ Clock.System.now().toEpochMilliseconds(),
+ ),
val showFirstRepaymentDatePick: Boolean = false,
val showInterestChargedFromDatePick: Boolean = false,
val repaidEvery: Int = 1,
@@ -756,7 +881,9 @@ constructor(
val chooseChargeIndex: Int = -1,
val addedCharges: List = emptyList(),
- val chargeDate: String = DateHelper.getDateAsStringFromLong(Clock.System.now().toEpochMilliseconds()),
+ val chargeDate: String = DateHelper.getDateAsStringFromLong(
+ Clock.System.now().toEpochMilliseconds(),
+ ),
val showChargesDatePick: Boolean = false,
val chargeAmount: String = "",
@@ -769,12 +896,15 @@ constructor(
data object ShowCharges : DialogState
data object ShowOverDueCharges : DialogState
}
+
sealed interface ScreenState {
data object Loading : ScreenState
data object Success : ScreenState
data object NetworkError : ScreenState
}
- val isDetailsNextEnabled = loanProductSelected != -1 && externalId.isNotEmpty() && submissionDate.isNotEmpty() && expectedDisbursementDate.isNotEmpty()
+
+ val isDetailsNextEnabled =
+ loanProductSelected != -1 && externalId.isNotEmpty() && submissionDate.isNotEmpty() && expectedDisbursementDate.isNotEmpty()
val isCollateralBtnEnabled = collateralQuantity != 0 && collateralSelectedIndex != -1
}
@@ -818,7 +948,9 @@ sealed interface NewLoanAccountAction {
data class OnRepaidEveryChange(val number: Int) : NewLoanAccountAction
data class OnSelectedOnIndexChange(val index: Int) : NewLoanAccountAction
data class OnSelectedDayIndexChange(val index: Int) : NewLoanAccountAction
- data class OnNominalInterestRateChange(val rate: Double, val text: String) : NewLoanAccountAction
+ data class OnNominalInterestRateChange(val rate: Double, val text: String) :
+ NewLoanAccountAction
+
data class OnNominalFrequencyIndexChange(val index: Int) : NewLoanAccountAction
data class OnNominalMethodIndexChange(val index: Int) : NewLoanAccountAction
data class OnNominalAmortizationIndexChange(val index: Int) : NewLoanAccountAction
@@ -851,6 +983,8 @@ sealed interface NewLoanAccountAction {
data class DeleteChargeFromSelectedCharges(val index: Int) : NewLoanAccountAction
data class EditChargeDialog(val index: Int) : NewLoanAccountAction
data class EditCharge(val index: Int) : NewLoanAccountAction
+ data object SubmitLoanApplication : NewLoanAccountAction
+ data object GotoPreviousStep : NewLoanAccountAction
}
data class CreatedCollateral(
diff --git a/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/pages/PreviewPage.kt b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/pages/PreviewPage.kt
index 9c3cf9f0e8a..b24d6e8be41 100644
--- a/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/pages/PreviewPage.kt
+++ b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/pages/PreviewPage.kt
@@ -10,26 +10,294 @@
package com.mifos.feature.loan.newLoanAccount.pages
import androidclient.feature.loan.generated.resources.Res
-import androidclient.feature.loan.generated.resources.next
-import androidclient.feature.loan.generated.resources.step_preview
+import androidclient.feature.loan.generated.resources.back
+import androidclient.feature.loan.generated.resources.expected_disbursement
+import androidclient.feature.loan.generated.resources.external_id
+import androidclient.feature.loan.generated.resources.feature_loan_charge_submit
+import androidclient.feature.loan.generated.resources.first_repayment_date
+import androidclient.feature.loan.generated.resources.interest_calculation_period
+import androidclient.feature.loan.generated.resources.interest_charged_from
+import androidclient.feature.loan.generated.resources.loan_new_loan_active_charges
+import androidclient.feature.loan.generated.resources.loan_new_loan_amortization
+import androidclient.feature.loan.generated.resources.loan_new_loan_arrears_tolerance
+import androidclient.feature.loan.generated.resources.loan_new_loan_ballon_repayment_amount
+import androidclient.feature.loan.generated.resources.loan_new_loan_calculate_interest_for_exact_days_in_pertial
+import androidclient.feature.loan.generated.resources.loan_new_loan_charges
+import androidclient.feature.loan.generated.resources.loan_new_loan_days_in_month
+import androidclient.feature.loan.generated.resources.loan_new_loan_enable_installment_level
+import androidclient.feature.loan.generated.resources.loan_new_loan_installment_amount
+import androidclient.feature.loan.generated.resources.loan_new_loan_interest_free_period
+import androidclient.feature.loan.generated.resources.loan_new_loan_is_equal_amortization
+import androidclient.feature.loan.generated.resources.loan_new_loan_is_savings_linked
+import androidclient.feature.loan.generated.resources.loan_new_loan_loan_officer
+import androidclient.feature.loan.generated.resources.loan_new_loan_loan_purpose
+import androidclient.feature.loan.generated.resources.loan_new_loan_loan_term
+import androidclient.feature.loan.generated.resources.loan_new_loan_moratorium
+import androidclient.feature.loan.generated.resources.loan_new_loan_nominal_interest_rate
+import androidclient.feature.loan.generated.resources.loan_new_loan_on_arrears_aging
+import androidclient.feature.loan.generated.resources.loan_new_loan_on_interest_payment
+import androidclient.feature.loan.generated.resources.loan_new_loan_on_principal_payment
+import androidclient.feature.loan.generated.resources.loan_new_loan_recalculate_interest
+import androidclient.feature.loan.generated.resources.loan_new_loan_repaid_every
+import androidclient.feature.loan.generated.resources.loan_new_loan_view
+import androidclient.feature.loan.generated.resources.no
+import androidclient.feature.loan.generated.resources.number_of_repayments
+import androidclient.feature.loan.generated.resources.principal
+import androidclient.feature.loan.generated.resources.product_name
+import androidclient.feature.loan.generated.resources.repayment_strategy
+import androidclient.feature.loan.generated.resources.step_details
+import androidclient.feature.loan.generated.resources.submission_date
+import androidclient.feature.loan.generated.resources.terms
+import androidclient.feature.loan.generated.resources.yes
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
-import androidx.compose.material3.Button
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
+import com.mifos.core.common.utils.CurrencyFormatter
+import com.mifos.core.designsystem.theme.DesignToken
+import com.mifos.core.designsystem.theme.MifosTypography
+import com.mifos.core.ui.components.MifosDefaultListingComponentFromStringResources
+import com.mifos.core.ui.components.MifosProgressIndicator
+import com.mifos.core.ui.components.MifosProgressIndicatorOverlay
+import com.mifos.core.ui.components.MifosRowWithTextAndButton
+import com.mifos.core.ui.components.MifosTwoButtonRow
+import com.mifos.feature.loan.newLoanAccount.NewLoanAccountAction
+import com.mifos.feature.loan.newLoanAccount.NewLoanAccountState
import org.jetbrains.compose.resources.stringResource
@Composable
-fun PreviewPage(onNext: () -> Unit) {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Text(stringResource(Res.string.step_preview))
- Spacer(Modifier.height(8.dp))
- Button(onClick = onNext) {
- Text(stringResource(Res.string.next))
+fun PreviewPage(
+ state: NewLoanAccountState,
+ onAction: (NewLoanAccountAction) -> Unit,
+) {
+ if (state.isLoading) {
+ MifosProgressIndicatorOverlay()
+ } else {
+ PreviewPageContent(
+ state,
+ onAction = onAction,
+ )
+ }
+}
+
+@Composable
+fun PreviewPageContent(
+ state: NewLoanAccountState,
+ onAction: (NewLoanAccountAction) -> Unit,
+) {
+ Column(
+ Modifier.fillMaxSize().padding(bottom = DesignToken.padding.large),
+ ) {
+ Column(
+ modifier = Modifier.weight(1f)
+ .verticalScroll(rememberScrollState()),
+ verticalArrangement = Arrangement.spacedBy(20.dp),
+ ) {
+ Text(
+ text = stringResource(Res.string.step_details),
+ style = MifosTypography.labelLarge,
+ )
+ DetailsCard(
+ productName = state.productLoans[state.loanProductSelected].name.toString(),
+ loanOfficer = if (state.loanOfficerIndex == -1) {
+ ""
+ } else {
+ state.loanTemplate?.loanOfficerOptions[state.loanOfficerIndex]?.displayName.toString()
+ },
+ externalId = state.externalId,
+ submittedDate = state.submissionDate,
+ expectedDisbursement = state.expectedDisbursementDate,
+ loadPurpose = if (state.loanPurposeIndex == -1) {
+ ""
+ } else {
+ state.loanTemplate?.loanPurposeOptions[state.loanPurposeIndex]?.name.toString()
+ },
+ isSavingsLinked = if (state.linkSavingsIndex == -1) {
+ stringResource(Res.string.no)
+ } else {
+ stringResource(Res.string.yes)
+ },
+ )
+
+ Text(
+ text = stringResource(Res.string.terms),
+ style = MifosTypography.labelLarge,
+ )
+ TermsCard(
+ principal = CurrencyFormatter.format(
+ balance = state.principalAmount,
+ currencyCode = state.loanTemplate?.currency?.code,
+ maximumFractionDigits = 2,
+ ),
+ loanTerm = if (state.termFrequencyIndex == -1) {
+ ""
+ } else {
+ state.loanTemplate?.termFrequencyTypeOptions[state.termFrequencyIndex]?.value
+ ?: ""
+ },
+ numberOfRepayments = state.noOfRepayments.toString(),
+ firstRepaymentDate = state.firstRepaymentDate,
+ interestChargedForm = state.interestChargedFromDate,
+ repaidEvery = "",
+ nominalInterestRate = state.nominalInterestRate.toString(),
+ isEqualAmortization = state.isCheckedEqualAmortization.toString(),
+ amortization = if (state.nominalAmortizationIndex == -1) {
+ ""
+ } else {
+ state.loanTemplate?.amortizationTypeOptions[state.nominalAmortizationIndex]?.value
+ ?: ""
+ },
+ interestCalculationPeriod = if (state.interestCalculationPeriodIndex == -1) {
+ ""
+ } else {
+ state.loanTemplate?.interestCalculationPeriodTypeOptions[state.interestCalculationPeriodIndex]?.value
+ ?: ""
+ },
+ calculateInterestForExactDaysInPartial = "",
+ arrearsTolerance = state.arrearsTolerance.toString(),
+ interestFreePeriod = state.interestFreePeriod.toString(),
+ repaymentStrategy = if (state.repaymentStrategyIndex == -1) {
+ ""
+ } else {
+ state.loanTemplate?.transactionProcessingStrategyOptions[state.repaymentStrategyIndex]?.name
+ ?: ""
+ },
+ // todo
+ installmentAmount = "",
+ ballonRepayment = state.balloonRepaymentAmount.toString(),
+ )
+
+ Text(
+ text = stringResource(Res.string.loan_new_loan_moratorium),
+ style = MifosTypography.labelLarge,
+ )
+ MoratoriumCard(
+ onPrincipalPayment = state.moratoriumGraceOnPrincipalPayment.toString(),
+ onInternestPayment = state.moratoriumGraceOnInterestPayment.toString(),
+ onAreasAging = state.moratoriumOnArrearsAgeing.toString(),
+ // todo
+ enableInstallmentLevelDelinquency = "",
+ recalculateInterest = if (state.loanTemplate?.isInterestRecalculationEnabled
+ ?: false
+ ) {
+ stringResource(Res.string.yes)
+ } else {
+ stringResource(Res.string.no)
+ },
+ // todo
+ daysInMonth = "",
+ )
+
+ Text(
+ text = stringResource(Res.string.loan_new_loan_charges),
+ style = MifosTypography.labelLarge,
+ )
+
+ MifosRowWithTextAndButton(
+ onBtnClick = { onAction(NewLoanAccountAction.ShowCharges) },
+ text = state.addedCharges.size.toString() + " " + stringResource(Res.string.loan_new_loan_active_charges),
+ btnText = stringResource(Res.string.loan_new_loan_view),
+ modifier = Modifier.fillMaxWidth(),
+ )
}
+ MifosTwoButtonRow(
+ modifier = Modifier.padding(top = DesignToken.padding.small),
+ firstBtnText = stringResource(Res.string.back),
+ secondBtnText = stringResource(Res.string.feature_loan_charge_submit),
+ onFirstBtnClick = { onAction(NewLoanAccountAction.GotoPreviousStep) },
+ onSecondBtnClick = { onAction(NewLoanAccountAction.SubmitLoanApplication) },
+ )
}
}
+
+@Composable
+private fun MoratoriumCard(
+ onPrincipalPayment: String,
+ onInternestPayment: String,
+ onAreasAging: String,
+ enableInstallmentLevelDelinquency: String,
+ recalculateInterest: String,
+ daysInMonth: String,
+) {
+ MifosDefaultListingComponentFromStringResources(
+ data = mapOf(
+ Res.string.loan_new_loan_on_principal_payment to onPrincipalPayment,
+ Res.string.loan_new_loan_on_interest_payment to onInternestPayment,
+ Res.string.loan_new_loan_on_arrears_aging to onAreasAging,
+ Res.string.loan_new_loan_enable_installment_level to enableInstallmentLevelDelinquency,
+ Res.string.loan_new_loan_recalculate_interest to recalculateInterest,
+ Res.string.loan_new_loan_days_in_month to daysInMonth,
+ ),
+ )
+}
+
+@Composable
+private fun TermsCard(
+ principal: String,
+ loanTerm: String,
+ numberOfRepayments: String,
+ firstRepaymentDate: String,
+ interestChargedForm: String,
+ repaidEvery: String,
+ nominalInterestRate: String,
+ isEqualAmortization: String,
+ amortization: String,
+ interestCalculationPeriod: String,
+ calculateInterestForExactDaysInPartial: String,
+ arrearsTolerance: String,
+ interestFreePeriod: String,
+ repaymentStrategy: String,
+ installmentAmount: String,
+ ballonRepayment: String,
+) {
+ MifosDefaultListingComponentFromStringResources(
+ data = mapOf(
+ Res.string.principal to principal,
+ Res.string.loan_new_loan_loan_term to loanTerm,
+ Res.string.number_of_repayments to numberOfRepayments,
+ Res.string.first_repayment_date to firstRepaymentDate,
+ Res.string.interest_charged_from to interestChargedForm,
+ Res.string.loan_new_loan_repaid_every to repaidEvery,
+ Res.string.loan_new_loan_nominal_interest_rate to nominalInterestRate,
+ Res.string.loan_new_loan_is_equal_amortization to isEqualAmortization,
+ Res.string.loan_new_loan_amortization to amortization,
+ Res.string.interest_calculation_period to interestCalculationPeriod,
+ Res.string.loan_new_loan_calculate_interest_for_exact_days_in_pertial to calculateInterestForExactDaysInPartial,
+ Res.string.loan_new_loan_arrears_tolerance to arrearsTolerance,
+ Res.string.loan_new_loan_interest_free_period to interestFreePeriod,
+ Res.string.repayment_strategy to repaymentStrategy,
+ Res.string.loan_new_loan_installment_amount to installmentAmount,
+ Res.string.loan_new_loan_ballon_repayment_amount to ballonRepayment,
+ ),
+ )
+}
+
+@Composable
+private fun DetailsCard(
+ productName: String,
+ loanOfficer: String,
+ externalId: String,
+ submittedDate: String,
+ expectedDisbursement: String,
+ loadPurpose: String,
+ isSavingsLinked: String,
+) {
+ MifosDefaultListingComponentFromStringResources(
+ data = mapOf(
+ Res.string.product_name to productName,
+ Res.string.loan_new_loan_loan_officer to loanOfficer,
+ Res.string.external_id to externalId,
+ Res.string.submission_date to submittedDate,
+ Res.string.expected_disbursement to expectedDisbursement,
+ Res.string.loan_new_loan_loan_purpose to loadPurpose,
+ Res.string.loan_new_loan_is_savings_linked to isSavingsLinked,
+ ),
+ )
+}