"use client"; import { useState } from "react"; import { FileText, Plus, Search, Link as LinkIcon, } from "lucide-react"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- function timeAgo(dateStr: string): string { const diff = Date.now() - new Date(dateStr).getTime(); const hours = Math.floor(diff / 3600000); if (hours < 24) return `${hours}h ago`; const days = Math.floor(hours / 24); return `${days}d ago`; } interface KBDocument { id: string; title: string; content: string; createdBy: string; updatedAt: string; referencedBy: string[]; } // --------------------------------------------------------------------------- // Simple Markdown-ish renderer (handles headers, code blocks, tables, lists) // --------------------------------------------------------------------------- function renderMarkdown(text: string): React.ReactNode[] { const lines = text.split("\n"); const elements: React.ReactNode[] = []; let i = 0; while (i < lines.length) { const line = lines[i]!; // Code block if (line.startsWith("```")) { const lang = line.slice(3).trim(); const codeLines: string[] = []; i++; while (i < lines.length && !lines[i]!.startsWith("```")) { codeLines.push(lines[i]!); i++; } i++; // skip closing ``` elements.push(
{codeLines.join("\n")}
);
continue;
}
// Table (simplified: detect | pipes)
if (line.includes("|") && line.trim().startsWith("|")) {
const tableRows: string[] = [];
while (i < lines.length && lines[i]!.includes("|") && lines[i]!.trim().startsWith("|")) {
tableRows.push(lines[i]!);
i++;
}
// Filter out separator rows (|---|---|)
const dataRows = tableRows.filter((r) => !r.match(/^\|[\s-|]+\|$/));
if (dataRows.length > 0) {
const parseRow = (row: string) =>
row.split("|").filter((c) => c.trim() !== "").map((c) => c.trim());
const header = parseRow(dataRows[0]!);
const body = dataRows.slice(1).map(parseRow);
elements.push(
| {h} | ))}
|---|
| {cell} | ))}
{renderInline(line)}
); i++; } return elements; } function renderInline(text: string): React.ReactNode { // Handle inline code `...` const parts = text.split(/(`[^`]+`)/); return parts.map((part, i) => { if (part.startsWith("`") && part.endsWith("`")) { return (
{part.slice(1, -1)}
);
}
return part;
});
}
// ---------------------------------------------------------------------------
// Components
// ---------------------------------------------------------------------------
function DocListItem({
doc,
isSelected,
onClick,
}: {
doc: KBDocument;
isSelected: boolean;
onClick: () => void;
}) {
return (
);
}
function DocDetail({ doc }: { doc: KBDocument }) {
return (