diff --git a/docs/release-control/v6/internal/subsystems/cloud-paid.md b/docs/release-control/v6/internal/subsystems/cloud-paid.md index a86190f033..bba23cf7d8 100644 --- a/docs/release-control/v6/internal/subsystems/cloud-paid.md +++ b/docs/release-control/v6/internal/subsystems/cloud-paid.md @@ -509,9 +509,9 @@ campaign badge copy, and annual summary text must come from the shared plan-definition owners rather than page-local string parsing or hardcoded retail amounts inside hosted pricing/signup screens. The same owner also holds shared hosted commercial copy such as page title, -introductory description, common Cloud inclusions, and setup-step guidance -when those facts describe the canonical offer rather than one page's local -layout. +introductory description, common Cloud inclusions, setup-step guidance, +hosted-signup section headings, and primary hosted-signup CTA labels when +those facts describe the canonical offer rather than one page's local layout. That same counted-unit boundary also owns the disclosure rule for retail copy: default billing and pricing surfaces should use concise monitored-system copy, while the full counted-unit definition appears only behind explicit disclosure diff --git a/frontend-modern/src/pages/HostedSignup.tsx b/frontend-modern/src/pages/HostedSignup.tsx index ce7c393644..43e22a3a9c 100644 --- a/frontend-modern/src/pages/HostedSignup.tsx +++ b/frontend-modern/src/pages/HostedSignup.tsx @@ -1,11 +1,15 @@ -import { Show, createMemo, createSignal } from 'solid-js'; +import { For, Show, createMemo, createSignal } from 'solid-js'; import { useLocation } from '@solidjs/router'; import { Card } from '@/components/shared/Card'; import { PageHeader } from '@/components/shared/PageHeader'; import { HostedSignupAPI, type HostedAPIError } from '@/api/hostedSignup'; import { getUpgradeActionUrlOrFallback } from '@/stores/license'; import { logger } from '@/utils/logger'; -import { getCloudPlanForTier, getCloudPlanPricePresentation } from '@/utils/cloudPlans'; +import { + HOSTED_SIGNUP_PRESENTATION, + getCloudPlanForTier, + getCloudPlanPricePresentation, +} from '@/utils/cloudPlans'; type SignupStatus = 'idle' | 'submitting' | 'success' | 'unavailable' | 'error'; @@ -131,13 +135,15 @@ export default function HostedSignup() { return (
-

Workspace

+

+ {HOSTED_SIGNUP_PRESENTATION.workspaceHeading} +

-

Plan

+

+ {HOSTED_SIGNUP_PRESENTATION.planHeading} +

@@ -239,16 +250,20 @@ export default function HostedSignup() {
-

Next

+

+ {HOSTED_SIGNUP_PRESENTATION.nextHeading} +

    -
  1. Continue through checkout if prompted.
  2. -
  3. Finish sign-in from the email link.
  4. -
  5. Open your workspace and start connecting systems.
  6. + {(step) =>
  7. {step}
  8. }
-

Already signed up?

-

Request a fresh sign-in link.

+

+ {HOSTED_SIGNUP_PRESENTATION.existingAccountHeading} +

+

+ {HOSTED_SIGNUP_PRESENTATION.existingAccountDescription} +

- - Sending... + + {HOSTED_SIGNUP_PRESENTATION.sendingSignInLinkLabel} diff --git a/frontend-modern/src/pages/__tests__/HostedSignup.test.tsx b/frontend-modern/src/pages/__tests__/HostedSignup.test.tsx index 6eaa611489..d644168c91 100644 --- a/frontend-modern/src/pages/__tests__/HostedSignup.test.tsx +++ b/frontend-modern/src/pages/__tests__/HostedSignup.test.tsx @@ -63,6 +63,8 @@ describe('HostedSignup', () => { expect(screen.getByText('Plan')).toBeInTheDocument(); expect(screen.getByText('Next')).toBeInTheDocument(); expect(screen.getByText('Continue through checkout if prompted.')).toBeInTheDocument(); + expect(screen.getByText('Already signed up?')).toBeInTheDocument(); + expect(screen.getByText('Request a fresh sign-in link.')).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Email Sign-In Link' })).toBeInTheDocument(); fireEvent.input(screen.getByLabelText('Work Email'), { diff --git a/frontend-modern/src/utils/__tests__/cloudPlans.test.ts b/frontend-modern/src/utils/__tests__/cloudPlans.test.ts index a4b4aed997..4c93a211ab 100644 --- a/frontend-modern/src/utils/__tests__/cloudPlans.test.ts +++ b/frontend-modern/src/utils/__tests__/cloudPlans.test.ts @@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'; import { CLOUD_COMMERCIAL_PRESENTATION, CLOUD_PLAN_BY_TIER, + HOSTED_SIGNUP_PRESENTATION, getCloudPlanPricePresentation, } from '@/utils/cloudPlans'; @@ -48,4 +49,25 @@ describe('cloudPlans', () => { ], }); }); + + it('keeps hosted signup commercial copy in the common contract', () => { + expect(HOSTED_SIGNUP_PRESENTATION).toEqual({ + pageTitlePrefix: 'Pulse Cloud', + pageDescription: 'Create your managed Pulse Cloud workspace.', + workspaceHeading: 'Workspace', + planHeading: 'Plan', + nextHeading: 'Next', + nextSteps: [ + 'Continue through checkout if prompted.', + 'Finish sign-in from the email link.', + 'Open your workspace and start connecting systems.', + ], + existingAccountHeading: 'Already signed up?', + existingAccountDescription: 'Request a fresh sign-in link.', + createWorkspaceLabel: 'Create Workspace', + creatingWorkspaceLabel: 'Creating...', + emailSignInLinkLabel: 'Email Sign-In Link', + sendingSignInLinkLabel: 'Sending...', + }); + }); }); diff --git a/frontend-modern/src/utils/cloudPlans.ts b/frontend-modern/src/utils/cloudPlans.ts index ac10fb4f3c..1853466fb1 100644 --- a/frontend-modern/src/utils/cloudPlans.ts +++ b/frontend-modern/src/utils/cloudPlans.ts @@ -30,6 +30,21 @@ export interface CloudCommercialPresentation { setupSteps: readonly string[]; } +export interface HostedSignupPresentation { + pageTitlePrefix: string; + pageDescription: string; + workspaceHeading: string; + planHeading: string; + nextHeading: string; + nextSteps: readonly string[]; + existingAccountHeading: string; + existingAccountDescription: string; + createWorkspaceLabel: string; + creatingWorkspaceLabel: string; + emailSignInLinkLabel: string; + sendingSignInLinkLabel: string; +} + export const DEFAULT_CLOUD_TIER: CloudTierKey = 'starter'; export const CLOUD_PLAN_DEFINITIONS: readonly CloudPlanDefinition[] = [ @@ -101,6 +116,25 @@ export const CLOUD_COMMERCIAL_PRESENTATION: CloudCommercialPresentation = { ], } as const; +export const HOSTED_SIGNUP_PRESENTATION: HostedSignupPresentation = { + pageTitlePrefix: 'Pulse Cloud', + pageDescription: 'Create your managed Pulse Cloud workspace.', + workspaceHeading: 'Workspace', + planHeading: 'Plan', + nextHeading: 'Next', + nextSteps: [ + 'Continue through checkout if prompted.', + 'Finish sign-in from the email link.', + 'Open your workspace and start connecting systems.', + ], + existingAccountHeading: 'Already signed up?', + existingAccountDescription: 'Request a fresh sign-in link.', + createWorkspaceLabel: 'Create Workspace', + creatingWorkspaceLabel: 'Creating...', + emailSignInLinkLabel: 'Email Sign-In Link', + sendingSignInLinkLabel: 'Sending...', +} as const; + export function parseCloudTier(value?: string | null): CloudTierKey { switch ((value || '').trim().toLowerCase()) { case 'power':