Skip to content

Auto-create workspace for Track signups during onboarding#85330

Open
MelvinBot wants to merge 17 commits intomainfrom
claude-autoCreateWorkspaceForTrackSignups
Open

Auto-create workspace for Track signups during onboarding#85330
MelvinBot wants to merge 17 commits intomainfrom
claude-autoCreateWorkspaceForTrackSignups

Conversation

@MelvinBot
Copy link
Contributor

@MelvinBot MelvinBot commented Mar 16, 2026

Explanation of Change

For PERSONAL_SPEND users, instead of navigating to the optional workspace creation screens (OnboardingWorkspaceOptional → OnboardingWorkspaceConfirmation → OnboardingWorkspaceInvite), this change silently auto-creates a workspace during onboarding and completes it immediately.

This addresses the problem that ~67% of Track users skip the optional workspace creation step, ending up without a workspace, categories, or reports — all of which are required for the Track use case.

What happens now for PERSONAL_SPEND users:

  1. On the Personal Details screen (public domain users) or the Purpose screen (private domain users), when PERSONAL_SPEND is selected:

    • A workspace is auto-created with the name "{firstName}'s Workspace"
    • completeOnboarding() is called with engagementChoice: TRACK_WORKSPACE
    • The user navigates directly to onboarding completion (skipping all 3 optional workspace screens)
  2. TRACK_WORKSPACE users continue to navigate to the workspace screens as before (no change).

The workspace auto-creation logic is extracted into a shared useAutoCreateTrackWorkspace hook used by both BaseOnboardingPersonalDetails and BaseOnboardingPurpose.

Fixed Issues

$ #85228

Tests

  • Verified ESLint passes on the modified files
  • Verified the code follows the same workspace creation pattern used in BaseOnboardingWorkspaceOptional.tsx

Manual test steps:

  1. Sign up as a new user (public domain email)
  2. Select "Track" (PERSONAL_SPEND) as onboarding purpose
  3. Enter first name and last name on the Personal Details screen
  4. Press Continue
  5. Verify a workspace is automatically created (named "{firstName}'s Workspace")
  6. Verify you are navigated directly to the app (skipping workspace naming and invite screens)
  7. Verify the workspace has categories enabled, workflows enabled, and reimbursement disabled

Private domain test steps:

  1. Sign up as a new user with a private domain email
  2. Enter your name on the Personal Details screen and proceed through the private domain flow
  3. On the Purpose screen, select "Track and budget expenses" (PERSONAL_SPEND)
  4. Verify a workspace is automatically created and you skip the workspace creation screens
  5. Verify you are navigated directly to the app

Regression test:

  1. Sign up and select a non-PERSONAL_SPEND purpose
  2. Verify the existing onboarding flow is unchanged
  3. Sign up and select TRACK_WORKSPACE
  4. Verify the user is still navigated to the workspace optional screen as before
  • Verify that no errors appear in the JS console

Offline tests

  1. Sign up and proceed through onboarding in offline mode
  2. Select "Track" (PERSONAL_SPEND) as onboarding purpose
  3. Verify the workspace creation is queued and completes when back online

