// Hauptanwendung class SportAnmeldungApp { constructor() { this.kurse = []; this.betriebe = []; this.user = null; this.init(); } async init() { this.setupThemeToggle(); this.setupNavigation(); this.setupTabs(); this.setupLoginHandlers(); this.setupLogoutHandler(); await this.checkAuthAndToggleUI(); await this.loadInitialData(); this.setupFormHandlers(); } setupThemeToggle() { const toggle = document.getElementById('theme-toggle'); const icon = toggle.querySelector('.theme-icon'); const savedTheme = localStorage.getItem('theme') || 'light'; document.documentElement.setAttribute('data-theme', savedTheme); icon.textContent = savedTheme === 'dark' ? '☀️' : '🌙'; toggle.setAttribute('aria-pressed', savedTheme === 'dark' ? 'true' : 'false'); toggle.addEventListener('click', () => { const currentTheme = document.documentElement.getAttribute('data-theme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', newTheme); localStorage.setItem('theme', newTheme); icon.textContent = newTheme === 'dark' ? '☀️' : '🌙'; toggle.setAttribute('aria-pressed', newTheme === 'dark' ? 'true' : 'false'); }); } setupNavigation() { const navButtons = document.querySelectorAll('.nav-btn'); navButtons.forEach((btn) => { btn.addEventListener('click', (e) => { const view = e.target.dataset.view; this.switchView(view); }); }); } switchView(viewName) { document.querySelectorAll('.view').forEach((v) => v.classList.remove('active')); document.querySelectorAll('.nav-btn').forEach((b) => b.classList.remove('active')); const view = document.getElementById(`${viewName}-view`); if (view) view.classList.add('active'); document.querySelector(`[data-view="${viewName}"]`)?.classList.add('active'); if (viewName === 'berichte') { this.loadBerichte(); } else if (viewName === 'rechnungen') { this.loadRechnungsOptionen(); } } setupTabs() { const tabButtons = document.querySelectorAll('.tab-btn'); tabButtons.forEach((btn) => { btn.addEventListener('click', (e) => { const tab = e.target.dataset.tab; this.switchTab(tab); }); }); } switchTab(tabName) { document.querySelectorAll('.tab-content').forEach((t) => t.classList.remove('active')); document.querySelectorAll('.tab-btn').forEach((b) => b.classList.remove('active')); document.getElementById(`${tabName}-tab`).classList.add('active'); document.querySelector(`[data-tab="${tabName}"]`).classList.add('active'); } async checkAuthAndToggleUI() { try { const me = await API.me(); this.user = me.authenticated ? me.user : null; const isAdmin = !!this.user && this.user.role === 'admin'; document.querySelectorAll('.admin-only').forEach((el) => { el.classList.toggle('hidden', !isAdmin); }); document.getElementById('logout-btn').classList.toggle('hidden', !this.user); document.getElementById('login-tab-btn').classList.toggle('hidden', !!this.user); // Wenn aktuell Berichte/Rechnungen aktiv sind, aber nicht admin → auf Anmeldung umschalten const activeView = document.querySelector('.view.active')?.id || ''; if (!isAdmin && (activeView === 'berichte-view' || activeView === 'rechnungen-view')) { this.switchView('login'); } } catch (e) { this.user = null; document.querySelectorAll('.admin-only').forEach((el) => el.classList.add('hidden')); document.getElementById('logout-btn').classList.add('hidden'); document.getElementById('login-tab-btn').classList.remove('hidden'); } } async loadInitialData() { try { this.kurse = await API.getKurse(); this.betriebe = await API.getBetriebe(); this.renderKurse(); this.renderBetriebe(); } catch (error) { console.error('Fehler beim Laden der Daten:', error); alert('Fehler beim Laden der Daten. Bitte überprüfen Sie die API-Verbindung.'); } } renderKurse() { const container = document.getElementById('kurse-container'); container.innerHTML = this.kurse .map( (kurs) => `
` ) .join(''); document.querySelectorAll('.kurs-card').forEach((card) => { const checkbox = card.querySelector('input[type="checkbox"]'); if (checkbox && !checkbox.disabled) { card.addEventListener('click', (e) => { if (e.target.tagName !== 'INPUT') { checkbox.checked = !checkbox.checked; card.classList.toggle('selected', checkbox.checked); } }); checkbox.addEventListener('change', () => { card.classList.toggle('selected', checkbox.checked); }); } }); } renderBetriebe() { const select = document.getElementById('betrieb'); const rechnungSelect = document.getElementById('rechnung-betrieb'); const options = this.betriebe .map((betrieb) => ``) .join(''); select.innerHTML = '' + options; rechnungSelect.innerHTML = '' + options; } setupFormHandlers() { const form = document.getElementById('anmelde-form'); form.addEventListener('submit', (e) => { e.preventDefault(); this.handleAnmeldung(); }); const rechnungBtn = document.getElementById('rechnung-erstellen'); rechnungBtn.addEventListener('click', () => { this.handleRechnungErstellen(); }); document.getElementById('neu-anmelden')?.addEventListener('click', () => { document.getElementById('erfolg-meldung').classList.add('hidden'); form.reset(); document.querySelectorAll('.kurs-card').forEach((c) => c.classList.remove('selected')); }); document.getElementById('zur-uebersicht')?.addEventListener('click', () => { this.switchView('berichte'); }); } setupLoginHandlers() { const form = document.getElementById('login-form'); if (!form) return; form.addEventListener('submit', async (e) => { e.preventDefault(); const email = document.getElementById('login-email').value.trim(); const password = document.getElementById('login-password').value; const err = document.getElementById('login-error'); err.textContent = ''; try { await API.login(email, password); await this.checkAuthAndToggleUI(); this.switchView('berichte'); } catch (ex) { err.textContent = ex.message || 'Login fehlgeschlagen'; } }); } setupLogoutHandler() { const btn = document.getElementById('logout-btn'); btn.addEventListener('click', async () => { try { await API.logout(); this.user = null; await this.checkAuthAndToggleUI(); this.switchView('anmeldung'); } catch (e) { console.error(e); } }); } async handleAnmeldung() { const form = document.getElementById('anmelde-form'); const formData = new FormData(form); const selectedKurse = Array.from(document.querySelectorAll('input[name="kurse"]:checked')).map( (cb) => parseInt(cb.value, 10) ); if (selectedKurse.length === 0) { this.showFehler('Bitte wählen Sie mindestens eine Sportart aus.'); return; } const data = { vorname: formData.get('vorname'), nachname: formData.get('nachname'), email: formData.get('email'), geburtsdatum: formData.get('geburtsdatum') || null, betrieb_id: parseInt(formData.get('betrieb'), 10), kurs_ids: selectedKurse, }; try { const response = await API.anmelden(data); this.showErfolg(response); form.reset(); document.querySelectorAll('.kurs-card').forEach((c) => c.classList.remove('selected')); await this.loadInitialData(); } catch (error) { this.showFehler(error.message); } } showErfolg(response) { const meldung = document.getElementById('erfolg-meldung'); const text = document.getElementById('erfolg-text'); text.innerHTML = ` Vielen Dank für Ihre Anmeldung!| Betrieb | Anzahl Schüler | Anmeldungen | Details |
|---|---|---|---|
|
${b.betrieb_name} ${b.adresse} |
${b.anzahl_schueler} | ${b.anzahl_anmeldungen} |
${
b.schueler.length > 0
? `
|
| Kurs | Teilnehmer | Auslastung | Details |
|---|---|---|---|
| ${k.kurs_name} | ${k.anzahl_teilnehmer} / ${k.max_teilnehmer} |
${
k.teilnehmer.length > 0
? `
|
Rechnungsnummer: ${rechnung.rechnungsnummer}
Datum: ${new Date(rechnung.datum).toLocaleDateString('de-DE')}
Musterstraße 123
12345 Musterstadt
${rechnung.betrieb.name}
${rechnung.betrieb.adresse}
${rechnung.betrieb.email}
| Kurs | Anzahl Teilnehmer | Gebühr pro Teilnehmer | Gesamt |
|---|---|---|---|
| ${z.kurs_name} | ${z.anzahl_teilnehmer} | ${z.gebuehr}€ | ${z.gesamt_kurs}€ |
Bitte überweisen Sie den Betrag innerhalb von 14 Tagen unter Angabe der Rechnungsnummer.