Skip to content

feat(loan): add export transactions dialog to loan transactions screen#2607

Open
gurnoorpannu wants to merge 42 commits into
openMF:devfrom
gurnoorpannu:feature/loan-transactions-export-dialog
Open

feat(loan): add export transactions dialog to loan transactions screen#2607
gurnoorpannu wants to merge 42 commits into
openMF:devfrom
gurnoorpannu:feature/loan-transactions-export-dialog

Conversation

@gurnoorpannu

@gurnoorpannu gurnoorpannu commented Feb 10, 2026

Copy link
Copy Markdown
Contributor

Fixes - Jira-#657

Before:-
image

After:-

image

Recording:-

FILE.2026-02-16.18.20.06.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

  • New Features
    • Added an export dialog on the loan transactions screen to pick From/To dates and generate reports.
    • Export action button added to the toolbar.
  • Behavior
    • Date inputs validate the range and show an "invalid date range" message when applicable.
  • Localization
    • New localized labels for export, date fields, report generation, validation, and close.

@coderabbitai

coderabbitai Bot commented Feb 10, 2026

Copy link
Copy Markdown

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

Adds an export feature: seven new string resources, a new ExportTransactionsDialog composable with from/to date pickers and range validation, and an export IconButton in LoanTransactionsScreen that opens the dialog and returns a selected date range.

Changes

Cohort / File(s) Summary
String Resources
feature/loan/src/commonMain/composeResources/values/strings.xml
Added seven strings for the export dialog and date-range validation: feature_loan_export, feature_loan_export_transactions, feature_loan_from_date, feature_loan_to_date, feature_loan_generate_report, feature_loan_invalid_date_range, feature_loan_close.
Export Dialog Component
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt
New composable with two date pickers (initialized to now, selectable from 2000-01-01), date helpers/formatting, real-time validation (to >= from), error messaging, and onGenerateReport(fromMillis, toMillis) callback.
Screen Integration
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/LoanTransactionsScreen.kt
Added export IconButton, showExportDialog state, conditional rendering of ExportTransactionsDialog, and placeholder wiring of onGenerateReport with dialog dismissal.

Sequence Diagram

sequenceDiagram
    participant User
    participant LTScreen as LoanTransactionsScreen
    participant Dialog as ExportTransactionsDialog
    participant Picker as DatePicker

    User->>LTScreen: Tap export button
    LTScreen->>LTScreen: set showExportDialog = true
    LTScreen->>Dialog: render dialog

    User->>Dialog: Open from-date picker
    Dialog->>Picker: request from-date (min 2000-01-01)
    Picker->>Dialog: return fromDate (ms)
    Dialog->>Dialog: update fromDate

    User->>Dialog: Open to-date picker
    Dialog->>Picker: request to-date (min 2000-01-01)
    Picker->>Dialog: return toDate (ms)
    Dialog->>Dialog: update toDate, validate range

    alt Valid date range
        User->>Dialog: Tap Generate Report
        Dialog->>LTScreen: onGenerateReport(fromMs, toMs)
        LTScreen->>Dialog: dismiss dialog
    else Invalid date range
        Dialog->>User: show invalid date range error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • biplab1

Poem

🐇 I hopped between From and To with care,

I nudged the dates until they paired,
When ranges match I drum and trot,
Pack your transactions in a neat little lot,
Close the dialog — the report is there!

🚥 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 directly and clearly describes the main change: adding an export transactions dialog to the loan transactions screen, which matches the primary content of the changeset.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@Kartikey15dem

Copy link
Copy Markdown
Contributor

I think the the close(x) button should be black with transparent background.

private fun formatDateFromMillis(millis: Long?): String {
if (millis == null) return ""
val localDate = Instant.fromEpochMilliseconds(millis)
.toLocalDateTime(TimeZone.currentSystemDefault())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

there is a time zone mismatch with fun createSelectableDatesFrom(minDate: LocalDate) = object : SelectableDates I suggest using TimeZone.UTC for consistency

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will fix that, ty for the review :)


<!-- Export Loan Transactions -->
<string name="feature_loan_export">Export</string>
<string name="feature_loan_export_transactions">Export</string>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why two different keys with same values ? you meant the second one to be Export Transactions did't you

}

