- COMP-139: Command palette for quick navigation - COMP-140: Accessibility improvements - COMP-141: Scroll animations with animate-on-scroll component - COMP-143: Demo workspace with seed data and demo banner - COMP-145: Keyboard navigation and shortcuts help Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-Claude) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
81 lines
1.9 KiB
TypeScript
81 lines
1.9 KiB
TypeScript
import { Suspense } from "react";
|
|
import { TraceList } from "@/components/trace-list";
|
|
import { DemoSeedTrigger } from "@/components/demo-seed-trigger";
|
|
import { DemoBanner } from "@/components/demo-banner";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
interface TraceItem {
|
|
id: string;
|
|
name: string;
|
|
status: "RUNNING" | "COMPLETED" | "ERROR";
|
|
startedAt: string;
|
|
endedAt: string | null;
|
|
durationMs: number | null;
|
|
tags: string[];
|
|
metadata: Record<string, unknown>;
|
|
isDemo?: boolean;
|
|
_count: {
|
|
decisionPoints: number;
|
|
spans: number;
|
|
events: number;
|
|
};
|
|
}
|
|
|
|
interface TracesResponse {
|
|
traces: TraceItem[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
totalPages: number;
|
|
}
|
|
|
|
async function getTraces(
|
|
limit = 50,
|
|
page = 1
|
|
): Promise<TracesResponse> {
|
|
try {
|
|
const res = await fetch(
|
|
`http://localhost:3000/api/traces?limit=${limit}&page=${page}`,
|
|
{ cache: "no-store" }
|
|
);
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to fetch traces: ${res.status}`);
|
|
}
|
|
|
|
return res.json();
|
|
} catch (error) {
|
|
console.error("Error fetching traces:", error);
|
|
return {
|
|
traces: [],
|
|
total: 0,
|
|
page: 1,
|
|
limit,
|
|
totalPages: 0,
|
|
};
|
|
}
|
|
}
|
|
|
|
export default async function DashboardPage() {
|
|
const data = await getTraces(50, 1);
|
|
|
|
const hasTraces = data.traces.length > 0;
|
|
const allTracesAreDemo =
|
|
hasTraces && data.traces.every((t) => t.isDemo === true);
|
|
|
|
return (
|
|
<DemoSeedTrigger hasTraces={hasTraces}>
|
|
{allTracesAreDemo && <DemoBanner allTracesAreDemo={allTracesAreDemo} />}
|
|
<Suspense fallback={<div className="p-8 text-zinc-400">Loading traces...</div>}>
|
|
<TraceList
|
|
initialTraces={data.traces}
|
|
initialTotal={data.total}
|
|
initialTotalPages={data.totalPages}
|
|
initialPage={data.page}
|
|
/>
|
|
</Suspense>
|
|
</DemoSeedTrigger>
|
|
);
|
|
}
|