/** * OnboardingWizard — 3-step minimalist onboarding. * * Shown after first registration. Claude-inspired: clean, fast, no friction. * Step 1: Your name * Step 2: What you'll use HomePilot for + preferred tone * Step 3: Ready — welcome screen */ import React, { useState } from 'react'; import { ArrowRight, ArrowLeft, Check, Sparkles, MessageSquare, Image, Search, Heart, Film } from 'lucide-react'; const USE_CASES = [ { id: 'chat', label: 'Chat & Conversation', icon: MessageSquare, color: '#3b82f6' }, { id: 'images', label: 'Image Generation', icon: Image, color: '#8b5cf6' }, { id: 'research', label: 'Research & Knowledge', icon: Search, color: '#06b6d4' }, { id: 'companion', label: 'AI Companion', icon: Heart, color: '#ec4899' }, { id: 'content', label: 'Content Creation', icon: Film, color: '#f59e0b' }, ]; const TONES = [ { id: 'casual', label: 'Casual', desc: 'Friendly and relaxed' }, { id: 'balanced', label: 'Balanced', desc: 'Natural and adaptable' }, { id: 'professional', label: 'Professional', desc: 'Clear and formal' }, ]; export default function OnboardingWizard({ backendUrl, token, username, onComplete }) { const [step, setStep] = useState(1); const [displayName, setDisplayName] = useState(''); const [selectedUseCases, setSelectedUseCases] = useState([]); const [tone, setTone] = useState('balanced'); const [saving, setSaving] = useState(false); const toggleUseCase = (id) => { setSelectedUseCases(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]); }; const handleFinish = async () => { setSaving(true); try { await fetch(`${backendUrl}/v1/auth/onboarding`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }, credentials: 'include', body: JSON.stringify({ display_name: displayName.trim() || username, use_cases: selectedUseCases, preferred_tone: tone, }), }); } catch { // Non-fatal — proceed anyway } setSaving(false); onComplete(displayName.trim() || username); }; const cardStyle = { width: '100%', maxWidth: 480, background: 'rgba(30, 41, 59, 0.8)', border: '1px solid rgba(148, 163, 184, 0.1)', borderRadius: 16, padding: 32, backdropFilter: 'blur(12px)', }; return (
{/* Progress dots */}
{[1, 2, 3].map(s => (
))}
{/* Step 1: Your name */} {step === 1 && (

Welcome to HomePilot

Let's set up your profile so your AI companions know who you are.

setDisplayName(e.target.value)} placeholder={username} autoFocus maxLength={64} style={{ width: '100%', padding: '12px 14px', borderRadius: 10, border: '1px solid rgba(148, 163, 184, 0.15)', background: 'rgba(15, 23, 42, 0.5)', color: '#e2e8f0', fontSize: 16, outline: 'none', boxSizing: 'border-box', marginBottom: 24, }} onKeyDown={e => e.key === 'Enter' && setStep(2)}/>
)} {/* Step 2: Use cases + tone */} {step === 2 && (

How will you use HomePilot?

Select all that apply — this helps personalize your experience.

{/* Use case chips */}
{USE_CASES.map(uc => { const selected = selectedUseCases.includes(uc.id); const Icon = uc.icon; return (); })}
{/* Tone */}
{TONES.map(t => ())}
)} {/* Step 3: Ready */} {step === 3 && (

You're all set{displayName ? `, ${displayName}` : ''}!

Your profile is ready. Your AI companions will use this to personalize your experience over time.

{/* Summary */}
{displayName &&
Name: {displayName}
} {selectedUseCases.length > 0 && (
Interests: {selectedUseCases.map(id => USE_CASES.find(u => u.id === id)?.label).join(', ')}
)}
Style: {TONES.find(t => t.id === tone)?.label}
)} {/* Skip link */} {step < 3 && ()}
); }