Files
Benjamin Boenisch 5a31f52310 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>
2026-02-11 23:47:26 +01:00

249 lines
8.9 KiB
TypeScript

'use client'
import { useState, useEffect } from 'react'
import { X, Settings, Save, RotateCcw } from 'lucide-react'
import { TeacherSettings, PhaseDurations } from '@/lib/companion/types'
import {
DEFAULT_TEACHER_SETTINGS,
DEFAULT_PHASE_DURATIONS,
PHASE_ORDER,
PHASE_DISPLAY_NAMES,
PHASE_COLORS,
calculateTotalDuration,
} from '@/lib/companion/constants'
interface SettingsModalProps {
isOpen: boolean
onClose: () => void
settings: TeacherSettings
onSave: (settings: TeacherSettings) => void
}
export function SettingsModal({
isOpen,
onClose,
settings,
onSave,
}: SettingsModalProps) {
const [localSettings, setLocalSettings] = useState<TeacherSettings>(settings)
const [durations, setDurations] = useState<PhaseDurations>(settings.defaultPhaseDurations)
useEffect(() => {
setLocalSettings(settings)
setDurations(settings.defaultPhaseDurations)
}, [settings])
if (!isOpen) return null
const totalDuration = calculateTotalDuration(durations)
const handleDurationChange = (phase: keyof PhaseDurations, value: number) => {
const newDurations = { ...durations, [phase]: Math.max(1, Math.min(60, value)) }
setDurations(newDurations)
}
const handleReset = () => {
setDurations(DEFAULT_PHASE_DURATIONS)
setLocalSettings(DEFAULT_TEACHER_SETTINGS)
}
const handleSave = () => {
const newSettings: TeacherSettings = {
...localSettings,
defaultPhaseDurations: durations,
}
onSave(newSettings)
onClose()
}
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
{/* Backdrop */}
<div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
onClick={onClose}
/>
{/* Modal */}
<div className="relative bg-white rounded-2xl shadow-xl w-full max-w-lg mx-4 max-h-[90vh] overflow-hidden">
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-slate-200">
<div className="flex items-center gap-3">
<div className="p-2 bg-slate-100 rounded-xl">
<Settings className="w-5 h-5 text-slate-600" />
</div>
<h2 className="text-xl font-semibold text-slate-900">Einstellungen</h2>
</div>
<button
onClick={onClose}
className="p-2 hover:bg-slate-100 rounded-lg transition-colors"
>
<X className="w-5 h-5 text-slate-500" />
</button>
</div>
{/* Content */}
<div className="p-6 space-y-6 overflow-y-auto max-h-[60vh]">
{/* Phase Durations */}
<div>
<h3 className="text-sm font-medium text-slate-700 mb-4">
Standard-Phasendauern (Minuten)
</h3>
<div className="space-y-4">
{PHASE_ORDER.map((phase) => (
<div key={phase} className="flex items-center gap-4">
<div className="flex items-center gap-2 w-32">
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: PHASE_COLORS[phase].hex }}
/>
<span className="text-sm text-slate-700">
{PHASE_DISPLAY_NAMES[phase]}
</span>
</div>
<input
type="number"
min={1}
max={60}
value={durations[phase]}
onChange={(e) => handleDurationChange(phase, parseInt(e.target.value) || 1)}
className="w-20 px-3 py-2 border border-slate-200 rounded-lg text-center focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
<input
type="range"
min={1}
max={45}
value={durations[phase]}
onChange={(e) => handleDurationChange(phase, parseInt(e.target.value))}
className="flex-1"
style={{
accentColor: PHASE_COLORS[phase].hex,
}}
/>
</div>
))}
</div>
<div className="mt-4 p-3 bg-slate-50 rounded-xl flex items-center justify-between">
<span className="text-sm text-slate-600">Gesamtdauer:</span>
<span className="font-semibold text-slate-900">{totalDuration} Minuten</span>
</div>
</div>
{/* Other Settings */}
<div className="space-y-4 pt-4 border-t border-slate-200">
<h3 className="text-sm font-medium text-slate-700 mb-4">
Weitere Einstellungen
</h3>
{/* Auto Advance */}
<label className="flex items-center justify-between p-3 bg-slate-50 rounded-xl cursor-pointer">
<div>
<span className="text-sm font-medium text-slate-700">
Automatischer Phasenwechsel
</span>
<p className="text-xs text-slate-500">
Phasen automatisch wechseln wenn Zeit abgelaufen
</p>
</div>
<input
type="checkbox"
checked={localSettings.autoAdvancePhases}
onChange={(e) =>
setLocalSettings({ ...localSettings, autoAdvancePhases: e.target.checked })
}
className="w-5 h-5 text-blue-600 rounded focus:ring-blue-500"
/>
</label>
{/* Sound Notifications */}
<label className="flex items-center justify-between p-3 bg-slate-50 rounded-xl cursor-pointer">
<div>
<span className="text-sm font-medium text-slate-700">
Ton-Benachrichtigungen
</span>
<p className="text-xs text-slate-500">
Signalton bei Phasenende und Warnungen
</p>
</div>
<input
type="checkbox"
checked={localSettings.soundNotifications}
onChange={(e) =>
setLocalSettings({ ...localSettings, soundNotifications: e.target.checked })
}
className="w-5 h-5 text-blue-600 rounded focus:ring-blue-500"
/>
</label>
{/* Keyboard Shortcuts */}
<label className="flex items-center justify-between p-3 bg-slate-50 rounded-xl cursor-pointer">
<div>
<span className="text-sm font-medium text-slate-700">
Tastaturkuerzel anzeigen
</span>
<p className="text-xs text-slate-500">
Hinweise zu Tastaturkuerzeln einblenden
</p>
</div>
<input
type="checkbox"
checked={localSettings.showKeyboardShortcuts}
onChange={(e) =>
setLocalSettings({ ...localSettings, showKeyboardShortcuts: e.target.checked })
}
className="w-5 h-5 text-blue-600 rounded focus:ring-blue-500"
/>
</label>
{/* High Contrast */}
<label className="flex items-center justify-between p-3 bg-slate-50 rounded-xl cursor-pointer">
<div>
<span className="text-sm font-medium text-slate-700">
Hoher Kontrast
</span>
<p className="text-xs text-slate-500">
Bessere Sichtbarkeit durch erhoehten Kontrast
</p>
</div>
<input
type="checkbox"
checked={localSettings.highContrastMode}
onChange={(e) =>
setLocalSettings({ ...localSettings, highContrastMode: e.target.checked })
}
className="w-5 h-5 text-blue-600 rounded focus:ring-blue-500"
/>
</label>
</div>
</div>
{/* Footer */}
<div className="flex items-center justify-between p-6 border-t border-slate-200 bg-slate-50">
<button
onClick={handleReset}
className="flex items-center gap-2 px-4 py-2 text-slate-600 hover:bg-slate-200 rounded-lg transition-colors"
>
<RotateCcw className="w-4 h-4" />
Zuruecksetzen
</button>
<div className="flex items-center gap-3">
<button
onClick={onClose}
className="px-4 py-2 text-slate-600 hover:bg-slate-200 rounded-lg transition-colors"
>
Abbrechen
</button>
<button
onClick={handleSave}
className="flex items-center gap-2 px-6 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 transition-colors"
>
<Save className="w-4 h-4" />
Speichern
</button>
</div>
</div>
</div>
</div>
)
}