Skip to content

Conversation

@Arinyadav1
Copy link
Contributor

@Arinyadav1 Arinyadav1 commented Nov 5, 2025

Fixes - Jira-#611

IMG_4970.1.MOV

Summary by CodeRabbit

  • New Features

    • Per-item expansion/collapse for savings listings.
    • Approval flow navigation added for savings accounts.
    • View-account navigation now forwards account type along with account ID.
  • Refactor

    • Expansion state externalized from listing components for caller control.
    • Switched list rendering to index-aware handling to support per-item expansion across deposit screens.
    • Updated navigation parameter signatures to support approve/view workflows.

@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Walkthrough

The expanded/collapse state for MifosActionsSavingsListingComponent was moved from internal component state to external props (isExpanded, onExpandToggle). Screens now manage per-item expansion with rememberSaveable. Navigation and ViewModel signatures were updated to include account type and an approval navigation callback.

Changes

Cohort / File(s) Summary
Core UI Component Refactoring
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt, core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosAllUiComponentsPreview.kt
MifosActionsSavingsListingComponent now accepts isExpanded: Boolean and onExpandToggle: () -> Unit; removed internal rememberSaveable-backed expansion state; header click delegates to onExpandToggle; AnimatedVisibility driven by isExpanded; previews updated to pass new params.
Screen Expansion State Management
feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt, feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt, feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt
Switched list rendering to itemsIndexed; introduced per-item expandedIndex using rememberSaveable/mutableStateOf; pass isExpanded and onExpandToggle into each MifosActionsSavingsListingComponent instance and wire toggle logic to update expandedIndex.
Navigation Updates
feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt, feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsRoute.kt
Added navigateToApproveAccount: (Int) -> Unit; changed navigateToViewAccount signature to (Int, SavingAccountDepositTypeEntity) -> Unit; wired navigation callbacks to navController::navigateToSavingsAccountSummaryScreen and navController::navigateToSavingsAccountApproval; added import for SavingAccountDepositTypeEntity.
Event and Action Signatures
feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt
Converted ApproveAccount from object to data class ApproveAccount(val accountId: Int); updated ViewAccount to data class ViewAccount(val accountId: Int, val accountType: SavingAccountDepositTypeEntity); adjusted ViewModel to emit events with the new parameters.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Screen
    participant Component as MifosActionsSavingsListingComponent
    participant ViewModel
    participant Navigation

    rect rgb(220,245,220)
    Note over User,Screen: Expand/collapse (per-item)
    User->>Screen: Click header
    Screen->>Screen: Update expandedIndex (rememberSaveable)
    Screen->>Component: render with isExpanded, onExpandToggle
    Component->>Component: AnimatedVisibility driven by isExpanded
    end

    rect rgb(245,245,220)
    Note over User,ViewModel: Approve flow
    User->>Component: Tap Approve
    Component->>Screen: emit Approve action (accountId)
    Screen->>ViewModel: handle ApproveAccount(accountId)
    ViewModel->>Navigation: navigateToApproveAccount(accountId)
    end

    rect rgb(245,220,245)
    Note over User,ViewModel: View flow with type
    User->>Component: Tap View
    Component->>Screen: emit View action (accountId, depositType)
    Screen->>ViewModel: handle ViewAccount(accountId, depositType)
    ViewModel->>Navigation: navigateToViewAccount(accountId, depositType)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • Consistency of all call sites after ViewAccount and ApproveAccount signature changes.
    • Proper persistence and edge cases of expandedIndex with rememberSaveable.
    • Navigation wiring propagation through the NavGraph and destinations.
    • UI callbacks to ensure no regressions in action handling (approve/view) and that index-to-id mappings are correct.

Possibly related PRs

  • Client add charge #2533 — Similar refactor of MifosActionsListingCardComponent.kt moving expansion state out of the component and into callers; likely overlaps in API changes.

Suggested reviewers

  • revanthkumarJ
  • biplab1

Poem

🐰 I nudged the state from inside to out,

Per-item springs that pop and shout,
Approvals hop with id and type,
Navigation bound, the flows take flight,
The rabbit cheers — compact and bright!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% 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 describes the main objective of the PR, which is connecting the savings account item list to the savings account detail page through navigation and state management changes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27811bc and 3842db5.

📒 Files selected for processing (1)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt

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.

@revanthkumarJ
Copy link
Contributor

@Arinyadav1 resolve the conflicts and let me know i will approve

@therajanmaurya therajanmaurya enabled auto-merge (squash) November 7, 2025 13:39
Copy link

@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: 14

Caution

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

⚠️ Outside diff range comments (2)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientLoanAccounts/ClientLoanAccountsViewModel.kt (1)

70-74: Critical: ViewAccount action missing account identifier.

The ViewAccount action is defined as a data object (line 161) and carries no parameters, yet this handler needs to know which loan account the user selected. Currently, only state.clientId is passed to the event, but there's no way to specify which loan account from the list should be viewed.

This prevents navigation to a specific account's detail page.

Apply this diff to fix the action and handler:

