Skip to content

feat(recent-transaction): redesign screen and update state management#3045

Merged
therajanmaurya merged 2 commits intoopenMF:developmentfrom
Nagarjuna0033:MM-480
Jan 2, 2026
Merged

feat(recent-transaction): redesign screen and update state management#3045
therajanmaurya merged 2 commits intoopenMF:developmentfrom
Nagarjuna0033:MM-480

Conversation

@Nagarjuna0033
Copy link
Contributor

@Nagarjuna0033 Nagarjuna0033 commented Dec 30, 2025

  • 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.

Fixes - Jira-#480

Didn't create a Jira ticket, click here to create new.

Before After
image image

Summary by CodeRabbit

Release Notes

  • New Features

    • Added transaction filtering with options to filter by account and transaction type (All, Debits, Credits).
    • Introduced Clear All filters button and pull-to-refresh functionality for recent transactions.
    • Enhanced error messaging with improved user feedback.
  • Chores

    • Added Kotlin serialization support to build configuration.

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

- 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`.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

This 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

Cohort / File(s) Summary
Navigation Layer
cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
Renamed recentTransactionNavGraph to recentTransactionDestination; updated signature to pass navigateBack callback instead of NavController instance.
Navigation Layer
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt
Introduced serializable RecentTransactionRoute data object; renamed function from recentTransactionScreenRoute to recentTransactionDestination; replaced composable() with composableWithSlideTransitions<RecentTransactionRoute>.
Navigation Layer
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavigation.kt
Removed entire file containing route constants and sealed navigation hierarchy.
Build Configuration
feature/recent-transaction/build.gradle.kts
Added Kotlin serialization plugin alias to plugins block.
String Resources
feature/recent-transaction/src/commonMain/composeResources/values/strings.xml
Added 14 new string resources for filter UI (filter titles, account labels, transaction type options, buttons).
Screen Implementation
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt
Refactored public screen function to internal; introduced modular composables (RecentTransactionScreenContent, RecentTransactionScreenDialog, TransactionFilterSheetContent); switched to state-driven UI with MifosElevatedScaffold, pull-to-refresh, and LazyColumn-based transaction rendering; replaced hard-coded strings with generated resources.
State Management
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt
Major refactor to BaseViewModel architecture; added network monitoring via NetworkMonitor; introduced new action/event/state types (RecentTransactionAction, RecentTransactionEvent, RecentTransactionUiState); implemented transaction filtering (ALL/DEBIT/CREDIT), grouping by date, and account-aware loading.
State Management
feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/utils/RecentTransactionState.kt
Removed entire file containing previous state definitions (enum TransactionFilterType, data class RecentTransactionUiState, sealed interfaces RecentTransactionAction, RecentTransactionEvent).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Arinyadav1
  • therajanmaurya

Poem

🐰 Hops with glee through filters bright,
Routes now serialized, state flows right,
BaseViewModel's grand new dance,
Screens refactored at a glance—
Navigation clean, our rabbits prance!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.84% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary changes: a screen redesign and state management update to BaseViewModel, which aligns with the main modifications across the codebase.
✨ 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.

Copy link
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: 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 transactionId is already a Long but is converted to String at line 190 (transactionId.toString()). The navigation callback in RecentTransactionNavGraph.kt accepts Long for accountId but String for transactionId. 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.

  1. The toUiTransaction() extension is only used within this internal class, so it should be marked as private for proper encapsulation.
  2. 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.navigation import appears to be unused since the code only uses composableWithSlideTransitions and 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.Serializable
feature/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 making FilterOptionChip internal.

FilterOptionChip is a public composable in a file where other composables are marked internal. For consistency and proper encapsulation, consider marking it internal unless 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

📥 Commits

Reviewing files that changed from the base of the PR and between 99c8d68 and 3ddb854.

📒 Files selected for processing (8)
  • cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
  • feature/recent-transaction/build.gradle.kts
  • feature/recent-transaction/src/commonMain/composeResources/values/strings.xml
  • feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt
  • feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavigation.kt
  • feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/screen/RecentTransactionScreen.kt
  • 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/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.kts
  • cmp-navigation/src/commonMain/kotlin/cmp/navigation/authenticated/AuthenticatedNavigation.kt
  • feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/navigation/RecentTransactionNavGraph.kt
  • feature/recent-transaction/src/commonMain/kotlin/org/mifos/mobile/feature/recent/transaction/viewmodel/RecentTransactionViewModel.kt
  • feature/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.kt
  • feature/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.kt
  • feature/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.kt
  • feature/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 @Serializable route 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 BaseViewModel with the appropriate type parameters and uses ScreenUiState for handling loading/success/error states. The initial state setup with clientId from userPreferencesRepository is 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 in ClientChargeViewModel and TransactionViewModel from the codebase.


355-371: Verify dividendPayout classification as debit.

dividendPayout is classified as a debit (returns false), 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 RecentTransactionUiState is well-structured with clear documentation. The computed hasActiveFilters property is a clean approach for deriving filter state. The sealed DialogState interface properly encapsulates dialog-related state.


444-473: Clean action/event separation.

The sealed interfaces for RecentTransactionAction and RecentTransactionEvent follow 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 recentTransactionDestination integration 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 the NavController.

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 @Serializable route object and composableWithSlideTransitions is well-implemented. The callback-based approach for navigateBack and navigateToDetails provides 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_label and balance are 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 RecentTransactionScreen composable is well-structured with:

  • Proper use of EventsEffect for handling one-time navigation events
  • remember(viewModel) wrapping for action callbacks to prevent unnecessary recompositions
  • Clean separation between screen entry point and content/dialog composables

@therajanmaurya therajanmaurya merged commit 73648d9 into openMF:development Jan 2, 2026
8 checks passed
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.

3 participants