From c91ad3dbdfcd41e36b6983a3e70a36ddb553192a Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 6 Oct 2025 16:32:12 +0100 Subject: [PATCH 01/25] added the logic to BreadCrumnbNavBar --- .../com/mifos/core/ui/components/MifosBreadCrumb.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index 6abfffeba9e..8a9c5239537 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -81,6 +81,9 @@ fun MifosBreadcrumbNavBar( isActive = index == routes.lastIndex, onClick = { if (index != routes.lastIndex && route != "...") { + navController.previousBackStackEntry + ?.savedStateHandle + ?.set("shouldRefresh", true) navController.popBackStack(route, inclusive = false) } }, @@ -93,7 +96,10 @@ fun MifosBreadcrumbNavBar( } } - IconButton(onClick = { navController.popBackStack() }) { + IconButton(onClick = { + navController.previousBackStackEntry + ?.savedStateHandle + ?.set("shouldRefresh", true) }) { Icon( painter = painterResource(Res.drawable.bread_crumb_back_icon), contentDescription = "Back", From 1a1ae202d857d70def93db9f0a70994ad345ceb5 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 6 Oct 2025 16:38:02 +0100 Subject: [PATCH 02/25] added the logic to BreadCrumnbNavBar --- .../feature/client/clientEditProfile/ClientProfileEditScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index 3e38b32166a..149305ac78a 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -76,6 +76,7 @@ internal fun ClientProfileEditScreen( ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() + EventsEffect(viewModel.eventFlow) { event -> when (event) { ClientProfileEditEvent.NavigateBack -> onNavigateBack() From 8dfdf6550b249a1d102953a866ea33cfeec70da7 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 6 Oct 2025 16:55:22 +0100 Subject: [PATCH 03/25] ClientProfileDetailsScreen fixed --- .../mifos/core/ui/components/MifosBreadCrumb.kt | 3 ++- .../ClientProfileDetailsScreen.kt | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index 8a9c5239537..a7ba8c80ddb 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -99,7 +99,8 @@ fun MifosBreadcrumbNavBar( IconButton(onClick = { navController.previousBackStackEntry ?.savedStateHandle - ?.set("shouldRefresh", true) }) { + ?.set("shouldRefresh", true) + navController.popBackStack()}) { Icon( painter = painterResource(Res.drawable.bread_crumb_back_icon), contentDescription = "Back", diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index 68250c546c9..17109d80d2f 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -44,7 +44,9 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text 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 import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -87,6 +89,20 @@ internal fun ClientProfileDetailsScreen( viewModel: ClientProfileDetailsViewModel = koinViewModel(), ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() + val currentBackStackEntry = navController.currentBackStackEntry + val savedStateHandle = currentBackStackEntry?.savedStateHandle + + val profileUpdated by savedStateHandle + ?.getStateFlow("shouldRefresh", false) + ?.collectAsStateWithLifecycle(initialValue = false) + ?: remember { mutableStateOf(false) } + + LaunchedEffect(profileUpdated) { + if (profileUpdated) { + viewModel.trySendAction(ClientProfileDetailsAction.OnRetry) + savedStateHandle?.set("shouldRefresh", false) // reset after refresh + } + } EventsEffect(viewModel.eventFlow) { event -> when (event) { From 749f570408a5c8f6ff905c6ca1bf8e828e0791e8 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 6 Oct 2025 17:03:45 +0100 Subject: [PATCH 04/25] Client Profile Screen fixed --- .../client/clientProfile/ClientProfileScreen.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 104271d4da9..99e6716a79c 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -27,7 +27,9 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text 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 import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -41,6 +43,7 @@ import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.util.EventsEffect import com.mifos.core.ui.util.TextUtil +import com.mifos.feature.client.clientDetailsProfile.ClientProfileDetailsAction import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard import com.mifos.feature.client.clientProfile.components.clientsActionItems @@ -61,6 +64,20 @@ internal fun ClientProfileScreen( viewModel: ClientProfileViewModel = koinViewModel(), ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() + val currentBackStackEntry = navController.currentBackStackEntry + val savedStateHandle = currentBackStackEntry?.savedStateHandle + + val profileUpdated by savedStateHandle + ?.getStateFlow("shouldRefresh", false) + ?.collectAsStateWithLifecycle(initialValue = false) + ?: remember { mutableStateOf(false) } + + LaunchedEffect(profileUpdated) { + if (profileUpdated) { + viewModel.trySendAction(ClientProfileAction.OnRetry) + savedStateHandle?.set("shouldRefresh", false) // reset after refresh + } + } EventsEffect(viewModel.eventFlow) { event -> when (event) { From c9070312b03ef7997fcb5c1013820e2408b32ca6 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 6 Oct 2025 17:26:16 +0100 Subject: [PATCH 05/25] problem fixed --- cmp-android/build.gradle.kts | 3 ++- .../app/ComponentActivityExtensions.kt | 24 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cmp-android/build.gradle.kts b/cmp-android/build.gradle.kts index 1844bc542d4..9fa0f14114d 100644 --- a/cmp-android/build.gradle.kts +++ b/cmp-android/build.gradle.kts @@ -7,6 +7,7 @@ * * See https://github.com/openMF/android-client/blob/master/LICENSE.md */ + import org.mifos.MifosBuildType import org.mifos.dynamicVersion @@ -153,4 +154,4 @@ dependencyGuard { modules = true tree = true } -} \ No newline at end of file +} diff --git a/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt b/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt index 97ab3d3eb31..ce320435cd1 100644 --- a/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt +++ b/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt @@ -39,9 +39,7 @@ private val SCRIM_COLOR: Int = Color.TRANSPARENT * [here](https://github.com/android/nowinandroid/blob/689ef92e41427ab70f82e2c9fe59755441deae92/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt#L94). */ @Suppress("MaxLineLength") -fun ComponentActivity.setupEdgeToEdge( - appThemeFlow: Flow, -) { +fun ComponentActivity.setupEdgeToEdge(appThemeFlow: Flow) { lifecycleScope.launch { lifecycle.repeatOnLifecycle(state = Lifecycle.State.STARTED) { combine( @@ -55,12 +53,13 @@ fun ComponentActivity.setupEdgeToEdge( // This handles all the settings to go edge-to-edge. We are using a transparent // scrim for system bars and switching between "light" and "dark" based on the // system and internal app theme settings. - val style = SystemBarStyle.auto( - darkScrim = SCRIM_COLOR, - lightScrim = SCRIM_COLOR, - // Disabling Dark Mode for this app - detectDarkMode = { false }, - ) + val style = + SystemBarStyle.auto( + darkScrim = SCRIM_COLOR, + lightScrim = SCRIM_COLOR, + // Disabling Dark Mode for this app + detectDarkMode = { false }, + ) enableEdgeToEdge(statusBarStyle = style, navigationBarStyle = style) } } @@ -75,9 +74,10 @@ fun ComponentActivity.setupEdgeToEdge( private fun ComponentActivity.isSystemInDarkModeFlow(): Flow = callbackFlow { channel.trySend(element = resources.configuration.isSystemInDarkMode) - val listener = Consumer { - channel.trySend(element = it.isSystemInDarkMode) - } + val listener = + Consumer { + channel.trySend(element = it.isSystemInDarkMode) + } addOnConfigurationChangedListener(listener = listener) awaitClose { removeOnConfigurationChangedListener(listener = listener) } } From 586119e7c74025785f57587ce21aa751541b202d Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 6 Oct 2025 17:40:05 +0100 Subject: [PATCH 06/25] after running the commands --- .../kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt | 3 ++- .../client/clientEditProfile/ClientProfileEditScreen.kt | 1 - .../mifos/feature/client/clientProfile/ClientProfileScreen.kt | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index a7ba8c80ddb..16b6e5bcd09 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -100,7 +100,8 @@ fun MifosBreadcrumbNavBar( navController.previousBackStackEntry ?.savedStateHandle ?.set("shouldRefresh", true) - navController.popBackStack()}) { + navController.popBackStack() + }) { Icon( painter = painterResource(Res.drawable.bread_crumb_back_icon), contentDescription = "Back", diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index 149305ac78a..3e38b32166a 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -76,7 +76,6 @@ internal fun ClientProfileEditScreen( ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - EventsEffect(viewModel.eventFlow) { event -> when (event) { ClientProfileEditEvent.NavigateBack -> onNavigateBack() diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 99e6716a79c..bffe4ca96fe 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -43,7 +43,6 @@ import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.util.EventsEffect import com.mifos.core.ui.util.TextUtil -import com.mifos.feature.client.clientDetailsProfile.ClientProfileDetailsAction import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard import com.mifos.feature.client.clientProfile.components.clientsActionItems From 931df6e2c8705a40a0519daf5699cefc7a3bc072 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Wed, 8 Oct 2025 17:30:05 +0100 Subject: [PATCH 07/25] Added delay... --- .../clientEditProfile/ClientProfileEditScreen.kt | 14 ++++++++++++-- .../ClientProfileEditViewModel.kt | 12 ++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index 3e38b32166a..baff94a9749 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -76,14 +76,14 @@ internal fun ClientProfileEditScreen( ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - EventsEffect(viewModel.eventFlow) { event -> + /*EventsEffect(viewModel.eventFlow) { event -> when (event) { ClientProfileEditEvent.NavigateBack -> onNavigateBack() ClientProfileEditEvent.OnSaveSuccess -> { onNavigateBack() } } - } + }*/ ClientProfileEditScaffold( modifier = modifier, @@ -206,6 +206,16 @@ private fun ClientProfileEditDialogs( ) } + is ClientProfileEditState.DialogState.Success -> { + MifosBasicDialog( + title = "Success", + content = { Text("Your profile image has been updated successfully!") }, + confirmText = "Done", + onConfirm = { onAction(ClientProfileEditAction.DismissModalBottomSheet) }, + onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) }, + ) + } + ClientProfileEditState.DialogState.ShowDeleteDialog -> { MifosBasicDialog( visibilityState = BasicDialogState.Shown( diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index cf2e40fad8a..cf57c3805c2 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -21,6 +21,7 @@ import com.mifos.core.ui.util.BaseViewModel import com.mifos.core.ui.util.imageToByteArray import com.mifos.core.ui.util.multipartRequestBody import com.mifos.feature.client.utils.toPlatformFile +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -123,6 +124,7 @@ internal class ClientProfileEditViewModel( } } + is DataState.Loading -> { mutableStateFlow.update { it.copy( @@ -132,13 +134,15 @@ internal class ClientProfileEditViewModel( } is DataState.Success -> { + + loadImage(route.id) + delay(2000) mutableStateFlow.update { it.copy( - dialogState = ClientProfileEditState.DialogState.Loading, + dialogState = ClientProfileEditState.DialogState.Success, openImagePicker = false, ) } - loadImage(route.id) } } } @@ -179,14 +183,18 @@ data class ClientProfileEditState( sealed interface DialogState { data class Error(val message: String) : DialogState data object Loading : DialogState + data object Success : DialogState data object ShowDeleteDialog : DialogState data object ShowUploadOptions : DialogState + } } sealed interface ClientProfileEditEvent { data object NavigateBack : ClientProfileEditEvent data object OnSaveSuccess : ClientProfileEditEvent + data class OnError(val message: String) : ClientProfileEditEvent + } sealed interface ClientProfileEditAction { From 503e411badb5e7fc9f60e8879cf83b28a6ac781b Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Wed, 8 Oct 2025 17:43:17 +0100 Subject: [PATCH 08/25] no dialog but the state is being updated in the previous screen --- .../client/clientEditProfile/ClientProfileEditViewModel.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index cf57c3805c2..cb14f0b6c4d 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -134,15 +134,15 @@ internal class ClientProfileEditViewModel( } is DataState.Success -> { - - loadImage(route.id) - delay(2000) mutableStateFlow.update { it.copy( dialogState = ClientProfileEditState.DialogState.Success, openImagePicker = false, ) } + + loadImage(route.id) + } } } From 4f00921832fcd994fed521f2b40504a7c5e95adb Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Thu, 9 Oct 2025 08:57:55 +0100 Subject: [PATCH 09/25] Issue resolved --- .../ClientProfileEditViewModel.kt | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index cb14f0b6c4d..da9f65c4996 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -134,15 +134,22 @@ internal class ClientProfileEditViewModel( } is DataState.Success -> { - mutableStateFlow.update { - it.copy( - dialogState = ClientProfileEditState.DialogState.Success, - openImagePicker = false, - ) + viewModelScope.launch { + clientDetailsRepo.getImage(route.id).collect { result -> + when (result) { + is DataState.Success -> mutableStateFlow.update { + it.copy( + profileImage = imageToByteArray(result.data), + dialogState = ClientProfileEditState.DialogState.Success, + ) + } + is DataState.Loading -> mutableStateFlow.update { + it.copy(dialogState = ClientProfileEditState.DialogState.Loading) + } + else -> Unit + } + } } - - loadImage(route.id) - } } } From b4fbffebf84d85b5967dd881caad6e7390dbc777 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Thu, 9 Oct 2025 15:42:13 +0100 Subject: [PATCH 10/25] Created a customized dialog for MifosDialogStates --- .../component/MifosBasicDialog.kt | 74 +++++++++++++++++++ .../ClientProfileEditScreen.kt | 22 +++--- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt b/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt index abef577a603..3ac0bdd5db4 100644 --- a/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt +++ b/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt @@ -15,8 +15,11 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -32,6 +35,10 @@ import com.mifos.core.designsystem.theme.MifosTypography import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.PreviewParameter import org.jetbrains.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material.icons.filled.Error +import androidx.compose.ui.graphics.Color @Composable fun MifosBasicDialog( @@ -197,6 +204,73 @@ fun MifosBasicDialog( ) } + + +enum class MifosDialogStatus { SUCCESS, FAILURE } + +@Composable +fun MifosStatusDialog( + status: MifosDialogStatus, + message: String, + onDismissRequest: () -> Unit +) { + data class DialogUI( + val title: String, + val icon: androidx.compose.ui.graphics.vector.ImageVector, + val color: Color + ) + + val dialogUI: DialogUI = when (status) { + MifosDialogStatus.SUCCESS -> DialogUI( + title = "Success", + icon = Icons.Filled.CheckCircle, + color = Color(0xFF4CAF50) + ) + MifosDialogStatus.FAILURE -> DialogUI( + title = "Error", + icon = Icons.Filled.Error, + color = Color(0xFFF44336) + ) + } + + AlertDialog( + onDismissRequest = onDismissRequest, + icon = { + Icon( + imageVector = dialogUI.icon, + contentDescription = dialogUI.title, + tint = dialogUI.color, + modifier = Modifier + .size(84.dp) + .padding(bottom = 4.dp) + ) + }, + title = { + Text( + text = dialogUI.title, + style = MaterialTheme.typography.titleLarge + ) + }, + text = { + Text( + text = message, + style = MaterialTheme.typography.bodyMedium + ) + }, + confirmButton = { + Button( + onClick = onDismissRequest, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + Text("Continue") + } + }, + modifier = Modifier.testTag("MifosStatusDialog") + ) +} + @Preview @Composable private fun MifosBasicDialog_preview() { diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index baff94a9749..b2bd760a793 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -47,9 +47,12 @@ import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.mifos.core.designsystem.component.BasicDialogState +import com.mifos.core.designsystem.component.DialogStatus import com.mifos.core.designsystem.component.MifosBasicDialog +import com.mifos.core.designsystem.component.MifosDialogStatus import com.mifos.core.designsystem.component.MifosOutlinedButton import com.mifos.core.designsystem.component.MifosScaffold +import com.mifos.core.designsystem.component.MifosStatusDialog import com.mifos.core.designsystem.component.MifosTextButton import com.mifos.core.designsystem.icon.MifosIcons import com.mifos.core.designsystem.theme.DesignToken @@ -198,21 +201,18 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Loading -> MifosProgressIndicator() is ClientProfileEditState.DialogState.Error -> { - MifosErrorComponent( - isNetworkConnected = state.networkConnection, - message = state.dialogState.message, - isRetryEnabled = true, - onRetry = onRetry, + MifosStatusDialog( + status = MifosDialogStatus.FAILURE, + message = "Failed to update profile. Please try again.", + onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } is ClientProfileEditState.DialogState.Success -> { - MifosBasicDialog( - title = "Success", - content = { Text("Your profile image has been updated successfully!") }, - confirmText = "Done", - onConfirm = { onAction(ClientProfileEditAction.DismissModalBottomSheet) }, - onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) }, + MifosStatusDialog( + status = MifosDialogStatus.SUCCESS, + message = "Profile updated successfully!", + onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } From 3289eb54c53026d4f30952b594bb7a4e77e0567e Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Fri, 10 Oct 2025 16:29:04 +0100 Subject: [PATCH 11/25] string resource not working --- cmp-android/src/main/res/values/strings.xml | 4 ++++ .../client/clientEditProfile/ClientProfileEditScreen.kt | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cmp-android/src/main/res/values/strings.xml b/cmp-android/src/main/res/values/strings.xml index c81f00fb228..cd2a156ec56 100644 --- a/cmp-android/src/main/res/values/strings.xml +++ b/cmp-android/src/main/res/values/strings.xml @@ -421,6 +421,10 @@ No more Clients Available No more Groups Available No more Centers Available + Your profile image has been updated successfully! + We couldn’t update your profile image. Please try again. + should_refresh + Number of repayments diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index b2bd760a793..9983dcd5fcf 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -17,7 +17,10 @@ import androidclient.feature.client.generated.resources.choose_from_option import androidclient.feature.client.generated.resources.delete_dialog_message import androidclient.feature.client.generated.resources.delete_dialog_title import androidclient.feature.client.generated.resources.delete_photo +import androidclient.feature.client.generated.resources.dialog_continue import androidclient.feature.client.generated.resources.edit_profile_title +import androidclient.feature.client.generated.resources.feature_client_Image_Upload_Failed +import androidclient.feature.client.generated.resources.feature_client_Image_Upload_Successful import androidclient.feature.client.generated.resources.from_camera import androidclient.feature.client.generated.resources.from_gallery import androidclient.feature.client.generated.resources.remove @@ -47,7 +50,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.mifos.core.designsystem.component.BasicDialogState -import com.mifos.core.designsystem.component.DialogStatus import com.mifos.core.designsystem.component.MifosBasicDialog import com.mifos.core.designsystem.component.MifosDialogStatus import com.mifos.core.designsystem.component.MifosOutlinedButton @@ -203,7 +205,7 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Error -> { MifosStatusDialog( status = MifosDialogStatus.FAILURE, - message = "Failed to update profile. Please try again.", + message = stringResource(Res.string.feature_client_Image_Upload_Failed), onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } @@ -211,7 +213,7 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Success -> { MifosStatusDialog( status = MifosDialogStatus.SUCCESS, - message = "Profile updated successfully!", + message = stringResource(Res.string.feature_client_profile_update_success_message), onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } From 8007673d5287285afae906660e84482c9cae471e Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Sun, 12 Oct 2025 06:05:57 +0100 Subject: [PATCH 12/25] need to make the constant global within the client module --- cmp-android/src/main/res/values/strings.xml | 3 --- .../mifos/core/ui/components/MifosBreadCrumb.kt | 2 +- .../values/strings.commonMain.cvr | 0 .../composeResources/values/strings.xml | 3 +++ .../ClientProfileDetailsScreen.kt | 6 ++++-- .../clientEditProfile/ClientProfileEditScreen.kt | 15 ++++----------- .../ClientProfileEditViewModel.kt | 4 ++++ .../client/clientProfile/ClientProfileScreen.kt | 5 +++-- 8 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 feature/client/src/commonMain/composeResources/values/strings.commonMain.cvr diff --git a/cmp-android/src/main/res/values/strings.xml b/cmp-android/src/main/res/values/strings.xml index cd2a156ec56..44bfc8a2189 100644 --- a/cmp-android/src/main/res/values/strings.xml +++ b/cmp-android/src/main/res/values/strings.xml @@ -421,9 +421,6 @@ No more Clients Available No more Groups Available No more Centers Available - Your profile image has been updated successfully! - We couldn’t update your profile image. Please try again. - should_refresh Number of repayments diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index 0a6e711aa6f..c1647319965 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -83,7 +83,7 @@ fun MifosBreadcrumbNavBar( if (index != routes.lastIndex && route != "...") { navController.previousBackStackEntry ?.savedStateHandle - ?.set("shouldRefresh", true) + ?.set(SavedStateKeys.PROFILE_SHOULD_REFRESH_KEY, true) navController.popBackStack(route, inclusive = false) } }, diff --git a/feature/client/src/commonMain/composeResources/values/strings.commonMain.cvr b/feature/client/src/commonMain/composeResources/values/strings.commonMain.cvr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/feature/client/src/commonMain/composeResources/values/strings.xml b/feature/client/src/commonMain/composeResources/values/strings.xml index 8fca3f4cb18..8b3ce438d5a 100644 --- a/feature/client/src/commonMain/composeResources/values/strings.xml +++ b/feature/client/src/commonMain/composeResources/values/strings.xml @@ -387,6 +387,9 @@ I Confirm Cancel Continue + Your profile image has been updated successfully! + We couldn’t update your profile image. Please try again. + should refresh Assign Staff diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index 2666ba89f12..064c9d5ae73 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -19,6 +19,7 @@ import androidclient.feature.client.generated.resources.dialog_continue import androidclient.feature.client.generated.resources.dialog_unassign_message import androidclient.feature.client.generated.resources.dismiss_text import androidclient.feature.client.generated.resources.pen_icon +import androidclient.feature.client.generated.resources.profile_should_refresh import androidclient.feature.client.generated.resources.scroll_for_more_options import androidclient.feature.client.generated.resources.staff_unassign_failure_title import androidclient.feature.client.generated.resources.staff_unassign_success_message @@ -69,6 +70,7 @@ import com.mifos.core.ui.util.TextUtil import com.mifos.feature.client.clientDetailsProfile.components.ClientDetailsProfile import com.mifos.feature.client.clientDetailsProfile.components.ClientProfileDetailsActionItem import com.mifos.feature.client.clientDetailsProfile.components.clientsDetailsActionItems +import com.mifos.feature.client.clientEditProfile.ClientProfileKeys import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel @@ -94,14 +96,14 @@ internal fun ClientProfileDetailsScreen( val savedStateHandle = currentBackStackEntry?.savedStateHandle val profileUpdated by savedStateHandle - ?.getStateFlow("shouldRefresh", false) + ?.getStateFlow(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) ?.collectAsStateWithLifecycle(initialValue = false) ?: remember { mutableStateOf(false) } LaunchedEffect(profileUpdated) { if (profileUpdated) { viewModel.trySendAction(ClientProfileDetailsAction.OnRetry) - savedStateHandle?.set("shouldRefresh", false) // reset after refresh + savedStateHandle?.set(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index 9983dcd5fcf..fa9e16cd445 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -23,8 +23,10 @@ import androidclient.feature.client.generated.resources.feature_client_Image_Upl import androidclient.feature.client.generated.resources.feature_client_Image_Upload_Successful import androidclient.feature.client.generated.resources.from_camera import androidclient.feature.client.generated.resources.from_gallery +import androidclient.feature.client.generated.resources.profile_update_error_message import androidclient.feature.client.generated.resources.remove import androidclient.feature.client.generated.resources.update_profile_photo_message +import androidclient.feature.client.generated.resources.update_success_message import androidclient.feature.client.generated.resources.upload_new_photo import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -81,15 +83,6 @@ internal fun ClientProfileEditScreen( ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - /*EventsEffect(viewModel.eventFlow) { event -> - when (event) { - ClientProfileEditEvent.NavigateBack -> onNavigateBack() - ClientProfileEditEvent.OnSaveSuccess -> { - onNavigateBack() - } - } - }*/ - ClientProfileEditScaffold( modifier = modifier, state = state, @@ -205,7 +198,7 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Error -> { MifosStatusDialog( status = MifosDialogStatus.FAILURE, - message = stringResource(Res.string.feature_client_Image_Upload_Failed), + message = stringResource(Res.string.profile_update_error_message), onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } @@ -213,7 +206,7 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Success -> { MifosStatusDialog( status = MifosDialogStatus.SUCCESS, - message = stringResource(Res.string.feature_client_profile_update_success_message), + message = stringResource(Res.string.update_success_message), onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index da9f65c4996..33b703e8b64 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -217,3 +217,7 @@ sealed interface ClientProfileEditAction { data class UpdateImagePicker(val status: Boolean) : ClientProfileEditAction data class OnImageSelected(val image: ImageBitmap) : ClientProfileEditAction } + +object SavedStateKeys { + const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" +} diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index bffe4ca96fe..66794d66aff 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -43,6 +43,7 @@ import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.util.EventsEffect import com.mifos.core.ui.util.TextUtil +import com.mifos.feature.client.clientEditProfile.ClientProfileKeys import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard import com.mifos.feature.client.clientProfile.components.clientsActionItems @@ -67,14 +68,14 @@ internal fun ClientProfileScreen( val savedStateHandle = currentBackStackEntry?.savedStateHandle val profileUpdated by savedStateHandle - ?.getStateFlow("shouldRefresh", false) + ?.getStateFlow(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) ?.collectAsStateWithLifecycle(initialValue = false) ?: remember { mutableStateOf(false) } LaunchedEffect(profileUpdated) { if (profileUpdated) { viewModel.trySendAction(ClientProfileAction.OnRetry) - savedStateHandle?.set("shouldRefresh", false) // reset after refresh + savedStateHandle?.set(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) // reset after refresh } } From a8073d85106cd0b034d217cdcae5ee368408cb63 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Sun, 12 Oct 2025 20:51:11 +0100 Subject: [PATCH 13/25] Added state constant --- .../clientDetailsProfile/ClientProfileDetailsScreen.kt | 5 +++-- .../client/clientEditProfile/ClientProfileEditViewModel.kt | 3 --- .../feature/client/clientProfile/ClientProfileScreen.kt | 5 +++-- .../kotlin/com/mifos/feature/client/utils/Constants.kt | 3 +++ 4 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index 064c9d5ae73..a1ab9036126 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -71,6 +71,7 @@ import com.mifos.feature.client.clientDetailsProfile.components.ClientDetailsPro import com.mifos.feature.client.clientDetailsProfile.components.ClientProfileDetailsActionItem import com.mifos.feature.client.clientDetailsProfile.components.clientsDetailsActionItems import com.mifos.feature.client.clientEditProfile.ClientProfileKeys +import com.mifos.feature.client.utils.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel @@ -96,14 +97,14 @@ internal fun ClientProfileDetailsScreen( val savedStateHandle = currentBackStackEntry?.savedStateHandle val profileUpdated by savedStateHandle - ?.getStateFlow(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) + ?.getStateFlow(PROFILE_SHOULD_REFRESH_KEY, false) ?.collectAsStateWithLifecycle(initialValue = false) ?: remember { mutableStateOf(false) } LaunchedEffect(profileUpdated) { if (profileUpdated) { viewModel.trySendAction(ClientProfileDetailsAction.OnRetry) - savedStateHandle?.set(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) + savedStateHandle?.set(PROFILE_SHOULD_REFRESH_KEY, false) } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index 33b703e8b64..393ae91d2a2 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -218,6 +218,3 @@ sealed interface ClientProfileEditAction { data class OnImageSelected(val image: ImageBitmap) : ClientProfileEditAction } -object SavedStateKeys { - const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" -} diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 66794d66aff..26f2998ca3d 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -47,6 +47,7 @@ import com.mifos.feature.client.clientEditProfile.ClientProfileKeys import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard import com.mifos.feature.client.clientProfile.components.clientsActionItems +import com.mifos.feature.client.utils.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel @@ -68,14 +69,14 @@ internal fun ClientProfileScreen( val savedStateHandle = currentBackStackEntry?.savedStateHandle val profileUpdated by savedStateHandle - ?.getStateFlow(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) + ?.getStateFlow(PROFILE_SHOULD_REFRESH_KEY, false) ?.collectAsStateWithLifecycle(initialValue = false) ?: remember { mutableStateOf(false) } LaunchedEffect(profileUpdated) { if (profileUpdated) { viewModel.trySendAction(ClientProfileAction.OnRetry) - savedStateHandle?.set(ClientProfileKeys.PROFILE_SHOULD_REFRESH_KEY, false) // reset after refresh + savedStateHandle?.set(PROFILE_SHOULD_REFRESH_KEY, false) // reset after refresh } } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt new file mode 100644 index 00000000000..5998c622454 --- /dev/null +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt @@ -0,0 +1,3 @@ +package com.mifos.feature.client.utils + +internal const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" \ No newline at end of file From ee529265b420f6c5c35280fda9a635464ffbecb6 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 13 Oct 2025 04:33:08 +0100 Subject: [PATCH 14/25] code clean up --- .../kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt | 5 +++-- .../commonMain/kotlin/com/mifos/core/ui/util/Constants.kt | 3 +++ .../clientDetailsProfile/ClientProfileDetailsScreen.kt | 1 - .../feature/client/clientProfile/ClientProfileScreen.kt | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index c1647319965..251bdc957c7 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -30,6 +30,7 @@ import androidx.navigation.NavController import com.mifos.core.designsystem.theme.DesignToken import com.mifos.core.designsystem.theme.MifosTheme import com.mifos.core.designsystem.theme.MifosTypography +import com.mifos.core.ui.util.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.ui.tooling.preview.Preview @@ -83,7 +84,7 @@ fun MifosBreadcrumbNavBar( if (index != routes.lastIndex && route != "...") { navController.previousBackStackEntry ?.savedStateHandle - ?.set(SavedStateKeys.PROFILE_SHOULD_REFRESH_KEY, true) + ?.set(PROFILE_SHOULD_REFRESH_KEY, true) navController.popBackStack(route, inclusive = false) } }, @@ -100,7 +101,7 @@ fun MifosBreadcrumbNavBar( IconButton(onClick = { navController.previousBackStackEntry ?.savedStateHandle - ?.set("shouldRefresh", true) + ?.set(PROFILE_SHOULD_REFRESH_KEY, true) navController.popBackStack() }) { Icon( diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt new file mode 100644 index 00000000000..1b7d883b297 --- /dev/null +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt @@ -0,0 +1,3 @@ +package com.mifos.core.ui.util + +internal const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index a1ab9036126..c708f05cbe8 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -70,7 +70,6 @@ import com.mifos.core.ui.util.TextUtil import com.mifos.feature.client.clientDetailsProfile.components.ClientDetailsProfile import com.mifos.feature.client.clientDetailsProfile.components.ClientProfileDetailsActionItem import com.mifos.feature.client.clientDetailsProfile.components.clientsDetailsActionItems -import com.mifos.feature.client.clientEditProfile.ClientProfileKeys import com.mifos.feature.client.utils.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 26f2998ca3d..7a56ad607a2 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -43,7 +43,6 @@ import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.util.EventsEffect import com.mifos.core.ui.util.TextUtil -import com.mifos.feature.client.clientEditProfile.ClientProfileKeys import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard import com.mifos.feature.client.clientProfile.components.clientsActionItems From 24b46016d5a05e17bbbd2f57db0117f3b3cf9500 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 13 Oct 2025 05:23:59 +0100 Subject: [PATCH 15/25] added more string resources --- .../commonMain/composeResources/values/strings.xml | 4 ++++ .../designsystem/component/MifosBasicDialog.kt | 14 ++++++++++---- .../commonMain/composeResources/values/strings.xml | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/core/designsystem/src/commonMain/composeResources/values/strings.xml b/core/designsystem/src/commonMain/composeResources/values/strings.xml index 43820ac5143..2bdfff95763 100644 --- a/core/designsystem/src/commonMain/composeResources/values/strings.xml +++ b/core/designsystem/src/commonMain/composeResources/values/strings.xml @@ -16,6 +16,10 @@ Enter a tenant Cancel Save + Success + Failure + Continue + MifosStatusDialog Mifos diff --git a/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt b/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt index 3ac0bdd5db4..80556b56ab8 100644 --- a/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt +++ b/core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBasicDialog.kt @@ -39,6 +39,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.Error import androidx.compose.ui.graphics.Color +import core.designsystem.generated.resources.Res +import core.designsystem.generated.resources.core_designsystem_dialog_continue +import core.designsystem.generated.resources.core_designsystem_dialog_failure +import core.designsystem.generated.resources.core_designsystem_dialog_success +import core.designsystem.generated.resources.core_designsystem_mifosStatusDialog +import org.jetbrains.compose.resources.stringResource @Composable fun MifosBasicDialog( @@ -222,12 +228,12 @@ fun MifosStatusDialog( val dialogUI: DialogUI = when (status) { MifosDialogStatus.SUCCESS -> DialogUI( - title = "Success", + title = stringResource(Res.string.core_designsystem_dialog_success), icon = Icons.Filled.CheckCircle, color = Color(0xFF4CAF50) ) MifosDialogStatus.FAILURE -> DialogUI( - title = "Error", + title = stringResource(Res.string.core_designsystem_dialog_failure), icon = Icons.Filled.Error, color = Color(0xFFF44336) ) @@ -264,10 +270,10 @@ fun MifosStatusDialog( .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp) ) { - Text("Continue") + Text(stringResource(Res.string.core_designsystem_dialog_continue)) } }, - modifier = Modifier.testTag("MifosStatusDialog") + modifier = Modifier.testTag(stringResource(Res.string.core_designsystem_mifosStatusDialog)) ) } diff --git a/feature/client/src/commonMain/composeResources/values/strings.xml b/feature/client/src/commonMain/composeResources/values/strings.xml index 8b3ce438d5a..4e0e16d6aa7 100644 --- a/feature/client/src/commonMain/composeResources/values/strings.xml +++ b/feature/client/src/commonMain/composeResources/values/strings.xml @@ -390,6 +390,8 @@ Your profile image has been updated successfully! We couldn’t update your profile image. Please try again. should refresh + Success + Failure Assign Staff From 1fd2c45ae27cb830842f7c1a5adb82df0cc79a80 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Thu, 27 Nov 2025 19:58:33 +0100 Subject: [PATCH 16/25] Progress; string resource might not be correct --- .../client/clientEditProfile/ClientProfileEditScreen.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index fa9e16cd445..79c04a1db2e 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -21,6 +21,7 @@ import androidclient.feature.client.generated.resources.dialog_continue import androidclient.feature.client.generated.resources.edit_profile_title import androidclient.feature.client.generated.resources.feature_client_Image_Upload_Failed import androidclient.feature.client.generated.resources.feature_client_Image_Upload_Successful +import androidclient.feature.client.generated.resources.feature_client_error import androidclient.feature.client.generated.resources.from_camera import androidclient.feature.client.generated.resources.from_gallery import androidclient.feature.client.generated.resources.profile_update_error_message @@ -198,7 +199,7 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Error -> { MifosStatusDialog( status = MifosDialogStatus.FAILURE, - message = stringResource(Res.string.profile_update_error_message), + message = stringResource(Res.string.feature_client_error), onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } @@ -206,7 +207,7 @@ private fun ClientProfileEditDialogs( is ClientProfileEditState.DialogState.Success -> { MifosStatusDialog( status = MifosDialogStatus.SUCCESS, - message = stringResource(Res.string.update_success_message), + message = stringResource(Res.string.feature_client_Image_Upload_Successful), onDismissRequest = { onAction(ClientProfileEditAction.DismissModalBottomSheet) } ) } From 19ee01c0672e35f81732d70002ada9b6dbca30c9 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Thu, 27 Nov 2025 20:00:05 +0100 Subject: [PATCH 17/25] comment the import code for the string resources --- .../client/clientEditProfile/ClientProfileEditScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index 79c04a1db2e..ecfd7ad4d36 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -24,10 +24,10 @@ import androidclient.feature.client.generated.resources.feature_client_Image_Upl import androidclient.feature.client.generated.resources.feature_client_error import androidclient.feature.client.generated.resources.from_camera import androidclient.feature.client.generated.resources.from_gallery -import androidclient.feature.client.generated.resources.profile_update_error_message +//import androidclient.feature.client.generated.resources.profile_update_error_message import androidclient.feature.client.generated.resources.remove import androidclient.feature.client.generated.resources.update_profile_photo_message -import androidclient.feature.client.generated.resources.update_success_message +//import androidclient.feature.client.generated.resources.update_success_message import androidclient.feature.client.generated.resources.upload_new_photo import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer From 262fd40216873047e5476fb15b07e6781b422dbb Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Fri, 28 Nov 2025 17:16:59 +0100 Subject: [PATCH 18/25] applied the requested changes --- .../src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt | 2 +- .../client/clientDetailsProfile/ClientProfileDetailsScreen.kt | 3 +-- .../mifos/feature/client/clientProfile/ClientProfileScreen.kt | 2 +- .../kotlin/com/mifos/feature/client/utils/Constants.kt | 3 --- 4 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt index 1b7d883b297..1357a0fa84f 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt @@ -1,3 +1,3 @@ package com.mifos.core.ui.util -internal const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" \ No newline at end of file +const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index f6331fcc2b5..c9507bae30a 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -19,7 +19,6 @@ import androidclient.feature.client.generated.resources.dialog_continue import androidclient.feature.client.generated.resources.dialog_unassign_message import androidclient.feature.client.generated.resources.dismiss_text import androidclient.feature.client.generated.resources.pen_icon -import androidclient.feature.client.generated.resources.profile_should_refresh import androidclient.feature.client.generated.resources.scroll_for_more_options import androidclient.feature.client.generated.resources.staff_unassign_failure_title import androidclient.feature.client.generated.resources.staff_unassign_success_message @@ -66,11 +65,11 @@ import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.components.MifosStatusDialog import com.mifos.core.ui.util.EventsEffect +import com.mifos.core.ui.util.PROFILE_SHOULD_REFRESH_KEY import com.mifos.core.ui.util.TextUtil import com.mifos.feature.client.clientDetailsProfile.components.ClientDetailsProfile import com.mifos.feature.client.clientDetailsProfile.components.ClientProfileDetailsActionItem import com.mifos.feature.client.clientDetailsProfile.components.clientsDetailsActionItems -import com.mifos.feature.client.utils.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 7a56ad607a2..44afc384ede 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -42,11 +42,11 @@ import com.mifos.core.ui.components.MifosErrorComponent import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.util.EventsEffect +import com.mifos.core.ui.util.PROFILE_SHOULD_REFRESH_KEY import com.mifos.core.ui.util.TextUtil import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard import com.mifos.feature.client.clientProfile.components.clientsActionItems -import com.mifos.feature.client.utils.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.stringResource import org.koin.compose.viewmodel.koinViewModel diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt deleted file mode 100644 index 5998c622454..00000000000 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/utils/Constants.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.mifos.feature.client.utils - -internal const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" \ No newline at end of file From 420501b26947e055bb471bf0366936ab36eb14d9 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 5 Jan 2026 12:00:26 +0100 Subject: [PATCH 19/25] implementing repository level approach --- .../data/repository/ClientDetailsRepository.kt | 2 ++ .../repositoryImp/ClientDetailsRepositoryImp.kt | 17 +++++++++++++++++ .../client/clientProfile/ClientProfileScreen.kt | 15 +-------------- .../clientProfile/ClientProfileViewModel.kt | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsRepository.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsRepository.kt index 885c1916a39..bf1f014d83d 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsRepository.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsRepository.kt @@ -20,12 +20,14 @@ import com.mifos.room.entities.accounts.ClientAccounts import com.mifos.room.entities.client.ClientEntity import io.ktor.client.request.forms.MultiPartFormDataContent import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharedFlow /** * Created by Aditya Gupta on 06/08/23. */ interface ClientDetailsRepository { + val clientDataUpdated: SharedFlow // Emits clientId when updated suspend fun uploadClientImage(clientId: Int, image: MultiPartFormDataContent) suspend fun deleteClientImage(clientId: Int) diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt index d2e697cc1a1..4b1c759c99b 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt @@ -23,6 +23,9 @@ import com.mifos.room.entities.accounts.ClientAccounts import com.mifos.room.entities.client.ClientEntity import io.ktor.client.request.forms.MultiPartFormDataContent import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow /** * Created by Aditya Gupta on 06/08/23. @@ -31,12 +34,26 @@ class ClientDetailsRepositoryImp( private val dataManagerClient: DataManagerClient, ) : ClientDetailsRepository { + + // Add this: MutableSharedFlow for internal emissions + private val _clientDataUpdated = MutableSharedFlow( + replay = 0, + extraBufferCapacity = 1 + ) + + // Expose as read-only SharedFlow + override val clientDataUpdated: SharedFlow = _clientDataUpdated.asSharedFlow() + override suspend fun uploadClientImage(clientId: Int, image: MultiPartFormDataContent) { dataManagerClient.uploadClientImage(clientId, image) + // Emit update signal after successful upload + _clientDataUpdated.tryEmit(clientId) } override suspend fun deleteClientImage(clientId: Int) { dataManagerClient.deleteClientImage(clientId) + // Emit update signal after successful delete + _clientDataUpdated.tryEmit(clientId) } override suspend fun getClientAccounts(clientId: Int): ClientAccounts { diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 44afc384ede..be04a441be3 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -64,20 +64,7 @@ internal fun ClientProfileScreen( viewModel: ClientProfileViewModel = koinViewModel(), ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - val currentBackStackEntry = navController.currentBackStackEntry - val savedStateHandle = currentBackStackEntry?.savedStateHandle - - val profileUpdated by savedStateHandle - ?.getStateFlow(PROFILE_SHOULD_REFRESH_KEY, false) - ?.collectAsStateWithLifecycle(initialValue = false) - ?: remember { mutableStateOf(false) } - - LaunchedEffect(profileUpdated) { - if (profileUpdated) { - viewModel.trySendAction(ClientProfileAction.OnRetry) - savedStateHandle?.set(PROFILE_SHOULD_REFRESH_KEY, false) // reset after refresh - } - } + EventsEffect(viewModel.eventFlow) { event -> when (event) { diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt index 83df4d9f265..b332b74fbce 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt @@ -20,6 +20,7 @@ import com.mifos.core.ui.util.BaseViewModel import com.mifos.core.ui.util.imageToByteArray import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.room.entities.client.ClientEntity +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.jetbrains.compose.resources.StringResource @@ -46,6 +47,19 @@ internal class ClientProfileViewModel( init { getClientAndObserveNetwork() + observeClientUpdates() // Add this + } + + // Add this method to observe repository updates + private fun observeClientUpdates() { + viewModelScope.launch { + clientDetailsRepo.clientDataUpdated + .filter { updatedClientId -> updatedClientId == route.id } + .collect { + // Automatically refresh when this client's data is updated + loadClientDetailsAndImage(route.id) + } + } } private fun getClientAndObserveNetwork() { From 3a6d8b3c8df763a8dedfab740f5fc4f715ede432 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 5 Jan 2026 13:56:52 +0100 Subject: [PATCH 20/25] code clean-up --- .../repository/ClientDetailsEditRepository.kt | 3 +++ .../ClientDetailsEditRepositoryImpl.kt | 13 +++++++++++++ .../repositoryImp/ClientDetailsRepositoryImp.kt | 3 --- .../mifos/core/ui/components/MifosBreadCrumb.kt | 7 ------- .../kotlin/com/mifos/core/ui/util/Constants.kt | 3 --- .../ClientProfileDetailsScreen.kt | 15 --------------- .../ClientProfileDetailsViewModel.kt | 13 +++++++++++++ .../ClientEditDetailsViewModel.kt | 13 ++++++++++++- .../client/clientProfile/ClientProfileScreen.kt | 1 - .../clientProfile/ClientProfileViewModel.kt | 5 ++--- 10 files changed, 43 insertions(+), 33 deletions(-) delete mode 100644 core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt index c69601c7959..d7f3ad927e6 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt @@ -10,7 +10,10 @@ package com.mifos.core.data.repository import com.mifos.room.entities.client.ClientPayloadEntity +import kotlinx.coroutines.flow.SharedFlow interface ClientDetailsEditRepository { + + val clientDataUpdated: SharedFlow suspend fun updateClient(clientId: Int, clientPayload: ClientPayloadEntity): Int? } diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt index f0ee995d113..1654ddb9b1d 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt @@ -12,10 +12,23 @@ package com.mifos.core.data.repositoryImp import com.mifos.core.data.repository.ClientDetailsEditRepository import com.mifos.core.network.datamanager.DataManagerClient import com.mifos.room.entities.client.ClientPayloadEntity +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow class ClientDetailsEditRepositoryImpl( private val dataManagerClient: DataManagerClient, ) : ClientDetailsEditRepository { + + + private val _clientDataUpdated = MutableSharedFlow( + replay = 0, + extraBufferCapacity = 1 + ) + + override val clientDataUpdated: SharedFlow = _clientDataUpdated.asSharedFlow() + + override suspend fun updateClient(clientId: Int, clientPayload: ClientPayloadEntity): Int? { return dataManagerClient.updateClient(clientId, clientPayload) } diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt index 4b1c759c99b..2abb73e29aa 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt @@ -34,14 +34,11 @@ class ClientDetailsRepositoryImp( private val dataManagerClient: DataManagerClient, ) : ClientDetailsRepository { - - // Add this: MutableSharedFlow for internal emissions private val _clientDataUpdated = MutableSharedFlow( replay = 0, extraBufferCapacity = 1 ) - // Expose as read-only SharedFlow override val clientDataUpdated: SharedFlow = _clientDataUpdated.asSharedFlow() override suspend fun uploadClientImage(clientId: Int, image: MultiPartFormDataContent) { diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index 251bdc957c7..2bf221624eb 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -30,7 +30,6 @@ import androidx.navigation.NavController import com.mifos.core.designsystem.theme.DesignToken import com.mifos.core.designsystem.theme.MifosTheme import com.mifos.core.designsystem.theme.MifosTypography -import com.mifos.core.ui.util.PROFILE_SHOULD_REFRESH_KEY import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.ui.tooling.preview.Preview @@ -82,9 +81,6 @@ fun MifosBreadcrumbNavBar( isActive = index == routes.lastIndex, onClick = { if (index != routes.lastIndex && route != "...") { - navController.previousBackStackEntry - ?.savedStateHandle - ?.set(PROFILE_SHOULD_REFRESH_KEY, true) navController.popBackStack(route, inclusive = false) } }, @@ -99,9 +95,6 @@ fun MifosBreadcrumbNavBar( IconButton(onClick = { - navController.previousBackStackEntry - ?.savedStateHandle - ?.set(PROFILE_SHOULD_REFRESH_KEY, true) navController.popBackStack() }) { Icon( diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt deleted file mode 100644 index 1357a0fa84f..00000000000 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/Constants.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.mifos.core.ui.util - -const val PROFILE_SHOULD_REFRESH_KEY = "profile_should_refresh" \ No newline at end of file diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index c9507bae30a..35dfa575148 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -65,7 +65,6 @@ import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.components.MifosStatusDialog import com.mifos.core.ui.util.EventsEffect -import com.mifos.core.ui.util.PROFILE_SHOULD_REFRESH_KEY import com.mifos.core.ui.util.TextUtil import com.mifos.feature.client.clientDetailsProfile.components.ClientDetailsProfile import com.mifos.feature.client.clientDetailsProfile.components.ClientProfileDetailsActionItem @@ -92,20 +91,6 @@ internal fun ClientProfileDetailsScreen( navigateToAddCharge: (Int) -> Unit, ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - val currentBackStackEntry = navController.currentBackStackEntry - val savedStateHandle = currentBackStackEntry?.savedStateHandle - - val profileUpdated by savedStateHandle - ?.getStateFlow(PROFILE_SHOULD_REFRESH_KEY, false) - ?.collectAsStateWithLifecycle(initialValue = false) - ?: remember { mutableStateOf(false) } - - LaunchedEffect(profileUpdated) { - if (profileUpdated) { - viewModel.trySendAction(ClientProfileDetailsAction.OnRetry) - savedStateHandle?.set(PROFILE_SHOULD_REFRESH_KEY, false) - } - } EventsEffect(viewModel.eventFlow) { event -> when (event) { diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt index 6ab45c13418..6bf11c61efb 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt @@ -35,6 +35,7 @@ import com.mifos.core.ui.util.imageToByteArray import com.mifos.core.ui.util.toDateString import com.mifos.feature.client.clientDetailsProfile.components.ClientProfileDetailsActionItem import com.mifos.room.entities.client.ClientEntity +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.jetbrains.compose.resources.StringResource @@ -62,13 +63,25 @@ internal class ClientProfileDetailsViewModel( init { getClientAndObserveNetwork() + observeClientUpdates() } private fun getClientAndObserveNetwork() { observeNetwork() + observeClientUpdates() loadClientDetailsAndImage(route.id) } + private fun observeClientUpdates() { + viewModelScope.launch { + clientDetailsRepo.clientDataUpdated + .filter { updatedClientId -> updatedClientId == route.id } + .collect { + loadClientDetailsAndImage(route.id) + } + } + } + /** * Fetches both client details and profile image. * diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt index 200fffa0970..1e1ab1ca4bc 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt @@ -29,6 +29,7 @@ import com.mifos.room.entities.organisation.OfficeEntity import com.mifos.room.entities.organisation.StaffEntity import com.mifos.room.entities.templates.clients.ClientsTemplateEntity import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.jetbrains.compose.resources.getString @@ -44,7 +45,17 @@ internal class ClientEditDetailsViewModel( val route = savedStateHandle.toRoute() init { - loadClientDetails(route.id) + observeClientUpdates() + } + + private fun observeClientUpdates() { + viewModelScope.launch { + repository.clientDataUpdated + .filter { updatedClientId -> updatedClientId == route.id } + .collect { + loadClientDetails(route.id) + } + } } fun loadClientDetails(clientId: Int = route.id) { diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 09203567928..3e4b54a7428 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -42,7 +42,6 @@ import com.mifos.core.ui.components.MifosErrorComponent import com.mifos.core.ui.components.MifosProgressIndicator import com.mifos.core.ui.components.MifosRowCard import com.mifos.core.ui.util.EventsEffect -import com.mifos.core.ui.util.PROFILE_SHOULD_REFRESH_KEY import com.mifos.core.ui.util.TextUtil import com.mifos.feature.client.clientProfile.components.ClientProfileActionItem import com.mifos.feature.client.clientProfile.components.ProfileCard diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt index b332b74fbce..c8b6d0ca9d9 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt @@ -47,16 +47,15 @@ internal class ClientProfileViewModel( init { getClientAndObserveNetwork() - observeClientUpdates() // Add this + observeClientUpdates() } - // Add this method to observe repository updates + private fun observeClientUpdates() { viewModelScope.launch { clientDetailsRepo.clientDataUpdated .filter { updatedClientId -> updatedClientId == route.id } .collect { - // Automatically refresh when this client's data is updated loadClientDetailsAndImage(route.id) } } From 312fbe1030dfbef7b0876fec114c0cb6e929ba21 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 5 Jan 2026 14:11:23 +0100 Subject: [PATCH 21/25] code clean-up --- cmp-android/build.gradle.kts | 3 +-- .../cmp/android/app/ComponentActivityExtensions.kt | 10 +++++----- cmp-android/src/main/res/values/strings.xml | 1 - .../com/mifos/core/ui/components/MifosBreadCrumb.kt | 8 ++++---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/cmp-android/build.gradle.kts b/cmp-android/build.gradle.kts index abf4a931d66..9e39c81d996 100644 --- a/cmp-android/build.gradle.kts +++ b/cmp-android/build.gradle.kts @@ -7,7 +7,6 @@ * * See https://github.com/openMF/android-client/blob/master/LICENSE.md */ - import org.mifos.MifosBuildType import org.mifos.dynamicVersion @@ -155,4 +154,4 @@ dependencyGuard { modules = true tree = true } -} +} \ No newline at end of file diff --git a/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt b/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt index ce320435cd1..6c34f84f165 100644 --- a/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt +++ b/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt @@ -39,7 +39,9 @@ private val SCRIM_COLOR: Int = Color.TRANSPARENT * [here](https://github.com/android/nowinandroid/blob/689ef92e41427ab70f82e2c9fe59755441deae92/app/src/main/kotlin/com/google/samples/apps/nowinandroid/MainActivity.kt#L94). */ @Suppress("MaxLineLength") -fun ComponentActivity.setupEdgeToEdge(appThemeFlow: Flow) { +fun ComponentActivity.setupEdgeToEdge( + appThemeFlow: Flow +) { lifecycleScope.launch { lifecycle.repeatOnLifecycle(state = Lifecycle.State.STARTED) { combine( @@ -53,8 +55,7 @@ fun ComponentActivity.setupEdgeToEdge(appThemeFlow: Flow) { // This handles all the settings to go edge-to-edge. We are using a transparent // scrim for system bars and switching between "light" and "dark" based on the // system and internal app theme settings. - val style = - SystemBarStyle.auto( + val style = SystemBarStyle.auto( darkScrim = SCRIM_COLOR, lightScrim = SCRIM_COLOR, // Disabling Dark Mode for this app @@ -74,8 +75,7 @@ fun ComponentActivity.setupEdgeToEdge(appThemeFlow: Flow) { private fun ComponentActivity.isSystemInDarkModeFlow(): Flow = callbackFlow { channel.trySend(element = resources.configuration.isSystemInDarkMode) - val listener = - Consumer { + val listener = Consumer { channel.trySend(element = it.isSystemInDarkMode) } addOnConfigurationChangedListener(listener = listener) diff --git a/cmp-android/src/main/res/values/strings.xml b/cmp-android/src/main/res/values/strings.xml index 44bfc8a2189..c81f00fb228 100644 --- a/cmp-android/src/main/res/values/strings.xml +++ b/cmp-android/src/main/res/values/strings.xml @@ -422,7 +422,6 @@ No more Groups Available No more Centers Available - Number of repayments Days in year diff --git a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt index 2bf221624eb..d153ff2df8a 100644 --- a/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt +++ b/core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt @@ -93,10 +93,10 @@ fun MifosBreadcrumbNavBar( } } - - IconButton(onClick = { - navController.popBackStack() - }) { + IconButton( + onClick = { navController.popBackStack() }, + modifier = Modifier.size(DesignToken.sizes.iconMedium), + ) { Icon( painter = painterResource(Res.drawable.bread_crumb_back_icon), contentDescription = "Back", From 6b6161cc053b38d6960858a1c721404c1d11e950 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 5 Jan 2026 15:53:39 +0100 Subject: [PATCH 22/25] resolved navigation when the dialog is dismissed --- .../app/ComponentActivityExtensions.kt | 16 +++++++------- .../repository/ClientDetailsEditRepository.kt | 3 +-- .../ClientDetailsEditRepositoryImpl.kt | 12 ----------- .../ClientDetailsRepositoryImp.kt | 2 -- .../composeResources/values/strings.xml | 2 +- .../ClientProfileDetailsViewModel.kt | 1 - .../ClientEditDetailsViewModel.kt | 14 ------------- .../ClientProfileEditScreen.kt | 21 +++++++++++++++++++ .../clientProfile/ClientProfileScreen.kt | 2 -- 9 files changed, 31 insertions(+), 42 deletions(-) diff --git a/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt b/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt index 6c34f84f165..97ab3d3eb31 100644 --- a/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt +++ b/cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt @@ -40,7 +40,7 @@ private val SCRIM_COLOR: Int = Color.TRANSPARENT */ @Suppress("MaxLineLength") fun ComponentActivity.setupEdgeToEdge( - appThemeFlow: Flow + appThemeFlow: Flow, ) { lifecycleScope.launch { lifecycle.repeatOnLifecycle(state = Lifecycle.State.STARTED) { @@ -56,11 +56,11 @@ fun ComponentActivity.setupEdgeToEdge( // scrim for system bars and switching between "light" and "dark" based on the // system and internal app theme settings. val style = SystemBarStyle.auto( - darkScrim = SCRIM_COLOR, - lightScrim = SCRIM_COLOR, - // Disabling Dark Mode for this app - detectDarkMode = { false }, - ) + darkScrim = SCRIM_COLOR, + lightScrim = SCRIM_COLOR, + // Disabling Dark Mode for this app + detectDarkMode = { false }, + ) enableEdgeToEdge(statusBarStyle = style, navigationBarStyle = style) } } @@ -76,8 +76,8 @@ private fun ComponentActivity.isSystemInDarkModeFlow(): Flow = callbackFlow { channel.trySend(element = resources.configuration.isSystemInDarkMode) val listener = Consumer { - channel.trySend(element = it.isSystemInDarkMode) - } + channel.trySend(element = it.isSystemInDarkMode) + } addOnConfigurationChangedListener(listener = listener) awaitClose { removeOnConfigurationChangedListener(listener = listener) } } diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt index d7f3ad927e6..2d260d18f82 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ClientDetailsEditRepository.kt @@ -10,10 +10,9 @@ package com.mifos.core.data.repository import com.mifos.room.entities.client.ClientPayloadEntity -import kotlinx.coroutines.flow.SharedFlow + interface ClientDetailsEditRepository { - val clientDataUpdated: SharedFlow suspend fun updateClient(clientId: Int, clientPayload: ClientPayloadEntity): Int? } diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt index 1654ddb9b1d..e6d6d3a1e21 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsEditRepositoryImpl.kt @@ -12,23 +12,11 @@ package com.mifos.core.data.repositoryImp import com.mifos.core.data.repository.ClientDetailsEditRepository import com.mifos.core.network.datamanager.DataManagerClient import com.mifos.room.entities.client.ClientPayloadEntity -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.asSharedFlow class ClientDetailsEditRepositoryImpl( private val dataManagerClient: DataManagerClient, ) : ClientDetailsEditRepository { - - private val _clientDataUpdated = MutableSharedFlow( - replay = 0, - extraBufferCapacity = 1 - ) - - override val clientDataUpdated: SharedFlow = _clientDataUpdated.asSharedFlow() - - override suspend fun updateClient(clientId: Int, clientPayload: ClientPayloadEntity): Int? { return dataManagerClient.updateClient(clientId, clientPayload) } diff --git a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt index 2abb73e29aa..3cad34a17a6 100644 --- a/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt +++ b/core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt @@ -43,13 +43,11 @@ class ClientDetailsRepositoryImp( override suspend fun uploadClientImage(clientId: Int, image: MultiPartFormDataContent) { dataManagerClient.uploadClientImage(clientId, image) - // Emit update signal after successful upload _clientDataUpdated.tryEmit(clientId) } override suspend fun deleteClientImage(clientId: Int) { dataManagerClient.deleteClientImage(clientId) - // Emit update signal after successful delete _clientDataUpdated.tryEmit(clientId) } diff --git a/core/designsystem/src/commonMain/composeResources/values/strings.xml b/core/designsystem/src/commonMain/composeResources/values/strings.xml index 2bdfff95763..6eedeca78df 100644 --- a/core/designsystem/src/commonMain/composeResources/values/strings.xml +++ b/core/designsystem/src/commonMain/composeResources/values/strings.xml @@ -19,7 +19,7 @@ Success Failure Continue - MifosStatusDialog + MifosStatusDialog Mifos diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt index 6bf11c61efb..c9ba9fa0046 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsViewModel.kt @@ -68,7 +68,6 @@ internal class ClientProfileDetailsViewModel( private fun getClientAndObserveNetwork() { observeNetwork() - observeClientUpdates() loadClientDetailsAndImage(route.id) } diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt index 1e1ab1ca4bc..377a79c9702 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsViewModel.kt @@ -44,20 +44,6 @@ internal class ClientEditDetailsViewModel( ) { val route = savedStateHandle.toRoute() - init { - observeClientUpdates() - } - - private fun observeClientUpdates() { - viewModelScope.launch { - repository.clientDataUpdated - .filter { updatedClientId -> updatedClientId == route.id } - .collect { - loadClientDetails(route.id) - } - } - } - fun loadClientDetails(clientId: Int = route.id) { viewModelScope.launch { getClientDetailsUseCase(clientId).collect { result -> diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt index ecfd7ad4d36..9fc22670623 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditScreen.kt @@ -43,7 +43,9 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text 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 import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue @@ -84,6 +86,25 @@ internal fun ClientProfileEditScreen( ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() + var hasShownSuccess by remember { mutableStateOf(false) } + + LaunchedEffect(state.dialogState) { + when (state.dialogState) { + is ClientProfileEditState.DialogState.Success -> { + hasShownSuccess = true + } + null -> { + if (hasShownSuccess) { + hasShownSuccess = false + onNavigateBack() + } + } + else -> { + hasShownSuccess = false + } + } + } + ClientProfileEditScaffold( modifier = modifier, state = state, diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt index 3e4b54a7428..4064ea6e6c9 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt @@ -27,9 +27,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text 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 import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle From 9735a57666aafba96d948a9161b35ed6f8ff0252 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 5 Jan 2026 16:25:56 +0100 Subject: [PATCH 23/25] one more... --- .../clientEditProfile/ClientProfileEditViewModel.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index 393ae91d2a2..1d39cf70ada 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -9,6 +9,8 @@ */ package com.mifos.feature.client.clientEditProfile +import androidclient.feature.client.generated.resources.Res +import androidclient.feature.client.generated.resources.unknown_error import androidx.compose.ui.graphics.ImageBitmap import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope @@ -146,6 +148,13 @@ internal class ClientProfileEditViewModel( is DataState.Loading -> mutableStateFlow.update { it.copy(dialogState = ClientProfileEditState.DialogState.Loading) } + is DataState.Error -> mutableStateFlow.update { + it.copy( + dialogState = ClientProfileEditState.DialogState.Error( + result.message, + ), + ) + } else -> Unit } } From 6c97ec60104dc5d32657da9e8f04e5c5a55d8637 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Mon, 5 Jan 2026 16:43:11 +0100 Subject: [PATCH 24/25] code clean --- .../client/clientDetailsProfile/ClientProfileDetailsScreen.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt index 35dfa575148..69be5e212a1 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt @@ -44,9 +44,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text 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 import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier From a5e7115553026f55049f17e86e645da88d427600 Mon Sep 17 00:00:00 2001 From: Ufuoma Isaac Date: Tue, 6 Jan 2026 08:13:24 +0100 Subject: [PATCH 25/25] remove unused import --- .../client/clientEditProfile/ClientProfileEditViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt index 1d39cf70ada..220ff91a560 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditProfile/ClientProfileEditViewModel.kt @@ -23,7 +23,6 @@ import com.mifos.core.ui.util.BaseViewModel import com.mifos.core.ui.util.imageToByteArray import com.mifos.core.ui.util.multipartRequestBody import com.mifos.feature.client.utils.toPlatformFile -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch