[split-required] Split remaining 500-680 LOC files (final batch)
website (17 pages + 3 components): - multiplayer/wizard, middleware/wizard+test-wizard, communication - builds/wizard, staff-search, voice, sbom/wizard - foerderantrag, mail/tasks, tools/communication, sbom - compliance/evidence, uni-crawler, brandbook (already done) - CollectionsTab, IngestionTab, RiskHeatmap backend-lehrer (5 files): - letters_api (641 → 2), certificates_api (636 → 2) - alerts_agent/db/models (636 → 3) - llm_gateway/communication_service (614 → 2) - game/database already done in prior batch klausur-service (2 files): - hybrid_vocab_extractor (664 → 2) - klausur-service/frontend: api.ts (620 → 3), EHUploadWizard (591 → 2) voice-service (3 files): - bqas/rag_judge (618 → 3), runner (529 → 2) - enhanced_task_orchestrator (519 → 2) studio-v2 (6 files): - korrektur/[klausurId] (578 → 4), fairness (569 → 2) - AlertsWizard (552 → 2), OnboardingWizard (513 → 2) - korrektur/api.ts (506 → 3), geo-lernwelt (501 → 2) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
139
studio-v2/lib/korrektur/api-core.ts
Normal file
139
studio-v2/lib/korrektur/api-core.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Korrektur Core API - Base functions and CRUD operations
|
||||
*
|
||||
* Split from api.ts. This module contains the base fetch wrapper
|
||||
* and all core Klausur/Student/Annotation/Fairness operations.
|
||||
*/
|
||||
|
||||
import type {
|
||||
Klausur, StudentWork, CriteriaScores, Annotation,
|
||||
AnnotationPosition, AnnotationType, FairnessAnalysis,
|
||||
EHSuggestion, GradeInfo, CreateKlausurData,
|
||||
} from '@/app/korrektur/types'
|
||||
|
||||
export const getApiBase = (): string => {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8086'
|
||||
const { hostname } = window.location
|
||||
return hostname === 'localhost' ? 'http://localhost:8086' : '/klausur-api'
|
||||
}
|
||||
|
||||
export async function apiFetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
||||
const url = `${getApiBase()}${endpoint}`
|
||||
const response = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', ...options.headers } })
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ detail: 'Unknown error' }))
|
||||
throw new Error(errorData.detail || `HTTP ${response.status}`)
|
||||
}
|
||||
return response.json()
|
||||
}
|
||||
|
||||
// Klausuren
|
||||
export async function getKlausuren(): Promise<Klausur[]> {
|
||||
const data = await apiFetch<{ klausuren: Klausur[] }>('/api/v1/klausuren')
|
||||
return data.klausuren || []
|
||||
}
|
||||
|
||||
export async function getKlausur(id: string): Promise<Klausur> {
|
||||
return apiFetch<Klausur>(`/api/v1/klausuren/${id}`)
|
||||
}
|
||||
|
||||
export async function createKlausur(data: CreateKlausurData): Promise<Klausur> {
|
||||
return apiFetch<Klausur>('/api/v1/klausuren', { method: 'POST', body: JSON.stringify(data) })
|
||||
}
|
||||
|
||||
export async function deleteKlausur(id: string): Promise<void> {
|
||||
await apiFetch(`/api/v1/klausuren/${id}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
// Students
|
||||
export async function getStudents(klausurId: string): Promise<StudentWork[]> {
|
||||
const data = await apiFetch<{ students: StudentWork[] }>(`/api/v1/klausuren/${klausurId}/students`)
|
||||
return data.students || []
|
||||
}
|
||||
|
||||
export async function getStudent(studentId: string): Promise<StudentWork> {
|
||||
return apiFetch<StudentWork>(`/api/v1/students/${studentId}`)
|
||||
}
|
||||
|
||||
export async function uploadStudentWork(klausurId: string, file: File, anonymId: string): Promise<StudentWork> {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('anonym_id', anonymId)
|
||||
const response = await fetch(`${getApiBase()}/api/v1/klausuren/${klausurId}/students`, { method: 'POST', body: formData })
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ detail: 'Upload failed' }))
|
||||
throw new Error(errorData.detail || `HTTP ${response.status}`)
|
||||
}
|
||||
return response.json()
|
||||
}
|
||||
|
||||
export async function deleteStudent(studentId: string): Promise<void> {
|
||||
await apiFetch(`/api/v1/students/${studentId}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
// Criteria & Gutachten
|
||||
export async function updateCriteria(studentId: string, criteria: CriteriaScores): Promise<StudentWork> {
|
||||
return apiFetch<StudentWork>(`/api/v1/students/${studentId}/criteria`, { method: 'PUT', body: JSON.stringify({ criteria_scores: criteria }) })
|
||||
}
|
||||
|
||||
export async function updateGutachten(studentId: string, gutachten: string): Promise<StudentWork> {
|
||||
return apiFetch<StudentWork>(`/api/v1/students/${studentId}/gutachten`, { method: 'PUT', body: JSON.stringify({ gutachten }) })
|
||||
}
|
||||
|
||||
export async function generateGutachten(studentId: string): Promise<{ gutachten: string }> {
|
||||
return apiFetch<{ gutachten: string }>(`/api/v1/students/${studentId}/gutachten/generate`, { method: 'POST' })
|
||||
}
|
||||
|
||||
// Annotations
|
||||
export async function getAnnotations(studentId: string): Promise<Annotation[]> {
|
||||
const data = await apiFetch<{ annotations: Annotation[] }>(`/api/v1/students/${studentId}/annotations`)
|
||||
return data.annotations || []
|
||||
}
|
||||
|
||||
export async function createAnnotation(studentId: string, annotation: { page: number; position: AnnotationPosition; type: AnnotationType; text: string; severity?: 'minor' | 'major' | 'critical'; suggestion?: string; linked_criterion?: string }): Promise<Annotation> {
|
||||
return apiFetch<Annotation>(`/api/v1/students/${studentId}/annotations`, { method: 'POST', body: JSON.stringify(annotation) })
|
||||
}
|
||||
|
||||
export async function updateAnnotation(annotationId: string, updates: Partial<{ text: string; severity: 'minor' | 'major' | 'critical'; suggestion: string }>): Promise<Annotation> {
|
||||
return apiFetch<Annotation>(`/api/v1/annotations/${annotationId}`, { method: 'PUT', body: JSON.stringify(updates) })
|
||||
}
|
||||
|
||||
export async function deleteAnnotation(annotationId: string): Promise<void> {
|
||||
await apiFetch(`/api/v1/annotations/${annotationId}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
// EH/RAG
|
||||
export async function getEHSuggestions(studentId: string, criterion?: string): Promise<EHSuggestion[]> {
|
||||
const data = await apiFetch<{ suggestions: EHSuggestion[] }>(`/api/v1/students/${studentId}/eh-suggestions`, { method: 'POST', body: JSON.stringify({ criterion }) })
|
||||
return data.suggestions || []
|
||||
}
|
||||
|
||||
export async function queryRAG(query: string, topK: number = 5): Promise<{ results: Array<{ text: string; score: number; metadata: any }> }> {
|
||||
return apiFetch('/api/v1/eh/rag-query', { method: 'POST', body: JSON.stringify({ query, top_k: topK }) })
|
||||
}
|
||||
|
||||
export async function uploadEH(file: File): Promise<{ id: string; name: string }> {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
const response = await fetch(`${getApiBase()}/api/v1/eh/upload`, { method: 'POST', body: formData })
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ detail: 'EH Upload failed' }))
|
||||
throw new Error(errorData.detail || `HTTP ${response.status}`)
|
||||
}
|
||||
return response.json()
|
||||
}
|
||||
|
||||
// Fairness & Export
|
||||
export async function getFairnessAnalysis(klausurId: string): Promise<FairnessAnalysis> {
|
||||
return apiFetch<FairnessAnalysis>(`/api/v1/klausuren/${klausurId}/fairness`)
|
||||
}
|
||||
|
||||
export async function getGradeInfo(): Promise<GradeInfo> {
|
||||
return apiFetch<GradeInfo>('/api/v1/grade-info')
|
||||
}
|
||||
|
||||
export function getGutachtenExportUrl(studentId: string): string { return `${getApiBase()}/api/v1/students/${studentId}/export/gutachten` }
|
||||
export function getAnnotationsExportUrl(studentId: string): string { return `${getApiBase()}/api/v1/students/${studentId}/export/annotations` }
|
||||
export function getOverviewExportUrl(klausurId: string): string { return `${getApiBase()}/api/v1/klausuren/${klausurId}/export/overview` }
|
||||
export function getAllGutachtenExportUrl(klausurId: string): string { return `${getApiBase()}/api/v1/klausuren/${klausurId}/export/all-gutachten` }
|
||||
export function getStudentFileUrl(studentId: string): string { return `${getApiBase()}/api/v1/students/${studentId}/file` }
|
||||
Reference in New Issue
Block a user