fix: Restore all files lost during destructive rebase

A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-02-09 09:51:32 +01:00
parent f7487ee240
commit 21a844cb8a
1986 changed files with 744143 additions and 1731 deletions

View File

@@ -0,0 +1,175 @@
import { createContext, useContext, useState, useCallback, ReactNode } from 'react'
import { klausurApi, Klausur, StudentKlausur } from '../services/api'
interface KlausurContextType {
klausuren: Klausur[]
currentKlausur: Klausur | null
currentStudent: StudentKlausur | null
loading: boolean
error: string | null
loadKlausuren: () => Promise<void>
selectKlausur: (id: string, keepStudent?: boolean) => Promise<void>
selectStudent: (id: string) => void
setStudentById: (id: string) => void
refreshAndSelectStudent: (klausurId: string, studentId: string) => Promise<void>
createKlausur: (data: Partial<Klausur>) => Promise<Klausur>
deleteKlausur: (id: string) => Promise<void>
updateCriteria: (studentId: string, criterion: string, score: number) => Promise<void>
}
const KlausurContext = createContext<KlausurContextType | null>(null)
export function KlausurProvider({ children }: { children: ReactNode }) {
const [klausuren, setKlausuren] = useState<Klausur[]>([])
const [currentKlausur, setCurrentKlausur] = useState<Klausur | null>(null)
const [currentStudent, setCurrentStudent] = useState<StudentKlausur | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const loadKlausuren = useCallback(async () => {
setLoading(true)
setError(null)
try {
const data = await klausurApi.listKlausuren()
setKlausuren(data)
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to load Klausuren')
} finally {
setLoading(false)
}
}, [])
const selectKlausur = useCallback(async (id: string, keepStudent = false) => {
setLoading(true)
setError(null)
try {
const klausur = await klausurApi.getKlausur(id)
setCurrentKlausur(klausur)
// Optionally keep the current student selection (for refresh after save)
if (keepStudent && currentStudent) {
const updatedStudent = klausur.students.find(s => s.id === currentStudent.id)
setCurrentStudent(updatedStudent || null)
} else if (!keepStudent) {
setCurrentStudent(null)
}
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to load Klausur')
} finally {
setLoading(false)
}
}, [currentStudent])
const selectStudent = useCallback((id: string) => {
if (!currentKlausur) return
const student = currentKlausur.students.find(s => s.id === id)
setCurrentStudent(student || null)
}, [currentKlausur])
// Set student directly by ID (for cases where we need to set before state updates)
const setStudentById = useCallback((id: string) => {
if (!currentKlausur) return
const student = currentKlausur.students.find(s => s.id === id)
if (student) {
setCurrentStudent(student)
}
}, [currentKlausur])
// Combined refresh and select - useful after upload
const refreshAndSelectStudent = useCallback(async (klausurId: string, studentId: string) => {
setLoading(true)
setError(null)
try {
const klausur = await klausurApi.getKlausur(klausurId)
setCurrentKlausur(klausur)
const student = klausur.students.find(s => s.id === studentId)
if (student) {
setCurrentStudent(student)
}
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to load Klausur')
} finally {
setLoading(false)
}
}, [])
const createKlausur = useCallback(async (data: Partial<Klausur>) => {
setLoading(true)
setError(null)
try {
const klausur = await klausurApi.createKlausur(data)
setKlausuren(prev => [...prev, klausur])
return klausur
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to create Klausur')
throw e
} finally {
setLoading(false)
}
}, [])
const deleteKlausur = useCallback(async (id: string) => {
setLoading(true)
setError(null)
try {
await klausurApi.deleteKlausur(id)
setKlausuren(prev => prev.filter(k => k.id !== id))
if (currentKlausur?.id === id) {
setCurrentKlausur(null)
setCurrentStudent(null)
}
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to delete Klausur')
throw e
} finally {
setLoading(false)
}
}, [currentKlausur])
const updateCriteria = useCallback(async (studentId: string, criterion: string, score: number) => {
try {
const updated = await klausurApi.updateCriteria(studentId, criterion, score)
if (currentKlausur) {
setCurrentKlausur({
...currentKlausur,
students: currentKlausur.students.map(s =>
s.id === studentId ? updated : s
)
})
}
if (currentStudent?.id === studentId) {
setCurrentStudent(updated)
}
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to update criteria')
throw e
}
}, [currentKlausur, currentStudent])
return (
<KlausurContext.Provider value={{
klausuren,
currentKlausur,
currentStudent,
loading,
error,
loadKlausuren,
selectKlausur,
selectStudent,
setStudentById,
refreshAndSelectStudent,
createKlausur,
deleteKlausur,
updateCriteria
}}>
{children}
</KlausurContext.Provider>
)
}
export function useKlausur() {
const context = useContext(KlausurContext)
if (!context) {
throw new Error('useKlausur must be used within a KlausurProvider')
}
return context
}