'use client'
import { useNoteEditorContext } from './note-editor-context'
import { NoteEditorToolbar } from './note-editor-toolbar'
import { NoteTitleBlock } from './note-title-block'
import { NoteContentArea } from './note-content-area'
import { EditorImages } from '@/components/editor-images'
import { ComparisonModal } from '@/components/comparison-modal'
import { FusionModal } from '@/components/fusion-modal'
import { ReminderDialog } from '@/components/reminder-dialog'
import { ContextualAIChat } from '@/components/contextual-ai-chat'
import { NoteDocumentInfoPanel } from '@/components/note-document-info-panel'
import { fr } from 'date-fns/locale/fr'
import { enUS } from 'date-fns/locale/en-US'
import { formatAbsoluteDateLocalized } from '@/lib/utils/format-localized-date'
import { ChevronRight } from 'lucide-react'
import { toast } from 'sonner'
import { Note } from '@/lib/types'
import { GhostTags } from '@/components/ghost-tags'
import { LabelBadge } from '@/components/label-badge'
import { NoteAttachments } from '@/components/note-attachments'
import { DocumentQAOverlay } from '@/components/document-qa-overlay'
import { useLanguage } from '@/lib/i18n'
import { useState } from 'react'
interface NoteEditorFullPageProps {
onClose: () => void
}
export function NoteEditorFullPage({ onClose }: NoteEditorFullPageProps) {
const { t, language } = useLanguage()
const dateLocale = language === 'fr' ? fr : enUS
const { state, actions, note, readOnly, notebooks, fileInputRef, globalLabels } = useNoteEditorContext()
const [docQAAttachment, setDocQAAttachment] = useState<{ id: string; fileName: string } | null>(null)
const [attachmentsCount, setAttachmentsCount] = useState(0)
const [uploadTrigger, setUploadTrigger] = useState(0)
const notebookName = notebooks.find(nb => nb.id === note.notebookId)?.name || null
const getLabelType = (name: string): 'ai' | 'user' => {
const found = globalLabels.find(l => l.name.toLowerCase() === name.toLowerCase())
return (found as any)?.type === 'ai' ? 'ai' : 'user'
}
return (
<>
{/* ── outer container ── */}
{/* ── main scrollable column ── */}
{/* TOOLBAR */}
setUploadTrigger(v => v + 1)} attachmentsCount={attachmentsCount} />
{/* BODY — max-w-4xl, responsive px, py-16 */}
{/* Breadcrumb + Title block */}
{/* Breadcrumb: Notebook › Date */}
{notebookName && {notebookName}}
{notebookName && }
{formatAbsoluteDateLocalized(new Date(note.contentUpdatedAt), language, 'MMM d, yyyy', dateLocale)}
{/* Title */}
{(state.labels.length > 0 || (state.filteredSuggestions.length > 0)) && (
{state.labels.map((label) => (
actions.handleRemoveLabel(label)}
/>
))}
{!readOnly && (
)}
)}
{/* Hero image — show first note image if present */}
{state.allImages.length > 0 && (
)}
{/* Content area — max-w-3xl for wider reading column */}
setDocQAAttachment(att)}
onCountChange={setAttachmentsCount}
triggerUpload={uploadTrigger}
/>
{/* ── Side panel: AI Chat ── */}
{state.aiOpen && (
actions.setAiOpen(false)}
noteTitle={state.title}
noteContent={state.content}
noteImages={state.allImages}
noteId={note.id}
onApplyToNote={(nc: string) => {
actions.setPreviousContentForCopilot(state.content)
actions.setContent(nc)
if (state.isMarkdown) actions.setShowMarkdownPreview(true)
}}
onUndoLastAction={state.previousContentForCopilot !== null ? () => { actions.setContent(state.previousContentForCopilot!); actions.setPreviousContentForCopilot(null) } : undefined}
lastActionApplied={state.previousContentForCopilot !== null}
notebooks={notebooks}
notebookId={note.notebookId ?? undefined}
notebookName={notebookName ?? undefined}
diagramInsertFormat={state.isMarkdown ? 'markdown' : 'html'}
onGenerateTitle={async () => {
const plain = state.content.replace(/<[^>]+>/g, ' ').trim()
const wordCount = plain.split(/\s+/).filter(Boolean).length
if (wordCount < 10) {
toast.error(t('ai.titleGenerationMinWords', { count: wordCount }))
return
}
actions.setIsProcessingAI(true)
try {
const res = await fetch('/api/ai/title-suggestions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: plain }),
})
if (res.ok) {
const data = await res.json()
const s = data.suggestions?.[0]?.title ?? ''
if (s) {
actions.setTitle(s)
toast.success(t('ai.titleApplied'))
} else {
toast.error(t('ai.titleGenerationFailed'))
}
} else {
toast.error(t('ai.titleGenerationError'))
}
} catch { toast.error(t('ai.networkErrorShort')) } finally { actions.setIsProcessingAI(false) }
}}
/>
)}
{/* ── Side panel: Document Info ── */}
{state.infoOpen && (
actions.setInfoOpen(false)}
onNoteRestored={(r: Note) => { actions.setContent(r.content || ''); actions.setTitle(r.title || ''); actions.setIsDirty(false) }}
/>
)}
{docQAAttachment && (
setDocQAAttachment(null)}
onApplyToNote={(content) => {
actions.setPreviousContentForCopilot(state.content)
actions.setContent(state.content + '\n\n' + content)
}}
/>
)}
>
)
}