Skip to content

MM-520 the transfer feature is implemented through two different navigation paths with inconsistent UI#3075

Open
Naman-kr404 wants to merge 3 commits intoopenMF:developmentfrom
Naman-kr404:MM-520-the-transfer-feature-is-implemented-through-two-different-navigation-paths-with-inconsistent-ui
Open

MM-520 the transfer feature is implemented through two different navigation paths with inconsistent UI#3075
Naman-kr404 wants to merge 3 commits intoopenMF:developmentfrom
Naman-kr404:MM-520-the-transfer-feature-is-implemented-through-two-different-navigation-paths-with-inconsistent-ui

Conversation

@Naman-kr404
Copy link
Copy Markdown
Contributor

@Naman-kr404 Naman-kr404 commented Jan 15, 2026

Fixes - Jira-#520

Current Flow

Users can make transfers either via the Transfer tab in the bottom navigation or by navigating to Savings Account, selecting an account, and tapping Transfer.

Issue

Both flows perform the same transfer functionality but display different UI, causing duplication.

Before (Via Transfer tab and saving account respectively, both are different)
tpt
saving

------------------------------------|----------------------------------------|
| | |
After (Via Transfer tab and saving account respectively, both are same) |
tpppp
saving

Summary by CodeRabbit

  • Refactor
    • Removed the separate third‑party transfer feature and consolidated transfer flows into the unified transfer experience; navigation simplified across authenticated areas.
  • New Features
    • Added a shortcut to open the Make Transfer screen directly.
  • Bug Fixes
    • Safer handling of outstanding balance data and stricter enablement logic for the Make Transfer form.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

This PR removes the Third Party Transfer (TPT) feature and its DI module, deletes TPT UI, ViewModel, and navigation helpers; updates authenticated/navbar navigation to stop wiring the TPT navigator; and redirects transfer-related navigation to the Make Transfer flow with minor MakeTransferViewModel and navigation adjustments.

Changes

Cohort / File(s) Summary
Gitignore & DI init
\.gitignore, cmp-navigation/src/commonMain/kotlin/cmp/navigation/di/KoinModules.kt
Added cmp-ios/Pods/ to .gitignore; removed ThirdPartyTransferModule from Koin feature modules.
Authenticated navigation graph
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt, cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavbarNavigation.kt
Removed imports/parameters and wiring for TptNavigator in authenticated and navbar graph builders.
Authenticated navbar items & screen
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavBarTabItem.kt, cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavbarNavigationScreen.kt
Added noNavigationRoute; TransferTab now uses it; replaced tpt graph integration with makeTransfer/transferProcess/passcode/status destinations and related navigation helpers.
Third‑party transfer feature removal
feature/third-party-transfer/src/.../di/ThirdPartyTransferModule.kt, .../thirdPartyTransfer/TptScreen.kt, .../thirdPartyTransfer/TptScreenRoute.kt, .../TptViewModel.kt, .../navigation/ThirdPartyTransferRoute.kt
Deleted entire TPT feature: DI module, navigation routes/helpers, UI composables, and ViewModel/state/actions/events/validation types.
Make Transfer navigation
feature/transfer-process/src/commonMain/kotlin/.../MakeTransferNavigation.kt
Added overload navigateToMakeTransferScreen(navOptions: NavOptions? = null) using accountId = -1L; made outstandingBalance usage null-safe.
Make Transfer ViewModel
feature/transfer-process/src/commonMain/kotlin/.../MakeTransferViewModel.kt
Tightened isEnabled to require MakeTransferScreenState.Success; changed route accountId initialization to use non-null value.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • revanthkumarJ
  • therajanmaurya
  • itsPronay

Poem

🐇 I hopped through code both near and far,

