diff --git a/ci-prepush.sh b/ci-prepush.sh
old mode 100644
new mode 100755
diff --git a/cmp-navigation/src/androidMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.android.kt b/cmp-navigation/src/androidMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.android.kt
new file mode 100644
index 000000000..5bea8cb87
--- /dev/null
+++ b/cmp-navigation/src/androidMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.android.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2025 Mifos Initiative
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
+ */
+package cmp.navigation.authenticated
+
+import org.mifos.mobile.feature.beneficiary.beneficiaryApplicationConfirmation.BeneficiaryApplicationConfirmationNavRoute
+import org.mifos.mobile.feature.loan.application.confirmDetails.ConfirmDetailsRoute
+import org.mifos.mobile.feature.transfer.process.transferProcess.TransferProcessRoute
+
+actual fun getPopRules(): Map = mapOf(
+ ConfirmDetailsRoute::class.qualifiedName.orEmpty() to 2,
+ TransferProcessRoute::class.qualifiedName.orEmpty() to 2,
+ BeneficiaryApplicationConfirmationNavRoute::class.qualifiedName.orEmpty() to 2,
+)
diff --git a/cmp-navigation/src/appleMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.apple.kt b/cmp-navigation/src/appleMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.apple.kt
new file mode 100644
index 000000000..5bea8cb87
--- /dev/null
+++ b/cmp-navigation/src/appleMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.apple.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2025 Mifos Initiative
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
+ */
+package cmp.navigation.authenticated
+
+import org.mifos.mobile.feature.beneficiary.beneficiaryApplicationConfirmation.BeneficiaryApplicationConfirmationNavRoute
+import org.mifos.mobile.feature.loan.application.confirmDetails.ConfirmDetailsRoute
+import org.mifos.mobile.feature.transfer.process.transferProcess.TransferProcessRoute
+
+actual fun getPopRules(): Map = mapOf(
+ ConfirmDetailsRoute::class.qualifiedName.orEmpty() to 2,
+ TransferProcessRoute::class.qualifiedName.orEmpty() to 2,
+ BeneficiaryApplicationConfirmationNavRoute::class.qualifiedName.orEmpty() to 2,
+)
diff --git a/cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt b/cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
index 820f980a0..bd6b1bc9f 100644
--- a/cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
+++ b/cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
@@ -33,7 +33,6 @@ import org.mifos.mobile.feature.accounts.accounts.navigateToAccountsScreen
import org.mifos.mobile.feature.auth.login.navigateToLoginScreen
import org.mifos.mobile.feature.auth.navigation.AuthGraphRoute
import org.mifos.mobile.feature.beneficiary.beneficiaryApplication.navigateToManualBeneficiaryAddScreen
-import org.mifos.mobile.feature.beneficiary.beneficiaryApplicationConfirmation.BeneficiaryApplicationConfirmationNavRoute
import org.mifos.mobile.feature.beneficiary.navigation.BeneficiaryNavRoute
import org.mifos.mobile.feature.beneficiary.navigation.beneficiaryNavGraph
import org.mifos.mobile.feature.beneficiary.navigation.navigateToBeneficiaryNavGraph
@@ -41,7 +40,6 @@ import org.mifos.mobile.feature.charge.charges.navigateToClientChargeScreen
import org.mifos.mobile.feature.charge.navigation.clientChargeNavGraph
import org.mifos.mobile.feature.charge.navigation.navigateToChargeGraph
import org.mifos.mobile.feature.home.navigation.HomeNavigationDestination
-import org.mifos.mobile.feature.loan.application.confirmDetails.ConfirmDetailsRoute
import org.mifos.mobile.feature.loan.application.navigation.loanApplicationNavGraph
import org.mifos.mobile.feature.loan.application.navigation.navigateToLoanApplicationGraph
import org.mifos.mobile.feature.loanaccount.loanAccountDetails.navigateToLoanAccountDetailsScreen
@@ -69,13 +67,14 @@ import org.mifos.mobile.feature.status.navigation.statusDestination
import org.mifos.mobile.feature.third.party.transfer.navigation.TptNavigationDestination
import org.mifos.mobile.feature.transfer.process.makeTransfer.makeTransferDestination
import org.mifos.mobile.feature.transfer.process.makeTransfer.navigateToMakeTransferScreen
-import org.mifos.mobile.feature.transfer.process.transferProcess.TransferProcessRoute
import org.mifos.mobile.feature.transfer.process.transferProcess.navigateToTransferProcessScreen
import org.mifos.mobile.feature.transfer.process.transferProcess.transferProcessDestination
@Serializable
internal data object AuthenticatedGraphRoute
+expect fun getPopRules(): Map
+
internal fun NavController.navigateToAuthenticatedGraph(navOptions: NavOptions? = null) {
navigate(route = AuthenticatedGraphRoute, navOptions = navOptions)
}
@@ -471,11 +470,7 @@ fun NavController.navigateToBeneficiaryFromStatus() {
}
fun NavController.popScreens(
- popRules: Map = mapOf(
- ConfirmDetailsRoute::class.qualifiedName.orEmpty() to 2,
- TransferProcessRoute::class.qualifiedName.orEmpty() to 2,
- BeneficiaryApplicationConfirmationNavRoute::class.qualifiedName.orEmpty() to 2,
- ),
+ popRules: Map = getPopRules(),
) {
val lastEntry = previousBackStackEntry?.destination?.route
diff --git a/cmp-navigation/src/desktopMain/java/cmp/navigation/authenticated/AuthenticatedNavigation.desktop.kt b/cmp-navigation/src/desktopMain/java/cmp/navigation/authenticated/AuthenticatedNavigation.desktop.kt
new file mode 100644
index 000000000..5bea8cb87
--- /dev/null
+++ b/cmp-navigation/src/desktopMain/java/cmp/navigation/authenticated/AuthenticatedNavigation.desktop.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2025 Mifos Initiative
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
+ */
+package cmp.navigation.authenticated
+
+import org.mifos.mobile.feature.beneficiary.beneficiaryApplicationConfirmation.BeneficiaryApplicationConfirmationNavRoute
+import org.mifos.mobile.feature.loan.application.confirmDetails.ConfirmDetailsRoute
+import org.mifos.mobile.feature.transfer.process.transferProcess.TransferProcessRoute
+
+actual fun getPopRules(): Map = mapOf(
+ ConfirmDetailsRoute::class.qualifiedName.orEmpty() to 2,
+ TransferProcessRoute::class.qualifiedName.orEmpty() to 2,
+ BeneficiaryApplicationConfirmationNavRoute::class.qualifiedName.orEmpty() to 2,
+)
diff --git a/cmp-navigation/src/jsMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.js.kt b/cmp-navigation/src/jsMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.js.kt
new file mode 100644
index 000000000..85bb5f57f
--- /dev/null
+++ b/cmp-navigation/src/jsMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.js.kt
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2025 Mifos Initiative
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
+ */
+package cmp.navigation.authenticated
+
+actual fun getPopRules(): Map = mapOf(
+ "cmp.navigation.authenticated.ConfirmDetailsRoute" to 2,
+ "cmp.navigation.authenticated.TransferProcessRoute" to 2,
+ "cmp.navigation.authenticated.BeneficiaryApplicationConfirmationNavRoute" to 2,
+)
diff --git a/cmp-navigation/src/wasmJsMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.wasmJs.kt b/cmp-navigation/src/wasmJsMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.wasmJs.kt
new file mode 100644
index 000000000..85bb5f57f
--- /dev/null
+++ b/cmp-navigation/src/wasmJsMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.wasmJs.kt
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2025 Mifos Initiative
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
+ */
+package cmp.navigation.authenticated
+
+actual fun getPopRules(): Map = mapOf(
+ "cmp.navigation.authenticated.ConfirmDetailsRoute" to 2,
+ "cmp.navigation.authenticated.TransferProcessRoute" to 2,
+ "cmp.navigation.authenticated.BeneficiaryApplicationConfirmationNavRoute" to 2,
+)
diff --git a/cmp-web/build.gradle.kts b/cmp-web/build.gradle.kts
index bee2fc340..5dec055ff 100644
--- a/cmp-web/build.gradle.kts
+++ b/cmp-web/build.gradle.kts
@@ -59,6 +59,10 @@ kotlin {
}
}
+tasks.register("jsBrowserRun") {
+ dependsOn("jsBrowserDevelopmentRun")
+}
+
compose.resources {
publicResClass = true
generateResClass = always
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationContent.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationContent.kt
index ac7bd4afe..655cb9c0b 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationContent.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationContent.kt
@@ -50,6 +50,13 @@ import org.mifos.mobile.core.designsystem.theme.MifosTypography
import org.mifos.mobile.core.model.enums.BeneficiaryState
import org.mifos.mobile.core.ui.component.MifosDropDownTextField
+/**
+ * Composable function to display a beneficiary application form.
+ *
+ * @param state The current state of the beneficiary application form.
+ * @param onAction A callback to handle actions from the form.
+ * @param modifier The modifier to apply to the composable.
+ */
@Composable
@Suppress("CyclomaticComplexMethod", "ComplexCondition")
internal fun BeneficiaryApplicationContent(
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationNavRoute.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationNavRoute.kt
index 4d9858022..3f2cdb0fb 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationNavRoute.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationNavRoute.kt
@@ -15,7 +15,16 @@ import androidx.navigation.NavOptions
import kotlinx.serialization.Serializable
import org.mifos.mobile.core.model.enums.BeneficiaryState
import org.mifos.mobile.core.ui.composableWithSlideTransitions
-
+/**
+ * Data class representing the navigation route for the beneficiary application screen.
+ *
+ * @property beneficiaryId the ID of the beneficiary.
+ * @property beneficiaryState the state of the beneficiary.
+ * @property name the name of the beneficiary.
+ * @property accountType the account type of the beneficiary.
+ * @property accountNumber the account number of the beneficiary.
+ * @property officeName the office name of the beneficiary.
+ */
@Serializable
data class BeneficiaryApplicationNavRoute(
val beneficiaryId: Long = -1L,
@@ -26,6 +35,17 @@ data class BeneficiaryApplicationNavRoute(
val officeName: String = "",
)
+/**
+ * Navigate to the manual beneficiary add screen.
+ *
+ * @param beneficiaryId the ID of the beneficiary.
+ * @param name the name of the beneficiary.
+ * @param accountType the account type of the beneficiary.
+ * @param accountNumber the account number of the beneficiary.
+ * @param officeName the office name of the beneficiary.
+ * @param beneficiaryState the state of the beneficiary.
+ * @param navOptions the navigation options.
+ */
fun NavController.navigateToManualBeneficiaryAddScreen(
beneficiaryId: Long = -1L,
name: String = "",
@@ -48,6 +68,13 @@ fun NavController.navigateToManualBeneficiaryAddScreen(
)
}
+/**
+ * Composable function to define the manual beneficiary add destination in the navigation graph.
+ *
+ * @param navigateBack a function to navigate back to the previous screen.
+ * @param navigateToQR a function to navigate to the QR code screen.
+ * @param navigateToConfirmationScreen a function to navigate to the confirmation screen.
+ */
fun NavGraphBuilder.manualBeneficiaryAddDestination(
navigateBack: () -> Unit,
navigateToQR: () -> Unit,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationScreen.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationScreen.kt
index 65024eb60..b66f9c98a 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationScreen.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplication/BeneficiaryApplicationScreen.kt
@@ -31,6 +31,15 @@ import org.mifos.mobile.core.ui.component.MifosProgressIndicator
import org.mifos.mobile.core.ui.utils.EventsEffect
import org.mifos.mobile.core.ui.utils.ScreenUiState
+/**
+ * Composable function to display the beneficiary application screen.
+ *
+ * @param navigateBack a function to navigate back to the previous screen.
+ * @param navigateToQR a function to navigate to the QR code screen.
+ * @param navigateToConfirmationScreen a function to navigate to the confirmation screen.
+ * @param modifier the modifier to apply to the composable.
+ * @param viewModel the [BeneficiaryApplicationViewModel] to use for the composable.
+ */
@Composable
internal fun BeneficiaryApplicationScreen(
navigateBack: () -> Unit,
@@ -86,6 +95,12 @@ internal fun BeneficiaryApplicationScreen(
)
}
+/**
+ * Composable function to display dialogs for the beneficiary application screen.
+ *
+ * @param state the current state of the screen.
+ * @param onAction a function to handle user actions.
+ */
@Composable
private fun BeneficiaryApplicationDialogs(
state: BeneficiaryApplicationState,
@@ -104,6 +119,16 @@ private fun BeneficiaryApplicationDialogs(
}
}
+/**
+ * Composable function to display the beneficiary application screen.
+ *
+ * It displays a progress indicator when the UI state is loading, a network error component
+ * when the network status is false, and the beneficiary application content when the UI state is success.
+ *
+ * @param state the current state of the screen.
+ * @param onAction a function to handle user actions.
+ * @param modifier the modifier to apply to the composable.
+ */
@Composable
private fun BeneficiaryApplicationScreen(
state: BeneficiaryApplicationState,
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 b2ebacab9..987047e2f 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
@@ -379,6 +379,31 @@ internal class BeneficiaryApplicationViewModel(
}
}
+/**
+ * Data class to represent the state of the beneficiary application screen.
+ *
+ * @param topBarTitle the title to display in the top bar.
+ * @param beneficiaryId the ID of the beneficiary.
+ * @param networkUnavailable a flag to indicate if the network is unavailable.
+ * @param template the beneficiary template.
+ * @param beneficiary the beneficiary.
+ * @param beneficiaryState the state of the beneficiary.
+ * @param dialogState the state of the dialog.
+ * @param accountTypeError the error message for the account type.
+ * @param accountNumberError the error message for the account number.
+ * @param officeNameError the error message for the office name.
+ * @param transferLimitError the error message for the transfer limit.
+ * @param beneficiaryNameError the error message for the beneficiary name.
+ * @param accountType the account type of the beneficiary.
+ * @param accountNumber the account number of the beneficiary.
+ * @param officeName the office name of the beneficiary.
+ * @param transferLimit the transfer limit of the beneficiary.
+ * @param beneficiaryName the beneficiary name.
+ * @param networkStatus the network status.
+ * @param uiState the UI state of the screen.
+ * @param shoeOverlay the overlay to display.
+ */
+
data class BeneficiaryApplicationState(
val topBarTitle: StringResource = Res.string.add_beneficiary,
val beneficiaryId: Long = -1L,
@@ -414,8 +439,16 @@ data class BeneficiaryApplicationState(
beneficiaryName.isNotEmpty()
}
+/**
+ * Data class to represent the events of the beneficiary application screen.
+ *
+ * @param Navigate navigate to the next screen.
+ * @param SubmitBeneficiary submit the beneficiary application.
+ * @param NavigateToQR navigate to the QR screen.
+ */
sealed interface BeneficiaryApplicationEvent {
data object Navigate : BeneficiaryApplicationEvent
+
data class SubmitBeneficiary(
val beneficiaryId: Long,
val beneficiaryState: String,
@@ -425,20 +458,39 @@ sealed interface BeneficiaryApplicationEvent {
val accountNumber: String,
val transferLimit: Int,
) : BeneficiaryApplicationEvent
+
data object NavigateToQR : BeneficiaryApplicationEvent
}
+/***
+ * Data class to represent the actions of the beneficiary application screen.
+ *
+ * @param LoadBeneficiaryTemplate load the beneficiary template.
+ * @param SubmitBeneficiary submit the beneficiary application.
+ * @param OnNavigate navigate to the next screen.
+ * @param OnRetry retry the operation.
+ * @param NavigateToQR navigate to the QR screen.
+ */
+
sealed interface BeneficiaryApplicationAction {
+
data object LoadBeneficiaryTemplate : BeneficiaryApplicationAction
data object SubmitBeneficiary : BeneficiaryApplicationAction
+
data object OnNavigate : BeneficiaryApplicationAction
+
data object OnRetry : BeneficiaryApplicationAction
+
data object NavigateToQR : BeneficiaryApplicationAction
data class OnAccountTypeChanged(val accountType: Int) : BeneficiaryApplicationAction
+
data class OnAccountNumberChanged(val accountNumber: String) : BeneficiaryApplicationAction
+
data class OnOfficeNameChanged(val officeName: String) : BeneficiaryApplicationAction
+
data class OnTransferLimitChanged(val transferLimit: String) : BeneficiaryApplicationAction
+
data class OnBeneficiaryNameChanged(val beneficiaryName: String) : BeneficiaryApplicationAction
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryApplicationAction
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationNavigation.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationNavigation.kt
index 298829d2b..54d170533 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationNavigation.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationNavigation.kt
@@ -17,6 +17,17 @@ import androidx.navigation.NavOptions
import kotlinx.serialization.Serializable
import org.mifos.mobile.core.ui.composableWithSlideTransitions
+/**
+ * Data class representing the navigation route for the beneficiary application confirmation screen.
+ *
+ * @property beneficiaryId the ID of the beneficiary.
+ * @property beneficiaryState the state of the beneficiary.
+ * @property name the name of the beneficiary.
+ * @property officeName the office name of the beneficiary.
+ * @property accountType the account type of the beneficiary.
+ * @property accountNumber the account number of the beneficiary.
+ * @property transferLimit the transfer limit of the beneficiary.
+ */
@Serializable
data class BeneficiaryApplicationConfirmationNavRoute(
val beneficiaryId: Long = -1L,
@@ -28,6 +39,18 @@ data class BeneficiaryApplicationConfirmationNavRoute(
val transferLimit: Int,
)
+/**
+ * Navigates to the beneficiary application confirmation screen.
+ *
+ * @param beneficiaryId the ID of the beneficiary.
+ * @param beneficiaryState the state of the beneficiary.
+ * @param name the name of the beneficiary.
+ * @param officeName the office name of the beneficiary.
+ * @param accountType the account type of the beneficiary.
+ * @param accountNumber the account number of the beneficiary.
+ * @param transferLimit the transfer limit of the beneficiary.
+ * @param navOptions the navigation options.
+ */
fun NavController.navigateToBeneficiaryApplicationAddConfirmationScreen(
beneficiaryId: Long = -1L,
beneficiaryState: String,
@@ -52,6 +75,13 @@ fun NavController.navigateToBeneficiaryApplicationAddConfirmationScreen(
)
}
+/**
+ * Adds a destination to the navigation graph for the beneficiary application confirmation screen.
+ *
+ * @param navigateBack a function to navigate back to the previous screen.
+ * @param navigateToStatusScreen a function to navigate to the status screen.
+ * @param navigateToAuthenticateScreen a function to navigate to the authentication screen.
+ */
fun NavGraphBuilder.beneficiaryAddConfirmationDestination(
navigateBack: () -> Unit,
navigateToStatusScreen: (String, String, String, String, String) -> Unit,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationScreen.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationScreen.kt
index 7482f6dda..7aba77aa4 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationScreen.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationScreen.kt
@@ -38,6 +38,14 @@ import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay
import org.mifos.mobile.core.ui.utils.EventsEffect
import org.mifos.mobile.core.ui.utils.ScreenUiState
+/**
+ * Composable function to render the beneficiary application confirmation screen.
+ *
+ * @param navigateBack a function to navigate back to the previous screen.
+ * @param navigateToStatusScreen a function to navigate to the status screen.
+ * @param navigateToAuthenticateScreen a function to navigate to the authenticate screen.
+ * @param viewModel the view model for the beneficiary application confirmation screen.
+ */
@Composable
internal fun BeneficiaryApplicationConfirmationScreen(
navigateBack: () -> Unit,
@@ -80,6 +88,11 @@ internal fun BeneficiaryApplicationConfirmationScreen(
)
}
+/**
+ * Composable function to display error dialogs for the Beneficiary Application Confirmation screen.
+ * @param state the state of the Beneficiary Application Confirmation screen.
+ * @return a Unit or null if no dialog should be shown.
+ */
@Composable
private fun BeneficiaryApplicationConfirmationScreenDialogs(
state: BeneficiaryApplicationConfirmationState,
@@ -94,6 +107,14 @@ private fun BeneficiaryApplicationConfirmationScreenDialogs(
}
}
+/**
+ * Composable function to render the content of the Beneficiary Application confirmation screen.
+ *
+ * @param state the state of the Beneficiary Application confirmation screen.
+ * @param modifier the modifier to apply to the content.
+ * @param onAction the action to perform when the confirm button is clicked.
+ * @return a Unit or null if no content should be rendered.
+ */
@Composable
fun BeneficiaryApplicationConfirmationScreenContent(
state: BeneficiaryApplicationConfirmationState,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationViewModel.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationViewModel.kt
index bc1baf642..abb6e83c5 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationViewModel.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryApplicationConfirmation/BeneficiaryApplicationConfirmationViewModel.kt
@@ -164,6 +164,11 @@ internal class BeneficiaryApplicationConfirmationViewModel(
}
}
+/**
+ * Handles the result of the beneficiary creation API call.
+ * If the API call is successful, navigates the user to the beneficiary status screen.
+ * If the API call fails, navigates the user to the previous screen with an error message.
+ */
private fun processSubmitBeneficiaryResult(response: DataState) {
viewModelScope.launch {
when (response) {
@@ -226,6 +231,12 @@ internal class BeneficiaryApplicationConfirmationViewModel(
}
}
+ /**
+ * Processes the result of an update beneficiary API call.
+ * Handles success, failure and loading states.
+ * Shows an overlay during the loading state.
+ * Shows a success or failure message on the status screen depending on the result.
+ */
private fun processUpdateBeneficiaryResult(response: DataState) {
viewModelScope.launch {
when (response) {
@@ -325,6 +336,11 @@ internal class BeneficiaryApplicationConfirmationViewModel(
}
}
+ /**
+ * Initializes the map details state variable with the route details.
+ *
+ * @param savedStateHandle the SavedStateHandle containing the route details.
+ */
private suspend fun initializeMapDetails() {
val route = savedStateHandle.toRoute()
val details = mapOf(
@@ -363,6 +379,25 @@ internal class BeneficiaryApplicationConfirmationViewModel(
}
}
+/**
+ * Represents the state of the Beneficiary Application Confirmation screen.
+ *
+ * @param details the map of beneficiary details to display on the screen.
+ * @param topBarTitle the title to display on the top bar of the screen.
+ * @param beneficiaryId the ID of the beneficiary being updated or added.
+ * @param name the name of the beneficiary.
+ * @param officeName the name of the office where the beneficiary is registered.
+ * @param accountType the type of account the beneficiary has (e.g. savings, loan).
+ * @param accountNumber the account number of the beneficiary.
+ * @param transferLimit the transfer limit of the beneficiary.
+ * @param networkUnavailable indicates whether the network is unavailable.
+ * @param beneficiaryState the state of the beneficiary (e.g. updating, adding).
+ * @param dialogState the state of any dialogs to display on the screen.
+ * @param uiState the current UI state of the screen (e.g. loading, error, success).
+ * @param showOverlay indicates whether to show an overlay on the screen.
+ * @param networkStatus indicates whether the network is available.
+ */
+
data class BeneficiaryApplicationConfirmationState(
val details: Map = emptyMap(),
val topBarTitle: StringResource = Res.string.add_beneficiary,
@@ -386,20 +421,47 @@ data class BeneficiaryApplicationConfirmationState(
}
}
+/*
+* Represents the events that can occur on the Beneficiary Application Confirmation screen.
+*/
+
sealed interface BeneficiaryApplicationConfirmationEvent {
+ /**
+ * Represents the event of navigating back to the previous screen.
+ */
data object Navigate : BeneficiaryApplicationConfirmationEvent
+
+ /**
+ * Represents the event of navigating to the Beneficiary Status screen.
+ *
+ * @param eventType the type of event (e.g. success, error).
+ * @param eventDestination the destination to navigate to.
+ * @param title the title to display on the screen.
+ * @param subtitle the subtitle to display on the screen.
+ * @param buttonText the text to display on the button.
+ */
data class NavigateToStatus(
val eventType: String,
val eventDestination: String,
val title: String,
val subtitle: String,
+
val buttonText: String,
) : BeneficiaryApplicationConfirmationEvent
+
data class NavigateToAuthenticate(
val status: String = EventType.SUCCESS.name,
) : BeneficiaryApplicationConfirmationEvent
}
+/**
+ * Represents the actions that can be performed on the Beneficiary Application Confirmation screen.
+ *
+ * @param SubmitBeneficiary the action of submitting the beneficiary application.
+ * @param ReceiveNetworkStatus the action of receiving the network status.
+ * @param OnNavigate the action of navigating back to the previous screen.
+ */
+
sealed interface BeneficiaryApplicationConfirmationAction {
data object SubmitBeneficiary : BeneficiaryApplicationConfirmationAction
@@ -408,9 +470,18 @@ sealed interface BeneficiaryApplicationConfirmationAction {
data object OnNavigate : BeneficiaryApplicationConfirmationAction
+ /**
+ * Represents the internal actions that can be performed on the Beneficiary Application Confirmation screen.
+ *
+ * @param ReceiveAuthenticationResult the action of receiving the authentication result.
+ * @param ReceiveSubmitBeneficiary the action of receiving the result of submitting the beneficiary application.
+ * @param ReceiveUpdateBeneficiary the action of receiving the result of updating the beneficiary application.
+ */
sealed interface Internal : BeneficiaryApplicationConfirmationAction {
data class ReceiveAuthenticationResult(val result: Boolean) : Internal
+
data class ReceiveSubmitBeneficiary(val result: DataState) : Internal
+
data class ReceiveUpdateBeneficiary(val result: DataState) : Internal
}
}
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailContent.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailContent.kt
index e7fa5804c..d4b93ce8d 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailContent.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailContent.kt
@@ -43,6 +43,13 @@ import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme
import org.mifos.mobile.core.designsystem.theme.MifosTypography
import org.mifos.mobile.core.ui.component.MifosBeneficiaryTopCard
+/**
+ * Composable function to display beneficiary details.
+ *
+ * @param state The state of the beneficiary screen.
+ * @param onAction The callback to handle actions on the beneficiary screen.
+ * @param modifier The modifier for the composable.
+ */
@Composable
internal fun BeneficiaryDetailContent(
state: BeneficiaryDetailState?,
@@ -116,6 +123,12 @@ internal fun BeneficiaryDetailContent(
}
}
+/**
+ * A composable function to display a row of actions for the beneficiary detail screen.
+ *
+ * @param onAction A callback to handle actions from the beneficiary detail screen.
+ * @param modifier The modifier to apply to the composable.
+ */
@Composable
internal fun ActionBar(
onAction: (BeneficiaryDetailAction) -> Unit,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailScreen.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailScreen.kt
index ac154eaf8..c35ad43cf 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailScreen.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailScreen.kt
@@ -35,6 +35,15 @@ import org.mifos.mobile.core.ui.component.MifosProgressIndicator
import org.mifos.mobile.core.ui.utils.EventsEffect
import org.mifos.mobile.core.ui.utils.ScreenUiState
+/**
+ * A composable function to display the beneficiary detail screen.
+ *
+ * @param navigateBack A callback to navigate back from the beneficiary detail screen.
+ * @param updateBeneficiary A callback to update a beneficiary.
+ * @param modifier The modifier to apply to the composable.
+ * @param viewModel The view model to use for the beneficiary detail screen.
+ */
+
@Composable
internal fun BeneficiaryDetailScreen(
navigateBack: () -> Unit,
@@ -69,6 +78,12 @@ internal fun BeneficiaryDetailScreen(
)
}
+/**
+ * A composable function to display the beneficiary detail dialogs.
+ *
+ * @param state The view state to use for the beneficiary detail dialogs.
+ * @param onAction A callback to handle the dialog actions.
+ */
@Composable
private fun BeneficiaryDialogs(
state: BeneficiaryDetailState,
@@ -100,6 +115,13 @@ private fun BeneficiaryDialogs(
}
}
+/**
+ * A composable function to display the beneficiary detail screen.
+ *
+ * @param state The view state to use for the beneficiary detail screen.
+ * @param onAction A callback to handle the actions from the view state.
+ * @param modifier The modifier to apply to the composable.
+ */
@Composable
private fun BeneficiaryDetailScreen(
state: BeneficiaryDetailState,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailViewModel.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailViewModel.kt
index 6f631ddc4..e2ea2bd0c 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailViewModel.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryDetailViewModel.kt
@@ -28,6 +28,13 @@ import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary
import org.mifos.mobile.core.ui.utils.BaseViewModel
import org.mifos.mobile.core.ui.utils.ScreenUiState
+/**
+ * A view model for the beneficiary detail screen.
+ *
+ * @param beneficiaryRepositoryImp The repository for beneficiary data.
+ * @param networkMonitor The network monitor to use for network status.
+ * @param savedStateHandle The saved state handle to use for navigation.
+ */
internal class BeneficiaryDetailViewModel(
private val beneficiaryRepositoryImp: BeneficiaryRepository,
private val networkMonitor: NetworkMonitor,
@@ -41,6 +48,9 @@ internal class BeneficiaryDetailViewModel(
},
) {
+ /**
+ * Initialize the view model.
+ */
init {
observeNetwork()
}
@@ -84,14 +94,27 @@ internal class BeneficiaryDetailViewModel(
}
}
+ /**
+ * Updates the view model state using the provided lambda transformation.
+ * @param update The lambda transformation to apply to the current state.
+ */
private fun updateState(update: (BeneficiaryDetailState) -> BeneficiaryDetailState) {
mutableStateFlow.update(update)
}
+ /**
+ * Updates the beneficiary dialog state in the view model state.
+ *
+ * @param dialogState The new dialog state to set. If null, the dialog state will be cleared.
+ */
private fun setDialogState(dialogState: BeneficiaryDetailState.DialogState?) {
updateState { it.copy(beneficiaryDialog = dialogState) }
}
+ /*
+ * Update the view model state to show a loading state and then
+ * an internal action to handle the list is sent.
+ * */
private fun loadBeneficiary() {
updateState {
it.copy(
@@ -105,6 +128,13 @@ internal class BeneficiaryDetailViewModel(
}
}
+ /**
+ * Handles the response from the beneficiary list API and updates the view model state accordingly.
+ * If the response is successful, the view model state is updated to show a success state and
+ * the beneficiary is updated to the one with the matching ID.
+ *
+ * @param beneficiary The response from the beneficiary list API.
+ */
private fun handleResponse(beneficiary: DataState>) {
when (beneficiary) {
DataState.Loading -> {
@@ -138,6 +168,14 @@ internal class BeneficiaryDetailViewModel(
}
}
+ /**
+ * Deletes a beneficiary with the given ID.
+ *
+ * This function updates the view model state to show an overlay and then
+ * sends an internal action to handle the response from the delete beneficiary API.
+ *
+ * @param beneficiaryId The ID of the beneficiary to delete.
+ */
private fun deleteBeneficiary(beneficiaryId: Long?) {
viewModelScope.launch {
updateState {
@@ -154,6 +192,16 @@ internal class BeneficiaryDetailViewModel(
}
}
+ /**
+ * Processes the result of the delete beneficiary API.
+ *
+ * If the response is loading, the view model state is updated to show an overlay.
+ * If the response is an error, the view model state is updated to show an error state and a dialog
+ * is shown with a generic error message.
+ * If the response is successful, the view model state is updated to navigate back to the previous screen.
+ *
+ * @param response The response from the delete beneficiary API.
+ */
private fun processDeleteBeneficiaryResult(response: DataState) {
viewModelScope.launch {
when (response) {
@@ -183,6 +231,11 @@ internal class BeneficiaryDetailViewModel(
}
}
+ /**
+ * Handles actions from the UI.
+ *
+ * @param action The action to handle.
+ */
override fun handleAction(action: BeneficiaryDetailAction) {
when (action) {
is BeneficiaryDetailAction.ReceiveNetworkStatus -> handleNetworkStatus(action.isOnline)
@@ -211,6 +264,9 @@ internal class BeneficiaryDetailViewModel(
}
}
+ /**
+ * Shows a confirmation dialog before deleting a beneficiary.
+ */
private fun showDeleteConfirmation() {
viewModelScope.launch {
val message = getString(Res.string.delete_beneficiary_confirmation)
@@ -223,6 +279,16 @@ internal class BeneficiaryDetailViewModel(
}
}
+/**
+ * Represents the state of the Beneficiary Detail screen.
+ *
+ * @property beneficiaryId The ID of the beneficiary to display.
+ * @property beneficiary The beneficiary to display.
+ * @property beneficiaryDialog The dialog state of the beneficiary detail screen.
+ * @property networkStatus The current network status of the device.
+ * @property uiState The current UI state of the beneficiary detail screen.
+ * @property showOverlay Whether to show the overlay or not.
+ */
data class BeneficiaryDetailState(
val beneficiaryId: Long = -1L,
val beneficiary: Beneficiary? = null,
@@ -239,22 +305,52 @@ data class BeneficiaryDetailState(
}
}
+/*
+* Represents the events that can be triggered from the Beneficiary Detail screen.
+*
+* @property NavigateBack Navigates back to the previous screen.
+* @property UpdateBeneficiary Updates the beneficiary with the given ID.
+* */
+
sealed interface BeneficiaryDetailEvent {
+
data object NavigateBack : BeneficiaryDetailEvent
+
data class UpdateBeneficiary(val beneficiaryId: Long) : BeneficiaryDetailEvent
}
+/*
+* Represents the actions that can be triggered from the Beneficiary Detail screen.
+*
+* @property OnRefresh Refreshes the beneficiary list.
+* @property OnUpdateBeneficiary Updates the beneficiary with the given ID.
+* @property DeleteBeneficiary Deletes the beneficiary with the given ID.
+* @property OnNavigate Navigates to the beneficiary list screen.
+* @property ErrorDialogDismiss Dismisses the error dialog.
+* @property ShowDeleteConfirmation Shows the delete confirmation dialog.
+* @property ReceiveNetworkStatus Receives the network status.
+* @property Internal Internal actions.
+* */
sealed interface BeneficiaryDetailAction {
+
data object OnRefresh : BeneficiaryDetailAction
+
data object OnUpdateBeneficiary : BeneficiaryDetailAction
+
data object DeleteBeneficiary : BeneficiaryDetailAction
+
data object OnNavigate : BeneficiaryDetailAction
+
data object ErrorDialogDismiss : BeneficiaryDetailAction
+
data object ShowDeleteConfirmation : BeneficiaryDetailAction
+
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryDetailAction
sealed interface Internal : BeneficiaryDetailAction {
+
data class ReceiveBeneficiaryResult(val result: DataState>) : Internal
+
data class ReceiveDeleteBeneficiary(val result: DataState) : Internal
}
}
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryNavRoute.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryNavRoute.kt
index f9a061c25..56f7c88c8 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryNavRoute.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryDetail/BeneficiaryNavRoute.kt
@@ -17,11 +17,23 @@ import androidx.navigation.NavOptions
import kotlinx.serialization.Serializable
import org.mifos.mobile.core.ui.composableWithSlideTransitions
+/**
+ * Represents the navigation route for the Beneficiary Detail screen.
+ *
+ * @property beneficiaryId The ID of the beneficiary to display.
+ */
+
@Serializable
data class BeneficiaryDetailNavRoute(
val beneficiaryId: Long = -1L,
)
+/**
+ * Navigates to the Beneficiary Detail screen.
+ *
+ * @param beneficiaryId The ID of the beneficiary to display.
+ * @param navOptions The navigation options to use for navigation.
+ */
fun NavController.navigateToBeneficiaryDetailScreen(
beneficiaryId: Long = -1L,
navOptions: NavOptions? = null,
@@ -29,6 +41,12 @@ fun NavController.navigateToBeneficiaryDetailScreen(
this.navigate(BeneficiaryDetailNavRoute(beneficiaryId), navOptions)
}
+/**
+ * Adds a destination to the navigation graph for the Beneficiary Detail screen.
+ *
+ * @param navigateBack a function to navigate back to the previous screen.
+ * @param updateBeneficiary a function to update a beneficiary with the given ID.
+ */
fun NavGraphBuilder.beneficiaryDetailScreenDestination(
navigateBack: () -> Unit,
updateBeneficiary: (beneficiaryId: Long) -> Unit,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListNavigation.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListNavigation.kt
index 7c4ec48b9..46671436d 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListNavigation.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListNavigation.kt
@@ -19,10 +19,21 @@ import org.mifos.mobile.core.ui.composableWithPushTransitions
@Serializable
data object BeneficiaryListNavRoute
+/**
+ * Navigates to the beneficiary list screen.
+ */
fun NavController.navigateToBeneficiaryListScreen() {
this.navigate(BeneficiaryListNavRoute)
}
+/**
+ * Adds a destination to the navigation graph for the beneficiary list screen.
+ *
+ * @param navigateBack a function to navigate back to the previous screen.
+ * @param addBeneficiaryClicked a function to navigate to the add beneficiary screen.
+ * @param onBeneficiaryItemClick a function to navigate to a beneficiary detail screen when a
+ * beneficiary item is clicked.
+ */
fun NavGraphBuilder.beneficiaryListScreen(
navigateBack: () -> Unit,
addBeneficiaryClicked: () -> Unit,
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListScreen.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListScreen.kt
index 38a028db3..cd852bdba 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListScreen.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/beneficiaryList/BeneficiaryListScreen.kt
@@ -75,7 +75,16 @@ import org.mifos.mobile.core.ui.component.MifosPoweredCard
import org.mifos.mobile.core.ui.component.MifosProgressIndicator
import org.mifos.mobile.core.ui.utils.EventsEffect
import org.mifos.mobile.core.ui.utils.ScreenUiState
-
+/**
+ * Composable function to display the beneficiary list screen.
+ *
+ * @param navigateBack The callback to navigate back to the previous screen.
+ * @param addBeneficiaryClicked The callback to navigate to the add beneficiary screen.
+ * @param onBeneficiaryItemClick The callback to navigate to a beneficiary detail screen when a
+ * beneficiary item is clicked.
+ * @param modifier The modifier to apply to the composable.
+ * @param viewModel The view model to use for the beneficiary list screen.
+ */
@Composable
internal fun BeneficiaryListScreen(
navigateBack: () -> Unit,
@@ -113,6 +122,13 @@ internal fun BeneficiaryListScreen(
)
}
+/**
+ * Composable function to display the dialogs for the beneficiary list screen.
+ *
+ * @param state the state of the beneficiary list screen.
+ * @param onAction the callback to handle user actions.
+ * @return a Unit or null if no dialog should be shown.
+ */
@Composable
private fun BeneficiaryListDialog(
state: BeneficiaryListState,
@@ -130,6 +146,13 @@ private fun BeneficiaryListDialog(
}
}
+/**
+ * Composable function to display the beneficiary list screen.
+ *
+ * @param state The state of the beneficiary list screen.
+ * @param onAction The callback to handle user actions.
+ * @param modifier The modifier to apply to the composable function.
+ */
@Composable
private fun BeneficiaryListScreen(
state: BeneficiaryListState,
@@ -158,6 +181,13 @@ private fun BeneficiaryListScreen(
}
}
+/**
+ * Composable function to display the beneficiary list content.
+ *
+ * @param state The state of the beneficiary list content.
+ * @param onAction The callback to handle user actions.
+ * @param modifier The modifier to apply to the composable function.
+ */
@Composable
fun BeneficiaryListContent(
state: BeneficiaryListState,
@@ -253,6 +283,12 @@ fun BeneficiaryListContent(
}
}
+/**
+ * A composable function to display the action bar with add and filter buttons.
+ *
+ * @param onAction The callback to handle user actions.
+ * @param modifier The modifier to apply to the composable function.
+ */
@Composable
internal fun ActionBar(
onAction: (BeneficiaryListAction) -> Unit,
@@ -313,6 +349,13 @@ internal fun ActionBar(
}
}
+/**
+ * A composable function to display the beneficiary filters.
+ *
+ * @param state The view state to use for the beneficiary filters.
+ * @param onAction A callback to handle user actions.
+ * @param modifier The modifier to apply to the composable function.
+ */
@Composable
internal fun BeneficiaryFilters(
state: BeneficiaryListState,
@@ -383,6 +426,17 @@ internal fun BeneficiaryFilters(
}
}
+/**
+ * A composable function to display a filter section.
+ *
+ * @param title The title of the filter section.
+ * @param selectedFilters The list of selected filters.
+ * @param isExpanded Whether the filter section is expanded or not.
+ * @param onToggle The callback to toggle the filter section.
+ * @param filters The list of filters to display.
+ * @param onCheckChanged The callback to handle the check changed event of the filters.
+ * @param modifier The modifier to apply to the composable.
+ */
@Composable
internal fun FilterSection(
title: String,
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 39b09b1b8..e908ec614 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
@@ -26,6 +26,12 @@ import org.mifos.mobile.core.model.entity.templates.beneficiary.BeneficiaryTempl
import org.mifos.mobile.core.ui.utils.BaseViewModel
import org.mifos.mobile.core.ui.utils.ScreenUiState
+/**
+ * ViewModel for BeneficiaryListScreen
+ *
+ * @param beneficiaryRepositoryImp The repository for beneficiary data.
+ * @param networkMonitor The monitor for network connectivity.
+ */
internal class BeneficiaryListViewModel(
private val beneficiaryRepositoryImp: BeneficiaryRepository,
private val networkMonitor: NetworkMonitor,
@@ -33,6 +39,16 @@ internal class BeneficiaryListViewModel(
initialState = BeneficiaryListState(),
) {
+ /**
+ * Initialize the view model.
+ */
+ init {
+ observeNetwork()
+ }
+
+ /**
+ * Initialize the view model.
+ */
init {
observeNetwork()
}
@@ -107,10 +123,18 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Update the state of the view model.
+ *
+ * @param update The function to update the state.
+ */
private fun updateState(update: (BeneficiaryListState) -> BeneficiaryListState) {
mutableStateFlow.update(update)
}
+ /**
+ * Fetch the list of beneficiaries from the repository.
+ */
private fun fetchBeneficiaries() {
updateState {
it.copy(
@@ -124,6 +148,11 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Process the list of beneficiaries.
+ *
+ * @param beneficiaryList The list of beneficiaries.
+ */
private fun processBeneficiaryList(beneficiaryList: DataState>) {
when (beneficiaryList) {
DataState.Loading -> updateState {
@@ -171,18 +200,32 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Handle the click on the add beneficiary button.
+ */
private fun handleAddBeneficiaryClick() {
sendEvent(BeneficiaryListEvent.AddBeneficiaryClicked)
}
+ /**
+ * Handle the click on a beneficiary item.
+ *
+ * @param action The action to handle.
+ */
private fun handleBeneficiaryItemClick(action: BeneficiaryListAction.OnBeneficiaryItemClick) {
sendEvent(BeneficiaryListEvent.BeneficiaryItemClick(action.position))
}
+ /**
+ * Handle the click on the navigate button.
+ */
private fun handleNavigate() {
sendEvent(BeneficiaryListEvent.Navigate)
}
+ /**
+ * Handle the click on the get filter results button.
+ */
private fun handleGetFilterResults() {
val filteredAccounts = if (state.selectedAccounts.isNotEmpty()) {
state.beneficiaries.filter {
@@ -209,6 +252,11 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Handle the change of the selected accounts.
+ *
+ * @param action The action to handle.
+ */
private fun handleAccountChange(action: BeneficiaryListAction.OnAccountChange) {
val currentAccounts = state.selectedAccounts
val updatedAccounts = if (currentAccounts.contains(action.account)) {
@@ -222,6 +270,11 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Handle the change of the selected offices.
+ *
+ * @param action The action to handle.
+ */
private fun handleOfficeChange(action: BeneficiaryListAction.OnOfficeChange) {
val currentOffices = state.selectedOffices
val updatedOffices = if (currentOffices.contains(action.office)) {
@@ -253,6 +306,9 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Handle the click on the toggle filter dialog button.
+ */
private fun handleToggleFilterDialog() {
updateState {
it.copy(
@@ -272,6 +328,9 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Reset the filters.
+ */
private fun resetFilters() {
updateState {
it.copy(
@@ -282,6 +341,9 @@ internal class BeneficiaryListViewModel(
}
}
+ /**
+ * Dismiss the dialog.
+ */
private fun dismissDialog() {
updateState {
it.copy(
@@ -291,6 +353,23 @@ internal class BeneficiaryListViewModel(
}
}
+/**
+ * State class for the beneficiary list screen.
+ *
+ * @param networkStatus The network status.
+ * @param isRefreshing Whether the screen is refreshing.
+ * @param beneficiaries The list of beneficiaries.
+ * @param template The beneficiary template.
+ * @param selectedAccounts The selected accounts.
+ * @param selectedOffices The selected offices.
+ * @param offices The list of offices.
+ * @param isEmpty Whether the list of beneficiaries is empty.
+ * @param isFilteredEmpty Whether the filtered list of beneficiaries is empty.
+ * @param filteredBeneficiaries The filtered list of beneficiaries.
+ * @param dialogState The dialog state.
+ * @param uiState The screen UI state.
+ */
+
data class BeneficiaryListState(
val networkStatus: Boolean = false,
val isRefreshing: Boolean = false,
@@ -313,28 +392,58 @@ data class BeneficiaryListState(
val isAnyFilterSelected = selectedAccounts.isNotEmpty() || selectedOffices.isNotEmpty()
}
+/**
+ * Action class for the beneficiary list screen.
+ *
+ * @param RefreshBeneficiaries Refresh the list of beneficiaries.
+ * @param OnAddBeneficiaryClicked Add a new beneficiary.
+ * @param OnBeneficiaryItemClick Click on a beneficiary item.
+ * @param OnNavigate Navigate to another screen.
+ * @param ToggleFilter Toggle the filter dialog.
+ * @param ResetFilters Reset the filters.
+ * @param GetFilterResults Get the filter results.
+ * @param DismissDialog Dismiss the dialog.
+ * @param OnAccountChange Change the selected account.
+ */
sealed interface BeneficiaryListAction {
+
data object RefreshBeneficiaries : BeneficiaryListAction
+
data object OnAddBeneficiaryClicked : BeneficiaryListAction
+
data class OnBeneficiaryItemClick(val position: Long) : BeneficiaryListAction
+
data object OnNavigate : BeneficiaryListAction
+
data object ToggleFilter : BeneficiaryListAction
+
data object ResetFilters : BeneficiaryListAction
+
data object GetFilterResults : BeneficiaryListAction
+
data object DismissDialog : BeneficiaryListAction
+
data class OnAccountChange(val account: String) : BeneficiaryListAction
+
data class OnOfficeChange(val office: String) : BeneficiaryListAction
+
data object LoadBeneficiaries : BeneficiaryListAction
data class ReceiveNetworkStatus(val isOnline: Boolean) : BeneficiaryListAction
sealed interface Internal : BeneficiaryListAction {
-
data class ReceiveBeneficiaryResult(
val beneficiaryList: DataState>,
) : Internal
}
}
+/**
+ * Event class for the beneficiary list screen.
+ *
+ * @param AddBeneficiaryClicked Add a new beneficiary.
+ * @param BeneficiaryItemClick Click on a beneficiary item.
+ * @param Navigate Navigate to another screen.
+ */
sealed interface BeneficiaryListEvent {
data object AddBeneficiaryClicked : BeneficiaryListEvent
data class BeneficiaryItemClick(val position: Long) : BeneficiaryListEvent
diff --git a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/navigation/BeneficiaryNavRoute.kt b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/navigation/BeneficiaryNavRoute.kt
index ad0616781..9431705ed 100644
--- a/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/navigation/BeneficiaryNavRoute.kt
+++ b/feature/beneficiary/src/commonMain/kotlin/org/mifos/mobile/feature/beneficiary/navigation/BeneficiaryNavRoute.kt
@@ -24,12 +24,42 @@ import org.mifos.mobile.feature.beneficiary.beneficiaryDetail.navigateToBenefici
import org.mifos.mobile.feature.beneficiary.beneficiaryList.BeneficiaryListNavRoute
import org.mifos.mobile.feature.beneficiary.beneficiaryList.beneficiaryListScreen
+/**
+ * Data class representing the navigation route for the beneficiary feature.
+ *
+ * @property BeneficiaryNavRoute the navigation route for the beneficiary feature.
+ */
@Serializable
data object BeneficiaryNavRoute
+/**
+ * Navigate to the beneficiary navigation graph.
+ *
+ * @param navOptions the navigation options to use when navigating to the beneficiary navigation graph.
+ */
fun NavController.navigateToBeneficiaryNavGraph(navOptions: NavOptions? = null) =
navigate(BeneficiaryNavRoute, navOptions)
+/**
+ * Adds a navigation graph for the beneficiary feature.
+ *
+ * The navigation graph has the following destinations:
+ * - Beneficiary List Screen: The screen that displays the list of all beneficiaries.
+ * - Manual Beneficiary Add Screen: The screen that allows the user to manually add a beneficiary.
+ * - Beneficiary Application Confirmation Screen: The screen that confirms the addition of a beneficiary.
+ * - Beneficiary Detail Screen: The screen that displays the details of a beneficiary.
+ *
+ * The navigation graph is structured as follows:
+ * - The Beneficiary List Screen is the starting point of the graph.
+ * - The Manual Beneficiary Add Screen is reachable from the Beneficiary List Screen.
+ * - The Beneficiary Application Confirmation Screen is reachable from the Manual Beneficiary Add Screen.
+ * - The Beneficiary Detail Screen is reachable from the Beneficiary List Screen and the Manual Beneficiary Add Screen.
+ *
+ * @param navController The navigation controller to use for navigation.
+ * @param navigateToQR A function to navigate to the QR code screen.
+ * @param navigateToStatusScreen A function to navigate to the status screen.
+ * @param navigateToAuthenticateScreen A function to navigate to the authentication screen.
+ */
fun NavGraphBuilder.beneficiaryNavGraph(
navController: NavController,
navigateToQR: () -> Unit,
diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock
index 0d38cc329..d13a271c5 100644
--- a/kotlin-js-store/yarn.lock
+++ b/kotlin-js-store/yarn.lock
@@ -2848,11 +2848,6 @@ ws@8.18.0, ws@^8.13.0:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
-ws@8.5.0:
- version "8.5.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
- integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==
-
ws@~8.17.1:
version "8.17.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b"