From e9f83d0980b437b01aedd3f8713ae4762f6e4ddf Mon Sep 17 00:00:00 2001 From: admin-valentin Date: Sat, 1 Aug 2026 21:01:56 +0000 Subject: [PATCH] =?UTF-8?q?feat(CC-058):=20add=20AI=20Context=20&=20Source?= =?UTF-8?q?s=20page=20=E2=80=94=20per-request=20context=20manifest=20viewe?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/dashboard/ai/context/page.tsx | 178 ++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 src/app/dashboard/ai/context/page.tsx diff --git a/src/app/dashboard/ai/context/page.tsx b/src/app/dashboard/ai/context/page.tsx new file mode 100644 index 0000000..fd9e08e --- /dev/null +++ b/src/app/dashboard/ai/context/page.tsx @@ -0,0 +1,178 @@ +'use client'; + +import { useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { apiFetch } from '../../../../lib/api'; +import { useSession } from '../../../../components/session-provider'; + +interface AiRequest { + id: string; + purpose: string; + actionClass: string; + model: string; + templateVersion: string | null; + resultStatus: string; + costUsd: string | null; + contextManifest?: unknown; + createdAt: string; + completedAt: string | null; +} + +const STATUS_CFG: Record = { + pending: { label: 'Pending', cls: 'bg-amber-500/10 text-amber-700 dark:text-amber-300' }, + completed: { label: 'Completat', cls: 'bg-signal-ok/10 text-signal-ok' }, + failed: { label: 'Eșuat', cls: 'bg-signal-danger/10 text-signal-danger' }, + cancelled: { label: 'Anulat', cls: 'bg-muted text-ink-faint' }, +}; + +export default function AiContextPage() { + const { activeTenant } = useSession(); + const tenantId = activeTenant?.tenantId ?? ''; + const [selectedId, setSelectedId] = useState(null); + + const { data: requests = [], isLoading } = useQuery({ + queryKey: ['ai-requests', tenantId], + queryFn: () => apiFetch('/v1/ai-requests?limit=100', { tenantId }), + enabled: Boolean(tenantId), + }); + + const { data: selected } = useQuery({ + queryKey: ['ai-requests', tenantId, selectedId], + queryFn: () => apiFetch(`/v1/ai-requests/${selectedId}`, { tenantId }), + enabled: Boolean(selectedId && tenantId), + }); + + return ( +
+ {/* Sidebar: request list */} + + + {/* Main: context manifest viewer */} + {!selectedId ? ( +
+
+

🔍

+

+ Selectează o cerere AI din stânga pentru a vedea contextul complet — ce date au fost permise și ce model a primit. +

+
+
+ ) : !selected ? ( +
+

Se încarcă contextul…

+
+ ) : ( +
+
+

{selected.purpose}

+
+ {selected.actionClass} + {selected.model} + {selected.templateVersion && ( + template v{selected.templateVersion} + )} + {selected.costUsd && parseFloat(selected.costUsd) > 0 && ( + ${parseFloat(selected.costUsd).toFixed(6)} + )} + {new Date(selected.createdAt).toLocaleString('ro-RO')} +
+
+ + {/* Status */} +
+ + {(STATUS_CFG[selected.resultStatus] ?? STATUS_CFG.pending).label} + + {selected.completedAt && ( + + completat la {new Date(selected.completedAt).toLocaleTimeString('ro-RO')} + + )} +
+ + {/* Context Manifest */} +
+

+ Context Manifest +

+

+ Datele permise pentru această cerere AI — conform politicii de acces a platformei. +

+ {selected.contextManifest ? ( +
+                {JSON.stringify(selected.contextManifest, null, 2)}
+              
+ ) : ( +
+

+ Context manifest nu este disponibil pentru această cerere. +

+
+ )} +
+ + {/* Hash */} +
+

+ Hash Manifest +

+

+ {(selected as unknown as { contextManifestHash: string }).contextManifestHash ?? '—'} +

+
+
+ )} +
+ ); +}