spb/social-runtime-crawler
Public
TypeScript 91.8%
HTML 3.2%
JavaScript 3%
SQL 1.4%
CSS 0.7%
1"use client";23import Link from "next/link";4import { useApi } from "@/lib/api";5import { ago, fmtDate, truncate } from "@/lib/format";6import { Empty, Panel, Skeleton, StatusPill, Table, Tag } from "@/components/ui";78interface Row {9 session_id: string;10 platform: string;11 account_alias: string;12 mode: string | null;13 goal: string | null;14 started_at: string;15 ended_at: string | null;16 health: string;17 actions: number;18 entities: number;19 schemas: number;20 patterns: number;21 ended_because: string | null;22}2324export default function Sessions() {25 const { data, loading } = useApi<Row[]>("/sessions?limit=200", { refreshMs: 10_000 });26 return (27 <div className="space-y-4">28 <h1 className="text-2xl font-semibold tracking-tight">Sessions</h1>29 <Panel pad={false}>30 <div className="p-4">31 {loading ? (32 <Skeleton rows={8} />33 ) : data?.length ? (34 <Table head={["status", "platform", "goal", "mode", "steps", "entities", "schemas", "learned", "started", "ended"]}>35 {data.map((r) => (36 <tr key={r.session_id}>37 <td>38 <StatusPill status={r.ended_at ? (r.health === "auth_required" ? "auth_required" : "done") : r.health} />39 </td>40 <td>41 <Tag>{r.platform}</Tag>42 <div className="text-[10px] text-dim mono">{r.account_alias}</div>43 </td>44 <td className="max-w-[420px]">45 <Link href={`/sessions/${r.session_id}`} className="hover:text-cyan">46 {truncate(r.goal ?? "(no goal)", 90)}47 </Link>48 <div className="text-[10px] text-dim mono">{r.session_id}</div>49 </td>50 <td className="text-fg-2">{r.mode ?? "—"}</td>51 <td className="mono">{r.actions}</td>52 <td className="mono">{r.entities}</td>53 <td className="mono">{r.schemas}</td>54 <td className="mono">{r.patterns}</td>55 <td className="text-dim whitespace-nowrap" title={fmtDate(r.started_at)}>56 {ago(r.started_at)}57 </td>58 <td className="text-dim whitespace-nowrap">{r.ended_because ?? (r.ended_at ? "—" : "running")}</td>59 </tr>60 ))}61 </Table>62 ) : (63 <Empty>No sessions yet.</Empty>64 )}65 </div>66 </Panel>67 </div>68 );69}70