feat(recent-transaction): redesign screen and update state management#3045
feat(recent-transaction): redesign screen and update state management#3045therajanmaurya merged 2 commits intoopenMF:developmentfrom
Conversation
- Redesign `RecentTransactionScreen` to use `MifosElevatedScaffold`, `MifosPoweredCard`, and updated UI components for transactions and filters. - Migrate `RecentTransactionViewModel` to inherit from `BaseViewModel` and refactor state management to use `ScreenUiState`. - Introduce `UiTransaction` and `RecentTransactionUiState` within the ViewModel package to replace the deleted `RecentTransactionState.kt`. - Replace string-based navigation with type-safe serialization-based navigation in `RecentTransactionNavGraph.kt`. - Add necessary string resources for the new UI layout and filter dialogs. - Remove obsolete `RecentTransactionNavigation.kt` and `RecentTransactionState.kt`.
📝 WalkthroughWalkthroughThis PR refactors the recent-transaction feature from a legacy state-management pattern to a BaseViewModel-driven architecture with serializable routes. Navigation functions are renamed for consistency (NavGraph→Destination), the RecentTransactionScreen is reorganized into modular composables (content/dialog), and a new filtering system is introduced with corresponding UI strings and state handling. The ViewModel now manages network-aware data fetching, local transaction filtering, and event-driven navigation. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt (2)
182-197: Consider simplifying the transaction click handling.The
transactionIdis already aLongbut is converted toStringat line 190 (transactionId.toString()). The navigation callback inRecentTransactionNavGraph.ktacceptsLongforaccountIdbutStringfortransactionId. This inconsistency may cause confusion. Consider keeping the types consistent across the navigation layer.
340-348: Consider making the extension function private and avoiding hardcoded currency.
- The
toUiTransaction()extension is only used within this internal class, so it should be marked asprivatefor proper encapsulation.- The hardcoded
"USD"fallback (line 347) may not be appropriate for all deployment regions.🔎 Proposed fix
- fun Transactions.toUiTransaction() = UiTransaction( + private fun Transactions.toUiTransaction() = UiTransaction( id = id?.toLong(), date = date, amount = amount, type = transactionType, typeValue = transactionType?.value, isCredit = transactionType.isCredit(), - currency = currency?.code ?: "USD", + currency = currency?.code.orEmpty(), )feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt (1)
16-16: Unused import.The
androidx.navigation.compose.navigationimport appears to be unused since the code only usescomposableWithSlideTransitionsand doesn't create a nested navigation graph.🔎 Proposed fix
import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder -import androidx.navigation.compose.navigation import kotlinx.serialization.Serializablefeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt (2)
464-469: Consider using safe call instead of force unwrap.While the null check at line 466 makes the
!!at line 467 safe, using a safe call pattern is more idiomatic and protects against future refactoring errors.🔎 Proposed fix
Button( - onClick = { - if (selectedAccount != null) { - onAction(RecentTransactionAction.ApplyFilter(selectedAccount!!, selectedType)) - } - }, + onClick = { + selectedAccount?.let { account -> + onAction(RecentTransactionAction.ApplyFilter(account, selectedType)) + } + },
489-521: Consider makingFilterOptionChipinternal.
FilterOptionChipis a public composable in a file where other composables are markedinternal. For consistency and proper encapsulation, consider marking itinternalunless it's intended to be reused by other modules.🔎 Proposed fix
@Composable -fun FilterOptionChip( +internal fun FilterOptionChip( label: String, isSelected: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier, ) {
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.ktfeature/recent-transaction/build.gradle.ktsfeature/recent-transaction/src/commonMain/composeResources/values/strings.xmlfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavigation.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/utils/RecentTransactionState.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt
💤 Files with no reviewable changes (2)
- feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/utils/RecentTransactionState.kt
- feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavigation.kt
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{kt,kts}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{kt,kts}: Use Koin for dependency injection across all platforms
Implement ScreenState pattern for handling loading/success/error states in features
Files:
feature/recent-transaction/build.gradle.ktscmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt
**/{build.gradle.kts,build.gradle}
📄 CodeRabbit inference engine (CLAUDE.md)
**/{build.gradle.kts,build.gradle}: Apply convention plugins from build-logic/convention/ to standardize module configuration across the project
Use JDK 21 for the project
Files:
feature/recent-transaction/build.gradle.kts
**/*ViewModel.kt
📄 CodeRabbit inference engine (CLAUDE.md)
Use ViewModels with StateFlow/SharedFlow for state management
Files:
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Applies to **/*ViewModel.kt : Use ViewModels with StateFlow/SharedFlow for state management
📚 Learning: 2025-12-29T16:08:08.437Z
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Applies to **/{build.gradle.kts,build.gradle} : Apply convention plugins from build-logic/convention/ to standardize module configuration across the project
Applied to files:
feature/recent-transaction/build.gradle.kts
📚 Learning: 2025-12-29T16:08:08.437Z
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Applies to cmp-android/build.gradle.kts : Configure Android product flavors for demo and prod environments
Applied to files:
feature/recent-transaction/build.gradle.kts
📚 Learning: 2025-12-29T16:08:08.437Z
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Applies to **/*.{kt,kts} : Use Koin for dependency injection across all platforms
Applied to files:
feature/recent-transaction/build.gradle.kts
📚 Learning: 2025-12-29T16:08:08.437Z
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Use Jetbrains Compose Navigation with graph hierarchy: ROOT_GRAPH → AUTH_GRAPH → PASSCODE_GRAPH → MAIN_GRAPH
Applied to files:
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt
📚 Learning: 2025-12-29T16:08:08.437Z
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Applies to **/*ViewModel.kt : Use ViewModels with StateFlow/SharedFlow for state management
Applied to files:
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt
📚 Learning: 2025-12-29T16:08:08.437Z
Learnt from: CR
Repo: openMF/mifos-mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T16:08:08.437Z
Learning: Applies to **/*.{kt,kts} : Implement ScreenState<T> pattern for handling loading/success/error states in features
Applied to files:
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.ktfeature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt
🧬 Code graph analysis (2)
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt (1)
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt (1)
recentTransactionDestination(28-38)
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt (5)
feature/client-charge/src/commonMain/kotlin/org/mifos/mobile/feature/charge/charges/ClientChargeViewModel.kt (3)
observeNetworkStatus(87-96)updateState(101-103)handleAction(108-131)feature/share-account/src/commonMain/kotlin/org/mifos/mobile/feature/shareaccount/shareAccount/ShareAccountViewModel.kt (2)
updateState(122-124)handleAction(56-84)feature/accounts/src/commonMain/kotlin/org/mifos/mobile/feature/accounts/transactionDetail/TransactionDetailsViewModel.kt (2)
updateState(156-158)handleAction(67-72)feature/savings-account/src/commonMain/kotlin/org/mifos/mobile/feature/savingsaccount/savingsAccountDetails/SavingsAccountDetailsViewModel.kt (2)
updateState(130-132)handleAction(100-123)feature/accounts/src/commonMain/kotlin/org/mifos/mobile/feature/accounts/accounts/AccountsViewModel.kt (1)
handleAction(45-89)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: PR Checks KMP / Static Analysis Check
🔇 Additional comments (10)
feature/recent-transaction/build.gradle.kts (1)
10-13: LGTM!The addition of the Kotlin serialization plugin is appropriate for supporting the new
@Serializableroute objects used in type-safe navigation. The convention plugin from build-logic is already applied as per coding guidelines.feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt (5)
36-44: LGTM!The ViewModel correctly extends
BaseViewModelwith the appropriate type parameters and usesScreenUiStatefor handling loading/success/error states. The initial state setup withclientIdfromuserPreferencesRepositoryis well-structured. Based on learnings, this follows the StateFlow/SharedFlow pattern for state management and the ScreenState pattern for handling UI states.
55-93: Network observation follows established patterns.The network monitoring implementation using
distinctUntilChanged()and the action-based approach (ReceiveNetworkResult) aligns with similar implementations inClientChargeViewModelandTransactionViewModelfrom the codebase.
355-371: VerifydividendPayoutclassification as debit.
dividendPayoutis classified as a debit (returnsfalse), but dividend payouts typically represent money flowing into the account, which would be a credit. Please verify this business logic is intentional.
416-439: LGTM!The
RecentTransactionUiStateis well-structured with clear documentation. The computedhasActiveFiltersproperty is a clean approach for deriving filter state. The sealedDialogStateinterface properly encapsulates dialog-related state.
444-473: Clean action/event separation.The sealed interfaces for
RecentTransactionActionandRecentTransactionEventfollow best practices with clear separation between user-initiated actions, internal actions, and navigation events.cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt (1)
299-308: LGTM!The
recentTransactionDestinationintegration follows the same callback-based pattern used by other destinations in this file (e.g.,notificationDestination,accountTransactionsDestination,transactionDetailDestination). The navigation callbacks are properly wired to theNavController.feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt (1)
21-37: LGTM!The type-safe navigation setup with
@Serializableroute object andcomposableWithSlideTransitionsis well-implemented. The callback-based approach fornavigateBackandnavigateToDetailsprovides clean separation between navigation concerns and screen logic.feature/recent-transaction/src/commonMain/composeResources/values/strings.xml (1)
17-31: LGTM!The new string resources properly support the filter dialog UI. The format placeholders for
account_number_labelandbalanceare correctly defined.Consider whether common strings like
something_went_wrong,filter,all, etc., should be extracted to a shared core resources module to avoid duplication across features, but this is a minor organizational consideration.feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt (1)
96-128: LGTM!The
RecentTransactionScreencomposable is well-structured with:
- Proper use of
EventsEffectfor handling one-time navigation eventsremember(viewModel)wrapping for action callbacks to prevent unnecessary recompositions- Clean separation between screen entry point and content/dialog composables
RecentTransactionScreento useMifosElevatedScaffold,MifosPoweredCard, and updated UI components for transactions and filters.RecentTransactionViewModelto inherit fromBaseViewModeland refactor state management to useScreenUiState.UiTransactionandRecentTransactionUiStatewithin the ViewModel package to replace the deletedRecentTransactionState.kt.RecentTransactionNavGraph.kt.RecentTransactionNavigation.ktandRecentTransactionState.kt.Fixes - Jira-#480
Didn't create a Jira ticket, click here to create new.
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.