Skip to content

fix(client): Added Create Account buttons for all types of accounts.#2583

Open
techsavvy185 wants to merge 9 commits intoopenMF:developmentfrom
techsavvy185:createAccountFlow
Open

fix(client): Added Create Account buttons for all types of accounts.#2583
techsavvy185 wants to merge 9 commits intoopenMF:developmentfrom
techsavvy185:createAccountFlow

Conversation

@techsavvy185
Copy link
Contributor

@techsavvy185 techsavvy185 commented Jan 25, 2026

Fixes - Jira-#629

Screen_recording_20260127_184125.webm

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Run the static analysis check ./gradlew check or ci-prepush.sh to make sure you didn't break anything

  • If you have multiple commits please combine them into one commit by squashing them.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added account creation functionality across loan, savings, fixed deposit, recurring deposit, and share account screens—users can now create new accounts directly from list views
    • Improved empty state screens with prominent action buttons to quickly create new accounts
    • Enhanced header layouts with account creation icons for better navigation and accessibility

@coderabbitai
Copy link

coderabbitai bot commented Jan 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds account creation callback parameters and AddAccount event/action handling across five account modules (Loan, Fixed Deposit, Recurring Deposit, Savings, Share). Routes, screens, and view models are updated to support account creation from empty states, with UI components displaying AddAccount buttons and localized empty-state messages.

Changes

Cohort / File(s) Summary
Client Loan Accounts
ClientLoanAccountsRoute.kt, ClientLoanAccountsScreen.kt, ClientLoanAccountsViewModel.kt
Added createAccount: (Int) -> Unit parameter to route and screen; implemented AddAccount action/event handling; updated header with vertical alignment and conditional icon rendering; integrated new empty-state message resource.
Fixed Deposit Account
FixedDepositAccountRoute.kt, FixedDepositAccountScreen.kt, FixedDepositAccountViewModel.kt
Added createAccount: (Int) -> Unit parameter to route and screen; extended header with addAccount and isFixedDepositScreenEmpty parameters; replaced empty-card message resource and wired AddAccount event to creation callback; added AddAccount action/event to ViewModel.
Recurring Deposit Account
RecurringDepositAccountRoute.kt, RecurringDepositAccountScreen.kt, RecurringDepositAccountViewModel.kt
Added createAccount: (Int) -> Unit parameter to route and screen; implemented conditional header rendering for AddAccount icon; replaced empty-state message resource and wired AddAccount action; introduced AddAccount action/event handling in ViewModel.
Savings Accounts
SavingsAccountsRoute.kt, SavingsAccountsScreen.kt, SavingsAccountsViewModel.kt
Added createAccount: (Int) -> Unit parameter to route and screen; propagated isSavingsScreenEmpty flag to header; replaced static empty card with dynamic MifosEmptyCard; updated header icon visibility logic; added AddAccount action/event to ViewModel.
Share Accounts
ShareAccountsRoute.kt, ShareAccountsScreen.kt, ShareAccountsViewModel.kt
Added createAccount: (Int) -> Unit parameter to route and screen; integrated isShareAccountsEmpty flag in header with conditional action rendering; replaced empty-state UI with MifosEmptyCard and localized message; added AddAccount action/event handling in ViewModel.
Navigation & UI Components
ClientNavigation.kt, MifosEmptyCard.kt
Enhanced savingsAccountsDestination and clientLoanAccountsDestination with createAccount callbacks; extended MifosEmptyCard with onClick and isButtonPresent parameters to support optional buttons with localized labels.
Localization Resources
core/ui/.../strings.xml, feature/client/.../strings.xml
Added new string resources: core_ui_click_to_add_new in core UI and five account-type-specific empty list messages (feature_*_account_empty_list_message) in feature client module.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • biplab1
  • therajanmaurya
  • revanthkumarJ

Poem

🐰 With buttons now blossoming where lists once stood bare,
Five account types shimmer with AddAccount flair,
Click to create, navigate with grace,
Empty screens brighten—each in their place! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding Create Account buttons for all account types across the client feature.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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

@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

