Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix wrong scheduled transfer payment direction on PWA #3402

Merged
merged 10 commits into from
Nov 19, 2024
Merged

Conversation

joel-jeremy
Copy link
Contributor

@joel-jeremy joel-jeremy commented Sep 9, 2024

Fixes #3230

This PR introduces a new hook useAccountPreviewTransactions which builds on top of the new usePreviewTransactions hook. This new hook centralizes the logic to inverse the payees, accounts, amounts depending on where the preview transactions are being viewed from.

@actual-github-bot actual-github-bot bot changed the title Fix #3230 [WIP] Fix #3230 Sep 9, 2024
Copy link

netlify bot commented Sep 9, 2024

Deploy Preview for actualbudget ready!

Name Link
🔨 Latest commit 1e01626
🔍 Latest deploy log https://app.netlify.com/sites/actualbudget/deploys/673d01a3309b660008b05060
😎 Deploy Preview https://deploy-preview-3402.demo.actualbudget.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@joel-jeremy joel-jeremy changed the title [WIP] Fix #3230 [Mobile] Fix wrong schedule transfer direction on PWA Sep 9, 2024
@joel-jeremy joel-jeremy changed the title [Mobile] Fix wrong schedule transfer direction on PWA [Mobile] Fix wrong scheduled transfer direction on PWA Sep 9, 2024
Copy link
Contributor

github-actions bot commented Sep 9, 2024

Bundle Stats — desktop-client

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
9 → 10 5.43 MB → 5.43 MB (-19 B) -0.00%
Changeset
File Δ Size
src/hooks/useAccountPreviewTransactions.ts 🆕 +1.63 kB 0 B → 1.63 kB
src/components/mobile/utils.ts 🆕 +344 B 0 B → 344 B
home/runner/work/actual/actual/packages/loot-core/src/shared/schedules.ts 📈 +75 B (+1.41%) 5.19 kB → 5.27 kB
home/runner/work/actual/actual/packages/loot-core/src/client/data-hooks/transactions.ts 📈 +32 B (+0.74%) 4.22 kB → 4.25 kB
src/components/mobile/accounts/AccountTransactions.tsx 📈 +39 B (+0.52%) 7.39 kB → 7.43 kB
src/components/accounts/Account.tsx 📈 +101 B (+0.22%) 44.53 kB → 44.63 kB
home/runner/work/actual/actual/packages/loot-core/src/client/data-hooks/schedules.tsx 📉 -1 B (-0.03%) 3.01 kB → 3.01 kB
src/components/transactions/TransactionsTable.jsx 📉 -220 B (-0.32%) 67.1 kB → 66.88 kB
src/components/mobile/transactions/TransactionEdit.jsx 📉 -412 B (-1.17%) 34.28 kB → 33.88 kB
src/components/mobile/transactions/TransactionListItem.tsx 📉 -86 B (-1.28%) 6.54 kB → 6.46 kB
home/runner/work/actual/actual/packages/loot-core/src/client/query-hooks.ts 📉 -17 B (-1.96%) 869 B → 852 B
src/hooks/usePreviewTransactions.ts 🔥 -1.5 kB (-100%) 1.5 kB → 0 B
View detailed bundle breakdown

Added

Asset File Size % Changed
static/js/useAccountPreviewTransactions.js 0 B → 1.63 kB (+1.63 kB) -

Removed

No assets were removed

Bigger

Asset File Size % Changed
static/js/narrow.js 82.68 kB → 82.72 kB (+39 B) +0.05%

Smaller

Asset File Size % Changed
static/js/wide.js 242.81 kB → 241.19 kB (-1.62 kB) -0.67%
static/js/index.js 3.44 MB → 3.44 MB (-65 B) -0.00%

Unchanged

Asset File Size % Changed
static/js/indexeddb-main-thread-worker-e59fee74.js 13.5 kB 0%
static/js/resize-observer.js 18.37 kB 0%
static/js/workbox-window.prod.es5.js 5.69 kB 0%
static/js/BackgroundImage.js 122.29 kB 0%
static/js/AppliedFilters.js 21.3 kB 0%
static/js/ReportRouter.js 1.49 MB 0%

Copy link
Contributor

github-actions bot commented Sep 9, 2024

Bundle Stats — loot-core

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
1 1.32 MB → 1.32 MB (+42 B) +0.00%
Changeset
File Δ Size
packages/loot-core/src/shared/schedules.ts 📈 +77 B (+0.83%) 9.1 kB → 9.18 kB
View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

Asset File Size % Changed
kcab.worker.js 1.32 MB → 1.32 MB (+42 B) +0.00%

Smaller

No assets were smaller

Unchanged

No assets were unchanged

@joel-jeremy joel-jeremy changed the title [Mobile] Fix wrong scheduled transfer direction on PWA Fix wrong scheduled transfer direction on PWA Sep 9, 2024
@joel-jeremy joel-jeremy changed the title Fix wrong scheduled transfer direction on PWA Fix wrong scheduled transfer payment direction on PWA Sep 10, 2024
Comment on lines -1654 to 1678
collapseTransactions={ids =>
this.props.splitsExpandedDispatch({ type: 'close-splits', ids })
}
>
Copy link
Contributor

@jfdoming jfdoming Sep 15, 2024

Choose a reason for hiding this comment

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

With the change from a callback to a useEffect, I now see a very brief flash of expanded preview transactions on desktop. It's not a big deal, but any ideas on how we can avoid that?

Repro: create test budget, update the "Fast Internet" schedule to a date in the future, and make it a splitting rule. Then view the "Bank of America" account

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be fixed now :)

Copy link
Contributor

coderabbitai bot commented Sep 18, 2024

Walkthrough

The pull request introduces significant changes across multiple components and hooks within the desktop client application. The Account.tsx file has undergone alterations to the AllTransactions component, removing the collapseTransactions prop and replacing the usePreviewTransactions hook with useAccountPreviewTransactions. This new hook accepts an accountId and provides a structured response containing previewTransactions and isLoading. Additionally, the handling of transactions has been refined, including the removal of the _inverse property from transaction objects. The AccountTransactions.tsx component also adopts the new hook, ensuring consistent transaction display logic.

In the TransactionEdit.jsx file, the getDescriptionPretty function has been removed, consolidating its functionality into the getPrettyPayee logic, which now utilizes a new hook. The TransactionsTable.jsx file has seen updates in transaction serialization and styling, enhancing clarity. The getScheduledAmount function has been modified to accommodate new input types, and the _amount property in the ScheduleEntity interface has been updated for better specificity. Overall, these changes streamline transaction handling and improve code maintainability.

Assessment against linked issues

Objective Addressed Explanation
Ensure correct handling of transaction amounts in the preview (3230)
Adjust transaction display logic to reflect payment direction (3230)

Possibly related PRs

Suggested labels

::sparkles: Merged

Suggested reviewers

  • youngcw
  • jfdoming

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/desktop-client/src/components/accounts/Account.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-eslint-plugin".

