Skip to content

Filter Amex Direct parent card from company cards page#82448

Merged
amyevans merged 18 commits intomainfrom
claude-filterAmexParentCard
Feb 27, 2026
Merged

Filter Amex Direct parent card from company cards page#82448
amyevans merged 18 commits intomainfrom
claude-filterAmexParentCard

Conversation

@MelvinBot
Copy link
Contributor

Explanation of Change

For Amex Direct (FDX) feeds, accountList[0] is the parent card (primary account holder), which aggregates child accounts rather than representing a distinct individual card. This parent card should not appear in the company cards page or be assignable, as assigning it causes confusion and duplicate transactions.

This PR adds a feedName parameter to getFilteredCardList (in CardUtils.ts) and buildCompanyCardEntries (in useCompanyCards.ts). When the feed is an Amex Direct feed (oauth.americanexpressfdx.com), both functions now skip accountList[0] when building the list of unassigned cards. Already-assigned cards (Phase 1 of buildCompanyCardEntries) are unaffected — if the parent card was somehow already assigned, it would still display.

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/600138

PROPOSAL: https://github.com/Expensify/Expensify/issues/600138#issuecomment-3897665859

Tests

  1. Connect an Amex Direct (FDX) company card feed to a workspace
  2. Navigate to Settings > Workspaces > [workspace] > Company Cards > [Amex feed]
  3. Verify that the parent card (the first entry in accountList, which has no cardholder name — e.g., "Business Platinum Card - 03005") does not appear in the card list
  4. Verify that all child cards (entries with cardholder names — e.g., "Business Platinum Card - BOB ARNOLD - 02015") still appear correctly
  5. Click Assign card and verify the parent card does not appear in the card selection dropdown
  6. Verify non-Amex Direct feeds (Chase, Capital One, etc.) are unaffected — all cards still appear
  • Verify that no errors appear in the JS console

Offline tests

No offline-specific behavior changes. The filtering is applied purely to the in-memory card list rendering.

QA Steps

  1. Have a workspace with an Amex Direct (FDX) company card feed connected
  2. Navigate to the Company Cards page for that feed
  3. Verify the parent card (first entry in the account list, no cardholder name) is not shown
  4. Verify all child cards (with cardholder names) are shown correctly
  5. Try assigning a card — verify the parent card is not in the assignment dropdown
  6. Check a non-Amex Direct feed — verify all cards still appear normally
  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native

N/A - No UI changes, only filtering logic

Android: mWeb Chrome

N/A - No UI changes, only filtering logic

iOS: Native

N/A - No UI changes, only filtering logic

iOS: mWeb Safari

N/A - No UI changes, only filtering logic

MacOS: Chrome / Safari

N/A - No UI changes, only filtering logic

@MelvinBot MelvinBot requested a review from a team February 13, 2026 18:18
… picker

For Amex Direct (FDX) feeds, accountList[0] is the parent card (primary
account holder) which aggregates child accounts. This card should not
appear in the company cards list or be assignable, as it does not
represent a distinct card.

Adds a feedName parameter to getFilteredCardList and
buildCompanyCardEntries. When the feed is Amex Direct, both functions
skip accountList[0] when building the list of unassigned cards.
Already-assigned cards are unaffected.

Co-authored-by: Carlos Miceli <carlosmiceli@users.noreply.github.com>
@MelvinBot MelvinBot force-pushed the claude-filterAmexParentCard branch from 7090ed0 to 6c68930 Compare February 13, 2026 18:29
@MelvinBot
Copy link
Contributor Author

Fixed both failing checks:

1. typecheck failure: All 5 modified files (CardUtils.ts, useCompanyCards.ts, CardSelectionStep.tsx, InviteNewMemberStep.tsx, CardUtilsTest.ts) had their contents replaced with a single-line file path reference instead of actual code. The branch was recreated from main with the correct implementation.

2. verifySignedCommits failure: The original commit was unsigned. The new commit is properly signed.

Changes implemented:

  • Added optional feedName parameter to getFilteredCardList (in CardUtils.ts) and buildCompanyCardEntries (in useCompanyCards.ts)
  • When the feed is Amex Direct (oauth.americanexpressfdx.com), both functions skip accountList[0] (the parent card) when building the unassigned card list
  • Updated CardSelectionStep.tsx and InviteNewMemberStep.tsx to pass the feed name
  • Added 3 unit tests covering: Amex Direct filtering, non-Amex feeds unaffected, and backward compatibility when feedName is omitted
  • Typecheck passes locally

Co-authored-by: Carlos Miceli <carlosmiceli@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing spellcheck check. The cspell dictionary didn't recognize "HITT" (a surname used in the test data — "MASON HITT"). Added it to cspell.json.

@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/hooks/useCompanyCards.ts 100.00% <100.00%> (ø)
src/libs/CardUtils.ts 78.93% <100.00%> (+0.61%) ⬆️
src/libs/SearchUIUtils.ts 68.35% <100.00%> (+0.03%) ⬆️
...pace/companyCards/assignCard/CardSelectionStep.tsx 0.00% <ø> (ø)
...ce/companyCards/assignCard/InviteNewMemberStep.tsx 0.00% <0.00%> (ø)
... and 27 files with indirect coverage changes

