'use client'
import { useState, useRef } from 'react'
import { useNoteEditorContext } from './note-editor-context'
import { LabelManager } from '@/components/label-manager'
import { LabelBadge } from '@/components/label-badge'
import { GhostTags } from '@/components/ghost-tags'
import { EditorImages } from '@/components/editor-images'
import { TitleSuggestions } from '@/components/title-suggestions'
import { NoteTypeSelector } from '@/components/note-type-selector'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import {
X, Plus, Palette, Image as ImageIcon, Bell, Eye, Link as LinkIcon, Sparkles,
Maximize2, Copy, ArrowLeft, ChevronRight, PanelRight, Check, Loader2, Save, MoreHorizontal,
Trash2, LogOut, Wand2, Share2
} from 'lucide-react'
import { NoteShareDialog } from './note-share-dialog'
import { deleteNote, leaveSharedNote } from '@/app/actions/notes'
import { useRefresh } from '@/lib/use-refresh'
import { useLanguage } from '@/lib/i18n'
import { NOTE_COLORS, NoteColor, Note } from '@/lib/types'
import { cn } from '@/lib/utils'
import { toast } from 'sonner'
import { format } from 'date-fns'
interface NoteEditorToolbarProps {
mode: 'fullPage' | 'dialog'
onClose: () => void
}
export function NoteEditorToolbar({ mode, onClose }: NoteEditorToolbarProps) {
const { state, actions, note, readOnly, fullPage, notebooks, fileInputRef } = useNoteEditorContext()
const { t } = useLanguage()
const { refreshNotes } = useRefresh()
const [isConverting, setIsConverting] = useState(false)
const [shareOpen, setShareOpen] = useState(false)
const notebookName = notebooks.find(nb => nb.id === note.notebookId)?.name || null
// Snapshot for undo — stored in a ref so the toast callback isn't a stale closure
const undoSnapshotRef = useRef<{ content: string; noteType: string } | null>(null)
const handleConvertToRichtext = async () => {
if (isConverting || !state.content.trim()) return
setIsConverting(true)
// Capture snapshot BEFORE converting
const snapshot = { content: state.content, noteType: state.noteType }
undoSnapshotRef.current = snapshot
try {
let html: string
if (state.noteType === 'markdown') {
// Proper markdown → HTML via marked (no AI needed)
const { marked } = await import('marked')
html = await marked(state.content, { async: false }) as string
} else {
// Plain text → wrap paragraphs in
tags
html = state.content
.split(/\n{2,}/)
.map(para => `
${para.trim().replace(/\n/g, '
')}
`)
.join('')
}
actions.setContent(html)
actions.setNoteType('richtext')
toast.success(t('notes.convertedToRichText') || 'Converted to rich text', {
duration: 8000,
action: {
label: t('notes.undo') || '↩ Undo',
onClick: () => {
const snap = undoSnapshotRef.current
if (!snap) return
actions.setContent(snap.content)
actions.setNoteType(snap.noteType as any)
undoSnapshotRef.current = null
toast.info(t('ai.undoApplied') || 'Conversion undone')
},
},
})
} catch {
toast.error(t('notes.transformFailed') || 'Conversion failed')
} finally {
setIsConverting(false)
}
}
if (mode === 'fullPage') {
return (
{/* Left: back */}
{/* Right: status + type + AI + Info */}
{/* Save status */}
{state.isSaving
? <>Saving…>
: state.isDirty
? <>Modified>
: <>Saved>}
{/* Note type */}
{ actions.setNoteType(newType); actions.setIsDirty(true) }}
compact
/>
{/* Preview toggle — icon only */}
{(state.noteType === 'text' || state.noteType === 'markdown') && !readOnly && (
)}
{/* Convert to Rich Text — icon only */}
{(state.noteType === 'text' || state.noteType === 'markdown') && !readOnly && (
)}
{/* AI — icon only */}
{/* Save — icon only */}
{!readOnly && (
)}
{/* Share button */}
{!readOnly && (
)}
{/* Three-dot options menu */}
{!readOnly && (
{
try {
await deleteNote(note.id)
refreshNotes(note.notebookId)
toast.success('Note supprimée.')
onClose()
} catch { toast.error('Impossible de supprimer.') }
}}
className="text-red-600 dark:text-red-400 focus:text-red-600"
>
Supprimer la note
)}
{/* Share Dialog portal */}
{shareOpen && (
setShareOpen(false)}
/>
)}
{/* Info panel toggle — rightmost, icon only */}
)
}
// Dialog toolbar
return (
{!readOnly && (
<>
{/* Reminder */}
{/* Add Image */}
{/* Add Link */}
{ actions.setNoteType(newType); if (newType !== 'markdown') actions.setShowMarkdownPreview(false) }} />
{state.noteType === 'markdown' && (
)}
{/* AI Copilot */}
{state.noteType !== 'checklist' && (
)}
{/* Size Selector */}
{(['small', 'medium', 'large'] as const).map((s) => (
))}
{/* Color Picker */}
{Object.entries(NOTE_COLORS).map(([colorName, classes]) => (
{/* Label Manager */}
>
)}
{readOnly && (
{t('notes.sharedReadOnly')}
)}
{readOnly ? (
<>
>
) : (
<>
>
)}
)
}