Skip to content

Add Next button to company card assignee step instead of tap-to-advance (redo with regression fixes) - #98220

Draft
MelvinBot wants to merge 1 commit into
mainfrom
claude-assigneeStepNextButtonRedo
Draft

Add Next button to company card assignee step instead of tap-to-advance (redo with regression fixes)#98220
MelvinBot wants to merge 1 commit into
mainfrom
claude-assigneeStepNextButtonRedo

Conversation

@MelvinBot

Copy link
Copy Markdown
Contributor

Explanation of Change

This re-applies PR #97259 (reverted by #97501) with fixes for the two regressions that caused the revert, so the improvement can safely ship this time.

Original change (re-applied): The "Choose the cardholder" step (AssigneeStep) submitted and navigated immediately on row tap, with no confirm/Next button, and it auto-focused/highlighted a row so it looked pre-selected (most obvious in a single-member workspace). Users waited for a Next button that never appeared and had to re-tap the seemingly-selected row. This makes AssigneeStep match the sibling CardSelectionStep pattern and the approved design mocks:

  • No cardholder is pre-selected when the step opens for a brand-new assignment — selection is tracked in local state and drives the row highlight. Re-entering the step for an assignment that already has a cardholder (edit flow / header-back from Confirmation) intentionally pre-selects that saved cardholder, mirroring CardSelectionStep.
  • Tapping a cardholder only selects them (no auto-advance).
  • A footer Next button confirms the selection and runs the existing submit logic, so routing for an existing member, the invite-new-member flow, and the "assignee unchanged" fast-path is unchanged.
  • Pressing Next with nothing selected shows a "Please select a cardholder to continue" error instead of navigating.

Regression fixes added on top of #97259:

  • Company Card - Next button is disabled while offline in "choose the cardholder" step #97426 — Next button disabled offline. The new FormAlertWithSubmitButton was force-disabled offline (its default), even though selecting a cardholder is a local-state-only step with no network call. Added enabledWhenOffline so Next stays usable offline and the empty-selection error is reachable.
  • Company cards - Different back button behavior when returning from invite page on confirm page #97410 — wrong back-button behavior after the invite sub-flow. InviteNewMemberStep's back handler unconditionally reset isEditing to false. When the user reached the invite step while editing the cardholder from Confirmation, backing out then made AssigneeStep's own back dismiss the whole RHP instead of returning to Confirmation. The handler no longer forces isEditing: false — omitting the field leaves the Onyx.merge value untouched, so an in-progress edit keeps isEditing: true (back returns to Confirmation) while a fresh assign flow is unaffected (already false throughout).

Added a cardholder-specific error string across all locales and unit tests covering no-auto-advance, Next-navigates, empty-selection-error, saved-cardholder pre-selection, plain-back vs. edit-back navigation, and a new offline regression test for #97426.

Fixed Issues

$ #97224
PROPOSAL: #97224 (comment)

Tests

// TODO: The human co-author must fill out the tests you ran before marking this PR as "ready for review". Suggested coverage: (1) open Assign card on a multi-member workspace → no cardholder pre-selected, Next shown; (2) tap a cardholder → row highlights, no auto-advance; (3) Next with no selection → "Please select a cardholder to continue"; (4) regression #97410 → edit the cardholder from Confirmation, type a non-member email, Next into invite, back, back → returns to Confirmation (does not dismiss the RHP); (5) regression #97426 → offline, Next is enabled.

  • Verify that no errors appear in the JS console

Offline tests

Selection state and the empty-selection error are handled entirely in local state, so the step works offline (regression #97426):

  1. Turn off your network connection.
  2. Open the "Choose the cardholder" step and confirm the Next button is enabled.
  3. Press Next without a selection and verify the "Please select a cardholder to continue" error appears.
  4. Tap a cardholder and press Next; verify the flow advances.

QA Steps

// TODO: These must be filled out, or the issue title must include "[No QA]."

  • 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 followed proper code patterns (see Reviewing the code)
    • 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 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)
  • 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)
  • 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.
  • 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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

Re-applies #97259 (reverted by #97501) and fixes the two regressions that
caused the revert:
- #97426: add enabledWhenOffline so the Next button is usable offline
- #97410: stop InviteNewMemberStep's back handler from clobbering isEditing,
  which broke back navigation to Confirmation after the invite sub-flow