QA Steps

  1. Sign up as a new user with a public domain email
  2. Select "Track and budget expenses" as onboarding purpose
  3. Enter name and press Continue
  4. Verify workspace is auto-created and workspace screens are skipped
  5. Repeat with a private domain email — verify the same behavior when selecting "Track and budget expenses" on the Purpose screen
  • 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 / Chrome
    • iOS / native
    • iOS / Safari
    • MacOS / Chrome / Safari
    • MacOS / Desktop
  • 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 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 the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
    • 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 verified the translation was requested/reviewed 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 approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • 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.js 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 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
    • If we are not using the full Onyx data that we loaded, I've added the proper selector in order to ensure the component only re-renders when the data it is using changes
      • 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(themeColors.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 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.
  • 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 author checklist, including those that don't apply to this PR.

Screenshots/Videosundefined

For PERSONAL_SPEND users, instead of navigating to the optional workspace
creation screens (which ~67% skip), silently auto-create a workspace
during the OnboardingPersonalDetails step with the user's first name
and complete onboarding immediately.

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot MelvinBot requested a review from a team March 16, 2026 06:36
@MelvinBot
Copy link
Contributor Author

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:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-autoCreateWorkspaceForTrackSignups
git checkout -b claude-autoCreateWorkspaceForTrackSignups upstream/claude-autoCreateWorkspaceForTrackSignups
git push -u origin claude-autoCreateWorkspaceForTrackSignups

Then you can close this PR and open a new one from your fork.

@codecov
Copy link

codecov bot commented Mar 16, 2026

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.

Files with missing lines Coverage Δ
src/libs/actions/Policy/Policy.ts 46.52% <100.00%> (-0.31%) ⬇️
.../pages/OnboardingPurpose/BaseOnboardingPurpose.tsx 93.54% <0.00%> (-3.12%) ⬇️
...gPersonalDetails/BaseOnboardingPersonalDetails.tsx 87.75% <0.00%> (-3.74%) ⬇️
src/hooks/useAutoCreateTrackWorkspace.ts 50.00% <50.00%> (ø)
... and 8 files with indirect coverage changes

@jayeshmangwani
Copy link
Contributor

@MelvinBot, we’re still seeing the workspace creation option for private domain users.

Please check all cases where, after selecting Track and budget expenses, users are navigated to the optional workspace creation step. We want to auto-create a workspace for every user who selects Track and budget expenses during onboarding and skip this step entirely.

… Purpose screen

Private domain users who already had their name filled in were being
navigated to the workspace creation optional screen when selecting
Track and budget expenses. This bypassed the auto-create logic added
in PersonalDetails because private domain users go through a different
flow: PersonalDetails → Workspaces/PrivateDomain → Purpose, and the
Purpose screen was routing them to the WorkspaceOptional screen
instead of auto-creating the workspace.

Now the Purpose screen auto-creates the workspace and completes
onboarding directly for private domain PERSONAL_SPEND users, matching
the same pattern used in BaseOnboardingPersonalDetails.

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

I investigated all code paths where a user selecting "Track and budget expenses" (PERSONAL_SPEND) could be navigated to the optional workspace creation step. Here's what I found:

Root Cause: Private domain users follow a different onboarding flow: PersonalDetails → Workspaces/PrivateDomain → Purpose. By the time they reach the Purpose screen, their first name is already set in the form. When they selected PERSONAL_SPEND, the Purpose screen at BaseOnboardingPurpose.tsx:100-103 navigated them directly to ROUTES.ONBOARDING_WORKSPACE (the WorkspaceOptional screen), completely bypassing the auto-create logic added in BaseOnboardingPersonalDetails.tsx.

Fix: Replaced the navigation to the workspace optional screen with inline workspace auto-creation and onboarding completion logic in BaseOnboardingPurpose.tsx. This matches the same pattern used in BaseOnboardingPersonalDetails.tsx — creating a workspace named "{firstName}'s Workspace", calling completeOnboarding with TRACK_WORKSPACE engagement choice, and navigating directly to the app.

Scope check: I verified there are only two navigation paths to ROUTES.ONBOARDING_WORKSPACE:

  1. BaseOnboardingPurpose.tsx:102 — private domain PERSONAL_SPEND users → fixed in this commit
  2. BaseOnboardingPersonalDetails.tsx:194TRACK_WORKSPACE users (backend-only choice, not user-selectable as "Track and budget expenses") → not affected

…n the previous commit

The previous commit accidentally included 663 unrelated file changes
from a dirty working tree. This restores all files to their main
branch state except for the two intended onboarding files.

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing check: The previous commit accidentally included 663 unrelated file changes from a dirty working tree, which caused test failures in tests/unit/canEditFieldOfMoneyRequestTest.ts (among other regressions). Restored all files to their main branch state, keeping only the two intended onboarding files (BaseOnboardingPersonalDetails.tsx and BaseOnboardingPurpose.tsx).

…spaceForTrackSignups

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing checks by merging main into the branch.

Root cause: The previous commit accidentally included ~665 unrelated file changes from a dirty working tree. While the fix commit (5a4acda) reverted those changes, the PR's merge base was still very old, causing GitHub to compute a massive diff (665 files). This caused:

  1. generateTranslations — failed because GitHub's API rejects diffs exceeding 300 files
  2. build (Deploy ExpensifyHelp) — Cloudflare API returned 504 (infrastructure/transient, unrelated to PR)
  3. Jest test failures (previous run) — the dirty commit had modified code that broke 2 tests in canEditFieldOfMoneyRequestTest.ts; already fixed by 5a4acda

Fix: Merged main into the branch, which updated the merge base and reduced the PR diff from 665 files down to just the 2 actual changed files (BaseOnboardingPersonalDetails.tsx and BaseOnboardingPurpose.tsx).

@jayeshmangwani
Copy link
Contributor

@MelvinBot Please mark PR as Ready for review

@MelvinBot
Copy link
Contributor Author

I attempted to mark this PR as "Ready for review" but don't have the required permissions to execute gh pr ready. You can mark it yourself by running:

gh pr ready 85330 --repo Expensify/App

Or by clicking the "Ready for review" button on the PR page.

@jayeshmangwani
Copy link
Contributor

@MelvinBot mark as ready for review

@MelvinBot MelvinBot marked this pull request as ready for review March 19, 2026 11:12
@MelvinBot MelvinBot requested a review from a team as a code owner March 19, 2026 11:12
@MelvinBot
Copy link
Contributor Author

PR has been marked as ready for review.

@melvin-bot melvin-bot bot requested a review from jayeshmangwani March 19, 2026 11:12
@melvin-bot
Copy link

melvin-bot bot commented Mar 19, 2026

@jayeshmangwani 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]

