From 1a769f85dd13f4c11de5e92d9f98d2139718c93a Mon Sep 17 00:00:00 2001 From: itsPronay Date: Tue, 16 Sep 2025 14:18:42 +0600 Subject: [PATCH 1/4] preview --- .../components/MifosRowWithTextAndButton.kt | 3 + .../newLoanAccount/NewLoanAccountScreen.kt | 5 +- .../loan/newLoanAccount/pages/PreviewPage.kt | 361 +++++++++++++++++- 3 files changed, 356 insertions(+), 13 deletions(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRowWithTextAndButton.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRowWithTextAndButton.kt index eb502411759..224c43ec9d7 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRowWithTextAndButton.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRowWithTextAndButton.kt @@ -12,12 +12,14 @@ package com.mifos.core.ui.components import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme 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.designsystem.component.MifosOutlinedButton import com.mifos.core.designsystem.theme.DesignToken import com.mifos.core.designsystem.theme.MifosTheme @@ -46,6 +48,7 @@ fun MifosRowWithTextAndButton( ) Spacer(Modifier.width(DesignToken.padding.extraSmall)) MifosOutlinedButton( + modifier = Modifier.height(36.dp), onClick = { onBtnClick() }, text = { Text( 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..c6a716de1ca 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,7 +136,9 @@ private fun NewLoanAccountScaffold( } }, Step(stringResource(Res.string.step_preview)) { - PreviewPage { + PreviewPage( + state = state + ) { onAction(NewLoanAccountAction.NextStep) } }, @@ -483,3 +485,4 @@ private fun ShowChargesDialog( }, ) } + 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..283ca4f88b0 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,363 @@ 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 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.Row +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.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mifos.core.designsystem.theme.MifosTypography +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, +) { + val notAvailable = "Not Available" + Column( + modifier = Modifier.fillMaxSize() + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(20.dp), + ) { + Text( + "Details", + style = MifosTypography.labelLarge, + ) + DetailsCard( + productName = state.productLoans[state.loanProductSelected].name.toString(), + loanOfficer = if (state.loanOfficerIndex == -1) { + notAvailable + } else { + state.loanTemplate?.loanOfficerOptions[state.loanOfficerIndex]?.displayName.toString() + }, + externalId = state.externalId, + submittedDate = state.submissionDate, + expectedDisbursement = state.expectedDisbursementDate, + loadPurpose = if (state.loanPurposeIndex == -1) { + notAvailable + } else state.loanTemplate?.loanPurposeOptions[state.loanPurposeIndex]?.name.toString(), + isSavingsLinked = if (state.linkSavingsIndex == -1) { + "NO" + } else "YES", + ) + + Text( + "Terms", + style = MifosTypography.labelLarge, + ) + TermsCard( + //todo currency + principal = state.principalAmount.toString(), + loanTerm = if (state.termFrequencyIndex == -1) { + notAvailable + } 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) { + notAvailable + } else { + state.loanTemplate?.transactionProcessingStrategyOptions[state.repaymentStrategyIndex]?.name + ?: notAvailable + }, + installmentAmount = "", + ballonRepayment = state.balloonRepaymentAmount.toString(), + ) + + Text( + "Moratorium", + style = MifosTypography.labelLarge, + ) + MoratoriumCard( + onPrincipalPayment = state.moratoriumGraceOnPrincipalPayment.toString(), + onInternestPayment = state.moratoriumGraceOnInterestPayment.toString(), + onAreasAging = state.moratoriumOnArrearsAgeing.toString(), + enableInstallmentLevelDelinquency = "", + recalculateInterest = "", + daysInMonth = "", + ) + + Text( + "Moratorium", + style = MifosTypography.labelLarge, + ) + + MifosRowWithTextAndButton( + onBtnClick = {}, + text = "Add Charges", + btnText = "View", + modifier = Modifier.fillMaxWidth(), + ) + + MifosTwoButtonRow( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + firstBtnText = "Back", + secondBtnText = "Submit", + onFirstBtnClick = {}, + onSecondBtnClick = {}, + ) + } +} + +@Composable +private fun MoratoriumCard( + onPrincipalPayment: String, + onInternestPayment: String, + onAreasAging: String, + enableInstallmentLevelDelinquency: String, + recalculateInterest: String, + daysInMonth: String, +) { + OutlinedCard( + modifier = Modifier.fillMaxWidth(), + ) { + Column( + modifier = Modifier.fillMaxWidth().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + LoanPreviewItemRow( + title = "On principal payment", + description = onPrincipalPayment, + ) + + LoanPreviewItemRow( + title = "On interest payment", + description = onInternestPayment, + ) + + LoanPreviewItemRow( + title = "On Arrears Aging", + description = onAreasAging, + ) + + LoanPreviewItemRow( + title = "Enable installment level Delinquency", + description = enableInstallmentLevelDelinquency, + ) + + LoanPreviewItemRow( + title = "Recalculate Interest", + description = recalculateInterest, + ) + + LoanPreviewItemRow( + title = "Days in month", + description = 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, +) { + OutlinedCard( + modifier = Modifier.fillMaxWidth(), + ) { + Column( + modifier = Modifier.fillMaxWidth().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + LoanPreviewItemRow( + title = "Principal", + description = principal, + ) + + LoanPreviewItemRow( + title = "Loan Term", + description = loanTerm, + ) + + LoanPreviewItemRow( + title = "Number of Repayments", + description = numberOfRepayments, + ) + + LoanPreviewItemRow( + title = "First Repayment Date", + description = firstRepaymentDate, + ) + + LoanPreviewItemRow( + title = "Interest Charged From:", + description = interestChargedForm, + ) + + LoanPreviewItemRow( + title = "Repaid Every:", + description = repaidEvery, + ) + + LoanPreviewItemRow( + title = "Nominal Interest Rate:", + description = nominalInterestRate, + ) + + LoanPreviewItemRow( + title = "Is Equal Amortization:", + description = isEqualAmortization, + ) + + LoanPreviewItemRow( + title = "Amortization:", + description = amortization, + ) + LoanPreviewItemRow( + title = "Interest Calculation Period:", + description = interestCalculationPeriod, + ) + + LoanPreviewItemRow( + title = "Calculate interest for exact days in partial :", + description = calculateInterestForExactDaysInPartial, + ) + LoanPreviewItemRow( + title = "Arrears tolerance:", + description = arrearsTolerance, + ) + + LoanPreviewItemRow( + title = "Interest free period:", + description = interestFreePeriod, + ) + LoanPreviewItemRow( + title = "Repayment strategy:", + description = repaymentStrategy, + ) + LoanPreviewItemRow( + title = "Installment Amount:", + description = installmentAmount, + ) + LoanPreviewItemRow( + title = "Balloon Repayment Amount", + description = ballonRepayment, + ) + } + } +} + +@Composable +private fun DetailsCard( + productName: String, + loanOfficer: String, + externalId: String, + submittedDate: String, + expectedDisbursement: String, + loadPurpose: String, + isSavingsLinked: String, +) { + OutlinedCard( + modifier = Modifier.fillMaxWidth(), + ) { + Column( + modifier = Modifier.fillMaxWidth().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + LoanPreviewItemRow(title = "Product Name", description = productName) + LoanPreviewItemRow(title = "Loan Officer", description = loanOfficer) + LoanPreviewItemRow(title = "External ID", description = externalId) + LoanPreviewItemRow( + title = "Submitted Date", + description = submittedDate, + ) + + LoanPreviewItemRow( + title = "Expected Disbursement", + description = expectedDisbursement, + ) + + LoanPreviewItemRow( + title = "Loan Purpose", + description = loadPurpose, + ) + + LoanPreviewItemRow( + title = "Is Savings Linked", + description = isSavingsLinked, + ) + } + + } +} + +@Composable +private fun LoanPreviewItemRow( + title: String, + description: String, +) { + Row( + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = "$title:", + style = MifosTypography.labelMediumEmphasized, + modifier = Modifier.weight(5f), + maxLines = 1, + ) + + Text( + text = description, + modifier = Modifier.weight(5f), + maxLines = 1, + textAlign = TextAlign.End, + style = MifosTypography.labelMedium, + ) } } From aa1e011325c9ab4f60c3632179568dfb7efd4c48 Mon Sep 17 00:00:00 2001 From: itsPronay Date: Tue, 16 Sep 2025 16:05:49 +0600 Subject: [PATCH 2/4] update --- .../composeResources/values/strings.xml | 41 +++++ .../loan/newLoanAccount/pages/PreviewPage.kt | 168 +++++++++++------- 2 files changed, 141 insertions(+), 68 deletions(-) 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/pages/PreviewPage.kt b/feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/pages/PreviewPage.kt index 283ca4f88b0..160bbdaedf0 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,6 +10,44 @@ package com.mifos.feature.loan.newLoanAccount.pages import androidclient.feature.loan.generated.resources.Res +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.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.Row @@ -18,6 +56,9 @@ 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.CardColors +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -39,20 +80,19 @@ fun PreviewPage( state: NewLoanAccountState, onAction: (NewLoanAccountAction) -> Unit, ) { - val notAvailable = "Not Available" Column( modifier = Modifier.fillMaxSize() .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(20.dp), ) { Text( - "Details", + text = stringResource(Res.string.terms), style = MifosTypography.labelLarge, ) DetailsCard( productName = state.productLoans[state.loanProductSelected].name.toString(), loanOfficer = if (state.loanOfficerIndex == -1) { - notAvailable + "" } else { state.loanTemplate?.loanOfficerOptions[state.loanOfficerIndex]?.displayName.toString() }, @@ -60,22 +100,22 @@ fun PreviewPage( submittedDate = state.submissionDate, expectedDisbursement = state.expectedDisbursementDate, loadPurpose = if (state.loanPurposeIndex == -1) { - notAvailable + "" } else state.loanTemplate?.loanPurposeOptions[state.loanPurposeIndex]?.name.toString(), isSavingsLinked = if (state.linkSavingsIndex == -1) { - "NO" - } else "YES", + stringResource(Res.string.no) + } else stringResource(Res.string.yes), ) Text( - "Terms", + text = stringResource(Res.string.terms), style = MifosTypography.labelLarge, ) TermsCard( //todo currency principal = state.principalAmount.toString(), loanTerm = if (state.termFrequencyIndex == -1) { - notAvailable + "" } else { state.loanTemplate?.termFrequencyTypeOptions[state.termFrequencyIndex]?.value ?: "" }, @@ -101,17 +141,17 @@ fun PreviewPage( arrearsTolerance = state.arrearsTolerance.toString(), interestFreePeriod = state.interestFreePeriod.toString(), repaymentStrategy = if (state.repaymentStrategyIndex == -1) { - notAvailable + "" } else { state.loanTemplate?.transactionProcessingStrategyOptions[state.repaymentStrategyIndex]?.name - ?: notAvailable + ?: "" }, installmentAmount = "", ballonRepayment = state.balloonRepaymentAmount.toString(), ) Text( - "Moratorium", + text = stringResource(Res.string.loan_new_loan_moratorium), style = MifosTypography.labelLarge, ) MoratoriumCard( @@ -124,21 +164,21 @@ fun PreviewPage( ) Text( - "Moratorium", + text = stringResource(Res.string.loan_new_loan_charges), style = MifosTypography.labelLarge, ) MifosRowWithTextAndButton( onBtnClick = {}, - text = "Add Charges", - btnText = "View", + 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.fillMaxWidth().padding(horizontal = 16.dp), - firstBtnText = "Back", - secondBtnText = "Submit", + firstBtnText = stringResource(Res.string.back), + secondBtnText = stringResource(Res.string.feature_loan_charge_submit), onFirstBtnClick = {}, onSecondBtnClick = {}, ) @@ -156,45 +196,39 @@ private fun MoratoriumCard( ) { OutlinedCard( modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.background, + ), ) { Column( modifier = Modifier.fillMaxWidth().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { LoanPreviewItemRow( - title = "On principal payment", + title = stringResource(Res.string.loan_new_loan_on_principal_payment), description = onPrincipalPayment, ) - LoanPreviewItemRow( - title = "On interest payment", + title = stringResource(Res.string.loan_new_loan_on_interest_payment), description = onInternestPayment, ) - LoanPreviewItemRow( - title = "On Arrears Aging", + title = stringResource(Res.string.loan_new_loan_on_arrears_aging), description = onAreasAging, ) - LoanPreviewItemRow( - title = "Enable installment level Delinquency", + title = stringResource(Res.string.loan_new_loan_enable_installment_level), description = enableInstallmentLevelDelinquency, ) - LoanPreviewItemRow( - title = "Recalculate Interest", + title = stringResource(Res.string.loan_new_loan_recalculate_interest), description = recalculateInterest, ) - LoanPreviewItemRow( - title = "Days in month", + title = stringResource(Res.string.loan_new_loan_days_in_month), description = daysInMonth, ) - - } - - } } @@ -219,83 +253,76 @@ private fun TermsCard( ) { OutlinedCard( modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.background, + ), ) { Column( modifier = Modifier.fillMaxWidth().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { LoanPreviewItemRow( - title = "Principal", + title = stringResource(Res.string.principal), description = principal, ) - LoanPreviewItemRow( - title = "Loan Term", + title = stringResource(Res.string.loan_new_loan_loan_term), description = loanTerm, ) - LoanPreviewItemRow( - title = "Number of Repayments", + title = stringResource(Res.string.number_of_repayments), description = numberOfRepayments, ) - LoanPreviewItemRow( - title = "First Repayment Date", + title = stringResource(Res.string.first_repayment_date), description = firstRepaymentDate, ) - LoanPreviewItemRow( - title = "Interest Charged From:", + title = stringResource(Res.string.interest_charged_from), description = interestChargedForm, ) - LoanPreviewItemRow( - title = "Repaid Every:", + title = stringResource(Res.string.loan_new_loan_repaid_every), description = repaidEvery, ) - LoanPreviewItemRow( - title = "Nominal Interest Rate:", + title = stringResource(Res.string.loan_new_loan_nominal_interest_rate), description = nominalInterestRate, ) - LoanPreviewItemRow( - title = "Is Equal Amortization:", + title = stringResource(Res.string.loan_new_loan_is_equal_amortization), description = isEqualAmortization, ) - LoanPreviewItemRow( - title = "Amortization:", + title = stringResource(Res.string.loan_new_loan_amortization), description = amortization, ) LoanPreviewItemRow( - title = "Interest Calculation Period:", + title = stringResource(Res.string.interest_calculation_period), description = interestCalculationPeriod, ) - LoanPreviewItemRow( - title = "Calculate interest for exact days in partial :", + title = stringResource(Res.string.loan_new_loan_calculate_interest_for_exact_days_in_pertial), description = calculateInterestForExactDaysInPartial, ) LoanPreviewItemRow( - title = "Arrears tolerance:", + title = stringResource(Res.string.loan_new_loan_arrears_tolerance), description = arrearsTolerance, ) - LoanPreviewItemRow( - title = "Interest free period:", + title = stringResource(Res.string.loan_new_loan_interest_free_period), description = interestFreePeriod, ) LoanPreviewItemRow( - title = "Repayment strategy:", + title = stringResource(Res.string.repayment_strategy), description = repaymentStrategy, ) LoanPreviewItemRow( - title = "Installment Amount:", + title = stringResource(Res.string.loan_new_loan_installment_amount), description = installmentAmount, ) LoanPreviewItemRow( - title = "Balloon Repayment Amount", + title = stringResource(Res.string.loan_new_loan_ballon_repayment_amount), description = ballonRepayment, ) } @@ -319,30 +346,35 @@ private fun DetailsCard( modifier = Modifier.fillMaxWidth().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { - LoanPreviewItemRow(title = "Product Name", description = productName) - LoanPreviewItemRow(title = "Loan Officer", description = loanOfficer) - LoanPreviewItemRow(title = "External ID", description = externalId) LoanPreviewItemRow( - title = "Submitted Date", + title = stringResource(Res.string.product_name), + description = productName, + ) + LoanPreviewItemRow( + title = stringResource(Res.string.loan_new_loan_loan_officer), + description = loanOfficer, + ) + LoanPreviewItemRow( + title = stringResource(Res.string.external_id), + description = externalId, + ) + LoanPreviewItemRow( + title = stringResource(Res.string.submission_date), description = submittedDate, ) - LoanPreviewItemRow( - title = "Expected Disbursement", + title = stringResource(Res.string.expected_disbursement), description = expectedDisbursement, ) - LoanPreviewItemRow( - title = "Loan Purpose", + title = stringResource(Res.string.loan_new_loan_loan_purpose), description = loadPurpose, ) - LoanPreviewItemRow( - title = "Is Savings Linked", + title = stringResource(Res.string.loan_new_loan_is_savings_linked), description = isSavingsLinked, ) } - } } From e8722763f344da1da2a38c8d178a9d6c8d69d15a Mon Sep 17 00:00:00 2001 From: itsPronay Date: Tue, 16 Sep 2025 21:06:19 +0600 Subject: [PATCH 3/4] update --- .../loan/newLoanAccount/NewLoanAccountViewModel.kt | 13 +++++++++++++ .../loan/newLoanAccount/pages/PreviewPage.kt | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) 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..44728a38746 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 @@ -23,6 +23,7 @@ import com.mifos.core.network.model.CollateralItem import com.mifos.core.ui.util.BaseViewModel import com.mifos.core.ui.util.TextFieldsValidator import com.mifos.feature.loan.newLoanAccount.NewLoanAccountState.DialogState +import com.mifos.room.entities.accounts.loans.LoanAccountEntity import com.mifos.room.entities.templates.loans.LoanTemplate import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -172,9 +173,19 @@ internal class NewLoanAccountViewModel( is NewLoanAccountAction.EditChargeDialog -> handleEditChargeDialog(action.index) is NewLoanAccountAction.EditCharge -> handleEditCharge(action.index) + + NewLoanAccountAction.GotoPreviousStep -> {} + NewLoanAccountAction.SubmitLoanApplication -> { + + } } } + private fun submitLoanApplication() { + viewModelScope.launch { + LoanAccountEntity + } + } private fun handleChooseChargeIndexChange(action: NewLoanAccountAction.OnChooseChargeIndexChange) { mutableStateFlow.update { it.copy(chooseChargeIndex = action.index) @@ -851,6 +862,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 160bbdaedf0..d510dc0cdf2 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 @@ -146,6 +146,7 @@ fun PreviewPage( state.loanTemplate?.transactionProcessingStrategyOptions[state.repaymentStrategyIndex]?.name ?: "" }, + //todo installmentAmount = "", ballonRepayment = state.balloonRepaymentAmount.toString(), ) @@ -158,8 +159,14 @@ fun PreviewPage( onPrincipalPayment = state.moratoriumGraceOnPrincipalPayment.toString(), onInternestPayment = state.moratoriumGraceOnInterestPayment.toString(), onAreasAging = state.moratoriumOnArrearsAgeing.toString(), + //todo enableInstallmentLevelDelinquency = "", - recalculateInterest = "", + recalculateInterest = if (state.loanTemplate?.isInterestRecalculationEnabled ?: false) { + stringResource(Res.string.yes) + } else { + stringResource(Res.string.no) + }, + //todo daysInMonth = "", ) From b4254658112b1364e04aa33c9e1eb5c6ef5fb5aa Mon Sep 17 00:00:00 2001 From: itsPronay Date: Wed, 17 Sep 2025 22:33:00 +0600 Subject: [PATCH 4/4] update --- .../newLoanAccount/NewLoanAccountScreen.kt | 3 +- .../newLoanAccount/NewLoanAccountViewModel.kt | 195 ++++++++++++++---- .../loan/newLoanAccount/pages/PreviewPage.kt | 44 ++-- 3 files changed, 189 insertions(+), 53 deletions(-) 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 c6a716de1ca..2990bbcd07c 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 @@ -137,7 +137,7 @@ private fun NewLoanAccountScaffold( }, Step(stringResource(Res.string.step_preview)) { PreviewPage( - state = state + state = state, ) { onAction(NewLoanAccountAction.NextStep) } @@ -485,4 +485,3 @@ private fun ShowChargesDialog( }, ) } - 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 44728a38746..7a5ccf4c7e8 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,18 +12,20 @@ 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 -import com.mifos.room.entities.accounts.loans.LoanAccountEntity import com.mifos.room.entities.templates.loans.LoanTemplate import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -36,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( @@ -72,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) @@ -82,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) @@ -110,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() @@ -144,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() @@ -154,7 +205,9 @@ internal class NewLoanAccountViewModel( is NewLoanAccountAction.AddChargeToList -> handleAddChargeToList() - is NewLoanAccountAction.OnChooseChargeIndexChange -> handleChooseChargeIndexChange(action) + is NewLoanAccountAction.OnChooseChargeIndexChange -> handleChooseChargeIndexChange( + action, + ) is NewLoanAccountAction.ShowAddChargeDialog -> handleShowAddChargeDialog() @@ -175,17 +228,68 @@ internal class NewLoanAccountViewModel( is NewLoanAccountAction.EditCharge -> handleEditCharge(action.index) NewLoanAccountAction.GotoPreviousStep -> {} - NewLoanAccountAction.SubmitLoanApplication -> { - } + NewLoanAccountAction.SubmitLoanApplication -> submitLoanApplication() } } private fun submitLoanApplication() { viewModelScope.launch { - LoanAccountEntity + 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.invoke(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) + } + } + } } } + private fun handleChooseChargeIndexChange(action: NewLoanAccountAction.OnChooseChargeIndexChange) { mutableStateFlow.update { it.copy(chooseChargeIndex = action.index) @@ -634,6 +738,7 @@ internal class NewLoanAccountViewModel( ) } } + else -> Unit } } @@ -709,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(), @@ -724,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, @@ -735,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, @@ -767,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 = "", @@ -780,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 } @@ -829,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 @@ -862,7 +983,7 @@ 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 SubmitLoanApplication : NewLoanAccountAction data object GotoPreviousStep : NewLoanAccountAction } 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 d510dc0cdf2..5d6636137e9 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 @@ -56,19 +56,16 @@ 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.CardColors import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.mifos.core.designsystem.theme.MifosTypography +import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowWithTextAndButton import com.mifos.core.ui.components.MifosTwoButtonRow import com.mifos.feature.loan.newLoanAccount.NewLoanAccountAction @@ -79,6 +76,21 @@ import org.jetbrains.compose.resources.stringResource fun PreviewPage( state: NewLoanAccountState, onAction: (NewLoanAccountAction) -> Unit, +) { + if (state.isLoading) { + MifosProgressIndicator() + } else { + PreviewPageContent( + state, + onAction = onAction, + ) + } +} + +@Composable +fun PreviewPageContent( + state: NewLoanAccountState, + onAction: (NewLoanAccountAction) -> Unit, ) { Column( modifier = Modifier.fillMaxSize() @@ -101,10 +113,14 @@ fun PreviewPage( expectedDisbursement = state.expectedDisbursementDate, loadPurpose = if (state.loanPurposeIndex == -1) { "" - } else state.loanTemplate?.loanPurposeOptions[state.loanPurposeIndex]?.name.toString(), + } else { + state.loanTemplate?.loanPurposeOptions[state.loanPurposeIndex]?.name.toString() + }, isSavingsLinked = if (state.linkSavingsIndex == -1) { stringResource(Res.string.no) - } else stringResource(Res.string.yes), + } else { + stringResource(Res.string.yes) + }, ) Text( @@ -112,7 +128,7 @@ fun PreviewPage( style = MifosTypography.labelLarge, ) TermsCard( - //todo currency + // todo currency principal = state.principalAmount.toString(), loanTerm = if (state.termFrequencyIndex == -1) { "" @@ -146,7 +162,7 @@ fun PreviewPage( state.loanTemplate?.transactionProcessingStrategyOptions[state.repaymentStrategyIndex]?.name ?: "" }, - //todo + // todo installmentAmount = "", ballonRepayment = state.balloonRepaymentAmount.toString(), ) @@ -159,14 +175,14 @@ fun PreviewPage( onPrincipalPayment = state.moratoriumGraceOnPrincipalPayment.toString(), onInternestPayment = state.moratoriumGraceOnInterestPayment.toString(), onAreasAging = state.moratoriumOnArrearsAgeing.toString(), - //todo + // todo enableInstallmentLevelDelinquency = "", recalculateInterest = if (state.loanTemplate?.isInterestRecalculationEnabled ?: false) { stringResource(Res.string.yes) } else { stringResource(Res.string.no) }, - //todo + // todo daysInMonth = "", ) @@ -176,18 +192,18 @@ fun PreviewPage( ) MifosRowWithTextAndButton( - onBtnClick = {}, + 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.fillMaxWidth().padding(horizontal = 16.dp), + modifier = Modifier.fillMaxWidth(), firstBtnText = stringResource(Res.string.back), secondBtnText = stringResource(Res.string.feature_loan_charge_submit), - onFirstBtnClick = {}, - onSecondBtnClick = {}, + onFirstBtnClick = { onAction(NewLoanAccountAction.GotoPreviousStep) }, + onSecondBtnClick = { onAction(NewLoanAccountAction.SubmitLoanApplication) }, ) } }