Skip to content

LOW-32: Make savings goal deposits first-class in transaction flow#74

Open
soliktomasz wants to merge 2 commits into
mainfrom
codex/linear-mention-low-32-make-savings-goal-deposits-first-cla
Open

LOW-32: Make savings goal deposits first-class in transaction flow#74
soliktomasz wants to merge 2 commits into
mainfrom
codex/linear-mention-low-32-make-savings-goal-deposits-first-cla

Conversation

@soliktomasz
Copy link
Copy Markdown
Owner

@soliktomasz soliktomasz commented May 17, 2026

Motivation

  • Goals compute progress from goal-linked TransferOut transactions but the UI did not carry a selected goal into the transaction flow so users could not easily create linked deposits.
  • The transaction form lacked a goal selector and the Goals page "Auto transfer" action was a dead control, preventing users from linking/unlinking transfers to goals.

Description

  • Pass savingsGoalId in the Goals page deposit and auto-transfer actions via the URL (/transactions?form=transfer&savingsGoalId=<id>).
  • Extend TransactionForm to track savingsGoalId, render a transfer-only savings goal selector, and include savingsGoalId in create/update payloads.
  • Load savings goals on the Transactions page, prefill the transfer form from the savingsGoalId URL param, and propagate the field when editing/duplicating transfers.
  • Add optional savingsGoalId to the apiClient.createTransaction and apiClient.updateTransaction payload typings and add UI labels for the new selector in I18nContext.
  • Add a unit test in TransactionForm.test.tsx that verifies a transfer submission includes the selected savingsGoalId.

Testing

  • Added a unit test TransactionForm.test.tsx that asserts apiClient.createTransaction is called with savingsGoalId when submitting a transfer, and the test file is included in the change set.
  • Attempted to run the test with npm test -- TransactionForm.test.tsx but the environment does not have vitest installed and the test run failed with sh: 1: vitest: not found.

Codex Task

Summary by CodeRabbit

  • New Features

    • Users can now associate transactions with savings goals via a dropdown selector in the transaction form.
    • When navigating to the transfer form from the Goals page, the current goal is automatically pre-selected.
    • Added savings goal selection for creating and editing transfer transactions.
  • Tests

    • Added test coverage for transaction form submission with savings goal selection.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

Warning

Rate limit exceeded

@soliktomasz has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 44 minutes and 31 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 406442c9-01e3-40b9-aeab-bbf6a5c65869

📥 Commits

Reviewing files that changed from the base of the PR and between 1f9d3c6 and afce358.

📒 Files selected for processing (6)
  • frontend/src/api/client.ts
  • frontend/src/components/TransactionForm.test.tsx
  • frontend/src/components/TransactionForm.tsx
  • frontend/src/pages/GoalsPage.tsx
  • frontend/src/pages/TransactionsPage.tsx
  • frontend/src/state/I18nContext.tsx
📝 Walkthrough

Walkthrough

The PR extends the transaction form to optionally associate transactions with savings goals. API client payloads now accept savingsGoalId, the form fetches and displays available goals in a dropdown for Transfer transactions, pages read goal IDs from URL parameters, and UI labels are localized across four languages.

Changes

Savings Goal Association for Transactions

