import React from "react"; import { useEffect, useMemo, useState } from "react"; import { deleteDocument, listDocuments, searchDocuments } from "../../services/api"; export default function DocumentPicker({ value, onSelect, values = [], onSelectMany, multiSelect = false, disabled = false, label = "Use previously uploaded document", reloadToken = 0, }) { const [documents, setDocuments] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [search, setSearch] = useState(""); const load = async (query = "") => { setLoading(true); setError(""); try { const response = query.trim() ? await searchDocuments(query.trim(), 100) : await listDocuments({ limit: 100 }); const fetchedDocs = Array.isArray(response?.data) ? response.data : []; setDocuments(fetchedDocs); // Clean up selections: remove any IDs that do not exist in the fetched database documents if (!query.trim() && fetchedDocs.length > 0) { const fetchedIds = new Set(fetchedDocs.map((d) => String(d.id))); const validValues = (values || []).map(String).filter((id) => fetchedIds.has(id)); if (validValues.length !== (values || []).length) { if (multiSelect && onSelectMany) { const nextDocs = fetchedDocs.filter((d) => validValues.includes(String(d.id))); onSelectMany(nextDocs); } else if (!multiSelect && onSelect) { const stillExists = fetchedDocs.some((d) => String(d.id) === String(value)); if (!stillExists) { onSelect(null); } } } } } catch (err) { setError(err?.response?.data?.detail || err?.message || "Failed to load documents"); setDocuments([]); } finally { setLoading(false); } }; useEffect(() => { void load(); }, [reloadToken]); const handleDelete = async (docId) => { if (!window.confirm("Are you sure you want to delete this document? This action cannot be undone.")) return; try { setLoading(true); await deleteDocument(docId); // Update selections if the deleted doc was selected if (multiSelect && onSelectMany) { const current = new Set((values || []).map((id) => String(id))); if (current.has(String(docId))) { current.delete(String(docId)); onSelectMany(documents.filter(d => current.has(String(d.id)) && String(d.id) !== String(docId))); } } else if (!multiSelect && onSelect && String(value) === String(docId)) { onSelect(null); } await load(search); } catch (err) { alert(err?.response?.data?.detail || err?.message || "Failed to delete document"); } finally { setLoading(false); } }; const selectedDocument = useMemo( () => documents.find((doc) => String(doc.id) === String(value || "")) || null, [documents, value], ); const selectedSet = useMemo(() => new Set((values || []).map((id) => String(id))), [values]); return (

{label}

setSearch(e.target.value)} placeholder="Search by filename" className="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm" disabled={disabled || loading} />
{documents.length === 0 ? (

No documents found

) : ( documents.map((doc) => { const isChecked = multiSelect ? selectedSet.has(String(doc.id)) : String(value) === String(doc.id); return (
); }) )}
{multiSelect ? (

Selected: {values.length} document(s)

) : selectedDocument && (

Selected: {selectedDocument.filename}

)} {error &&

{error}

}
); }