@melvin-bot melvin-bot bot requested review from heyjennahay and removed request for a team March 19, 2026 11:12

if (onboardingPurposeSelected === CONST.ONBOARDING_CHOICES.PERSONAL_SPEND || onboardingPurposeSelected === CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE) {
if (onboardingPurposeSelected === CONST.ONBOARDING_CHOICES.PERSONAL_SPEND) {
updateDisplayName(firstName, lastName, formatPhoneNumber, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? '');
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)

This ~45-line block (policy lookup, createWorkspace, completeOnboardingReport, setOnboardingAdminsChatReportID/setOnboardingPolicyID, and navigateAfterOnboardingWithMicrotaskQueue) is nearly identical to the block added in BaseOnboardingPurpose.tsx. The only differences are the source of firstName/lastName (from form values vs. personalDetailsForm) and onboardingPurposeSelected vs. choice. This duplication increases maintenance overhead and bug risk — a fix applied to one location could easily be missed in the other.

Extract a shared helper function (e.g., autoCreateWorkspaceAndCompleteOnboarding) in a shared module (such as src/libs/actions/Onboarding.ts or a new utility) that accepts the differing parameters:

function autoCreateWorkspaceAndCompleteOnboarding({
    firstName,
    lastName,
    onboardingPurposeSelected,
    // ... other varying params
}: AutoCreateWorkspaceParams) {
    const paidGroupPolicy = Object.values(allPolicies ?? {}).find(...);
    const shouldCreateWorkspace = !onboardingPolicyID && !paidGroupPolicy;
    // ... createWorkspace, completeOnboarding, navigation ...
}

Then call this helper from both BaseOnboardingPersonalDetails and BaseOnboardingPurpose.


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.

Addressed in the latest commit. Extracted the shared workspace-creation-and-onboarding-completion logic into a new useAutoCreateTrackWorkspace hook (src/hooks/useAutoCreateTrackWorkspace.ts). Both BaseOnboardingPersonalDetails and BaseOnboardingPurpose now call autoCreateTrackWorkspace(firstName, lastName, purposeSelected) instead of duplicating the ~45-line block.

if (isPrivateDomainAndHasAccessiblePolicies && personalDetailsForm?.firstName) {
if (choice === CONST.ONBOARDING_CHOICES.PERSONAL_SPEND) {
Navigation.navigate(ROUTES.ONBOARDING_WORKSPACE.getRoute(route.params?.backTo));
const paidGroupPolicy = Object.values(allPolicies ?? {}).find((policy) => isPaidGroupPolicy(policy) && isPolicyAdmin(policy, session?.email));
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)

This ~45-line block (policy lookup, createWorkspace, completeOnboarding, setOnboardingAdminsChatReportID/setOnboardingPolicyID, and navigateAfterOnboardingWithMicrotaskQueue) is nearly identical to the block added in BaseOnboardingPersonalDetails.tsx. Duplicating this complex business logic across two UI components makes it easy to introduce divergence when one side is updated but the other is not.

Extract the shared workspace-creation-and-onboarding-completion logic into a reusable helper function and call it from both locations. See the comment on BaseOnboardingPersonalDetails.tsx for a suggested approach.


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.

Addressed in the latest commit. Extracted the shared workspace-creation-and-onboarding-completion logic into a new useAutoCreateTrackWorkspace hook (src/hooks/useAutoCreateTrackWorkspace.ts). Both BaseOnboardingPersonalDetails and BaseOnboardingPurpose now call autoCreateTrackWorkspace(firstName, lastName, purposeSelected) instead of duplicating the ~45-line block.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 98d0ab2921

ℹ️ 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".

updateDisplayName(firstName, lastName, formatPhoneNumber, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? '');

const paidGroupPolicy = Object.values(allPolicies ?? {}).find((policy) => isPaidGroupPolicy(policy) && isPolicyAdmin(policy, session?.email));
const shouldCreateWorkspace = !onboardingPolicyID && !paidGroupPolicy;

Choose a reason for hiding this comment

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

P1 Badge Honor restricted policy-creation before auto-creating workspace

This PERSONAL_SPEND path now auto-creates a workspace whenever !onboardingPolicyID && !paidGroupPolicy, but it never checks the domain security restriction (enableRestrictedPolicyCreation). In onboarding we previously enforced that restriction by gating workspace creation in BaseOnboardingWorkspaceOptional (!isRestrictedPolicyCreation), so restricted private-domain users are now forced into a create-workspace attempt they were previously blocked from. In practice that either creates an unauthorized workspace or fails the write while onboarding continues with an optimistic newPolicyID, which can leave onboarding/navigation state inconsistent for that user segment.

Useful? React with 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in the latest commit. The new useAutoCreateTrackWorkspace hook checks isRestrictedPolicyCreation from usePreferredPolicy() — when restricted, shouldCreateWorkspace is set to false, so workspace creation is skipped and onboarding completes with the existing onboardingPolicyID (or none).

@jayeshmangwani
Copy link
Contributor

@MelvinBot ,

  1. can you check this comments Auto-create workspace for Track signups during onboarding #85330 (comment) and Auto-create workspace for Track signups during onboarding #85330 (comment) , and update the code to use the unified function in BaseOnboardingPersonalDetails and BaseOnboardingPurpose for createWorkspace, completeOnboarding, and navigation?

  2. Also, for this one Auto-create workspace for Track signups during onboarding #85330 (comment), add a check for isRestrictedPolicyCreation, if the user can’t create policies, we shouldn’t auto-create the workspace.

…estrictedPolicyCreation check

- Created useAutoCreateTrackWorkspace hook that encapsulates the
  workspace creation, onboarding completion, and navigation logic
  for PERSONAL_SPEND users
- Both BaseOnboardingPersonalDetails and BaseOnboardingPurpose now
  call this shared hook instead of duplicating the ~45-line block
- Added isRestrictedPolicyCreation check: if the user's domain
  restricts policy creation, the workspace auto-creation is skipped
  (onboarding still completes without a workspace)

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot MelvinBot requested a review from a team as a code owner March 19, 2026 16:57
@MelvinBot
Copy link
Contributor Author

The ESLint failure (@typescript-eslint/prefer-nullish-coalescing in Policy.ts) was already fixed in the latest commit.

The build (developmentDebug, false) failure is unrelated to this PR — it's a CI infrastructure issue where node_modules/expo/scripts/autolinking.gradle doesn't exist. The other Android build variant (build (Debug, true)) from the same workflow run passed successfully, confirming this isn't caused by the PR's code changes. This should resolve on re-run.

@MelvinBot
Copy link
Contributor Author

The failing build (developmentDebug, false) check is unrelated to this PR.

Analysis: The error is Could not read script 'node_modules/expo/scripts/autolinking.gradle' as it does not exist — an Android build infrastructure issue with a missing expo autolinking gradle script. This PR only modifies TypeScript files (src/hooks/, src/libs/actions/, src/pages/), none of which affect Android build configuration.

Evidence: The same Build and deploy apps for testing workflow is also currently failing on the main branch, confirming this is a pre-existing issue.

The only other failing check is checklist, which is the PR Author Checklist and not a code issue.

@jayeshmangwani
Copy link
Contributor

@MelvinBot Let’s define displayName in useAutoCreateTrackWorkspace.ts, since same value used in PersonalDetails.updateDisplayName, and pass it as displayNameOverride instead of only firstName.

const displayName = createDisplayName(
        session?.email ?? '',
        {
            firstName,
            lastName,
        },
        formatPhoneNumber,
    );

@MelvinBot
Copy link
Contributor Author

I have failed to help you. I let you down and for that I am sorry. Please try again later. This may be due to a Claude outage (check here).

Failure details: https://github.com/Expensify/Expensify/actions/runs/23351895310

@jayeshmangwani
Copy link
Contributor

@MelvinBot Let’s define displayName in useAutoCreateTrackWorkspace.ts, since same value used in PersonalDetails.updateDisplayName, and pass it as displayNameOverride instead of only firstName.

const displayName = createDisplayName(
        session?.email ?? '',
        {
            firstName,
            lastName,
        },
        formatPhoneNumber,
    );

Compute displayName via createDisplayName (which considers both
firstName and lastName, falling back to formatted email) and pass it
as displayNameOverride to generateDefaultWorkspaceName. This aligns
with how PersonalDetails.updateDisplayName computes the same value.

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Done! I've updated useAutoCreateTrackWorkspace.ts to compute displayName using createDisplayName (same as PersonalDetails.updateDisplayName uses) and pass it as displayNameOverride to generateDefaultWorkspaceName instead of just firstName.

Changes:

  • Imported createDisplayName from @libs/PersonalDetailsUtils and useLocalize for formatPhoneNumber
  • Compute displayName inside the callback: createDisplayName(session?.email ?? '', {firstName, lastName}, formatPhoneNumber)
  • Pass displayName to generateDefaultWorkspaceName instead of firstName

This ensures the workspace name uses the full display name (first + last, falling back to formatted email) — consistent with how the display name is computed elsewhere.

Copy link
Contributor

@jayeshmangwani jayeshmangwani left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Fixed the failing Prettier check: sorted imports in src/hooks/useAutoCreateTrackWorkspace.ts (useLocalize and useOnboardingMessages were out of alphabetical order).

The two Android/iOS build failures (developmentDebug and DebugDevelopment) are unrelated to this PR — they fail due to a missing expo/scripts/autolinking.gradle file, which is an infrastructure/build-system issue not caused by the changes in this PR.

@MelvinBot
Copy link
Contributor Author

The failing build (developmentDebug, false) check is unrelated to this PR's changes. The CI runner timed out trying to download the actions/setup-java GitHub Action:

Action 'https://api.github.com/repos/actions/setup-java/tarball/...' download has timed out.
Error: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.

This is a transient GitHub infrastructure issue. Re-running the failed check should resolve it.

@MelvinBot
Copy link
Contributor Author

The failing checks are unrelated to this PR's changes.

build (developmentDebug, false) — Android: Failed because the actions/setup-java action download timed out repeatedly (HttpClient.Timeout of 100 seconds elapsing). This is a GitHub Actions infrastructure issue — the job couldn't even set up Java.

build (New Expensify Dev, DebugDevelopment, false) — iOS: No compilation errors related to this PR's TypeScript changes. The same build jobs are also failing on main right now, confirming this is an infrastructure-level issue.

Evidence: This PR only modifies 4 TypeScript files (useAutoCreateTrackWorkspace.ts, Policy.ts, BaseOnboardingPersonalDetails.tsx, BaseOnboardingPurpose.tsx), none of which affect native Android/iOS builds. All code-related checks (ESLint, typecheck, all 8 test jobs, prettier, storybook) passed.

These should resolve on a re-run once the infrastructure stabilizes.

@MelvinBot
Copy link
Contributor Author

The failing checks are unrelated to this PR's changes.

This PR modifies only TypeScript files:

  • src/hooks/useAutoCreateTrackWorkspace.ts
  • src/libs/actions/Policy/Policy.ts
  • src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx
  • src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx

Failing checks:

  1. build (developmentDebug, false) — Android build failed because GitHub Actions timed out downloading the actions/setup-java action (infrastructure issue, not code-related).

  2. build (New Expensify Dev, DebugDevelopment, false) — iOS build failed with Swift compiler errors in ios/AppDelegate.swift: ambiguous implicit access level for import of 'ExpoModulesCore' and 'Expo'. This is a Xcode 26.2 / Swift 6 compatibility issue in native iOS code — completely unrelated to the TypeScript changes in this PR.

Both failures should resolve on re-run or are pre-existing issues affecting the main branch CI.

@MelvinBot
Copy link
Contributor Author

The failing build checks are unrelated to this PR's changes.

Analysis:

This PR only modifies 4 TypeScript files:

  • src/hooks/useAutoCreateTrackWorkspace.ts
  • src/libs/actions/Policy/Policy.ts
  • src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx
  • src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx

The two failing checks are native platform builds:

  1. build (developmentDebug, false) (Android): Fails with Could not read script '/home/runner/_work/App/App/node_modules/expo/scripts/autolinking.gradle' as it does not exist. — This is a CI environment issue where node_modules weren't properly installed for the Android Gradle build. Not related to any TypeScript source changes.

  2. build (New Expensify Dev, DebugDevelopment, false) (iOS): The failure log shows only CocoaPods native dependency compilation (RCT-Folly headers, Airship SDK Swift compilation). No errors related to the changed TypeScript files.

All code-related checks (ESLint, TypeScript typecheck, tests, prettier, storybook) are passing. These native build failures appear to be CI infrastructure/flaky issues. Re-running the failing checks should resolve them.

@lakchote
Copy link
Contributor

@jayeshmangwani could you please tell Melvin to merge main to solve the stale workflow failures?

@jayeshmangwani
Copy link
Contributor

@MelvinBot Please merge the latest main to branch to verify if the remote build failed checks are resolved.

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Merged the latest main into this branch (228 files changed, no conflicts). The CI checks should re-run now — let's see if the build failures are resolved.

@jayeshmangwani
Copy link
Contributor

@lakchote iOS remote build check is still failing, after merging main.

@MelvinBot
Copy link
Contributor Author

The failing check build (New Expensify Dev, DebugDevelopment, false) is unrelated to this PR.

Analysis: This PR only modifies TypeScript/React files (useAutoCreateTrackWorkspace.ts, Policy.ts, BaseOnboardingPersonalDetails.tsx, BaseOnboardingPurpose.tsx). The failure is in the iOS native build step (Rock Remote Build - iOS), which compiles native Pods (AppAuth, Airship, etc.) that are not affected by these changes. The build log is truncated and does not reveal a specific compilation error. Additionally, the same workflow recently failed on the main branch (run 23358003619), indicating an infrastructure/flaky issue.

Evidence: Files changed are all .ts/.tsx — no native iOS code was modified. The build log shows only deprecation warnings in third-party Pods before cutting off.

Recommendation: Re-run the failing check. If it continues to fail, this is a pre-existing iOS build infrastructure issue that should be investigated separately.

@lakchote
Copy link
Contributor

@MelvinBot merge latest main

@MelvinBot
Copy link
Contributor Author

I can only make code changes when directed by the PR author, an assignee, or an existing co-author. To have me merge main into this branch, the PR assignee (jayeshmangwani) should reply with a request tagging me.

@jayeshmangwani
Copy link
Contributor

@MelvinBot merge latest main

…spaceForTrackSignups

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@MelvinBot
Copy link
Contributor Author

Merged latest main into this branch. The merge was clean with no conflicts.

const {isRestrictedPolicyCreation} = usePreferredPolicy();
const hasActiveAdminPolicies = useHasActiveAdminPolicies();
const {onboardingMessages} = useOnboardingMessages();
// We need to use isSmallScreenWidth, see navigateAfterOnboarding function comment
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// We need to use isSmallScreenWidth, see navigateAfterOnboarding function comment
// We need to use isSmallScreenWidth, see navigateAfterOnboarding function comment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done — added the blank line and expanded the comment with a brief explanation of why isSmallScreenWidth is used here: navigateAfterOnboarding relies on actual device screen width to handle navigation stack differences (on small screens, removing OnboardingModalNavigator redirects to HOME, requiring explicit navigation to the last accessed report).

const hasActiveAdminPolicies = useHasActiveAdminPolicies();
const {onboardingMessages} = useOnboardingMessages();
// We need to use isSmallScreenWidth, see navigateAfterOnboarding function comment
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
Copy link
Contributor

Choose a reason for hiding this comment

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

Explain why you prefer to use isSmallScreenWidth over shouldUseNarrowLayout here

Copy link
Contributor

Choose a reason for hiding this comment

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

@MelvinBot Can you make the update suggested in this comment #85330 (comment) and include a brief explanation for using isSmallScreenWidth here?

…eateTrackWorkspace

Co-authored-by: Jayesh Mangwani <jayeshmangwani@users.noreply.github.com>
@jayeshmangwani
Copy link
Contributor

@lakchote comments updated.

Copy link
Contributor

@heyjennahay heyjennahay left a comment

Choose a reason for hiding this comment

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

Product change LGTM

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

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

5 participants