Layer / File(s) Summary
API Contract Extension
frontend/src/api/client.ts
API client createTransaction and updateTransaction payload types extended with optional savingsGoalId?: string field.
Form Type and Prop Structure
frontend/src/components/TransactionForm.tsx
Imported SavingsGoal type, extended TransactionFormProps with optional savingsGoals list, initialized savingsGoalId default in form values, and added savingsGoals parameter destructuring.
Transfer Form UI and Submission
frontend/src/components/TransactionForm.tsx
Rendered a savings-goal <select> dropdown for Transfer transactions, wired to form state, and updated submission to include savingsGoalId in API payload for Transfer type.
Pages Data Fetching and Wiring
frontend/src/pages/TransactionsPage.tsx, frontend/src/pages/GoalsPage.tsx
TransactionsPage fetches available savings goals and reads savingsGoalId from URL query parameters, wires goals to both main and inline TransactionForm components, and includes savingsGoalId when editing/duplicating transfers. GoalsPage passes savingsGoalId in navigation URL for both deposit and transfer actions.
Test Coverage for savingsGoalId
frontend/src/components/TransactionForm.test.tsx
Added mocked API client methods and a test verifying TransactionForm submission in create mode invokes apiClient.createTransaction with savingsGoalId.
Translation Keys
frontend/src/state/I18nContext.tsx
Added transactionForm.savingsGoal and transactionForm.noSavingsGoal i18n keys across English, Polish, German, and Spanish translation dictionaries.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • soliktomasz/Ledgerra#73: Implements the backend counterpart—backup/restore, validation, and hydration of SavingsGoalId in archived transactions corresponding to the frontend transaction↔goal linkage.

  • soliktomasz/Ledgerra#38: Establishes the foundational transaction-contract and API client SavingsGoalId plumbing for transfer-goal linking that this PR builds upon.

  • soliktomasz/Ledgerra#15: Earlier refactor of TransactionForm.tsx submit logic for create/edit and transaction-type behavior that this PR extends with savings-goal field handling.

Poem

🐰 A goal and a transfer now hold hands so tight,
With dropdowns and queries, the UI shines bright.
From GoalsPage to TransactionForm they dance,
And savingsGoalId gets its well-deserved chance!
🎯✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: making savings goal deposits a first-class feature in the transaction workflow, which aligns with the PR's core objective of integrating goal selection throughout the transaction form and navigation flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/linear-mention-low-32-make-savings-goal-deposits-first-cla

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.

