Jai-rathore29's picture
Deploy: DocAgent backend (deterministic date-anomaly fix)
f65e025
Raw
History Blame Contribute Delete
4.78 kB
"use client";
import { useEffect, useState } from "react";
import {
AlertTriangle,
Download,
FileSearch,
LayoutGrid,
ScrollText,
Table2,
} from "lucide-react";
import type { Citation, DocumentDetail } from "@/lib/types";
import DocumentViewer from "@/components/DocumentViewer";
import FieldsPanel from "@/components/FieldsPanel";
import ClassifyPanel from "@/components/ClassifyPanel";
import SummaryPanel from "@/components/SummaryPanel";
import ExportPanel from "@/components/ExportPanel";
import ProcessingBar from "@/components/ProcessingBar";
type Tab = "viewer" | "fields" | "classify" | "summary" | "export";
const TABS: { id: Tab; label: string; icon: any }[] = [
{ id: "viewer", label: "Viewer", icon: FileSearch },
{ id: "fields", label: "Fields & Tables", icon: Table2 },
{ id: "classify", label: "Classification", icon: LayoutGrid },
{ id: "summary", label: "Summary", icon: ScrollText },
{ id: "export", label: "Export", icon: Download },
];
export default function Workspace({
detail,
provider,
focusCitation,
onRefresh,
}: {
detail: DocumentDetail | null;
provider: string | null;
focusCitation: Citation | null;
onRefresh: () => void;
}) {
const [tab, setTab] = useState<Tab>("viewer");
useEffect(() => {
if (focusCitation) setTab("viewer");
}, [focusCitation]);
const anomalyCount = detail?.anomalies?.length ?? 0;
if (!detail) {
return (
<div className="flex h-full flex-col items-center justify-center px-6 text-center">
<div className="relative mb-5">
<div className="absolute inset-0 rounded-2xl bg-brand-500/10 blur-2xl" />
<div className="relative flex h-16 w-16 items-center justify-center rounded-2xl border border-white/[0.06] bg-surface-900">
<FileSearch className="text-white/30" size={28} />
</div>
</div>
<h2 className="text-base font-semibold text-white/70">Your workspace</h2>
<p className="mt-1.5 max-w-sm text-sm leading-relaxed text-white/40">
Upload a document to view it here alongside extracted fields,
classification, summary, and export controls.
</p>
<div className="mt-6 grid grid-cols-2 gap-2 text-left">
{[
["Viewer", "See pages with source highlights"],
["Fields", "Structured data + confidence"],
["Classify", "Auto document-type detection"],
["Export", "JSON · CSV · Excel"],
].map(([t, d]) => (
<div
key={t}
className="rounded-xl border border-white/[0.05] bg-surface-900/50 px-3 py-2.5"
>
<p className="text-xs font-medium text-white/70">{t}</p>
<p className="mt-0.5 text-[11px] text-white/35">{d}</p>
</div>
))}
</div>
</div>
);
}
return (
<div className="flex h-full flex-col">
<ProcessingBar detail={detail} />
{/* tabs */}
<div className="flex items-center gap-1 px-3 py-2">
{TABS.map((t) => {
const Icon = t.icon;
const active = tab === t.id;
return (
<button
key={t.id}
onClick={() => setTab(t.id)}
className={`relative flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition ${
active
? "bg-white/[0.07] text-white shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]"
: "text-white/45 hover:bg-white/[0.03] hover:text-white/75"
}`}
>
<Icon size={13} className={active ? "text-brand-300" : ""} />
{t.label}
{t.id === "fields" && anomalyCount > 0 && (
<span className="ml-0.5 flex items-center gap-0.5 rounded-full bg-amber-500/20 px-1.5 text-[10px] font-semibold text-amber-300">
<AlertTriangle size={9} />
{anomalyCount}
</span>
)}
</button>
);
})}
</div>
<div className="hairline opacity-60" />
{/* body */}
<div className="min-h-0 flex-1 overflow-hidden">
{tab === "viewer" && (
<DocumentViewer detail={detail} focusCitation={focusCitation} />
)}
{tab === "fields" && (
<FieldsPanel detail={detail} provider={provider} onRefresh={onRefresh} />
)}
{tab === "classify" && (
<ClassifyPanel detail={detail} provider={provider} onRefresh={onRefresh} />
)}
{tab === "summary" && (
<SummaryPanel detail={detail} provider={provider} onRefresh={onRefresh} />
)}
{tab === "export" && <ExportPanel detail={detail} />}
</div>
</div>
);
}