feat: module-driven onboarding system + simplified 3-step signup
Add OnboardingProviderProtocol so modules declare their own post-signup onboarding steps. The core OnboardingAggregator discovers enabled providers and exposes a dashboard API (GET /dashboard/onboarding). A session-scoped banner on the store dashboard shows a checklist that guides merchants through setup without blocking signup. Signup is simplified from 4 steps to 3 (Plan → Account → Payment): store creation is merged into account creation, store language is captured from the user's browsing language, and platform-specific template branching is removed. Includes 47 unit and integration tests covering all new providers, the aggregator, the API endpoint, and the signup service changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -337,6 +337,85 @@
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{# =============================================================================
|
||||
Onboarding Banner
|
||||
Shows a checklist of post-signup onboarding steps from all enabled modules.
|
||||
Steps are fetched from the API, dismiss is session-scoped (sessionStorage).
|
||||
|
||||
Usage:
|
||||
{{ onboarding_banner() }}
|
||||
============================================================================= #}
|
||||
{% macro onboarding_banner() %}
|
||||
<div x-data="onboardingBanner()"
|
||||
x-show="visible"
|
||||
x-cloak
|
||||
class="mb-4 bg-white dark:bg-gray-800 rounded-lg shadow-xs border border-gray-200 dark:border-gray-700 overflow-hidden">
|
||||
{# Header with progress #}
|
||||
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<span x-html="$icon('rocket', 'w-5 h-5 text-purple-600 dark:text-purple-400')"></span>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white" x-text="t('onboarding.banner.title')">Get Started</h3>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400"
|
||||
x-text="`${completedSteps}/${totalSteps}`"></span>
|
||||
</div>
|
||||
<button @click="dismiss()"
|
||||
class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"
|
||||
:title="t('onboarding.banner.dismiss')">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{# Progress bar #}
|
||||
<div class="mt-3 w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
|
||||
<div class="bg-purple-600 h-2 rounded-full transition-all duration-500"
|
||||
:style="`width: ${progressPercentage}%`"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Step checklist #}
|
||||
<div class="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
<template x-for="step in steps" :key="step.key">
|
||||
<a :href="step.route"
|
||||
class="flex items-center px-6 py-3 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors group">
|
||||
{# Completion indicator #}
|
||||
<div class="flex-shrink-0 mr-4">
|
||||
<template x-if="step.completed">
|
||||
<div class="w-6 h-6 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center">
|
||||
<svg class="w-4 h-4 text-green-600 dark:text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="!step.completed">
|
||||
<div class="w-6 h-6 rounded-full border-2 border-gray-300 dark:border-gray-600 group-hover:border-purple-400 transition-colors"></div>
|
||||
</template>
|
||||
</div>
|
||||
{# Step icon + text #}
|
||||
<div class="flex-shrink-0 mr-3">
|
||||
<span x-html="$icon(step.icon, 'w-5 h-5 text-gray-400 dark:text-gray-500')" class="block"></span>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-white"
|
||||
:class="{ 'line-through text-gray-400 dark:text-gray-500': step.completed }"
|
||||
x-text="t(step.title_key)"></p>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 truncate"
|
||||
x-text="t(step.description_key)"></p>
|
||||
</div>
|
||||
{# Arrow #}
|
||||
<template x-if="!step.completed">
|
||||
<svg class="w-4 h-4 text-gray-400 group-hover:text-purple-500 transition-colors flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{# =============================================================================
|
||||
Email Settings Warning
|
||||
Shows warning banner when store email settings are not configured.
|
||||
|
||||
Reference in New Issue
Block a user