Caution

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

⚠️ Outside diff range comments (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)

244-248: Pre-existing bug: ApproveAccount action is not dispatched.

The ApproveAccount action is constructed but never sent via onAction(), so the approve functionality won't work. Compare with ViewAccount (lines 237-243) which correctly calls onAction(...).

🐛 Proposed fix
                                            is Actions.ApproveAccount -> {
-                                                RecurringDepositAccountAction.ApproveAccount(
+                                                onAction(RecurringDepositAccountAction.ApproveAccount(
                                                     recurringDeposit.accountNo ?: "",
-                                                )
+                                                ))
                                             }
🤖 Fix all issues with AI agents
In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientLoanAccounts/ClientLoanAccountsScreen.kt`:
- Around line 242-249: Replace the null content description on the add-icon
button so screen readers can announce it: in the Icon inside IconButton (the one
invoking onAction(ClientLoanAccountsAction.AddAccount) and using
painterResource(Res.drawable.add_icon)), set contentDescription to a meaningful
string (preferably via a string resource, e.g.
stringResource(R.string.add_account) or a localized label like "Add account")
instead of null so the button is accessible.

In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt`:
- Around line 13-14: The Add icon in FixedDepositAccountScreen (the clickable
add icon near where the composable shows an empty state) has a null
contentDescription, making it inaccessible; update the composable that renders
the add_icon (in FixedDepositAccountScreen) to pass a meaningful, localized
contentDescription string (create a new string resource like "add_fixed_deposit"
or reuse an appropriate existing resource) and wire it via stringResource(...)
so screen readers announce the action; ensure the contentDescription is non-null
for the Image/Icon composable and update any related preview/tests to reflect
the new resource.

