/** * DocCasePanel — links from a document page to any narrative case files * that reference it. * * No detective surfacing. No evidence/hypothesis/contradiction IDs. Just * the cases that drew on this document, presented as story cards. */ import Link from "next/link"; interface ReportRow { slug: string; topic: string; topic_pt_br: string | null; opening: string } export async function DocBureauPanel({ docId }: { docId: string }) { const { readdir, readFile } = await import("node:fs/promises"); const path = await import("node:path"); const dir = path.join(process.env.CASE_ROOT || "/data/ufo/case", "reports"); let reports: ReportRow[] = []; try { const files = await readdir(dir); for (const f of files) { if (!f.endsWith(".md")) continue; const md = await readFile(path.join(dir, f), "utf-8"); if (!md.includes(docId)) continue; const topicMatch = md.match(/topic:\s*"([^"]+)"/); const topicPtMatch = md.match(/topic_pt_br:\s*"([^"]+)"/); const bodyMatch = md.match(/^---[\s\S]+?\n---\n([\s\S]+)$/); const body = bodyMatch?.[1] ?? ""; // First non-heading paragraph as opening hook. const opening = body .split("\n") .find((l) => l.trim().length > 0 && !l.startsWith("#") && !l.startsWith(">") && !l.startsWith("|") && !l.startsWith("---")) ?.slice(0, 240) ?? ""; reports.push({ slug: f.replace(/\.md$/, ""), topic: topicMatch?.[1] ?? f, topic_pt_br: topicPtMatch?.[1] ?? null, opening, }); } } catch { /* fine — no reports yet */ } if (reports.length === 0) { return null; } return (
// Casos narrados que citam este documento
{reports.map((r) => (
{r.topic_pt_br || r.topic}
{r.opening && (
{r.opening}
)}
/c/{r.slug} →
))}
); }