auto-claude: subtask-2-7 - Create OnboardingWizard component
Add main wizard container with step management, navigation, and FullScreenDialog pattern: - Step-by-step wizard flow (Welcome → OAuth → Graphiti → First Spec → Completion) - WizardProgress indicator integration - Navigation handlers (next, back, skip) - Persists onboardingCompleted flag to settings store - Integrates all step components with proper callbacks - Handles task creator and settings opening from within wizard 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { Wand2 } from 'lucide-react';
|
||||
import {
|
||||
FullScreenDialog,
|
||||
FullScreenDialogContent,
|
||||
FullScreenDialogHeader,
|
||||
FullScreenDialogBody,
|
||||
FullScreenDialogTitle,
|
||||
FullScreenDialogDescription
|
||||
} from '../ui/full-screen-dialog';
|
||||
import { ScrollArea } from '../ui/scroll-area';
|
||||
import { WizardProgress, WizardStep } from './WizardProgress';
|
||||
import { WelcomeStep } from './WelcomeStep';
|
||||
import { OAuthStep } from './OAuthStep';
|
||||
import { GraphitiStep } from './GraphitiStep';
|
||||
import { FirstSpecStep } from './FirstSpecStep';
|
||||
import { CompletionStep } from './CompletionStep';
|
||||
import { useSettingsStore } from '../../stores/settings-store';
|
||||
|
||||
interface OnboardingWizardProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
onOpenTaskCreator?: () => void;
|
||||
onOpenSettings?: () => void;
|
||||
}
|
||||
|
||||
// Wizard step identifiers
|
||||
type WizardStepId = 'welcome' | 'oauth' | 'graphiti' | 'first-spec' | 'completion';
|
||||
|
||||
// Step configuration
|
||||
const WIZARD_STEPS: { id: WizardStepId; label: string }[] = [
|
||||
{ id: 'welcome', label: 'Welcome' },
|
||||
{ id: 'oauth', label: 'Auth' },
|
||||
{ id: 'graphiti', label: 'Memory' },
|
||||
{ id: 'first-spec', label: 'First Task' },
|
||||
{ id: 'completion', label: 'Done' }
|
||||
];
|
||||
|
||||
/**
|
||||
* Main onboarding wizard component.
|
||||
* Provides a full-screen, multi-step wizard experience for new users
|
||||
* to configure their Auto Claude environment.
|
||||
*
|
||||
* Features:
|
||||
* - Step progress indicator
|
||||
* - Navigation between steps (next, back, skip)
|
||||
* - Persists completion state to settings
|
||||
* - Can be re-run from settings
|
||||
*/
|
||||
export function OnboardingWizard({
|
||||
open,
|
||||
onOpenChange,
|
||||
onOpenTaskCreator,
|
||||
onOpenSettings
|
||||
}: OnboardingWizardProps) {
|
||||
const { updateSettings } = useSettingsStore();
|
||||
const [currentStepIndex, setCurrentStepIndex] = useState(0);
|
||||
const [completedSteps, setCompletedSteps] = useState<Set<WizardStepId>>(new Set());
|
||||
|
||||
// Get current step ID
|
||||
const currentStepId = WIZARD_STEPS[currentStepIndex].id;
|
||||
|
||||
// Build step data for progress indicator
|
||||
const steps: WizardStep[] = WIZARD_STEPS.map((step, index) => ({
|
||||
id: step.id,
|
||||
label: step.label,
|
||||
completed: completedSteps.has(step.id) || index < currentStepIndex
|
||||
}));
|
||||
|
||||
// Navigation handlers
|
||||
const goToNextStep = useCallback(() => {
|
||||
// Mark current step as completed
|
||||
setCompletedSteps(prev => new Set(prev).add(currentStepId));
|
||||
|
||||
if (currentStepIndex < WIZARD_STEPS.length - 1) {
|
||||
setCurrentStepIndex(prev => prev + 1);
|
||||
}
|
||||
}, [currentStepIndex, currentStepId]);
|
||||
|
||||
const goToPreviousStep = useCallback(() => {
|
||||
if (currentStepIndex > 0) {
|
||||
setCurrentStepIndex(prev => prev - 1);
|
||||
}
|
||||
}, [currentStepIndex]);
|
||||
|
||||
const skipWizard = useCallback(async () => {
|
||||
// Mark onboarding as completed and close
|
||||
await updateSettings({ onboardingCompleted: true });
|
||||
onOpenChange(false);
|
||||
resetWizard();
|
||||
}, [updateSettings, onOpenChange]);
|
||||
|
||||
const finishWizard = useCallback(async () => {
|
||||
// Mark onboarding as completed
|
||||
await updateSettings({ onboardingCompleted: true });
|
||||
onOpenChange(false);
|
||||
resetWizard();
|
||||
}, [updateSettings, onOpenChange]);
|
||||
|
||||
// Reset wizard state (for re-running)
|
||||
const resetWizard = useCallback(() => {
|
||||
setCurrentStepIndex(0);
|
||||
setCompletedSteps(new Set());
|
||||
}, []);
|
||||
|
||||
// Handle opening task creator from within wizard
|
||||
const handleOpenTaskCreator = useCallback(() => {
|
||||
if (onOpenTaskCreator) {
|
||||
// Close wizard first, then open task creator
|
||||
onOpenChange(false);
|
||||
onOpenTaskCreator();
|
||||
}
|
||||
}, [onOpenTaskCreator, onOpenChange]);
|
||||
|
||||
// Handle opening settings from completion step
|
||||
const handleOpenSettings = useCallback(() => {
|
||||
if (onOpenSettings) {
|
||||
// Finish wizard first, then open settings
|
||||
finishWizard();
|
||||
onOpenSettings();
|
||||
}
|
||||
}, [onOpenSettings, finishWizard]);
|
||||
|
||||
// Render current step content
|
||||
const renderStepContent = () => {
|
||||
switch (currentStepId) {
|
||||
case 'welcome':
|
||||
return (
|
||||
<WelcomeStep
|
||||
onGetStarted={goToNextStep}
|
||||
onSkip={skipWizard}
|
||||
/>
|
||||
);
|
||||
case 'oauth':
|
||||
return (
|
||||
<OAuthStep
|
||||
onNext={goToNextStep}
|
||||
onBack={goToPreviousStep}
|
||||
onSkip={skipWizard}
|
||||
/>
|
||||
);
|
||||
case 'graphiti':
|
||||
return (
|
||||
<GraphitiStep
|
||||
onNext={goToNextStep}
|
||||
onBack={goToPreviousStep}
|
||||
onSkip={skipWizard}
|
||||
/>
|
||||
);
|
||||
case 'first-spec':
|
||||
return (
|
||||
<FirstSpecStep
|
||||
onNext={goToNextStep}
|
||||
onBack={goToPreviousStep}
|
||||
onSkip={skipWizard}
|
||||
onOpenTaskCreator={handleOpenTaskCreator}
|
||||
/>
|
||||
);
|
||||
case 'completion':
|
||||
return (
|
||||
<CompletionStep
|
||||
onFinish={finishWizard}
|
||||
onOpenTaskCreator={handleOpenTaskCreator}
|
||||
onOpenSettings={handleOpenSettings}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Handle dialog close - ask for confirmation if not completed
|
||||
const handleOpenChange = useCallback((newOpen: boolean) => {
|
||||
if (!newOpen) {
|
||||
// If closing before completion, skip the wizard
|
||||
skipWizard();
|
||||
} else {
|
||||
onOpenChange(newOpen);
|
||||
}
|
||||
}, [skipWizard, onOpenChange]);
|
||||
|
||||
return (
|
||||
<FullScreenDialog open={open} onOpenChange={handleOpenChange}>
|
||||
<FullScreenDialogContent>
|
||||
<FullScreenDialogHeader>
|
||||
<FullScreenDialogTitle className="flex items-center gap-3">
|
||||
<Wand2 className="h-6 w-6" />
|
||||
Setup Wizard
|
||||
</FullScreenDialogTitle>
|
||||
<FullScreenDialogDescription>
|
||||
Configure your Auto Claude environment in a few simple steps
|
||||
</FullScreenDialogDescription>
|
||||
|
||||
{/* Progress indicator - show for all steps except welcome and completion */}
|
||||
{currentStepId !== 'welcome' && currentStepId !== 'completion' && (
|
||||
<div className="mt-6">
|
||||
<WizardProgress currentStep={currentStepIndex} steps={steps} />
|
||||
</div>
|
||||
)}
|
||||
</FullScreenDialogHeader>
|
||||
|
||||
<FullScreenDialogBody>
|
||||
<ScrollArea className="h-full">
|
||||
{renderStepContent()}
|
||||
</ScrollArea>
|
||||
</FullScreenDialogBody>
|
||||
</FullScreenDialogContent>
|
||||
</FullScreenDialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user