v2 onboarding: dedicated verify step and upgrade-free-trial as the last step (#22303)
https://github.com/user-attachments/assets/b1ee4f77-c6d7-4638-b9f1-dd801d1cc0db Completes the onboarding-v2 flow: a dedicated verify step, the reordering that makes the plan step come last, and the upgrade-free-trial page itself. ## Verify step (`/verify-v2`) After the cross-domain token exchange, v2 sign-ups land on a clean `BlankLayout` "Verifying your email" screen (fading Twenty logo) instead of the v1 `AuthModal` flashing over the background mock. The redirect target is chosen from `isOnboardingV2` (read from the Jotai store at redirect time). The pulsing logo is extracted into a shared `OnboardingPulsingLogo`, reused by the workspace-activation loader. `/verify-v2` joins the same exempt lists as `/verify` (ongoing-creation guard, metadata gater, apollo unauthenticated handler, captcha, page title) — intentionally not `useShowAuthModal`, which is what drops the modal. ## Plan step is now last `getOnboardingStatus` checks `PLAN_REQUIRED` after invite-team instead of first, so onboarding runs workspace activation → email → profile → invite → plan. This is what lets the upgrade step be reached as the final step instead of gating right after sign-up. Applies to both v1 and v2 (same order). ## Upgrade free trial page (`PlanRequiredV2` → `ChooseYourPlanV2` / `UpgradeFreeTrial`) The final step, full-screen under `BlankLayout` via `OnboardingV2Layout`, matching the Figma (billing card with the Stripe form, the "Basic / without credit card" option, trial + credits pills). Reuses the v1 `ChooseYourPlanContent` billing logic (`SubscriptionPaymentForm`, `useHandleCheckoutSession`). The "+N free credits" reward comes from `clientConfig.onboarding.upgradeCreditsReward` (sourced from `BILLING_FREE_WORKFLOW_CREDITS_FOR_TRIAL_PERIOD_WITH_CREDIT_CARD`). ## Also Fixes a latent staleness in the Apollo `onUnauthenticatedError` handler — it captured `location` from the memoized client, now read via a ref — so auth-path exemptions are correct after navigation. Note: the onboarding step order change affects v1 too (plan becomes its last step as well).
This commit is contained in:
+1
@@ -89,6 +89,7 @@ describe('ClientConfigController', () => {
|
||||
importContactsCreditsReward: 2,
|
||||
inviteTeamMaxCreditsReward: 9,
|
||||
inviteTeamCreditsRewardPerUser: 3,
|
||||
upgradeCreditsReward: 5,
|
||||
},
|
||||
isAttachmentPreviewEnabled: true,
|
||||
analyticsEnabled: false,
|
||||
|
||||
@@ -214,6 +214,8 @@ export class OnboardingConfig {
|
||||
inviteTeamMaxCreditsReward: number;
|
||||
|
||||
inviteTeamCreditsRewardPerUser: number;
|
||||
|
||||
upgradeCreditsReward: number;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
|
||||
+2
@@ -95,6 +95,7 @@ describe('ClientConfigService', () => {
|
||||
ONBOARDING_IMPORT_CONTACTS_CREDITS_REWARD: 2_000_000,
|
||||
ONBOARDING_INVITE_TEAM_MAX_CREDITS_REWARD: 9_000_000,
|
||||
ONBOARDING_INVITE_TEAM_CREDITS_REWARD_PER_USER: 3_000_000,
|
||||
BILLING_FREE_WORKFLOW_CREDITS_FOR_TRIAL_PERIOD_WITH_CREDIT_CARD: 5_000_000,
|
||||
IS_ATTACHMENT_PREVIEW_ENABLED: true,
|
||||
ANALYTICS_ENABLED: true,
|
||||
MESSAGING_PROVIDER_MICROSOFT_ENABLED: false,
|
||||
@@ -172,6 +173,7 @@ describe('ClientConfigService', () => {
|
||||
importContactsCreditsReward: 2,
|
||||
inviteTeamMaxCreditsReward: 9,
|
||||
inviteTeamCreditsRewardPerUser: 3,
|
||||
upgradeCreditsReward: 5,
|
||||
},
|
||||
isAttachmentPreviewEnabled: true,
|
||||
analyticsEnabled: true,
|
||||
|
||||
+5
@@ -235,6 +235,11 @@ export class ClientConfigService {
|
||||
'ONBOARDING_INVITE_TEAM_CREDITS_REWARD_PER_USER',
|
||||
),
|
||||
),
|
||||
upgradeCreditsReward: toDisplayCredits(
|
||||
this.twentyConfigService.get(
|
||||
'BILLING_FREE_WORKFLOW_CREDITS_FOR_TRIAL_PERIOD_WITH_CREDIT_CARD',
|
||||
),
|
||||
),
|
||||
},
|
||||
isAttachmentPreviewEnabled: this.twentyConfigService.get(
|
||||
'IS_ATTACHMENT_PREVIEW_ENABLED',
|
||||
|
||||
@@ -64,14 +64,6 @@ export class OnboardingService {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
await this.billingService.isSubscriptionIncompleteOnboardingStatus(
|
||||
workspace.id,
|
||||
)
|
||||
) {
|
||||
return OnboardingStatus.PLAN_REQUIRED;
|
||||
}
|
||||
|
||||
if (this.isWorkspaceActivationPending(workspace)) {
|
||||
return OnboardingStatus.WORKSPACE_ACTIVATION;
|
||||
}
|
||||
@@ -108,6 +100,14 @@ export class OnboardingService {
|
||||
return OnboardingStatus.INVITE_TEAM;
|
||||
}
|
||||
|
||||
if (
|
||||
await this.billingService.isSubscriptionIncompleteOnboardingStatus(
|
||||
workspace.id,
|
||||
)
|
||||
) {
|
||||
return OnboardingStatus.PLAN_REQUIRED;
|
||||
}
|
||||
|
||||
if (isBookOnboardingPending) {
|
||||
const calendarBookingPageId = this.twentyConfigService.get(
|
||||
'CALENDAR_BOOKING_PAGE_ID',
|
||||
|
||||
Reference in New Issue
Block a user