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>
28 lines
924 B
TypeScript
28 lines
924 B
TypeScript
import { useEffect, useState } from 'react'
|
|
import { getOnboardingStatus } from '@/api/onboarding'
|
|
import type { OnboardingStatus } from '@/api/onboarding'
|
|
|
|
/**
|
|
* Tiny shared hook that fetches `/users/onboarding-status` once on mount.
|
|
*
|
|
* Used by `NextStepCard`, `SetupChecklist`, and `QuickStartPage` so the toggle
|
|
* row can disappear when there's nothing to show. Each consumer has its own
|
|
* state — fetches are not deduplicated. That's fine for now; if it becomes a
|
|
* problem we can lift this into a Zustand store or react-query.
|
|
*/
|
|
export function useOnboardingStatus(): OnboardingStatus | null {
|
|
const [status, setStatus] = useState<OnboardingStatus | null>(null)
|
|
|
|
useEffect(() => {
|
|
getOnboardingStatus()
|
|
.then(setStatus)
|
|
.catch(() => {
|
|
// Silently fail — never block the dashboard if the endpoint is down.
|
|
})
|
|
}, [])
|
|
|
|
return status
|
|
}
|
|
|
|
export default useOnboardingStatus
|