'use client' import { useState, useCallback } from 'react' import { motion, AnimatePresence } from 'motion/react' import { Sparkles, X, CheckCircle2, FolderPlus, Folder, ChevronDown, ChevronUp, Loader2, AlertCircle, Check, ArrowRight } from 'lucide-react' import { cn } from '@/lib/utils' import { analyzeNotebookForOrganization, executeNotebookOrganization, type OrganizationGroup, type OrganizationPlan, } from '@/app/actions/organize-notebook' import { toast } from 'sonner' import { useLanguage } from '@/lib/i18n' interface OrganizeNotebookDialogProps { open: boolean onOpenChange: (open: boolean) => void notebookId: string notebookName: string onDone?: () => void } type Step = 'idle' | 'analyzing' | 'preview' | 'executing' | 'done' export function OrganizeNotebookDialog({ open, onOpenChange, notebookId, notebookName, onDone, }: OrganizeNotebookDialogProps) { const { t, language } = useLanguage() const slide = language === 'fa' || language === 'ar' ? -480 : 480 const [step, setStep] = useState('idle') const [plan, setPlan] = useState(null) const [editableGroups, setEditableGroups] = useState([]) const [expandedGroups, setExpandedGroups] = useState>(new Set()) const [error, setError] = useState(null) const [result, setResult] = useState<{ created: number; moved: number } | null>(null) const handleAnalyze = useCallback(async () => { setStep('analyzing'); setError(null); setPlan(null) const res = await analyzeNotebookForOrganization(notebookId, language) if (!res.success || !res.plan) { setError(res.error ?? 'Erreur'); setStep('idle'); return } setPlan(res.plan) setEditableGroups(res.plan.groups.map(g => ({ ...g, notes: [...g.notes] }))) setExpandedGroups(new Set(res.plan.groups.map((_, i) => i))) setStep('preview') }, [notebookId]) const handleRenameGroup = (idx: number, name: string) => { setEditableGroups(prev => prev.map((g, i) => i === idx ? { ...g, name } : g)) } const handleToggleNote = (groupIdx: number, noteId: string) => { setEditableGroups(prev => prev.map((g, i) => { if (i !== groupIdx) return g const has = g.notes.some(n => n.id === noteId) return { ...g, notes: has ? g.notes.filter(n => n.id !== noteId) : g.notes } })) } const handleRemoveGroup = (idx: number) => { setEditableGroups(prev => prev.filter((_, i) => i !== idx)) } const toggleExpand = (idx: number) => { setExpandedGroups(prev => { const n = new Set(prev); n.has(idx) ? n.delete(idx) : n.add(idx); return n }) } const handleExecute = useCallback(async () => { if (!plan) return setStep('executing') const finalPlan: OrganizationPlan = { notebookId: plan.notebookId, groups: editableGroups.filter(g => g.notes.length > 0 && g.name.trim()), } const res = await executeNotebookOrganization(finalPlan) if (!res.success) { setError(res.error ?? 'Erreur'); setStep('preview'); return } setResult({ created: res.created, moved: res.moved }) setStep('done') toast.success(t('organizeNotebook.toastSuccess', { created: res.created, moved: res.moved })) onDone?.() }, [plan, editableGroups, onDone, t]) const handleClose = () => { if (step === 'analyzing' || step === 'executing') return onOpenChange(false) setTimeout(() => { setStep('idle'); setPlan(null); setEditableGroups([]); setError(null); setResult(null) }, 300) } if (!open) return null const totalNotes = editableGroups.reduce((acc, g) => acc + g.notes.length, 0) const newSubNbs = editableGroups.filter(g => g.isNew).length return ( {open && ( <> e.stopPropagation()} > {/* Header */}

{t('organizeNotebook.title')}

{notebookName}

{/* Content */}
{/* IDLE */} {step === 'idle' && ( {error && (

{error}

)}

{t('organizeNotebook.intro')}

{[{ icon: FolderPlus, text: t('organizeNotebook.bulletThemes') }, { icon: Folder, text: t('organizeNotebook.bulletSubfolders') }, { icon: Check, text: t('organizeNotebook.bulletPreview') }].map((item, i) => (
{item.text}
))}
)} {/* ANALYZING */} {step === 'analyzing' && (

{t('organizeNotebook.analyzingTitle')}

{t('organizeNotebook.analyzingSubtitle')}

{[0, 1, 2].map(i => ( ))}
)} {/* PREVIEW */} {step === 'preview' && (

{t('organizeNotebook.previewSummary', { groups: editableGroups.length, notes: totalNotes, newSubs: newSubNbs })}

{error && (

{error}

)} {editableGroups.map((group, idx) => (
{group.isNew ? : }
handleRenameGroup(idx, e.target.value)} className="flex-1 bg-transparent text-[13px] font-semibold text-ink dark:text-dark-ink outline-none focus:text-brand-accent transition-colors min-w-0" /> {group.isNew && ( {t('organizeNotebook.badgeNew')} )}
{expandedGroups.has(idx) && (
{group.notes.map(note => (
handleToggleNote(idx, note.id)} className="flex items-center gap-2 py-1.5 rounded-lg px-2 hover:bg-foreground/[0.03] transition-colors group cursor-pointer">
{note.title || t('organizeNotebook.untitledNote')}
))}
)}
{!expandedGroups.has(idx) && (
{t('organizeNotebook.notesInGroup', { count: group.notes.length })}
)}
))}
)} {/* EXECUTING */} {step === 'executing' && (

{t('organizeNotebook.executingTitle')}

{t('organizeNotebook.executingSubtitle')}

)} {/* DONE */} {step === 'done' && (

{t('organizeNotebook.doneTitle')}

{result &&

{t('organizeNotebook.doneStats', { created: result.created, moved: result.moved })}

}
)}
{/* Footer */}
{step === 'idle' && ( )} {step === 'preview' && (
)} {step === 'done' && ( )}
)}
) }