* Rename pre-subscription onboarding funnel to Welcome. Move the ICP steps to /welcome, drop the social-connect checkout gate, hold unpaid members on a subscription-required screen, and keep legacy /onboarding URLs working until the post-subscription checklist lands. Closes #237 Co-authored-by: Cursor <cursoragent@cursor.com> * Drop legacy /onboarding ICP URL aliases. Unfinished users re-enter Welcome via EnsureAccountReady on next login; /onboarding stays free for the post-subscription checklist. Co-authored-by: Cursor <cursoragent@cursor.com> * Simplify Welcome PostHog event names. Use welcome.persona/goals/referral and drop the unused checkout case — begin checkout stays on the frontend as checkout.started / begin_checkout. Co-authored-by: Cursor <cursoragent@cursor.com> * Slim welcome goal options to match the #204 set. Drop team_collaboration, automate_api, and track_performance so the goals step stays at nine choices. Co-authored-by: Cursor <cursoragent@cursor.com> * Split Welcome AI goals into TryPost AI and MCP assistants. Rewrite ai_content for in-app generation and add use_mcp so Claude/ChatGPT/Cursor intent is captured separately across locales. Co-authored-by: Cursor <cursoragent@cursor.com> * Harden Welcome goals gate and drop dead checkout UI. Treat removed goal values as incomplete so mid-funnel users re-select, remove the unused canCheckout branch, and fix the pt-BR welcome progress label. Co-authored-by: Cursor <cursoragent@cursor.com> * Add password visibility toggle to the login form. Match the register eye control so users can reveal their password while signing in. Co-authored-by: Cursor <cursoragent@cursor.com> * Point the sidebar community link to Discord. Replace the X stay-updated entry with Join Discord and the trypost.it/discord invite. Co-authored-by: Cursor <cursoragent@cursor.com> * Rename the sidebar Discord link to Discord community. Softer label that matches the other support nav items. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix broken Turkish Discord community translation. An unescaped apostrophe left a parse error in lang/tr/sidebar.php. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
118 lines
4.3 KiB
Vue
118 lines
4.3 KiB
Vue
<script setup lang="ts">
|
|
import { Link } from '@inertiajs/vue3';
|
|
import { computed } from 'vue';
|
|
|
|
import {
|
|
goals as goalsRoute,
|
|
persona as personaRoute,
|
|
referralSource as referralSourceRoute,
|
|
} from '@/routes/app/welcome';
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
title?: string;
|
|
description?: string;
|
|
step?: number;
|
|
totalSteps?: number;
|
|
wide?: boolean;
|
|
}>(),
|
|
{
|
|
title: undefined,
|
|
description: undefined,
|
|
step: undefined,
|
|
totalSteps: 3,
|
|
wide: false,
|
|
},
|
|
);
|
|
|
|
const stepRoutes = computed(() => [
|
|
personaRoute(),
|
|
goalsRoute(),
|
|
referralSourceRoute(),
|
|
]);
|
|
|
|
const canNavigateTo = (stepNumber: number): boolean =>
|
|
props.step !== undefined && stepNumber < props.step;
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="flex min-h-svh flex-col items-center justify-center gap-6 bg-background p-6 md:p-10"
|
|
>
|
|
<div class="w-full" :class="wide ? 'max-w-4xl' : 'max-w-xl'">
|
|
<div class="flex flex-col gap-8">
|
|
<div class="flex flex-col items-center gap-4">
|
|
<Link
|
|
:href="personaRoute()"
|
|
class="flex flex-col items-center gap-2 font-medium"
|
|
>
|
|
<img
|
|
src="/images/trypost/logo-light.png"
|
|
alt="TryPost"
|
|
class="h-8 w-auto dark:hidden"
|
|
/>
|
|
<img
|
|
src="/images/trypost/logo-dark.png"
|
|
alt="TryPost"
|
|
class="hidden h-8 w-auto dark:block"
|
|
/>
|
|
</Link>
|
|
|
|
<nav
|
|
v-if="step !== undefined"
|
|
class="flex items-center gap-2"
|
|
:aria-label="$t('welcome.progress')"
|
|
>
|
|
<template
|
|
v-for="stepNumber in totalSteps"
|
|
:key="stepNumber"
|
|
>
|
|
<Link
|
|
v-if="canNavigateTo(stepNumber)"
|
|
:href="stepRoutes[stepNumber - 1]"
|
|
class="flex h-6 w-8 items-center"
|
|
:aria-label="
|
|
$t('welcome.go_to_step', {
|
|
step: String(stepNumber),
|
|
})
|
|
"
|
|
:data-testid="`welcome-step-${stepNumber}`"
|
|
>
|
|
<span
|
|
class="h-2 w-full rounded-full bg-primary transition-opacity hover:opacity-70 motion-reduce:transition-none"
|
|
/>
|
|
</Link>
|
|
<div
|
|
v-else
|
|
:class="[
|
|
'h-2 w-8 rounded-full transition-colors',
|
|
stepNumber <= step
|
|
? 'bg-primary'
|
|
: 'bg-muted',
|
|
]"
|
|
:aria-current="
|
|
stepNumber === step ? 'step' : undefined
|
|
"
|
|
:aria-label="
|
|
stepNumber === step
|
|
? $t('welcome.step_current', {
|
|
step: String(stepNumber),
|
|
})
|
|
: undefined
|
|
"
|
|
/>
|
|
</template>
|
|
</nav>
|
|
|
|
<div class="space-y-2 text-center">
|
|
<h1 class="text-2xl font-bold">{{ title }}</h1>
|
|
<p class="text-muted-foreground">
|
|
{{ description }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<slot />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|