'use client' /** * Communication Tool - Lehrer-Eltern-Kommunikation * * KI-gestuetzte Unterstuetzung fuer professionelle, rechtlich fundierte * und empathische Elternkommunikation basierend auf den Prinzipien * der gewaltfreien Kommunikation (GFK). */ import { useState, useEffect } from 'react' const API_BASE = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000' interface Option { value: string label: string } interface LegalReference { law: string paragraph: string title: string summary: string relevance: string } interface GFKPrinciple { principle: string description: string example: string } interface ValidationResult { is_valid: boolean issues: string[] suggestions: string[] positive_elements: string[] gfk_score: number } export default function CommunicationToolPage() { // Form state const [communicationType, setCommunicationType] = useState('behavior') const [tone, setTone] = useState('professional') const [state, setState] = useState('NRW') const [studentName, setStudentName] = useState('') const [parentName, setParentName] = useState('') const [situation, setSituation] = useState('') const [additionalInfo, setAdditionalInfo] = useState('') // Options const [types, setTypes] = useState([]) const [tones, setTones] = useState([]) const [states, setStates] = useState([]) // Result state const [generatedMessage, setGeneratedMessage] = useState('') const [subject, setSubject] = useState('') const [validation, setValidation] = useState(null) const [legalRefs, setLegalRefs] = useState([]) const [gfkPrinciples, setGfkPrinciples] = useState([]) // UI state const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [showGFKInfo, setShowGFKInfo] = useState(false) const [showLegalInfo, setShowLegalInfo] = useState(false) // Fetch options on mount useEffect(() => { const fetchOptions = async () => { try { const [typesRes, tonesRes, statesRes, gfkRes] = await Promise.all([ fetch(`${API_BASE}/v1/communication/types`), fetch(`${API_BASE}/v1/communication/tones`), fetch(`${API_BASE}/v1/communication/states`), fetch(`${API_BASE}/v1/communication/gfk-principles`), ]) if (typesRes.ok) setTypes(await typesRes.json()) if (tonesRes.ok) setTones(await tonesRes.json()) if (statesRes.ok) setStates(await statesRes.json()) if (gfkRes.ok) setGfkPrinciples(await gfkRes.json()) } catch (e) { console.error('Fehler beim Laden der Optionen:', e) // Fallback-Werte setTypes([ { value: 'behavior', label: 'Verhalten/Disziplin' }, { value: 'academic', label: 'Schulleistungen' }, { value: 'attendance', label: 'Fehlzeiten' }, { value: 'meeting_invite', label: 'Einladung zum Gespraech' }, { value: 'positive_feedback', label: 'Positives Feedback' }, { value: 'concern', label: 'Bedenken aeussern' }, { value: 'conflict', label: 'Konfliktloesung' }, ]) setTones([ { value: 'professional', label: 'Professionell-freundlich' }, { value: 'formal', label: 'Sehr foermlich' }, { value: 'warm', label: 'Warmherzig' }, { value: 'concerned', label: 'Besorgt' }, ]) setStates([ { value: 'NRW', label: 'Nordrhein-Westfalen' }, { value: 'BY', label: 'Bayern' }, { value: 'BW', label: 'Baden-Wuerttemberg' }, ]) } } fetchOptions() }, []) // Generate message const handleGenerate = async () => { if (!studentName || !parentName || !situation) { setError('Bitte fuellen Sie alle Pflichtfelder aus.') return } setLoading(true) setError(null) try { const res = await fetch(`${API_BASE}/v1/communication/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ communication_type: communicationType, tone, state, student_name: studentName, parent_name: parentName, situation, additional_info: additionalInfo || undefined, }), }) if (!res.ok) { throw new Error(`Server-Fehler: ${res.status}`) } const data = await res.json() setGeneratedMessage(data.message) setSubject(data.subject) setValidation(data.validation) setLegalRefs(data.legal_references || []) } catch (e) { setError(`Fehler bei der Generierung: ${e instanceof Error ? e.message : 'Unbekannter Fehler'}`) } finally { setLoading(false) } } // Improve existing text const handleImprove = async () => { if (!generatedMessage) return setLoading(true) setError(null) try { const res = await fetch(`${API_BASE}/v1/communication/improve`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: generatedMessage }), }) if (!res.ok) { throw new Error(`Server-Fehler: ${res.status}`) } const data = await res.json() if (data.was_improved) { setGeneratedMessage(data.improved_text) // Re-validate const valRes = await fetch(`${API_BASE}/v1/communication/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: data.improved_text }), }) if (valRes.ok) { setValidation(await valRes.json()) } } } catch (e) { setError(`Fehler bei der Verbesserung: ${e instanceof Error ? e.message : 'Unbekannter Fehler'}`) } finally { setLoading(false) } } // Copy to clipboard const handleCopy = async () => { try { await navigator.clipboard.writeText(generatedMessage) alert('In die Zwischenablage kopiert!') } catch (e) { console.error('Kopieren fehlgeschlagen:', e) } } return (
{/* Header */}

Kommunikationsassistent

KI-gestuetzte Unterstuetzung fuer professionelle Elternkommunikation nach den Prinzipien der gewaltfreien Kommunikation (GFK)

{/* Input Form */}

Nachricht erstellen

{/* Communication Type */}
{/* Tone */}
{/* State */}
{/* Student Name */}
setStudentName(e.target.value)} placeholder="z.B. Max" className="w-full border rounded-md p-2" />
{/* Parent Name */}
setParentName(e.target.value)} placeholder="z.B. Frau Mueller" className="w-full border rounded-md p-2" />
{/* Situation */}