In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccounts.kt`:
- Around line 254-262: Remove the no-op DesignToken.padding expression and
replace it with a proper Spacer using Modifier.width or Modifier.padding as
appropriate (replace the standalone DesignToken.padding near the IconButton);
also fix accessibility by providing a meaningful contentDescription for the Icon
(do not use contentDescription = null) — either hardcode a short label like "Add
account" or reference a string resource, and ensure the IconButton callback
remains onAction.invoke(SavingsAccountAction.AddAccount).
🧹 Nitpick comments (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/shareAccounts/ShareAccountsScreen.kt (1)

186-202: Consider adding meaningful contentDescription for accessibility.

The new Add icon (and the existing Search/Filter icons) have contentDescription = null, which makes them inaccessible to screen readers. For interactive icons, providing descriptive labels improves accessibility.

♿ Suggested improvement for accessibility
         Icon(
             modifier = Modifier.onClick { onAction.invoke(ShareAccountsAction.ToggleSearchBar) },
             painter = painterResource(Res.drawable.search),
-            contentDescription = null,
+            contentDescription = "Search accounts",
         )
         Spacer(modifier = Modifier.width(DesignToken.spacing.largeIncreased))
         Icon(
             modifier = Modifier.onClick { onAction.invoke(ShareAccountsAction.AddAccount) },
             painter = painterResource(Res.drawable.add_icon),
-            contentDescription = null,
+            contentDescription = "Add account",
         )
         Spacer(modifier = Modifier.width(DesignToken.spacing.largeIncreased))
         Icon(
             modifier = Modifier.onClick { onAction.invoke(ShareAccountsAction.ToggleFiler) },
             painter = painterResource(Res.drawable.filter),
-            contentDescription = null,
+            contentDescription = "Filter accounts",
         )

@techsavvy185 techsavvy185 changed the title Create account flow fix(client): Added Create Account buttons for all types of accounts. Jan 26, 2026
Copy link
Collaborator

@niyajali niyajali left a comment

Choose a reason for hiding this comment

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

Do these require changes in all places

@niyajali
Copy link
Collaborator

@techsavvy185 could you also post images/videos of the outcome

@techsavvy185
Copy link
Contributor Author

@niyajali Thanks for the review! I'll make the required changes. I've already attached a screen recording in the PR, is there anything specific I should cover?

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: 0

Caution

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

⚠️ Outside diff range comments (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)

270-310: Add an accessible contentDescription for the new add button.

The new clickable icon has contentDescription = null, so screen readers can’t discover or announce the action. Please provide a localized label.

♿ Suggested fix
         Icon(
             painter = painterResource(Res.drawable.add_icon),
-            contentDescription = null,
+            contentDescription = stringResource(Res.string.client_add_account),
             modifier = Modifier.clickable {
                 addAccount.invoke()
             },
         )
🧹 Nitpick comments (4)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/shareAccounts/ShareAccountsViewModel.kt (1)

36-36: Minor style inconsistency: is keyword used for data object.

Other data object actions in this when block (e.g., ToggleFiler, ToggleSearchBar, Refresh) use direct matching without is. For consistency, consider removing the is keyword here.

Suggested change
-            is ShareAccountsAction.AddAccount -> sendEvent(ShareAccountsEvent.AddAccount(route.clientId))
+            ShareAccountsAction.AddAccount -> sendEvent(ShareAccountsEvent.AddAccount(route.clientId))
feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsRoute.kt (1)

35-35: Simplify the pass-through lambda.

The lambda wrapping is unnecessary since it just forwards the argument directly.

♻️ Suggested simplification
-            createAccount = { clientId -> createAccount(clientId) },
+            createAccount = createAccount,
feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt (1)

267-274: Consider reordering parameters for consistency.

The addAccount parameter (without default) is placed after modifier (with default). While Kotlin's named arguments make this work, grouping parameters without defaults before those with defaults improves readability and aligns with common Compose conventions.

♻️ Suggested parameter order
 `@Composable`
 fun FixedDepositAccountHeader(
     totalItem: String,
     onToggleFilter: () -> Unit,
+    addAccount: () -> Unit,
     onToggleSearch: () -> Unit,
     modifier: Modifier = Modifier,
-    addAccount: () -> Unit,
-    onToggleSearch: () -> Unit,
 )
feature/client/src/commonMain/kotlin/com/mifos/feature/client/shareAccounts/ShareAccountsScreen.kt (1)

192-196: Consider adding contentDescription for accessibility.

Setting contentDescription = null means screen readers cannot describe this button. For better accessibility, provide a meaningful description.

This also applies to the existing search and filter icons in this header.

♻️ Suggested improvement
         Icon(
             modifier = Modifier.onClick { onAction.invoke(ShareAccountsAction.AddAccount) },
             painter = painterResource(Res.drawable.add_icon),
-            contentDescription = null,
+            contentDescription = "Add Share Account",
         )

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: 2

🤖 Fix all issues with AI agents
In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt`:
- Around line 12-21: The icon usage (add_icon) in RecurringDepositAccountScreen
currently sets contentDescription = null and always renders a Spacer after the
icon, which removes the action from screen readers and leaves a gap when the
icon is hidden; update the composable(s) that render add_icon (e.g., the
icon/Image composable and its surrounding layout in
RecurringDepositAccountScreen and the similar block around the code referenced
at lines ~307-318) to: 1) provide a meaningful contentDescription using an
accessible string resource (e.g.,
Res.client_profile_recurring_deposit_account_title or a dedicated "add" label)
instead of null, and 2) render the Spacer conditionally only when the icon is
actually shown (wrap the Spacer in the same if that shows the icon) so no extra
gap appears when the icon is omitted. Ensure the accessible label is localized
via the existing resources import.

