Skip to content

Implement Share Account Preview Screen#2549

Merged
therajanmaurya merged 1 commit intoopenMF:developmentfrom
Arinyadav1:implement-share-preview
Dec 6, 2025
Merged

Implement Share Account Preview Screen#2549
therajanmaurya merged 1 commit intoopenMF:developmentfrom
Arinyadav1:implement-share-preview

Conversation

@Arinyadav1
Copy link
Contributor

@Arinyadav1 Arinyadav1 commented Dec 5, 2025

Fixes - Jira-#546

IMG_5328.MOV

Summary by CodeRabbit

  • New Features

    • Added share account creation and submission functionality with real-time feedback.
    • Enhanced preview page displaying full account details, terms, and charges before submission.
    • Integrated snackbar notifications for successful account creation.
  • Documentation

    • Updated form field labels to indicate required fields.
    • Added success message confirmation text.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 5, 2025

Walkthrough

This PR adds share account creation functionality across the data, network, and UI layers. It introduces a new ShareAccountPayload model, network endpoint, repository method, and UI form with validation and success feedback. Replaces CreatedCharges with ChargeItem and refactors PreviewPage to display submission details before account creation.

Changes

Cohort / File(s) Summary
Network Models & Services
core/network/src/commonMain/kotlin/com/mifos/core/network/model/share/ShareAccountPayload.kt, core/network/src/commonMain/kotlin/com/mifos/core/network/services/ShareAccountService.kt
Introduces ShareAccountPayload and ChargeItem serializable data classes; adds POST endpoint createShareAccount to ShareAccountService accepting ShareAccountPayload and returning HttpResponse.
Data Manager
core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerShare.kt
Adds suspend function createShareAccount wrapping the network call with error extraction and JSON response parsing.
Repository Layer
core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ShareAccountRepository.kt, core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ShareAccountRepositoryImpl.kt
Adds new repository interface and implementation for createShareAccount returning Flow<DataState<GenericResponse>>.
UI State Management
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountViewModel.kt
Adds createShareAccount() flow for submission, introduces SuccessResponseStatus in DialogState, replaces CreatedCharges with ChargeItem, adds SubmitShareAccount action, and updates state constructor with launchEffectKey.
UI Screens & Composition
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountScreen.kt, feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/PreviewPage.kt
Adds SnackbarHostState management and LaunchedEffect-based success handling in CreateShareAccountScreen; refactors PreviewPage from simple button to state-driven scrollable layout displaying Details, Terms, and Charges sections.
UI Pages
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/DetailsPage.kt
Appends asterisks to product name and submission date labels to indicate required fields.
Resources
feature/client/src/commonMain/composeResources/values/strings.xml
Adds feature_share_account_submit and feature_share_account_created_successfully strings; removes trailing asterisks from existing feature_share_account_detail_product_name and feature_share_account_detail_submission_date labels.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • ChargeItem type migration: Verify that replacing CreatedCharges with ChargeItem throughout the ViewModel and charge-handling flows is complete and backward compatible where needed.
  • PreviewPage refactor: Substantial UI layout changes warrant careful review of layout logic, scrolling behavior, and action wiring (Back/Submit handlers).
  • SnackbarHostState threading: Confirm snackbarHostState is correctly propagated through CreateShareAccountDialog, CreateShareAccountContent, and MifosScaffold without composition instability.
  • Error handling in DataManagerShare: Review error extraction and IllegalStateException throwing logic; verify response parsing with ignoreUnknownKeys configuration is appropriate.
  • LaunchedEffect success flow: Check that the delay, logging, snackbar display, and navigation back sequence is robust and does not cause unwanted recompositions.

Possibly related PRs

Suggested reviewers

  • sam-arth07
  • biplab1

Poem

🐰 A new share account, what a delight!
From payload to preview, we've built it just right.
With charges and dates, all validated with care,
Success messages bloom in the snackbar's air! 🎉

Pre-merge checks and finishing touches

❌ 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%. 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 reflects the main objective: implementing a Share Account Preview Screen, which is demonstrated by the PreviewPage refactor and the complete addition of share account creation workflow.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 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: 4

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/createShareAccount/CreateShareAccountViewModel.kt (1)

