""" Fehlzeiten Widget fuer das Lehrer-Dashboard. Zeigt abwesende Schueler fuer heute. """ class FehlzeitenWidget: widget_id = 'fehlzeiten' widget_name = 'Fehlzeiten' widget_icon = '⚠' # Warning widget_color = '#ef4444' # Red default_width = 'half' has_settings = True @staticmethod def get_css() -> str: return """ /* ===== Fehlzeiten Widget Styles ===== */ .widget-fehlzeiten { background: var(--bp-surface, #1e293b); border: 1px solid var(--bp-border, #475569); border-radius: 12px; padding: 16px; height: 100%; display: flex; flex-direction: column; } .widget-fehlzeiten .widget-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--bp-border-subtle, rgba(255,255,255,0.1)); } .widget-fehlzeiten .widget-title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; color: var(--bp-text, #e5e7eb); } .widget-fehlzeiten .widget-icon { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; background: rgba(239, 68, 68, 0.15); color: #ef4444; border-radius: 8px; font-size: 14px; } .widget-fehlzeiten .fehlzeiten-count { background: rgba(239, 68, 68, 0.15); color: #ef4444; padding: 4px 10px; border-radius: 12px; font-size: 12px; font-weight: 600; } .widget-fehlzeiten .fehlzeiten-list { flex: 1; overflow-y: auto; } .widget-fehlzeiten .fehlzeit-item { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--bp-border-subtle, rgba(255,255,255,0.05)); } .widget-fehlzeiten .fehlzeit-item:last-child { border-bottom: none; } .widget-fehlzeiten .fehlzeit-status { width: 10px; height: 10px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; } .widget-fehlzeiten .fehlzeit-status.krank { background: #ef4444; } .widget-fehlzeiten .fehlzeit-status.entschuldigt { background: #f59e0b; } .widget-fehlzeiten .fehlzeit-status.unentschuldigt { background: #6b7280; } .widget-fehlzeiten .fehlzeit-content { flex: 1; } .widget-fehlzeiten .fehlzeit-name { font-size: 14px; font-weight: 500; color: var(--bp-text, #e5e7eb); margin-bottom: 4px; } .widget-fehlzeiten .fehlzeit-details { font-size: 12px; color: var(--bp-text-muted, #9ca3af); } .widget-fehlzeiten .fehlzeit-details .grund { display: inline-flex; align-items: center; gap: 4px; margin-right: 8px; } .widget-fehlzeiten .fehlzeiten-empty { text-align: center; padding: 24px; color: var(--bp-text-muted, #9ca3af); font-size: 13px; } .widget-fehlzeiten .fehlzeiten-empty-icon { font-size: 32px; margin-bottom: 8px; } .widget-fehlzeiten .fehlzeiten-empty.success { color: #10b981; } .widget-fehlzeiten .fehlzeiten-empty.success .fehlzeiten-empty-icon { opacity: 1; } .widget-fehlzeiten .fehlzeiten-footer { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--bp-border-subtle, rgba(255,255,255,0.1)); } .widget-fehlzeiten .fehlzeiten-all-btn { width: 100%; padding: 10px; background: transparent; border: 1px dashed var(--bp-border, #475569); border-radius: 8px; color: var(--bp-text-muted, #9ca3af); font-size: 12px; cursor: pointer; transition: all 0.2s; } .widget-fehlzeiten .fehlzeiten-all-btn:hover { border-color: #ef4444; color: #ef4444; } """ @staticmethod def get_html() -> str: return """
""" @staticmethod def get_js() -> str: return """ // ===== Fehlzeiten Widget JavaScript ===== const FEHLZEITEN_STORAGE_KEY = 'bp-lehrer-fehlzeiten'; function getDefaultFehlzeiten() { // Demo data - in production this would come from an API return [ { id: 1, name: 'Max Mueller', klasse: '10a', grund: 'krank', seit: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(), notiz: 'Attest liegt vor' }, { id: 2, name: 'Lisa Schmidt', klasse: '11b', grund: 'entschuldigt', seit: new Date().toISOString(), notiz: 'Arzttermin' }, { id: 3, name: 'Tom Weber', klasse: '10a', grund: 'unentschuldigt', seit: new Date().toISOString(), notiz: null } ]; } function loadFehlzeiten() { const stored = localStorage.getItem(FEHLZEITEN_STORAGE_KEY); return stored ? JSON.parse(stored) : getDefaultFehlzeiten(); } function saveFehlzeiten(fehlzeiten) { localStorage.setItem(FEHLZEITEN_STORAGE_KEY, JSON.stringify(fehlzeiten)); } function formatFehlzeitDauer(seit) { const seitDate = new Date(seit); const now = new Date(); const diffDays = Math.floor((now - seitDate) / (24 * 60 * 60 * 1000)); if (diffDays === 0) return 'heute'; if (diffDays === 1) return 'seit gestern'; return `seit ${diffDays} Tagen`; } function getGrundLabel(grund) { const labels = { krank: '😷 Krank', entschuldigt: '✅ Entschuldigt', unentschuldigt: '❓ Unentschuldigt' }; return labels[grund] || grund; } function renderFehlzeiten() { const list = document.getElementById('fehlzeiten-list'); const countEl = document.getElementById('fehlzeiten-count'); if (!list) return; const fehlzeiten = loadFehlzeiten(); if (countEl) { countEl.textContent = fehlzeiten.length; } if (fehlzeiten.length === 0) { list.innerHTML = `