'use client' import { useState, useEffect, useCallback } from 'react' import { motion, AnimatePresence } from 'motion/react' import { useSession } from 'next-auth/react' import { useRouter } from 'next/navigation' import { Sparkles, X } from 'lucide-react' import { cn } from '@/lib/utils' import { useLanguage } from '@/lib/i18n' import { OnboardingStepWelcome } from './onboarding-step-welcome' import { OnboardingStepNotes } from './onboarding-step-notes' import { OnboardingStepAha } from './onboarding-step-aha' import { OnboardingStepFeatures } from './onboarding-step-features' const TOTAL_STEPS = 4 async function markOnboardingComplete() { const res = await fetch('/api/user/me', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ onboardingCompleted: true }), }) if (!res.ok) throw new Error('Failed to save onboarding state') } async function getNoteCount(): Promise { try { const res = await fetch('/api/notes?limit=1') if (!res.ok) return 0 const data = await res.json() if (data?.data && Array.isArray(data.data)) return data.data.length if (Array.isArray(data)) return data.length return 0 } catch { return 0 } } export function OnboardingWizard() { const { data: session, update: updateSession } = useSession() const { language, t } = useLanguage() const router = useRouter() const [step, setStep] = useState(1) const [visible, setVisible] = useState(false) const [minimized, setMinimized] = useState(false) const [noteCount, setNoteCount] = useState(0) const [demoNotesJustCreated, setDemoNotesJustCreated] = useState(false) const [triedCount, setTriedCount] = useState(0) const user = session?.user as any useEffect(() => { if (!session) return if (user?.onboardingCompleted === false) { setVisible(true) getNoteCount().then(setNoteCount) } }, [session, user?.onboardingCompleted]) const handleSkip = useCallback(async () => { setVisible(false) setMinimized(false) try { await markOnboardingComplete() await updateSession({ onboardingCompleted: true }) } catch (e) { console.error('[Onboarding] skip failed:', e) } }, [updateSession]) const handleNext = useCallback(() => { setStep(s => Math.min(s + 1, TOTAL_STEPS)) }, []) const handleNotesNext = useCallback((justCreated: boolean) => { setDemoNotesJustCreated(justCreated) setStep(s => Math.min(s + 1, TOTAL_STEPS)) }, []) const handleDone = useCallback(async () => { setVisible(false) setMinimized(false) try { await markOnboardingComplete() await updateSession({ onboardingCompleted: true }) } catch (e) { console.error('[Onboarding] done failed:', e) } }, [updateSession]) // Called from step 4 when user clicks "Essayer" on a feature const handleTry = useCallback((href: string) => { setMinimized(true) setTriedCount(c => c + 1) router.push(href) }, [router]) if (!visible) return null return ( <> {/* Minimized pill — always rendered when minimized so it shows on any page */} {minimized && ( setMinimized(false)} className="fixed bottom-6 right-6 z-[300] flex items-center gap-2.5 rounded-full bg-violet-600 text-white shadow-lg shadow-violet-500/30 px-4 py-3 text-sm font-medium hover:bg-violet-700 transition-colors" > {t('onboarding.pill_resume')} {triedCount > 0 && ( {triedCount} )} )} {/* Full wizard modal */} {!minimized && ( {/* Progress */}
{Array.from({ length: TOTAL_STEPS }).map((_, i) => ( ))}

{t('onboarding.progress', { current: step, total: TOTAL_STEPS })}

{/* Skip / close button (steps 1-3 only, step 4 has its own CTA) */} {step < 4 && ( )} {/* Step content */} {step === 1 && ( )} {step === 2 && ( )} {step === 3 && ( )} {step === 4 && ( )}
)}
) }