@soliktomasz soliktomasz marked this pull request as ready for review May 17, 2026 15:57
Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/TransactionForm.test.tsx`:
- Around line 76-77: Replace the nonstandard programmatic submit with a user
action and wait for the async side effect: change the test to click the Save
transaction button (use fireEvent.click on the button obtained via
screen.getByRole) instead of fireEvent.submit, and wrap the assertion about
apiClient.createTransaction (the mocked function) in waitFor so the test awaits
the async handleSubmit path and avoids the race condition.

In `@frontend/src/components/TransactionForm.tsx`:
- Around line 80-82: The object literal in TransactionForm that contains the
properties `note: ""` and `savingsGoalId: ""` is missing a comma after `note:
""`; update the object (the initializer inside the TransactionForm component
where `note` and `savingsGoalId` are defined) by adding a trailing comma after
`note: ""` so the properties are correctly separated and the file parses.

In `@frontend/src/state/I18nContext.tsx`:
- Around line 1201-1202: The Polish, German and Spanish dictionaries in
I18nContext.tsx still have English values for the keys
transactionForm.savingsGoal and transactionForm.noSavingsGoal; update those key
values in the Polish section to "Cel oszczędności" and "Brak celu oszczędności",
in the German section to "Sparziel" and "Kein Sparziel", and in the Spanish
section to "Objetivo de ahorro" and "Sin objetivo de ahorro" so each locale
shows the correct translations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 34054068-66ad-4917-900f-8a741360d6a7

📥 Commits

Reviewing files that changed from the base of the PR and between b5144d0 and 1f9d3c6.

📒 Files selected for processing (6)
  • frontend/src/api/client.ts
  • frontend/src/components/TransactionForm.test.tsx
  • frontend/src/components/TransactionForm.tsx
  • frontend/src/pages/GoalsPage.tsx
  • frontend/src/pages/TransactionsPage.tsx
  • frontend/src/state/I18nContext.tsx

Comment on lines +76 to +77
fireEvent.submit(screen.getByRole("button", { name: "Save transaction" }));
expect(apiClient.createTransaction).toHaveBeenCalledWith("token", expect.objectContaining({ savingsGoalId: "g1" }));
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the test file
fd -t f "TransactionForm.test.tsx"

Repository: soliktomasz/Ledgerra

Length of output: 113


🏁 Script executed:

# Check file size and content
if [ -f "frontend/src/components/TransactionForm.test.tsx" ]; then
  wc -l "frontend/src/components/TransactionForm.test.tsx"
fi

Repository: soliktomasz/Ledgerra

Length of output: 116


🏁 Script executed:

# Read the test file focusing on lines around 76-77
if [ -f "frontend/src/components/TransactionForm.test.tsx" ]; then
  cat -n "frontend/src/components/TransactionForm.test.tsx" | sed -n '1,100p'
fi

Repository: soliktomasz/Ledgerra

Length of output: 3429


🏁 Script executed:

# Check the TransactionForm component to understand the form submission behavior
fd -t f "TransactionForm.tsx" | grep -v test

Repository: soliktomasz/Ledgerra

Length of output: 108


🏁 Script executed:

# Read the TransactionForm component to understand form submission
cat -n "frontend/src/components/TransactionForm.tsx" | head -150

Repository: soliktomasz/Ledgerra

Length of output: 5417


🏁 Script executed:

# Search for the form submission handler in the component
rg -A 20 "createTransaction" "frontend/src/components/TransactionForm.tsx"

Repository: soliktomasz/Ledgerra

Length of output: 725


🏁 Script executed:

# Let's see more of the TransactionForm component, especially the form/button structure
rg -B 5 -A 10 "Save transaction|submit" "frontend/src/components/TransactionForm.tsx" | head -50

Repository: soliktomasz/Ledgerra

Length of output: 1854


🏁 Script executed:

# Check the complete handleSubmit and form structure
cat -n "frontend/src/components/TransactionForm.tsx" | sed -n '139,200p'

Repository: soliktomasz/Ledgerra

Length of output: 2573


Use a user-triggered submit path and await the async side effect.

Line 76 dispatches submit on the button element, which is non-standard with Testing Library; Line 77 also asserts immediately without awaiting, creating a race condition since handleSubmit is async and the mocked createTransaction resolves a promise. Use fireEvent.click on the button and wrap the assertion in waitFor.

Suggested test hardening
-import { cleanup, fireEvent, render, screen } from "`@testing-library/react`";
+import { cleanup, fireEvent, render, screen, waitFor } from "`@testing-library/react`";
...
-    fireEvent.submit(screen.getByRole("button", { name: "Save transaction" }));
-    expect(apiClient.createTransaction).toHaveBeenCalledWith("token", expect.objectContaining({ savingsGoalId: "g1" }));
+    fireEvent.click(screen.getByRole("button", { name: "Save transaction" }));
+    await waitFor(() => {
+      expect(apiClient.createTransaction).toHaveBeenCalledWith(
+        "token",
+        expect.objectContaining({ savingsGoalId: "g1" })
+      );
+    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/TransactionForm.test.tsx` around lines 76 - 77,
Replace the nonstandard programmatic submit with a user action and wait for the
async side effect: change the test to click the Save transaction button (use
fireEvent.click on the button obtained via screen.getByRole) instead of
fireEvent.submit, and wrap the assertion about apiClient.createTransaction (the
mocked function) in waitFor so the test awaits the async handleSubmit path and
avoids the race condition.

Comment thread frontend/src/components/TransactionForm.tsx Outdated
Comment thread frontend/src/state/I18nContext.tsx Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1f9d3c60d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +80 to +81
note: ""
savingsGoalId: ""
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Insert comma between default form value fields

Add a comma after note in buildDefaultValues; without it, this object literal is invalid syntax and TransactionForm.tsx cannot compile, which blocks the transaction UI (and related tests/build steps) from running at all.

Useful? React with 👍 / 👎.

@soliktomasz soliktomasz force-pushed the codex/linear-mention-low-32-make-savings-goal-deposits-first-cla branch from 1f9d3c6 to 3b02220 Compare May 17, 2026 16:03
Updates the "Savings goal" and "No savings goal" phrases to their correct Polish, German, and Spanish localizations. Previously, these phrases appeared in English within their respective language blocks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant