import { useState, useEffect } from "react"; import { Upload, Trash2, FileText, Check, Loader2, Database, X, } from "lucide-react"; import { getDocuments, uploadDocument, processDocument, deleteDocument, type ApiDocument, type DocumentStatus, } from "../../services/api"; interface KnowledgeManagementProps { open: boolean; onClose: () => void; } const getUserId = (): string | null => { const stored = localStorage.getItem("chatbot_user"); if (!stored) return null; return (JSON.parse(stored).user_id as string) ?? null; }; export default function KnowledgeManagement({ open, onClose, }: KnowledgeManagementProps) { const [documents, setDocuments] = useState([]); const [loadingDocs, setLoadingDocs] = useState(false); const [docsError, setDocsError] = useState(null); const [uploading, setUploading] = useState(false); const [uploadError, setUploadError] = useState(null); const [processing, setProcessing] = useState(null); const [deleting, setDeleting] = useState(null); useEffect(() => { if (!open) return; const userId = getUserId(); if (!userId) return; loadDocuments(userId); }, [open]); const loadDocuments = async (userId: string) => { setLoadingDocs(true); setDocsError(null); try { setDocuments(await getDocuments(userId)); } catch (err) { setDocsError( err instanceof Error ? err.message : "Failed to load documents" ); } finally { setLoadingDocs(false); } }; const handleFileUpload = async (e: React.ChangeEvent) => { const files = e.target.files; if (!files || files.length === 0) return; const userId = getUserId(); if (!userId) return; setUploading(true); setUploadError(null); for (let i = 0; i < files.length; i++) { const file = files[i]; try { const uploadRes = await uploadDocument(userId, file); const newDoc: ApiDocument = { id: uploadRes.data.id, filename: uploadRes.data.filename, status: "pending", file_size: file.size, file_type: file.name.split(".").pop() ?? "", created_at: new Date().toISOString(), }; setDocuments((prev) => [newDoc, ...prev]); await processDocumentById(userId, uploadRes.data.id); } catch (err) { setUploadError(err instanceof Error ? err.message : "Upload failed"); } } setUploading(false); e.target.value = ""; }; const processDocumentById = async (userId: string, docId: string) => { setProcessing(docId); setDocuments((prev) => prev.map((d) => d.id === docId ? { ...d, status: "processing" as DocumentStatus } : d ) ); try { await processDocument(userId, docId); setDocuments((prev) => prev.map((d) => d.id === docId ? { ...d, status: "completed" as DocumentStatus } : d ) ); } catch { setDocuments((prev) => prev.map((d) => d.id === docId ? { ...d, status: "failed" as DocumentStatus } : d ) ); } finally { setProcessing(null); } }; const handleDeleteDocument = async (docId: string) => { const userId = getUserId(); if (!userId) return; setDeleting(docId); try { await deleteDocument(userId, docId); setDocuments((prev) => prev.filter((d) => d.id !== docId)); } catch (err) { console.error("Delete failed:", err); } finally { setDeleting(null); } }; const deleteAllDocuments = async () => { if (!window.confirm("Are you sure you want to delete all documents?")) return; const userId = getUserId(); if (!userId) return; for (const doc of documents) { try { await deleteDocument(userId, doc.id); } catch { // continue deleting others } } setDocuments([]); }; const formatFileSize = (bytes: number) => { if (bytes < 1024) return bytes + " B"; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB"; return (bytes / (1024 * 1024)).toFixed(2) + " MB"; }; const formatDate = (isoString: string) => { return new Date(isoString).toLocaleString(); }; const renderStatus = (doc: ApiDocument) => { if (doc.status === "completed") { return (
Processed
); } if (doc.status === "processing" || processing === doc.id) { return (
Processing...
); } // pending or failed return ( ); }; if (!open) return null; return (
{/* Header */}

Knowledge Management

{/* Content */}
{/* Upload Section */}
{uploadError && (

{uploadError}

)}
{/* Documents List */}

Documents ({documents.length})

{documents.length > 0 && ( )}
{loadingDocs ? (
) : docsError ? (

{docsError}

) : documents.length === 0 ? (

No documents uploaded yet

Upload files to build your knowledge base

) : ( documents.map((doc) => (

{doc.filename}

{formatFileSize(doc.file_size)} •{" "} {formatDate(doc.created_at)}

{renderStatus(doc)}
)) )}
{/* Footer */}

Supported formats: PDF, DOCX, TXT

); }