Files
breakpilot-lehrer/admin-lehrer/app/(admin)/infrastructure/night-mode/_components/useNightMode.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

175 lines
4.9 KiB
TypeScript

import { useEffect, useState, useCallback } from 'react'
import type { NightModeConfig, NightModeStatus, ServicesInfo } from './types'
export function useNightMode() {
const [status, setStatus] = useState<NightModeStatus | null>(null)
const [services, setServices] = useState<ServicesInfo | null>(null)
const [loading, setLoading] = useState(true)
const [actionLoading, setActionLoading] = useState<string | null>(null)
const [error, setError] = useState<string | null>(null)
const [successMessage, setSuccessMessage] = useState<string | null>(null)
const [editMode, setEditMode] = useState(false)
const [editConfig, setEditConfig] = useState<NightModeConfig | null>(null)
const fetchData = useCallback(async () => {
setError(null)
try {
const [statusRes, servicesRes] = await Promise.all([
fetch('/api/admin/night-mode'),
fetch('/api/admin/night-mode/services'),
])
if (statusRes.ok) {
const data = await statusRes.json()
setStatus(data)
if (!editMode) {
setEditConfig(data.config)
}
} else {
const errData = await statusRes.json()
setError(errData.error || 'Fehler beim Laden des Status')
}
if (servicesRes.ok) {
setServices(await servicesRes.json())
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Verbindung zum Night-Scheduler fehlgeschlagen')
} finally {
setLoading(false)
}
}, [editMode])
useEffect(() => {
fetchData()
}, [fetchData])
// Auto-Refresh alle 30 Sekunden
useEffect(() => {
const interval = setInterval(fetchData, 30000)
return () => clearInterval(interval)
}, [fetchData])
const saveConfig = async () => {
if (!editConfig) return
setActionLoading('save')
setError(null)
setSuccessMessage(null)
try {
const response = await fetch('/api/admin/night-mode', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(editConfig),
})
if (!response.ok) {
const errData = await response.json()
throw new Error(errData.error || 'Fehler beim Speichern')
}
setEditMode(false)
setSuccessMessage('Konfiguration gespeichert')
setTimeout(() => setSuccessMessage(null), 3000)
fetchData()
} catch (err) {
setError(err instanceof Error ? err.message : 'Speichern fehlgeschlagen')
} finally {
setActionLoading(null)
}
}
const executeAction = async (action: 'start' | 'stop') => {
setActionLoading(action)
setError(null)
setSuccessMessage(null)
try {
const response = await fetch('/api/admin/night-mode/execute', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action }),
})
if (!response.ok) {
const errData = await response.json()
throw new Error(errData.error || `Fehler bei ${action}`)
}
const data = await response.json()
setSuccessMessage(data.message || `${action === 'start' ? 'Gestartet' : 'Gestoppt'}`)
setTimeout(() => setSuccessMessage(null), 5000)
fetchData()
} catch (err) {
setError(err instanceof Error ? err.message : `${action} fehlgeschlagen`)
} finally {
setActionLoading(null)
}
}
const toggleEnabled = async () => {
if (!editConfig) return
const newConfig = { ...editConfig, enabled: !editConfig.enabled }
setEditConfig(newConfig)
setActionLoading('toggle')
setError(null)
try {
const response = await fetch('/api/admin/night-mode', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newConfig),
})
if (!response.ok) {
throw new Error('Fehler beim Umschalten')
}
setSuccessMessage(newConfig.enabled ? 'Nachtmodus aktiviert' : 'Nachtmodus deaktiviert')
setTimeout(() => setSuccessMessage(null), 3000)
fetchData()
} catch (err) {
setError(err instanceof Error ? err.message : 'Umschalten fehlgeschlagen')
// Zuruecksetzen bei Fehler
setEditConfig({ ...editConfig })
} finally {
setActionLoading(null)
}
}
const cancelEdit = () => {
setEditMode(false)
setEditConfig(status?.config || null)
}
const runningCount = Object.values(status?.services_status || {}).filter(
s => s.toLowerCase() === 'running' || s.toLowerCase().includes('up')
).length
const stoppedCount = Object.values(status?.services_status || {}).filter(
s => s.toLowerCase() === 'exited' || s.toLowerCase().includes('exit')
).length
return {
status,
services,
loading,
actionLoading,
error,
successMessage,
editMode,
setEditMode,
editConfig,
setEditConfig,
saveConfig,
executeAction,
toggleEnabled,
cancelEdit,
runningCount,
stoppedCount,
}
}