'use client' /** * Custom hook for the Klausur-Korrektur list page. * Encapsulates all state and data fetching logic. */ import { useState, useEffect, useCallback } from 'react' import type { Klausur, GradeInfo } from '../../app/admin/klausur-korrektur/types' import type { TabId, CreateKlausurForm, VorabiturEHForm, EHTemplate, DirektuploadForm, } from './list-types' import { API_BASE } from './list-types' interface UseKlausurListArgs { /** Base route path for navigation, e.g. '/admin/klausur-korrektur' or '/lehrer/klausur-korrektur' */ basePath: string } export function useKlausurList({ basePath }: UseKlausurListArgs) { const [activeTab, setActiveTab] = useState(() => { if (typeof window !== 'undefined') { const hasVisited = localStorage.getItem('klausur_korrektur_visited') return hasVisited ? 'klausuren' : 'willkommen' } return 'willkommen' }) const [klausuren, setKlausuren] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [creating, setCreating] = useState(false) const [gradeInfo, setGradeInfo] = useState(null) // Vorabitur templates const [templates, setTemplates] = useState([]) const [loadingTemplates, setLoadingTemplates] = useState(false) // Create form state const [form, setForm] = useState({ title: '', subject: 'Deutsch', year: new Date().getFullYear(), semester: 'Abitur', modus: 'abitur', }) const [ehForm, setEhForm] = useState({ aufgabentyp: '', titel: '', text_titel: '', text_autor: '', aufgabenstellung: '', }) // Direktupload form const [direktForm, setDirektForm] = useState({ files: [], ehFile: null, ehText: '', aufgabentyp: '', klausurTitle: `Schnellkorrektur ${new Date().toLocaleDateString('de-DE')}`, }) const [direktStep, setDirektStep] = useState<1 | 2 | 3>(1) const [uploading, setUploading] = useState(false) // Fetch klausuren const fetchKlausuren = useCallback(async () => { try { setLoading(true) const res = await fetch(`${API_BASE}/api/v1/klausuren`) if (res.ok) { const data = await res.json() setKlausuren(Array.isArray(data) ? data : data.klausuren || []) setError(null) } else { setError(`Fehler beim Laden: ${res.status}`) } } catch (err) { console.error('Failed to fetch klausuren:', err) setError('Verbindung zum Klausur-Service fehlgeschlagen') } finally { setLoading(false) } }, []) // Fetch grade info const fetchGradeInfo = useCallback(async () => { try { const res = await fetch(`${API_BASE}/api/v1/grade-info`) if (res.ok) setGradeInfo(await res.json()) } catch (err) { console.error('Failed to fetch grade info:', err) } }, []) // Fetch templates const fetchTemplates = useCallback(async () => { try { setLoadingTemplates(true) const res = await fetch(`${API_BASE}/api/v1/vorabitur/templates`) if (res.ok) { const data = await res.json() setTemplates(data.templates || []) } } catch (err) { console.error('Failed to fetch templates:', err) } finally { setLoadingTemplates(false) } }, []) useEffect(() => { fetchKlausuren(); fetchGradeInfo() }, [fetchKlausuren, fetchGradeInfo]) useEffect(() => { if (form.modus === 'vorabitur' && templates.length === 0) fetchTemplates() }, [form.modus, templates.length, fetchTemplates]) const markAsVisited = () => { if (typeof window !== 'undefined') localStorage.setItem('klausur_korrektur_visited', 'true') } // Create new Klausur const handleCreateKlausur = async (e: React.FormEvent) => { e.preventDefault() if (!form.title.trim()) { setError('Bitte einen Titel eingeben'); return } if (form.modus === 'vorabitur') { if (!ehForm.aufgabentyp) { setError('Bitte einen Aufgabentyp auswaehlen'); return } if (!ehForm.aufgabenstellung.trim()) { setError('Bitte die Aufgabenstellung eingeben'); return } } try { setCreating(true) const res = await fetch(`${API_BASE}/api/v1/klausuren`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form), }) if (!res.ok) { const errorData = await res.json() setError(errorData.detail || 'Fehler beim Erstellen'); return } const newKlausur = await res.json() if (form.modus === 'vorabitur') { const ehRes = await fetch(`${API_BASE}/api/v1/klausuren/${newKlausur.id}/vorabitur-eh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ aufgabentyp: ehForm.aufgabentyp, titel: ehForm.titel || `EH: ${form.title}`, text_titel: ehForm.text_titel || null, text_autor: ehForm.text_autor || null, aufgabenstellung: ehForm.aufgabenstellung, }), }) if (!ehRes.ok) { console.error('Failed to create EH:', await ehRes.text()) setError('Klausur erstellt, aber Erwartungshorizont konnte nicht erstellt werden.') } } setKlausuren(prev => [newKlausur, ...prev]) setForm({ title: '', subject: 'Deutsch', year: new Date().getFullYear(), semester: 'Abitur', modus: 'abitur' }) setEhForm({ aufgabentyp: '', titel: '', text_titel: '', text_autor: '', aufgabenstellung: '' }) setActiveTab('klausuren') if (!error) setError(null) } catch (err) { console.error('Failed to create klausur:', err) setError('Fehler beim Erstellen der Klausur') } finally { setCreating(false) } } // Delete Klausur const handleDeleteKlausur = async (id: string) => { if (!confirm('Klausur wirklich loeschen? Alle Studentenarbeiten werden ebenfalls geloescht.')) return try { const res = await fetch(`${API_BASE}/api/v1/klausuren/${id}`, { method: 'DELETE' }) if (res.ok) setKlausuren(prev => prev.filter(k => k.id !== id)) else setError('Fehler beim Loeschen') } catch (err) { console.error('Failed to delete klausur:', err) setError('Fehler beim Loeschen der Klausur') } } // Direktupload const handleDirektupload = async () => { if (direktForm.files.length === 0) { setError('Bitte mindestens eine Arbeit hochladen'); return } try { setUploading(true) const klausurRes = await fetch(`${API_BASE}/api/v1/klausuren`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: direktForm.klausurTitle, subject: 'Deutsch', year: new Date().getFullYear(), semester: 'Vorabitur', modus: 'vorabitur', }), }) if (!klausurRes.ok) { const err = await klausurRes.json() throw new Error(err.detail || 'Klausur erstellen fehlgeschlagen') } const newKlausur = await klausurRes.json() if (direktForm.ehText.trim() || direktForm.aufgabentyp) { const ehRes = await fetch(`${API_BASE}/api/v1/klausuren/${newKlausur.id}/vorabitur-eh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ aufgabentyp: direktForm.aufgabentyp || 'textanalyse_pragmatisch', titel: `EH: ${direktForm.klausurTitle}`, aufgabenstellung: direktForm.ehText || 'Individuelle Aufgabenstellung', }), }) if (!ehRes.ok) console.error('EH creation failed, continuing with upload') } for (let i = 0; i < direktForm.files.length; i++) { const file = direktForm.files[i] const formData = new FormData() formData.append('file', file) formData.append('anonym_id', `Arbeit-${i + 1}`) const uploadRes = await fetch(`${API_BASE}/api/v1/klausuren/${newKlausur.id}/students`, { method: 'POST', body: formData, }) if (!uploadRes.ok) console.error(`Upload failed for file ${i + 1}:`, file.name) } setKlausuren(prev => [newKlausur, ...prev]) markAsVisited() window.location.href = `${basePath}/${newKlausur.id}` } catch (err) { console.error('Direktupload failed:', err) setError(err instanceof Error ? err.message : 'Fehler beim Direktupload') } finally { setUploading(false) } } return { // Data klausuren, gradeInfo, templates, // UI state activeTab, loading, error, creating, loadingTemplates, form, ehForm, direktForm, direktStep, uploading, // Setters setActiveTab, setError, setForm, setEhForm, setDirektForm, setDirektStep, // Actions markAsVisited, handleCreateKlausur, handleDeleteKlausur, handleDirektupload, // Route config basePath, } }