feat: Add Attendees to Edit multiple in expenses - #97108
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fefa84706e
ℹ️ 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".
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.
|
There was a problem hiding this comment.
Pull request overview
Adds bulk-edit support for Attendees when using Spend > Reports > select multiple expenses > Edit multiple, including navigation/route wiring and persistence via a dedicated API command.
Changes:
- Add “Attendees” as an editable field in the Search “Edit multiple” flow, including a new RHP page for selecting attendees.
- Update bulk-edit persistence to write attendees via
UpdateMoneyRequestAttendees, including optimistic transaction updates and recent-attendee tracking. - Add/extend unit tests to cover attendees-only updates and mixed (generic + attendees) updates.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/actions/IOUTest/BulkEditTest.ts | Adds tests validating attendees persistence command selection and optimistic updates. |
| src/SCREENS.ts | Introduces a new Search bulk-edit attendees RHP screen constant. |
| src/ROUTES.ts | Adds the route for the Search bulk-edit attendees RHP page. |
| src/pages/Search/SearchEditMultiple/SearchEditMultipleUtils.ts | Adds selection-level gating to determine when attendees bulk edit is enabled. |
| src/pages/Search/SearchEditMultiple/SearchEditMultiplePage.tsx | Surfaces the Attendees field in the bulk-edit field list and includes it in save payload. |
| src/pages/Search/SearchEditMultiple/SearchEditMultipleAttendeesPage.tsx | New RHP page for choosing attendees and writing to the bulk-edit draft transaction. |
| src/pages/iou/request/MoneyRequestAttendeeSelector.tsx | Adjusts error-message behavior to avoid showing it during loading/transition. |
| src/libs/ReportUtils.ts | Allows bulk-editing the ATTENDEES edit-request field. |
| src/libs/Navigation/linkingConfig/config.ts | Wires deep linking config for the new attendees RHP screen/route. |
| src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx | Registers the attendees RHP page in the Search modal stack navigator. |
| src/libs/actions/IOU/BulkEdit.ts | Implements attendees bulk-edit persistence (including optimistic updates and API command splitting). |
| src/CONST/index.ts | Adds ATTENDEES to EDIT_REQUEST_FIELD constants. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
joekaufmanexpensify
left a comment
There was a problem hiding this comment.
Good for product.
|
Bug: One attendee selected shown from bulk edit when both transactions have two same attendees I think the expected behavior should show no attendee selected, just like other field selectors. So bulk edit has consistent behavior for all fields - there's no default values and merged values until selecting some. @joekaufmanexpensify do you agree? Screen.Recording.2026-07-28.at.4.34.31.PM.mov |
|
Yep, I think that works. One note: an expense must always have one attendee. I assume we'll throw if the user tries to proceed without selecting at least one attendee? If so, good with me. 👍 |
yes, you're right we can't proceed if no attendee is selected. Screen.Recording.2026-07-29.at.9.38.21.PM.mov |
|
Sounds good. This is good with me then. 👍 |
|
@samranahm gentle bump on #97108 (comment) and #97108 (comment) |
|
Ahh, missed this one. Looking into it. |
Agreed. We'll show the current user as the default attendee only for expenses that haven't been updated yet. Once an expense or all selected expenses has been updated, no attendee will be selected by default unless all the selected expenses have the same one attendee, and the user won't be able to save without selecting at least one attendee. |
|
Sounds good. Yep, as long as that's how the other fields work, sounds good to me. |
|
Sounds good. Looking at the other fields again and none of them preselect a value even when every selected expense already shares the same value (e.g. category). The only reason attendees has a default was to avoid the “At least one attendee must be selected” error on page open. We’re now deferring that error until the user tries to save with nothing selected, so attendees can start empty like the other fields and stay consistent. |
|
@eh2077 All yours, please take a look. |
|
Test steps updated. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari |
|
Resolving merge conflicts. |
Explanation of Change
Fixed Issues
$ #94313
PROPOSAL: #94313 (comment)
Tests
Precondition:
Offline tests
QA Steps
Same as test
// TODO: These must be filled out, or the issue title must include "[No QA]."
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
Android.mWeb.Chrome.mp4
iOS: Native
IOS.Native.mp4
iOS: mWeb Safari
IOS.mWeb.Safari.mp4
MacOS: Chrome / Safari
macOS.Chrome.mp4