-            is ClientLoanAccountsAction.ViewAccount -> sendEvent(
+            is ClientLoanAccountsAction.ViewAccount -> sendEvent(
                 ClientLoanAccountsEvent.ViewAccount(
-                    state.clientId,
+                    action.accountId,
                 ),
             )

And update the action definition at line 161:

-    data object ViewAccount : ClientLoanAccountsAction
+    data class ViewAccount(val accountId: Int) : ClientLoanAccountsAction

You may also need to verify that the ClientLoanAccountsEvent.ViewAccount event carries the correct parameters for navigation (e.g., both clientId and accountId if both are required by the detail screen).

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileNavigation.kt (1)

24-46: Wire or remove the unused parameter.

The navigateToAddCharge parameter is accepted but never passed to ClientProfileScreen, creating dead code. Either wire it through to the screen or remove it from the function signature if it's not yet needed.

If the parameter should be wired, apply this diff:

 fun NavGraphBuilder.clientProfileDestination(
     onNavigateBack: () -> Unit,
     navController: NavController,
     notes: (Int) -> Unit,
     documents: (Int) -> Unit,
     identifiers: (Int) -> Unit,
     navigateToClientDetailsScreen: (Int) -> Unit,
     viewAddress: (Int) -> Unit,
     viewAssociatedAccounts: (Int) -> Unit,
     navigateToAddCharge: (Int) -> Unit,
 ) {
     composable<ClientProfileRoute> {
         ClientProfileScreen(
             notes = notes,
             documents = documents,
             identifiers = identifiers,
             onNavigateBack = onNavigateBack,
             navigateToClientDetailsScreen = navigateToClientDetailsScreen,
             viewAddress = viewAddress,
             viewAssociatedAccounts = viewAssociatedAccounts,
             navController = navController,
+            navigateToAddCharge = navigateToAddCharge,
         )
     }
 }

Otherwise, remove the parameter:

 fun NavGraphBuilder.clientProfileDestination(
     onNavigateBack: () -> Unit,
     navController: NavController,
     notes: (Int) -> Unit,
     documents: (Int) -> Unit,
     identifiers: (Int) -> Unit,
     navigateToClientDetailsScreen: (Int) -> Unit,
     viewAddress: (Int) -> Unit,
     viewAssociatedAccounts: (Int) -> Unit,
-    navigateToAddCharge: (Int) -> Unit,
 ) {
🧹 Nitpick comments (8)
feature/client/src/nativeMain/kotlin/com/mifos/feature/client/charges/ClientChargesScreen.native.kt (1)

27-34: LGTM: Appropriate stub implementation.

The placeholder implementation clearly communicates that this feature is not yet available on the native platform. The unused parameters are expected in a stub.

If you plan to implement native platform support in the future, consider adding a TODO comment with a tracking issue reference for visibility.

feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt (1)

68-70: Consider conditional rendering to avoid composing both empty card and empty LazyColumn.

The empty state logic correctly identifies when there are no items. However, both MifosEmptyCard and the LazyColumn (lines 72-145) will be composed when the list is empty. While this works functionally, you might want to conditionally render the LazyColumn only when there are items for cleaner composition.

For example:

 if (chargesPagingList.loadState.refresh is LoadState.NotLoading && chargesPagingList.itemCount == 0) {
     MifosEmptyCard()
-}
-
-LazyColumn {
+} else {
+    LazyColumn {
+        // ... existing content
+    }
+}

Alternatively, if you prefer to keep the current structure, that's also acceptable since the empty LazyColumn doesn't consume visual space.

core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)

156-162: Rename preview function for clarity.

The preview function has the same name as the composable (MifosProgressIndicatorMini), which can cause confusion. Consider using a more descriptive name following the established pattern in this file.

Apply this diff to align with the naming pattern:

 @Preview
 @Composable
-private fun MifosProgressIndicatorMini() {
+private fun MifosProgressIndicatorMini_Preview() {
     MifosTheme {
         MifosProgressIndicatorMini()
     }
 }
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt (1)

453-453: Use non-nullable Int type instead of Int?.

The expandedIndex is initialized to -1 and never assigned null, so the nullable type Int? is unnecessary. Using -1 as a sentinel for "no item expanded" is appropriate, but the type should reflect that it's always non-null.

Apply this diff:

-    var expandedIndex: Int? by rememberSaveable { mutableStateOf(-1) }
+    var expandedIndex: Int by rememberSaveable { mutableStateOf(-1) }
feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt (1)

101-103: Consider validating client ID before navigation.

The code falls back to -1 when state.client?.id is null. If the client ID is unavailable, navigating to add a charge with an invalid ID could cause downstream errors. Consider either:

  1. Disabling the "Add Charge" action when client data is unavailable, or
  2. Showing an error message instead of navigating with -1.

Example validation approach:

 ClientProfileDetailsActionItem.AddCharge -> {
-    navigateToAddCharge(state.client?.id ?: -1)
+    state.client?.id?.let { clientId ->
+        navigateToAddCharge(clientId)
+    } ?: run {
+        // Show error or log warning
+    }
 }
core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ChargeRepository.kt (1)

39-50: Standardize parameter ordering for consistency.

There's an inconsistency in parameter ordering across the interface:

  • Read operations (getListOfPagingCharges, getChargeTemplate, createCharges, getListOfClientCharges, getListOfOtherAccountCharge, getCharge) use resourceType first, then resourceId
  • Mutation operations (deleteCharge, updateCharge) use resourceId first, then resourceType

This inconsistency can lead to confusion and parameter-swapping errors.

Consider standardizing all methods to use resourceType first, then resourceId:

 suspend fun deleteCharge(
-    resourceId: Int,
     resourceType: String,
+    resourceId: Int,
     chargeId: Int,
 ): Flow<DataState<Unit>>

 suspend fun updateCharge(
-    resourceId: Int,
     resourceType: String,
+    resourceId: Int,
     chargeId: Int,
     payload: ChargesPayload,
 ): Flow<DataState<Unit>>
core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerCharge.kt (2)

86-101: Preserve exception context in error handling.

The error handling throws a new IllegalStateException without preserving the original exception context. This can make debugging more difficult in production.

Apply this diff to preserve the exception chain:

 suspend fun createCharges(
     resourceId: Int,
     resourceType: String,
     payload: ChargesPayload,
 ): ChargeCreationResponse {
     val response =
         mBaseApiManager.chargeService.createCharges(resourceType, resourceId, payload)

     if (!response.status.isSuccess()) {
         val errorMsg = extractErrorMessage(response)

-        throw IllegalStateException(errorMsg)
+        throw IllegalStateException(errorMsg, response.status.description?.let { Exception(it) })
     }

     return Json.decodeFromString<ChargeCreationResponse>(response.bodyAsText())
 }

Alternatively, consider defining a custom exception type that better represents API errors rather than using IllegalStateException.


103-127: Note: Parameter ordering inconsistency.

Similar to the comment on ChargeRepository.kt, these methods have resourceId before resourceType, while other methods in this class use resourceType first. Consider standardizing the parameter order across all methods for consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ece7c4a and 81567fb.

📒 Files selected for processing (62)
  • cmp-navigation/build.gradle.kts (1 hunks)
  • cmp-navigation/src/commonMain/kotlin/cmp/navigation/di/KoinModules.kt (2 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt (3 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/pagingSource/ClientChargesPagingSource.kt (3 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ChargeDialogRepository.kt (0 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ChargeRepository.kt (1 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ChargeDialogRepositoryImp.kt (0 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ChargeRepositoryImp.kt (1 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientChargeRepositoryImp.kt (0 hunks)
  • core/database/src/commonMain/kotlin/com/mifos/room/helper/ChargeDaoHelper.kt (2 hunks)
  • core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/theme/DesignToken.kt (1 hunks)
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt (2 hunks)
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateChargesUseCase.kt (1 hunks)
  • core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/GetChargesTemplateUseCase.kt (1 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/DataManager.kt (0 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerCharge.kt (2 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerRecurringAccount.kt (0 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/di/DataMangerModule.kt (2 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/ChargeService.kt (1 hunks)
  • core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt (7 hunks)
  • core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosAllUiComponentsPreview.kt (2 hunks)
  • core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (2 hunks)
  • feature/client/src/androidMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.android.kt (1 hunks)
  • feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargesScreen.android.kt (0 hunks)
  • feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt (3 hunks)
  • feature/client/src/commonMain/composeResources/values/strings.xml (3 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesRoute.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesScreen.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesViewModel.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientApplyNewApplications/ClientApplyNewApplicationRoute.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientApplyNewApplications/ClientApplyNewApplicationsScreen.kt (2 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientChargeDialog/ChargeDialogScreen.kt (0 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientChargeDialog/ChargeDialogUiState.kt (0 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargeUiState.kt (0 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargesScreen.kt (0 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargesViewModel.kt (0 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsNavigation.kt (2 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt (2 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientLoanAccounts/ClientLoanAccountsScreen.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientLoanAccounts/ClientLoanAccountsViewModel.kt (4 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileNavigation.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesRoute.kt (2 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesViewmodel.kt (3 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt (2 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt (5 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountViewModel.kt (3 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt (10 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (5 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountViewModel.kt (3 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt (8 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt (7 hunks)
  • feature/client/src/desktopMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.desktop.kt (2 hunks)
  • feature/client/src/nativeMain/kotlin/com/mifos/feature/client/charges/ClientChargesScreen.native.kt (2 hunks)
  • feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt (4 hunks)
  • feature/recurringDeposit/src/commonMain/composeResources/values/string.xml (1 hunks)
  • feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountRoute.kt (1 hunks)
  • feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountScreen.kt (4 hunks)
  • feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountViewModel.kt (3 hunks)
  • feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/di/RecurringDepositModule.kt (1 hunks)
  • feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/pages/DetailsPage.kt (1 hunks)
  • feature/savings/src/commonMain/kotlin/com/mifos/feature/savings/savingsAccountv2/SavingsAccountScreen.kt (3 hunks)
💤 Files with no reviewable changes (11)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ChargeDialogRepositoryImp.kt
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientChargeDialog/ChargeDialogUiState.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerRecurringAccount.kt
  • core/network/src/commonMain/kotlin/com/mifos/core/network/DataManager.kt
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargeUiState.kt
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargesViewModel.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientChargeRepositoryImp.kt
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ChargeDialogRepository.kt
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientChargeDialog/ChargeDialogScreen.kt
  • feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargesScreen.android.kt
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientCharges/ClientChargesScreen.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsViewModel.kt
🧰 Additional context used
🧬 Code graph analysis (14)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt (1)
  • MifosActionsSavingsListingComponent (728-819)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientLoanAccounts/ClientLoanAccountsScreen.kt (4)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)
  • MifosProgressIndicator (41-68)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosSearchBar.kt (1)
  • MifosSearchBar (40-104)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosEmptyCard.kt (1)
  • MifosEmptyCard (28-46)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt (1)
  • MifosActionsLoanListingComponent (401-502)
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountRoute.kt (1)
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountScreen.kt (1)
  • RecurringAccountScreen (43-66)
feature/client/src/androidMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.android.kt (5)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosSweetError.kt (1)
  • MifosSweetError (40-83)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)
  • MifosProgressIndicator (41-68)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBottomSheet.kt (1)
  • MifosBottomSheet (47-89)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt (1)
  • MifosActionsChargeListingComponent (598-726)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosTwoButtonRow.kt (1)
  • MifosTwoButtonRow (31-91)
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/pages/DetailsPage.kt (4)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosTextFieldDropdown.kt (1)
  • MifosTextFieldDropdown (39-112)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosOutlinedTextField.kt (1)
  • MifosDatePickerTextField (363-402)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)
  • MifosProgressIndicatorMini (122-146)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosTwoButtonRow.kt (1)
  • MifosTwoButtonRow (31-91)
core/data/src/commonMain/kotlin/com/mifos/core/data/pagingSource/ClientChargesPagingSource.kt (4)
core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ChargeRepository.kt (2)
  • getListOfPagingCharges (24-67)
  • getListOfPagingCharges (26-29)
core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ChargeRepositoryImp.kt (1)
  • getListOfPagingCharges (32-44)
core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerCharge.kt (1)
  • getListOfPagingCharges (54-80)
core/network/src/commonMain/kotlin/com/mifos/core/network/services/ChargeService.kt (1)
  • getListOfPagingCharges (77-83)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesRoute.kt (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesScreen.kt (1)
  • ChargesScreen (96-121)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/theme/Theme.kt (1)
  • MifosTheme (250-275)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesScreen.kt (11)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/EventsEffect.kt (1)
  • EventsEffect (28-43)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt (1)
  • MifosBreadcrumbNavBar (36-107)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRowWithTextAndButton.kt (1)
  • MifosRowWithTextAndButton (35-95)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (2)
  • MifosProgressIndicatorOverlay (70-102)
  • MifosProgressIndicator (41-68)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosErrorComponent.kt (1)
  • MifosErrorComponent (41-60)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosStatusDialog.kt (1)
  • MifosStatusDialog (36-103)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosBottomSheet.kt (1)
  • MifosBottomSheet (47-89)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt (1)
  • MifosActionsChargeListingComponent (598-726)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosTwoButtonRow.kt (1)
  • MifosTwoButtonRow (31-91)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosTextFieldDropdown.kt (1)
  • MifosTextFieldDropdown (39-112)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosOutlinedTextField.kt (1)
  • MifosDatePickerTextField (363-402)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt (2)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesRoute.kt (1)
  • chargesDestination (23-33)
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountRoute.kt (1)
  • recurringAccountDestination (22-32)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt (1)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/EventsEffect.kt (1)
  • EventsEffect (28-43)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesViewModel.kt (4)
core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ChargeRepository.kt (3)
  • updateCharge (45-50)
  • deleteCharge (39-43)
  • getCharge (62-66)
core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ChargeRepositoryImp.kt (3)
  • updateCharge (78-94)
  • deleteCharge (62-76)
  • getCharge (111-121)
core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerCharge.kt (3)
  • updateCharge (115-127)
  • deleteCharge (103-113)
  • getCharge (149-159)
core/network/src/commonMain/kotlin/com/mifos/core/network/services/ChargeService.kt (3)
  • updateCharge (174-180)
  • deleteCharge (158-163)
  • getCharge (125-130)
feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt (1)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosEmptyCard.kt (1)
  • MifosEmptyCard (28-46)
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountScreen.kt (5)
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/pages/DetailsPage.kt (1)
  • DetailsPage (51-168)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosBreadCrumb.kt (1)
  • MifosBreadcrumbNavBar (36-107)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosErrorComponent.kt (1)
  • MifosErrorComponent (41-60)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)
  • MifosProgressIndicator (41-68)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosStepper.kt (1)
  • MifosStepper (47-139)
🔇 Additional comments (34)
feature/client/src/nativeMain/kotlin/com/mifos/feature/client/charges/ClientChargesScreen.native.kt (2)

10-10: LGTM: Package reorganization.

The package rename from clientCharges to charges removes redundancy and aligns with the feature module structure.


23-25: LGTM: API alignment with multiplatform architecture.

The function rename and signature change align with the broader refactor to use action-based callbacks. The onAction: (ChargesAction) -> Unit parameter provides more flexibility than the previous onRetry callback.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientLoanAccounts/ClientLoanAccountsViewModel.kt (2)

100-131: LGTM: Loading state management is correct.

The loading state is properly managed—set to true at the start of the fetch operation and explicitly cleared to false in both success and error paths. This ensures the UI will always exit the loading state regardless of outcome.


134-146: LGTM: State definition with isLoading is well-structured.

The addition of the isLoading flag with a sensible default and the simplified DialogState (containing only Error) properly separates loading state from error state. This refactor improves clarity and aligns with the broader pattern applied across the PR.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientApplyNewApplications/ClientApplyNewApplicationsScreen.kt (2)

82-84: LGTM!

The call site correctly passes state.clientId to the recurring account navigation callback, matching the pattern used for loan, savings, and share accounts.


65-65: All upstream callers are correctly updated.

Verification confirms the signature change is properly implemented across the codebase:

  • Route definition expects onNavigateApplyRecurringAccount: (Int) -> Unit
  • Navigation function navigateToRecurringAccountRoute(clientId: Int) matches this signature
  • Call site passes the correct method reference with matching signature

No further changes needed.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientApplyNewApplications/ClientApplyNewApplicationRoute.kt (1)

28-28: LGTM!

The signature change is consistent with the screen implementation and follows the established navigation pattern. The callback is correctly propagated to ClientApplyNewApplicationsScreen at line 38.

core/network/src/commonMain/kotlin/com/mifos/core/network/di/DataMangerModule.kt (1)

27-27: LGTM!

The import is correctly placed in alphabetical order.

feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt (1)

36-36: LGTM!

The import is properly added to support the empty state rendering below.

feature/savings/src/commonMain/kotlin/com/mifos/feature/savings/savingsAccountv2/SavingsAccountScreen.kt (2)

37-40: LGTM! Necessary imports for state management.

The added imports support the new per-item expansion state introduced in ShowChargesDialog.


352-356: Verification confirms ID assumptions are valid.

The expansion toggle implementation is safe:

  • Charge IDs are sourced from API data (selectedCharge.id), not user-assigned
  • The -1 sentinel is never assigned as a valid charge ID
  • No collision risk exists

The code can be approved as-is. Note: The type design using Int? with -1 default is semantically inconsistent but functionally correct and matches the existing codebase pattern.

core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosProgressIndicator.kt (1)

122-146: Verify animation iterations behavior.

The animateLottieCompositionAsState call at Line 131 doesn't specify an iterations parameter, so the animation will play once by default. Other progress indicators use iterations = Int.MAX_VALUE for continuous animation. Confirm whether the single-play behavior is intentional for this mini indicator or if continuous animation is needed.

If continuous animation is desired, apply this diff:

-    val progress by animateLottieCompositionAsState(composition)
+    val progress by animateLottieCompositionAsState(
+        composition,
+        iterations = Int.MAX_VALUE,
+    )
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/newLoanAccount/NewLoanAccountScreen.kt (2)

44-47: LGTM!

The new imports support the externalized expansion state management pattern introduced in this file.


477-480: LGTM!

The expansion toggle logic correctly implements single-item expansion using charge IDs as keys. The pattern is consistent across both overdue and regular charges.

Note: The implementation assumes that it.id values are unique across all charges. If duplicate IDs exist, multiple items may appear expanded/collapsed together.

Also applies to: 508-511

core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosAllUiComponentsPreview.kt (2)

170-171: LGTM!

The preview correctly supplies the new isExpanded and onExpandToggle parameters, showing the component in its expanded state.


938-939: LGTM!

The preview parameters are updated to match the new component API, replacing isExpandable with externally controlled isExpanded and onExpandToggle.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsScreen.kt (1)

89-89: LGTM!

The new navigateToAddCharge callback follows the established pattern for navigation functions in this screen.

feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/di/RecurringDepositModule.kt (1)

1-18: LGTM!

The new DI module follows the established pattern for feature modules and correctly exposes the RecurringAccountViewModel. The module is properly integrated into the DI graph via KoinModules.kt.

cmp-navigation/src/commonMain/kotlin/cmp/navigation/di/KoinModules.kt (1)

34-34: LGTM!

The RecurringDepositModule is properly imported and registered in the DI graph, following the established pattern for feature modules.

Also applies to: 87-87

feature/client/src/desktopMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.desktop.kt (1)

10-10: LGTM!

The API surface updates align with the broader refactoring to use action-based callbacks. Since this is a desktop stub showing "Not available in desktop yet", the onAction parameter is appropriately unused.

Also applies to: 23-25

core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt (1)

42-42: All references to GetAllChargesV2UseCase have been successfully updated.

Verification confirms:

  • The old use case file no longer exists
  • No remaining references to GetAllChargesV2UseCase in the codebase
  • GetChargesTemplateUseCase is properly imported at line 42
  • The new use case is correctly registered in the DI module at line 120
  • ChargesViewModel is actively using the new use case
feature/client/src/commonMain/kotlin/com/mifos/feature/client/di/ClientModule.kt (1)

14-14: All references to ClientChargesViewModel have been successfully updated.

The verification confirms that the migration from ClientChargesViewModel to ChargesViewModel is complete. The DI module correctly imports and binds ChargesViewModel at lines 14 and 53, with no remaining references to the old ViewModel name found anywhere in the codebase.

core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/GetChargesTemplateUseCase.kt (1)

23-25: Flow wrapping aligns with repository contract.

Resource-scoped fetch with asDataStateFlow() keeps the API neat; no issues spotted.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt (1)

190-238: Expansion wiring and action dispatch look good.

Indexed expansion plus the routed approve callback keep behavior intact.

core/database/src/commonMain/kotlin/com/mifos/room/helper/ChargeDaoHelper.kt (1)

32-61: Rename stays consistent.

Resource-scoped save mirrors prior flow; no issues spotted.

core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/CreateChargesUseCase.kt (1)

24-29: Resource-based call update looks correct.

Constructor wiring and the invoke delegation now match the new ChargeRepository.createCharges(resourceType, resourceId, payload) contract—no issues spotted here.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientDetailsProfile/ClientProfileDetailsNavigation.kt (1)

34-50: New add-charge callback is wired through.

The extra lambda is threaded cleanly from the destination builder into ClientProfileDetailsScreen, keeping the nav surface consistent.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.kt (1)

18-22: Shared ShowClientCharge entry point looks solid.

The expect composable takes the paging stream and action callback we need for platform actuals; no concerns.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountViewModel.kt (1)

133-158: Loading flag handling reads well.

The DataState branches now toggle isLoading while clearing dialog state, which keeps UI feedback straightforward.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt (1)

64-189: Navigation handling now carries account context.

Forwarding accountId + depositType for view and exposing the approve route keeps the screen aligned with the updated event model—looks good.

core/data/src/commonMain/kotlin/com/mifos/core/data/pagingSource/ClientChargesPagingSource.kt (1)

18-22: LGTM: Clean refactor to resource-based pattern.

The generalization from clientId to resourceType/resourceId makes this paging source reusable across different resource types (clients, savings accounts, loans, etc.), aligning well with the PR's objective to connect multiple account types.

feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountScreen.kt (2)

45-49: LGTM: Proper DI integration.

The migration from viewModel() to koinViewModel() aligns with the Koin dependency injection pattern used across the codebase, and the addition of navController enables breadcrumb navigation.


109-141: LGTM: Well-structured state-driven UI.

The state-based rendering pattern (Loading → Error → Success) with breadcrumb navigation provides proper user feedback and improves navigation UX. The state handling is clean and follows best practices.

core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ChargeRepositoryImp.kt (1)

28-122: LGTM: Clean repository implementation.

The implementation correctly delegates to DataManagerCharge and properly wraps results in Flow<DataState<...>> for consistent error handling across the data layer. The paging integration is well-structured.

val extraLarge: Dp = 28.dp,
val extraLargeIncreased: Dp = 32.dp,
val extraExtraLarge: Dp = 48.dp,
val half: Dp = 500.dp,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Update documentation and verify usage of the new spacing value.

The new half spacing field is missing from the KDoc comment above (lines 72-82), which documents all other spacing values. Additionally, the name "half" breaks the established semantic naming pattern (extraSmall, small, medium, large, etc.) and may cause confusion.

Please add documentation for this field. Apply this diff:

  * @param extraExtraLarge Significant spacing for major layout divisions or empty states (48.dp).
+ * @param half Half of maximum spacing, used for substantial offsets or specific layout needs (500.dp).
  * @param full Maximum spacing, typically used for centering or deep offset layouts (1000.dp).

Consider renaming to better match the semantic pattern, such as halfFull, substantial, or extraExtraExtraLarge.

Verify that this spacing value is used correctly across the codebase:


🏁 Script executed:

#!/bin/bash
# Description: Find usages of the new 'half' spacing value to confirm it's needed and applied correctly

# Search for references to DesignToken.spacing.half or spacing.half
rg -n --type=kotlin 'spacing\.half' -C 3

# Also check for any hardcoded 500.dp values that might be replaced by this token
rg -n --type=kotlin '\b500\.dp\b' -C 2

Length of output: 3973


Add documentation and replace hardcoded 500.dp values with the new token.

The new half spacing field is missing from the KDoc comment (lines 72-82). Additionally, two hardcoded 500.dp values in the codebase should be replaced with DesignToken.spacing.half for consistency and centralized design management.

Add documentation to DesignToken.kt with this diff:

  * @param extraExtraLarge Significant spacing for major layout divisions or empty states (48.dp).
+ * @param half Half of maximum spacing, used for constraining scrollable content heights (500.dp).
  * @param full Maximum spacing, typically used for centering or deep offset layouts (1000.dp).

Replace hardcoded values:

  • core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRadioButtonAlertDialog.kt line 56: .heightIn(max = 500.dp).heightIn(max = DesignToken.spacing.half)
  • core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosAlertDialog.kt line 130: .heightIn(max = 500.dp).heightIn(max = DesignToken.spacing.half)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/theme/DesignToken.kt
around line 96, add the missing KDoc entry for the new spacing field `half`
within the existing KDoc block (lines ~72-82) describing its purpose (represents
half spacing, maps to 500.dp) and ensure the property declaration remains `val
half: Dp = 500.dp`; then replace hardcoded 500.dp usages with the new token: in
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosRadioButtonAlertDialog.kt
at line ~56 change `.heightIn(max = 500.dp)` to `.heightIn(max =
DesignToken.spacing.half)` and in
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosAlertDialog.kt
at line ~130 change `.heightIn(max = 500.dp)` to `.heightIn(max =
DesignToken.spacing.half)`.

Comment on lines 65 to 111
val chargesList = chargesPagingList[0]?.pageItems ?: emptyList()

MifosBottomSheet(
onDismiss = {
onAction(ChargesAction.DismissDialog)
},
content = {
Column(
modifier = Modifier.padding(DesignToken.padding.large)
.heightIn(max = DesignToken.spacing.half),
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.largeIncreased),
) {
Text(
text = stringResource(Res.string.charges_view_charges),
style = MifosTypography.titleMediumEmphasized,
)

LazyColumn(
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.medium),
) {
items(chargesList) {
MifosActionsChargeListingComponent(
chargeTitle = it.name.toString(),
type = it.chargeCalculationType?.value.toString(),
date = it.formattedDueDate,
collectedOn = it.formattedDueDate,
amount = it.amount.toString(),
onActionClicked = { action ->
when (action) {
is Actions.Delete -> {
onAction(ChargesAction.DeleteCharge(it.id))
}

is Actions.Edit -> {
onAction(ChargesAction.FetchEditChargeData(it.id))
}

else -> {}
}
},
isExpanded = expandedIndex == it.id,
onExpandToggle = {
expandedIndex = if (expandedIndex == it.id) -1 else it.id
},
)
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Paging pipeline only renders the first page.

chargesPagingList[0]?.pageItems drops every subsequent page, so accounts with >1 page of charges will never see later entries. Please iterate over all loaded pages instead of hard-coding index 0.

Apply this diff to materialize every page item:

-            val chargesList = chargesPagingList[0]?.pageItems ?: emptyList()
-
             MifosBottomSheet(
                 onDismiss = {
                     onAction(ChargesAction.DismissDialog)
                 },
                 content = {
                     Column(
                         modifier = Modifier.padding(DesignToken.padding.large)
                             .heightIn(max = DesignToken.spacing.half),
                         verticalArrangement = Arrangement.spacedBy(DesignToken.padding.largeIncreased),
                     ) {
                         Text(
                             text = stringResource(Res.string.charges_view_charges),
                             style = MifosTypography.titleMediumEmphasized,
                         )

                         LazyColumn(
                             verticalArrangement = Arrangement.spacedBy(DesignToken.padding.medium),
                         ) {
-                            items(chargesList) {
-                                MifosActionsChargeListingComponent(
-                                    chargeTitle = it.name.toString(),
-                                    type = it.chargeCalculationType?.value.toString(),
-                                    date = it.formattedDueDate,
-                                    collectedOn = it.formattedDueDate,
-                                    amount = it.amount.toString(),
-                                    onActionClicked = { action ->
-                                        when (action) {
-                                            is Actions.Delete -> {
-                                                onAction(ChargesAction.DeleteCharge(it.id))
-                                            }
-
-                                            is Actions.Edit -> {
-                                                onAction(ChargesAction.FetchEditChargeData(it.id))
-                                            }
-
-                                            else -> {}
-                                        }
-                                    },
-                                    isExpanded = expandedIndex == it.id,
-                                    onExpandToggle = {
-                                        expandedIndex = if (expandedIndex == it.id) -1 else it.id
-                                    },
-                                )
-                            }
+                            items(count = chargesPagingList.itemCount) { pageIndex ->
+                                chargesPagingList[pageIndex]?.pageItems.orEmpty().forEach { charge ->
+                                    MifosActionsChargeListingComponent(
+                                        chargeTitle = charge.name.toString(),
+                                        type = charge.chargeCalculationType?.value.toString(),
+                                        date = charge.formattedDueDate,
+                                        collectedOn = charge.formattedDueDate,
+                                        amount = charge.amount.toString(),
+                                        onActionClicked = { action ->
+                                            when (action) {
+                                                is Actions.Delete -> {
+                                                    onAction(ChargesAction.DeleteCharge(charge.id))
+                                                }
+
+                                                is Actions.Edit -> {
+                                                    onAction(ChargesAction.FetchEditChargeData(charge.id))
+                                                }
+
+                                                else -> {}
+                                            }
+                                        },
+                                        isExpanded = expandedIndex == charge.id,
+                                        onExpandToggle = {
+                                            expandedIndex = if (expandedIndex == charge.id) -1 else charge.id
+                                        },
+                                    )
+                                }
+                            }
                         }

                         MifosTwoButtonRow(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val chargesList = chargesPagingList[0]?.pageItems ?: emptyList()
MifosBottomSheet(
onDismiss = {
onAction(ChargesAction.DismissDialog)
},
content = {
Column(
modifier = Modifier.padding(DesignToken.padding.large)
.heightIn(max = DesignToken.spacing.half),
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.largeIncreased),
) {
Text(
text = stringResource(Res.string.charges_view_charges),
style = MifosTypography.titleMediumEmphasized,
)
LazyColumn(
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.medium),
) {
items(chargesList) {
MifosActionsChargeListingComponent(
chargeTitle = it.name.toString(),
type = it.chargeCalculationType?.value.toString(),
date = it.formattedDueDate,
collectedOn = it.formattedDueDate,
amount = it.amount.toString(),
onActionClicked = { action ->
when (action) {
is Actions.Delete -> {
onAction(ChargesAction.DeleteCharge(it.id))
}
is Actions.Edit -> {
onAction(ChargesAction.FetchEditChargeData(it.id))
}
else -> {}
}
},
isExpanded = expandedIndex == it.id,
onExpandToggle = {
expandedIndex = if (expandedIndex == it.id) -1 else it.id
},
)
}
}
MifosBottomSheet(
onDismiss = {
onAction(ChargesAction.DismissDialog)
},
content = {
Column(
modifier = Modifier.padding(DesignToken.padding.large)
.heightIn(max = DesignToken.spacing.half),
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.largeIncreased),
) {
Text(
text = stringResource(Res.string.charges_view_charges),
style = MifosTypography.titleMediumEmphasized,
)
LazyColumn(
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.medium),
) {
items(count = chargesPagingList.itemCount) { pageIndex ->
chargesPagingList[pageIndex]?.pageItems.orEmpty().forEach { charge ->
MifosActionsChargeListingComponent(
chargeTitle = charge.name.toString(),
type = charge.chargeCalculationType?.value.toString(),
date = charge.formattedDueDate,
collectedOn = charge.formattedDueDate,
amount = charge.amount.toString(),
onActionClicked = { action ->
when (action) {
is Actions.Delete -> {
onAction(ChargesAction.DeleteCharge(charge.id))
}
is Actions.Edit -> {
onAction(ChargesAction.FetchEditChargeData(charge.id))
}
else -> {}
}
},
isExpanded = expandedIndex == charge.id,
onExpandToggle = {
expandedIndex = if (expandedIndex == charge.id) -1 else charge.id
},
)
}
}
}
🤖 Prompt for AI Agents
In
feature/client/src/androidMain/kotlin/com/mifos/feature/client/charges/ShowClientCharge.android.kt
around lines 65 to 111, the code currently uses chargesPagingList[0]?.pageItems
which only takes the first page and drops subsequent pages; replace that with a
safe aggregation across all loaded pages (e.g., iterate over chargesPagingList
and collect/flatten each pageItems into a single list, handling null pages and
null pageItems by using empty lists) and then use that flattened list for the
LazyColumn items so every loaded page item is rendered.

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify if this import is necessary.

The items import appears to be for the List/Array-based extension function, but the code uses items(count = ...) at line 73, which is a different overload from LazyListScope. Please confirm whether this import is actually needed.

Run the following script to check if the List-based items function is used elsewhere in this file:


🏁 Script executed:

#!/bin/bash
# Check if the items function is used with a List or collection in this file
rg -n 'items\s*\(' feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt -A 2

Length of output: 142



---

🏁 Script executed:

```shell
#!/bin/bash
# View the import section and LazyColumn context to confirm
sed -n '1,30p' feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt && echo "---" && sed -n '70,80p' feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt

Length of output: 166



---

🏁 Script executed:

```shell
#!/bin/bash
# View the import section and LazyColumn context to confirm
sed -n '1,30p' feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt && echo "---" && sed -n '70,80p' feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt

Length of output: 1828


Remove the unused items import at line 20.

The import androidx.compose.foundation.lazy.items is for List/Array-based extension functions, but the code uses items(count = ...) at line 73, which is the count-based overload built into LazyListScope. This import is not needed.

🤖 Prompt for AI Agents
In
feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientUpcomingCharges/ClientUpcomingChargesScreen.android.kt
around line 20, the import androidx.compose.foundation.lazy.items is unused
because the file uses the count-based items(count = ...) overload; remove that
import line to eliminate the unused import.

Comment on lines 17 to 21
@Serializable
data class ChargesRoute(
val resourceId: Int = -1,
val resourceType: String = "",
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify sentinel default values are validated before use.

The default values resourceId = -1 and resourceType = "" serve as sentinel values. Ensure that ChargesScreen or its ViewModel validates these before making API calls, as invalid defaults could lead to runtime errors or unexpected API behavior.

Run this script to verify validation logic in ChargesScreen and ChargesViewModel:


🏁 Script executed:

#!/bin/bash
# Description: Check if ChargesScreen/ChargesViewModel validates resourceId and resourceType

# Search for validation of resourceId and resourceType in ChargesScreen and ChargesViewModel
rg -nP -A5 -B5 'resourceId.*(-1|validation|check|require)' --type=kt -g '**/charges/**'
rg -nP -A5 -B5 'resourceType.*(isEmpty|isBlank|validation|check|require)' --type=kt -g '**/charges/**'

Length of output: 53


🏁 Script executed:

#!/bin/bash
# Find relevant Kotlin files in charges directory
echo "=== Finding Kotlin files in charges directory ==="
fd -e kt -p '.*charges.*' | head -20

echo -e "\n=== Searching for ChargesScreen ==="
fd -e kt 'ChargesScreen' 

echo -e "\n=== Searching for ChargesViewModel ==="
fd -e kt 'ChargesViewModel'

Length of output: 2624


🏁 Script executed:

#!/bin/bash
# Search for validation patterns around resourceId and resourceType
echo "=== Checking for resourceId validation ==="
rg -n 'resourceId' -g '**charges**' -A3 -B3 | head -50

echo -e "\n=== Checking for resourceType validation ==="
rg -n 'resourceType' -g '**charges**' -A3 -B3 | head -50

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Search for patterns indicating validation: require, check, isEmpty, isBlank, etc
echo "=== Checking for defensive checks before API calls ==="
rg -n '(require|check|isEmpty|isBlank|validates|guard)' -g '**charges**' | head -30

Length of output: 54


🏁 Script executed:

#!/bin/bash
# Read the ChargesScreen and ChargesViewModel files directly
echo "=== ChargesScreen.kt ==="
cat feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesScreen.kt

echo -e "\n\n=== ChargesViewModel.kt ==="
cat feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesViewModel.kt

Length of output: 39987


Validate sentinel route parameters before making API calls.

The default values resourceId = -1 and resourceType = "" are sentinel values that lack validation before use. In ChargesViewModel.observeNetwork(), these values are passed directly to repository.getListOfClientCharges(), repository.getListOfOtherAccountCharge(), and getChargeTemplateUseCase() without guard clauses. Add validation (e.g., require(route.resourceId > 0) and require(route.resourceType.isNotEmpty())) in observeNetwork() or in the init block to prevent invalid API calls.

🤖 Prompt for AI Agents
In
feature/client/src/commonMain/kotlin/com/mifos/feature/client/charges/ChargesRoute.kt
around lines 17 to 21, the data class uses sentinel defaults (resourceId = -1,
resourceType = ""), so update the consumer (ChargesViewModel.observeNetwork() or
the ChargesRoute init) to validate these before making API calls: add
require(route.resourceId > 0) and require(route.resourceType.isNotEmpty()) (or
equivalent guard clauses) and bail out or return early if validation fails so
repository.getListOfClientCharges(), repository.getListOfOtherAccountCharge(),
and getChargeTemplateUseCase() are never called with invalid parameters.

Comment on lines 233 to 237
is Actions.ApproveAccount -> {
RecurringDepositAccountAction.ApproveAccount(
recurringDeposit.accountNo ?: "",
)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Approve action never dispatches.

Line 234 instantiates RecurringDepositAccountAction.ApproveAccount but fails to call onAction, so tapping “Approve” now does nothing. Please forward the action just like the view branch.

Apply this diff:

-                                    is Actions.ApproveAccount -> {
-                                        RecurringDepositAccountAction.ApproveAccount(
-                                            recurringDeposit.accountNo ?: "",
-                                        )
-                                    }
+                                    is Actions.ApproveAccount -> {
+                                        onAction(
+                                            RecurringDepositAccountAction.ApproveAccount(
+                                                recurringDeposit.accountNo ?: "",
+                                            ),
+                                        )
+                                    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
is Actions.ApproveAccount -> {
RecurringDepositAccountAction.ApproveAccount(
recurringDeposit.accountNo ?: "",
)
}
is Actions.ApproveAccount -> {
onAction(
RecurringDepositAccountAction.ApproveAccount(
recurringDeposit.accountNo ?: "",
),
)
}
🤖 Prompt for AI Agents
In
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt
around lines 233 to 237, the Approve branch constructs
RecurringDepositAccountAction.ApproveAccount but never dispatches it; change the
code to call onAction with that action (i.e., replace the bare instantiation
with
onAction(RecurringDepositAccountAction.ApproveAccount(recurringDeposit.accountNo
?: ""))) so the tap triggers the action, mirroring the view branch behavior.

Comment on lines 47 to 53
import org.jetbrains.compose.resources.stringResource
import kotlin.time.Clock
import kotlin.time.ExperimentalTime

@OptIn(ExperimentalTime::class, ExperimentalMaterial3Api::class)
@Composable
fun DetailsPage(onNext: () -> Unit) {
fun DetailsPage(
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix the Clock import to restore compilation.

Clock.System lives in kotlinx.datetime.Clock; importing kotlin.time.Clock leaves System unresolved and the file won’t compile. Drop the ExperimentalTime opt-in and use the datetime Clock instead.

-import kotlin.time.Clock
-import kotlin.time.ExperimentalTime
-
-@OptIn(ExperimentalTime::class, ExperimentalMaterial3Api::class)
+import kotlinx.datetime.Clock
+
+@OptIn(ExperimentalMaterial3Api::class)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import org.jetbrains.compose.resources.stringResource
import kotlin.time.Clock
import kotlin.time.ExperimentalTime
@OptIn(ExperimentalTime::class, ExperimentalMaterial3Api::class)
@Composable
fun DetailsPage(onNext: () -> Unit) {
fun DetailsPage(
import org.jetbrains.compose.resources.stringResource
import kotlinx.datetime.Clock
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DetailsPage(
🤖 Prompt for AI Agents
In
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/pages/DetailsPage.kt
around lines 47-53, the file incorrectly imports kotlin.time.Clock and opts into
ExperimentalTime which makes Clock.System unresolved; remove the import of
kotlin.time.Clock, remove the ExperimentalTime opt-in, add an import for
kotlinx.datetime.Clock (so you can use Clock.System), and keep the existing
ExperimentalMaterial3Api opt-in only.

Comment on lines 114 to 152
if (!state.template?.fieldOfficerOptions.isNullOrEmpty()) {
MifosDatePickerTextField(
value = state.submissionDate,
label = stringResource(Res.string.submitted_on),
openDatePicker = {
onAction(RecurringAccountAction.OnSubmissionDatePick(true))
},
)

Spacer(Modifier.height(DesignToken.padding.large))
MifosTextFieldDropdown(
value = if (state.fieldOfficerIndex == -1) {
""
} else {
state.fieldOfficerOptions?.get(state.fieldOfficerIndex)?.displayName ?: ""
},
onValueChanged = {},
onOptionSelected = { index, value ->
onAction(RecurringAccountAction.OnFieldOfficerChange(index))
},
options = state.fieldOfficerOptions?.mapNotNull {
it.displayName
} ?: emptyList(),
label = stringResource(Res.string.field_officer),
)

MifosOutlinedTextField(
value = state.externalId,
onValueChange = {
onAction(RecurringAccountAction.OnExternalIdChange(it))
},
label = stringResource(Res.string.external_id),
config = MifosTextFieldConfig(
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
),
),
)
Spacer(Modifier.height(DesignToken.padding.large))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Do not hide submission date/external ID behind field-officer options.

By wrapping the submission date picker and external ID field inside if (!state.template?.fieldOfficerOptions.isNullOrEmpty()), those inputs disappear whenever the template has no field officer choices—users then lose mandatory form fields. Please move the conditional so only the field-officer dropdown is gated.

-        if (!state.template?.fieldOfficerOptions.isNullOrEmpty()) {
-            MifosDatePickerTextField(...)
-            ...
-            MifosTextFieldDropdown( // field officer
-                ...
-            )
-
-            MifosOutlinedTextField(...)
-            Spacer(...)
-        }
+        MifosDatePickerTextField(...)
+
+        Spacer(Modifier.height(DesignToken.padding.large))
+
+        if (!state.template?.fieldOfficerOptions.isNullOrEmpty()) {
+            MifosTextFieldDropdown(
+                ...
+            )
+            Spacer(Modifier.height(DesignToken.padding.large))
+        }
+
+        MifosOutlinedTextField(...)
+        Spacer(Modifier.height(DesignToken.padding.large))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!state.template?.fieldOfficerOptions.isNullOrEmpty()) {
MifosDatePickerTextField(
value = state.submissionDate,
label = stringResource(Res.string.submitted_on),
openDatePicker = {
onAction(RecurringAccountAction.OnSubmissionDatePick(true))
},
)
Spacer(Modifier.height(DesignToken.padding.large))
MifosTextFieldDropdown(
value = if (state.fieldOfficerIndex == -1) {
""
} else {
state.fieldOfficerOptions?.get(state.fieldOfficerIndex)?.displayName ?: ""
},
onValueChanged = {},
onOptionSelected = { index, value ->
onAction(RecurringAccountAction.OnFieldOfficerChange(index))
},
options = state.fieldOfficerOptions?.mapNotNull {
it.displayName
} ?: emptyList(),
label = stringResource(Res.string.field_officer),
)
MifosOutlinedTextField(
value = state.externalId,
onValueChange = {
onAction(RecurringAccountAction.OnExternalIdChange(it))
},
label = stringResource(Res.string.external_id),
config = MifosTextFieldConfig(
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
),
),
)
Spacer(Modifier.height(DesignToken.padding.large))
MifosDatePickerTextField(
value = state.submissionDate,
label = stringResource(Res.string.submitted_on),
openDatePicker = {
onAction(RecurringAccountAction.OnSubmissionDatePick(true))
},
)
Spacer(Modifier.height(DesignToken.padding.large))
if (!state.template?.fieldOfficerOptions.isNullOrEmpty()) {
MifosTextFieldDropdown(
value = if (state.fieldOfficerIndex == -1) {
""
} else {
state.fieldOfficerOptions?.get(state.fieldOfficerIndex)?.displayName ?: ""
},
onValueChanged = {},
onOptionSelected = { index, value ->
onAction(RecurringAccountAction.OnFieldOfficerChange(index))
},
options = state.fieldOfficerOptions?.mapNotNull {
it.displayName
} ?: emptyList(),
label = stringResource(Res.string.field_officer),
)
Spacer(Modifier.height(DesignToken.padding.large))
}
MifosOutlinedTextField(
value = state.externalId,
onValueChange = {
onAction(RecurringAccountAction.OnExternalIdChange(it))
},
label = stringResource(Res.string.external_id),
config = MifosTextFieldConfig(
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
),
),
)
Spacer(Modifier.height(DesignToken.padding.large))
🤖 Prompt for AI Agents
In
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/pages/DetailsPage.kt
around lines 114 to 152, the submission date picker and external ID field are
incorrectly placed inside the conditional that checks fieldOfficerOptions,
causing them to be hidden when no field-officer options exist; refactor by
moving the if (!state.template?.fieldOfficerOptions.isNullOrEmpty()) so it wraps
only the MifosTextFieldDropdown block (leave MifosDatePickerTextField and
MifosOutlinedTextField outside and always rendered), and ensure the dropdown
still uses the options mapping and index handling as before.

Comment on lines 27 to 30
onNavigateBack = {},
onFinish = {},
navController = navController,
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Restore navigation callbacks in RecurringAccountScreen wiring
Line 27 currently passes onNavigateBack = {} and onFinish = {}. RecurringAccountScreen raises these callbacks when the user taps back or after completing account creation, so turning them into no-ops leaves the user stuck on this screen. Please hook them back to real navigation (e.g., by calling the appropriate navController operations) instead of empty lambdas.

         RecurringAccountScreen(
-            onNavigateBack = {},
-            onFinish = {},
+            onNavigateBack = { navController.popBackStack() },
+            onFinish = { navController.popBackStack() },
             navController = navController,
         )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onNavigateBack = {},
onFinish = {},
navController = navController,
)
RecurringAccountScreen(
onNavigateBack = { navController.popBackStack() },
onFinish = { navController.popBackStack() },
navController = navController,
)
🤖 Prompt for AI Agents
In
feature/recurringDeposit/src/commonMain/kotlin/com/mifos/feature/recurringDeposit/newRecurringDepositAccount/RecurringAccountRoute.kt
around lines 27–30, the call sites currently pass onNavigateBack = {} and
onFinish = {}, which are no-ops and prevent navigation; replace those lambdas
with real navController operations: set onNavigateBack to call
navController.popBackStack() (or navController.navigateUp()) and set onFinish to
navigate to the post-creation destination (e.g.,
navController.navigate("accounts") or the specific account details route),
making sure to use appropriate nav options (popUpTo or clearBackStack) if needed
to prevent returning to the form.

Comment on lines 309 to 310
var expandedIndex: Int? by rememberSaveable { mutableStateOf(-1) }

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix type inconsistency and clarify variable naming.

Two issues with the state declaration:

  1. Type mismatch: Declaring Int? (nullable) but initializing with non-null -1 is inconsistent.
  2. Misleading name: expandedIndex suggests it stores an index, but Line 352 shows it actually stores an id value from it.id.

Apply this diff to use idiomatic nullable handling and clearer naming:

-    var expandedIndex: Int? by rememberSaveable { mutableStateOf(-1) }
+    var expandedItemId: Int? by rememberSaveable { mutableStateOf(null) }

Then update the toggle logic accordingly:

-                        isExpanded = expandedIndex == it.id,
+                        isExpanded = expandedItemId == it.id,
                         onExpandToggle = {
-                            expandedIndex = if (expandedIndex == it.id) -1 else it.id
+                            expandedItemId = if (expandedItemId == it.id) null else it.id
                         },

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
feature/savings/src/commonMain/kotlin/com/mifos/feature/savings/savingsAccountv2/SavingsAccountScreen.kt
around lines 309–310, the state is declared as `var expandedIndex: Int? by
rememberSaveable { mutableStateOf(-1) }` which mixes a nullable type with a
non-null sentinel and the name implies an index while you actually store an id;
change the variable to a nullable id name (e.g., `expandedId: Int?`) and
initialize it with `null` via rememberSaveable { mutableStateOf<Int?>(null) };
then update the toggle logic to compare against `it.id` and set `expandedId = if
(expandedId == it.id) null else it.id`, and update any other usages/readers to
use the new name and nullable semantics.

# Conflicts:
#	feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt
#	feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt
#	feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt
@Arinyadav1 Arinyadav1 force-pushed the connect-saving-item-to-saving-detail-page branch from 81567fb to 27811bc Compare November 7, 2025 16:00
@Arinyadav1
Copy link
Contributor Author

@revanthkumarJ resolve merge conflicts

@therajanmaurya therajanmaurya merged commit a762133 into openMF:development Nov 19, 2025
2 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