Repository navigation
Conversation
…ls page Co-authored-by: Nguyen Van Duc <[email protected]>
|
I created this PR from an upstream branch since I don't have push access to your fork. To take ownership of this branch and be able to push updates, run: Then you can close this PR and open a new one from your fork. |
🦜 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 b244de15..5d9ade6b 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -11546,8 +11546,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
},
billedTo: 'Abgerechnet an',
activity: 'Aktivität',
- findActiveUser: 'Aktiven Benutzer suchen',
- noActiveUsers: 'In diesem Monat gab es keine aktiven Benutzer.',
+ findActiveUser: 'Aktive Nutzerin oder aktiven Nutzer finden',
+ noActiveUsers: 'Diesen Monat gibt es keine aktiven Nutzer.',
viewReceipt: 'Beleg anzeigen',
viewInvoice: 'Rechnung anzeigen',
},
diff --git a/src/languages/el.ts b/src/languages/el.ts
index d2ae78ee..990ccff7 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -11762,8 +11762,8 @@ ${reportName}`,
},
billedTo: 'Χρέωση σε',
activity: 'Δραστηριότητα',
- findActiveUser: 'Εύρεση ενεργού χρήστη',
- noActiveUsers: 'Δεν υπήρξαν ενεργοί χρήστες αυτόν τον μήνα.',
+ findActiveUser: 'Βρείτε έναν ενεργό χρήστη',
+ noActiveUsers: 'Δεν υπάρχουν ενεργοί χρήστες αυτόν τον μήνα.',
viewReceipt: 'Προβολή απόδειξης',
viewInvoice: 'Προβολή τιμολογίου',
},
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 55970db1..ffe8a8f3 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -11733,8 +11733,8 @@ ${reportName}`,
},
billedTo: 'Facturado a',
activity: 'Actividad',
- findActiveUser: 'Buscar un usuario activo',
- noActiveUsers: 'No hubo usuarios activos este mes.',
+ findActiveUser: 'Busca una persona usuaria activa',
+ noActiveUsers: 'No hay usuarios activos este mes.',
viewReceipt: 'Ver recibo',
viewInvoice: 'Ver factura',
},
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 119fcf79..b7c4a1c6 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -11572,7 +11572,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
},
billedTo: 'Facturé à',
activity: 'Activité',
- findActiveUser: 'Rechercher un utilisateur actif',
+ findActiveUser: 'Trouver un utilisateur actif',
noActiveUsers: 'Aucun utilisateur actif ce mois-ci.',
viewReceipt: 'Voir le reçu',
viewInvoice: 'Voir la facture',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index f99d3bff..d43a570b 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -11329,8 +11329,8 @@ ${reportName}`,
},
billedTo: '請求先',
activity: 'アクティビティ',
- findActiveUser: 'アクティブユーザーを検索',
- noActiveUsers: '今月のアクティブユーザーはいません。',
+ findActiveUser: 'アクティブなユーザーを検索',
+ noActiveUsers: '今月はアクティブユーザーがいません。',
viewReceipt: '領収書を表示',
viewInvoice: '請求書を表示',
},
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 09498a93..a7695e33 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -11478,7 +11478,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
billedTo: 'Obciążono',
activity: 'Aktywność',
findActiveUser: 'Znajdź aktywnego użytkownika',
- noActiveUsers: 'W tym miesiącu nie było aktywnych użytkowników.',
+ noActiveUsers: 'W tym miesiącu nie ma aktywnych użytkowników.',
viewReceipt: 'Wyświetl paragon',
viewInvoice: 'Wyświetl fakturę',
},
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
🤖 Web test steps verification results: ❌ fail The Payment details page couldn't be reached on dev web, so none of the steps could be checked. The test account has no billing history. Turning on the
|
|
- Activity label: 8px/20px padding and 12px bottom margin - Search input: 44px tall, 12px above the card - Active users count header: 36px tall - Activity rows: ph4 + pv1 wrapper Co-authored-by: Nguyen Van Duc <[email protected]>
|
I pushed all four style changes in bbb8e21:
Two shared files changed, so please check them:
Typecheck, ESLint, the React Compiler check, and the page's tests (35 of 35) pass. I didn't check the layout in a browser because the test account has no payment history to open. |
|
|
I updated the PR body:
|
|
@MelvinBot open the PR |
|
🤖 I marked this PR as ready for review. The Tests and QA Steps sections are still TODOs. You need to fill them in, and add screenshots, before the checklist passes. |
|
@nkdengineer 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] |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@trjExpensify Is there a case where there's no active user? |
|
It looks good on my side, but we still need a real account to test Screen.Recording.2026-10-19.at.10.25.59.mov |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bbb8e2157f
ℹ️ 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".
| if (!hasActiveUsers) { | ||
| activityHeader = ( | ||
| <View style={[styles.mh5, styles.p4, styles.highlightBG, styles.borderRadiusComponentNormal]}> | ||
| <Text style={[styles.textLabelSupporting, styles.userSelectText]}>{translate('subscription.paymentHistory.noActiveUsers')}</Text> |
There was a problem hiding this comment.
Avoid treating missing activity data as an empty month
When OpenPaymentDetailsPage fails, openPaymentDetailsPage() still sets isLoaded: true through finallyData, while activeUsers remains undefined; the same state can occur for an older cached purchase. Since getActiveUserAccountIDs() converts undefined to [], this branch then displays the definitive and incorrect “No active users this month.” message and does not retry until another mount. Preserve an unknown/error state separately from a successfully returned empty activeUsers array.
Useful? React with 👍 / 👎.
|
🚧 trjExpensify has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
I think we should hide the search bar unless there's 12+ active users to search in the select list like elsewhere. Seems pretty pointless. Separately, and this can probably be follow-up, but I think I should be able to click on a member to open their public profile? 2026-10-20_19-21-21.mp4 |
|
Both make sense to me 👍 |
|
@dukenv0307 I think it's better to switch the |
|
Please also update the suggestion behavior here |
|
Based on #104325 (comment), let's switch to using
Then fix it as well |
…r for 12+ active users Co-authored-by: Nguyen Van Duc <[email protected]>
|
MelvinBot has made 5 consecutive commits trying to fix CI failures. Automatic CI fix dispatches are now paused for this PR. Next steps: A human should review the recent commits and resolve the conflicting CI errors manually. |
|
I switched the Activity list to
Typecheck, lint, oxfmt, the React Compiler check, and the page's UI tests (3 of 3) pass. I also updated the PR description. I didn't check it in a browser because the test account has no payment history, so please test it with real data. |
Create an App issue as the sub-issue of #101649 |
|
Thanks for your solution. It looks good on web.
@nkdengineer could you please review it again? |
|
I created [CFI] Payment history: open an active user's public profile from the Activity list and added it as a sub-issue of [CFI] Add a "View payment history" page with historical billing receipts and monthly user activity. The issue covers making the Activity rows open the user's public profile, the same way the report participants list does. It depends on this PR. I assigned it to you and added the |
|
@nkdengineer I think this is on you for a re-review. :) |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-10-21.at.21.11.37.movAndroid: mWeb ChromeScreen.Recording.2026-10-21.at.21.13.35.moviOS: HybridAppScreen.Recording.2026-10-21.at.21.12.01.moviOS: mWeb SafariScreen.Recording.2026-10-21.at.21.14.08.movMacOS: Chrome / SafariScreen.Recording.2026-10-21.at.21.14.28.mov |
nkdengineer
left a comment
There was a problem hiding this comment.
Looks good to me and test well. A small NAB
| it('returns no users when the details have not loaded or nobody was billed', () => { | ||
| // Given a missing purchase, a purchase without active users, and a purchase with an empty list | ||
| // When the active users are read | ||
| // Then the list is empty, so the page renders the empty state instead of a blank section |
There was a problem hiding this comment.
| // Then the list is empty, so the page renders the empty state instead of a blank section | |
| // Then the list is empty, so the page hides the Activity section |
There was a problem hiding this comment.
I updated the comment to nkdengineer's suggestion in 5e13eb7. It now reads "Then the list is empty, so the page hides the Activity section". See PaymentHistoryUtilsTest.ts:448.
Co-authored-by: Nguyen Van Duc <[email protected]>
|
@MelvinBot Why is the test failing? |
|
The failing check isn't caused by this PR. In Rerun the failed job and it should pass. I wasn't able to start the rerun myself. The other failing check, |
|
@MelvinBot merge main |
…ActivityList Co-authored-by: Nguyen Van Duc <[email protected]>
|
I merged After the merge, TypeScript passes for the app and test projects, and the payment history tests pass (35 of 35). |
|
@MelvinBot Is the failing test fixed on main? |
|
Yes. [No QA] Recycle Jest workers past 2GB to stop CI OOM kills merged to To pick up the fix, merge Details
|
|
@MelvinBot merge main |
…ActivityList Co-authored-by: Nguyen Van Duc <[email protected]>
|
I merged TypeScript passes after the merge. CI is now running the tests on the new commit. |







Explanation of Change
Adds the Activity section to the Payment details page (FE 5/7 of the payment history project), laid out like the mock: an
Activitylabel, a "Find an active user" search field, and a table. The table's header shows the active user count, and each row shows the user's avatar, name, and email.Activitylabel, search field, and table are hidden.getActiveUserAccountIDsdedupespurchase.activeUsers, so a person billed under two workspaces is counted and listed once.Table. A newPaymentActivityTable(insrc/components/Tables/) renders the list with the sharedTablecomponent, like the room members and report participants tables. The existing details (date, amount, badge, Billed to, View receipt) and theActivitylabel are passed as itsheaderComponent, so the whole page scrolls as one list. Rows are virtualized, read-only, and sorted by name.Tablealso adds the bottom safe-area padding.CONST.STANDARD_LIST_ITEM_LIMIT(12) active users, like other select lists. It filters by name or email withtokenizedSearchand shows the standard table "No results found" state when nothing matches. The count always shows every active user.activityandfindActiveUseris added in every locale, using the "active users" wording. The Collect-plan "members" variant is FE 7/7.Data contract: the list reads
purchase.activeUsers, the account IDs thatOpenPaymentDetailsPagereturns. This field was already declared inPurchaseList.tsby FE 4/7. Display names, emails, and avatars come frompersonalDetailsList. If the backend ends up sending the rawbillablePolicies[*].actorListemails instead, onlygetActiveUserAccountIDsand the item mapping need to change.AI tests run locally:
npm run typecheck: passednpm run linton changed files: passednpm run fmt(oxfmt): no changes outside this PRnpm run react-compiler-compliance-check check <changed components>: passednpm test -- tests/ui/PaymentDetailsPageTest.tsx: 3/3 passed. The UI test covers the deduped count, the rows with emails, the search bar hidden below 12 active users, search filtering with 12 active users, the no-results state, and a month with no active users hiding the section.npm testsuite, the Storybook smoke test, the translation dry run, and the spell check.Fixed Issues
$ #101832
PROPOSAL:
Tests
Precondition: An account with subscription payment history and payment history beta is enabled
Steps:
Offline tests
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)npm run compress-svg)Avataris modified, I verified thatAvataris working as expected)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