@OptIn(ExperimentalTime::class)
@Composable

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think this function should not be annotated with Composable it does not emit UI, call remember or other compose APIs or take compose parameter, marking it with compose it triggers unnecessary recomposition tracking overhead.

var showToDatePicker by rememberSaveable { mutableStateOf(false) }
var fromDate: Long? by rememberSaveable { mutableStateOf(null) }
var toDate: Long? by rememberSaveable { mutableStateOf(null) }
var showInvalidDateRangeError by remember { mutableStateOf(false) }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this will be lost on config change, should not it be rememberSaveable also ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@markrizkalla I kept it as remember intentionally since it is just a error message that gets recalculated when the user interacts with the form only the actual date values need to survive config changes

@gurnoorpannu gurnoorpannu force-pushed the feature/loan-transactions-export-dialog branch from 377ec90 to c7cb0e4 Compare February 16, 2026 09:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
feature/loan/src/commonMain/composeResources/values/strings.xml (1)

297-298: Duplicate string values: feature_loan_export and feature_loan_export_transactions are both "Export".

These strings serve different UI purposes: feature_loan_export is used as a content description for the export button icon (line 136 of LoanTransactionsScreen.kt), while feature_loan_export_transactions is the dialog title (line 134 of ExportTransactionsDialog.kt). Consider differentiating their values—e.g., "Export" for the button and "Export Transactions" for the dialog title—to provide better context in different parts of the UI.

@amanna13 amanna13 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hey @gurnoorpannu ! Consider attaching a video (screen recording) for all the possible situations as mentioned in the ticket description-

On tapping Export, show a dialog with:
From Date (required)
To Date (required)
Cancel button
Generate Report button (disabled until validation passes)
Validation rules:
Both dates must be selected
To Date cannot be earlier than From Date
Only after valid input, the Generate Report button should become active

It's hard to validate these things with a single screenshot.
Thanks!

@gurnoorpannu

Copy link
Copy Markdown
Contributor Author

Hey @gurnoorpannu ! Consider attaching a video (screen recording) for all the possible situations as mentioned in the ticket description-

On tapping Export, show a dialog with:
From Date (required)
To Date (required)
Cancel button
Generate Report button (disabled until validation passes)
Validation rules:
Both dates must be selected
To Date cannot be earlier than From Date
Only after valid input, the Generate Report button should become active

It's hard to validate these things with a single screenshot. Thanks!

updated it 👍

@amanna13

Copy link
Copy Markdown
Member

@gurnoorpannu Have you validated that if To Date is earlier than From Date then Generate Report button should not be active !? Also I had a doubt, correct me if I'm wrong. The ticket mentions that button must be named as "Generate Report" in your implementation you have button named "Generate".
From a user perspective, I believe that "Generate Report" adds more clarity to what it's intended use is for.

return selectedDate >= minDate
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If you can, try to move this composable to core/ui module so that it can be reused.
We use date pickers in lot of places.

@gurnoorpannu

gurnoorpannu commented Feb 17, 2026

Copy link
Copy Markdown
Contributor Author

@gurnoorpannu Have you validated that if To Date is earlier than From Date then Generate Report button should not be active !? Also I had a doubt, correct me if I'm wrong. The ticket mentions that button must be named as "Generate Report" in your implementation you have button named "Generate". From a user perspective, I believe that "Generate Report" adds more clarity to what it's intended use is for.

@amanna13 the logic is there for the dates. And for the Generate button , is asked @biplab1 sir for that as generate Report was breaking the ui
IMAGE 2026-02-17 21:14:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt (1)

185-197: Replace non-null assertions with a safe-call to avoid any future footgun.

fromDate!! and toDate!! are safe today because the button is only enabled when isValidDateRange is true, which guards both non-null. However, the correctness of the call site depends entirely on the enabled state remaining in sync with the null-checks. A let-based pattern makes the contract explicit without any runtime cost.

