Skip to content

fix(search): use of xml strings in search filter instead of hardcoded values#2621

Open
amanna13 wants to merge 2 commits intoopenMF:developmentfrom
amanna13:refactor/xml-string-search
Open

fix(search): use of xml strings in search filter instead of hardcoded values#2621
amanna13 wants to merge 2 commits intoopenMF:developmentfrom
amanna13:refactor/xml-string-search

Conversation

@amanna13
Copy link
Member

@amanna13 amanna13 commented Feb 22, 2026

Fixes - Jira-#712

Screen_recording_20260222_133757.mp4

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

  • Refactor

    • Filter options updated to use individual resource-based labels and values for Clients, Groups, Centers, Loans, and Savings Accounts, improving string management.
  • Localization

    • Spanish translations added for per-option filter labels; filter UI now displays localized labels with a localized "All" fallback.

@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

📝 Walkthrough

Walkthrough

Refactors search filter options to use localized string resources: replaces string-array usage with per-option label/value resources (default locale) and per-option labels in Spanish; updates FilterOption to hold StringResource references and modifies UI components and ViewModel to resolve those resources at runtime.

Changes

Cohort / File(s) Summary
String resources (default)
feature/search/src/commonMain/composeResources/values/feature_search_strings.xml
Replaced two string-array resources with individual label and value string resources for: clients, groups, centers, loans, savings.
String resources (Spanish)
feature/search/src/commonMain/composeResources/values-es/feature_search_strings.xml
Removed two string-array resources and added per-option label strings (clients, groups, centers, loans, savings); value strings not added in this locale.
ViewModel / FilterOption
feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt
Changed FilterOption to use StringResource properties (labelRes, valueRes) and updated concrete options to reference Res.string entries; ViewModel now resolves valueRes via getString before search.
UI components
feature/search/src/commonMain/kotlin/com/mifos/feature/search/components/FilterDialog.kt, .../SearchBox.kt
Updated UI to render labels using stringResource(option.labelRes) and fallback to localized "All" via resource; selection logic unchanged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~23 minutes

Possibly related PRs

Suggested reviewers

  • revanthkumarJ
  • itsPronay
  • sahilshivekar

Poem

🐰 I hopped through XML, soft and spry,
Swapped arrays for names that speak each sky,
Labels now local, values tucked neat,
Filters sing languages, nimble feet,
— a rabbit cheers the search complete.

🚥 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 accurately describes the main change: replacing hardcoded filter values with XML string resources across the search module.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Caution

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

⚠️ Outside diff range comments (1)
feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt (1)

171-195: ⚠️ Potential issue | 🟠 Major

Add the missing FilterOption.Centers data object and imports — XML string resources are currently unused.

Both values/feature_search_strings.xml and values-es/feature_search_strings.xml define feature_search_filter_options_centers_label and feature_search_filter_options_centers_value (Spanish: "Centros"), but no corresponding data object Centers exists in the FilterOption sealed class. These resources are dead code. Either add the missing Centers data object with its imports, or remove the unused resource strings from both XML locale files.

➕ Proposed addition of the missing Centers data object

In SearchViewModel.kt, add the missing import and data object:

 import androidclient.feature.search.generated.resources.feature_search_filter_options_groups_value
+import androidclient.feature.search.generated.resources.feature_search_filter_options_centers_label
+import androidclient.feature.search.generated.resources.feature_search_filter_options_centers_value
 import androidclient.feature.search.generated.resources.feature_search_filter_options_loans_label
     data object Groups : FilterOption(
         labelRes = Res.string.feature_search_filter_options_groups_label,
         valueRes = Res.string.feature_search_filter_options_groups_value,
     )

+    data object Centers : FilterOption(
+        labelRes = Res.string.feature_search_filter_options_centers_label,
+        valueRes = Res.string.feature_search_filter_options_centers_value,
+    )
+
     data object LoanAccounts : FilterOption(
-        val values = listOf(Clients, Groups, LoanAccounts, SavingsAccounts)
+        val values = listOf(Clients, Groups, Centers, LoanAccounts, SavingsAccounts)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt`
around lines 171 - 195, Add the missing FilterOption.Centers data object and
corresponding import usage so the XML string resources are used: inside the
sealed class FilterOption add a data object Centers with labelRes =
Res.string.feature_search_filter_options_centers_label and valueRes =
Res.string.feature_search_filter_options_centers_value, and include Centers in
the companion object values list (FilterOption.values). Alternatively, if you
prefer to delete unused resources instead, remove
feature_search_filter_options_centers_label and
feature_search_filter_options_centers_value from both locale XMLs.
🧹 Nitpick comments (1)
feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt (1)

108-110: Consider replacing valueRes API strings with constants to decouple the ViewModel from the UI resource layer.

getString(it.valueRes) resolves a locale string resource inside the ViewModel just to get an API parameter like "clients" or "loans". These values are not display text and must never vary by locale. Calling org.jetbrains.compose.resources.getString (a Compose Multiplatform UI primitive) in the ViewModel breaks architectural separation and introduces an unnecessary suspend-point for what are effectively compile-time constants.

A cleaner approach is to add a plain val value: String to FilterOption directly:

♻️ Proposed refactor to remove API-value resource resolution from the ViewModel
-sealed class FilterOption(val labelRes: StringResource, val valueRes: StringResource) {
+sealed class FilterOption(val labelRes: StringResource, val value: String) {

     data object Clients : FilterOption(
         labelRes = Res.string.feature_search_filter_options_clients_label,
-        valueRes = Res.string.feature_search_filter_options_clients_value,
+        value = "clients",
     )

     data object Groups : FilterOption(
         labelRes = Res.string.feature_search_filter_options_groups_label,
-        valueRes = Res.string.feature_search_filter_options_groups_value,
+        value = "groups",
     )

     data object LoanAccounts : FilterOption(
         labelRes = Res.string.feature_search_filter_options_loans_label,
-        valueRes = Res.string.feature_search_filter_options_loans_value,
+        value = "loans",
     )

     data object SavingsAccounts : FilterOption(
         labelRes = Res.string.feature_search_filter_options_savings_label,
-        valueRes = Res.string.feature_search_filter_options_savings_value,
+        value = "savingsaccounts",
     )
 }

Then in getSearchResult():

-            resources = state.value.selectedFilter?.let { getString(it.valueRes) },
+            resources = state.value.selectedFilter?.value,

This also lets you drop the getString and StringResource imports from the ViewModel and removes the *_value XML string resources entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt`
around lines 108 - 110, The ViewModel is resolving UI string resources
(getString(it.valueRes)) for API parameters; add a plain String property to the
FilterOption data/class (e.g., val value: String) and populate it where
FilterOption instances are created, then update
SearchViewModel.getSearchResult()/search invocation to pass
state.value.selectedFilter?.value to searchRepository.searchResources instead of
getString(it.valueRes); remove the getString import and any StringResource usage
plus the corresponding *_value XML resources since API values are now
compile-time constants.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@feature/search/src/commonMain/composeResources/values/feature_search_strings.xml`:
- Around line 26-35: The API parameter string resources
(feature_search_filter_options_clients_value,
feature_search_filter_options_groups_value,
feature_search_filter_options_centers_value,
feature_search_filter_options_loans_value,
feature_search_filter_options_savings_value) should be marked non-translatable
to prevent translators from altering request parameters; update each of those
<string> entries to include translatable="false" while leaving the corresponding
*_label entries unchanged so UI text remains translatable.

---

Outside diff comments:
In
`@feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt`:
- Around line 171-195: Add the missing FilterOption.Centers data object and
corresponding import usage so the XML string resources are used: inside the
sealed class FilterOption add a data object Centers with labelRes =
Res.string.feature_search_filter_options_centers_label and valueRes =
Res.string.feature_search_filter_options_centers_value, and include Centers in
the companion object values list (FilterOption.values). Alternatively, if you
prefer to delete unused resources instead, remove
feature_search_filter_options_centers_label and
feature_search_filter_options_centers_value from both locale XMLs.

---

Duplicate comments:
In
`@feature/search/src/commonMain/composeResources/values-es/feature_search_strings.xml`:
- Around line 26-35: The localized file incorrectly translates the API token
strings — update the value entries for
feature_search_filter_options_clients_value,
feature_search_filter_options_groups_value,
feature_search_filter_options_centers_value,
feature_search_filter_options_loans_value, and
feature_search_filter_options_savings_value so they remain the original API
identifiers (clients, groups, centers, loans, savingsaccounts) rather than
localized text; locate these string resources in the feature_search_strings.xml
and replace the translated values with the exact API tokens to ensure the app
sends the correct unlocalized values.

---

Nitpick comments:
In
`@feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt`:
- Around line 108-110: The ViewModel is resolving UI string resources
(getString(it.valueRes)) for API parameters; add a plain String property to the
FilterOption data/class (e.g., val value: String) and populate it where
FilterOption instances are created, then update
SearchViewModel.getSearchResult()/search invocation to pass
state.value.selectedFilter?.value to searchRepository.searchResources instead of
getString(it.valueRes); remove the getString import and any StringResource usage
plus the corresponding *_value XML resources since API values are now
compile-time constants.

<item>Savings Accounts</item>
</string-array>

<string-array name="feature_search_filter_option_values">
Copy link
Member

Choose a reason for hiding this comment

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

Why removed string array?

Copy link
Member Author

Choose a reason for hiding this comment

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

The string-array was originally introduced during "Migrate Search Fragment To Compose"
The filter options are mainly structured data of the

  • label (these are localized)
  • values (these are the constants - localization not needed)

I believe using string-array in this context would introduce additional complexity. It would be depended on the positional indexing between the two arrays.

@amanna13 amanna13 force-pushed the refactor/xml-string-search branch from 9ddea74 to 60f0b72 Compare February 22, 2026 09:05
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

🧹 Nitpick comments (1)
feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt (1)

171-195: Consider keeping API parameter values as plain String constants rather than StringResource.

valueRes entries are all marked translatable="false" — they are effectively compile-time constants. Resolving them via getString() (a suspend call) on every search invocation adds unnecessary async overhead for values that never change. Labels genuinely need localization and should stay as StringResource; values do not.

♻️ Suggested refactor
-sealed class FilterOption(val labelRes: StringResource, val valueRes: StringResource) {
+sealed class FilterOption(val labelRes: StringResource, val value: String) {

     data object Clients : FilterOption(
         labelRes = Res.string.feature_search_filter_options_clients_label,
-        valueRes = Res.string.feature_search_filter_options_clients_value,
+        value = "clients",
     )

     data object Groups : FilterOption(
         labelRes = Res.string.feature_search_filter_options_groups_label,
-        valueRes = Res.string.feature_search_filter_options_groups_value,
+        value = "groups",
     )

     data object LoanAccounts : FilterOption(
         labelRes = Res.string.feature_search_filter_options_loans_label,
-        valueRes = Res.string.feature_search_filter_options_loans_value,
+        value = "loans",
     )

     data object SavingsAccounts : FilterOption(
         labelRes = Res.string.feature_search_filter_options_savings_label,
-        valueRes = Res.string.feature_search_filter_options_savings_value,
+        value = "savingsaccounts",
     )
 }

Then in getSearchResult():

-resources = state.value.selectedFilter?.let { getString(it.valueRes) },
+resources = state.value.selectedFilter?.value,

This also removes the need to import StringResource, getString, and the four *_value resource references in SearchViewModel.kt, and allows the *_value string resources in the XML (and their ES counterparts) to be removed entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt`
around lines 171 - 195, The FilterOption sealed class currently stores API
parameter values as StringResource causing suspend getString() calls; change the
constructor to accept a plain String for the API value (e.g., rename valueRes ->
value or similar) and update the data objects Clients, Groups, LoanAccounts,
SavingsAccounts to supply compile-time string constants (e.g., "clients",
"groups", "loanAccounts", "savingsAccounts"). Then update getSearchResult() to
use the new plain String property instead of calling getString(), and remove
now-unused imports (StringResource, getString) and the corresponding *_value XML
resources. Ensure references to FilterOption.value in other code are updated to
the new property name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@feature/search/src/commonMain/composeResources/values/feature_search_strings.xml`:
- Around line 30-31: The EN/ES string resources
feature_search_filter_options_centers_label and
feature_search_filter_options_centers_value are unused because FilterOption in
SearchViewModel.kt only defines Clients, Groups, LoanAccounts, and
SavingsAccounts; either add a new FilterOption data object named Centers to the
sealed class (and update any imports/usages that populate/filter options) so the
resources are consumed, or remove both resource entries from the locale files;
reference the sealed class FilterOption and the file SearchViewModel.kt when
making the change and ensure any UI code that builds the filter list is updated
to include FilterOption.Centers if you add it.

---

Nitpick comments:
In
`@feature/search/src/commonMain/kotlin/com/mifos/feature/search/SearchViewModel.kt`:
- Around line 171-195: The FilterOption sealed class currently stores API
parameter values as StringResource causing suspend getString() calls; change the
constructor to accept a plain String for the API value (e.g., rename valueRes ->
value or similar) and update the data objects Clients, Groups, LoanAccounts,
SavingsAccounts to supply compile-time string constants (e.g., "clients",
"groups", "loanAccounts", "savingsAccounts"). Then update getSearchResult() to
use the new plain String property instead of calling getString(), and remove
now-unused imports (StringResource, getString) and the corresponding *_value XML
resources. Ensure references to FilterOption.value in other code are updated to
the new property name.

@sonarqubecloud
Copy link

@therajanmaurya
Copy link
Member

Fix conflicts

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants