Add natural language filter entry point to Spend page - #94217
Conversation
Adds PARSE_EXPENSE_FILTERS to READ_COMMANDS, ParseExpenseFiltersParams type, and the ReadCommandParameters mapping for the NL spend filter feature.
Wires the SearchNLFilterPage into the navigation layer:
- SCREENS.SEARCH.ADVANCED_FILTERS_DESCRIBE_RHP screen constant
- ROUTES.SEARCH_ADVANCED_FILTERS_DESCRIBE static route ('search/filters/describe')
- SearchAdvancedFiltersParamList type entry
- Linking config entry
- SearchAdvancedFiltersModalStackNavigator registration
- Stub SearchNLFilterPage component (full implementation in next phase)
Replaces stub with full implementation: TextInput for query input, loading state on submit button, success navigation to search results, and inline error display from ParseExpenseFilters API response. Adds translation keys for en/es.
Add "Describe your search" as the first item in the filter panel with a Sparkles icon, separated from the rest of the sections by a horizontal rule. Tapping it navigates to the SearchNLFilterPage.
ParseExpenseFilters returns dynamic data (success/failure with payload) rather than Onyx-persisted state, so it belongs in SIDE_EFFECT_REQUEST_COMMANDS and uses makeRequestWithSideEffects. Adds the action function and ParseExpenseFiltersResult type; extends Response.ts with the API response fields.
Main replaced AdvancedSearchFilters.tsx with SearchAdvancedFiltersPage + a unified ADVANCED_FILTERS_CONTENT_RHP route (filterKey param) for all filters. Resolved conflicts by: - Keeping both ADVANCED_FILTERS_DESCRIBE_RHP and ADVANCED_FILTERS_CONTENT_RHP in types.ts and config.ts - Migrating the "Describe your search" MenuItem from the deleted AdvancedSearchFilters.tsx to SearchAdvancedFiltersBase.tsx - Including all new Search.ts exports from main alongside parseExpenseFilters
This comment has been minimized.
This comment has been minimized.
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.
|
This comment has been minimized.
This comment has been minimized.
# Conflicts: # android/app/build.gradle # android/app/src/main/java/com/expensify/chat/MainApplication.kt # config/eslint/eslint.seatbelt.tsv # ios/AppDelegate.swift # ios/NewExpensify/Info.plist # ios/NotificationServiceExtension/Info.plist # ios/ShareViewController/Info.plist # package-lock.json # package.json # src/CONST/index.ts # src/ROUTES.ts # src/SCREENS.ts # src/components/MoneyReportHeaderActions/MoneyReportHeaderSecondaryActions.tsx # src/components/MoneyReportHeaderKYCDropdown.tsx # src/components/MoneyRequestConfirmationList/sections/DateField.tsx # src/components/MoneyRequestHeaderSecondaryActions.tsx # src/components/ReportActionItem/MoneyRequestView.tsx # src/components/Search/FilterDropdowns/SearchAdvancedFiltersPopup/index.tsx # src/components/Search/hooks/useSearchListViewState.ts # src/components/Search/index.tsx # src/components/Tables/WorkspaceExpensifyCardsTable/WorkspaceExpensifyCardsTableRow.tsx # src/hooks/useDeleteTransactions.ts # src/hooks/useExpenseActions.ts # src/hooks/useLifecycleActions.tsx # src/hooks/useReportSubmitToPopover.tsx # src/hooks/useSearchBulkActions.ts # src/hooks/useSelectedTransactionsActions.ts # src/hooks/useUnreadMarker.ts # src/languages/de.ts # src/languages/en.ts # src/languages/es.ts # src/languages/fr.ts # src/languages/it.ts # src/languages/ja.ts # src/languages/nl.ts # src/languages/pl.ts # src/languages/pt-BR.ts # src/languages/zh-hans.ts # src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx # src/libs/Navigation/linkingConfig/OldRoutes.ts # src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts # src/libs/Navigation/linkingConfig/config.ts # src/libs/PolicyUtils.ts # src/libs/ReportUtils.ts # src/libs/SearchUIUtils.ts # src/libs/actions/IOU/MoneyRequest.ts # src/libs/actions/IOU/ReportWorkflow.ts # src/libs/actions/SplitExpenses.ts # src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts # src/pages/home/RecentlyAddedSection/useRecentlyAddedData.ts # src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx # src/pages/iou/request/step/IOURequestStepAmount.tsx # src/pages/iou/request/step/IOURequestStepConfirmation.tsx # src/pages/iou/request/step/IOURequestStepDate.tsx # src/pages/workspace/WorkspaceInitialPage.tsx # src/pages/workspace/WorkspaceMembersPage.tsx # src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx # src/pages/workspace/rules/AgentRulesSection.tsx # src/pages/workspace/tags/DynamicWorkspaceEditTagsPage.tsx # src/pages/workspace/tags/WorkspaceTagsPage.tsx # tests/actions/IOUTest/SplitTest.ts # tests/navigation/getMatchingNewRouteTest.ts # tests/ui/ForYouSectionTest.tsx # tests/ui/MoneyRequestReportPreview.test.tsx # tests/ui/ReportActionItemTest.tsx # tests/unit/PolicyUtilsTest.ts # tests/unit/hooks/useReviewFlaggedExpenses.test.ts
This comment has been minimized.
This comment has been minimized.
…ceCompanyCardEditCardNamePage
|
🚧 marcaaron has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
|
@JmillsExpensify pretty rough version of this, I think, but working. One thing that is not 100% working is resolving the workspace. For example, I ask for all anthropic receipts that I can see. And the AI locked it to my default workspace, so I need to figure out why. But I think it works pretty well for most other cases. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 414135e2b3
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
🚧 marcaaron has triggered a test Expensify/App build. You can view the workflow run here. |
- Pin left column to its designed width so the right content panel isn't squeezed - Describe button now activates on hover (matching all other filter items) instead of requiring a click - Replace single-line autoGrowHeight input with a multiline textarea that fills the available panel height
|
@shawnborton @dubielzyk-expensify @dannymcclain are you guys thinking something like this:
Or more of a start small and auto-grow to a max situation? This is the only other mock that I have, so wasn't 100% sure.
|




Explanation of Change
Adds a "Describe your search" entry point to the Spend page Advanced Filters. Users type a plain-English description of what they want to see ("meals over $50 last month", "card expenses Q2"), and the backend (GPT-4.1 via Web-Expensify/Web-Expensify#53678) parses it into a structured query and returns a search URL. The App navigates directly to the search results.
New screen at
ROUTES.SEARCH_ADVANCED_FILTERS_DESCRIBE(/search/filters/describe). Entry point added at the top of the Advanced Filters list (and the filters dropdown on wide screens) with a sparkle icon.Holding on:
Fixed Issues
$ https://github.com/Expensify/Expensify/issues/647828
PROPOSAL:
Tests
Prerequisites: Sign in to
dev.new.expensify.com:8082. Have a workspace with at least one custom category (e.g. "Meals and Entertainment").Entry point
/search/filters/describewith a text input and "Create filters" button.Semantic category match
meals over $50 last month.category:"Meals and Entertainment",amount>5000, and last-month date filters in the query.Keyword fallback (no matching category)
coffee over $20.keyword:coffee amount>2000— notcategory:coffee.Error state
what are my biggest expense categories./search/filters/describe.Back navigation
Offline tests
N/A — the feature requires a live API call to OpenAI. The "Create filters" button will return an error when offline; no special offline handling is needed.
QA Steps
Prerequisites: Have an active workspace with at least one custom category (e.g. "Meals and Entertainment"). Have expenses in that workspace across different months and amounts.
Desktop: describe mode opens inline in the popup
Desktop: semantic query applies filters and closes the popup
meals over $50 last month.Desktop: unrecognized query shows an error inline
what are my biggest expense categories.Mobile: describe mode opens a full-screen page
Mobile: semantic query navigates to results
card expenses last 30 days.expenseType:cardand a 30-day date range as filter chips.Network error resets the loading state (desktop and mobile)
meals last month).Desktop: popup closes before navigating on success
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, 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