♻️ Proposed refactor
-                            onClick = {
-                                onGenerateReport(fromDate!!, toDate!!)
-                            },
+                            onClick = {
+                                val from = fromDate
+                                val to = toDate
+                                if (from != null && to != null) {
+                                    onGenerateReport(from, to)
+                                }
+                            },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`
around lines 185 - 197, Replace the unsafe non-null assertions in the
MifosButton onClick (currently calling onGenerateReport(fromDate!!, toDate!!))
with a safe-call/let pattern that only invokes onGenerateReport when both
fromDate and toDate are non-null; update the onClick in ExportTransactionsDialog
(the MifosButton handler) to check fromDate and toDate via safe calls (e.g.,
nested let or a combined null-check) before calling onGenerateReport so the call
no longer relies on !! while preserving the enabled/isValidDateRange behavior.
🤖 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/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`:
- Around line 128-136: Replace the bare Icon(...) with an IconButton that wraps
the MifosIcons.Cancel icon and calls onDismiss() (use IconButton { Icon(...) }
or the Compose equivalent) so the touch target meets the 48×48 dp minimum;
change the icon's contentDescription from the shared feature_loan_cancel string
to a dedicated string resource (e.g., feature_loan_close) so screen readers
distinguish the close icon from the Cancel button below, and add that new string
resource ("Close"/"Dismiss") accordingly.
- Around line 223-231: The current createSelectableDatesFrom implementation only
overrides isSelectableDate, causing the year spinner to allow navigation before
minDate and permitting future dates; update the returned SelectableDates
anonymous object to also override isSelectableYear(year: Int): Boolean to return
year in minDate.year..today.year (compute today via
Clock.System.now()/Instant/LocalDate with TimeZone.UTC), and modify
isSelectableDate to also cap the upper bound by today (i.e., return selectedDate
>= minDate && selectedDate <= today) so both individual dates and year
navigation are correctly constrained; refer to createSelectableDatesFrom,
isSelectableDate, isSelectableYear, LocalDate and TimeZone.UTC to locate the
changes.
- Around line 56-62: The file imports the wrong Instant
(kotlinx.datetime.Instant) which is incompatible with kotlinx-datetime 0.7.1;
remove the line importing kotlinx.datetime.Instant and replace it with import
kotlin.time.Instant so the Instant.fromEpochMilliseconds() calls in
ExportTransactionsDialog (and related uses alongside kotlin.time.Clock) compile
correctly.

---

Nitpick comments:
In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`:
- Around line 185-197: Replace the unsafe non-null assertions in the MifosButton
onClick (currently calling onGenerateReport(fromDate!!, toDate!!)) with a
safe-call/let pattern that only invokes onGenerateReport when both fromDate and
toDate are non-null; update the onClick in ExportTransactionsDialog (the
MifosButton handler) to check fromDate and toDate via safe calls (e.g., nested
let or a combined null-check) before calling onGenerateReport so the call no
longer relies on !! while preserving the enabled/isValidDateRange behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (4)
feature/loan/src/commonMain/composeResources/values/strings.xml (1)

297-298: feature_loan_export and feature_loan_export_transactions have identical values.

Both resolve to "Export". If the dialog title ever needs to read "Export Transactions" (which is common UX), the strings will need to be separated anyway. Consider differentiating them now.

♻️ Suggested rename
-    <string name="feature_loan_export_transactions">Export</string>
+    <string name="feature_loan_export_transactions">Export Transactions</string>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@feature/loan/src/commonMain/composeResources/values/strings.xml` around lines
297 - 298, The two string resources feature_loan_export and
feature_loan_export_transactions both have the same value "Export", which
prevents using a distinct dialog title like "Export Transactions"; update
feature_loan_export_transactions to a more specific label such as "Export
Transactions" (or another appropriate differentiated text) and ensure any
callers that expect the dialog title use feature_loan_export_transactions,
leaving feature_loan_export for the generic export label; also update any
localization entries that mirror these keys.
feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt (3)

185-187: Replace !! assertions with a safe let call.

fromDate!! and toDate!! are guarded by isValidDateRange, so they cannot NPE at runtime, but non-null assertions are generally fragile if the guard condition changes in the future.

♻️ Proposed refactor
-            onClick = {
-                onGenerateReport(fromDate!!, toDate!!)
-            },
+            onClick = {
+                val from = fromDate
+                val to = toDate
+                if (from != null && to != null) {
+                    onGenerateReport(from, to)
+                }
+            },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`
around lines 185 - 187, The onClick currently calls onGenerateReport(fromDate!!,
toDate!!) using non-null assertions which is fragile; instead, guard the call
with a safe let so the report is only generated when both dates are non-null. In
ExportTransactionsDialog, replace the forced unwraps by checking the same
condition you use for enabling (isValidDateRange) or use fromDate?.let { f ->
toDate?.let { t -> onGenerateReport(f, t) } } so onGenerateReport is invoked
only with non-null f and t.

114-116: Box wrapper has no effect and can be removed.

Box(contentAlignment = Alignment.Center) only makes sense when children overlap. Here it wraps a single Column child; the contentAlignment is ignored, and the Box adds a pointless layout node.

♻️ Proposed fix
-            Box(
-                contentAlignment = Alignment.Center,
-            ) {
-                Column(modifier = Modifier.padding(20.dp)) {
+            Column(modifier = Modifier.padding(20.dp)) {

Also remove the corresponding closing } for the Box.

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

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`
around lines 114 - 116, Remove the unnecessary Box wrapper in
ExportTransactionsDialog: delete the Box(contentAlignment = Alignment.Center, )
block and its matching closing brace so the inner Column becomes the direct
child of the parent composable; this removes a pointless layout node since Box's
contentAlignment is unused when only a single Column child is present (search
for Box(...) and the nested Column in ExportTransactionsDialog to locate the
code).

83-86: toDatePickerState minimum date doesn't reflect the selected fromDate.

Both picker states hardcode 2000-01-01 as the minimum, so the "To Date" picker allows selecting any date from 2000 onwards regardless of what fromDate is set to. Users can pick an invalid range in the picker itself, with only a post-selection error message catching it. Reactively updating toDatePickerState's minimum to match fromDate would prevent the invalid selection entirely.

♻️ Suggested UX improvement
-    val toDatePickerState = rememberDatePickerState(
-        initialSelectedDateMillis = Clock.System.now().toEpochMilliseconds(),
-        selectableDates = createSelectableDatesFrom(LocalDate.parse("2000-01-01")),
-    )
+    val toDatePickerState = key(fromDate) {
+        rememberDatePickerState(
+            initialSelectedDateMillis = fromDate ?: Clock.System.now().toEpochMilliseconds(),
+            selectableDates = createSelectableDatesFrom(
+                minDate = fromDate
+                    ?.let { Instant.fromEpochMilliseconds(it).toLocalDateTime(TimeZone.UTC).date }
+                    ?: LocalDate.parse("2000-01-01"),
+            ),
+        )
+    }

Note: wrapping rememberDatePickerState in key(fromDate) recreates the picker state whenever fromDate changes, so toDate will also be reset when fromDate changes. Add handling if you want to preserve a previously valid toDate selection.

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

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`
around lines 83 - 86, The To-date picker currently hardcodes the minimum as
"2000-01-01" so users can pick a to-date earlier than the selected from-date;
update the toDatePickerState to react to the selected fromDate by recreating it
with the appropriate selectableDates (use
createSelectableDatesFrom(LocalDate.parse(fromDate)) or equivalent) so the
minimum equals the chosen fromDate; implement this by wrapping the
rememberDatePickerState call for toDatePickerState in key(fromDate) and
constructing selectableDates from the parsed fromDate so the picker prevents
invalid ranges (note you may need to add handling to preserve an existing valid
toDate if desired).
🤖 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/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`:
- Around line 191-195: The "Generate Report" label in ExportTransactionsDialog
can truncate on small screens or large font scales because the MifosButton (in
ExportTransactionsDialog) is given weight(1f) and the Text composable uses
maxLines = 1; fix by either shortening the label (change the stringResource used
by the Text in the MifosButton to "Generate") or allow wrapping by changing the
Text in ExportTransactionsDialog to maxLines = 2 (and optionally set overflow =
TextOverflow.Ellipsis) so the button text doesn't clip under increased font
scales; update the Text inside the MifosButton in ExportTransactionsDialog
accordingly.

---

