/**
* 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 */}
{/* 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 && (
)}
);
}