feat(cc-050): AI Execution History page
This commit is contained in:
parent
c92d3a81b5
commit
58b8a5f9ba
1 changed files with 96 additions and 0 deletions
96
src/app/dashboard/ai/history/page.tsx
Normal file
96
src/app/dashboard/ai/history/page.tsx
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
'use client';
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { apiFetch } from '../../../../lib/api';
|
||||
import type { AiRequest } from '../../../../lib/api';
|
||||
import { useSession } from '../../../../components/session-provider';
|
||||
|
||||
export default function AiHistoryPage() {
|
||||
const { activeTenant } = useSession();
|
||||
const tenantId = activeTenant?.tenantId ?? '';
|
||||
|
||||
const { data: requests = [], isLoading } = useQuery({
|
||||
queryKey: ['ai-requests', tenantId],
|
||||
queryFn: () => apiFetch<AiRequest[]>('/v1/ai-requests?limit=200', { tenantId }),
|
||||
enabled: Boolean(tenantId),
|
||||
staleTime: 30_000,
|
||||
});
|
||||
|
||||
function statusClass(status: string) {
|
||||
switch (status) {
|
||||
case 'completed': return 'bg-signal-ok text-white';
|
||||
case 'failed': return 'bg-signal-danger text-white';
|
||||
case 'pending': return 'bg-bronze-wash text-bronze-deep';
|
||||
default: return 'bg-paper-sunken text-ink-faint';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-5xl space-y-6">
|
||||
<div>
|
||||
<h1 className="font-display text-2xl font-semibold text-ink">Istoric Execuții AI</h1>
|
||||
<p className="mt-1 text-sm text-ink-faint">
|
||||
Toate cererile AI înregistrate pentru workspace —{' '}
|
||||
{isLoading ? '…' : `${requests.length} cereri`}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{isLoading ? (
|
||||
<p className="text-sm text-ink-faint">Se încarcă…</p>
|
||||
) : requests.length === 0 ? (
|
||||
<div className="card p-10 text-center">
|
||||
<p className="text-sm font-medium text-ink">Nicio cerere AI înregistrată</p>
|
||||
<p className="mt-1 text-xs text-ink-faint">
|
||||
Cererile AI sunt înregistrate automat la utilizare.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="card overflow-hidden">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b border-paper-sunken text-left">
|
||||
<th className="px-4 py-3 text-xs font-medium text-ink-faint">Data</th>
|
||||
<th className="px-4 py-3 text-xs font-medium text-ink-faint">Scop</th>
|
||||
<th className="px-4 py-3 text-xs font-medium text-ink-faint">Model</th>
|
||||
<th className="px-4 py-3 text-xs font-medium text-ink-faint">Clasă acțiune</th>
|
||||
<th className="px-4 py-3 text-right text-xs font-medium text-ink-faint">Cost USD</th>
|
||||
<th className="px-4 py-3 text-xs font-medium text-ink-faint">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{requests.map((req) => (
|
||||
<tr key={req.id} className="border-b border-paper-sunken last:border-0 hover:bg-paper-sunken/50 transition-colors">
|
||||
<td className="px-4 py-2.5 font-mono text-[11px] text-ink-faint whitespace-nowrap">
|
||||
{new Date(req.createdAt).toLocaleString('ro-RO', {
|
||||
month: 'short', day: 'numeric',
|
||||
hour: '2-digit', minute: '2-digit',
|
||||
})}
|
||||
</td>
|
||||
<td className="max-w-[200px] px-4 py-2.5">
|
||||
<p className="truncate text-sm text-ink capitalize">{req.purpose.replace(/_/g, ' ')}</p>
|
||||
</td>
|
||||
<td className="px-4 py-2.5 font-mono text-[11px] text-ink-faint">{req.model}</td>
|
||||
<td className="px-4 py-2.5">
|
||||
<span className="rounded bg-paper-sunken px-1.5 py-0.5 font-mono text-[10px] text-ink-faint">
|
||||
{req.actionClass}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-2.5 text-right font-mono text-xs text-ink">
|
||||
{req.costUsd ? `$${Number(req.costUsd).toFixed(4)}` : '—'}
|
||||
</td>
|
||||
<td className="px-4 py-2.5">
|
||||
<span className={`rounded-full px-2 py-0.5 text-[10px] font-medium ${statusClass(req.resultStatus)}`}>
|
||||
{req.resultStatus}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue