Phase 2 Task 41 — Dashboard redesign. Backend: - Extend GET /users/onboarding-status with email_verified and shop_setup_done. - tried_ai_assistant kept in payload for backward-compat during deploy. Frontend: - New NextStepCard: surfaces the highest-priority incomplete onboarding item with a primary CTA. Priority order: verify email > set up shop > run first FlowPilot session > connect PSA > invite teammate > pick a plan (gated on trial stage warning/urgent/expired). Returns null when all done OR onboarding_dismissed. - New SetupChecklist: unified single list (no SOLO/TEAM bifurcation), drops the stale tried_ai_assistant / Script Builder item, surfaces "Pick a plan" when trial stage is warning or later. - Mounted on QuickStartPage below the hero with a "Show all setup steps" toggle. The whole onboarding section auto-hides when there's nothing left to nudge on, so the dashboard goes back to clean once setup is done. - Removed the orphaned OnboardingChecklist component (was defined but never mounted). - New useOnboardingStatus hook so page + components share one fetch contract. Tests: - Backend: test_onboarding_status_includes_email_verified_and_shop_setup_done. - Frontend (Vitest): 13 new tests across NextStepCard, SetupChecklist, and QuickStartPage covering priority ordering, dismissal, the SOLO/TEAM removal, the toggle reveal, and the trial-stage gate on Pick a plan. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
from typing import Literal, Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class OnboardingStatus(BaseModel):
|
|
created_flow: bool
|
|
ran_session: bool
|
|
exported_session: bool
|
|
# Kept for backward-compat during deploy; new code paths should not branch on this.
|
|
tried_ai_assistant: bool
|
|
invited_teammate: bool
|
|
connected_psa: bool
|
|
is_team_user: bool
|
|
dismissed: bool
|
|
# New (Phase 2 — Task 41) — drive the unified next-step card + checklist.
|
|
email_verified: bool
|
|
shop_setup_done: bool
|
|
|
|
|
|
# --- Welcome wizard (Phase 2) ----------------------------------------------
|
|
|
|
|
|
TeamSizeBucket = Literal["1-2", "3-5", "6-10", "11-25", "26+"]
|
|
RoleAtSignup = Literal["owner", "lead_tech", "tech", "other"]
|
|
PrimaryPsa = Literal["connectwise", "autotask", "halopsa", "none"]
|
|
WizardStep = Literal[1, 2, 3]
|
|
WizardAction = Literal["complete", "skip"]
|
|
|
|
|
|
class OnboardingStepData(BaseModel):
|
|
"""Optional payload carried with `action="complete"` for steps 1 and 2.
|
|
|
|
Step 1 fields: company_name, team_size_bucket, role_at_signup
|
|
Step 2 fields: primary_psa
|
|
Step 3 has no data (invitations posted separately).
|
|
"""
|
|
|
|
# Step 1
|
|
company_name: Optional[str] = Field(default=None, max_length=255)
|
|
team_size_bucket: Optional[TeamSizeBucket] = None
|
|
role_at_signup: Optional[RoleAtSignup] = None
|
|
# Step 2
|
|
primary_psa: Optional[PrimaryPsa] = None
|
|
|
|
|
|
class OnboardingStepRequest(BaseModel):
|
|
step: WizardStep
|
|
action: WizardAction
|
|
data: Optional[OnboardingStepData] = None
|
|
|
|
|
|
class OnboardingStepResponse(BaseModel):
|
|
onboarding_step_completed: Optional[int]
|
|
onboarding_dismissed: bool
|