Co-authored-by: Abdelrahman Khattab <abzokhattab@users.noreply.github.com>
@OSBotify

Copy link
Copy Markdown
Contributor

🦜 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 diff
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 546fed3eebd..85a70289cce 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -5896,7 +5896,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             directFeed: 'Direktfeed',
             whoNeedsCardAssigned: 'Wer braucht eine zugewiesene Karte?',
             chooseTheCardholder: 'Wähle den Karteninhaber',
-            pleaseSelectACardholder: 'Bitte wähle einen Karteninhaber aus, um fortzufahren',
+            pleaseSelectACardholder: 'Bitte wählen Sie eine Karteninhaberin oder einen Karteninhaber aus, um fortzufahren',
             chooseCard: 'Wähle eine Karte',
             chooseCardFor: (assignee: string) => `Wähle eine Karte für <strong>${assignee}</strong>. Du findest die gesuchte Karte nicht? <concierge-link>Gib uns Bescheid.</concierge-link>`,
             noActiveCards: 'Keine aktiven Karten in diesem Feed',
diff --git a/src/languages/el.ts b/src/languages/el.ts
index 3a1372b2b77..e566e43dd95 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -320,7 +320,6 @@ const translations: TranslationDeepObject<typeof en> = {
         automatic: 'Αυτόματο',
         showing: 'Εμφανίζονται',
         of: 'του',
-        // @context Carousel pagination counter showing the current item's position out of the total (e.g. "3 of 50").
         currentOfTotal: ({current, total}: {current: number; total: number}) => `${current} από ${total}`,
         default: 'Προεπιλογή',
         update: 'Ενημέρωση',
@@ -6017,7 +6016,7 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ
             directFeed: 'Άμεση ροή',
             whoNeedsCardAssigned: 'Ποιος χρειάζεται να του ανατεθεί κάρτα;',
             chooseTheCardholder: 'Επιλέξτε τον κατόχο κάρτας',
-            pleaseSelectACardholder: 'Παρακαλώ επιλέξτε έναν κάτοχο κάρτας για να συνεχίσετε',
+            pleaseSelectACardholder: 'Παρακαλώ επιλέξτε έναν κατόχο κάρτας για να συνεχίσετε',
             chooseCard: 'Επιλέξτε μια κάρτα',
             chooseCardFor: (assignee: string) =>
                 `Επιλέξτε μια κάρτα για τον/την <strong>${assignee}</strong>. Δεν μπορείτε να βρείτε την κάρτα που αναζητάτε; <concierge-link>Ενημερώστε μας.</concierge-link>`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 5a6380394bc..704f56cb0f0 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -5766,7 +5766,7 @@ ${amount} para ${merchant} - ${date}`,
             directFeed: 'Fuente directa',
             whoNeedsCardAssigned: '¿Quién necesita una tarjeta?',
             chooseTheCardholder: 'Elige el titular de la tarjeta',
-            pleaseSelectACardholder: 'Selecciona un titular de la tarjeta para continuar',
+            pleaseSelectACardholder: 'Selecciona un titular de tarjeta para continuar',
             chooseCard: 'Elige una tarjeta',
             chooseCardFor: (assignee) => `Elige una tarjeta para <strong>${assignee}</strong>. ¿No encuentras la tarjeta que buscas? <concierge-link>Avísanos.</concierge-link>`,
             noActiveCards: 'No hay tarjetas activas en este feed',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 090e305f0ed..d81e9ee5e9f 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -5801,7 +5801,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             directFeed: 'ダイレクトフィード',
             whoNeedsCardAssigned: '誰にカードを割り当てる必要がありますか?',
             chooseTheCardholder: 'カード名義人を選択',
-            pleaseSelectACardholder: '続行するにはカード名義人を選択してください',
+            pleaseSelectACardholder: '続行するカード保有者を選択してください',
             chooseCard: 'カードを選択',
             chooseCardFor: (assignee: string) =>
                 `<strong>${assignee}</strong> に割り当てるカードを選択してください。お探しのカードが見つかりませんか?<concierge-link>お知らせください。</concierge-link>`,

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

View workflow run

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

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

Files with missing lines Coverage Δ
src/CONST/index.ts 94.81% <ø> (ø)
...space/companyCards/assignCard/ConfirmationStep.tsx 84.61% <ø> (+4.39%) ⬆️
...ce/companyCards/assignCard/InviteNewMemberStep.tsx 0.00% <ø> (ø)
...workspace/companyCards/assignCard/AssigneeStep.tsx 79.24% <94.11%> (+19.69%) ⬆️
... and 12 files with indirect coverage changes

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 I looked into the failing checks. None are caused by this PR, so there's nothing to fix in the code. All JS/TS checks pass (typecheck, ESLint, Jest, Storybook, React Compiler, Knip, unused styles, spellcheck, formatting, translations, and Reassure perf tests). This PR only touches .ts/.tsx files.

The four red checks break down as:

Unrelated iOS build failures (infra / dependency, not this PR):

  • Remote Build iOS / build (Expensify Dev, Debug, true)job log. CocoaPods install failed downloading the prebuilt React Native artifact: curl: (56) The requested URL returned error: 401 for react-native-artifacts-0.86.0-1-reactnative-core-debug.tar.gz. This is a transient auth flake against the artifact registry (the other artifacts downloaded fine with 200s) — not something a code change here can fix.
  • Remote Build iOS / build (New Expensify Dev, DebugDevelopment, false)job log. A Swift compile error inside a dependency: node_modules/expo-modules-core/ios/Core/Events/EventEmitter.swift:52 (and :79): error: sending 'emitter' risks causing data races. This is a Swift 6 concurrency error in expo-modules-core, unrelated to the TypeScript changes in this PR.

Expected non-blocking checks:

  • PR Author Checklist / checklist — the author checklist/test sections in the PR body still need to be filled out by the human co-author (the body has // TODO placeholders for the Tests/QA Steps and the checkboxes are unchecked).
  • Check independent approval — waiting on peer review/approval.

Recommendation: Re-run the two iOS build jobs (the 401 is likely transient). If the expo-modules-core Swift error persists, it's an environment/dependency issue affecting native iOS builds broadly, not this change — worth confirming it reproduces on main. I did not push any commits since there's no code fix to make here.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 I tried to record the "Choose the cardholder" flow on web to populate the empty Screenshots/Videos section, but I couldn't reach that step in the automated test environment — so I have no verifying screenshots/videos of the actual fix to add.

Why: the throwaway test account has no workspace with a connected company-card feed (and members), which is the precondition for the Assign flow. The only way to create one from a fresh account is Company cards → Add cards (BYOC), and that immediately hits a "Validate your account" magic-code screen that I can't clear. So none of the four checks — no pre-selection + Next shown, tap-selects-without-advancing, empty-selection error, Next advances — could be exercised.

What I got before the block Company cards page for new workspace - only BYOC Add cards option, no existing feed Validate your account security-code prompt shown after clicking Add cards

To get real screenshots/videos here, the flow needs a test account with an already-connected company-card feed that has members (or a validated account). If you have such an account, the human co-author can run the steps in the PR's Tests section and drop the captures into the Screenshots/Videos section. Happy to re-run if the environment is seeded — reply @MelvinBot retry.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Nothing has changed since my previous analysis — the same checks are failing on the same CI run (the two iOS build jobs have not re-run, and there's no new commit on the branch).

tl;dr — there's still no code fix to make here. All JS/TS checks and Reassure perf tests pass; this PR only touches .ts/.tsx files. The four red checks are:

  • Remote Build iOS / build (Expensify Dev, Debug, true) — transient CocoaPods 401 fetching a prebuilt React Native artifact (infra/auth flake).
  • Remote Build iOS / build (New Expensify Dev, DebugDevelopment, false) — a Swift 6 data-race compile error inside a dependency (node_modules/expo-modules-core/.../EventEmitter.swift), not touchable by this PR.
  • PR Author Checklist / checklist and Check independent approval — expected non-blocking checks (human checklist still to be filled out; awaiting peer review).

To move this forward: re-run the two Remote Build iOS jobs (the 401 is likely transient). If the expo-modules-core Swift error persists after a fresh run, it's an environment/dependency issue affecting native iOS builds broadly — worth confirming it reproduces on main rather than expecting a change in this PR. I did not push any commits since there's nothing to fix in the code.

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.

3 participants