feat: Scan state persists across navigation — resume polling on return
- URL, mode, tab, scan result persisted in localStorage - Active scan_id stored — polling resumes when returning to page - Scan results survive navigation to other SDK modules - 'Scan laeuft noch...' shown when returning to in-progress scan - Cleans up localStorage when scan completes or fails Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,15 +21,71 @@ const TABS: { id: AnalysisTab; label: string; desc: string }[] = [
|
||||
]
|
||||
|
||||
export default function AgentPage() {
|
||||
const [url, setUrl] = useState('')
|
||||
const [mode, setMode] = useState<AnalysisMode>('post_launch')
|
||||
const [tab, setTab] = useState<AnalysisTab>('quick')
|
||||
// Restore state from localStorage on mount
|
||||
const [url, setUrl] = useState(() => typeof window !== 'undefined' ? localStorage.getItem('agent-scan-url') || '' : '')
|
||||
const [mode, setMode] = useState<AnalysisMode>(() => (typeof window !== 'undefined' ? localStorage.getItem('agent-scan-mode') as AnalysisMode : null) || 'post_launch')
|
||||
const [tab, setTab] = useState<AnalysisTab>(() => (typeof window !== 'undefined' ? localStorage.getItem('agent-scan-tab') as AnalysisTab : null) || 'quick')
|
||||
const [scanLoading, setScanLoading] = useState(false)
|
||||
const [scanError, setScanError] = useState<string | null>(null)
|
||||
const [scanData, setScanData] = useState<any>(null)
|
||||
const [scanData, setScanData] = useState<any>(() => {
|
||||
if (typeof window === 'undefined') return null
|
||||
try { const s = localStorage.getItem('agent-scan-result'); return s ? JSON.parse(s) : null } catch { return null }
|
||||
})
|
||||
const [scanProgress, setScanProgress] = useState<string>('')
|
||||
const [activeScanId, setActiveScanId] = useState<string>(() => typeof window !== 'undefined' ? localStorage.getItem('agent-scan-id') || '' : '')
|
||||
const { analyze, answerFollowUp, loading, error, result, history } = useAgentAnalysis()
|
||||
|
||||
// Persist state to localStorage
|
||||
React.useEffect(() => { localStorage.setItem('agent-scan-url', url) }, [url])
|
||||
React.useEffect(() => { localStorage.setItem('agent-scan-mode', mode) }, [mode])
|
||||
React.useEffect(() => { localStorage.setItem('agent-scan-tab', tab) }, [tab])
|
||||
React.useEffect(() => { if (scanData?.services) localStorage.setItem('agent-scan-result', JSON.stringify(scanData)) }, [scanData])
|
||||
|
||||
// Resume polling if scan was in progress when page was left
|
||||
React.useEffect(() => {
|
||||
if (!activeScanId || scanData?.services) return
|
||||
let cancelled = false
|
||||
setScanLoading(true)
|
||||
setScanProgress('Scan laeuft noch...')
|
||||
const poll = async () => {
|
||||
while (!cancelled) {
|
||||
await new Promise(r => setTimeout(r, 5000))
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/agent/scan?scan_id=${activeScanId}`)
|
||||
if (!res.ok) continue
|
||||
const data = await res.json()
|
||||
if (data.progress) setScanProgress(data.progress)
|
||||
if (data.status === 'completed' && data.result) {
|
||||
setScanData(data.result)
|
||||
setScanProgress('')
|
||||
setScanLoading(false)
|
||||
localStorage.setItem('agent-scan-result', JSON.stringify(data.result))
|
||||
localStorage.removeItem('agent-scan-id')
|
||||
setActiveScanId('')
|
||||
return
|
||||
}
|
||||
if (data.status === 'failed') {
|
||||
setScanError(data.error || 'Scan fehlgeschlagen')
|
||||
setScanProgress('')
|
||||
setScanLoading(false)
|
||||
localStorage.removeItem('agent-scan-id')
|
||||
setActiveScanId('')
|
||||
return
|
||||
}
|
||||
if (data.status === 'not_found') {
|
||||
setScanProgress('')
|
||||
setScanLoading(false)
|
||||
localStorage.removeItem('agent-scan-id')
|
||||
setActiveScanId('')
|
||||
return
|
||||
}
|
||||
} catch { /* retry */ }
|
||||
}
|
||||
}
|
||||
poll()
|
||||
return () => { cancelled = true }
|
||||
}, []) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (!url.trim()) return
|
||||
@@ -51,6 +107,8 @@ export default function AgentPage() {
|
||||
if (!startRes.ok) throw new Error(`Scan konnte nicht gestartet werden: ${startRes.status}`)
|
||||
const { scan_id } = await startRes.json()
|
||||
if (!scan_id) throw new Error('Keine Scan-ID erhalten')
|
||||
setActiveScanId(scan_id)
|
||||
localStorage.setItem('agent-scan-id', scan_id)
|
||||
|
||||
// Step 2: Poll for results
|
||||
let attempts = 0
|
||||
@@ -68,6 +126,9 @@ export default function AgentPage() {
|
||||
if (pollData.status === 'completed' && pollData.result) {
|
||||
setScanData(pollData.result)
|
||||
setScanProgress('')
|
||||
localStorage.setItem('agent-scan-result', JSON.stringify(pollData.result))
|
||||
localStorage.removeItem('agent-scan-id')
|
||||
setActiveScanId('')
|
||||
break
|
||||
}
|
||||
if (pollData.status === 'failed') {
|
||||
|
||||
Reference in New Issue
Block a user