'use client' import { useState, useEffect, useMemo } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { Search, Sparkles, Link2, X, Folder } from 'lucide-react' export interface BlockSuggestion { blockId: string noteId: string noteTitle: string notebookName: string content: string snippet: string score?: number } interface BlockPickerProps { isOpen: boolean onClose: () => void currentNoteId?: string onSelectBlock: (block: BlockSuggestion) => void } export function BlockPicker({ isOpen, onClose, currentNoteId, onSelectBlock }: BlockPickerProps) { const [activeTab, setActiveTab] = useState<'suggestions' | 'search'>('suggestions') const [searchQuery, setSearchQuery] = useState('') const [suggestions, setSuggestions] = useState([]) const [searchResults, setSearchResults] = useState([]) const [loadingSuggestions, setLoadingSuggestions] = useState(false) const [loadingSearch, setLoadingSearch] = useState(false) // Load AI suggestions when opening useEffect(() => { if (!isOpen || !currentNoteId) return setLoadingSuggestions(true) fetch(`/api/blocks/suggestions?noteId=${currentNoteId}`) .then(r => r.json()) .then((data: { blocks: BlockSuggestion[] }) => setSuggestions(data.blocks || [])) .catch(() => setSuggestions([])) .finally(() => setLoadingSuggestions(false)) }, [isOpen, currentNoteId]) // Debounced search useEffect(() => { if (activeTab !== 'search') return if (!searchQuery.trim()) { setSearchResults([]) return } const timer = setTimeout(() => { setLoadingSearch(true) const params = new URLSearchParams({ q: searchQuery }) if (currentNoteId) params.set('excludeNoteId', currentNoteId) fetch(`/api/blocks/search?${params}`) .then(r => r.json()) .then((data: { blocks: BlockSuggestion[] }) => setSearchResults(data.blocks || [])) .catch(() => setSearchResults([])) .finally(() => setLoadingSearch(false)) }, 300) return () => clearTimeout(timer) }, [searchQuery, activeTab, currentNoteId]) if (!isOpen) return null const displayBlocks = activeTab === 'suggestions' ? suggestions : searchResults const isLoading = activeTab === 'suggestions' ? loadingSuggestions : loadingSearch return ( {isOpen && (
{/* Header */}

Living Block Picker

Connecter un bloc en temps réel

{/* Tabs */}
{(['suggestions', 'search'] as const).map(tab => ( ))}
{/* Search input */} {activeTab === 'search' && (
setSearchQuery(e.target.value)} placeholder="Rechercher un extrait de note..." className="w-full bg-white dark:bg-zinc-850 border border-[#D5D2CD] dark:border-neutral-800 rounded-xl pl-9 pr-4 py-2 text-xs outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500/20 transition-all font-sans" autoFocus />
)} {/* Block list */}
{isLoading ? (
Chargement des suggestions...
) : displayBlocks.length > 0 ? ( displayBlocks.map(block => ( )) ) : (
{activeTab === 'suggestions' ? 'Aucune suggestion disponible pour cette note.' : searchQuery ? 'Aucun bloc ne correspond à votre recherche.' : 'Tapez pour rechercher des blocs...'}
)}
)} ) }