"use client"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { ArrowLeft, Database, FileText, Layers, Loader2, RefreshCw, Settings as SettingsIcon, Star, Upload, } from "lucide-react"; import type { KnowledgeUploadPolicy } from "@/lib/knowledge-api"; import { formatKnowledgeTimestamp, resolveKbStatus, type KnowledgeBase, } from "@/lib/knowledge-helpers"; import type { TaskState } from "@/hooks/useKnowledgeProgress"; import type { HistoryEntry } from "@/hooks/useKnowledgeHistory"; import KbStatusBadge from "./KbStatusBadge"; import KbFilesTab from "./KbFilesTab"; import KbDocumentsSection from "./KbDocumentsSection"; import KbIndexVersionsSection from "./KbIndexVersionsSection"; import KbSettingsSection from "./KbSettingsSection"; type DetailSection = "files" | "add" | "versions" | "settings"; interface KnowledgeBaseDetailProps { kb: KnowledgeBase | null; uploadPolicy: KnowledgeUploadPolicy; task?: TaskState; history: HistoryEntry[]; onCreate: () => void; onUpload: (kbName: string, files: File[]) => Promise; onReindex: (kbName: string) => Promise; onRetry: (kbName: string) => Promise; onSetDefault: (kbName: string) => Promise; onDelete: (kbName: string) => Promise; onClearHistory: (kbName: string) => void; onBack?: () => void; } const SECTIONS: { key: DetailSection; label: string; Icon: typeof FileText; }[] = [ { key: "files", label: "Files", Icon: FileText }, { key: "add", label: "Add documents", Icon: Upload }, { key: "versions", label: "Index versions", Icon: Layers }, { key: "settings", label: "Settings", Icon: SettingsIcon }, ]; /** Sections that fill the detail body edge-to-edge (no max-w wrapper). */ const FULL_BLEED_SECTIONS = new Set(["files"]); export default function KnowledgeBaseDetail({ kb, uploadPolicy, task, history, onCreate, onUpload, onReindex, onRetry, onSetDefault, onDelete, onClearHistory, onBack, }: KnowledgeBaseDetailProps) { const { t } = useTranslation(); const [section, setSection] = useState("files"); const [retrySubmitting, setRetrySubmitting] = useState(false); if (!kb) { return (
{t("No knowledge base selected")}

{t( "Pick a knowledge base from the list, or create a new one to get started.", )}

); } const meta = kb.metadata || {}; const provider = kb.statistics?.rag_provider || "llamaindex"; const embeddingLabel = meta.embedding_model ? typeof meta.embedding_dim === "number" ? `${meta.embedding_model} · ${meta.embedding_dim}${t("d")}` : meta.embedding_model : t("Default embedding"); const updatedLabel = formatKnowledgeTimestamp(meta.last_updated) || t("Unknown time"); const lastIndexedLabel = formatKnowledgeTimestamp(meta.last_indexed_at); const isReindexingLocally = (task?.kind === "reindex" || task?.kind === "retry") && task.executing === true; const status = resolveKbStatus(kb); const canRetry = status === "error" && !kb.read_only; const handleRetry = async () => { if (!canRetry || retrySubmitting || isReindexingLocally) return; setRetrySubmitting(true); try { await onRetry(kb.name); } finally { setRetrySubmitting(false); } }; const fullBleed = FULL_BLEED_SECTIONS.has(section); return (
{/* Header */}
{onBack && ( )}

{kb.name}

{kb.is_default && ( {t("Default")} )} {kb.assigned && ( {kb.provenance_label || t("Assigned by admin")} )}

{provider} · {embeddingLabel} · {t("Updated")} {updatedLabel} {lastIndexedLabel ? ` · ${t("Last indexed")} ${lastIndexedLabel}` : ""}

{canRetry && ( )}
{/* Section nav */}
{/* Body */}
{section === "files" ? ( ) : (
{section === "add" && ( onClearHistory(kb.name)} onRetry={handleRetry} onUpload={(files) => kb.read_only ? Promise.resolve() : onUpload(kb.name, files) } /> )} {section === "versions" && ( kb.read_only ? Promise.resolve() : status === "error" ? handleRetry() : onReindex(kb.name) } /> )} {section === "settings" && ( kb.read_only ? Promise.resolve() : onSetDefault(kb.name) } onDelete={() => kb.read_only ? Promise.resolve() : onDelete(kb.name) } /> )}
)}
); }