@carlosmiceli carlosmiceli marked this pull request as ready for review February 16, 2026 21:02
@carlosmiceli carlosmiceli requested a review from a team as a code owner February 16, 2026 21:02
@melvin-bot melvin-bot bot requested review from heyjennahay and removed request for a team February 16, 2026 21:02
for (const name of accountList ?? []) {
// For Amex Direct (FDX) feeds, accountList[0] is the parent card (primary account holder)
// which aggregates child accounts and should not be assignable.
const isAmexDirectFeed = feedName ? getCompanyCardFeed(feedName).startsWith(CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX_DIRECT) : false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ CONSISTENCY-3 (docs)

The Amex Direct parent card filtering logic is duplicated between useCompanyCards.ts (here) and CardUtils.ts (getFilteredCardList). Both locations compute isAmexDirectFeed and slice/skip accountList[0] in the same way. This duplicated logic should be extracted into a shared helper in CardUtils.ts (e.g., filterAmexDirectParentCard) so both call sites can reuse it.

Suggested fix — add a helper to CardUtils.ts and use it in both places:

// In CardUtils.ts
function filterAmexDirectParentCard(accountList: string[], feedName?: CompanyCardFeedWithDomainID): string[] {
    const isAmexDirectFeed = feedName ? getCompanyCardFeed(feedName).startsWith(CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX_DIRECT) : false;
    return isAmexDirectFeed ? accountList.slice(1) : accountList;
}

Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Extracted the duplicated Amex Direct parent card filtering logic into a shared filterAmexDirectParentCard helper in CardUtils.ts. Both getFilteredCardList and buildCompanyCardEntries now call it instead of computing isAmexDirectFeed and slicing inline.

…x Direct parent card filtering logic

Co-authored-by: Carlos Miceli <carlosmiceli@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

MelvinBot commented Feb 16, 2026

The only failing check is checklist (PR Reviewer Checklist), which is unrelated to the PR code changes. This check is triggered by pull_request_review events and requires a reviewer to post a comment containing the reviewer checklist with all items checked — it cannot be fixed by pushing code.

All code-related checks are passing:

  • TypeScript Checks
  • ESLint check + Changed files ESLint check
  • Prettier check
  • Spell check
  • All Jest Unit Tests (jobs 1-8)
  • Storybook tests
  • All builds (iOS + Android, debug + dev)
  • verifySignedCommits
  • CLA

The checklist failure will resolve once a reviewer posts their completed reviewer checklist comment on this PR.

Comment on lines +791 to +792
const isAmexDirectFeed = feedName ? getCompanyCardFeed(feedName).startsWith(CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX_DIRECT) : false;
return isAmexDirectFeed ? accountList.slice(1) : accountList;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlosmiceli Is the first card a guaranteed parent card? If not, we might have a bug causing missing cards in newDot, and we should also confirm if this logic is necessary for oldDot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I've seen in every case so far, have you seen a different case at some point? Let's see if @robertjchen or @amyevans agree on this approach 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the first card a guaranteed parent card?

Yes, just based on the way that we build the data in the Scraper class the first card will always be a "parent" card.

However just removing the first card in the list is going to be an incomplete fix... Plenty of Amex connections have multiple card programs, so we'd want to ideally filter out all parent cards. Perhaps this could be achieved by looking for the matches and removing the card without a name in the found pair. So for example if the accountList has:

Business Platinum Card - 02015
Business Platinum Card - BOB ARNOLD - 02015

It removes Business Platinum Card - 02015

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good to know, thanks Amy, will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated filterAmexDirectParentCard to handle multiple card programs. Instead of naively removing accountList[0], it now:

  1. Scans the list for child cards (3+ segments when split by -) and collects their card type prefixes
  2. Filters out any parent card (exactly 2 segments: CardType - Digits) whose card type has at least one child

This handles feeds with multiple card programs (e.g., Platinum + Gold) where each program has its own parent card at any position in the list. Added a dedicated test for the multi-program scenario.

@MelvinBot
Copy link
Contributor Author

The only failing check is checklist, which is triggered by the pull_request_review event (fedirjh's review). This check requires the reviewer to post a completed Reviewer Checklist comment with all items checked off. It currently shows 0 out of 58 items completed.

This is not a code issue — no code changes can fix it. The reviewer needs to post their checklist comment to resolve this check.

@MelvinBot
Copy link
Contributor Author

Reviewed the feedback on this PR. Here's the status of each comment thread:

  1. CONSISTENCY-3 (bot suggestion) — Already addressed in commit c393677. The duplicated Amex Direct parent card filtering logic was extracted into a shared filterAmexDirectParentCard helper in CardUtils.ts, and both getFilteredCardList and buildCompanyCardEntries now call it.

  2. @fedirjh's question about whether the first card is a guaranteed parent card — This is a product/domain question that @carlosmiceli has already responded to, and is awaiting input from @robertjchen and @amyevans. No code change needed at this time.

No outstanding actionable code changes remain from the current review feedback.

@MelvinBot
Copy link
Contributor Author

The only failing check is checklist — this is not a code issue. It's the PR Reviewer Checklist check that triggers when a review is submitted. It requires the reviewer to post a comment with the completed Reviewer Checklist (all 58 items checked). This cannot be fixed by pushing code changes.

All code-related checks (typecheck, ESLint, tests, spellcheck, builds, Prettier, etc.) are passing.

@MelvinBot
Copy link
Contributor Author

The only failing check is checklist (reviewer checklist). This is not a code issue — it fails because the PR Reviewer Checklist comment has 0 out of 58 items checked.

This check requires a reviewer to post the reviewer checklist (from contributingGuides/REVIEWER_CHECKLIST.md) as a PR comment and check all the boxes after reviewing. It cannot be fixed by pushing code changes.

All code-related checks are passing: ESLint, typecheck, Prettier, tests (all 8 jobs), builds (all platforms), spellcheck, verifySignedCommits, and storybook tests.

@MelvinBot
Copy link
Contributor Author

The only failing check is checklist (PR Reviewer Checklist). This is not a code issue — it's failing because a reviewer checklist comment has been posted but none of the 58 items have been checked off yet (0/58 completed).

This check will pass once the assigned reviewer goes through and checks the boxes in their reviewer checklist comment. No code changes are needed.

MelvinBot and others added 2 commits February 17, 2026 22:59
Updated filterAmexDirectParentCard to detect parent cards structurally
by checking segment count (CardType - Digits vs CardType - Name - Digits)
instead of naively removing accountList[0]. This handles multiple card
programs per Amex Direct feed. Also replaced real card data in tests
with fake data.

Co-authored-by: Carlos Miceli <carlosmiceli@users.noreply.github.com>
Co-authored-by: Carlos Miceli <carlosmiceli@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing Prettier checktests/unit/CardUtilsTest.ts had a formatting diff (array literal that Prettier collapses to a single line). Ran Prettier and pushed the fix.

The other failing check (checklist) is the PR Reviewer Checklist — it requires a human reviewer to fill out their checklist items, so it's not something that can be fixed via code changes.

Co-authored-by: Carlos Miceli <carlosmiceli@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing checks:

  1. Prettier check (previous run) — was already fixed in the last push before this one.
  2. ESLint prefer-at ruleCardUtils.ts used segments[0] for array access in the new filterAmexDirectParentCards function. Changed to segments.at(0) ?? '' to comply with the codebase's rulesdir/prefer-at lint rule.
  3. PR Reviewer Checklist — this is a reviewer workflow check (0 of 58 items checked), not a code issue. It will pass once a reviewer fills in their checklist.

@MelvinBot
Copy link
Contributor Author

All checks are now passing on the latest run. The previous failures were:

  • ESLint check — failed due to pre-existing react-hooks/set-state-in-effect warnings in files unrelated to this PR (withPolicyConnections.tsx, WorkspaceWorkflowsApprovalsEditPage.tsx, WorkspaceWorkflowsApprovalsExpensesFromPage.tsx). This appears to have been resolved on main and the latest run passes.
  • Prettier check — also resolved in the latest push.

The current run shows all checks green: typecheck, all 8 test jobs, ESLint, Changed files ESLint, Prettier, builds, perf-tests, Storybook tests, spellcheck, and verifySignedCommits all pass. No fix was needed from my end.

@MelvinBot
Copy link
Contributor Author

Reviewed all open feedback threads — here's the current status:

  1. fedirjh's refactoring suggestion (parsedAccounts/childKeys pattern) — applied, with normalizeCardName added for consistency
  2. amyevans' normalizeCardName concern — fixed, both getAmexDirectParentCardNames and filterAmexDirectParentCard normalize before lookup
  3. Codex P1 (preserve assigned parent cards) — addressed, Phase 1 in buildCompanyCardEntries keeps previously assigned parent cards visible; filtering only applies to unassigned cards
  4. chrispader's .at(0) with extra condition suggestions — applied via the refactoring

All code-related CI checks are passing (ESLint, typecheck, Prettier, tests, builds, signed commits). The only failing check is the PR Reviewer Checklist, which requires manual completion by a reviewer.

@MelvinBot
Copy link
Contributor Author

The only failing check is PR Reviewer Checklist, which is not related to the code changes in this PR. It fails when a reviewer hasn't completed their checklist items. This is not something that can be fixed with a code change — it requires a reviewer to complete the checklist.

All code-related checks (ESLint, typecheck, Prettier, tests, builds, spellcheck, verifySignedCommits) are passing.

@MelvinBot
Copy link
Contributor Author

The only failing check is PR Reviewer Checklist / checklist — this is triggered because a reviewer posted the reviewer checklist but hasn't checked off all items yet (0 out of 57 completed). This is not a code issue and cannot be fixed by pushing commits. The reviewer needs to complete their checklist to resolve this check.

All other checks (ESLint, typecheck, Prettier, tests, builds, spellcheck, verifySignedCommits, etc.) are passing.

@MelvinBot
Copy link
Contributor Author

The only failing check is PR Reviewer Checklist, which requires a reviewer to manually complete the checklist items. This is not a code or CI issue — all other checks (ESLint, typecheck, Prettier, tests, builds, signed commits, etc.) are passing. No code fix is needed.

@MelvinBot
Copy link
Contributor Author

Reviewed all open feedback threads. All review comments are addressed in the current code:

  • fedirjh's refactoring suggestiongetAmexDirectParentCardNames already uses the parsedAccounts/childKeys/parentNames pattern. Replied to confirm.
  • chrispader's style preferences — Both applied (extra condition instead of empty string fallback).
  • amyevans' digit-matching requirement — Parent cards only filtered when a child has matching card type AND digits.
  • amyevans' normalizeCardName concern — Fixed; both getAmexDirectParentCardNames and filterAmexDirectParentCard normalize names.
  • Previously assigned parent cards — Phase 1 keeps them visible so admins can manage/unassign; filtering only applies to unassigned cards.
  • Fake test data — All real card data replaced with fake names/numbers.

All CI checks are passing.

@MelvinBot
Copy link
Contributor Author

The only failing check is the PR Reviewer Checklist (checklist), which reports "0 out of 57 checklist items" completed. This is not a code issue — it fails because a reviewer has posted the reviewer checklist but hasn't checked off the items yet.

All code-related checks (ESLint, typecheck, Prettier, tests, builds, spellcheck, signed commits, etc.) are passing. No code fix is needed here — a reviewer just needs to complete their checklist.

@MelvinBot
Copy link
Contributor Author

The only failing check is the PR Reviewer Checklist — a reviewer posted their checklist but hasn't checked off all the items yet (0 out of 57 completed). This is not a code issue and can't be fixed with a push.

All code checks are passing: ESLint, typecheck, Prettier, tests (all 8 shards), builds (all 4), spellcheck, signed commits, CLA, unused styles, storybook, perf-tests, and codecov.

@MelvinBot
Copy link
Contributor Author

The only failing check is the PR Reviewer Checklist (reviewerChecklist.js), which reports 0 out of 57 checklist items completed. This is not a code issue — it requires a reviewer to complete their checklist by checking all the boxes in their review comment. No code fix is needed.

@amyevans
Copy link
Contributor

amyevans commented Feb 26, 2026

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Android: mWeb Chrome
iOS: HybridApp
iOS: mWeb Safari
MacOS: Chrome / Safari

main:
main

branch:
branch

@MelvinBot
Copy link
Contributor Author

The only failing check is PR Reviewer Checklist — a reviewer posted their checklist but hasn't checked all the boxes yet (0 out of 57 items completed). All code checks (tests, typecheck, ESLint, Prettier, builds, signed commits, etc.) are passing.

This is not a code issue — it requires the reviewer to complete their checklist. No code fix is needed.

@MelvinBot
Copy link
Contributor Author

The only failing check is PR Reviewer Checklist (checklist), which reports 0 out of 57 items completed. This is not a code or CI issue — it requires the reviewer to complete their checklist by checking off each item. All code-related checks (ESLint, typecheck, tests, builds, Prettier, etc.) are passing.

@MelvinBot
Copy link
Contributor Author

The only failing check is the PR Reviewer Checklist (checklist), which requires a human reviewer to complete their checklist (0 out of 57 items checked). This is not a code issue and cannot be fixed with a code change.

All CI checks are passing: ESLint, Prettier, typecheck, all 8 test jobs, builds, spellcheck, signed commits, CLA, and security scans.

@amyevans
Copy link
Contributor

Mkay, the checklist failing is a bug (I opened a new issue for it here: https://github.com/Expensify/Expensify/issues/604937) but for now I'm just going to manually edit Melvin's comment in #82448 (comment) to remove the checklist mention

@amyevans
Copy link
Contributor

Checks are passing now. Code LGTM, but @fedirjh @chrispader please review. I will merge tomorrow if y'all are happy with it!

Copy link
Contributor

@fedirjh fedirjh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@amyevans amyevans merged commit ddd82df into main Feb 27, 2026
34 of 49 checks passed
@amyevans amyevans deleted the claude-filterAmexParentCard branch February 27, 2026 20:59
@github-actions
Copy link
Contributor

🚧 @amyevans has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

OSBotify commented Mar 2, 2026

🚀 Deployed to staging by https://github.com/amyevans in version: 9.3.28-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@m-natarajan
Copy link

@carlosmiceli @amyevans @heyjennahay Can this one please be tested internally, Currently we are blocked from using Amex credentials due to 2FA authentication, Reference here

@carlosmiceli
Copy link
Contributor

Yes, I can test it tomorrow.

@carlosmiceli
Copy link
Contributor

@m-natarajan just checked, works great.

@amyevans
Copy link
Contributor

amyevans commented Mar 3, 2026

@carlosmiceli thanks for QAing! can you check it off the list in #83947?

@OSBotify
Copy link
Contributor

OSBotify commented Mar 4, 2026

🚀 Deployed to staging by https://github.com/amyevans in version: 9.3.30-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify
Copy link
Contributor

OSBotify commented Mar 4, 2026

🚀 Deployed to production by https://github.com/blimpich in version: 9.3.30-3 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants