From a56ee69ba784ab36b92e25eb4fdf4501e9ff0cd7 Mon Sep 17 00:00:00 2001 From: Nagarjuna Date: Wed, 9 Apr 2025 17:17:37 +0530 Subject: [PATCH] refactor: handle api responses, cleaning up modules (#2837) --- build-logic/convention/build.gradle.kts | 4 - .../kotlin/AndroidHiltConventionPlugin.kt | 31 ----- build.gradle.kts | 1 - cmp-android/build.gradle.kts | 27 ----- .../demoDebugRuntimeClasspath.txt | 40 +------ .../demoReleaseRuntimeClasspath.txt | 40 +------ .../prodDebugRuntimeClasspath.txt | 40 +------ .../prodReleaseRuntimeClasspath.txt | 40 +------ .../navigation/navigation/FeatureNavHost.kt | 2 - .../mifos/mobile/core/common/DateHelper.kt | 3 - .../data/repository/TransferRepository.kt | 3 +- .../data/repositoryImpl/LoanRepositoryImp.kt | 36 +++--- .../SavingsAccountRepositoryImp.kt | 64 +++++++---- .../repositoryImpl/TransferRepositoryImp.kt | 27 +++-- .../mobile/core/data/util/ErrorHandling.kt | 17 +-- .../entity/accounts/loan/LoanWithdraw.kt | 4 +- .../savings/SavingsAccountUpdatePayload.kt | 7 +- .../savings/SavingsAccountWithdrawPayload.kt | 4 +- .../core/model/entity/mifoserror/Errors.kt | 7 +- .../model/entity/mifoserror/MifosError.kt | 7 +- .../services/SavingAccountsListService.kt | 3 +- .../services/ThirdPartyTransferService.kt | 4 +- .../feature/auth/login/LoginViewModel.kt | 3 - .../BeneficiaryApplicationViewModel.kt | 6 - .../BeneficiaryListViewModel.kt | 2 - .../charge/viewmodel/ClientChargeViewModel.kt | 2 - .../screen/LoanAccountScreenContent.kt | 14 +-- .../LoanAccountsDetailViewModel.kt | 2 - .../LoanAccountWithdrawScreen.kt | 44 ++++--- .../LoanAccountWithdrawViewModel.kt | 11 +- .../qrCodeDisplay/QrCodeDisplayViewModel.kt | 2 - .../screen/SavingsAccountScreenContent.kt | 36 +++--- .../SavingsAccountApplicationScreen.kt | 41 ++++--- .../SavingsAccountApplicationViewModel.kt | 108 ++++++++++++------ .../SavingAccountTransactionContent.kt | 2 - .../SavingsAccountWithdrawScreen.kt | 63 +++++----- .../SavingsAccountWithdrawViewModel.kt | 94 +++++++++------ .../transfer/ThirdPartyTransferViewModel.kt | 6 - .../process/TransferProcessViewModel.kt | 18 +-- .../navigation/TransferProcessNavGraph.kt | 2 +- .../profile/viewmodel/UserDetailViewModel.kt | 2 - gradle/libs.versions.toml | 20 +--- 42 files changed, 360 insertions(+), 529 deletions(-) delete mode 100644 build-logic/convention/src/main/kotlin/AndroidHiltConventionPlugin.kt diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 6d8751033..4b122dc40 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -71,10 +71,6 @@ gradlePlugin { } // Room Plugin - register("androidHilt") { - id = "mifos.android.hilt" - implementationClass = "AndroidHiltConventionPlugin" - } register("kmpRoom") { id = "mifos.kmp.room" implementationClass = "KMPRoomConventionPlugin" diff --git a/build-logic/convention/src/main/kotlin/AndroidHiltConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidHiltConventionPlugin.kt deleted file mode 100644 index 2d8bfac27..000000000 --- a/build-logic/convention/src/main/kotlin/AndroidHiltConventionPlugin.kt +++ /dev/null @@ -1,31 +0,0 @@ - -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.kotlin.dsl.dependencies -import org.mifos.mobile.libs - -class AndroidHiltConventionPlugin : Plugin { - override fun apply(target: Project) { - with(target) { - pluginManager.apply("com.google.devtools.ksp") - dependencies { - "ksp"(libs.findLibrary("hilt.compiler").get()) - } - - // Add support for Jvm Module, base on org.jetbrains.kotlin.jvm - pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { - dependencies { - "implementation"(libs.findLibrary("hilt.core").get()) - } - } - - /** Add support for Android modules, based on [AndroidBasePlugin] */ - pluginManager.withPlugin("com.android.base") { - pluginManager.apply("dagger.hilt.android.plugin") - dependencies { - "implementation"(libs.findLibrary("hilt.android").get()) - } - } - } - } -} diff --git a/build.gradle.kts b/build.gradle.kts index 53348c1c1..ff96dd548 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,7 +21,6 @@ plugins { alias(libs.plugins.firebase.perf) apply false alias(libs.plugins.gms) apply false - alias(libs.plugins.hilt) apply false alias(libs.plugins.room) apply false alias(libs.plugins.ksp) apply false diff --git a/cmp-android/build.gradle.kts b/cmp-android/build.gradle.kts index 333c0ce0a..9969891ed 100644 --- a/cmp-android/build.gradle.kts +++ b/cmp-android/build.gradle.kts @@ -104,34 +104,7 @@ dependencyGuard { dependencies { implementation(projects.cmpShared) - implementation(projects.core.logs) - implementation(projects.core.common) - implementation(projects.core.model) - implementation(projects.core.data) - implementation(projects.core.database) implementation(projects.core.ui) - implementation(projects.core.designsystem) - -// implementation(projects.feature.loan) -// implementation(projects.feature.beneficiary) -// implementation(projects.feature.guarantor) -// implementation(projects.feature.savings) -// implementation(projects.feature.qr) -// implementation(projects.feature.transferProcess) -// implementation(projects.feature.clientCharge) -// implementation(projects.feature.recentTransaction) -// implementation(projects.feature.thirdPartyTransfer) - implementation(projects.feature.help) -// implementation(projects.feature.notification) -// implementation(projects.feature.location) -// implementation(projects.feature.about) -// implementation(projects.feature.settings) -// implementation(projects.feature.updatePassword) -// implementation(projects.feature.home) -// implementation(projects.feature.auth) -// implementation(projects.feature.userProfile) - -// implementation(projects.libs.mifosPasscode) // Compose implementation(libs.androidx.core.ktx) diff --git a/cmp-android/dependencies/demoDebugRuntimeClasspath.txt b/cmp-android/dependencies/demoDebugRuntimeClasspath.txt index c6b3df197..c466ba0af 100644 --- a/cmp-android/dependencies/demoDebugRuntimeClasspath.txt +++ b/cmp-android/dependencies/demoDebugRuntimeClasspath.txt @@ -71,7 +71,6 @@ androidx.databinding:databinding-common:8.7.3 androidx.databinding:databinding-ktx:8.7.3 androidx.databinding:databinding-runtime:8.7.3 androidx.databinding:viewbinding:8.7.3 -androidx.documentfile:documentfile:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0 androidx.emoji2:emoji2-views-helper:1.3.0 androidx.emoji2:emoji2:1.3.0 @@ -80,7 +79,6 @@ androidx.fragment:fragment-ktx:1.8.5 androidx.fragment:fragment:1.8.5 androidx.graphics:graphics-path:1.0.1 androidx.interpolator:interpolator:1.0.0 -androidx.legacy:legacy-support-core-utils:1.0.0 androidx.lifecycle:lifecycle-common-java8:2.8.7 androidx.lifecycle:lifecycle-common-jvm:2.8.7 androidx.lifecycle:lifecycle-common:2.8.7 @@ -102,7 +100,6 @@ androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 androidx.lifecycle:lifecycle-viewmodel:2.8.7 androidx.loader:loader:1.0.0 -androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 androidx.navigation:navigation-common-ktx:2.8.4 androidx.navigation:navigation-common:2.8.4 @@ -111,25 +108,11 @@ androidx.navigation:navigation-fragment-ktx:2.8.4 androidx.navigation:navigation-fragment:2.8.4 androidx.navigation:navigation-runtime-ktx:2.8.4 androidx.navigation:navigation-runtime:2.8.4 -androidx.print:print:1.0.0 -androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 -androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common-jvm:2.7.0-alpha12 -androidx.room:room-common:2.7.0-alpha12 -androidx.room:room-ktx:2.7.0-alpha12 -androidx.room:room-runtime-android:2.7.0-alpha12 -androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 androidx.slidingpanelayout:slidingpanelayout:1.2.0 -androidx.sqlite:sqlite-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled:2.5.0-alpha12 -androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 -androidx.sqlite:sqlite-framework:2.5.0-alpha12 -androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 @@ -165,36 +148,20 @@ com.google.accompanist:accompanist-permissions:0.34.0 com.google.android.datatransport:transport-api:2.2.1 com.google.android.datatransport:transport-backend-cct:2.3.3 com.google.android.datatransport:transport-runtime:2.2.6 -com.google.android.gms:play-services-ads-identifier:18.0.0 com.google.android.gms:play-services-base:18.5.0 com.google.android.gms:play-services-basement:18.4.0 com.google.android.gms:play-services-maps:18.2.0 -com.google.android.gms:play-services-measurement-api:22.1.2 -com.google.android.gms:play-services-measurement-base:22.1.2 -com.google.android.gms:play-services-measurement-impl:22.1.2 -com.google.android.gms:play-services-measurement-sdk-api:22.1.2 -com.google.android.gms:play-services-measurement-sdk:22.1.2 -com.google.android.gms:play-services-measurement:22.1.2 com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1 com.google.android.gms:play-services-oss-licenses:17.1.0 -com.google.android.gms:play-services-stats:17.0.2 com.google.android.gms:play-services-tasks:18.2.0 com.google.android.odml:image:1.0.0-beta1 com.google.auto.value:auto-value-annotations:1.6.3 com.google.code.findbugs:jsr305:3.0.2 com.google.errorprone:error_prone_annotations:2.28.0 -com.google.firebase:firebase-analytics-ktx:22.1.2 -com.google.firebase:firebase-analytics:22.1.2 -com.google.firebase:firebase-annotations:16.2.0 -com.google.firebase:firebase-bom:33.7.0 -com.google.firebase:firebase-common-ktx:21.0.0 -com.google.firebase:firebase-common:21.0.0 -com.google.firebase:firebase-components:18.0.0 +com.google.firebase:firebase-annotations:16.0.0 +com.google.firebase:firebase-components:16.1.0 com.google.firebase:firebase-encoders-json:17.1.0 -com.google.firebase:firebase-encoders:17.0.0 -com.google.firebase:firebase-installations-interop:17.1.1 -com.google.firebase:firebase-installations:18.0.0 -com.google.firebase:firebase-measurement-connector:19.0.0 +com.google.firebase:firebase-encoders:16.1.0 com.google.guava:failureaccess:1.0.2 com.google.guava:guava:33.3.1-android com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava @@ -348,7 +315,6 @@ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1 -org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.10.1 org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1 diff --git a/cmp-android/dependencies/demoReleaseRuntimeClasspath.txt b/cmp-android/dependencies/demoReleaseRuntimeClasspath.txt index 0cb9be909..be6d561be 100644 --- a/cmp-android/dependencies/demoReleaseRuntimeClasspath.txt +++ b/cmp-android/dependencies/demoReleaseRuntimeClasspath.txt @@ -67,7 +67,6 @@ androidx.databinding:databinding-common:8.7.3 androidx.databinding:databinding-ktx:8.7.3 androidx.databinding:databinding-runtime:8.7.3 androidx.databinding:viewbinding:8.7.3 -androidx.documentfile:documentfile:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0 androidx.emoji2:emoji2-views-helper:1.3.0 androidx.emoji2:emoji2:1.3.0 @@ -76,7 +75,6 @@ androidx.fragment:fragment-ktx:1.8.5 androidx.fragment:fragment:1.8.5 androidx.graphics:graphics-path:1.0.1 androidx.interpolator:interpolator:1.0.0 -androidx.legacy:legacy-support-core-utils:1.0.0 androidx.lifecycle:lifecycle-common-java8:2.8.7 androidx.lifecycle:lifecycle-common-jvm:2.8.7 androidx.lifecycle:lifecycle-common:2.8.7 @@ -98,7 +96,6 @@ androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 androidx.lifecycle:lifecycle-viewmodel:2.8.7 androidx.loader:loader:1.0.0 -androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 androidx.navigation:navigation-common-ktx:2.8.4 androidx.navigation:navigation-common:2.8.4 @@ -107,25 +104,11 @@ androidx.navigation:navigation-fragment-ktx:2.8.4 androidx.navigation:navigation-fragment:2.8.4 androidx.navigation:navigation-runtime-ktx:2.8.4 androidx.navigation:navigation-runtime:2.8.4 -androidx.print:print:1.0.0 -androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 -androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common-jvm:2.7.0-alpha12 -androidx.room:room-common:2.7.0-alpha12 -androidx.room:room-ktx:2.7.0-alpha12 -androidx.room:room-runtime-android:2.7.0-alpha12 -androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 androidx.slidingpanelayout:slidingpanelayout:1.2.0 -androidx.sqlite:sqlite-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled:2.5.0-alpha12 -androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 -androidx.sqlite:sqlite-framework:2.5.0-alpha12 -androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 @@ -161,36 +144,20 @@ com.google.accompanist:accompanist-permissions:0.34.0 com.google.android.datatransport:transport-api:2.2.1 com.google.android.datatransport:transport-backend-cct:2.3.3 com.google.android.datatransport:transport-runtime:2.2.6 -com.google.android.gms:play-services-ads-identifier:18.0.0 com.google.android.gms:play-services-base:18.5.0 com.google.android.gms:play-services-basement:18.4.0 com.google.android.gms:play-services-maps:18.2.0 -com.google.android.gms:play-services-measurement-api:22.1.2 -com.google.android.gms:play-services-measurement-base:22.1.2 -com.google.android.gms:play-services-measurement-impl:22.1.2 -com.google.android.gms:play-services-measurement-sdk-api:22.1.2 -com.google.android.gms:play-services-measurement-sdk:22.1.2 -com.google.android.gms:play-services-measurement:22.1.2 com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1 com.google.android.gms:play-services-oss-licenses:17.1.0 -com.google.android.gms:play-services-stats:17.0.2 com.google.android.gms:play-services-tasks:18.2.0 com.google.android.odml:image:1.0.0-beta1 com.google.auto.value:auto-value-annotations:1.6.3 com.google.code.findbugs:jsr305:3.0.2 com.google.errorprone:error_prone_annotations:2.28.0 -com.google.firebase:firebase-analytics-ktx:22.1.2 -com.google.firebase:firebase-analytics:22.1.2 -com.google.firebase:firebase-annotations:16.2.0 -com.google.firebase:firebase-bom:33.7.0 -com.google.firebase:firebase-common-ktx:21.0.0 -com.google.firebase:firebase-common:21.0.0 -com.google.firebase:firebase-components:18.0.0 +com.google.firebase:firebase-annotations:16.0.0 +com.google.firebase:firebase-components:16.1.0 com.google.firebase:firebase-encoders-json:17.1.0 -com.google.firebase:firebase-encoders:17.0.0 -com.google.firebase:firebase-installations-interop:17.1.1 -com.google.firebase:firebase-installations:18.0.0 -com.google.firebase:firebase-measurement-connector:19.0.0 +com.google.firebase:firebase-encoders:16.1.0 com.google.guava:failureaccess:1.0.2 com.google.guava:guava:33.3.1-android com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava @@ -344,7 +311,6 @@ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1 -org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.10.1 org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1 diff --git a/cmp-android/dependencies/prodDebugRuntimeClasspath.txt b/cmp-android/dependencies/prodDebugRuntimeClasspath.txt index c6b3df197..c466ba0af 100644 --- a/cmp-android/dependencies/prodDebugRuntimeClasspath.txt +++ b/cmp-android/dependencies/prodDebugRuntimeClasspath.txt @@ -71,7 +71,6 @@ androidx.databinding:databinding-common:8.7.3 androidx.databinding:databinding-ktx:8.7.3 androidx.databinding:databinding-runtime:8.7.3 androidx.databinding:viewbinding:8.7.3 -androidx.documentfile:documentfile:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0 androidx.emoji2:emoji2-views-helper:1.3.0 androidx.emoji2:emoji2:1.3.0 @@ -80,7 +79,6 @@ androidx.fragment:fragment-ktx:1.8.5 androidx.fragment:fragment:1.8.5 androidx.graphics:graphics-path:1.0.1 androidx.interpolator:interpolator:1.0.0 -androidx.legacy:legacy-support-core-utils:1.0.0 androidx.lifecycle:lifecycle-common-java8:2.8.7 androidx.lifecycle:lifecycle-common-jvm:2.8.7 androidx.lifecycle:lifecycle-common:2.8.7 @@ -102,7 +100,6 @@ androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 androidx.lifecycle:lifecycle-viewmodel:2.8.7 androidx.loader:loader:1.0.0 -androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 androidx.navigation:navigation-common-ktx:2.8.4 androidx.navigation:navigation-common:2.8.4 @@ -111,25 +108,11 @@ androidx.navigation:navigation-fragment-ktx:2.8.4 androidx.navigation:navigation-fragment:2.8.4 androidx.navigation:navigation-runtime-ktx:2.8.4 androidx.navigation:navigation-runtime:2.8.4 -androidx.print:print:1.0.0 -androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 -androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common-jvm:2.7.0-alpha12 -androidx.room:room-common:2.7.0-alpha12 -androidx.room:room-ktx:2.7.0-alpha12 -androidx.room:room-runtime-android:2.7.0-alpha12 -androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 androidx.slidingpanelayout:slidingpanelayout:1.2.0 -androidx.sqlite:sqlite-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled:2.5.0-alpha12 -androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 -androidx.sqlite:sqlite-framework:2.5.0-alpha12 -androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 @@ -165,36 +148,20 @@ com.google.accompanist:accompanist-permissions:0.34.0 com.google.android.datatransport:transport-api:2.2.1 com.google.android.datatransport:transport-backend-cct:2.3.3 com.google.android.datatransport:transport-runtime:2.2.6 -com.google.android.gms:play-services-ads-identifier:18.0.0 com.google.android.gms:play-services-base:18.5.0 com.google.android.gms:play-services-basement:18.4.0 com.google.android.gms:play-services-maps:18.2.0 -com.google.android.gms:play-services-measurement-api:22.1.2 -com.google.android.gms:play-services-measurement-base:22.1.2 -com.google.android.gms:play-services-measurement-impl:22.1.2 -com.google.android.gms:play-services-measurement-sdk-api:22.1.2 -com.google.android.gms:play-services-measurement-sdk:22.1.2 -com.google.android.gms:play-services-measurement:22.1.2 com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1 com.google.android.gms:play-services-oss-licenses:17.1.0 -com.google.android.gms:play-services-stats:17.0.2 com.google.android.gms:play-services-tasks:18.2.0 com.google.android.odml:image:1.0.0-beta1 com.google.auto.value:auto-value-annotations:1.6.3 com.google.code.findbugs:jsr305:3.0.2 com.google.errorprone:error_prone_annotations:2.28.0 -com.google.firebase:firebase-analytics-ktx:22.1.2 -com.google.firebase:firebase-analytics:22.1.2 -com.google.firebase:firebase-annotations:16.2.0 -com.google.firebase:firebase-bom:33.7.0 -com.google.firebase:firebase-common-ktx:21.0.0 -com.google.firebase:firebase-common:21.0.0 -com.google.firebase:firebase-components:18.0.0 +com.google.firebase:firebase-annotations:16.0.0 +com.google.firebase:firebase-components:16.1.0 com.google.firebase:firebase-encoders-json:17.1.0 -com.google.firebase:firebase-encoders:17.0.0 -com.google.firebase:firebase-installations-interop:17.1.1 -com.google.firebase:firebase-installations:18.0.0 -com.google.firebase:firebase-measurement-connector:19.0.0 +com.google.firebase:firebase-encoders:16.1.0 com.google.guava:failureaccess:1.0.2 com.google.guava:guava:33.3.1-android com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava @@ -348,7 +315,6 @@ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1 -org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.10.1 org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1 diff --git a/cmp-android/dependencies/prodReleaseRuntimeClasspath.txt b/cmp-android/dependencies/prodReleaseRuntimeClasspath.txt index 0cb9be909..be6d561be 100644 --- a/cmp-android/dependencies/prodReleaseRuntimeClasspath.txt +++ b/cmp-android/dependencies/prodReleaseRuntimeClasspath.txt @@ -67,7 +67,6 @@ androidx.databinding:databinding-common:8.7.3 androidx.databinding:databinding-ktx:8.7.3 androidx.databinding:databinding-runtime:8.7.3 androidx.databinding:viewbinding:8.7.3 -androidx.documentfile:documentfile:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0 androidx.emoji2:emoji2-views-helper:1.3.0 androidx.emoji2:emoji2:1.3.0 @@ -76,7 +75,6 @@ androidx.fragment:fragment-ktx:1.8.5 androidx.fragment:fragment:1.8.5 androidx.graphics:graphics-path:1.0.1 androidx.interpolator:interpolator:1.0.0 -androidx.legacy:legacy-support-core-utils:1.0.0 androidx.lifecycle:lifecycle-common-java8:2.8.7 androidx.lifecycle:lifecycle-common-jvm:2.8.7 androidx.lifecycle:lifecycle-common:2.8.7 @@ -98,7 +96,6 @@ androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 androidx.lifecycle:lifecycle-viewmodel:2.8.7 androidx.loader:loader:1.0.0 -androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 androidx.navigation:navigation-common-ktx:2.8.4 androidx.navigation:navigation-common:2.8.4 @@ -107,25 +104,11 @@ androidx.navigation:navigation-fragment-ktx:2.8.4 androidx.navigation:navigation-fragment:2.8.4 androidx.navigation:navigation-runtime-ktx:2.8.4 androidx.navigation:navigation-runtime:2.8.4 -androidx.print:print:1.0.0 -androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 -androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common-jvm:2.7.0-alpha12 -androidx.room:room-common:2.7.0-alpha12 -androidx.room:room-ktx:2.7.0-alpha12 -androidx.room:room-runtime-android:2.7.0-alpha12 -androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 androidx.slidingpanelayout:slidingpanelayout:1.2.0 -androidx.sqlite:sqlite-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 -androidx.sqlite:sqlite-bundled:2.5.0-alpha12 -androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 -androidx.sqlite:sqlite-framework:2.5.0-alpha12 -androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 @@ -161,36 +144,20 @@ com.google.accompanist:accompanist-permissions:0.34.0 com.google.android.datatransport:transport-api:2.2.1 com.google.android.datatransport:transport-backend-cct:2.3.3 com.google.android.datatransport:transport-runtime:2.2.6 -com.google.android.gms:play-services-ads-identifier:18.0.0 com.google.android.gms:play-services-base:18.5.0 com.google.android.gms:play-services-basement:18.4.0 com.google.android.gms:play-services-maps:18.2.0 -com.google.android.gms:play-services-measurement-api:22.1.2 -com.google.android.gms:play-services-measurement-base:22.1.2 -com.google.android.gms:play-services-measurement-impl:22.1.2 -com.google.android.gms:play-services-measurement-sdk-api:22.1.2 -com.google.android.gms:play-services-measurement-sdk:22.1.2 -com.google.android.gms:play-services-measurement:22.1.2 com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1 com.google.android.gms:play-services-oss-licenses:17.1.0 -com.google.android.gms:play-services-stats:17.0.2 com.google.android.gms:play-services-tasks:18.2.0 com.google.android.odml:image:1.0.0-beta1 com.google.auto.value:auto-value-annotations:1.6.3 com.google.code.findbugs:jsr305:3.0.2 com.google.errorprone:error_prone_annotations:2.28.0 -com.google.firebase:firebase-analytics-ktx:22.1.2 -com.google.firebase:firebase-analytics:22.1.2 -com.google.firebase:firebase-annotations:16.2.0 -com.google.firebase:firebase-bom:33.7.0 -com.google.firebase:firebase-common-ktx:21.0.0 -com.google.firebase:firebase-common:21.0.0 -com.google.firebase:firebase-components:18.0.0 +com.google.firebase:firebase-annotations:16.0.0 +com.google.firebase:firebase-components:16.1.0 com.google.firebase:firebase-encoders-json:17.1.0 -com.google.firebase:firebase-encoders:17.0.0 -com.google.firebase:firebase-installations-interop:17.1.1 -com.google.firebase:firebase-installations:18.0.0 -com.google.firebase:firebase-measurement-connector:19.0.0 +com.google.firebase:firebase-encoders:16.1.0 com.google.guava:failureaccess:1.0.2 com.google.guava:guava:33.3.1-android com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava @@ -344,7 +311,6 @@ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1 -org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.10.1 org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1 diff --git a/cmp-navigation/src/commonMain/kotlin/cmp/navigation/navigation/FeatureNavHost.kt b/cmp-navigation/src/commonMain/kotlin/cmp/navigation/navigation/FeatureNavHost.kt index f5270edf4..3d837318d 100644 --- a/cmp-navigation/src/commonMain/kotlin/cmp/navigation/navigation/FeatureNavHost.kt +++ b/cmp-navigation/src/commonMain/kotlin/cmp/navigation/navigation/FeatureNavHost.kt @@ -14,7 +14,6 @@ import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import cmp.navigation.ui.AppState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.model.entity.TransferSuccessDestination import org.mifos.mobile.core.model.enums.AccountType import org.mifos.mobile.core.model.enums.ChargeType @@ -119,7 +118,6 @@ internal fun FeatureNavHost( viewQrCode = { appState.navController.navigateToQrDisplayScreen(it) }, callHelpline = { callHelpline() }, reviewTransfer = { transferPayload, transferType, transferDestination -> - logger.e("$transferPayload $transferType") appState.navController.navigateToTransferProcessScreen( transferPayload, transferType, diff --git a/core/common/src/commonMain/kotlin/org/mifos/mobile/core/common/DateHelper.kt b/core/common/src/commonMain/kotlin/org/mifos/mobile/core/common/DateHelper.kt index 91818b331..7d45f9a18 100644 --- a/core/common/src/commonMain/kotlin/org/mifos/mobile/core/common/DateHelper.kt +++ b/core/common/src/commonMain/kotlin/org/mifos/mobile/core/common/DateHelper.kt @@ -22,7 +22,6 @@ import kotlinx.datetime.format.FormatStringsInDatetimeFormats import kotlinx.datetime.format.byUnicodePattern import kotlinx.datetime.minus import kotlinx.datetime.toLocalDateTime -import org.mifos.mobile.core.common.FileUtils.Companion.logger import kotlin.time.Duration.Companion.days @OptIn(FormatStringsInDatetimeFormats::class) @@ -56,7 +55,6 @@ object DateHelper { * @return date in the format day month year (ex 14 Apr 2016) */ fun getDateAsString(integersOfDate: List): String { - logger.d { "ktorClient $integersOfDate" } val stringBuilder = StringBuilder() stringBuilder.append(integersOfDate[2]) .append(' ') @@ -133,7 +131,6 @@ object DateHelper { val localDate = LocalDate(dateList[0], dateList[1], dateList[2]) localDate.atStartOfDayIn(TimeZone.UTC).toEpochMilliseconds() } catch (e: Exception) { - logger.d { "Error parsing date: ${e.message}" } null } } diff --git a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/TransferRepository.kt b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/TransferRepository.kt index 84a0b1ef0..d91a8e807 100644 --- a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/TransferRepository.kt +++ b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repository/TransferRepository.kt @@ -10,7 +10,6 @@ package org.mifos.mobile.core.data.repository import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.model.entity.TransferResponse import org.mifos.mobile.core.model.entity.payload.TransferPayload import org.mifos.mobile.core.model.enums.TransferType @@ -19,5 +18,5 @@ interface TransferRepository { suspend fun makeTransfer( payload: TransferPayload, transferType: TransferType?, - ): DataState + ): DataState } diff --git a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/LoanRepositoryImp.kt b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/LoanRepositoryImp.kt index 456e8f005..3131a62ce 100644 --- a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/LoanRepositoryImp.kt +++ b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/LoanRepositoryImp.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.withContext import org.mifos.mobile.core.common.DataState import org.mifos.mobile.core.common.asDataStateFlow import org.mifos.mobile.core.data.repository.LoanRepository +import org.mifos.mobile.core.data.util.extractErrorMessage import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithdraw import org.mifos.mobile.core.model.entity.templates.loans.LoanTemplate @@ -27,21 +28,6 @@ class LoanRepositoryImp( private val ioDispatcher: CoroutineDispatcher, ) : LoanRepository { -// override fun getLoanWithAssociations( -// associationType: String?, -// loanId: Long?, -// ): Flow> { -// return dataManager.loanAccountsListApi.getLoanWithAssociations(loanId!!, associationType) -// .map { response -> -// logger.d { "success Getting loan details from server repo $response" } -// DataState.Success(response) -// }.catch { exception -> -// logger.e { "Error fetching loan details: ${exception.message}" } -// DataState.Error(exception) -// } -// .flowOn(ioDispatcher) -// } - override fun getLoanWithAssociations( associationType: String?, loanId: Long?, @@ -60,13 +46,21 @@ class LoanRepositoryImp( loanId: Long?, loanWithdraw: LoanWithdraw?, ): DataState { - return try { - withContext(ioDispatcher) { - dataManager.loanAccountsListApi.withdrawLoanAccount(loanId!!, loanWithdraw) + return withContext(ioDispatcher) { + try { + val response = + dataManager.loanAccountsListApi.withdrawLoanAccount(loanId!!, loanWithdraw) + if (response.status.value != 200) { + val errorMessage = extractErrorMessage(response) + return@withContext DataState.Error( + Exception(errorMessage), + null, + ) + } + DataState.Success("withdraw successful") + } catch (e: Exception) { + DataState.Error(e, null) } - DataState.Success("withdraw successful") - } catch (e: Exception) { - DataState.Error(e, null) } } diff --git a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/SavingsAccountRepositoryImp.kt b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/SavingsAccountRepositoryImp.kt index 430814f9a..9044edda3 100644 --- a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/SavingsAccountRepositoryImp.kt +++ b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/SavingsAccountRepositoryImp.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.withContext import org.mifos.mobile.core.common.DataState import org.mifos.mobile.core.common.asDataStateFlow import org.mifos.mobile.core.data.repository.SavingsAccountRepository +import org.mifos.mobile.core.data.util.extractErrorMessage import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountUpdatePayload import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountWithdrawPayload @@ -36,8 +37,7 @@ class SavingsAccountRepositoryImp( return dataManager.savingAccountsListApi.getSavingsWithAssociations( accountId!!, associationType, - ) - .asDataStateFlow().flowOn(ioDispatcher) + ).asDataStateFlow().flowOn(ioDispatcher) } override fun getSavingAccountApplicationTemplate( @@ -50,13 +50,21 @@ class SavingsAccountRepositoryImp( override suspend fun submitSavingAccountApplication( payload: SavingsAccountApplicationPayload?, ): DataState { - return try { - withContext(ioDispatcher) { - dataManager.savingAccountsListApi.submitSavingAccountApplication(payload) + return withContext(ioDispatcher) { + try { + val response = + dataManager.savingAccountsListApi.submitSavingAccountApplication(payload) + if (response.status.value != 200) { + val errorMessage = extractErrorMessage(response) + return@withContext DataState.Error( + Exception(errorMessage), + null, + ) + } + DataState.Success("Submitted successfully") + } catch (e: Exception) { + DataState.Error(e, null) } - DataState.Success("Submitted successfully") - } catch (e: Exception) { - DataState.Error(e, null) } } @@ -64,13 +72,21 @@ class SavingsAccountRepositoryImp( accountId: Long?, payload: SavingsAccountUpdatePayload?, ): DataState { - return try { - withContext(ioDispatcher) { - dataManager.savingAccountsListApi.updateSavingsAccountUpdate(accountId!!, payload) + return withContext(ioDispatcher) { + try { + val response = + dataManager.savingAccountsListApi.updateSavingsAccountUpdate(accountId!!, payload) + if (response.status.value != 200) { + val errorMessage = extractErrorMessage(response) + return@withContext DataState.Error( + Exception(errorMessage), + null, + ) + } + DataState.Success("Updated successfully") + } catch (e: Exception) { + DataState.Error(e, null) } - DataState.Success("Updated successfully") - } catch (e: Exception) { - DataState.Error(e, null) } } @@ -78,13 +94,21 @@ class SavingsAccountRepositoryImp( accountId: String?, payload: SavingsAccountWithdrawPayload?, ): DataState { - return try { - withContext(ioDispatcher) { - dataManager.savingAccountsListApi.submitWithdrawSavingsAccount(accountId!!, payload) + return withContext(ioDispatcher) { + try { + val response = + dataManager.savingAccountsListApi.submitWithdrawSavingsAccount(accountId!!, payload) + if (response.status.value != 200) { + val errorMessage = extractErrorMessage(response) + return@withContext DataState.Error( + Exception(errorMessage), + null, + ) + } + DataState.Success("Submitted successfully") + } catch (e: Exception) { + DataState.Error(e, null) } - DataState.Success("Submitted successfully") - } catch (e: Exception) { - DataState.Error(e, null) } } diff --git a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/TransferRepositoryImp.kt b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/TransferRepositoryImp.kt index c24f14506..f4307f5f4 100644 --- a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/TransferRepositoryImp.kt +++ b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/repositoryImpl/TransferRepositoryImp.kt @@ -9,10 +9,13 @@ */ package org.mifos.mobile.core.data.repositoryImpl +import io.ktor.client.statement.bodyAsText import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext +import kotlinx.serialization.json.Json import org.mifos.mobile.core.common.DataState import org.mifos.mobile.core.data.repository.TransferRepository +import org.mifos.mobile.core.data.util.extractErrorMessage import org.mifos.mobile.core.model.entity.TransferResponse import org.mifos.mobile.core.model.entity.payload.TransferPayload import org.mifos.mobile.core.model.enums.TransferType @@ -25,18 +28,26 @@ class TransferRepositoryImp( override suspend fun makeTransfer( payload: TransferPayload, transferType: TransferType?, - ): DataState { - return try { - val response = withContext(ioDispatcher) { - when (transferType) { + ): DataState { + return withContext(ioDispatcher) { + try { + val response = when (transferType) { TransferType.SELF -> dataManager.savingAccountsListApi.makeTransfer(payload) else -> dataManager.thirdPartyTransferApi.makeTransfer(payload) } - } + if (response.status.value != 200) { + val errorMessage = extractErrorMessage(response) + return@withContext DataState.Error( + Exception(errorMessage), + null, + ) + } - DataState.Success(response) - } catch (e: Exception) { - DataState.Error(e) + val transferResponse = Json.decodeFromString(response.bodyAsText()) + DataState.Success(transferResponse.resourceId.toString()) + } catch (e: Exception) { + DataState.Error(e, null) + } } } } diff --git a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/util/ErrorHandling.kt b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/util/ErrorHandling.kt index febd88385..08efe904d 100644 --- a/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/util/ErrorHandling.kt +++ b/core/data/src/commonMain/kotlin/org/mifos/mobile/core/data/util/ErrorHandling.kt @@ -11,19 +11,8 @@ package org.mifos.mobile.core.data.util import io.ktor.client.statement.HttpResponse import io.ktor.client.statement.bodyAsText -import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json - -@Serializable -data class ErrorResponse( - val defaultUserMessage: String? = null, - val errors: List? = null, -) - -@Serializable -data class ErrorDetail( - val defaultUserMessage: String? = null, -) +import org.mifos.mobile.core.model.entity.mifoserror.MifosError /** * Generic function to extract error messages from API responses @@ -32,8 +21,8 @@ suspend fun extractErrorMessage(response: HttpResponse): String { val responseText = response.bodyAsText() return try { val json = Json { ignoreUnknownKeys = true } - val errorResponse = json.decodeFromString(responseText) - errorResponse.errors?.firstOrNull()?.defaultUserMessage + val errorResponse = json.decodeFromString(responseText) + errorResponse.errors.firstOrNull()?.defaultUserMessage ?: errorResponse.defaultUserMessage ?: "Unknown error" } catch (e: Exception) { diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt index 96b754b66..474496605 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt @@ -20,6 +20,6 @@ data class LoanWithdraw( val note: String? = null, - val dateFormat: String = "dd-MM-yyyy", - val locale: String = "en", + val dateFormat: String? = null, + val locale: String? = null, ) : Parcelable diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt index f4a2418f2..ed87f7c17 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt @@ -9,14 +9,13 @@ */ package org.mifos.mobile.core.model.entity.accounts.savings -import org.mifos.mobile.core.model.Parcelable -import org.mifos.mobile.core.model.Parcelize +import kotlinx.serialization.Serializable -@Parcelize +@Serializable data class SavingsAccountUpdatePayload( val clientId: Long? = 0, val productId: Long? = 0, -) : Parcelable +) diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt index 29f15fded..4580e62f7 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt @@ -16,8 +16,8 @@ import org.mifos.mobile.core.model.Parcelize @Serializable @Parcelize data class SavingsAccountWithdrawPayload( - val locale: String = "en", - val dateFormat: String = "dd MMMM yyyy", + val locale: String? = null, + val dateFormat: String? = null, val withdrawnOnDate: String? = null, val note: String? = null, ) : Parcelable diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt index f909aa633..668b8ddf9 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt @@ -9,13 +9,12 @@ */ package org.mifos.mobile.core.model.entity.mifoserror -import org.mifos.mobile.core.model.Parcelable -import org.mifos.mobile.core.model.Parcelize +import kotlinx.serialization.Serializable -@Parcelize +@Serializable data class Errors( val developerMessage: String? = null, val defaultUserMessage: String? = null, val userMessageGlobalisationCode: String? = null, val parameterName: String? = null, -) : Parcelable +) diff --git a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt index 3b24376ca..2f57c616b 100644 --- a/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt +++ b/core/model/src/commonMain/kotlin/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt @@ -9,14 +9,13 @@ */ package org.mifos.mobile.core.model.entity.mifoserror -import org.mifos.mobile.core.model.Parcelable -import org.mifos.mobile.core.model.Parcelize +import kotlinx.serialization.Serializable -@Parcelize +@Serializable data class MifosError( val developerMessage: String? = null, val httpStatusCode: String? = null, val defaultUserMessage: String? = null, val userMessageGlobalisationCode: String? = null, val errors: List = emptyList(), -) : Parcelable +) diff --git a/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/SavingAccountsListService.kt b/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/SavingAccountsListService.kt index 3d519bc9a..926b18b75 100644 --- a/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/SavingAccountsListService.kt +++ b/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/SavingAccountsListService.kt @@ -17,7 +17,6 @@ import de.jensklingenberg.ktorfit.http.Path import de.jensklingenberg.ktorfit.http.Query import io.ktor.client.statement.HttpResponse import kotlinx.coroutines.flow.Flow -import org.mifos.mobile.core.model.entity.TransferResponse import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountUpdatePayload import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountWithdrawPayload @@ -41,7 +40,7 @@ interface SavingAccountsListService { ): Flow @POST(ApiEndPoints.ACCOUNT_TRANSFER) - suspend fun makeTransfer(@Body transferPayload: TransferPayload?): TransferResponse + suspend fun makeTransfer(@Body transferPayload: TransferPayload?): HttpResponse @GET(ApiEndPoints.SAVINGS_ACCOUNTS + "/template") fun getSavingsAccountApplicationTemplate( diff --git a/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt b/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt index e04a4d5b6..8d0a477cc 100644 --- a/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt +++ b/core/network/src/commonMain/kotlin/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt @@ -12,8 +12,8 @@ package org.mifos.mobile.core.network.services import de.jensklingenberg.ktorfit.http.Body import de.jensklingenberg.ktorfit.http.GET import de.jensklingenberg.ktorfit.http.POST +import io.ktor.client.statement.HttpResponse import kotlinx.coroutines.flow.Flow -import org.mifos.mobile.core.model.entity.TransferResponse import org.mifos.mobile.core.model.entity.payload.TransferPayload import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate import org.mifos.mobile.core.network.utils.ApiEndPoints @@ -23,5 +23,5 @@ interface ThirdPartyTransferService { fun accountTransferTemplate(): Flow @POST(ApiEndPoints.ACCOUNT_TRANSFER + "?type=tpt") - suspend fun makeTransfer(@Body transferPayload: TransferPayload?): TransferResponse + suspend fun makeTransfer(@Body transferPayload: TransferPayload?): HttpResponse } diff --git a/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/login/LoginViewModel.kt b/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/login/LoginViewModel.kt index 514d286eb..8c61e6037 100644 --- a/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/login/LoginViewModel.kt +++ b/feature/auth/src/commonMain/kotlin/org/mifos/mobile/feature/auth/login/LoginViewModel.kt @@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.ClientRepository import org.mifos.mobile.core.data.repository.UserAuthRepository import org.mifos.mobile.core.datastore.UserPreferencesRepository @@ -103,9 +102,7 @@ class LoginViewModel( it.copy(dialogState = null) } val user = action.loginResult.data - logger.d { "KtorClient getting before mapping $user" } val userData = user.toUserData() - logger.d { "KtorClient getting after mapping $userData" } viewModelScope.launch { userPreferencesRepositoryImpl.updateUser(userData) } diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationViewModel.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationViewModel.kt index 7e66fbf29..c317824f1 100644 --- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationViewModel.kt +++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationViewModel.kt @@ -32,7 +32,6 @@ import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.getString import org.mifos.mobile.core.common.Constants.BENEFICIARY_STATE import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.BeneficiaryRepository import org.mifos.mobile.core.data.util.NetworkMonitor import org.mifos.mobile.core.model.IgnoredOnParcel @@ -130,10 +129,6 @@ internal class BeneficiaryApplicationViewModel( beneficiaryRepositoryImp.beneficiaryList(), beneficiaryRepositoryImp.beneficiaryTemplate(), ) { beneficiaryList, beneficiaryTemplate -> - logger.d { - "KtorClient getting in function ${beneficiaryList.data} and beneficiary " + - "${beneficiaryTemplate.data}" - } updateStateFromResults(beneficiaryList, beneficiaryTemplate) }.catch { error -> updateState { @@ -159,7 +154,6 @@ internal class BeneficiaryApplicationViewModel( val error = (beneficiaryList as? DataState.Error)?.exception?.message ?: (beneficiaryTemplate as? DataState.Error)?.exception?.message ?: "An error occurred" - logger.d { "KtorClient error $error" } val errorMessage = "An error occurred" updateState { it.copy(dialogState = BeneficiaryApplicationState.DialogState.Error(errorMessage)) } } diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListViewModel.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListViewModel.kt index 2c17f8862..f848aa49c 100644 --- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListViewModel.kt +++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListViewModel.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.BeneficiaryRepository import org.mifos.mobile.core.data.util.NetworkMonitor import org.mifos.mobile.core.model.IgnoredOnParcel @@ -51,7 +50,6 @@ internal class BeneficiaryListViewModel( } viewModelScope.launch { beneficiaryRepositoryImp.beneficiaryList().catch { e -> - logger.d { "KtorClient in catch block ${e.message}" } updateState { it.copy( dialogState = BeneficiaryListState.DialogState.Error( diff --git a/feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/viewmodel/ClientChargeViewModel.kt b/feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/viewmodel/ClientChargeViewModel.kt index 03f567edf..d8eb85a23 100644 --- a/feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/viewmodel/ClientChargeViewModel.kt +++ b/feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/viewmodel/ClientChargeViewModel.kt @@ -34,7 +34,6 @@ import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.getString import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.ClientChargeRepository import org.mifos.mobile.core.data.util.NetworkMonitor import org.mifos.mobile.core.datastore.UserPreferencesRepository @@ -185,7 +184,6 @@ internal class ClientChargeViewModel( } private fun processLoanOrSavingsCharges(result: DataState>) { - logger.d { "KtorClient getting in function ${result.data}" } updateState { when (result) { DataState.Loading -> it.copy(chargeDialog = ClientChargeState.ChargeDialogState.Loading) diff --git a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/screen/LoanAccountScreenContent.kt b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/screen/LoanAccountScreenContent.kt index 42283775a..303c89001 100644 --- a/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/screen/LoanAccountScreenContent.kt +++ b/feature/loan-account/src/commonMain/kotlin/org/mifos/mobile/feature/loanaccount/screen/LoanAccountScreenContent.kt @@ -69,7 +69,7 @@ private fun LoanAccountListItem( loanAccount.status?.active == true && loanAccount.inArrears == true -> { Triple( first = MaterialTheme.colorScheme.error, - second = stringResource(resource = Res.string.feature_account_in_arrears) + + second = stringResource(resource = Res.string.feature_account_in_arrears) + " " + ( loanAccount.timeline?.actualDisbursementDate?.let { DateHelper.getDateAsString(it) @@ -82,7 +82,7 @@ private fun LoanAccountListItem( loanAccount.status?.active == true -> { Triple( first = MaterialTheme.colorScheme.primary, - second = stringResource(resource = Res.string.feature_account_active) + + second = stringResource(resource = Res.string.feature_account_active) + " " + ( loanAccount.timeline?.actualDisbursementDate?.let { DateHelper.getDateAsString(it) @@ -95,7 +95,7 @@ private fun LoanAccountListItem( loanAccount.status?.waitingForDisbursal == true -> { Triple( first = MaterialTheme.colorScheme.secondary, - second = stringResource(resource = Res.string.feature_account_disburse) + + second = stringResource(resource = Res.string.feature_account_disburse) + " " + ( loanAccount.timeline?.approvedOnDate?.let { DateHelper.getDateAsString( @@ -111,7 +111,7 @@ private fun LoanAccountListItem( loanAccount.status?.pendingApproval == true -> { Triple( first = MaterialTheme.colorScheme.tertiary, - second = stringResource(resource = Res.string.feature_account_approval_pending) + + second = stringResource(resource = Res.string.feature_account_approval_pending) + " " + ( loanAccount.timeline?.submittedOnDate?.let { DateHelper.getDateAsString( @@ -127,7 +127,7 @@ private fun LoanAccountListItem( loanAccount.status?.overpaid == true -> { Triple( first = MaterialTheme.colorScheme.tertiaryContainer, - second = stringResource(resource = Res.string.feature_account_overpaid) + + second = stringResource(resource = Res.string.feature_account_overpaid) + " " + ( loanAccount.timeline?.actualDisbursementDate?.let { DateHelper.getDateAsString(it) @@ -140,7 +140,7 @@ private fun LoanAccountListItem( loanAccount.status?.closed == true -> { Triple( first = MaterialTheme.colorScheme.onSurface, - second = stringResource(resource = Res.string.feature_account_closed) + + second = stringResource(resource = Res.string.feature_account_closed) + " " + ( loanAccount.timeline?.closedOnDate?.let { DateHelper.getDateAsString( @@ -156,7 +156,7 @@ private fun LoanAccountListItem( else -> { Triple( first = MaterialTheme.colorScheme.outline, - second = stringResource(resource = Res.string.feature_account_withdrawn) + + second = stringResource(resource = Res.string.feature_account_withdrawn) + " " + ( loanAccount.timeline?.withdrawnOnDate?.let { DateHelper.getDateAsString( diff --git a/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccount/LoanAccountsDetailViewModel.kt b/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccount/LoanAccountsDetailViewModel.kt index 340d1b6dd..60786b781 100644 --- a/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccount/LoanAccountsDetailViewModel.kt +++ b/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccount/LoanAccountsDetailViewModel.kt @@ -22,7 +22,6 @@ import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.Constants.LOAN_ID import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.LoanRepository import org.mifos.mobile.core.data.util.NetworkMonitor import org.mifos.mobile.core.datastore.UserPreferencesRepository @@ -159,7 +158,6 @@ internal class LoanAccountsDetailViewModel( updateState { currentState -> when (result) { is DataState.Error -> { - logger.e { "KtorClient error in ViewModel: ${result.exception.message}" } currentState.copy( dialogState = LoanAccountsState.DialogState.Error( result.exception.message ?: "An error occurred", diff --git a/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawScreen.kt b/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawScreen.kt index 1ca9fb442..af138ca51 100644 --- a/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawScreen.kt +++ b/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawScreen.kt @@ -13,12 +13,11 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -39,8 +38,8 @@ import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.ui.tooling.preview.Preview import org.koin.compose.viewmodel.koinViewModel import org.mifos.mobile.core.designsystem.component.MifosButton +import org.mifos.mobile.core.designsystem.component.MifosScaffold import org.mifos.mobile.core.designsystem.component.MifosTextField -import org.mifos.mobile.core.designsystem.component.MifosTopAppBar import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.ui.component.MifosErrorComponent @@ -76,6 +75,7 @@ internal fun LoanAccountWithdrawScreen( { viewModel.trySendAction(it) } }, modifier = modifier, + snackbarHostState = snackbarHostState, ) } @@ -103,29 +103,26 @@ private fun LoanAccountWithDrawDialog( private fun LoanAccountWithdrawScreen( state: LoanAccountWithdrawState, onAction: (LoanAccountWithdrawAction) -> Unit, + snackbarHostState: SnackbarHostState, modifier: Modifier = Modifier, ) { - Column( - modifier = modifier - .fillMaxSize() - .background(MaterialTheme.colorScheme.background), - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { - MifosTopAppBar( - backPress = { onAction(LoanAccountWithdrawAction.BackPress) }, - topBarTitle = stringResource(Res.string.withdraw_loan), - ) + MifosScaffold( + backPress = { onAction(LoanAccountWithdrawAction.BackPress) }, + topBarTitle = stringResource(Res.string.withdraw_loan), + snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, + content = { + Box(modifier = Modifier.padding(it)) { + Column(modifier = modifier.padding(16.dp)) { + LoanAccountWithdrawContent( + loanWithAssociations = state.loanWithAssociations, + state = state, + onAction = onAction, + ) + } + } + }, + ) - Spacer(modifier = Modifier.height(8.dp)) - - Box(modifier = Modifier.weight(1f).padding(16.dp)) { - LoanAccountWithdrawContent( - loanWithAssociations = state.loanWithAssociations, - state = state, - onAction = onAction, - ) - } - } LoanAccountWithDrawDialog( dialogState = state.dialogState, ) @@ -182,6 +179,7 @@ private fun LoanAccountWithdrawPreview() { state = LoanAccountWithdrawState(dialogState = null), modifier = Modifier, onAction = {}, + snackbarHostState = SnackbarHostState(), ) } } diff --git a/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawViewModel.kt b/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawViewModel.kt index 14f3580a7..85467f85f 100644 --- a/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawViewModel.kt +++ b/feature/loan/src/commonMain/kotlin/org/mifos/mobile/feature/loan/loanAccountWithdraw/LoanAccountWithdrawViewModel.kt @@ -11,6 +11,7 @@ package org.mifos.mobile.feature.loan.loanAccountWithdraw import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -75,7 +76,7 @@ internal class LoanAccountWithdrawViewModel( Clock.System.now().toEpochMilliseconds(), ), note = state.loanReason, - dateFormat = "dd-MM-yyyy", + dateFormat = DateHelper.SHORT_MONTH, locale = "en", ) updateState { @@ -100,12 +101,18 @@ internal class LoanAccountWithdrawViewModel( it.copy(dialogState = null) } sendEvent(LoanAccountWithdrawEvent.ShowToast(successMessage)) + delay(1500) sendEvent(LoanAccountWithdrawEvent.NavigateBack) } is DataState.Error -> { updateState { - it.copy(dialogState = LoanAccountWithdrawState.DialogState.Error(errorMessage)) + it.copy(dialogState = null) } + sendEvent( + LoanAccountWithdrawEvent.ShowToast( + response.exception.message ?: errorMessage, + ), + ) } } } diff --git a/feature/qr/src/commonMain/kotlin/org/mifos/mobile/feature/qr/qrCodeDisplay/QrCodeDisplayViewModel.kt b/feature/qr/src/commonMain/kotlin/org/mifos/mobile/feature/qr/qrCodeDisplay/QrCodeDisplayViewModel.kt index 39c5bf60f..550ed2292 100644 --- a/feature/qr/src/commonMain/kotlin/org/mifos/mobile/feature/qr/qrCodeDisplay/QrCodeDisplayViewModel.kt +++ b/feature/qr/src/commonMain/kotlin/org/mifos/mobile/feature/qr/qrCodeDisplay/QrCodeDisplayViewModel.kt @@ -30,7 +30,6 @@ import kotlinx.coroutines.launch import mifos_mobile.feature.qr.generated.resources.Res import mifos_mobile.feature.qr.generated.resources.choose_option import org.jetbrains.compose.resources.getString -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.model.IgnoredOnParcel import org.mifos.mobile.core.model.Parcelable import org.mifos.mobile.core.model.Parcelize @@ -76,7 +75,6 @@ internal class QrCodeDisplayViewModel( QrCodeDisplayAction.DismissDialog -> setDialogState(null) is QrCodeDisplayAction.ShareQrCode -> { viewModelScope.launch { - logger.d { "Sharing QR Code: ${action.option}, size: ${action.qrBitmap.size} bytes" } shareImage( action.option, action.qrBitmap, diff --git a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/screen/SavingsAccountScreenContent.kt b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/screen/SavingsAccountScreenContent.kt index 2af347eb8..f37ca1f04 100644 --- a/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/screen/SavingsAccountScreenContent.kt +++ b/feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/screen/SavingsAccountScreenContent.kt @@ -24,7 +24,6 @@ import mifos_mobile.feature.savings_account.generated.resources.feature_account_ import mifos_mobile.feature.savings_account.generated.resources.feature_account_approved import mifos_mobile.feature.savings_account.generated.resources.feature_account_closed import mifos_mobile.feature.savings_account.generated.resources.feature_account_matured -import mifos_mobile.feature.savings_account.generated.resources.feature_account_string_and_string import mifos_mobile.feature.savings_account.generated.resources.feature_account_submitted import org.jetbrains.compose.resources.stringResource import org.mifos.mobile.core.common.CurrencyFormatter @@ -69,7 +68,7 @@ private fun SavingsAccountListItem( savingAccount.status?.active == true -> { Triple( first = MaterialTheme.colorScheme.primary, - second = stringResource(Res.string.feature_account_active) + + second = stringResource(Res.string.feature_account_active) + " " + ( savingAccount.lastActiveTransactionDate?.let { DateHelper.getDateAsString( @@ -84,7 +83,7 @@ private fun SavingsAccountListItem( savingAccount.status?.approved == true -> { Triple( first = MaterialTheme.colorScheme.secondaryContainer, - second = stringResource(Res.string.feature_account_approved) + + second = stringResource(Res.string.feature_account_approved) + " " + ( savingAccount.timeLine?.approvedOnDate?.let { DateHelper.getDateAsString( @@ -99,7 +98,7 @@ private fun SavingsAccountListItem( savingAccount.status?.submittedAndPendingApproval == true -> { Triple( first = MaterialTheme.colorScheme.tertiaryContainer, - second = stringResource(Res.string.feature_account_submitted) + + second = stringResource(Res.string.feature_account_submitted) + " " + ( savingAccount.timeLine?.submittedOnDate?.let { DateHelper.getDateAsString( @@ -114,7 +113,7 @@ private fun SavingsAccountListItem( savingAccount.status?.matured == true -> { Triple( first = MaterialTheme.colorScheme.errorContainer, - second = stringResource(Res.string.feature_account_matured) + + second = stringResource(Res.string.feature_account_matured) + " " + ( savingAccount.lastActiveTransactionDate?.let { DateHelper.getDateAsString( @@ -129,38 +128,29 @@ private fun SavingsAccountListItem( else -> { Triple( first = MaterialTheme.colorScheme.surfaceVariant, - second = stringResource(Res.string.feature_account_closed) + ( - savingAccount.timeLine?.closedOnDate?.let { - DateHelper.getDateAsString( - it, - ) - } - ?: "" - ), + second = stringResource(Res.string.feature_account_closed) + " " + + ( + savingAccount.timeLine?.closedOnDate?.let { + DateHelper.getDateAsString( + it, + ) + } ?: "" + ), third = null, ) } } - val currencySymbolOrCode = - savingAccount.currency?.displaySymbol ?: savingAccount.currency?.code ?: "" - val formattedBalance = CurrencyFormatter.format( balance = savingAccount.accountBalance, currencyCode = savingAccount.currency?.code, maximumFractionDigits = 2, ) - val amountAndCurrency = stringResource( - Res.string.feature_account_string_and_string, - formattedBalance, - currencySymbolOrCode, - ) - AccountCard( savingAccount = savingAccount, statusString = statusDescription, - balance = amountAndCurrency, + balance = formattedBalance, indicatorColor = indicatorColor, textColor = balanceTextColor, onClick = { diff --git a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationScreen.kt b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationScreen.kt index b9dc12dbd..4e6b589dc 100644 --- a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationScreen.kt +++ b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -25,8 +26,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.launch import mifos_mobile.feature.savings.generated.resources.Res import mifos_mobile.feature.savings.generated.resources.apply_savings_account -import mifos_mobile.feature.savings.generated.resources.new_saving_account_created_successfully -import mifos_mobile.feature.savings.generated.resources.saving_account_updated_successfully import mifos_mobile.feature.savings.generated.resources.update_savings_account import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource @@ -44,13 +43,30 @@ internal fun SavingsAccountApplicationScreen( viewModel: SavingsAccountApplicationViewModel = koinViewModel(), ) { val uiState by viewModel.savingsAccountApplicationUiState.collectAsStateWithLifecycle() + val snackbarHostState = remember { SnackbarHostState() } + val scope = rememberCoroutineScope() SavingsAccountApplicationScreen( uiState = uiState, navigateBack = navigateBack, submit = viewModel::onSubmit, + onRetry = viewModel::onRetry, modifier = modifier, + snackbarHostState = snackbarHostState, ) + + LaunchedEffect(Unit) { + viewModel.eventFlow.collect { event -> + when (event) { + is UiEvent.ShowSnackbar -> { + scope.launch { + snackbarHostState.showSnackbar(event.message) + } + } + UiEvent.NavigateBack -> navigateBack.invoke() + } + } + } } @Composable @@ -58,12 +74,13 @@ private fun SavingsAccountApplicationScreen( uiState: SavingsAccountApplicationUiState, navigateBack: () -> Unit, submit: (Int, Int, showToast: (StringResource) -> Unit) -> Unit, + onRetry: () -> Unit, + snackbarHostState: SnackbarHostState, modifier: Modifier = Modifier, savingsWithAssociations: SavingsWithAssociations? = null, ) { var topBarTitleText by rememberSaveable { mutableStateOf("") } val scope = rememberCoroutineScope() - val snackbarHostState = remember { SnackbarHostState() } MifosScaffold( backPress = navigateBack, @@ -74,7 +91,9 @@ private fun SavingsAccountApplicationScreen( Box(modifier = Modifier.padding(it)) { when (uiState) { is SavingsAccountApplicationUiState.Error -> { - MifosErrorComponent() + MifosErrorComponent( + onRetry = onRetry, + ) } is SavingsAccountApplicationUiState.Loading -> { @@ -94,20 +113,6 @@ private fun SavingsAccountApplicationScreen( savingsAccountTemplate = uiState.template, ) } - - is SavingsAccountApplicationUiState.Success -> { - val message = when (uiState.requestType) { - SavingsAccountState.CREATE -> - stringResource(Res.string.new_saving_account_created_successfully) - else -> - stringResource(Res.string.saving_account_updated_successfully) - } - - scope.launch { - snackbarHostState.showSnackbar(message) - } - navigateBack.invoke() - } } } }, diff --git a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationViewModel.kt b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationViewModel.kt index 6907330e3..b6d8465aa 100644 --- a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationViewModel.kt +++ b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountApplication/SavingsAccountApplicationViewModel.kt @@ -13,23 +13,24 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import mifos_mobile.feature.savings.generated.resources.Res +import mifos_mobile.feature.savings.generated.resources.new_saving_account_created_successfully +import mifos_mobile.feature.savings.generated.resources.saving_account_updated_successfully import mifos_mobile.feature.savings.generated.resources.select_product_id import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.getString import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.DataState import org.mifos.mobile.core.common.DateHelper -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.SavingsAccountRepository import org.mifos.mobile.core.datastore.UserPreferencesDataSource import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload @@ -59,30 +60,43 @@ internal class SavingsAccountApplicationViewModel( MutableStateFlow(Loading) val savingsAccountApplicationUiState = _savingsAccountApplicationUiState.asStateFlow() + private val _savingsWithAssociations = MutableStateFlow(null) + private val savingsWithAssociations = _savingsWithAssociations.asStateFlow() + init { + observeSavingsWithAssociations() loadSavingsAccountApplicationTemplate() } + private val _eventFlow = MutableSharedFlow() + val eventFlow = _eventFlow.asSharedFlow() + @OptIn(ExperimentalCoroutinesApi::class) - private val savingsWithAssociations: StateFlow = savingsId - .flatMapLatest { id -> - savingsAccountRepositoryImp.getSavingsWithAssociations(id, Constants.TRANSACTIONS) - .map { dataState -> + private fun observeSavingsWithAssociations() { + viewModelScope.launch { + savingsId + .flatMapLatest { id -> + savingsAccountRepositoryImp.getSavingsWithAssociations(id, Constants.TRANSACTIONS) + } + .collect { dataState -> when (dataState) { - is DataState.Success -> dataState.data - else -> null + is DataState.Success -> { + _savingsWithAssociations.value = dataState.data + } + is DataState.Loading -> { + _savingsAccountApplicationUiState.value = Loading + } + is DataState.Error -> { + _savingsAccountApplicationUiState.value = + SavingsAccountApplicationUiState.Error(dataState.exception.message) + } } } } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5000), - initialValue = null, - ) + } private fun loadSavingsAccountApplicationTemplate() { viewModelScope.launch { - logger.d("_savingsAccountApplicationUiState: $_savingsAccountApplicationUiState") _savingsAccountApplicationUiState.value = Loading val clientIdValue = clientId.firstOrNull() if (clientIdValue == null) { @@ -99,15 +113,21 @@ internal class SavingsAccountApplicationViewModel( ) } .collect { response -> - if (response.data != null) { - _savingsAccountApplicationUiState.value = - SavingsAccountApplicationUiState.ShowUserInterface( - response.data!!, - savingsAccountState, - ) - } else { - _savingsAccountApplicationUiState.value = - SavingsAccountApplicationUiState.Error("Failed to load template. Data is null.") + when (response) { + is DataState.Error -> { + _savingsAccountApplicationUiState.value = + SavingsAccountApplicationUiState.Error("Failed to load template. Data is null.") + } + DataState.Loading -> { + Loading + } + is DataState.Success -> { + _savingsAccountApplicationUiState.value = + SavingsAccountApplicationUiState.ShowUserInterface( + response.data, + savingsAccountState, + ) + } } } } @@ -122,10 +142,16 @@ internal class SavingsAccountApplicationViewModel( _savingsAccountApplicationUiState.value = SavingsAccountApplicationUiState.Error(response.message) } - DataState.Loading -> TODO() + DataState.Loading -> Loading is DataState.Success -> { - _savingsAccountApplicationUiState.value = - SavingsAccountApplicationUiState.Success(savingsAccountState) + val messageRes = when (savingsAccountState) { + SavingsAccountState.CREATE -> Res.string.new_saving_account_created_successfully + else -> Res.string.saving_account_updated_successfully + } + + _eventFlow.emit(UiEvent.ShowSnackbar(getString(messageRes))) + delay(1500) + _eventFlow.emit(UiEvent.NavigateBack) } } } @@ -133,20 +159,28 @@ internal class SavingsAccountApplicationViewModel( private fun updateSavingsAccount(accountId: Long?, payload: SavingsAccountUpdatePayload?) { viewModelScope.launch { - _savingsAccountApplicationUiState.value = Loading + if (accountId == -1L) { + _eventFlow.emit(UiEvent.ShowSnackbar(getString(Res.string.select_product_id))) + return@launch + } val response = savingsAccountRepositoryImp.updateSavingsAccount(accountId, payload) when (response) { is DataState.Error -> { - _savingsAccountApplicationUiState.value = - SavingsAccountApplicationUiState.Error(response.message) + _eventFlow.emit(UiEvent.ShowSnackbar(response.exception.message ?: "Unknown error")) } DataState.Loading -> { Loading } is DataState.Success -> { - _savingsAccountApplicationUiState.value = - SavingsAccountApplicationUiState.Success(savingsAccountState) + val messageRes = when (savingsAccountState) { + SavingsAccountState.CREATE -> Res.string.new_saving_account_created_successfully + else -> Res.string.saving_account_updated_successfully + } + + _eventFlow.emit(UiEvent.ShowSnackbar(getString(messageRes))) + delay(1500) + _eventFlow.emit(UiEvent.NavigateBack) } } } @@ -189,10 +223,14 @@ internal class SavingsAccountApplicationViewModel( internal sealed class SavingsAccountApplicationUiState { data object Loading : SavingsAccountApplicationUiState() data class Error(val errorMessage: String?) : SavingsAccountApplicationUiState() - data class Success(val requestType: SavingsAccountState) : SavingsAccountApplicationUiState() data class ShowUserInterface( val template: SavingsAccountTemplate, val requestType: SavingsAccountState, ) : SavingsAccountApplicationUiState() } + +internal sealed class UiEvent { + data class ShowSnackbar(val message: String) : UiEvent() + data object NavigateBack : UiEvent() +} diff --git a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountTransaction/SavingAccountTransactionContent.kt b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountTransaction/SavingAccountTransactionContent.kt index 7fbcd0286..7811dd549 100644 --- a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountTransaction/SavingAccountTransactionContent.kt +++ b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountTransaction/SavingAccountTransactionContent.kt @@ -35,7 +35,6 @@ import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import org.mifos.mobile.core.common.CurrencyFormatter import org.mifos.mobile.core.common.DateHelper -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.model.entity.accounts.savings.Transactions @Composable @@ -80,7 +79,6 @@ private fun SavingsAccountTransactionListItem( transaction: Transactions, modifier: Modifier = Modifier, ) { - logger.d { "ktorClient getting transactions in Ui $transaction" } Row( modifier = modifier .fillMaxWidth() diff --git a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawScreen.kt b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawScreen.kt index 89cedc7e9..0fedfffc6 100644 --- a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawScreen.kt +++ b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawScreen.kt @@ -15,10 +15,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.SnackbarResult import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -36,8 +34,8 @@ import mifos_mobile.feature.savings.generated.resources.account_number import mifos_mobile.feature.savings.generated.resources.client_name import mifos_mobile.feature.savings.generated.resources.error_validation_blank import mifos_mobile.feature.savings.generated.resources.remark -import mifos_mobile.feature.savings.generated.resources.savings_account_withdraw_successful import mifos_mobile.feature.savings.generated.resources.withdraw_savings_account +import mifos_mobile.feature.savings.generated.resources.withdrawal import mifos_mobile.feature.savings.generated.resources.withdrawal_date import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel @@ -46,8 +44,10 @@ import org.mifos.mobile.core.designsystem.component.MifosButton import org.mifos.mobile.core.designsystem.component.MifosOutlinedTextField import org.mifos.mobile.core.designsystem.component.MifosScaffold import org.mifos.mobile.core.designsystem.component.MifosTextFieldConfig +import org.mifos.mobile.core.designsystem.icon.MifosIcons import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations -import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay +import org.mifos.mobile.core.ui.component.EmptyDataView +import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.MifosTitleDescSingleLineEqual @Composable @@ -58,25 +58,20 @@ internal fun SavingsAccountWithdrawScreen( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() val savingsWithAssociations by viewModel.savingsWithAssociations.collectAsStateWithLifecycle() - - val message = stringResource(Res.string.savings_account_withdraw_successful) val snackbarHostState = remember { SnackbarHostState() } val scope = rememberCoroutineScope() - LaunchedEffect(uiState) { - if (uiState is SavingsAccountWithdrawUiState.Success) { - scope.launch { - val result = snackbarHostState.showSnackbar( - message = message, - duration = SnackbarDuration.Short, - ) - if (result == SnackbarResult.Dismissed || result == SnackbarResult.ActionPerformed) { - navigateBack(true) + LaunchedEffect(Unit) { + viewModel.eventFlow.collect { event -> + when (event) { + is SavingsAccountWithdrawUiEvent.NavigateBack -> { + navigateBack.invoke(event.withDrawSuccess) + } + is SavingsAccountWithdrawUiEvent.ShowSnackbar -> { + scope.launch { + snackbarHostState.showSnackbar(event.message) + } } - } - } else if (uiState is SavingsAccountWithdrawUiState.Error) { - scope.launch { - (uiState as SavingsAccountWithdrawUiState.Error).message?.let { snackbarHostState.showSnackbar(it) } } } } @@ -84,7 +79,7 @@ internal fun SavingsAccountWithdrawScreen( SavingsAccountWithdrawScreen( uiState = uiState, snackbarHostState = snackbarHostState, - savingsWithAssociations = savingsWithAssociations?.data, + savingsWithAssociations = savingsWithAssociations, onBackPress = navigateBack, withdraw = viewModel::submitWithdrawSavingsAccount, modifier = modifier, @@ -105,17 +100,29 @@ private fun SavingsAccountWithdrawScreen( backPress = { onBackPress(false) }, topBarTitle = stringResource(Res.string.withdraw_savings_account), snackbarHost = { SnackbarHost(snackbarHostState) }, - content = { - padding -> + content = { padding -> Box(modifier = Modifier.padding(padding)) { - SavingsAccountWithdrawContent( - savingsWithAssociations = savingsWithAssociations, - withdraw = withdraw, - ) + when (uiState) { + is SavingsAccountWithdrawUiState.Error -> EmptyDataView( + icon = MifosIcons.Error, + error = Res.string.withdrawal, + modifier = Modifier.fillMaxSize(), + ) + SavingsAccountWithdrawUiState.Loading -> MifosProgressIndicator() + SavingsAccountWithdrawUiState.Ready, + SavingsAccountWithdrawUiState.Success, + -> { + SavingsAccountWithdrawContent( + savingsWithAssociations = savingsWithAssociations, + withdraw = withdraw, + ) + } - if (uiState is SavingsAccountWithdrawUiState.Loading) { - MifosProgressIndicatorOverlay() + is SavingsAccountWithdrawUiState.Message -> SavingsAccountWithdrawContent( + savingsWithAssociations = savingsWithAssociations, + withdraw = withdraw, + ) } } }, diff --git a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawViewModel.kt b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawViewModel.kt index 5b11542eb..9629a69ef 100644 --- a/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawViewModel.kt +++ b/feature/savings/src/commonMain/kotlin/org/mifos/mobile/feature/savings/savingsAccountWithdraw/SavingsAccountWithdrawViewModel.kt @@ -12,82 +12,100 @@ package org.mifos.mobile.feature.savings.savingsAccountWithdraw import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch +import mifos_mobile.feature.savings.generated.resources.Res +import mifos_mobile.feature.savings.generated.resources.savings_account_withdraw_successful +import org.jetbrains.compose.resources.getString import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.DataState import org.mifos.mobile.core.common.DateHelper import org.mifos.mobile.core.data.repository.SavingsAccountRepository import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountWithdrawPayload -import org.mifos.mobile.feature.savings.savingsAccountWithdraw.SavingsAccountWithdrawUiState.WithdrawUiReady +import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations internal class SavingsAccountWithdrawViewModel( private val savingsAccountRepositoryImp: SavingsAccountRepository, savedStateHandle: SavedStateHandle, ) : ViewModel() { - private val mUiState = MutableStateFlow(WithdrawUiReady) + private val mUiState = MutableStateFlow(SavingsAccountWithdrawUiState.Loading) val uiState = mUiState.asStateFlow() - private val mSnackbar = MutableStateFlow("") - val snackbarMessage = mSnackbar.asStateFlow() + private val savingsId: Long = savedStateHandle[Constants.SAVINGS_ID] ?: -1L - private val savingsId: StateFlow = savedStateHandle.getStateFlow( - key = Constants.SAVINGS_ID, - initialValue = -1L, - ) + private val _savingsWithAssociations = MutableStateFlow(null) + val savingsWithAssociations = _savingsWithAssociations.asStateFlow() - @OptIn(ExperimentalCoroutinesApi::class) - val savingsWithAssociations = savingsId - .flatMapLatest { + private val _eventFlow = MutableSharedFlow() + val eventFlow = _eventFlow.asSharedFlow() + + init { + fetchSavingsAccountWithAssociations() + } + + private fun fetchSavingsAccountWithAssociations() { + viewModelScope.launch { savingsAccountRepositoryImp.getSavingsWithAssociations( - savingsId.value, + savingsId, Constants.TRANSACTIONS, - ) + ).collect { result -> + when (result) { + is DataState.Success -> { + _savingsWithAssociations.value = result.data + mUiState.value = SavingsAccountWithdrawUiState.Ready + } + is DataState.Error -> { + _savingsWithAssociations.value = null + mUiState.value = SavingsAccountWithdrawUiState.Error + } + is DataState.Loading -> { + mUiState.value = SavingsAccountWithdrawUiState.Loading + } + } + } } - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5_000), - initialValue = null, - ) + } fun submitWithdrawSavingsAccount(remark: String) { + val accountNo = savingsWithAssociations.value?.accountNo ?: return + val payload = SavingsAccountWithdrawPayload( note = remark, withdrawnOnDate = DateHelper.formattedFullDate, + dateFormat = "dd MMMM yyyy", + locale = "en", ) viewModelScope.launch { mUiState.value = SavingsAccountWithdrawUiState.Loading - val response = savingsAccountRepositoryImp.submitWithdrawSavingsAccount( - savingsWithAssociations.value?.data?.accountNo, - payload, - ) - when (response) { - is DataState.Error -> { - mUiState.value = - SavingsAccountWithdrawUiState.Error(response.message) - } - DataState.Loading -> { - SavingsAccountWithdrawUiState.Loading - } + when (val response = savingsAccountRepositoryImp.submitWithdrawSavingsAccount(accountNo, payload)) { is DataState.Success -> { - mUiState.value = SavingsAccountWithdrawUiState.Success + val message = getString(Res.string.savings_account_withdraw_successful) + _eventFlow.emit(SavingsAccountWithdrawUiEvent.ShowSnackbar(message)) + delay(1500) + _eventFlow.emit(SavingsAccountWithdrawUiEvent.NavigateBack(true)) } + is DataState.Error -> mUiState.value = SavingsAccountWithdrawUiState.Message(response.message) + is DataState.Loading -> mUiState.value = SavingsAccountWithdrawUiState.Loading } } } } internal sealed interface SavingsAccountWithdrawUiState { - data object WithdrawUiReady : SavingsAccountWithdrawUiState + data object Ready : SavingsAccountWithdrawUiState data object Loading : SavingsAccountWithdrawUiState data object Success : SavingsAccountWithdrawUiState - data class Error(val message: String?) : SavingsAccountWithdrawUiState + data object Error : SavingsAccountWithdrawUiState + data class Message(val message: String?) : SavingsAccountWithdrawUiState +} + +internal sealed interface SavingsAccountWithdrawUiEvent { + data class ShowSnackbar(val message: String) : SavingsAccountWithdrawUiEvent + data class NavigateBack(val withDrawSuccess: Boolean) : SavingsAccountWithdrawUiEvent } diff --git a/feature/third-party-transfer/src/commonMain/kotlin/org/mifos/mobile/feature/third/party/transfer/ThirdPartyTransferViewModel.kt b/feature/third-party-transfer/src/commonMain/kotlin/org/mifos/mobile/feature/third/party/transfer/ThirdPartyTransferViewModel.kt index 03c9db2b5..8b671984d 100644 --- a/feature/third-party-transfer/src/commonMain/kotlin/org/mifos/mobile/feature/third/party/transfer/ThirdPartyTransferViewModel.kt +++ b/feature/third-party-transfer/src/commonMain/kotlin/org/mifos/mobile/feature/third/party/transfer/ThirdPartyTransferViewModel.kt @@ -18,7 +18,6 @@ import mifos_mobile.feature.third_party_transfer.generated.resources.Res import mifos_mobile.feature.third_party_transfer.generated.resources.internet_not_connected import org.jetbrains.compose.resources.getString import org.mifos.mobile.core.common.DataState -import org.mifos.mobile.core.common.FileUtils.Companion.logger import org.mifos.mobile.core.data.repository.BeneficiaryRepository import org.mifos.mobile.core.data.repository.ThirdPartyTransferRepository import org.mifos.mobile.core.data.util.NetworkMonitor @@ -81,10 +80,6 @@ internal class ThirdPartyTransferViewModel( transferRepository.thirdPartyTransferTemplate(), beneficiaryRepository.beneficiaryList(), ) { templateResult, beneficiariesResult -> - logger.d { - "KtorClient getting in function ${templateResult.data} and ben " + - "${beneficiariesResult.data}" - } updateStateFromResults(templateResult, beneficiariesResult) }.catch { error -> updateState { @@ -105,7 +100,6 @@ internal class ThirdPartyTransferViewModel( val error = (templateResult as? DataState.Error)?.exception?.message ?: (beneficiariesResult as? DataState.Error)?.exception?.message ?: "An error occurred" - logger.d { "KtorClient error $error" } val errorMessage = "An error occurred" updateState { it.copy(dialogState = ThirdPartyTransferState.DialogState.Error(errorMessage)) } } diff --git a/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/TransferProcessViewModel.kt b/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/TransferProcessViewModel.kt index d40031857..8551b2108 100644 --- a/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/TransferProcessViewModel.kt +++ b/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/TransferProcessViewModel.kt @@ -26,7 +26,6 @@ import org.mifos.mobile.core.data.repository.TransferRepository import org.mifos.mobile.core.model.IgnoredOnParcel import org.mifos.mobile.core.model.Parcelable import org.mifos.mobile.core.model.Parcelize -import org.mifos.mobile.core.model.entity.TransferResponse 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 @@ -57,7 +56,9 @@ internal class TransferProcessViewModel( updateState { it.copy( transferPayload = state.transferPayloadString?.let { jsonString -> - jsonString.let { Json.decodeFromString(jsonString) } + jsonString.let { + Json.decodeFromString(it) + } }, ) } @@ -97,21 +98,24 @@ internal class TransferProcessViewModel( } private fun processTransferResult( - response: DataState, + response: DataState, message: String, ) { when (response) { is DataState.Error -> { - updateState { - it.copy(dialogState = TransferProcessState.DialogState.Error(response.message)) - } + updateState { it.copy(dialogState = null) } + sendEvent( + TransferProcessEvent.ShowToast( + response.message, + ), + ) } DataState.Loading -> TransferProcessState.DialogState.Loading is DataState.Success -> { updateState { it.copy(dialogState = null) } sendEvent( TransferProcessEvent.ShowToast( - message + "with ID ${response.data.resourceId}", + message + "with ID ${response.data}", ), ) viewModelScope.launch { diff --git a/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/navigation/TransferProcessNavGraph.kt b/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/navigation/TransferProcessNavGraph.kt index ff17e2923..be392d861 100644 --- a/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/navigation/TransferProcessNavGraph.kt +++ b/feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/navigation/TransferProcessNavGraph.kt @@ -87,7 +87,7 @@ private fun ReviewTransferPayload.convertToTransferPayloadString(): String { fromClientId = this.payFromAccount?.clientId, fromAccountType = this.payFromAccount?.accountType?.id, fromOfficeId = this.payFromAccount?.officeId, - toOfficeId = this.payFromAccount?.officeId, + toOfficeId = this.payToAccount?.officeId, toAccountId = this.payToAccount?.accountNo, toClientId = this.payToAccount?.clientId, toAccountType = this.payToAccount?.accountType?.id, diff --git a/feature/user-profile/src/commonMain/kotlin/org/mifos/mobile/feature/user/profile/viewmodel/UserDetailViewModel.kt b/feature/user-profile/src/commonMain/kotlin/org/mifos/mobile/feature/user/profile/viewmodel/UserDetailViewModel.kt index 8e8b3b248..c19eef964 100644 --- a/feature/user-profile/src/commonMain/kotlin/org/mifos/mobile/feature/user/profile/viewmodel/UserDetailViewModel.kt +++ b/feature/user-profile/src/commonMain/kotlin/org/mifos/mobile/feature/user/profile/viewmodel/UserDetailViewModel.kt @@ -217,7 +217,6 @@ internal class UserDetailViewModel( e.message ?: "An error occurred", ), ) - logger.d { "Notifications@@@ $e" } }.collect { userDetail -> when (userDetail) { is DataState.Error -> { @@ -248,7 +247,6 @@ internal class UserDetailViewModel( val result = userDetailRepositoryImp.updateRegisterNotification(id, payload) when (result) { is DataState.Error -> { - logger.d { "Notifications@@@ ${result.message}" } setDialogState( UserDetailState.DialogState.Error( result.message, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2624dba42..a9d1c9bb9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,6 @@ androidxComposeBom = "2024.12.01" androidxComposeCompiler = "1.5.15" androidxCoreSplashscreen = "1.0.1" androidxEspresso = "3.6.1" -androidxHilt = "1.2.0" androidxLifecycle = "2.8.7" androidxMetrics = "1.0.0-beta01" androidxNavigation = "2.8.5" @@ -40,9 +39,6 @@ googleAppCodeScanner = "17.3.0" googleMaps = "4.4.1" googleOss = "17.1.0" googleOssPlugin = "0.10.6" -gsonVersion = "2.10.1" -hilt = "2.54" -hiltExt = "1.2.0" jacoco = "0.8.7" junitVersion = "4.13.2" ktlint = "12.1.1" @@ -56,7 +52,6 @@ multidexVersion = "2.0.1" okHttp3Version = "4.12.0" playServicesCodeScanner = "16.1.0" playServicesVersion = "19.0.0" -retrofitVersion = "2.11.0" roborazzi = "1.26.0" room = "2.7.0-alpha12" sqliteBundled = "2.5.0-alpha12" @@ -160,7 +155,6 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u androidx-compose-ui-util = { group = "androidx.compose.ui", name = "ui-util" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidxCoreSplashscreen" } -androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidxHilt" } androidx-lifecycle-extensions = { group = "androidx.lifecycle", name = "lifecycle-extensions", version.ref = "lifecycleExtensionsVersion" } androidx-lifecycle-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleVersion" } androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtxVersion" } @@ -199,13 +193,6 @@ google-map-compose = { group = "com.google.maps.android", name = "maps-compose", google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" } google-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "googleOssPlugin" } google-play-services-code-scanner = { group = "com.google.android.gms", name = "play-services-code-scanner", version.ref = "playServicesCodeScanner" } -gson = { group = "com.google.code.gson", name = "gson", version.ref = "gsonVersion" } -hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } -hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" } -hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } -hilt-core = { group = "com.google.dagger", name = "hilt-core", version.ref = "hilt" } -hilt-ext-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltExt" } -hilt-ext-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltExt" } jetbrains-kotlin-jdk7 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk7", version.ref = "kotlin" } junit = { group = "junit", name = "junit", version.ref = "junitVersion" } ktlint-gradlePlugin = { group = "org.jlleitschuh.gradle", name = "ktlint-gradle", version.ref = "ktlint" } @@ -222,9 +209,6 @@ slack-compose-lint = { group = "com.slack.lint.compose", name = "compose-lint-ch spotless-gradlePlugin = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version.ref = "spotlessVersion" } squareup-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okHttp3Version" } squareup-okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okHttp3Version" } -squareup-retrofit-adapter-rxjava = { group = "com.squareup.retrofit2", name = "adapter-rxjava2", version.ref = "retrofitVersion" } -squareup-retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofitVersion" } -squareup-retrofit2 = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofitVersion" } truth = { group = "com.google.truth", name = "truth", version.ref = "truth" } turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbineVersion" } twitter-detekt-compose = { group = "com.twitter.compose.rules", name = "detekt", version.ref = "twitter-detekt-compose" } @@ -343,11 +327,9 @@ android-library = { id = "com.android.library", version.ref = "androidGradlePlug android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -# Hilt & Room Plugins -hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } +# Room Plugins room = { id = "androidx.room", version.ref = "room" } -mifos-android-hilt = { id = "mifos.android.hilt", version = "unspecified" } mifos-kmp-room = { id = "mifos.kmp.room", version = "unspecified" } mifos-android-application = { id = "mifos.android.application", version = "unspecified" } mifos-android-application-compose = { id = "mifos.android.application.compose", version = "unspecified" }