/** * Constants for Companion Module * Phase colors, defaults, and configuration */ import { PhaseId, PhaseDurations, Phase, TeacherSettings } from './types' // ============================================================================ // Phase Colors (Didactic Color Psychology) // ============================================================================ export const PHASE_COLORS: Record = { einstieg: { hex: '#4A90E2', tailwind: 'bg-blue-500', gradient: 'from-blue-500 to-blue-600', }, erarbeitung: { hex: '#F5A623', tailwind: 'bg-orange-500', gradient: 'from-orange-500 to-orange-600', }, sicherung: { hex: '#7ED321', tailwind: 'bg-green-500', gradient: 'from-green-500 to-green-600', }, transfer: { hex: '#9013FE', tailwind: 'bg-purple-600', gradient: 'from-purple-600 to-purple-700', }, reflexion: { hex: '#6B7280', tailwind: 'bg-gray-500', gradient: 'from-gray-500 to-gray-600', }, } // ============================================================================ // Phase Definitions // ============================================================================ export const PHASE_SHORT_NAMES: Record = { einstieg: 'E', erarbeitung: 'A', sicherung: 'S', transfer: 'T', reflexion: 'R', } export const PHASE_DISPLAY_NAMES: Record = { einstieg: 'Einstieg', erarbeitung: 'Erarbeitung', sicherung: 'Sicherung', transfer: 'Transfer', reflexion: 'Reflexion', } export const PHASE_DESCRIPTIONS: Record = { einstieg: 'Motivation, Kontext setzen, Vorwissen aktivieren', erarbeitung: 'Hauptinhalt, aktives Lernen, neue Konzepte', sicherung: 'Konsolidierung, Zusammenfassung, Uebungen', transfer: 'Anwendung, neue Kontexte, kreative Aufgaben', reflexion: 'Rueckblick, Selbsteinschaetzung, Ausblick', } export const PHASE_ORDER: PhaseId[] = [ 'einstieg', 'erarbeitung', 'sicherung', 'transfer', 'reflexion', ] // ============================================================================ // Default Durations (in minutes) // ============================================================================ export const DEFAULT_PHASE_DURATIONS: PhaseDurations = { einstieg: 8, erarbeitung: 20, sicherung: 10, transfer: 7, reflexion: 5, } export const DEFAULT_LESSON_LENGTH = 45 // minutes (German standard) export const EXTENDED_LESSON_LENGTH = 50 // minutes (with buffer) // ============================================================================ // Timer Thresholds (in seconds) // ============================================================================ export const TIMER_WARNING_THRESHOLD = 5 * 60 // 5 minutes = warning (yellow) export const TIMER_CRITICAL_THRESHOLD = 2 * 60 // 2 minutes = critical (red) // ============================================================================ // SVG Pie Timer Constants // ============================================================================ export const PIE_TIMER_RADIUS = 42 export const PIE_TIMER_CIRCUMFERENCE = 2 * Math.PI * PIE_TIMER_RADIUS // ~263.89 export const PIE_TIMER_STROKE_WIDTH = 8 export const PIE_TIMER_SIZE = 120 // viewBox size // ============================================================================ // Timer Color Classes // ============================================================================ export const TIMER_COLOR_CLASSES = { plenty: 'text-green-500 stroke-green-500', warning: 'text-amber-500 stroke-amber-500', critical: 'text-red-500 stroke-red-500', overtime: 'text-red-600 stroke-red-600 animate-pulse', } export const TIMER_BG_COLORS = { plenty: 'bg-green-500/10', warning: 'bg-amber-500/10', critical: 'bg-red-500/10', overtime: 'bg-red-600/20', } // ============================================================================ // Keyboard Shortcuts // ============================================================================ export const KEYBOARD_SHORTCUTS = { PAUSE_RESUME: ' ', // Spacebar EXTEND_5MIN: 'e', NEXT_PHASE: 'n', CLOSE_MODAL: 'Escape', SHOW_HELP: '?', } as const export const KEYBOARD_SHORTCUT_DESCRIPTIONS: Record = { ' ': 'Pause/Fortsetzen', 'e': '+5 Minuten', 'n': 'Naechste Phase', 'Escape': 'Modal schliessen', '?': 'Hilfe anzeigen', } // ============================================================================ // Default Settings // ============================================================================ export const DEFAULT_TEACHER_SETTINGS: TeacherSettings = { defaultPhaseDurations: DEFAULT_PHASE_DURATIONS, preferredLessonLength: DEFAULT_LESSON_LENGTH, autoAdvancePhases: true, soundNotifications: true, showKeyboardShortcuts: true, highContrastMode: false, onboardingCompleted: false, } // ============================================================================ // System Templates // ============================================================================ export const SYSTEM_TEMPLATES = [ { templateId: 'standard-45', name: 'Standard (45 Min)', description: 'Klassische Unterrichtsstunde', durations: DEFAULT_PHASE_DURATIONS, isSystemTemplate: true, }, { templateId: 'double-90', name: 'Doppelstunde (90 Min)', description: 'Fuer laengere Arbeitsphasen', durations: { einstieg: 10, erarbeitung: 45, sicherung: 15, transfer: 12, reflexion: 8, }, isSystemTemplate: true, }, { templateId: 'math-focused', name: 'Mathematik-fokussiert', description: 'Lange Erarbeitung und Sicherung', durations: { einstieg: 5, erarbeitung: 25, sicherung: 10, transfer: 5, reflexion: 5, }, isSystemTemplate: true, }, { templateId: 'language-practice', name: 'Sprachpraxis', description: 'Betont kommunikative Phasen', durations: { einstieg: 10, erarbeitung: 15, sicherung: 8, transfer: 10, reflexion: 7, }, isSystemTemplate: true, }, ] // ============================================================================ // Suggestion Icons (Lucide icon names) // ============================================================================ export const SUGGESTION_ICONS = { grading: 'ClipboardCheck', homework: 'BookOpen', planning: 'Calendar', meeting: 'Users', deadline: 'Clock', material: 'FileText', communication: 'MessageSquare', default: 'Lightbulb', } // ============================================================================ // Priority Colors // ============================================================================ export const PRIORITY_COLORS = { urgent: { bg: 'bg-red-100', text: 'text-red-700', border: 'border-red-200', dot: 'bg-red-500', }, high: { bg: 'bg-orange-100', text: 'text-orange-700', border: 'border-orange-200', dot: 'bg-orange-500', }, medium: { bg: 'bg-yellow-100', text: 'text-yellow-700', border: 'border-yellow-200', dot: 'bg-yellow-500', }, low: { bg: 'bg-slate-100', text: 'text-slate-700', border: 'border-slate-200', dot: 'bg-slate-400', }, } // ============================================================================ // Event Type Icons & Colors // ============================================================================ export const EVENT_TYPE_CONFIG = { exam: { icon: 'FileQuestion', color: 'text-red-600', bg: 'bg-red-50', }, parent_meeting: { icon: 'Users', color: 'text-blue-600', bg: 'bg-blue-50', }, deadline: { icon: 'Clock', color: 'text-amber-600', bg: 'bg-amber-50', }, other: { icon: 'Calendar', color: 'text-slate-600', bg: 'bg-slate-50', }, } // ============================================================================ // Storage Keys // ============================================================================ export const STORAGE_KEYS = { SETTINGS: 'companion_settings', CURRENT_SESSION: 'companion_current_session', ONBOARDING_STATE: 'companion_onboarding', CUSTOM_TEMPLATES: 'companion_custom_templates', LAST_MODE: 'companion_last_mode', } // ============================================================================ // API Endpoints (relative to backend) // ============================================================================ export const API_ENDPOINTS = { DASHBOARD: '/api/state/dashboard', LESSON_START: '/api/classroom/sessions', LESSON_UPDATE: '/api/classroom/sessions', // + /{id} TEMPLATES: '/api/classroom/templates', SETTINGS: '/api/teacher/settings', FEEDBACK: '/api/feedback', } // ============================================================================ // Helper Functions // ============================================================================ /** * Create default phases array from durations */ export function createDefaultPhases(durations: PhaseDurations = DEFAULT_PHASE_DURATIONS): Phase[] { return PHASE_ORDER.map((phaseId, index) => ({ id: phaseId, shortName: PHASE_SHORT_NAMES[phaseId], displayName: PHASE_DISPLAY_NAMES[phaseId], duration: durations[phaseId], status: index === 0 ? 'active' : 'planned', color: PHASE_COLORS[phaseId].hex, })) } /** * Calculate total duration from phase durations */ export function calculateTotalDuration(durations: PhaseDurations): number { return Object.values(durations).reduce((sum, d) => sum + d, 0) } /** * Get timer color status based on remaining time */ export function getTimerColorStatus( remainingSeconds: number, isOvertime: boolean ): 'plenty' | 'warning' | 'critical' | 'overtime' { if (isOvertime) return 'overtime' if (remainingSeconds <= TIMER_CRITICAL_THRESHOLD) return 'critical' if (remainingSeconds <= TIMER_WARNING_THRESHOLD) return 'warning' return 'plenty' } /** * Format seconds as MM:SS */ export function formatTime(seconds: number): string { const absSeconds = Math.abs(seconds) const mins = Math.floor(absSeconds / 60) const secs = absSeconds % 60 const sign = seconds < 0 ? '-' : '' return `${sign}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}` } /** * Format minutes as "X Min" */ export function formatMinutes(minutes: number): string { return `${minutes} Min` }