From dd28b4f0bd05ff1d05711a90bc3d0d61cf19eed6 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Fri, 19 Jun 2026 21:24:35 +0000 Subject: [PATCH] =?UTF-8?q?design:=20OrganizeNotebookDialog=20redesign=20?= =?UTF-8?q?=E2=80=94=20propre=20et=20coh=C3=A9rent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Panneau latéral avec fond memento-paper (cohérent avec l'app) - Cartes de groupes avec bordures subtiles + hover brand-accent - Boutons primary en brand-accent (bronze) au lieu de bg-ink - Icônes dans des pastilles arrondies bg-brand-accent/10 - Animations fluides (spring, stagger) - Dark mode supporté (dark:bg-zinc-900) - Footer propre avec actions contextuelles par étape --- .../components/organize-notebook-dialog.tsx | 387 ++++++------------ 1 file changed, 131 insertions(+), 256 deletions(-) diff --git a/memento-note/components/organize-notebook-dialog.tsx b/memento-note/components/organize-notebook-dialog.tsx index af125d5..4a85ae9 100644 --- a/memento-note/components/organize-notebook-dialog.tsx +++ b/memento-note/components/organize-notebook-dialog.tsx @@ -2,7 +2,7 @@ import { useState, useCallback } from 'react' import { motion, AnimatePresence } from 'motion/react' -import { Sparkles, X, CheckCircle2, FolderPlus, Folder, ChevronDown, ChevronUp, Loader2, AlertCircle, Check } from 'lucide-react' +import { Sparkles, X, CheckCircle2, FolderPlus, Folder, ChevronDown, ChevronUp, Loader2, AlertCircle, Check, ArrowRight } from 'lucide-react' import { cn } from '@/lib/utils' import { analyzeNotebookForOrganization, @@ -31,7 +31,7 @@ export function OrganizeNotebookDialog({ onDone, }: OrganizeNotebookDialogProps) { const { t, language } = useLanguage() - const organizePanelSlide = language === 'fa' || language === 'ar' ? -60 : 60 + const slide = language === 'fa' || language === 'ar' ? -480 : 480 const [step, setStep] = useState('idle') const [plan, setPlan] = useState(null) const [editableGroups, setEditableGroups] = useState([]) @@ -40,18 +40,9 @@ export function OrganizeNotebookDialog({ const [result, setResult] = useState<{ created: number; moved: number } | null>(null) const handleAnalyze = useCallback(async () => { - setStep('analyzing') - setError(null) - setPlan(null) - + setStep('analyzing'); setError(null); setPlan(null) const res = await analyzeNotebookForOrganization(notebookId) - - if (!res.success || !res.plan) { - setError(res.error ?? t('organizeNotebook.unknownError')) - setStep('idle') - return - } - + 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))) @@ -61,64 +52,39 @@ export function OrganizeNotebookDialog({ 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, - } + 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 next = new Set(prev) - next.has(idx) ? next.delete(idx) : next.add(idx) - return next - }) + 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 ?? t('organizeNotebook.unknownError')) - setStep('preview') - return - } - + 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]) + }, [plan, editableGroups, onDone, t]) const handleClose = () => { if (step === 'analyzing' || step === 'executing') return onOpenChange(false) - // Reset after close animation - setTimeout(() => { - setStep('idle') - setPlan(null) - setEditableGroups([]) - setError(null) - setResult(null) - }, 300) + setTimeout(() => { setStep('idle'); setPlan(null); setEditableGroups([]); setError(null); setResult(null) }, 300) } if (!open) return null @@ -130,110 +96,89 @@ export function OrganizeNotebookDialog({ {open && ( <> - {/* Backdrop */} - - {/* Panel */} e.stopPropagation()} > {/* Header */} -
-
-
- +
+
+
+
-

{t('organizeNotebook.title')}

-

{notebookName}

+

{t('organizeNotebook.title')}

+

{notebookName}

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

{error}

+
+ +

{error}

)}
-

- {t('organizeNotebook.intro')} -

-
    - {[t('organizeNotebook.bulletThemes'), t('organizeNotebook.bulletSubfolders'), t('organizeNotebook.bulletPreview')].map(item => ( -
  • -
    - {item} -
  • - ))} -
+

{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')}

+
+

{t('organizeNotebook.analyzingTitle')}

+

{t('organizeNotebook.analyzingSubtitle')}

-
+
{[0, 1, 2].map(i => ( - + ))}
@@ -241,152 +186,94 @@ export function OrganizeNotebookDialog({ {/* PREVIEW */} {step === 'preview' && ( - - {/* Summary bar */} -
+ +
-

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

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

{error && ( -
- -

{error}

+
+ +

{error}

)} - {/* Groups */} -
- {editableGroups.map((group, idx) => ( - - {/* Group header */} -
-
- {group.isNew - ? - : - } -
- handleRenameGroup(idx, e.target.value)} - className="flex-1 bg-transparent text-[12px] font-semibold text-ink outline-none focus:text-brand-accent transition-colors min-w-0" - /> - {group.isNew && ( - - {t('organizeNotebook.badgeNew')} - - )} -
- - -
+ {editableGroups.map((group, idx) => ( + +
+
+ {group.isNew ? : }
- - {/* Notes list */} - - {expandedGroups.has(idx) && ( - -
- {group.notes.map(note => ( -
handleToggleNote(idx, note.id)} - > -
- -
- - {note.title || t('organizeNotebook.untitledNote')} - -
- ))} -
-
- )} -
- - {/* Collapsed count */} - {!expandedGroups.has(idx) && ( -
- {t('organizeNotebook.notesInGroup', { count: group.notes.length })} -
+ 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')}

+

{t('organizeNotebook.executingTitle')}

+

{t('organizeNotebook.executingSubtitle')}

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

{t('organizeNotebook.doneTitle')}

- {result && ( -

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

- )} +

{t('organizeNotebook.doneTitle')}

+ {result &&

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

}
)} @@ -394,47 +281,35 @@ export function OrganizeNotebookDialog({
- {/* Footer actions */} -
+ {/* Footer */} +
{step === 'idle' && ( - )} - {step === 'preview' && (
- -
)} - {step === 'done' && ( - )}