Nitpick comments:
In `@feature/loan/src/commonMain/composeResources/values/strings.xml`:
- Around line 297-298: The two string resources feature_loan_export and
feature_loan_export_transactions both have the same value "Export", which
prevents using a distinct dialog title like "Export Transactions"; update
feature_loan_export_transactions to a more specific label such as "Export
Transactions" (or another appropriate differentiated text) and ensure any
callers that expect the dialog title use feature_loan_export_transactions,
leaving feature_loan_export for the generic export label; also update any
localization entries that mirror these keys.

In
`@feature/loan/src/commonMain/kotlin/com/mifos/feature/loan/loanTransaction/ExportTransactionsDialog.kt`:
- Around line 185-187: The onClick currently calls onGenerateReport(fromDate!!,
toDate!!) using non-null assertions which is fragile; instead, guard the call
with a safe let so the report is only generated when both dates are non-null. In
ExportTransactionsDialog, replace the forced unwraps by checking the same
condition you use for enabling (isValidDateRange) or use fromDate?.let { f ->
toDate?.let { t -> onGenerateReport(f, t) } } so onGenerateReport is invoked
only with non-null f and t.
- Around line 114-116: Remove the unnecessary Box wrapper in
ExportTransactionsDialog: delete the Box(contentAlignment = Alignment.Center, )
block and its matching closing brace so the inner Column becomes the direct
child of the parent composable; this removes a pointless layout node since Box's
contentAlignment is unused when only a single Column child is present (search
for Box(...) and the nested Column in ExportTransactionsDialog to locate the
code).
- Around line 83-86: The To-date picker currently hardcodes the minimum as
"2000-01-01" so users can pick a to-date earlier than the selected from-date;
update the toDatePickerState to react to the selected fromDate by recreating it
with the appropriate selectableDates (use
createSelectableDatesFrom(LocalDate.parse(fromDate)) or equivalent) so the
minimum equals the chosen fromDate; implement this by wrapping the
rememberDatePickerState call for toDatePickerState in key(fromDate) and
constructing selectableDates from the parsed fromDate so the picker prevents
invalid ranges (note you may need to add handling to preserve an existing valid
toDate if desired).

@gurnoorpannu gurnoorpannu requested a review from a team March 4, 2026 20:35

@biplab1 biplab1 Mar 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you tell us the reason for implementing a separate date picker instead of using import androidx.compose.material3.DatePickerDialog? Please refer other modules where such an implementation is already present.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

MifosDatePickerDialog in ui directly wraps androidx.compose.material3.DatePickerDialog under the hood (you can see the import )

@biplab1 biplab1 Mar 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I meant we could use the Material DatePickerDialog directly as done in other modules instead of introducing new core/ui components.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you please explain the reason for implementing this? There are several screens where similar inputs are handled without such an implementation.

As a general rule, the codebase already contains multiple existing implementations for common patterns. It’s important to look for and reuse those wherever applicable in your current task.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this was requested in this comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

should I undo this?

@biplab1 biplab1 Mar 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please refer to the similar existing implementation in the codebase instead of introducing core/ui components. If the required reference implementation is not present, then we should first discuss it in the project's Slack channel before implementing it in a PR.

Comment thread version.txt

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file shouldn't be a part of this PR. Please revert this change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

mb this was pushed by mistake will undo this

@niyajali niyajali left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@gurnoorpannu All of your pull requests have similar problems. Examine other projects, such as mifos-pay to see how the ViewModel and Screen were implemented. Update all of your pull requests to match and then request reviews again.