Cleared out a path where old routes are,
Make‑transfer springs in place of the past,
Fresh, tidy hops — quick and fast! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly references the issue (MM-520) and accurately describes the main change: consolidating two different navigation paths for the transfer feature to use consistent UI instead of the previous duplication.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Naman-kr404 Naman-kr404 force-pushed the MM-520-the-transfer-feature-is-implemented-through-two-different-navigation-paths-with-inconsistent-ui branch from d7ab78f to 9524baf Compare January 26, 2026 19:24
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavBarTabItem.kt`:
- Line 25: Rename the typo'd property noNaviggationRoute to noNavigationRoute in
AuthenticatedNavBarTabItem and update all references (e.g., usages currently
referencing noNaviggationRoute at the two places noted) to the new identifier;
ensure any related imports/exports, string value stays the same
("__no_navigation__"), and run a quick build to catch any remaining references
to noNaviggationRoute so you replace them with noNavigationRoute.
🧹 Nitpick comments (6)
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavbarNavigation.kt (1)

20-20: Remove commented-out code instead of leaving it in place.

Since the TPT feature is being fully removed from the codebase, the commented-out import, parameter, and argument should be deleted rather than left as comments. Commented-out code creates noise and confusion for future maintainers. Version control preserves history if this code is ever needed again.

♻️ Suggested cleanup
 import org.mifos.mobile.core.ui.composableWithStayTransitions
 import org.mifos.mobile.feature.home.navigation.HomeNavigator
-// import org.mifos.mobile.feature.third.party.transfer.navigation.TptNavigator
 
 `@Serializable`
 data object AuthenticatedNavbarRoute
 internal fun NavGraphBuilder.authenticatedNavbarGraph(
     homeNavigator: HomeNavigator,
-//    tptNavigator: TptNavigator,
 ) {
     composableWithStayTransitions<AuthenticatedNavbarRoute> {
         AuthenticatedNavbarNavigationScreen(
             homeNavigator = homeNavigator,
-//            tptNavigator = tptNavigator,
-
         )
     }
 }

Also applies to: 29-39

feature/transfer-process/src/commonMain/kotlin/org/mifos/mobile/feature/transfer/process/makeTransfer/MakeTransferViewModel.kt (3)

66-67: Remove commented-out debug code before merging.

Lines 66-67 and 83-86 contain commented-out code with debug markers (e.g., 🔥 FORCE initial load). This appears to be development/debugging artifacts that should be cleaned up.

♻️ Proposed cleanup
-//            accountId = route.accountId ?: -1L,
             accountId = route.accountId,
     init {
         observeNetworkStatus()
-        // 🔥 FORCE initial load
-//        viewModelScope.launch {
-//            fetchAccountOptions()
-//        }
     }

Also applies to: 83-86


390-412: Remove large commented-out code block.

This entire block appears to be an alternative implementation that was commented out during development. Dead code like this should be removed to maintain code clarity. If needed later, it can be retrieved from version control history.

♻️ Remove the commented block
-//    private fun fetchAccountOptions() {
-//        //chatgpt
-//        if (state.accountId <= 0L) {
-//            fetchActiveAccount()
-//            return
-//        }
-//        updateState {
-//            it.copy(uiState = MakeTransferState.MakeTransferScreenState.Loading)
-//        }
-//
-//        viewModelScope.launch {
-//            savingsAccountRepositoryImpl
-//                .accountTransferTemplate(
-//                    accountId = state.accountId.takeIf { it != -1L } ?: 0L,
-//                    accountType = 2L
-//                )
-//                .collect { result ->
-//                    sendAction(
-//                        MakeTransferAction.Internal.ReceiveAccountOptionsTemplateResult(result)
-//                    )
-//                }
-//        }
-//    }

638-640: Use val instead of var for data class properties.

accountOptionsTemplate, fromAccountOptions, and toAccountOptions are declared as var, which breaks immutability of the state data class. State classes should be immutable; mutations should occur through copy().

♻️ Proposed fix
-    var accountOptionsTemplate: AccountOptionsTemplate = AccountOptionsTemplate(),
-    var fromAccountOptions: List<AccountOption> = emptyList(),
-    var toAccountOptions: List<AccountOption> = emptyList(),
+    val accountOptionsTemplate: AccountOptionsTemplate = AccountOptionsTemplate(),
+    val fromAccountOptions: List<AccountOption> = emptyList(),
+    val toAccountOptions: List<AccountOption> = emptyList(),
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavbarNavigationScreen.kt (1)

185-196: Clarify the repeat(2) back-stack manipulation logic.

The repeat(2) { navController.popScreens() } is a magic number pattern that's unclear in intent. What if the back stack has fewer than 2 entries? This could lead to unexpected behavior or crashes.

Consider:

  1. Adding a comment explaining why exactly 2 pops are needed.
  2. Using a more robust approach that handles edge cases gracefully.
#!/bin/bash
# Find the popScreens implementation to verify safety
ast-grep --pattern $'fun NavController.popScreens($$$) {
  $$$
}'

# Alternative search
rg -n "fun.*popScreens" --type=kt -A10
cmp-navigation/src/commonMain/kotlin/cmp/navigation/di/KoinModules.kt (1)

74-74: Remove the commented-out module instead of leaving it.

Since the Third Party Transfer feature is being removed, the commented-out line should be deleted entirely rather than left as a comment. Dead code should be removed to keep the codebase clean.

♻️ Proposed fix
             TransferProcessModule,
             SettingsModule,
-//            ThirdPartyTransferModule,
             BeneficiaryModule,

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavBarTabItem.kt (1)

45-60: TransferTab will not display as selected and navigation bar visibility may fail due to sentinel route design.

TransferTab returns "__no_navigation__" for both graphRoute and startDestinationRoute, but the tab selection logic (line 122) uses isCurrentRoute(it.graphRoute) to determine which tab to highlight. Since "__no_navigation__" never matches any actual navigation destination in the hierarchy, the TransferTab will never appear as selected, even when actively viewing the MakeTransfer screen.

Additionally, the navigation bar visibility check (line 141) uses startDestinationRoute, which will also fail to match. Consider mapping TransferTab to an actual route that corresponds to the MakeTransfer screen destination, or add special handling in isCurrentRoute() and the visibility check for the sentinel route.

🧹 Nitpick comments (1)
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticatednavbar/AuthenticatedNavBarTabItem.kt (1)

24-25: Consider moving constant to companion object.

noNavigationRoute is a constant string used as a sentinel value. Defining it as an instance property on the sealed class is unconventional; placing it in a companion object is more idiomatic for constants in Kotlin.

♻️ Suggested refactor
 sealed class AuthenticatedNavBarTabItem : NavigationItem {
-    val noNavigationRoute = "__no_navigation__"
+    companion object {
+        const val NO_NAVIGATION_ROUTE = "__no_navigation__"
+    }
     data object HomeTab : AuthenticatedNavBarTabItem() {

Then update references in TransferTab:

         override val graphRoute: String
-            get() = noNavigationRoute
+            get() = NO_NAVIGATION_ROUTE
         override val startDestinationRoute: String
-            get() = noNavigationRoute
+            get() = NO_NAVIGATION_ROUTE

@mena-rizkalla
Copy link
Copy Markdown
Contributor

Can you please update the pr description and put the images beside each other for easily comparing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants