Files
breakpilot-lehrer/admin-lehrer/app/(admin)/infrastructure/middleware/useMiddlewareAdmin.ts
Benjamin Admin b681ddb131 [split-required] Split 58 monoliths across Python, Go, TypeScript (Phases 1-3)
Phase 1 — Python (klausur-service): 5 monoliths → 36 files
- dsfa_corpus_ingestion.py (1,828 LOC → 5 files)
- cv_ocr_engines.py (2,102 LOC → 7 files)
- cv_layout.py (3,653 LOC → 10 files)
- vocab_worksheet_api.py (2,783 LOC → 8 files)
- grid_build_core.py (1,958 LOC → 6 files)

Phase 2 — Go (edu-search-service, school-service): 8 monoliths → 19 files
- staff_crawler.go (1,402 → 4), policy/store.go (1,168 → 3)
- policy_handlers.go (700 → 2), repository.go (684 → 2)
- search.go (592 → 2), ai_extraction_handlers.go (554 → 2)
- seed_data.go (591 → 2), grade_service.go (646 → 2)

Phase 3 — TypeScript (admin-lehrer): 45 monoliths → 220+ files
- sdk/types.ts (2,108 → 16 domain files)
- ai/rag/page.tsx (2,686 → 14 files)
- 22 page.tsx files split into _components/ + _hooks/
- 11 component files split into sub-components
- 10 SDK data catalogs added to loc-exceptions
- Deleted dead backup index_original.ts (4,899 LOC)

All original public APIs preserved via re-export facades.
Zero new errors: Python imports verified, Go builds clean,
TypeScript tsc --noEmit shows only pre-existing errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 17:28:57 +02:00

168 lines
4.6 KiB
TypeScript

'use client'
import { useEffect, useState, useCallback } from 'react'
import type { MiddlewareConfig, RateLimitIP, MiddlewareEvent, MiddlewareStats, TabId } from './types'
export function useMiddlewareAdmin() {
const [configs, setConfigs] = useState<MiddlewareConfig[]>([])
const [ipList, setIpList] = useState<RateLimitIP[]>([])
const [events, setEvents] = useState<MiddlewareEvent[]>([])
const [stats, setStats] = useState<MiddlewareStats[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [activeTab, setActiveTab] = useState<TabId>('overview')
const [actionLoading, setActionLoading] = useState<string | null>(null)
// IP Form
const [newIP, setNewIP] = useState('')
const [newIPType, setNewIPType] = useState<'whitelist' | 'blacklist'>('whitelist')
const [newIPReason, setNewIPReason] = useState('')
const fetchData = useCallback(async () => {
setLoading(true)
setError(null)
try {
const [configsRes, ipListRes, eventsRes, statsRes] = await Promise.all([
fetch('/api/admin/middleware'),
fetch('/api/admin/middleware/rate-limit/ip-list'),
fetch('/api/admin/middleware/events?limit=50'),
fetch('/api/admin/middleware/stats'),
])
if (configsRes.ok) {
setConfigs(await configsRes.json())
}
if (ipListRes.ok) {
setIpList(await ipListRes.json())
}
if (eventsRes.ok) {
setEvents(await eventsRes.json())
}
if (statsRes.ok) {
setStats(await statsRes.json())
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Verbindung zum Backend fehlgeschlagen')
} finally {
setLoading(false)
}
}, [])
useEffect(() => {
fetchData()
}, [fetchData])
useEffect(() => {
const interval = setInterval(fetchData, 30000)
return () => clearInterval(interval)
}, [fetchData])
const toggleMiddleware = async (name: string, enabled: boolean) => {
setActionLoading(name)
setError(null)
try {
const response = await fetch(`/api/admin/middleware/${name}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ enabled }),
})
if (!response.ok) {
throw new Error(`Fehler beim Aktualisieren: ${response.statusText}`)
}
setConfigs(prev =>
prev.map(c => (c.middleware_name === name ? { ...c, enabled } : c))
)
} catch (err) {
setError(err instanceof Error ? err.message : 'Aktualisierung fehlgeschlagen')
} finally {
setActionLoading(null)
}
}
const addIP = async (e: React.FormEvent) => {
e.preventDefault()
if (!newIP.trim()) return
setActionLoading('add-ip')
setError(null)
try {
const response = await fetch('/api/admin/middleware/rate-limit/ip-list', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
ip_address: newIP.trim(),
list_type: newIPType,
reason: newIPReason.trim() || null,
}),
})
if (!response.ok) {
const data = await response.json()
throw new Error(data.detail || `Fehler: ${response.statusText}`)
}
const newEntry = await response.json()
setIpList(prev => [newEntry, ...prev])
setNewIP('')
setNewIPReason('')
} catch (err) {
setError(err instanceof Error ? err.message : 'IP konnte nicht hinzugefuegt werden')
} finally {
setActionLoading(null)
}
}
const removeIP = async (id: string) => {
setActionLoading(`remove-${id}`)
setError(null)
try {
const response = await fetch(`/api/admin/middleware/rate-limit/ip-list/${id}`, {
method: 'DELETE',
})
if (!response.ok) {
throw new Error(`Fehler beim Loeschen: ${response.statusText}`)
}
setIpList(prev => prev.filter(ip => ip.id !== id))
} catch (err) {
setError(err instanceof Error ? err.message : 'IP konnte nicht entfernt werden')
} finally {
setActionLoading(null)
}
}
const whitelistCount = ipList.filter(ip => ip.list_type === 'whitelist').length
const blacklistCount = ipList.filter(ip => ip.list_type === 'blacklist').length
return {
configs,
ipList,
events,
stats,
loading,
error,
activeTab,
setActiveTab,
actionLoading,
newIP,
setNewIP,
newIPType,
setNewIPType,
newIPReason,
setNewIPReason,
fetchData,
toggleMiddleware,
addIP,
removeIP,
whitelistCount,
blacklistCount,
}
}