Files
resolutionflow/frontend/src/api/onboarding.ts
Michael Chihlas 0c326d0616 feat(dashboard): replace checklist with next-step card + unified list
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>
2026-05-06 23:19:58 -04:00

74 lines
2.2 KiB
TypeScript

import { apiClient } from './client'
export interface OnboardingStatus {
created_flow: boolean
ran_session: boolean
exported_session: boolean
/** @deprecated Phase 2 — kept for backward-compat. New UI no longer branches on this. */
tried_ai_assistant: boolean
invited_teammate: boolean
connected_psa: boolean
is_team_user: boolean
dismissed: boolean
// Phase 2 (Task 41) — drive the unified next-step card + checklist.
email_verified: boolean
shop_setup_done: boolean
}
export async function getOnboardingStatus(): Promise<OnboardingStatus> {
const response = await apiClient.get('/users/onboarding-status')
return response.data
}
export async function dismissOnboarding(): Promise<void> {
await apiClient.post('/users/onboarding-status/dismiss')
}
// --- Welcome wizard (Phase 2) ---------------------------------------------
export type WizardStep = 1 | 2 | 3
export type WizardAction = 'complete' | 'skip'
export type TeamSizeBucket = '1-2' | '3-5' | '6-10' | '11-25' | '26+'
export type RoleAtSignup = 'owner' | 'lead_tech' | 'tech' | 'other'
export type PrimaryPsa = 'connectwise' | 'autotask' | 'halopsa' | 'none'
export interface OnboardingStepData {
// Step 1
company_name?: string
team_size_bucket?: TeamSizeBucket
role_at_signup?: RoleAtSignup
// Step 2
primary_psa?: PrimaryPsa
}
export interface OnboardingStepRequest {
step: WizardStep
action: WizardAction
data?: OnboardingStepData
}
export interface OnboardingStepResponse {
onboarding_step_completed: number | null
onboarding_dismissed: boolean
}
export const onboardingApi = {
getStatus: getOnboardingStatus,
dismiss: dismissOnboarding,
/** Persist welcome-wizard progress for the current user. */
async updateStep(payload: OnboardingStepRequest): Promise<OnboardingStepResponse> {
const response = await apiClient.patch<OnboardingStepResponse>(
'/users/me/onboarding-step',
payload,
)
return response.data
},
/** Skip the rest of the welcome wizard — sets users.onboarding_dismissed=TRUE. */
async dismissRest(): Promise<OnboardingStepResponse> {
const response = await apiClient.post<OnboardingStepResponse>(
'/users/me/onboarding-dismiss-rest',
)
return response.data
},
}