'use client' import { useState, useEffect, useCallback, type ReactNode } from 'react' import { AnimatePresence } from 'framer-motion' import { useRouter, useSearchParams } from 'next/navigation' import { toast } from 'sonner' import type { Note } from '@/lib/types' import { getNoteById } from '@/app/actions/notes' import { NOTE_REQUEST_SAVE_EVENT } from '@/lib/note-change-sync' import { NOTE_PEEK_OPEN_EVENT, NOTE_PEEK_CLOSE_EVENT, type NotePeekOpenDetail, } from '@/lib/note-peek-sync' import { NoteEditorSplitPeek } from './note-editor-split-peek' import { useLanguage } from '@/lib/i18n' interface NoteEditorPeekHostProps { noteId: string fullPage?: boolean children: ReactNode } export function NoteEditorPeekHost({ noteId, fullPage, children }: NoteEditorPeekHostProps) { const router = useRouter() const searchParams = useSearchParams() const peekNoteId = searchParams.get('peekNote') const { t, language } = useLanguage() const isRtl = language === 'fa' || language === 'ar' const [peekState, setPeekState] = useState<{ note: Note; blockId?: string } | null>(null) const stripPeekFromUrl = useCallback(() => { if (!searchParams.get('peekNote')) return const params = new URLSearchParams(searchParams.toString()) params.delete('peekNote') const qs = params.toString() router.replace(qs ? `/home?${qs}` : '/home', { scroll: false }) }, [router, searchParams]) useEffect(() => { const onOpenPeek = (event: Event) => { const detail = (event as CustomEvent).detail if (!detail?.noteId) return if (detail.noteId === noteId) return void getNoteById(detail.noteId).then((fetched) => { if (fetched) { setPeekState({ note: fetched, blockId: detail.blockId }) } else { toast.error(t('notePeek.loadFailed')) } }) } const onClosePeek = () => setPeekState(null) window.addEventListener(NOTE_PEEK_OPEN_EVENT, onOpenPeek) window.addEventListener(NOTE_PEEK_CLOSE_EVENT, onClosePeek) return () => { window.removeEventListener(NOTE_PEEK_OPEN_EVENT, onOpenPeek) window.removeEventListener(NOTE_PEEK_CLOSE_EVENT, onClosePeek) } }, [noteId, t]) // Dashboard « Comparer / Lier » : ouvrir la note liée à droite dès que l’éditeur est monté. useEffect(() => { if (!peekNoteId || peekNoteId === noteId) return let cancelled = false void getNoteById(peekNoteId).then((fetched) => { if (cancelled) return if (fetched) { setPeekState(prev => (prev?.note.id === fetched.id ? prev : { note: fetched })) } else { toast.error(t('notePeek.loadFailed')) } }) return () => { cancelled = true } }, [peekNoteId, noteId, t]) const handleClosePeek = useCallback(() => { setPeekState(null) stripPeekFromUrl() }, [stripPeekFromUrl]) const handleOpenPeekFully = useCallback(() => { if (!peekState) return window.dispatchEvent(new CustomEvent(NOTE_REQUEST_SAVE_EVENT, { detail: { noteId, reason: 'before-peek-full-open' }, })) const params = new URLSearchParams(searchParams.toString()) params.set('openNote', peekState.note.id) params.delete('peekNote') router.replace(params.toString() ? `/home?${params.toString()}` : '/home', { scroll: false }) setPeekState(null) }, [noteId, peekState, router, searchParams]) const shellClass = fullPage ? 'flex flex-1 min-h-0 h-full w-full items-stretch overflow-hidden' : 'relative flex min-h-0 flex-1 flex-col overflow-hidden' return (
{children}
{peekState && ( router.replace('/home') : undefined } /> )}
) }