'use client' import { useState, useMemo } from 'react' import { Note } from '@/lib/types' import { format, formatDistanceToNow } from 'date-fns' import { fr } from 'date-fns/locale/fr' import { enUS } from 'date-fns/locale/en-US' import { X, Info, Clock, Hash, Book, FileText, Calendar, Tag, ChevronRight, Trash2, RotateCcw, Loader2, Check, History as HistoryIcon } from 'lucide-react' import { cn } from '@/lib/utils' import { useLanguage } from '@/lib/i18n' import { useNotebooks } from '@/context/notebooks-context' import { LabelBadge } from './label-badge' import { NoteHistoryModal } from './note-history-modal' import { enableNoteHistory, commitNoteHistory, getNoteHistory, deleteNoteHistoryEntry, restoreNoteVersion } from '@/app/actions/notes' import { useEffect } from 'react' type Tab = 'info' | 'versions' interface NoteDocumentInfoPanelProps { note: Note content: string onClose: () => void onNoteRestored?: (note: Note) => void } function getLocale(lang: string) { return lang === 'fr' ? fr : enUS } function wordCount(text: string) { return text.replace(/<[^>]+>/g, ' ').trim().split(/\s+/).filter(Boolean).length } function charCount(text: string) { return text.replace(/<[^>]+>/g, '').length } const noteTypeLabel: Record = { richtext: 'Rich Text', markdown: 'Markdown', text: 'Texte', checklist: 'Liste de tâches', } export function NoteDocumentInfoPanel({ note, content, onClose, onNoteRestored }: NoteDocumentInfoPanelProps) { const { t, language } = useLanguage() const { notebooks } = useNotebooks() const [activeTab, setActiveTab] = useState('info') const [showHistory, setShowHistory] = useState(false) const [historyEnabled, setHistoryEnabled] = useState(note.historyEnabled ?? false) const [isSavingVersion, setIsSavingVersion] = useState(false) const [versionSaved, setVersionSaved] = useState(false) const [historyEntries, setHistoryEntries] = useState([]) const [isLoadingHistory, setIsLoadingHistory] = useState(false) const [isDeleting, setIsDeleting] = useState(null) const [isRestoring, setIsRestoring] = useState(null) const locale = getLocale(language) useEffect(() => { if (activeTab === 'versions' && historyEnabled) { loadHistory() } }, [activeTab, historyEnabled, note.id]) const loadHistory = async () => { setIsLoadingHistory(true) try { const entries = await getNoteHistory(note.id, 50) setHistoryEntries(entries) } catch (e) { console.error(e) } finally { setIsLoadingHistory(false) } } const handleDeleteVersion = async (entryId: string) => { if (!confirm('Supprimer cette version ?')) return setIsDeleting(entryId) try { await deleteNoteHistoryEntry(note.id, entryId) setHistoryEntries(prev => prev.filter(e => e.id !== entryId)) } catch (e) { console.error(e) } finally { setIsDeleting(null) } } const handleRestoreVersion = async (entryId: string) => { setIsRestoring(entryId) try { const restored = await restoreNoteVersion(note.id, entryId) onNoteRestored?.(restored) loadHistory() } catch (e) { console.error(e) } finally { setIsRestoring(null) } } const notebook = useMemo( () => notebooks.find(nb => nb.id === note.notebookId), [notebooks, note.notebookId] ) const words = useMemo(() => wordCount(content), [content]) const chars = useMemo(() => charCount(content), [content]) const createdAt = note.createdAt ? new Date(note.createdAt as unknown as string) : null const updatedAt = note.contentUpdatedAt ? new Date(note.contentUpdatedAt as unknown as string) : null return ( <>
{/* Header tabs */}
{(['info', 'versions'] as Tab[]).map(tab => ( ))}
{/* Body */}
{/* ── INFO TAB ── */} {activeTab === 'info' && (
{/* Stats — grand display numbers */}
{words} mots
{chars} caractères
{notebook && (

Carnet

{notebook.name}

)}

Type

{noteTypeLabel[note.type] || note.type}

{createdAt && (

Créée le

{format(createdAt, 'd MMM yyyy', { locale })}

{formatDistanceToNow(createdAt, { addSuffix: true, locale })}

)} {updatedAt && (

Modifiée

{format(updatedAt, 'd MMM yyyy · HH:mm', { locale })}

{formatDistanceToNow(updatedAt, { addSuffix: true, locale })}

)} {(note.labels ?? []).length > 0 && (

Labels

{(note.labels ?? []).map(label => ( ))}
)}

ID

{note.id}

)} {/* ── VERSIONS TAB ── */} {activeTab === 'versions' && (
{!historyEnabled ? (

L'historique n'est pas activé pour cette note.

) : (

Versions sauvegardées

{/* Save version button */}
{/* Timeline */} {isLoadingHistory && historyEntries.length === 0 ? (

Chargement...

) : historyEntries.length === 0 ? (

Aucune version

) : (
{historyEntries.map((entry, idx) => { const colors = ['#E2E8F0', '#ACB995', '#E9ECEF'] const dotColor = colors[idx % colors.length] const isLatest = idx === 0 return (
{/* Dot */}
v{entry.version} {isLatest && ( Latest )}

{format(new Date(entry.createdAt), 'd MMM · HH:mm', { locale })} · {formatDistanceToNow(new Date(entry.createdAt), { addSuffix: true, locale })}

) })}
)} {/* Button to open the full modal (optional, but good to keep if user wants diff) */}
)}
)}
{/* NoteHistoryModal with correct props */} {showHistory && ( setShowHistory(v)} note={note} enabled={historyEnabled} onEnableHistory={async () => { await enableNoteHistory(note.id) setHistoryEnabled(true) }} onRestored={(restored) => { setShowHistory(false) onNoteRestored?.(restored) }} /> )} ) }