(The package "eslint-plugin-eslint-plugin" was not found when loaded as a Node module from the directory "/packages/eslint-plugin-actual".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-eslint-plugin@latest --save-dev

The plugin "eslint-plugin-eslint-plugin" was referenced from the config file in "packages/eslint-plugin-actual/.eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

Outside diff range and nitpick comments (1)
packages/loot-core/src/shared/schedules.ts (1)

272-281: LGTM!

The changes to the getScheduledAmount function look good. The function now correctly handles both number and object inputs, and the inverse flag is used to conditionally negate the input values.

Consider simplifying the object case by using object destructuring and the ternary operator:

-  const num1 = inverse ? -amount.num1 : amount.num1;
-  const num2 = inverse ? -amount.num2 : amount.num2;
-  return Math.round((num1 + num2) / 2);
+  const { num1, num2 } = amount;
+  return Math.round((inverse ? -num1 : num1 + inverse ? -num2 : num2) / 2);
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 17fd068 and 01e41fa.

Files selected for processing (10)
  • packages/desktop-client/src/components/accounts/Account.tsx (4 hunks)
  • packages/desktop-client/src/components/mobile/accounts/AccountTransactions.jsx (1 hunks)
  • packages/desktop-client/src/components/mobile/transactions/Transaction.jsx (4 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (8 hunks)
  • packages/desktop-client/src/components/mobile/usePrettyPayee.ts (1 hunks)
  • packages/desktop-client/src/components/transactions/TransactionsTable.jsx (4 hunks)
  • packages/desktop-client/src/hooks/usePreviewTransactions.ts (2 hunks)
  • packages/loot-core/src/shared/schedules.ts (1 hunks)
  • packages/loot-core/src/types/models/schedule.d.ts (1 hunks)
  • upcoming-release-notes/3402.md (1 hunks)
Additional comments not posted (31)
upcoming-release-notes/3402.md (1)

1-6: Release note looks good!

The release note accurately summarizes the bug fix based on the provided PR objectives and summary. It concisely describes the issue of wrong scheduled transaction amounts in the PWA and implies that the fix addresses this problem.

packages/desktop-client/src/components/mobile/usePrettyPayee.ts (1)

1-43: LGTM! The usePrettyPayee hook is well-implemented and covers various scenarios.

The usePrettyPayee hook is a great addition to the codebase. It provides a centralized and reusable way to format payee strings based on the context of a financial transaction. The hook takes into account various scenarios such as preview transactions, inverse transactions, transfer accounts, parent transactions, and regular payees.

The logic within the hook is well-structured and correctly extracts relevant properties from the transaction object. It utilizes the isPreviewId function to determine if the transaction is a preview and adjusts the amount accordingly based on the _inverse flag. The handling of transfer accounts considers both preview and inverse scenarios, ensuring accurate representation of the transfer direction.

The hook also handles parent transactions by returning the string "Split" and falls back to returning the payee's name if no specific conditions are met. In case none of the conditions are satisfied, it returns an empty string as a fallback.

Overall, the usePrettyPayee hook enhances the user experience by providing clear and contextual descriptions of transactions. It is a valuable addition to the codebase and will help maintain consistency in displaying payee information across the application.

packages/desktop-client/src/hooks/usePreviewTransactions.ts (4)

9-12: LGTM!

The imports are necessary and look good.


16-18: LGTM!

The new PreviewTransactionEntity type is necessary for adding the _inverse property to the TransactionEntity type. The type definition looks good.


64-69: LGTM!

The change in the setPreviewTransactions function is necessary for setting the _inverse property for each transaction. The logic and syntax look good.


20-24: Verify the function signature change in the codebase.

The change in the function signature is necessary for accepting the accountId parameter. The function signature looks good.

Run the following script to verify the function usage:

Verification successful

Function signature change verified successfully

The usePreviewTransactions function is correctly used with the new signature in the codebase. The only usage found is in ./packages/desktop-client/src/components/accounts/Account.tsx on line 161, where it's called as usePreviewTransactions({ accountId }). This matches the new signature that accepts an object with an optional accountId property.

No other occurrences of the function usage were found, suggesting that the changes have been properly applied throughout the codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `usePreviewTransactions` match the new signature.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type typescript -A 5 $'usePreviewTransactions'

Length of output: 85


Script:

#!/bin/bash
# Description: Verify all function calls to `usePreviewTransactions` match the new signature.

# Search for .ts and .tsx files containing usePreviewTransactions
find . -type f \( -name "*.ts" -o -name "*.tsx" \) -print0 | xargs -0 grep -n -A 5 "usePreviewTransactions" | grep -v "packages/desktop-client/src/hooks/usePreviewTransactions.ts"

Length of output: 1403

packages/desktop-client/src/components/mobile/transactions/Transaction.jsx (7)

29-29: LGTM!

The import statement for the usePrettyPayee hook is valid and follows the correct syntax. The naming convention suggests its purpose is to format or enhance the payee information for display.


75-75: Verify the purpose and usage of the _inverse property.

The newly destructured _inverse property from the transaction object suggests it represents some form of inversion or opposite state related to the transaction. However, its specific purpose and how it is used within the component is not clear from this line alone.

Please provide more context on what this property represents and how it is utilized in the component's logic, especially in relation to the transaction's state or behavior.


80-80: LGTM!

Renaming the variable from transferAcct to transferAccount enhances code readability by using a more descriptive and intuitive name. This change does not affect the functionality as it is a local variable.


107-111: LGTM!

The usage of the usePrettyPayee hook to derive the prettyPayee value is a good approach. By passing the relevant data (transaction, payee, transferAccount) to the hook, it encapsulates the logic to determine the appropriate payee name or details for display purposes. This promotes code reusability and keeps the component focused on rendering concerns.


102-102: Verify the behavior of getScheduledAmount and the impact of _inverse.

The amount value is conditionally assigned the result of getScheduledAmount(amount, _inverse) when isPreview is true. This suggests that for preview transactions, the scheduled amount needs to be calculated considering the _inverse property. However, the specific logic inside the getScheduledAmount function is not visible in this code snippet.

Please provide more context on how the _inverse property is used within getScheduledAmount and how it affects the calculated amount. It would be helpful to review the implementation of getScheduledAmount to ensure the behavior aligns with the expected functionality for preview transactions.


114-114: LGTM!

The update in the ternary operator condition to use the renamed transferAccount variable is consistent with the previous variable renaming. This change maintains the existing logic while improving code readability.


176-182: LGTM!

The conditional style update based on prettyPayee being an empty string is a reasonable approach to visually distinguish the case when there is no meaningful payee information available. Setting the color to theme.tableTextLight and font style to 'italic' provides a clear indication of this scenario.

Additionally, updating the displayed payee text from prettyDescription to prettyPayee aligns with the introduction of the usePrettyPayee hook and ensures that the UI reflects the formatted or enhanced payee information derived from the hook.

packages/desktop-client/src/components/mobile/accounts/AccountTransactions.jsx (1)

147-149: LGTM! The code change addresses the PR objective.

The modification to the usePreviewTransactions hook, passing the accountId derived from the account prop, allows the hook to retrieve transactions specific to the selected account. This change should help resolve the issue of incorrect display of payment and debit directions for upcoming transfer transactions in the PWA.

The logic for combining the transactions remains intact, ensuring that the component continues to function as expected.

packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (6)

64-64: Great refactor!

Introducing the usePrettyPayee custom hook is a nice way to centralize the payee description generation logic. It enhances maintainability and readability by encapsulating this functionality in a single place.


Line range hint 280-296: Looks good!

The ChildTransactionEdit component has been updated to use the usePrettyPayee hook for retrieving the pretty payee description. This change aligns with the introduction of the hook and ensures consistency in handling payee information.

Additionally, the prop renaming from getTransferAcct to getTransferAccount enhances code clarity.


486-492: Nice renaming!

Renaming the getTransferAcct function to getTransferAccount enhances code clarity and readability. This change makes the purpose of the function more evident.


689-693: Good usage of the new hook!

The TransactionEditInner component now directly uses the usePrettyPayee hook to obtain the title. This change aligns with the introduction of the hook and ensures consistency in retrieving the payee description across the codebase.


764-764: Consistent usage of usePrettyPayee.

The title value is now obtained using the usePrettyPayee hook, which is consistent with the changes made in other parts of the code. This ensures a unified approach to retrieving the payee description.


812-813: Prop renaming for clarity.

Renaming the getTransferAcct prop to getTransferAccount improves code clarity and readability. This change makes the purpose of the prop more evident and aligns with the function renaming.

packages/desktop-client/src/components/accounts/Account.tsx (5)

8-8: LGTM!

The useLayoutEffect import seems to be valid based on its usage later in the code.


160-161: LGTM!

The usage of usePreviewTransactions hook with { accountId } as an argument and typing prependTransactions as PreviewTransactionEntity[] looks good.


163-168: LGTM!

The usage of useLayoutEffect hook to dispatch an action for closing splits of parent transactions whenever prependTransactions changes looks good. The side effect is well-defined and the dependencies are correctly specified.


57-60: Verify the usage of imported type and hook.

The new import statements seem to be valid. However, verify that PreviewTransactionEntity type and usePreviewTransactions hook are being used correctly in the component.

Run the following script to verify the usage:

Verification successful

Imports are correctly used in the component.

The PreviewTransactionEntity type and usePreviewTransactions hook are both properly imported and utilized in the Account.tsx component:

  • PreviewTransactionEntity is used to type the prependTransactions variable.
  • usePreviewTransactions hook is called with the accountId parameter.

These imports are necessary and correctly implemented.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `PreviewTransactionEntity` type and `usePreviewTransactions` hook.

# Test: Search for the usage of `PreviewTransactionEntity` type. Expect: At least one match.
rg --type typescript $'PreviewTransactionEntity' -A 5

# Test: Search for the usage of `usePreviewTransactions` hook. Expect: At least one match.
rg --type typescript $'usePreviewTransactions\(' -A 5

Length of output: 177


Script:

#!/bin/bash
# Description: Verify the usage of `PreviewTransactionEntity` type and `usePreviewTransactions` hook.

# Find TypeScript files and search for `PreviewTransactionEntity`
fd -e ts -e tsx | xargs rg 'PreviewTransactionEntity' -n -A 5

# Find TypeScript files and search for `usePreviewTransactions`
fd -e ts -e tsx | xargs rg 'usePreviewTransactions\(' -n -A 5

Length of output: 3988


191-194: Verify the correctness of _inverse property on scheduledTransaction objects.

The change assumes that the _inverse property is correctly set on the scheduledTransaction objects returned by the usePreviewTransactions hook. Verify that this assumption holds true. If the property is correctly set, then this change looks good.

Run the following script to verify the _inverse property:

Verification successful

The _inverse property is correctly implemented and used.

The verification process confirms that the _inverse property is properly set on scheduledTransaction objects returned by the usePreviewTransactions hook. The property is determined based on whether the transaction's account matches the current accountId:

_inverse: accountId ? accountId !== t.account : false,

This implementation ensures that the _inverse property correctly indicates whether a transaction is incoming or outgoing relative to the current account. The property is then used appropriately in other parts of the codebase, such as in the usePrettyPayee hook and when calculating scheduled amounts.

The change in the original review comment, which directly passes scheduledTransaction._inverse to the getScheduledAmount function, is consistent with this implementation and can be approved.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that `scheduledTransaction` objects have the correct `_inverse` property.

# Test: Search for the usage of `usePreviewTransactions` hook and print the `_inverse` property of returned objects. 
# Expect: `_inverse` property should be a boolean value.
rg --type typescript $'usePreviewTransactions\(' -A 10 | rg $'_inverse'

Length of output: 104


Script:

#!/bin/bash
# Description: Verify the usage of usePreviewTransactions hook and _inverse property

# Search for usePreviewTransactions in .ts and .tsx files
echo "Searching for usePreviewTransactions:"
rg --type ts "usePreviewTransactions" -A 10

# Search for _inverse property in .ts and .tsx files
echo "\nSearching for _inverse property:"
rg --type ts "_inverse"

# Search for both usePreviewTransactions and _inverse in proximity
echo "\nSearching for usePreviewTransactions and _inverse in proximity:"
rg --type ts -e "usePreviewTransactions" -e "_inverse" -C 15

Length of output: 22673

packages/desktop-client/src/components/transactions/TransactionsTable.jsx (6)

94-94: LGTM!

Passing the transaction._inverse value to getScheduledAmount enhances the clarity of the amount calculation by directly incorporating the inverse logic into the function call.


746-752: LGTM!

Defining the payeeIconButtonStyle object improves code maintainability by centralizing the styles for payee icon buttons.


753-754: LGTM!

Defining the scheduleIconStyle and transferIconStyle objects improves code maintainability by centralizing the styles for schedule and transfer icons.


775-775: LGTM!

Extracting the logic for determining whether a transaction is a deposit into the isDeposit variable improves code readability and clarity.


783-783: LGTM!

Using the centralized payeeIconButtonStyle object for the style prop of the Button component ensures consistent styling and improves maintainability.


Line range hint 799-810: LGTM!

The changes in this code segment improve the maintainability and clarity of the transfer button:

  • Using the centralized payeeIconButtonStyle object for consistent styling.
  • Conditionally rendering arrow icons based on the isDeposit variable to clearly indicate the transfer direction.

@youngcw youngcw added this to the v24.10.0 milestone Sep 20, 2024
@jfdoming
Copy link
Contributor

jfdoming commented Sep 24, 2024

Thanks for the fix! It does seem to work better now, but I'm always a little wary of useLayoutEffect because it causes React to do two full renders. Since we don't actually need the first render at all (we're not measuring any component's size or something, just updating the state in a deterministic way), do you think another way can work?

Copy link
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: 6

🧹 Outside diff range and nitpick comments (11)
packages/desktop-client/src/components/mobile/usePrettyPayee.ts (2)

29-42: Refactor nested ternary operators for better readability.

The conditional logic effectively handles different scenarios and addresses the issue mentioned in the PR objectives. However, the nested ternary operators for transferAccountName could be simplified for better readability and maintainability.

Consider refactoring the transferAccountName assignment:

-    const transferAccountName = isPreview
-      ? _inverse
-        ? transactionAccount?.name
-        : transferAccount.name
-      : transferAccount.name;
+    const transferAccountName = isPreview && _inverse
+      ? transactionAccount?.name
+      : transferAccount.name;

This refactored version simplifies the logic while maintaining the same functionality.

The overall logic for handling different scenarios (transfer, split transaction, payee) is well-structured and follows good practices with early returns.


1-43: Overall implementation looks good, but consider performance optimization.

The usePrettyPayee hook effectively addresses the issue of incorrect display of payment and debit directions for upcoming transfer transactions. The implementation is well-structured, type-safe, and handles various scenarios appropriately.

However, there's an important consideration raised in the PR comments regarding the use of useLayoutEffect. While this hook doesn't directly use useLayoutEffect, it's crucial to ensure that any components using usePrettyPayee are not unnecessarily triggering additional renders.

To address the performance concern:

  1. Ensure that the state updates in components using this hook are wrapped in useMemo or useCallback where appropriate to prevent unnecessary re-renders.
  2. Consider memoizing the result of usePrettyPayee if it's used in multiple places within a component.
  3. If possible, lift the state management higher in the component tree to reduce the number of components that need to re-render when the transaction details change.

These optimizations should help mitigate any performance issues without needing to resort to useLayoutEffect.

packages/desktop-client/src/components/mobile/transactions/Transaction.jsx (1)

107-111: LGTM: Improved payee handling and display.

The replacement of prettyDescription with prettyPayee using the usePrettyPayee hook is a good improvement. It provides a more modular and potentially more efficient way of handling payee information. The updated rendering logic also handles empty payee names more gracefully.

Consider memoizing the result of usePrettyPayee to optimize performance, especially if the hook performs expensive calculations:

const prettyPayee = React.useMemo(
  () => usePrettyPayee({
    transaction,
    payee,
    transferAccount,
  }),
  [transaction, payee, transferAccount]
);

This optimization can help prevent unnecessary re-renders if the component updates frequently.

Also applies to: 176-182

packages/desktop-client/src/components/transactions/TransactionsTable.jsx (3)

95-95: Approved: Improved handling of scheduled transfer payment direction.

The modification to use getScheduledAmount(amount, transaction._inverse) addresses the issue of incorrect payment direction for scheduled transfers. This change aligns with the PR objectives and should resolve the problem described in issue #3230.

Consider adding a brief comment explaining the purpose of the _inverse parameter for better code readability:

-    amount = getScheduledAmount(amount, transaction._inverse);
+    // Use _inverse to correctly handle the direction of scheduled transfers
+    amount = getScheduledAmount(amount, transaction._inverse);

Line range hint 747-814: Approved: Improved code structure and readability in PayeeIcons component.

The changes to the PayeeIcons component enhance code maintainability by extracting style constants and simplifying the logic for determining deposits. These modifications align with React best practices and improve overall code quality.

For consistency with other parts of the codebase, consider using object shorthand notation for the style constants:

-const payeeIconButtonStyle = {
-  marginLeft: -5,
-  marginRight: 2,
-  width: 23,
-  height: 23,
-  color: 'inherit',
-};
+const payeeIconButtonStyle = {
+  marginLeft: -5,
+  marginRight: 2,
+  width: 23,
+  height: 23,
+  color: 'inherit',
+};
🧰 Tools
🪛 Biome

[error] 775-775: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


Line range hint 1-2392: Consider future refactoring for improved maintainability.

While the changes in this PR are well-implemented and address the specific issues at hand, the overall file structure could benefit from some refactoring in the future. Some suggestions for future improvements:

  1. Break down larger components (e.g., TransactionTableInner) into smaller, more manageable pieces.
  2. Consider extracting some of the complex logic into custom hooks or utility functions.
  3. Group related functions and components together, possibly into separate files, to improve code organization.

These suggestions are not critical for this PR but could be considered for future maintenance and refactoring efforts.

🧰 Tools
🪛 Biome

[error] 775-775: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/desktop-client/src/hooks/usePreviewTransactions.ts (4)

9-12: Consistent Import Paths

You are importing AccountEntity and ScheduleEntity from 'loot-core/types/models', while TransactionEntity is imported from '../../../loot-core/src/types/models/transaction.d'. For consistency and improved maintainability, consider importing all entities from the same module if possible.

Suggested change:

 import {
   type ScheduleStatuses,
   useCachedSchedules,
 } from 'loot-core/client/data-hooks/schedules';
 import { send } from 'loot-core/platform/client/fetch';
 import { ungroupTransactions } from 'loot-core/shared/transactions';
 import {
   type AccountEntity,
   type ScheduleEntity,
+  type TransactionEntity,
 } from 'loot-core/types/models';

-import { type TransactionEntity } from '../../../loot-core/src/types/models/transaction.d';

16-18: Avoid Using Underscore Prefix for Property Names

The property _inverse in PreviewTransactionEntity uses an underscore prefix, which may cause confusion since underscore prefixes are often used to indicate private or protected properties. Consider renaming _inverse to isInverse or inverse for better clarity and to follow common naming conventions.

Suggested change:

 export type PreviewTransactionEntity = TransactionEntity & {
-  _inverse?: boolean;
+  isInverse?: boolean;
 };

And update all occurrences of _inverse in the code accordingly.


20-24: Simplify Function Parameter Type Annotation

The type annotation for the usePreviewTransactions function parameters can be simplified for better readability. Instead of annotating the parameter inline, consider defining a separate interface or type for the parameters.

Suggested change:

+interface UsePreviewTransactionsParams {
+  accountId?: AccountEntity['id'];
+}

-export function usePreviewTransactions({
-  accountId,
-}: {
-  accountId?: AccountEntity['id'];
-}): PreviewTransactionEntity[] {
+export function usePreviewTransactions({ accountId }: UsePreviewTransactionsParams): PreviewTransactionEntity[] {

Line range hint 25-44: Avoid Side Effects During Render

The function usePreviewTransactions performs state updates directly within the function body when scheduleData changes. This can cause side effects during the rendering phase, leading to potential issues like infinite loops or unexpected behavior.

According to React Hooks best practices, side effects should be placed inside useEffect hooks to ensure they're executed appropriately after render. Move the state updates into a useEffect hook that depends on scheduleData.

Suggested refactor:

 import { useState, useEffect } from 'react';

 export function usePreviewTransactions({ accountId }: { accountId?: AccountEntity['id'] }): PreviewTransactionEntity[] {
   const scheduleData = useCachedSchedules();
-  const [previousScheduleData, setPreviousScheduleData] =
-    useState<ReturnType<typeof useCachedSchedules>>(scheduleData);
   const [previewTransactions, setPreviewTransactions] = useState<
     PreviewTransactionEntity[]
   >([]);

-  if (scheduleData !== previousScheduleData) {
-    setPreviousScheduleData(scheduleData);
-
+  useEffect(() => {
     if (scheduleData) {
       // Kick off an async rules application
       const schedules =
         scheduleData.schedules.filter(s =>
           isForPreview(s, scheduleData.statuses),
         ) || [];

       // ... rest of the code ...

       Promise.all(
         baseTrans.map(transaction => send('rules-run', { transaction })),
       )
         .then(newTrans => {
           // existing logic
           setPreviewTransactions(
             ungroupTransactions(withDefaults).map(t => ({
               ...t,
               _inverse: accountId ? accountId !== t.account : false,
             })),
           );
         })
+        .catch(error => {
+          console.error('Error fetching preview transactions:', error);
+        });
     }
-    return previewTransactions;
-  }
-
   return previewTransactions;
 }
packages/loot-core/src/shared/schedules.ts (1)

279-280: Simplify code by reducing redundancy

Currently, the code negates num1 and num2 individually when inverse is true. This can be simplified by calculating the sum first and then applying the inversion if necessary, which enhances readability and reduces redundancy.

Refactored code suggestion:

-  const num1 = inverse ? -amount.num1 : amount.num1;
-  const num2 = inverse ? -amount.num2 : amount.num2;
-  return Math.round((num1 + num2) / 2);
+  const sum = amount.num1 + amount.num2;
+  const avg = sum / 2;
+  return inverse ? -Math.round(avg) : Math.round(avg);

This approach calculates the average first and then applies the inversion, making the logic clearer.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 01e41fa and b02dda4.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/3402.md is excluded by !**/*.md
📒 Files selected for processing (9)
  • packages/desktop-client/src/components/accounts/Account.tsx (4 hunks)
  • packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx (1 hunks)
  • packages/desktop-client/src/components/mobile/transactions/Transaction.jsx (4 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (8 hunks)
  • packages/desktop-client/src/components/mobile/usePrettyPayee.ts (1 hunks)
  • packages/desktop-client/src/components/transactions/TransactionsTable.jsx (4 hunks)
  • packages/desktop-client/src/hooks/usePreviewTransactions.ts (2 hunks)
  • packages/loot-core/src/shared/schedules.ts (1 hunks)
  • packages/loot-core/src/types/models/schedule.d.ts (1 hunks)
🔇 Additional comments (20)
packages/desktop-client/src/components/mobile/usePrettyPayee.ts (2)

1-14: LGTM: Imports and type definitions are well-structured.

The imports and type definitions are clear, concise, and appropriate for the hook's functionality. The UsePrettyPayeeProps type is well-defined, providing a clear interface for the hook's parameters.


16-24: LGTM: Hook declaration and initial setup look good.

The function declaration, parameter destructuring, and initial variable setup are well-implemented. The use of the useAccount hook suggests proper integration with the existing codebase.

To ensure the useAccount hook is being used correctly, please run the following script:

✅ Verification successful

Verification Successful: useAccount hook is correctly implemented and used consistently.

All usages of the useAccount hook have been verified and are consistent with the implementation. No issues were found in the reviewed segment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation and usage of the useAccount hook

# Test: Check the implementation of useAccount
echo "Checking useAccount implementation:"
ast-grep --lang typescript --pattern 'export function useAccount($_) { $$$ }'

# Test: Check for other usages of useAccount in the codebase
echo "Checking useAccount usage in other files:"
rg --type typescript 'useAccount\(' -C 3

Length of output: 681


Script:

#!/bin/bash
# Description: Verify the usage of the useAccount hook by searching in .ts and .tsx files

# Test: Check for other usages of useAccount in the codebase
echo "Checking useAccount usage in .ts and .tsx files:"
rg 'useAccount\(' --type-add 'ts=*.ts' --type-add 'tsx=*.tsx' -t ts -t tsx -C 3

Length of output: 248


Script:

#!/bin/bash
# Description: Verify the usage of the useAccount hook by searching in .ts and .tsx files

# Test: Check for other usages of useAccount in the codebase
echo "Checking useAccount usage in .ts and .tsx files:"
rg 'useAccount\(' --type-add 'ts:*.ts' --type-add 'tsx:*.tsx' -t ts -t tsx -C 3

Length of output: 3243

packages/loot-core/src/types/models/schedule.d.ts (1)

35-35: 🛠️ Refactor suggestion

Improved type definition for _amount property

The change from unknown to number | { num1: number; num2: number } for the _amount property provides better type safety and more structure. This improvement aligns with the PR objective of fixing the payment direction issue.

However, consider the following points:

  1. This change might break existing code that relies on _amount being unknown. Ensure all usages of this property are updated accordingly.
  2. The DiscoverScheduleEntity type also uses ScheduleEntity['_amount'], so this change affects it as well. Verify if any adjustments are needed there.
  3. The object structure { num1: number; num2: number } is not self-explanatory. Consider using more descriptive property names or adding a comment to explain the purpose of this structure.

Consider renaming the object properties to be more descriptive:

_amount: number | { amount: number; direction: number };

This would make the intent clearer and improve code readability.

To ensure this change doesn't introduce any issues, please run the following script to check for any other occurrences of _amount in the codebase:

This will help identify any places where the code might need to be updated to accommodate the new type definition.

✅ Verification successful

Verification of _amount Type Change

The update of the _amount property to number | { num1: number; num2: number } has been successfully verified across the codebase. All references to _amount are consistent with the new type definition, and no conflicting usages were identified.

However, please ensure that functions handling _amount, such as getScheduledAmount, are correctly managing both number and the object structure to maintain runtime integrity.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of _amount in TypeScript and JavaScript files
rg --type-add 'web:*.{ts,tsx,js,jsx}' -t web '_amount' -C 3

Length of output: 10946

packages/desktop-client/src/components/mobile/transactions/Transaction.jsx (5)

29-29: LGTM: New import for improved payee handling.

The addition of the usePrettyPayee import aligns with the goal of improving how payee information is processed and displayed. This change contributes to a more modular and potentially more efficient approach to handling payee descriptions.


80-80: LGTM: Improved variable naming.

Renaming transferAcct to transferAccount enhances code readability and consistency. This change, while not affecting functionality, contributes to better code maintainability.


102-102: LGTM: Updated amount calculation for scheduled transactions.

The modification to include the _inverse parameter in the getScheduledAmount function call directly addresses the issue of incorrect payment directions for scheduled transactions. This change aligns well with the PR objective.

To ensure the correctness of this change, consider adding a test case that verifies the amount calculation for both regular and inverted scheduled transactions.


Line range hint 1-258: Address the concern about useLayoutEffect usage.

While the changes in this file look good and address the PR objectives effectively, there's a concern raised in the PR comments about the use of useLayoutEffect. This hook is not visible in the provided code snippet, but it's important to address this concern.

To investigate this issue, please run the following script:

#!/bin/bash
# Description: Check for useLayoutEffect usage in the codebase

# Test: Search for useLayoutEffect in React components
rg --type js 'useLayoutEffect'

If useLayoutEffect is indeed used, consider replacing it with useEffect unless there's a specific need for synchronous updates after DOM mutations. This change could potentially improve performance by avoiding an extra render cycle.


75-75: Verify the usage of the new _inverse property.

The addition of the _inverse property in the transaction object destructuring is a good step towards addressing the issue of incorrect payment directions. This change aligns with the PR objective.

To ensure this change is properly implemented, please run the following script to check its usage:

✅ Verification successful

Usage of _inverse Verified Successfully

The _inverse property is appropriately utilized in both TransactionsTable.jsx and Transaction.jsx when calculating the scheduled amount. This ensures that transaction directions are handled correctly as intended by the PR.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of _inverse property in the codebase

# Test: Search for _inverse usage in relation to transaction or scheduled amount calculations
rg --type js -e '_inverse.*getScheduledAmount' -e 'getScheduledAmount.*_inverse'

Length of output: 1076

packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx (1)

208-210: LGTM. Verify full resolution and consider performance optimization.

This change addresses the main issue by providing the specific accountId to usePreviewTransactions, which should help in correctly determining the payment direction for scheduled transfers.

Please verify if this change fully resolves the payment direction issue for scheduled transfers. You can use the test budget file mentioned in the linked issue #3230 to confirm.

Consider investigating the useLayoutEffect concern mentioned in the PR comments. If useLayoutEffect is being used in the usePreviewTransactions hook or related components, evaluate if it can be replaced with useEffect to potentially improve performance.

✅ Verification successful

Verification successful. No remaining issues related to payment direction were found in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining issues related to payment direction in the codebase

# Test: Search for TODO comments or FIXME related to payment direction
rg --type typescript "TODO|FIXME" -C 3 | rg -i "payment.*(direction|scheduled)"

# Test: Search for any functions or variables related to payment direction calculation
rg --type typescript "(calculate|determine|get).*payment.*direction" -C 3

Length of output: 227


Script:

#!/bin/bash
# Description: Check for any remaining issues related to payment direction in the codebase

# Test: Search for TODO comments or FIXME related to payment direction in .ts and .tsx files
rg --files -g '*.ts' -g '*.tsx' | xargs rg "TODO|FIXME" -C 3 | rg -i "payment.*(direction|scheduled)"

# Test: Search for any functions or variables related to payment direction calculation in .ts and .tsx files
rg --files -g '*.ts' -g '*.tsx' | xargs rg "(calculate|determine|get).*payment.*direction" -C 3

Length of output: 201

packages/desktop-client/src/components/transactions/TransactionsTable.jsx (1)

Line range hint 807-811: Approved: Improved clarity in transfer icon rendering logic.

The use of the isDeposit constant in the conditional rendering of transfer icons enhances code readability and maintains consistency with the changes made to handle payment directions correctly. This modification aligns well with the overall objectives of the PR.

packages/desktop-client/src/hooks/usePreviewTransactions.ts (1)

67-67: Verify Logic for Determining Transaction Direction

The _inverse property is calculated as:

_inverse: accountId ? accountId !== t.account : false,

Please verify that this logic correctly reflects the intended behavior. If accountId is provided, _inverse will be true when t.account is not equal to accountId, and false otherwise. If accountId is not provided, _inverse will be false.

packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (7)

64-64: LGTM: Imported usePrettyPayee hook

The usePrettyPayee hook is correctly imported and will help centralize the logic for obtaining a "pretty" payee description.


280-281: LGTM: Added getPayee and getTransferAccount props to ChildTransactionEdit

Passing getPayee and getTransferAccount as props to ChildTransactionEdit ensures that the component has access to the necessary data to compute the pretty payee information.


320-320: LGTM: Displaying prettyPayee in TapField

The TapField component correctly displays the prettyPayee value, enhancing the readability of the transaction's payee information.


486-489: LGTM: Renamed getTransferAcct to getTransferAccount

Renaming the function to getTransferAccount improves code readability and consistency, making the purpose of the function clearer.


689-693: LGTM: Using usePrettyPayee to compute title

The usePrettyPayee hook is appropriately used to compute the title variable, centralizing the logic for generating the payee description.


764-764: LGTM: Displaying title in TapField

Displaying the computed title in the TapField ensures that users see the correct and formatted payee information.


812-813: LGTM: Passing getPayee and getTransferAccount to ChildTransactionEdit

By passing down getPayee and getTransferAccount, the child component can accurately retrieve and display payee-related information.

packages/desktop-client/src/components/accounts/Account.tsx (2)

191-194: Confirm that _inverse is always defined on scheduledTransaction

When calling getScheduledAmount, the _inverse property of scheduledTransaction is used. Ensure that this property is always defined to prevent potential runtime errors due to undefined values.

Run the following script to check for any scheduledTransaction objects without the _inverse property:

#!/bin/bash
# Description: Find instances where `_inverse` might be undefined in scheduled transactions.

# Test: Search for `scheduledTransaction` assignments without `_inverse`.
# Expected: No results mean all scheduled transactions have `_inverse` defined.

rg --type ts --json 'scheduledTransaction' \
  | jq -r '.data.lines.text' \
  | rg --invert-match '_inverse'

159-168: Verify the necessity of useLayoutEffect to prevent UI flashes

The use of useLayoutEffect in this context may be causing unnecessary blocking of rendering. Ensure that it is required to prevent UI flashes when updating the splitsExpanded state. If possible, test whether switching to useEffect maintains the desired behavior without introducing UI glitches.

Run the following script to identify any potential side effects of using useLayoutEffect:

packages/loot-core/src/shared/schedules.ts Outdated Show resolved Hide resolved
packages/loot-core/src/shared/schedules.ts Outdated Show resolved Hide resolved
@jfdoming jfdoming assigned joel-jeremy and jfdoming and unassigned joel-jeremy and jfdoming Sep 29, 2024
@jfdoming jfdoming removed their request for review October 2, 2024 01:56
@MatissJanis MatissJanis removed this from the v24.10.0 milestone Oct 2, 2024
Copy link
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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b02dda4 and 0f33ef8.

📒 Files selected for processing (2)
  • packages/desktop-client/src/components/accounts/Account.tsx (4 hunks)
  • packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx (1 hunks)
🧰 Additional context used
📓 Learnings (2)
packages/desktop-client/src/components/accounts/Account.tsx (2)
Learnt from: jfdoming
PR: actualbudget/actual#3402
File: packages/desktop-client/src/components/accounts/Account.tsx:8-8
Timestamp: 2024-09-27T14:15:46.637Z
Learning: In the `AllTransactions` component of `Account.tsx`, the `useLayoutEffect` hook is appropriately used to dispatch an action that closes splits for parent transactions when `prependTransactions` changes, ensuring this occurs synchronously before the component is painted.
Learnt from: jfdoming
PR: actualbudget/actual#3402
File: packages/desktop-client/src/components/accounts/Account.tsx:8-8
Timestamp: 2024-10-08T15:46:15.739Z
Learning: In the `AllTransactions` component of `Account.tsx`, the `useLayoutEffect` hook is appropriately used to dispatch an action that closes splits for parent transactions when `prependTransactions` changes, ensuring this occurs synchronously before the component is painted.
packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx (2)
Learnt from: jfdoming
PR: actualbudget/actual#3402
File: packages/desktop-client/src/components/accounts/Account.tsx:8-8
Timestamp: 2024-09-27T14:15:46.637Z
Learning: In the `AllTransactions` component of `Account.tsx`, the `useLayoutEffect` hook is appropriately used to dispatch an action that closes splits for parent transactions when `prependTransactions` changes, ensuring this occurs synchronously before the component is painted.
Learnt from: jfdoming
PR: actualbudget/actual#3402
File: packages/desktop-client/src/components/accounts/Account.tsx:8-8
Timestamp: 2024-10-08T15:46:15.739Z
Learning: In the `AllTransactions` component of `Account.tsx`, the `useLayoutEffect` hook is appropriately used to dispatch an action that closes splits for parent transactions when `prependTransactions` changes, ensuring this occurs synchronously before the component is painted.
🔇 Additional comments (2)
packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx (2)

208-210: LGTM! This change addresses the core issue.

The modification to usePreviewTransactions by passing the accountId is a targeted fix that should resolve the issue of incorrect payment directions for scheduled transactions. This change allows the hook to fetch account-specific preview transactions, ensuring that the displayed information accurately reflects the intended payment direction.

This implementation aligns well with the PR objective and should improve the accuracy of transaction previews in the PWA.


208-210: Verify the fix across different account types

The change looks good and is well-implemented. It's a focused fix that should resolve the issue without introducing unnecessary complexity or performance overhead.

To ensure the fix works as intended across different scenarios:

Please run the following script to check if the usePreviewTransactions hook is consistently used with the accountId parameter across different account types:

This will help verify that the fix is applied consistently throughout the codebase, reducing the chance of similar issues in other components.

✅ Verification successful

Change Verified: usePreviewTransactions is consistently used with accountId across all relevant components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of usePreviewTransactions with accountId

# Test: Search for usePreviewTransactions usage
rg --type typescript 'usePreviewTransactions\(' packages/

Length of output: 94


Script:

#!/bin/bash
# Description: Check for consistent usage of usePreviewTransactions with accountId

# Test: Search for usePreviewTransactions usage in TypeScript files
rg 'usePreviewTransactions\(' --glob '*.ts' --glob '*.tsx' packages/

Length of output: 408

@youngcw youngcw added this to the v24.11.0 milestone Oct 15, 2024
@joel-jeremy
Copy link
Contributor Author

/update-vrt

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

🧹 Outside diff range and nitpick comments (2)
packages/desktop-client/src/components/mobile/utils.ts (1)

22-24: Remove redundant optional chaining.

The optional chaining (transaction?.amount) is unnecessary since we've already checked for the existence of transaction in line 18.

-    return `Transfer ${transaction?.amount > 0 ? 'from' : 'to'} ${transferAccount.name}`;
+    return `Transfer ${transaction.amount > 0 ? 'from' : 'to'} ${transferAccount.name}`;
packages/desktop-client/src/components/mobile/transactions/TransactionListItem.tsx (1)

Line range hint 165-178: Consider adding aria-label for schedule icon.

The schedule icon rendering logic looks good, but consider adding an aria-label to improve accessibility for screen readers.

 {scheduleId && (
   <SvgArrowsSynchronize
     style={{
       width: 12,
       height: 12,
       marginRight: 5,
       color: textStyle.color || theme.menuItemText,
     }}
+    aria-label="Scheduled transaction"
   />
 )}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ccfc118 and 14a5fd5.

📒 Files selected for processing (3)
  • packages/desktop-client/src/components/mobile/transactions/TransactionListItem.tsx (5 hunks)
  • packages/desktop-client/src/components/mobile/utils.ts (1 hunks)
  • packages/desktop-client/src/components/transactions/TransactionsTable.jsx (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/desktop-client/src/components/transactions/TransactionsTable.jsx
🔇 Additional comments (7)
packages/desktop-client/src/components/mobile/utils.ts (3)

1-11: LGTM! Well-structured type definitions and imports.

The type definitions are clear, properly typed, and follow TypeScript best practices.


18-20: Consider handling the case where only transaction exists.

The function returns an empty string when no payee or transfer account is provided, even if a transaction exists. Consider if this is the intended behavior or if we should provide a more meaningful fallback.

Also applies to: 29-31


13-31: Verify transfer direction logic across the codebase.

The transfer direction logic is crucial for fixing the reported issue with scheduled transfer payment direction. Let's verify that this implementation is consistent with other parts of the codebase.

Additionally, consider adding test cases to verify the behavior:

describe('getPrettyPayee', () => {
  it('should format transfer with correct direction for positive amount', () => {
    const result = getPrettyPayee({
      transaction: { amount: 100 },
      transferAccount: { name: 'Savings' }
    });
    expect(result).toBe('Transfer from Savings');
  });
  
  it('should format transfer with correct direction for negative amount', () => {
    const result = getPrettyPayee({
      transaction: { amount: -100 },
      transferAccount: { name: 'Savings' }
    });
    expect(result).toBe('Transfer to Savings');
  });
});

Would you like me to create a GitHub issue to track the addition of these test cases?

✅ Verification successful

Based on the search results, I can now provide a final response:

Transfer direction logic is correctly implemented and consistent

The transfer direction logic in getPrettyPayee follows the standard convention where:

  • Positive amount (amount > 0) indicates money coming "from" the transfer account
  • Negative amount (amount < 0) indicates money going "to" the transfer account

This is consistent with the general accounting principle where:

  • Positive amounts represent inflows/credits
  • Negative amounts represent outflows/debits

The suggested test cases would be valuable additions but are not fixing any inconsistency in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other instances of transfer direction logic
rg -A 3 "transfer.*from|to.*transfer" --type ts --type tsx

# Search for similar amount sign checks for transfer direction
ast-grep --pattern 'amount > 0 ? $from : $to'

Length of output: 136


Script:

#!/bin/bash
# Search for transfer direction logic with correct file types
rg -A 3 "transfer.*from|to.*transfer" -t typescript -t javascriptreact -t typescriptreact

# Search for amount-based direction checks with a more specific pattern
ast-grep --pattern 'amount > 0 ? "from" : "to"'

# Search for other transfer-related logic
rg -A 3 "Transfer (from|to)" -t typescript -t javascriptreact -t typescriptreact

# Look for similar transaction amount checks
rg -A 3 "transaction.*amount.*[<>].*0" -t typescript -t javascriptreact -t typescriptreact

Length of output: 422


Script:

#!/bin/bash
# Search for transfer direction logic using just ts extension
rg -A 3 "transfer.*from|to.*transfer" "*.ts"

# Search for Transfer from/to strings
rg -A 3 "Transfer (from|to)" "*.ts"

# Look for transaction amount comparisons
rg -A 3 "transaction.*amount.*[<>].*0" "*.ts"

# Find other instances of amount-based conditionals
rg -A 3 "amount.*[<>].*0.*\?" "*.ts"

Length of output: 351


Script:

#!/bin/bash
# First, find TypeScript files
fd -e ts -e tsx

# Then use these files to search for transfer-related logic
fd -e ts -e tsx -x rg -A 3 "Transfer (from|to)" {}

# Search for amount comparisons in these files
fd -e ts -e tsx -x rg -A 3 "amount.*[<>].*0" {}

# Look for transaction amount checks
fd -e ts -e tsx -x rg -A 3 "transaction.*amount" {}

Length of output: 74873

packages/desktop-client/src/components/mobile/transactions/TransactionListItem.tsx (4)

34-34: LGTM! Import change improves clarity.

The new getPrettyPayee import better reflects its purpose compared to the previous getDescriptionPretty.


59-59: LGTM! Variable names are more descriptive.

The renamed variables improve code readability:

  • transferAccount is clearer than transferAcct
  • scheduleId better indicates it's an identifier

Also applies to: 93-93


98-102: LGTM! Improved transaction display logic.

The changes improve the handling of payee names:

  • Uses the new getPrettyPayee utility for consistent display
  • Properly handles empty payee cases with "(No payee)" fallback
  • Correctly considers transfer account context

Also applies to: 179-185


87-87: Verify fix for scheduled transfer payment direction.

The changes look good, but let's verify the fix works for all scenarios mentioned in issue #3230.

Also applies to: 98-102

✅ Verification successful

Let me gather more specific information about the transfer-related changes and tests.


Let me search for more specific information about the transfer direction fix.


Based on the gathered information, I can now provide the final response:

Transfer direction fix has been properly implemented

The code correctly handles transfer direction through:

  • Proper transfer account lookup via payee?.transfer_acct
  • Consistent amount sign handling: transaction?.amount > 0 ? 'from' : 'to'
  • Appropriate display logic in TransactionListItem component

The changes align with the fix for scheduled transfer payment direction, as evidenced by:

  • Transfer direction is determined by the transaction amount sign
  • Transfer account context is properly maintained through payee relationships
  • Consistent handling across both regular and scheduled transactions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for related test cases and usage patterns

# Check for test coverage of transfer scenarios
rg -l "test.*transfer.*direction|test.*scheduled.*transfer" --type ts

# Look for similar transfer handling patterns
ast-grep --pattern 'useAccount($transferAcct)' --lang ts

# Check for potential edge cases in transfer handling
rg "transfer_acct.*amount" --type ts

Length of output: 454


Script:

#!/bin/bash
# Search for transfer-related code and tests more broadly
# Look for transfer amount handling in components
rg -A 5 "transfer.*amount|amount.*transfer" --type ts packages/desktop-client/src/

# Check for scheduled transaction tests
rg -A 5 "scheduled.*transaction|recurring.*transaction" --type ts packages/

# Look for transfer account handling patterns
ast-grep --pattern 'transfer: {
  $$$
  amount: $_,
  $$$
}'

# Find transfer direction logic
rg -A 5 "direction.*transfer|transfer.*direction" --type ts

Length of output: 8864


Script:

#!/bin/bash
# Look for transfer-related logic in the component and its dependencies
rg -A 10 "TransactionListItem" --type ts packages/desktop-client/src/

# Search for transfer amount sign handling
rg -A 5 "amount.*[<>].*0.*transfer|transfer.*amount.*[<>].*0" --type ts

# Find transfer account handling in the codebase
ast-grep --pattern 'const $_ = transaction?.amount $_ 0 ? $_ : $_'

# Look for payee-related transfer logic
rg -A 5 "payee.*transfer|transfer.*payee" --type ts packages/desktop-client/

Length of output: 14664

matt-fidd
matt-fidd previously approved these changes Nov 19, 2024
@joel-jeremy
Copy link
Contributor Author

The update-vrt seem to made the pipeline actions stuck

@youngcw
Copy link
Member

youngcw commented Nov 19, 2024

maybe try a dummy commit

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

🧹 Outside diff range and nitpick comments (2)
packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (1)

501-514: Consider memoizing transfer account lookups

While the renaming improves consistency, the function performs object lookups on every call. Consider memoizing the results to optimize performance, especially for lists with many transactions.

 const getTransferAccount = useCallback(
+  memoize(
     trans => {
       const payee = trans && getPayee(trans);
       return payee?.transfer_acct && accountsById?.[payee.transfer_acct];
     },
+  ),
    [accountsById, getPayee],
  );
packages/desktop-client/src/components/accounts/Account.tsx (1)

225-228: Simplify conditional check.

The current condition can be simplified while maintaining the same logic.

Consider this more concise version:

-  if (!previewTransactions?.length || filtered) {
+  if (filtered || !previewTransactions?.length) {
     return children(transactions, balances);
   }
   return children(allTransactions, allBalances);

This puts the more frequent condition first and makes the code slightly more readable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 14a5fd5 and 1e01626.

⛔ Files ignored due to path filters (4)
  • packages/desktop-client/e2e/accounts.mobile.test.js-snapshots/Mobile-Accounts-opens-individual-account-page-and-checks-that-filtering-is-working-1-chromium-linux.png is excluded by !**/*.png
  • packages/desktop-client/e2e/accounts.mobile.test.js-snapshots/Mobile-Accounts-opens-individual-account-page-and-checks-that-filtering-is-working-2-chromium-linux.png is excluded by !**/*.png
  • packages/desktop-client/e2e/accounts.mobile.test.js-snapshots/Mobile-Accounts-opens-individual-account-page-and-checks-that-filtering-is-working-3-chromium-linux.png is excluded by !**/*.png
  • upcoming-release-notes/3402.md is excluded by !**/*.md
📒 Files selected for processing (13)
  • packages/desktop-client/src/components/accounts/Account.tsx (5 hunks)
  • packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx (2 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (8 hunks)
  • packages/desktop-client/src/components/mobile/transactions/TransactionListItem.tsx (5 hunks)
  • packages/desktop-client/src/components/mobile/utils.ts (1 hunks)
  • packages/desktop-client/src/components/transactions/TransactionsTable.jsx (8 hunks)
  • packages/desktop-client/src/hooks/useAccountPreviewTransactions.ts (1 hunks)
  • packages/desktop-client/src/hooks/usePreviewTransactions.ts (0 hunks)
  • packages/loot-core/src/client/data-hooks/schedules.tsx (1 hunks)
  • packages/loot-core/src/client/data-hooks/transactions.ts (4 hunks)
  • packages/loot-core/src/client/query-hooks.ts (1 hunks)
  • packages/loot-core/src/shared/schedules.ts (1 hunks)
  • packages/loot-core/src/types/models/schedule.d.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/desktop-client/src/hooks/usePreviewTransactions.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/desktop-client/src/components/mobile/accounts/AccountTransactions.tsx
  • packages/desktop-client/src/components/mobile/transactions/TransactionListItem.tsx
  • packages/desktop-client/src/components/mobile/utils.ts
  • packages/desktop-client/src/components/transactions/TransactionsTable.jsx
  • packages/desktop-client/src/hooks/useAccountPreviewTransactions.ts
  • packages/loot-core/src/client/data-hooks/schedules.tsx
  • packages/loot-core/src/client/data-hooks/transactions.ts
  • packages/loot-core/src/client/query-hooks.ts
  • packages/loot-core/src/shared/schedules.ts
  • packages/loot-core/src/types/models/schedule.d.ts
🧰 Additional context used
📓 Learnings (1)
packages/desktop-client/src/components/accounts/Account.tsx (2)
Learnt from: jfdoming
PR: actualbudget/actual#3402
File: packages/desktop-client/src/components/accounts/Account.tsx:8-8
Timestamp: 2024-11-10T16:45:25.627Z
Learning: In the `AllTransactions` component of `Account.tsx`, the `useLayoutEffect` hook is appropriately used to dispatch an action that closes splits for parent transactions when `prependTransactions` changes, ensuring this occurs synchronously before the component is painted.
Learnt from: joel-jeremy
PR: actualbudget/actual#3685
File: packages/desktop-client/src/components/accounts/Account.tsx:655-665
Timestamp: 2024-11-10T16:45:31.225Z
Learning: The Account component in 'packages/desktop-client/src/components/accounts/Account.tsx' is being rewritten in a separate PR.
🪛 Biome
packages/desktop-client/src/components/accounts/Account.tsx

[error] 202-202: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

🔇 Additional comments (5)
packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx (4)

67-67: LGTM: Import of centralized payee display utility

The addition of getPrettyPayee import aligns with the PR's objective to fix transfer payment direction issues by centralizing the payee display logic.


Line range hint 283-299: LGTM: Consistent payee display in child transactions

The implementation correctly uses getPrettyPayee with all necessary context (transaction, payee, and transferAccount) to ensure consistent display of transfer directions in child transactions.


745-749: LGTM: Consistent transfer direction in transaction titles

The implementation correctly uses the centralized getPrettyPayee utility to ensure consistent display of transfer directions in transaction titles.


868-869: LGTM: Complete context for child transactions

Correctly passes necessary functions to child transactions to ensure consistent transfer direction display throughout the component hierarchy.

packages/desktop-client/src/components/accounts/Account.tsx (1)

161-176: LGTM! Clean implementation of preview transactions handling.

The useEffect hook is well-implemented with proper dependency management and loading state check. This change aligns with the PR's objective of fixing transaction display issues.

Comment on lines +196 to +207
const previewBalances = [...previewTransactions]
.reverse()
.map(scheduledTransaction => {
const amount =
(scheduledTransaction._inverse ? -1 : 1) *
getScheduledAmount(scheduledTransaction.amount);
.map(previewTransaction => {
return {
// TODO: fix me
// eslint-disable-next-line react-hooks/exhaustive-deps
balance: (runningBalance += amount),
id: scheduledTransaction.id,
balance: (runningBalance += previewTransaction.amount),
id: previewTransaction.id,
};
});
return groupById(scheduledBalances);
}, [showBalances, prependTransactions, runningBalance]);
return groupById(previewBalances);
}, [showBalances, previewTransactions, runningBalance]);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve balance calculation readability.

The current implementation uses assignment within an expression which makes the code harder to understand and maintain. This pattern can lead to subtle bugs as expressions are typically expected to be side-effect free.

Consider refactoring to make the logic more explicit:

-    const previewBalances = [...previewTransactions]
-      .reverse()
-      .map(previewTransaction => {
-        return {
-          // TODO: fix me
-          // eslint-disable-next-line react-hooks/exhaustive-deps
-          balance: (runningBalance += previewTransaction.amount),
-          id: previewTransaction.id,
-        };
-      });
+    const previewBalances = [...previewTransactions]
+      .reverse()
+      .map(previewTransaction => {
+        runningBalance += previewTransaction.amount;
+        return {
+          balance: runningBalance,
+          id: previewTransaction.id,
+        };
+      });
📝 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
const previewBalances = [...previewTransactions]
.reverse()
.map(scheduledTransaction => {
const amount =
(scheduledTransaction._inverse ? -1 : 1) *
getScheduledAmount(scheduledTransaction.amount);
.map(previewTransaction => {
return {
// TODO: fix me
// eslint-disable-next-line react-hooks/exhaustive-deps
balance: (runningBalance += amount),
id: scheduledTransaction.id,
balance: (runningBalance += previewTransaction.amount),
id: previewTransaction.id,
};
});
return groupById(scheduledBalances);
}, [showBalances, prependTransactions, runningBalance]);
return groupById(previewBalances);
}, [showBalances, previewTransactions, runningBalance]);
const previewBalances = [...previewTransactions]
.reverse()
.map(previewTransaction => {
runningBalance += previewTransaction.amount;
return {
balance: runningBalance,
id: previewTransaction.id,
};
});
return groupById(previewBalances);
}, [showBalances, previewTransactions, runningBalance]);
🧰 Tools
🪛 Biome

[error] 202-202: The assignment should not be in an expression.

The use of assignments in expressions is confusing.
Expressions are often considered as side-effect free.

(lint/suspicious/noAssignInExpressions)

@joel-jeremy
Copy link
Contributor Author

It's good now :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants