[Home Page] Add Review X expenses action to For you to surface expenses against company expense policy#91983
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 |
|
@ZhenjaHorbach 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] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0700258610
ℹ️ 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".
|
🚧 @JmillsExpensify has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
Thanks! @adamgrzybowski let me know when we're ready for another round of adhoc testing. |
|
@JmillsExpensify Could you please run the parrot and take a second look at the PR? |
|
@adamgrzybowski |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppIMG_2430.MP4Android: mWeb Chrome2026-06-09.17.04.18.moviOS: HybridAppIMG_2430.MP4iOS: mWeb Safari2026-06-09.17.04.18.movMacOS: Chrome / Safari2026-06-09.17.02.19.mov |
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index 9a5d4384381..5f16a3ad188 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1005,6 +1005,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Alles erledigt',
f1FlagsDescription: 'Sie haben alle offenen Aufgaben abgeschlossen.',
},
+ reviewExpenses: ({count}: {count: number}) => `Überprüfen Sie ${count} ${count === 1 ? 'Ausgabe' : 'Spesen'}`,
},
upcomingTravel: 'Bevorstehende Reisen',
upcomingTravelSection: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 9ed06f7e346..471f0899f1a 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -985,6 +985,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Todo al día',
f1FlagsDescription: 'Has completado todas las tareas pendientes.',
},
+ reviewExpenses: ({count}: {count: number}) => `Revisa ${count} ${count === 1 ? 'gasto' : 'gastos'}`,
},
gettingStartedSection: {
title: 'Primeros pasos',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index b6b2a780154..a4d1fd03f3c 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1008,6 +1008,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Tout est à jour',
f1FlagsDescription: 'Vous avez terminé toutes les tâches en cours.',
},
+ reviewExpenses: ({count}: {count: number}) => `Examiner ${count} ${count === 1 ? 'dépense' : 'dépenses'}`,
},
upcomingTravel: 'Voyages à venir',
upcomingTravelSection: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 705ae2ec94d..d18c7039ba5 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1006,6 +1006,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Tutto a posto',
f1FlagsDescription: 'Hai completato tutte le attività in sospeso.',
},
+ reviewExpenses: ({count}: {count: number}) => `Esamina ${count} ${count === 1 ? 'spesa' : 'spese'}`,
},
upcomingTravel: 'Prossimi viaggi',
upcomingTravelSection: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 22dff193299..230674aef9a 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -989,6 +989,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'すべて確認済みです',
f1FlagsDescription: 'すべての未処理の To-do が完了しました。',
},
+ reviewExpenses: ({count}: {count: number}) => `${count} 件の${count === 1 ? '経費' : '経費'}を確認`,
},
upcomingTravel: '今後の出張',
upcomingTravelSection: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index b6f95c44ed3..477ce90bbae 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1004,6 +1004,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Helemaal bij',
f1FlagsDescription: "Je hebt alle openstaande to-do's afgerond.",
},
+ reviewExpenses: ({count}: {count: number}) => `Beoordeel ${count} ${count === 1 ? 'uitgave' : 'uitgaven'}`,
},
upcomingTravel: 'Aankomende reizen',
upcomingTravelSection: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 1fe87f4ec8c..75b68ef8090 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1006,6 +1006,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Wszystko nadrobione',
f1FlagsDescription: 'Ukończyłeś wszystkie zaległe zadania.',
},
+ reviewExpenses: ({count}: {count: number}) => `Przejrzyj ${count} ${count === 1 ? 'wydatek' : 'wydatki'}`,
},
upcomingTravel: 'Nadchodząca podróż',
upcomingTravelSection: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 394be17dc88..5fb2e3a69df 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1004,6 +1004,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: 'Tudo em dia',
f1FlagsDescription: 'Você concluiu todas as tarefas pendentes.',
},
+ reviewExpenses: ({count}: {count: number}) => `Revisar ${count} ${count === 1 ? 'despesa' : 'despesas'}`,
},
upcomingTravel: 'Próximas viagens',
upcomingTravelSection: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 8013eff5912..afe96f3cd94 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -972,6 +972,7 @@ const translations: TranslationDeepObject<typeof en> = {
f1FlagsTitle: '全部完成',
f1FlagsDescription: '你已完成所有未完成的待办事项。',
},
+ reviewExpenses: ({count}: {count: number}) => `审核 ${count} ${count === 1 ? '费用' : '费用'}`,
},
upcomingTravel: '即将出行',
upcomingTravelSection: {
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
|
@ZhenjaHorbach PR is ready for next steps |
|
In that case, it's probably ready to merge. The eslint problems aren't related to this PR |
Hmmm |
And it would be nice to fix this also |
|
And actually this bug is more critical on native apps IMG_2430.MP4 |
|
And I hope only I don't have an icon for the Review X expenses field for native apps? 😅
|
Yeah, this seems to be much worse on mobile. I will reach you on Slack so we can figure out the repro. cc: @ZhenjaHorbach |
|
Agreed, it's a fair point on native. Let's address that. |
|
We coming back to this one soon? |
|
@JmillsExpensify We bumped into some weird reproduction issues with @ZhenjaHorbach, but it was probably local setup / cache / something else broken. Now we both can't reproduce the issues, so we should be good to go |
|
@JmillsExpensify Okay, so It's not obvious. @ZhenjaHorbach just reproduced it again, but it's really not deterministic. I will continue investigating it |
|
I think we can merge and see if QA team can reproduce it |
|
I like that idea. |
JmillsExpensify
left a comment
There was a problem hiding this comment.
Going to go ahead and approve
| const currentUserEmail = session?.email ?? ''; | ||
| const flaggedExpenses: FlaggedExpenseEntry[] = []; | ||
|
|
||
| for (const transactionKey of Object.keys(allTransactions)) { |
There was a problem hiding this comment.
Nope, should I sort it? If yes, what should I compare?
There was a problem hiding this comment.
Either transaction date or created by date. But I think we can leave as is for now. I'm going to merge
|
🚧 @grgia has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/grgia in version: 9.4.7-0 🚀
Bundle Size Analysis (Sentry): |
|
🤖 Reviewed this PR for help site impact. Changes are required. This PR adds a new Review X expenses item to Home's For you section, which surfaces policy-flagged expenses on a submitter's draft reports. The existing Understanding the For you Section article lists the items that can appear (Submit, Approve, Pay, Export, Fix) but does not mention Review. I created a draft help site PR documenting the new item: #93480 It adds Review to the list of items, lists it under the Submitter role, and notes where the item routes (the first flagged expense). @adamgrzybowski, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
Deploy Blocker ##93499 was identified to be related to this PR |


Explanation of Change
Review X expensesrow to Home'sFor youslot, above Submit/Approve/Pay/Export, that surfaces policy-flagged expenses on the user's Draft expense reports aggregated across workspaces.flaggedExpensesOnyx derived value +flaggedExpensesReviewSelector;Beginnavigates to the first flagged expense's parent report (RHP on wide, full route on narrow) withbackTo: ROUTES.HOME.Fixed Issues
$ #91704
PROPOSAL:
Tests
Offline tests
QA Steps
For youshowsReview 2 expensesabove Submit/Approve/Pay/Export with the exclamation icon andBeginbutton.Beginand verify it opens the first flagged expense's parent report (RHP on wide, full screen on narrow) withbackTo=/home.Review 1 expenseimmediately; resolve the last one and verify the row disappears.Reviewrow is not rendered.PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA steps**** sectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, 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.ScrollViewcomponent to make it scrollable when more elements are added to the page.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
Pending capture — to be attached before review.
Android: mWeb Chrome
Pending capture — to be attached before review.
iOS: Native
Pending capture — to be attached before review.
iOS: mWeb Safari
Pending capture — to be attached before review.
MacOS: Chrome / Safari
Pending capture — to be attached before review.