482-489: Bug: EditCharge uses wrong index for chargeId lookup.

The EditCharge handler retrieves the charge ID from chargeOptions[action.index] instead of using the selected chooseChargeIndex. The action.index represents the position in addedCharges, not chargeOptions:

 is CreateShareAccountAction.EditCharge -> {
     val createdData = ChargeItem(
-        chargeId = state.chargeOptions[action.index].id,
+        chargeId = state.chargeOptions[state.chooseChargeIndex!!].id,
         amount = state.chargeAmount.toDoubleOrNull(),
     )

Compare with AddChargeToList at line 468 which correctly uses state.chooseChargeIndex.

🧹 Nitpick comments (9)
core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ShareAccountRepository.kt (1)

20-21: Inconsistent function signature pattern.

The createShareAccount function is marked suspend while also returning a Flow. This differs from getShareTemplate on line 20, which only returns Flow without suspend. Since Flow is already cold and provides async behavior, the suspend modifier is typically unnecessary here.

Consider aligning with the existing pattern:

-    suspend fun createShareAccount(shareAccountPayload: ShareAccountPayload): Flow<DataState<GenericResponse>>
+    fun createShareAccount(shareAccountPayload: ShareAccountPayload): Flow<DataState<GenericResponse>>

This would also require updating the implementation to not be suspend.

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

30-36: The suspend modifier is unnecessary here.

Since the actual suspend call (dataManagerShare.createShareAccount) occurs inside the flow { } builder, the outer function doesn't need to be suspend. The flow collector will handle the suspension.

-    override suspend fun createShareAccount(
+    override fun createShareAccount(
         shareAccountPayload: ShareAccountPayload,
     ): Flow<DataState<GenericResponse>> {
         return flow {
             emit(dataManagerShare.createShareAccount(shareAccountPayload))
         }.asDataStateFlow()
     }

This aligns with the getShareTemplate function pattern in this same class.

core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerShare.kt (2)

38-40: Avoid creating a new Json instance on every call.

Creating a Json instance with configuration on each invocation is inefficient. Consider extracting this to a companion object or class-level property.

 class DataManagerShare(
     private val baseApiManager: BaseApiManager,
 ) {
+    private val json = Json { ignoreUnknownKeys = true }
 
     fun getShareTemplate(clientId: Int, productId: Int?): Flow<ShareTemplate> =
         baseApiManager.shareAccountService.shareProductTemplate(clientId, productId)

     suspend fun createShareAccount(shareAccountPayload: ShareAccountPayload): GenericResponse {
         val response = baseApiManager.shareAccountService.createShareAccount(shareAccountPayload)

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

             throw IllegalStateException(errorMsg)
         } else {
-            val json = Json { ignoreUnknownKeys = true }
-
             json.decodeFromString<GenericResponse>(response.bodyAsText())
         }
     }
 }

19-19: Unused import.

The import io.ktor.serialization.kotlinx.json.json appears unused in this file. The JSON parsing uses kotlinx.serialization.json.Json (line 21) instead.

-import io.ktor.serialization.kotlinx.json.json
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/PreviewPage.kt (2)

116-116: Hardcoded strings "Yes"/"No" should use string resources for internationalization.

Using hardcoded English strings bypasses the localization system.

Consider adding string resources for "Yes" and "No" and using stringResource() here:

-            Res.string.feature_share_account_terms_allow_dividends to if (state.isDividendAllowed) "Yes" else "No",
+            Res.string.feature_share_account_terms_allow_dividends to stringResource(if (state.isDividendAllowed) Res.string.common_yes else Res.string.common_no),

You'll need to add corresponding string resources if they don't already exist.


60-60: Consider using design tokens for spacing consistency.

The hardcoded 20.dp differs from the pattern used elsewhere (e.g., DesignToken.padding.large on lines 56 and 100).

-            verticalArrangement = Arrangement.spacedBy(20.dp),
+            verticalArrangement = Arrangement.spacedBy(DesignToken.padding.large),

Or use the appropriate token that matches 20.dp if it exists.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountScreen.kt (2)

121-134: Improve debug log with meaningful context.

The log statement Logger.d("SuccessResponseStatus") provides no useful diagnostic information. Consider including the actual status or message for better debugging:

-                Logger.d("SuccessResponseStatus")
+                Logger.d("SuccessResponseStatus: success=${state.dialogState.successStatus}, msg=${state.dialogState.msg}")

75-76: Consider using the existing EventsEffect pattern for consistency.

The codebase has an EventsEffect utility (referenced in core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/EventsEffect.kt) that provides lifecycle-aware event handling. The current approach uses LaunchedEffect with a random key (launchEffectKey) to trigger side effects from DialogState.

While this works, using a one-shot event flow pattern with EventsEffect (similar to how NavigateBack and Finish events are handled in lines 77-82) would be more consistent with the existing architecture and avoid coupling UI effects to dialog state.

Also applies to: 121-134

feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountViewModel.kt (1)

467-470: Consider validating charge amount before adding.

state.chargeAmount.toDoubleOrNull() returns null for invalid input, which would result in a ChargeItem with a null amount being added to the list. Consider validating the amount before allowing the charge to be added:

 is CreateShareAccountAction.AddChargeToList -> {
+    val amount = state.chargeAmount.toDoubleOrNull()
+    if (amount == null || state.chooseChargeIndex == null) {
+        // Optionally show validation error
+        return
+    }
     val createdData = ChargeItem(
-        chargeId = state.chargeOptions[state.chooseChargeIndex!!].id,
-        amount = state.chargeAmount.toDoubleOrNull(),
+        chargeId = state.chargeOptions[state.chooseChargeIndex].id,
+        amount = amount,
     )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 01c9f37 and 0078dcf.

📒 Files selected for processing (10)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ShareAccountRepository.kt (1 hunks)
  • core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ShareAccountRepositoryImpl.kt (2 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerShare.kt (1 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/model/share/ShareAccountPayload.kt (1 hunks)
  • core/network/src/commonMain/kotlin/com/mifos/core/network/services/ShareAccountService.kt (1 hunks)
  • feature/client/src/commonMain/composeResources/values/strings.xml (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountScreen.kt (6 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountViewModel.kt (8 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/DetailsPage.kt (1 hunks)
  • feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/PreviewPage.kt (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/DetailsPage.kt (1)
core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/component/MifosOutlinedTextField.kt (1)
  • MifosDatePickerTextField (363-413)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountViewModel.kt (3)
core/data/src/commonMain/kotlin/com/mifos/core/data/repository/ShareAccountRepository.kt (1)
  • createShareAccount (21-21)
core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ShareAccountRepositoryImpl.kt (1)
  • createShareAccount (30-36)
core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerShare.kt (1)
  • createShareAccount (30-42)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/PreviewPage.kt (3)
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/MifosTwoButtonRow.kt (1)
  • MifosTwoButtonRow (31-91)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt (1)
  • MifosDefaultListingComponentFromStringResources (244-267)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountScreen.kt (1)
core/ui/src/commonMain/kotlin/com/mifos/core/ui/util/EventsEffect.kt (1)
  • EventsEffect (28-43)
🔇 Additional comments (6)
feature/client/src/commonMain/composeResources/values/strings.xml (1)

554-558: LGTM!

The new string resources for the submit button and success message are appropriately added. Moving the required field indicator (*) from the resource to the code (in DetailsPage.kt) provides flexibility for conditional display.

feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/DetailsPage.kt (1)

120-125: LGTM!

The approach of appending the required field indicator (*) in code provides flexibility. The implementation is consistent between both required fields.

core/network/src/commonMain/kotlin/com/mifos/core/network/services/ShareAccountService.kt (1)

29-32: LGTM!

The new POST endpoint for creating share accounts is properly defined. Returning HttpResponse allows the DataManagerShare to handle response parsing and error extraction with custom logic.

core/network/src/commonMain/kotlin/com/mifos/core/network/model/share/ShareAccountPayload.kt (1)

14-52: The payload model follows proper Kotlin serialization conventions with clear distinction between required and optional fields. However, the non-nullable savingsAccountId field without a default value warrants verification against the actual API contract—if this field is sometimes omitted in API responses, it should be Int? with a nullable default.

Cross-reference with:

  • API endpoint documentation for share account creation
  • Actual request/response examples from integration tests
  • Similar payload models in the codebase to ensure consistency
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountViewModel.kt (2)

101-107: LGTM: Loading state handling.

The loading indicator is properly shown during the API call by setting isOverLayLoadingActive = true.


109-120: LGTM: Success state handling with localized message.

The success flow correctly clears the loading state, uses a localized string resource for the message, and triggers the UI effect via launchEffectKey.

Comment on lines +54 to +71
private fun createShareAccount() {
val shareAccountPayload = ShareAccountPayload(
clientId = route.clientId,
productId = state.productOption[state.shareProductIndex!!].id,
requestedShares = state.totalShares.toInt(),
externalId = state.externalId,
submittedDate = state.submissionDate,
dateFormat = DateHelper.SHORT_MONTH,
minimumActivePeriod = state.minActivePeriodFreq.toIntOrNull(),
minimumActivePeriodFrequencyType = if (state.minActivePeriodFreqTypeIdx != null) state.minimumActivePeriodFrequencyTypeOptions[state.minActivePeriodFreqTypeIdx!!].id else null,
lockinPeriodFrequency = state.lockInPeriodFreq.toIntOrNull(),
lockinPeriodFrequencyType = if (state.lockInPeriodFreqTypeIdx != null) state.lockInPeriodFrequencyTypeOptions[state.lockInPeriodFreqTypeIdx!!].id else null,
applicationDate = state.applicationDate,
allowDividendCalculationForInactiveClients = state.isDividendAllowed,
charges = state.addedCharges,
locale = Constants.LOCALE_EN,
savingsAccountId = state.savingsAccountOptions[state.savingsAccountIdx!!].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

Potential NPE: Validate nullable indices before payload construction.

The createShareAccount() function uses force-unwrap (!!) on nullable indices. While shareProductIndex and savingsAccountIdx are validated in earlier steps, direct invocation of SubmitShareAccount action could bypass these guards.

Consider adding validation or using safe calls:

 private fun createShareAccount() {
+    if (state.shareProductIndex == null || state.savingsAccountIdx == null) {
+        // Handle validation error - show user feedback
+        return
+    }
     val shareAccountPayload = ShareAccountPayload(
         clientId = route.clientId,
-        productId = state.productOption[state.shareProductIndex!!].id,
+        productId = state.productOption[state.shareProductIndex].id,
         // ... other fields
-        savingsAccountId = state.savingsAccountOptions[state.savingsAccountIdx!!].id,
+        savingsAccountId = state.savingsAccountOptions[state.savingsAccountIdx].id,
     )

Also, lines 63 and 65 use redundant patterns—after the if (... != null) check, prefer let over !!:

-minimumActivePeriodFrequencyType = if (state.minActivePeriodFreqTypeIdx != null) state.minimumActivePeriodFrequencyTypeOptions[state.minActivePeriodFreqTypeIdx!!].id else null,
+minimumActivePeriodFrequencyType = state.minActivePeriodFreqTypeIdx?.let { state.minimumActivePeriodFrequencyTypeOptions[it].id },

Comment on lines +77 to +88
is DataState.Error -> {
if (dataState.exception is IllegalStateException) {
mutableStateFlow.update {
it.copy(
dialogState = CreateShareAccountState.DialogState.SuccessResponseStatus(
successStatus = false,
msg = dataState.message,
),
launchEffectKey = Random.nextInt(),
isOverLayLoadingActive = false,
)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Misleading naming: SuccessResponseStatus used for error states.

Using SuccessResponseStatus(successStatus = false, ...) to represent errors is semantically confusing and could lead to maintenance issues. Consider renaming to a more generic ResponseStatus or creating separate dialog states for success and error:

 sealed interface DialogState {
     data class AddNewCharge(val edit: Boolean, val index: Int = -1) : DialogState
     data object ShowCharges : DialogState
-    data class SuccessResponseStatus(val successStatus: Boolean, val msg: String = "") :
-        DialogState
+    data class SubmissionResult(val isSuccess: Boolean, val message: String = "") :
+        DialogState
 }

Also applies to: 621-622

🤖 Prompt for AI Agents
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/CreateShareAccountViewModel.kt
around lines 77 to 88: the code sets dialogState to
CreateShareAccountState.DialogState.SuccessResponseStatus(successStatus = false,
...) for error branches which is misleading; change the dialog state model to
use a neutral or explicit error type — either rename SuccessResponseStatus to
ResponseStatus (or ResponseResult) and update all usages (including lines
~621-622), or add a distinct DialogState.ErrorResponseStatus with appropriate
fields and set that in error branches; update related consumers (UI renderers,
tests) to handle the new name/type.

Res.string.feature_share_account_terms_currency to state.currency.orEmpty(),
Res.string.feature_share_account_terms_current_price to state.currentPrice.orEmpty(),
Res.string.feature_share_account_terms_total_shares to state.totalShares,
Res.string.feature_share_account_terms_default_savings_account to state.savingsAccountOptions[state.savingsAccountIdx!!].savingsProductName.orEmpty(),
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

Potential null pointer exception with force unwrap.

Using state.savingsAccountIdx!! will crash if the index is null. If this page can only be reached after validation guarantees a non-null value, consider documenting this precondition. Otherwise, add null-safety.

-            Res.string.feature_share_account_terms_default_savings_account to state.savingsAccountOptions[state.savingsAccountIdx!!].savingsProductName.orEmpty(),
+            Res.string.feature_share_account_terms_default_savings_account to (state.savingsAccountIdx?.let { state.savingsAccountOptions.getOrNull(it)?.savingsProductName }.orEmpty()),
📝 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
Res.string.feature_share_account_terms_default_savings_account to state.savingsAccountOptions[state.savingsAccountIdx!!].savingsProductName.orEmpty(),
Res.string.feature_share_account_terms_default_savings_account to (state.savingsAccountIdx?.let { state.savingsAccountOptions.getOrNull(it)?.savingsProductName }.orEmpty()),
🤖 Prompt for AI Agents
In
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/PreviewPage.kt
around line 114, the code force-unwraps state.savingsAccountIdx which can NPE;
replace the force unwrap with a null-safe access (e.g., use
state.savingsAccountIdx?.let {
state.savingsAccountOptions.getOrNull(it)?.savingsProductName.orEmpty() } ?:
""), or explicitly guard earlier with a requireNotNull(state.savingsAccountIdx)
and document the precondition if the index must never be null.

) {
MifosDefaultListingComponentFromStringResources(
data = mapOf(
Res.string.feature_share_account_detail_product_name to state.productOption[state.shareProductIndex!!].name,
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

Potential null pointer exception with force unwrap.

Similar to savingsAccountIdx, using state.shareProductIndex!! will crash if null. Add null-safety or ensure the precondition is enforced before reaching this page.

-            Res.string.feature_share_account_detail_product_name to state.productOption[state.shareProductIndex!!].name,
+            Res.string.feature_share_account_detail_product_name to (state.shareProductIndex?.let { state.productOption.getOrNull(it)?.name }.orEmpty()),
📝 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
Res.string.feature_share_account_detail_product_name to state.productOption[state.shareProductIndex!!].name,
Res.string.feature_share_account_detail_product_name to (state.shareProductIndex?.let { state.productOption.getOrNull(it)?.name }.orEmpty()),
🤖 Prompt for AI Agents
In
feature/client/src/commonMain/kotlin/com/mifos/feature/client/createShareAccount/pages/PreviewPage.kt
around line 130, the code force-unwraps state.shareProductIndex (!!) which can
throw an NPE; replace the force-unwrap with a null-safe approach or enforce the
precondition: either (a) use a safe-access and handle null (e.g.,
state.shareProductIndex?.let { idx -> use idx } ?: return or provide a fallback)
or (b) assert the invariant at an earlier point with
requireNotNull(state.shareProductIndex) { "shareProductIndex must be set before
PreviewPage" } so the value is guaranteed non-null when accessed. Ensure the
chosen fix avoids runtime NPE and preserves correct UI flow.


throw IllegalStateException(errorMsg)
} else {
val json = Json { ignoreUnknownKeys = true }
Copy link
Contributor

Choose a reason for hiding this comment

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

isn't this already set in the Ktorfit client when it was created?
I have looked for a while but it must be.

@therajanmaurya therajanmaurya merged commit a8e9954 into openMF:development Dec 6, 2025
3 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