In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/shareAccounts/ShareAccountsScreen.kt`:
- Around line 12-17: The use of add_icon currently sets contentDescription =
null (making it invisible to screen readers) and always renders a Spacer even
when the icon is hidden; update the Icon/Image usage for add_icon in
ShareAccountsScreen (and the similar nodes around the 192-206 block) to provide
an accessible label by passing a meaningful string resource (e.g., from Res like
feature_share_account_empty_list_message or a new localized string such as "add
share" via Res) into contentDescription instead of null, and render the Spacer
conditionally only when the add_icon is actually visible (wrap Spacer rendering
with the same visibility condition used for the icon).
🧹 Nitpick comments (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt (1)

301-328: Consider aligning icon button patterns with SavingsAccountsHeader.

The header icons use Icon with clickable modifier, while SavingsAccountsHeader uses IconButton. For consistency across the codebase and better accessibility (proper touch targets), consider refactoring all interactive icons to use IconButton.

Also note that search icon (line 303) and filter icon (line 324) have contentDescription = null, though these lines aren't part of this PR's changes.

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: 0

Caution

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

⚠️ Outside diff range comments (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)

249-255: Bug: ApproveAccount action is created but never dispatched.

The ApproveAccount action is instantiated but not passed to onAction(), so clicking "Approve Account" does nothing. Compare with ViewAccount at line 243 which correctly calls onAction(...).

🐛 Proposed fix
                                         is Actions.ApproveAccount -> {
-                                            RecurringDepositAccountAction.ApproveAccount(
+                                            onAction(
+                                                RecurringDepositAccountAction.ApproveAccount(
-                                                recurringDeposit.accountNo ?: "",
+                                                    recurringDeposit.accountNo ?: "",
+                                                ),
                                             )
                                         }
🧹 Nitpick comments (3)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)

66-74: Parameter ordering violates Compose conventions.

The createAccount parameter is required (no default value) but is placed after modifier which has a default. Compose API guidelines recommend placing required parameters before optional ones, with modifier typically being the last optional parameter.

♻️ Suggested fix
 `@Composable`
 fun RecurringDepositAccountScreen(
     navController: NavController,
     navigateBack: () -> Unit,
     onApproveAccount: (String) -> Unit,
     onViewAccount: (String) -> Unit,
+    createAccount: (Int) -> Unit,
     modifier: Modifier = Modifier,
-    createAccount: (Int) -> Unit,
     viewModel: RecurringDepositAccountViewModel = koinViewModel(),
 ) {
feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt (2)

66-74: Consider reordering parameters for better API consistency.

The createAccount parameter (required, no default) is placed after modifier (optional with default). Kotlin/Compose conventions typically place required parameters before optional ones. Consider moving createAccount before modifier for consistency.

♻️ Suggested reordering
 `@Composable`
 fun FixedDepositAccountScreen(
     navController: NavController,
     navigateBack: () -> Unit,
     onApproveAccount: (String) -> Unit,
     onViewAccount: (String) -> Unit,
+    createAccount: (Int) -> Unit,
     modifier: Modifier = Modifier,
-    createAccount: (Int) -> Unit,
     viewModel: FixedDepositAccountViewModel = koinViewModel(),
 )

273-281: Consider consistent parameter ordering in header function.

Required parameters (onToggleFilter, addAccount, onToggleSearch, isFixedDepositScreenEmpty) are interleaved around the optional modifier parameter. For consistency, group all required parameters before optional ones.

♻️ Suggested reordering
 `@Composable`
 fun FixedDepositAccountHeader(
     totalItem: String,
     onToggleFilter: () -> Unit,
+    addAccount: () -> Unit,
     onToggleSearch: () -> Unit,
+    isFixedDepositScreenEmpty: Boolean,
     modifier: Modifier = Modifier,
-    addAccount: () -> Unit,
-    onToggleSearch: () -> Unit,
-    isFixedDepositScreenEmpty: Boolean,
 )

@techsavvy185
Copy link
Contributor Author

@niyajali I'm done with all the changes that were required. Could you please go through this?

@biplab1
Copy link
Contributor

biplab1 commented Feb 4, 2026

@techsavvy185 Please resolve the merge conflicts.

@techsavvy185
Copy link
Contributor Author

@biplab1 Yes, I'll complete it by tomorrow.

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: 1

Caution

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

⚠️ Outside diff range comments (3)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)

239-243: ⚠️ Potential issue | 🔴 Critical

Bug: ApproveAccount action is constructed but never dispatched.

The action is created but not passed to onAction(...), so clicking "Approve" on a recurring deposit account will silently do nothing. Compare with FixedDepositAccountScreen.kt (lines 241–247) where it's correctly wrapped in onAction(...).

Proposed fix
                                         is Actions.ApproveAccount -> {
-                                            RecurringDepositAccountAction.ApproveAccount(
+                                            onAction(RecurringDepositAccountAction.ApproveAccount(
                                                 recurringDeposit.accountNo ?: "",
-                                            )
+                                            ))
                                         }
feature/client/src/commonMain/kotlin/com/mifos/feature/client/navigation/ClientNavigation.kt (1)

362-365: ⚠️ Potential issue | 🟡 Minor

shareAccountsDestination has navigateToViewAccount wired to a no-op {}.

While createAccount is correctly handled internally in ShareAccountsRoute, the navigateToViewAccount callback is still an empty lambda. This means the "View Account" action on share account cards will silently do nothing. Is this intentional / pending implementation?

feature/client/src/commonMain/kotlin/com/mifos/feature/client/shareAccounts/ShareAccountsScreen.kt (1)

52-57: ⚠️ Potential issue | 🔴 Critical

Rename ShareAccountsScreen to ShareAccountsScreenRoute to fix compilation error.

ShareAccountsRoute.kt line 28 calls ShareAccountsScreenRoute(...), but ShareAccountsScreen.kt defines ShareAccountsScreen. This function name mismatch will cause a compilation error. Rename the function at line 53 from ShareAccountsScreen to ShareAccountsScreenRoute.

Additionally, fix accessibility issues: The three icons in ShareAccountHeader (lines 193, 199, 205) all have contentDescription = null. Provide descriptive content descriptions for search, add, and filter icons.

🤖 Fix all issues with AI agents
In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsScreen.kt`:
- Around line 242-272: DesignToken.padding expressions in the conditional block
inside SavingsAccountsScreen (around the IconButton calls that invoke
SavingsAccountAction.ToggleSearch, AddAccount, and ToggleFilter) are no-ops and
should be replaced with real spacing or removed; update those two occurrences to
use a Spacer with Modifier.width(DesignToken.spacing.largeIncreased) between the
icons (matching ShareAccountsScreen.kt) or simply delete the unused
DesignToken.padding lines so the IconButtons remain adjacent but valid touch
targets.
🧹 Nitpick comments (3)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/fixedDepositAccount/FixedDepositAccountScreen.kt (1)

65-73: Required parameter createAccount placed after optional parameter modifier.

Placing a required parameter (createAccount) after one with a default value (modifier) forces all callers to use named arguments. Move createAccount before modifier to follow Kotlin/Compose conventions.

Proposed fix
 fun FixedDepositAccountScreen(
     navController: NavController,
     navigateBack: () -> Unit,
     onApproveAccount: (String) -> Unit,
     onViewAccount: (String) -> Unit,
-    modifier: Modifier = Modifier,
     createAccount: (Int) -> Unit,
+    modifier: Modifier = Modifier,
     viewModel: FixedDepositAccountViewModel = koinViewModel(),
 )
feature/client/src/commonMain/kotlin/com/mifos/feature/client/recurringDepositAccount/RecurringDepositAccountScreen.kt (1)

65-73: Required parameter createAccount placed after optional parameter modifier.

Same issue as in FixedDepositAccountScreen — move createAccount before modifier.

Proposed fix
 fun RecurringDepositAccountScreen(
     navController: NavController,
     navigateBack: () -> Unit,
     onApproveAccount: (String) -> Unit,
     onViewAccount: (String) -> Unit,
-    modifier: Modifier = Modifier,
     createAccount: (Int) -> Unit,
+    modifier: Modifier = Modifier,
     viewModel: RecurringDepositAccountViewModel = koinViewModel(),
 )
feature/client/src/commonMain/kotlin/com/mifos/feature/client/savingsAccounts/SavingsAccountsRoute.kt (1)

35-35: Nit: Redundant lambda wrapper.

{ clientId -> createAccount(clientId) } can be simplified to a direct function reference.

Proposed fix
-            createAccount = { clientId -> createAccount(clientId) },
+            createAccount = createAccount,

@sonarqubecloud
Copy link

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.

4 participants