Files
stack/apps/web/src/app/(dashboard)/admin/page.tsx
2026-03-13 13:33:45 +00:00

100 lines
3.6 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { api } from '@/lib/api';
interface SessionInfo {
id: string;
provider: string;
modelId: string;
createdAt: string;
promptCount: number;
channels: string[];
durationMs: number;
}
interface SessionsResponse {
sessions: SessionInfo[];
total: number;
}
export default function AdminPage(): React.ReactElement {
const [sessions, setSessions] = useState<SessionInfo[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
api<SessionsResponse>('/api/sessions')
.then((res) => setSessions(res.sessions))
.catch(() => {})
.finally(() => setLoading(false));
}, []);
return (
<div className="mx-auto max-w-4xl space-y-8">
<h1 className="text-2xl font-semibold">Admin</h1>
{/* User Management placeholder */}
<section>
<h2 className="mb-4 text-lg font-medium text-text-secondary">User Management</h2>
<div className="rounded-lg border border-surface-border bg-surface-card p-6 text-center">
<p className="text-sm text-text-muted">
User management will be available when the admin API is implemented
</p>
</div>
</section>
{/* Active Agent Sessions */}
<section>
<h2 className="mb-4 text-lg font-medium text-text-secondary">Active Agent Sessions</h2>
{loading ? (
<p className="text-sm text-text-muted">Loading sessions...</p>
) : sessions.length === 0 ? (
<div className="rounded-lg border border-surface-border bg-surface-card p-4">
<p className="text-sm text-text-muted">No active sessions</p>
</div>
) : (
<div className="overflow-hidden rounded-lg border border-surface-border">
<table className="w-full">
<thead>
<tr className="border-b border-surface-border bg-surface-elevated text-left text-xs text-text-muted">
<th className="px-4 py-2 font-medium">Session ID</th>
<th className="px-4 py-2 font-medium">Provider</th>
<th className="px-4 py-2 font-medium">Model</th>
<th className="hidden px-4 py-2 font-medium md:table-cell">Prompts</th>
<th className="hidden px-4 py-2 font-medium md:table-cell">Duration</th>
</tr>
</thead>
<tbody>
{sessions.map((s) => (
<tr key={s.id} className="border-b border-surface-border last:border-b-0">
<td className="max-w-[200px] truncate px-4 py-2 font-mono text-xs text-text-primary">
{s.id}
</td>
<td className="px-4 py-2 text-xs text-text-muted">{s.provider}</td>
<td className="px-4 py-2 text-xs text-text-muted">{s.modelId}</td>
<td className="hidden px-4 py-2 text-xs text-text-muted md:table-cell">
{s.promptCount}
</td>
<td className="hidden px-4 py-2 text-xs text-text-muted md:table-cell">
{formatDuration(s.durationMs)}
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</section>
</div>
);
}
function formatDuration(ms: number): string {
const seconds = Math.floor(ms / 1000);
if (seconds < 60) return `${seconds}s`;
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes}m ${seconds % 60}s`;
const hours = Math.floor(minutes / 60);
return `${hours}h ${minutes % 60}m`;
}