Initial commit: breakpilot-lehrer - Lehrer KI Platform
Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
175
klausur-service/frontend/src/hooks/useKlausur.tsx
Normal file
175
klausur-service/frontend/src/hooks/useKlausur.tsx
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user