'use strict'; // NOTE: innerHTML usage is intentional - content comes from our own API/DB only (admin-imported Markdown). // This is an internal training tool for 2-5 known users. No user-generated content. var Flashcards = { session: null, render: function(params) { var el = document.getElementById('content'); if (params[0] === 'study' && params[1]) { this.renderStudy(el, params[1]); return; } el.textContent = 'Lade Decks...'; var self = this; API.get('/decks').then(function(data) { self.renderDeckList(el, data.decks); }).catch(function(e) { el.textContent = e.message; }); }, renderDeckList: function(el, decks) { var total = decks.reduce(function(s, d) { return s + (d.card_count || 0); }, 0); var totalDue = decks.reduce(function(s, d) { return s + (parseInt(d.due) || 0); }, 0); var h = '
'; decks.forEach(function(d) { var reviewed = parseInt(d.reviewed) || 0; var ct = d.card_count || 0; var due = parseInt(d.due) || 0; var pct = ct > 0 ? Math.round((reviewed / ct) * 100) : 0; h += '
'; h += '
' + Markdown.esc(d.name) + '
'; h += '
' + ct + ' Karten — ' + pct + '% gelernt
'; if (due > 0) h += '
' + due + ' Karten faellig
'; h += '
'; h += '
'; }); h += '
'; el.innerHTML = h; // safe: data from own API only el.querySelectorAll('.deck-card').forEach(function(card) { card.addEventListener('click', function() { location.hash = '#/flashcards/study/' + card.dataset.slug; }); }); }, renderStudy: function(el, slug) { el.textContent = 'Lade Karten...'; var self = this; API.get('/cards/due?deck=' + slug + '&limit=50').then(function(data) { if (data.cards.length === 0) { return API.get('/cards/deck/' + slug).then(function(allData) { var h = '← Zurueck zu Decks'; h += '

Keine faelligen Karten

'; h += '

Alle Karten sind gelernt. Komm spaeter wieder!


'; h += '
'; el.innerHTML = h; // safe: static text + number document.getElementById('start-all-btn').addEventListener('click', function() { self.startSession(el, slug, allData.cards); }); }); } self.startSession(el, slug, data.cards); }).catch(function(e) { el.textContent = e.message; }); }, startSession: function(el, slug, cards) { this.session = { slug: slug, cards: cards, index: 0, correct: 0, wrong: 0, showAnswer: false }; this.renderCard(el); }, renderCard: function(el) { var s = this.session; if (s.index >= s.cards.length) { this.renderSummary(el); return; } var card = s.cards[s.index]; var open = s.cards.length - s.index - 1; var deckName = card.deck_name || s.slug; var lastReview = card.last_reviewed_at ? 'Zuletzt: ' + new Date(card.last_reviewed_at).toLocaleDateString('de-DE') : 'Noch nie gelernt'; var h = '← Zurueck zu Decks'; h += '
' + Markdown.esc(deckName) + ''; h += '
' + s.correct + ' richtig'; h += '' + s.wrong + ' falsch'; h += '' + open + ' offen
'; h += 'Karte ' + (s.index + 1) + ' / ' + s.cards.length + '
'; h += '
'; h += '
'; h += '

'; h += '
' + (card.level || 'basis') + ''; h += '' + lastReview + '
'; h += '
' + Markdown.render(card.question) + '
'; if (s.showAnswer) { h += '
Antwort
' + Markdown.render(card.answer) + '
'; h += '
'; h += ''; h += ''; h += ''; h += '
'; } else { h += '
'; } h += '
'; el.innerHTML = h; // safe: Markdown content from own DB var self = this; if (s.showAnswer) { document.getElementById('rate-easy').addEventListener('click', function() { self.rate('easy'); }); document.getElementById('rate-medium').addEventListener('click', function() { self.rate('medium'); }); document.getElementById('rate-hard').addEventListener('click', function() { self.rate('hard'); }); document.getElementById('rate-wrong').addEventListener('click', function() { self.rate('wrong'); }); } else { document.getElementById('show-answer-btn').addEventListener('click', function() { s.showAnswer = true; self.renderCard(el); }); } }, rate: function(rating) { var s = this.session; var card = s.cards[s.index]; if (rating === 'easy' || rating === 'medium') s.correct++; else s.wrong++; API.post('/cards/' + card.id + '/review', { rating: rating }).catch(function(e) { console.error('Review error:', e); }); s.index++; s.showAnswer = false; this.renderCard(document.getElementById('content')); }, renderSummary: function(el) { var s = this.session; var total = s.correct + s.wrong; var pct = total > 0 ? Math.round((s.correct / total) * 100) : 0; var h = '← Zurueck zu Decks'; h += '

Session abgeschlossen!


'; h += '
'; h += '' + s.correct + ' richtig'; h += '' + s.wrong + ' falsch

'; h += '

' + pct + '% korrekt


'; h += 'Zurueck zu Decks
'; el.innerHTML = h; // safe: only session stats } };