fix: fichier manquant convert-notebook-dialog.tsx
Some checks failed
CI / Lint, Unit Tests & Build (push) Successful in 4m51s
CI / Deploy production (on server) (push) Failing after 2s

This commit is contained in:
Antigravity
2026-07-11 16:25:35 +00:00
parent 5eba211061
commit 4d029d3ebe

View File

@@ -0,0 +1,157 @@
'use client'
import { useState } from 'react'
import { motion, AnimatePresence } from 'motion/react'
import { FileText, FolderOpen, ChevronDown, Loader2, X } from 'lucide-react'
import { useLanguage } from '@/lib/i18n'
import type { Notebook } from '@/lib/types'
interface ConvertNotebookDialogProps {
open: boolean
idea: { id: string; title: string } | null
notebooks: Notebook[]
defaultNotebookId: string | null | undefined
onClose: () => void
onConfirm: (notebookId: string | null) => void
}
export function ConvertNotebookDialog({ open, idea, notebooks, defaultNotebookId, onClose, onConfirm }: ConvertNotebookDialogProps) {
const { t } = useLanguage()
const [showNotebookSelect, setShowNotebookSelect] = useState(false)
const [selectedNotebookId, setSelectedNotebookId] = useState<string | null>(defaultNotebookId ?? null)
const selectedNotebook = notebooks.find(nb => nb.id === selectedNotebookId)
const [loading, setLoading] = useState(false)
const handleConfirm = () => {
setLoading(true)
onConfirm(selectedNotebookId)
}
return (
<AnimatePresence>
{open && idea && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="fixed inset-0 z-[90] flex items-center justify-center bg-black/40 backdrop-blur-sm p-4"
onClick={(e) => { if (e.target === e.currentTarget) onClose() }}
role="dialog"
aria-modal="true"
aria-label={t('brainstorm.convertTitle') || 'Create note from idea'}
>
<motion.div
initial={{ scale: 0.92, y: 20 }}
animate={{ scale: 1, y: 0 }}
exit={{ scale: 0.92, y: 20 }}
transition={{ type: 'spring', stiffness: 340, damping: 30 }}
className="bg-memento-paper dark:bg-zinc-900 rounded-3xl shadow-2xl border border-border/40 w-full max-w-md overflow-hidden"
onClick={(e) => e.stopPropagation()}
>
<div className="px-6 py-5 border-b border-border/20 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-9 h-9 rounded-xl bg-emerald-500/10 flex items-center justify-center">
<FileText size={16} className="text-emerald-600 dark:text-emerald-400" />
</div>
<div>
<h3 className="font-memento-serif text-base font-medium text-ink dark:text-dark-ink">
{t('brainstorm.convertTitle') || 'Create note from idea'}
</h3>
<p className="text-[10px] text-concrete uppercase tracking-widest font-bold">
{t('brainstorm.convertSubtitle') || 'Choose where to save this note'}
</p>
</div>
</div>
<button
onClick={onClose}
className="p-1.5 rounded-lg text-concrete hover:text-ink hover:bg-black/5 dark:hover:bg-white/5 transition-colors cursor-pointer"
aria-label={t('common.close') || 'Close'}
>
<X size={16} />
</button>
</div>
<div className="px-6 py-5 space-y-4">
<div className="p-4 rounded-2xl bg-white/60 dark:bg-white/5 border border-border/30">
<p className="text-[10px] uppercase tracking-widest font-bold text-concrete mb-2">
{t('brainstorm.ideaLabel') || 'Idea'}
</p>
<p className="text-sm font-memento-serif text-ink dark:text-dark-ink leading-relaxed line-clamp-3">
{idea.title}
</p>
</div>
<div>
<p className="text-[10px] uppercase tracking-widest font-bold text-concrete mb-2">
{t('brainstorm.destinationLabel') || 'Notes will be saved to'}
</p>
<button
onClick={() => setShowNotebookSelect(!showNotebookSelect)}
className="w-full flex items-center justify-between p-3 rounded-xl bg-white/60 dark:bg-white/5 border border-border/30 hover:border-emerald-500/40 transition-colors cursor-pointer"
>
<div className="flex items-center gap-2.5">
<div className="w-7 h-7 rounded-lg bg-emerald-500/10 flex items-center justify-center shrink-0">
<FolderOpen size={13} className="text-emerald-600" />
</div>
<span className="text-sm font-medium text-ink dark:text-dark-ink truncate">
{selectedNotebook?.name || t('brainstorm.noNotebook') || 'No notebook'}
</span>
</div>
<ChevronDown size={14} className={`text-concrete transition-transform ${showNotebookSelect ? 'rotate-180' : ''}`} />
</button>
<AnimatePresence>
{showNotebookSelect && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.2 }}
className="overflow-hidden"
>
<div className="mt-1 max-h-48 overflow-y-auto rounded-xl border border-border/30 bg-white dark:bg-zinc-800 shadow-lg">
<button
onClick={() => { setSelectedNotebookId(null); setShowNotebookSelect(false) }}
className="w-full text-left px-3 py-2.5 hover:bg-emerald-500/5 transition-colors text-sm text-concrete cursor-pointer"
>
{t('brainstorm.noNotebook') || 'No notebook'}
</button>
{notebooks.map(nb => (
<button
key={nb.id}
onClick={() => { setSelectedNotebookId(nb.id); setShowNotebookSelect(false) }}
className={`w-full text-left px-3 py-2.5 hover:bg-emerald-500/5 transition-colors text-sm cursor-pointer flex items-center gap-2 ${selectedNotebookId === nb.id ? 'text-emerald-600 font-medium' : 'text-ink dark:text-dark-ink'}`}
>
<FolderOpen size={12} className="shrink-0 opacity-50" />
<span className="truncate">{nb.name}</span>
</button>
))}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
<div className="px-6 py-4 border-t border-border/20 flex items-center justify-end gap-3">
<button
onClick={onClose}
disabled={loading}
className="px-4 py-2.5 rounded-xl text-sm font-medium text-concrete hover:text-ink hover:bg-black/5 dark:hover:bg-white/5 transition-colors cursor-pointer"
>
{t('common.cancel')}
</button>
<button
onClick={handleConfirm}
disabled={loading}
className="px-5 py-2.5 rounded-xl bg-emerald-600 hover:bg-emerald-700 text-white text-sm font-bold uppercase tracking-wider transition-colors cursor-pointer disabled:opacity-50 flex items-center gap-2"
>
{loading ? <><Loader2 size={14} className="animate-spin" /> {t('common.creating') || 'Creating…'}</> : <><FileText size={14} /> {t('brainstorm.createNote') || 'Create note'}</>}
</button>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
)
}