Repository navigation
[CFI] Payment history: Activity list with the active user count - #104325
Conversation
…ls page Co-authored-by: Nguyen Van Duc <dukenv0307@users.noreply.github.com>
|
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 <dukenv0307@users.noreply.github.com>
|
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 👍 / 👎.
|
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 <dukenv0307@users.noreply.github.com>
|
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 <dukenv0307@users.noreply.github.com>
|
I merged TypeScript passes after the merge. CI is now running the tests on the new commit. |
|
@MelvinBot I think it's fixed on main, if so please merge main |
…ActivityList Co-authored-by: Nguyen Van Duc <dukenv0307@users.noreply.github.com>
|
I merged the latest
I couldn't run typecheck locally, so check the new CI run to confirm it passes. |
|
All yours @mollfpr |
|
🚧 mollfpr 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! 🧪🧪
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/mollfpr in version: 9.5.20-0 🚀
|
|
No help site update is needed. The new Activity section only appears on the Payment details page, and that whole page is behind the |
|
@jponikarchuk #104963 is not a bug. The search input only appears if we have >= 12 active users. |
|
🚀 Deployed to production by https://github.com/jasperhuangg in version: 9.5.20-5 🚀
Bundle Size Analysis (Sentry): |





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