"use client"; import { useState } from "react"; import { searchNoteSummaries, createNoteRelationship } from "@/lib/notes-client"; import type { NoteSummary } from "@/lib/types"; interface LinkNoteModalProps { noteId: string; workspaceId: string; existingLinkedIds: string[]; onLinked: () => void; onClose: () => void; } const RELATIONSHIP_TYPES = ["related", "parent", "child", "blocks", "blocked_by", "duplicate"] as const; export function LinkNoteModal({ noteId, workspaceId, existingLinkedIds, onLinked, onClose }: LinkNoteModalProps) { const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [selectedId, setSelectedId] = useState(null); const [relationshipType, setRelationshipType] = useState("related"); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [searched, setSearched] = useState(false); async function handleSearch(e: React.FormEvent) { e.preventDefault(); if (!query.trim()) return; try { const notes = await searchNoteSummaries(query.trim()); const filtered = notes.filter((n) => n.id !== noteId && !existingLinkedIds.includes(n.id)); setResults(filtered); setSearched(true); setSelectedId(null); } catch (err) { setError(err instanceof Error ? err.message : "Search failed"); } } async function handleLink() { if (!selectedId || saving) return; setSaving(true); setError(null); try { await createNoteRelationship({ id: crypto.randomUUID(), workspaceId, fromNoteId: noteId, toNoteId: selectedId, relationshipType, }); onLinked(); } catch (err) { setError(err instanceof Error ? err.message : "Failed to link note"); } finally { setSaving(false); } } return (
{ if (e.target === e.currentTarget) onClose(); }} >
Link Note
{error &&
{error}
}
setQuery(e.target.value)} placeholder="Search notes..." aria-label="Search notes to link" style={{ flex: 1 }} autoFocus />
{searched && results.length === 0 && (
No matching notes found.
)} {results.length > 0 && (
{results.map((note) => ( ))}
)} {selectedId && ( )}
); }