LoanTransactionsScreen(
uiState = uiState,
navigateBack = navigateBack,
onRetry = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

don't call any methods of ViewModel directly, consider send an appropriate action

@biplab1

biplab1 commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai Improve PR title based on github.com/openMF/mobile-wallet/wiki/Commit-style-guide. Give us just the title.

@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@biplab1: Based on the Commit Style Guide (present tense, lower case, type(scope): description format), here is the improved PR title:

feat(loan): add export transactions dialog to loan transactions screen

🌐 Web query:

openMF mobile-wallet wiki Commit style guide

💡 Result:

The openMF Mobile Wallet project (now hosted as openMF/mifos-pay) documents its commit message style guide in its GitHub Wiki. The guide recommends using:

  • Format: <type>(<scope>): <subject> (where <scope> is optional)
  • Types: feat, fix, docs, refactor, test, chore, misc
  • Example: feat(core): allow overriding of gradle config
  • Notes: scopes should be brief/recognizable, and the subject should be a short present-tense summary in lower case. [1]

The repository README links to this Wiki page under “How to Contribute” → “commit style guidelines”. [2]

Sources: [1] (github.com), [2] (github.com)

Citations:


@biplab1: Based on the commit style guide format <type>(<scope>): <subject>, using present-tense lower-case subject and a recognized scope, here is the improved PR title:

feat(loan): add export transactions dialog to loan transactions screen

🧠 Learnings used
Learnt from: biplab1
Repo: openMF/mifos-x-field-officer-app PR: 2647
File: feature/loan/src/commonMain/composeResources/values/strings.xml:460-460
Timestamp: 2026-03-24T00:43:11.613Z
Learning: In PR `#2647` (openMF/mifos-x-field-officer-app), the timeline string resource keys in `feature/loan/src/commonMain/composeResources/values/strings.xml` should follow the `_on_date` suffix naming pattern for date-type events (e.g., `feature_loan_timeline_amount_disbursed_on_date`, `feature_loan_timeline_application_submitted_on_date`, `feature_loan_timeline_application_approved_on_date`, `feature_loan_timeline_expected_disbursement_on_date`, `feature_loan_timeline_expected_maturity_on_date`, `feature_loan_timeline_maturity_on_date`). This was a naming convention decision by maintainer biplab1 to make date-carrying keys clearly distinguishable from state-only keys.

Learnt from: sahilshivekar
Repo: openMF/mifos-x-field-officer-app PR: 2647
File: feature/loan/src/commonMain/composeResources/values/strings.xml:452-452
Timestamp: 2026-03-16T11:54:08.124Z
Learning: In PR `#2647` (openMF/mifos-x-field-officer-app), the string resource `feature_loan_timeline_disbursed_date` in `feature/loan/src/commonMain/composeResources/values/strings.xml` intentionally uses the value "Amount Disbursed" as a timeline step label. It conveys that the loan amount was disbursed on the date shown below it in the timeline, not just a bare date field label. This is a deliberate UX copy choice.

@biplab1 biplab1 changed the title Implemented a Export Dialog Box in Transaction Screen feat(loan): add export transactions dialog to loan transactions screen Apr 13, 2026
}
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val selectedRow by viewModel.selectedRow.collectAsStateWithLifecycle()
val exportDialogState by viewModel.exportDialogState.collectAsStateWithLifecycle()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

as we are following MVI , all 3 should be in single state

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

no need of maintaining individual states

exportDialogState = exportDialogState,
onNavigateBack = navigateBack,
onRetry = viewModel::retry,
onRowSelected = viewModel::onRowSelected,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

craete onAction() and handle actions in viewmodel see mifos-mobile or wallet for reference

onRetry: () -> Unit = {},
onRowSelected: (LoanTransactionsUiState.LoanTransactionsTableData.TransactionRowData) -> Unit = {},
onDismissBottomSheet: () -> Unit = {},
onTransactionAction: (TransactionAction, Int) -> Unit = { _, _ -> },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

pass only OnAction and remove all lamdas

@gurnoorpannu

Copy link
Copy Markdown
Contributor Author

@revanthkumarJ made the changes

Comment thread core/ui/build.gradle.kts
commonMain.dependencies {
api(projects.core.designsystem)
api(projects.core.common)
api(libs.kotlinx.datetime)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can i know why you added api(projects.core.common) if tehre are no chnages in core:ui

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

oh my bad will fix this

val snackbarHostState = remember {
SnackbarHostState()
}
val snackbarHostState = remember { SnackbarHostState() }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm once have we used snackbarHostState anywhere if it is not used to show any meessages there is no need to pass it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah , saw that . will remove this too

@gurnoorpannu gurnoorpannu requested a review from revanthkumarJ May 2, 2026 06:11
@sonarqubecloud

sonarqubecloud Bot commented May 7, 2026

Copy link
Copy Markdown

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.

8 participants