fix: Scan progress display — separate progress state, guard ScanResult render

- scanProgress state tracks live progress (not mixed into scanData)
- ScanResult only renders when scanData.services exists (prevents crash)
- Purple progress bar with spinner shows current step during scan
- Fixes: TypeError 's.services.filter' when progress data set as scanData

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-05 08:29:03 +02:00
parent d80cb9c8e4
commit ea8353f1a0
+24 -12
View File
@@ -27,6 +27,7 @@ export default function AgentPage() {
const [scanLoading, setScanLoading] = useState(false)
const [scanError, setScanError] = useState<string | null>(null)
const [scanData, setScanData] = useState<any>(null)
const [scanProgress, setScanProgress] = useState<string>('')
const { analyze, answerFollowUp, loading, error, result, history } = useAgentAnalysis()
const handleSubmit = async (e: React.FormEvent) => {
@@ -39,6 +40,7 @@ export default function AgentPage() {
setScanLoading(true)
setScanError(null)
setScanData(null)
setScanProgress('Scan wird gestartet...')
try {
// Step 1: Start async scan
const startRes = await fetch('/api/sdk/v1/agent/scan', {
@@ -57,27 +59,26 @@ export default function AgentPage() {
await new Promise(r => setTimeout(r, 5000))
const pollRes = await fetch(`/api/sdk/v1/agent/scan?scan_id=${scan_id}`)
if (!pollRes.ok) { attempts++; continue }
const status = await pollRes.json()
const pollData = await pollRes.json()
// Update progress message
if (status.progress) {
setScanError(null)
// Show progress as temporary "error" (will be cleared when done)
setScanData({ _progress: status.progress } as any)
if (pollData.progress) {
setScanProgress(pollData.progress)
}
if (status.status === 'completed' && status.result) {
setScanData(status.result)
if (pollData.status === 'completed' && pollData.result) {
setScanData(pollData.result)
setScanProgress('')
break
}
if (status.status === 'failed') {
throw new Error(status.error || 'Scan fehlgeschlagen')
if (pollData.status === 'failed') {
throw new Error(pollData.error || 'Scan fehlgeschlagen')
}
attempts++
}
if (attempts >= maxAttempts) throw new Error('Scan-Timeout (10 Minuten)')
} catch (e) {
setScanError(e instanceof Error ? e.message : 'Unbekannter Fehler')
setScanProgress('')
} finally {
setScanLoading(false)
}
@@ -141,6 +142,17 @@ export default function AgentPage() {
</button>
</form>
{/* Scan Progress */}
{scanProgress && tab === 'scan' && (
<div className="bg-purple-50 border border-purple-200 rounded-lg p-4 text-sm text-purple-700 flex items-center gap-3">
<svg className="animate-spin w-5 h-5 text-purple-500 shrink-0" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
</svg>
{scanProgress}
</div>
)}
{/* Error */}
{currentError && (
<div className="bg-red-50 border border-red-200 rounded-lg p-4 text-sm text-red-700">{currentError}</div>
@@ -158,8 +170,8 @@ export default function AgentPage() {
</div>
)}
{/* Scan Result */}
{tab === 'scan' && scanData && (
{/* Scan Result — only render when we have a complete response with services */}
{tab === 'scan' && scanData && scanData.services && (
<div className="bg-white border border-gray-200 rounded-xl p-6 shadow-sm">
<ScanResult data={scanData} />
</div>