Workspace rate list display for auto-generated rates#96149
Conversation
|
Hey, I noticed you changed If you want to automatically generate translations for other locales, an Expensify employee will have to:
Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running: npx ts-node ./scripts/generateTranslations.ts --helpTypically, you'd want to translate only what you changed by running |
|
@cretadn22 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
@neil-marcellini Could you please help trigger the translation workflow? Thanks |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5295e3c468
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return false; | ||
| } | ||
|
|
||
| return rate.rate === governmentRate.rate && (rate.startDate ?? undefined) === governmentRate.startDate && (rate.endDate ?? undefined) === governmentRate.endDate; |
There was a problem hiding this comment.
Compare restored rates with numeric tolerance
For government rates whose displayed value does not round-trip exactly through the edit form, this exact equality keeps the auto-generated icon hidden even after the user restores the original value. The existing submit path stores Number(values.rate) * 100, so restoring a snapshot rate like 29 cents from 0.29 produces 28.999999999999996 in optimistic Onyx state; while offline (and potentially until the server normalizes it) isGovernmentRateUnmodified returns false even though the UI value matches the snapshot.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
@thelullabyy Good catch here. We should probably handle potential floating-point rounding differences when comparing rates
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari |
| */ | ||
| function isGovernmentRateUnmodified(rate: Rate): boolean { | ||
| const governmentRate = rate.attributes?.governmentRate; | ||
| if (!governmentRate) { |
There was a problem hiding this comment.
A smaller edge worth a thought while touching that line: if a malformed governmentRate snapshot exists but has no rate field and the rate's own fields are also unset, undefined === undefined on all three comparisons returns true and shows the icon. Guarding with governmentRate.rate === undefined → false would make the helper robust, but I wouldn't block on it.
| return false; | ||
| } | ||
|
|
||
| return rate.rate === governmentRate.rate && (rate.startDate ?? undefined) === governmentRate.startDate && (rate.endDate ?? undefined) === governmentRate.endDate; |
There was a problem hiding this comment.
@thelullabyy Good catch here. We should probably handle potential floating-point rounding differences when comparing rates
|
@thelullabyy Mind taking a look at the failing typescript checks and Jest Unit Tests? Also, please upload the complete test videos when you get a chance |
|
The test failed due to missing copies. I requested it here #96149 (comment) |
joekaufmanexpensify
left a comment
There was a problem hiding this comment.
Good for product.
Explanation of Change
Fixed Issues
$ #95280
PROPOSAL: NA
Tests
Setup:
Seed a mock government rate:
With the Distance rates page open, turn off internet, run this in the browser console:
Verify that:
In the rates table, the seeded rate shows a small lightning-bolt icon next to the amount in the Rate column.
Hover the icon: tooltip reads "This rate is auto-generated."
Other rates show no icon.
Shrink the browser window to mobile width (or test on the mobile web layout).
The bolt icon appears next to the "rate • date" line under the rate name, with the same tooltip behavior on hover.
Open the seeded rate > Rate, change the amount (e.g. 0.725 → 0.99), save.
Back in the list, the bolt icon is gone.
Change the amount back to exactly 0.725 and save.
The bolt icon reappears.
Edit the Start date (e.g. to 2026-02-01) → icon hides. Restore to 2026-01-01 → icon returns.
Edit the End date (e.g. to 2026-11-30) → icon hides. Restore to 2026-12-31 → icon returns.
Re-run the seed snippet but with endDate: null on the rate and no endDate key inside governmentRate → icon shows (omitted on both sides counts as a match).
Then set an end date on the rate via the UI → icon hides (omitted on only one side is not a match).
Rename the rate → icon stays (name isn't part of the snapshot).
Toggle the rate off/on via the switch → icon stays; only the status badge changes.
Sorting by any column and searching via Find rate work as before, with the icon following its row.
Open a workspace whose rates were never seeded: the list renders exactly as before, no icons, no layout shift in the Rate column.
Offline tests
QA Steps
Same as Tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Screen.Recording.2026-07-14.at.19.07.55.mov