feat: Add WFW-Aushang web app with PWA support, offline caching, and dark mode

- Created index.html for the main application interface with responsive design and dark mode support.
- Added manifest.webmanifest for PWA configuration, including app icons and display settings.
- Implemented service worker (sw.js) for offline caching of assets and network-first strategy for versioning.
- Introduced version.json to manage app versioning.
This commit is contained in:
thrhymes
2025-12-24 16:59:51 +01:00
parent 5577407f97
commit b049dded72
24 changed files with 4167 additions and 0 deletions

638
bibel-pwa/script.js Normal file
View File

@@ -0,0 +1,638 @@
/*
* Bibel LernApp
*
* Dieses Skript lädt die Daten aus einer separaten JSONDatei,
* gruppiert sie nach Themen, baut den LernkartenStapeln je nach Modus auf
* und verwaltet das Anzeigen von Karten, Zählern, Hinweisen und DarkMode.
* Außerdem wird ein SplashScreen bereitgestellt, über den die App
* installiert werden kann, sobald das BrowserEreignis
* `beforeinstallprompt` ausgelöst wird.
*/
(() => {
// FallbackDaten, falls data.json nicht geladen werden kann (z.B. beim file://Protokoll).
const fallbackData = [
{
"Thema": "Zukunft",
"Kommentar": "Die aktuelle Weltlage und die Einstellung der Menschen deuten darauf hin, dass große Veränderungen bevorstehen",
"Bibel-Verweis": "Mat. 24:3",
"Bibeltext": "Und als er auf dem Ölberg saß, traten zu ihm seine Jünger allein und fragten: Sage uns, wann wird das geschehen, und was wird das Zeichen deines Kommens und des Endes der Welt?",
"Schluesselwoerter": ["Veränderungen", "Zeichen"]
},
{
"Thema": "Zukunft",
"Kommentar": "Die Erde wird nie zerstört werden",
"Bibel-Verweis": "Ps. 104:5",
"Bibeltext": "Der du die Erde auf ihre Grundfesten gegründet hast, daß sie für immer und ewig steht.",
"Schluesselwoerter": ["Erde", "ewig"]
},
{
"Thema": "Zukunft",
"Kommentar": "Die Umweltzerstörung wird vollständig rückgängig gemacht",
"Bibel-Verweis": "Jes. 35:1-2",
"Bibeltext": "Die Wüste und Einöde wird lustig sein, und das dürre Land wird frohlocken; sie wird blühen wie die Lilien.",
"Schluesselwoerter": ["Wüste", "blühen"]
},
{
"Thema": "Zukunft",
"Kommentar": "Alle Menschen werden völlig gesund sein",
"Bibel-Verweis": "Jes. 33:24",
"Bibeltext": "Kein Einwohner wird sagen: Ich bin krank; dem Volk, das dort wohnt, wird seine Schuld vergeben sein.",
"Schluesselwoerter": ["gesund", "heil"]
},
{
"Thema": "Zukunft",
"Kommentar": "Sie können für immer auf der Erde leben",
"Bibel-Verweis": "Ps. 37:29",
"Bibeltext": "Die Gerechten erben das Land und bleiben ewiglich darin.",
"Schluesselwoerter": ["erben", "Land"]
},
{
"Thema": "Familie",
"Kommentar": "Ein Ehemann sollte seine Frau „lieben wie sich selbst“",
"Bibel-Verweis": "Eph. 5:33",
"Bibeltext": "Doch auch ihr, jeder von euch liebe seine Frau wie sich selbst; die Frau aber erweise dem Mann Ehrfurcht.",
"Schluesselwoerter": ["Liebe", "Respekt"]
},
{
"Thema": "Familie",
"Kommentar": "Eine Ehefrau sollte ihren Mann von Herzen respektieren",
"Bibel-Verweis": "Eph. 5:33",
"Bibeltext": "Doch auch ihr, jeder von euch liebe seine Frau wie sich selbst; die Frau aber erweise dem Mann Ehrfurcht.",
"Schluesselwoerter": ["Respekt", "Ehemann"]
},
{
"Thema": "Familie",
"Kommentar": "Mann und Frau sollten einander treu sein",
"Bibel-Verweis": "Mal. 2:16",
"Bibeltext": "Denn ich hasse die Scheidung, spricht der HERR … so hütet euch in eurem Geist und seid nicht treulos.",
"Schluesselwoerter": ["Treue", "Ehe"]
},
{
"Thema": "Familie",
"Kommentar": "Es wirkt sich auf Kinder gut aus, wenn sie ihre Eltern respektieren und auf sie hören",
"Bibel-Verweis": "Spr. 1:8-9",
"Bibeltext": "Höre, mein Sohn, die Unterweisung deines Vaters und verlaß nicht das Gesetz deiner Mutter; denn das wird deinem Haupt ein lieblicher Schmuck sein.",
"Schluesselwoerter": ["Kinder", "Gehorsam"]
},
{
"Thema": "Gott",
"Kommentar": "Gott hat einen Namen",
"Bibel-Verweis": "Ps. 83:18",
"Bibeltext": "… damit man erkenne: Du allein, dessen Name Jehova ist, der Höchste bist über die ganze Erde.",
"Schluesselwoerter": ["Name", "Jehova"]
},
{
"Thema": "Gott",
"Kommentar": "Gott kommuniziert mit uns",
"Bibel-Verweis": "2. Tim. 3:16-17",
"Bibeltext": "Alle Schrift ist von Gott eingegeben und nütze zur Lehre, zur Zurechtweisung, zur Besserung … damit der Mensch Gottes vollkommen sei.",
"Schluesselwoerter": ["Schrift", "göttlich"]
},
{
"Thema": "Gott",
"Kommentar": "Gott ist fair und hat keine Vorurteile",
"Bibel-Verweis": "5. Mo. 10:17",
"Bibeltext": "Denn der HERR, euer Gott, … ist kein Anseher der Person und nimmt keine Bestechung an.",
"Schluesselwoerter": ["gerecht", "unparteiisch"]
},
{
"Thema": "Gott",
"Kommentar": "Gott möchte uns helfen",
"Bibel-Verweis": "Ps. 46:1",
"Bibeltext": "Gott ist unsre Zuflucht und Stärke, ein bewährter Helfer in Nöten.",
"Schluesselwoerter": ["Hilfe", "Zuflucht"]
},
{
"Thema": "Gebet",
"Kommentar": "Gott wünscht sich, dass wir zu ihm beten",
"Bibel-Verweis": "Ps. 62:8",
"Bibeltext": "Vertraut auf ihn allezeit, liebe Leute, schüttet euer Herz vor ihm aus; Gott ist unsere Zuflucht.",
"Schluesselwoerter": ["Beten", "vertrauen"]
},
{
"Thema": "Gebet",
"Kommentar": "Aus der Bibel erfahren wir, wie man beten sollte",
"Bibel-Verweis": "Mat. 6:7-13",
"Bibeltext": "Wenn ihr betet, sollt ihr nicht plappern … Unser Vater im Himmel! Dein Name werde geheiligt …",
"Schluesselwoerter": ["Gebet", "Vaterunser"]
},
{
"Thema": "Gebet",
"Kommentar": "Wir sollten oft beten",
"Bibel-Verweis": "Mat. 7:7-8",
"Bibeltext": "Bittet, so wird euch gegeben; suchet, so werdet ihr finden; klopfet an, so wird euch aufgetan.",
"Schluesselwoerter": ["bitten", "suchen"]
},
{
"Thema": "Jesus",
"Kommentar": "Jesus war ein außergewöhnlicher Lehrer. Sein Rat funktioniert immer",
"Bibel-Verweis": "Mat. 6:14-15",
"Bibeltext": "Denn wenn ihr den Menschen ihre Verfehlungen vergebt, wird euch euer himmlischer Vater auch vergeben.",
"Schluesselwoerter": ["Vergebung", "Lehrer"]
},
{
"Thema": "Jesus",
"Kommentar": "Jesus hat Ereignisse vorausgesagt, die wir heute beobachten können",
"Bibel-Verweis": "Mat. 24:3",
"Bibeltext": "Und als er auf dem Ölberg saß, traten zu ihm seine Jünger allein und fragten: Sage uns, wann wird das geschehen, und was wird das Zeichen deines Kommens und des Endes der Welt?",
"Schluesselwoerter": ["Prophezeiung", "Endzeit"]
},
{
"Thema": "Jesus",
"Kommentar": "Jesus ist Gottes Sohn",
"Bibel-Verweis": "Mat. 16:16",
"Bibeltext": "Du bist der Christus, der Sohn des lebendigen Gottes.",
"Schluesselwoerter": ["Christus", "Sohn"]
},
{
"Thema": "Jesus",
"Kommentar": "Jesus ist nicht der allmächtige Gott",
"Bibel-Verweis": "Joh. 14:28",
"Bibeltext": "… denn der Vater ist größer als ich.",
"Schluesselwoerter": ["Vater", "größer"]
},
{
"Thema": "Reich Gottes",
"Kommentar": "Das Reich Gottes ist eine echte Regierung im Himmel",
"Bibel-Verweis": "Dan. 2:44",
"Bibeltext": "Aber zur Zeit solcher Königreiche wird der Gott des Himmels ein Königreich aufrichten, das nimmermehr zerstört wird; und sein Königreich wird auf kein ander Volk kommen. Es wird alle diese Königreiche zermalmen und verstören; aber es selbst wird ewiglich bleiben.",
"Schluesselwoerter": ["Königreich", "Himmel"]
},
{
"Thema": "Reich Gottes",
"Kommentar": "Gottes Reich wird alle Regierungen auf der Erde ersetzen",
"Bibel-Verweis": "Ps. 2:7-9",
"Bibeltext": "Du bist mein Sohn; heute habe ich dich gezeugt … Zerbrich sie mit eisernem Zepter und zerschmettere sie.",
"Schluesselwoerter": ["Regierungen", "ersetzen"]
},
{
"Thema": "Reich Gottes",
"Kommentar": "Nur Gottes Reich kann die Probleme der Menschheit lösen",
"Bibel-Verweis": "Ps. 37:10-11",
"Bibeltext": "Nur noch eine kleine Weile, so ist der Gottlose nicht mehr; … die Sanftmütigen aber werden das Land erben und großen Frieden haben.",
"Schluesselwoerter": ["Frieden", "Lösung"]
},
{
"Thema": "Leid",
"Kommentar": "Gott ist nicht schuld, wenn wir leiden",
"Bibel-Verweis": "5. Mo. 32:4",
"Bibeltext": "Er ist ein Fels; vollkommen ist sein Tun, denn alle seine Wege sind recht; ein treuer Gott, ohne Falsch.",
"Schluesselwoerter": ["gerecht", "Schuld"]
},
{
"Thema": "Leid",
"Kommentar": "Diese Welt wird vom Teufel beherrscht",
"Bibel-Verweis": "Luk. 4:5-6",
"Bibeltext": "Da führte ihn der Teufel auf einen hohen Berg … Dir will ich alle Macht und Herrlichkeit dieser Reiche geben, denn sie ist mir übergeben.",
"Schluesselwoerter": ["Teufel", "Welt"]
},
{
"Thema": "Leid",
"Kommentar": "Gott sieht es, wenn Sie leiden, und möchte Ihnen helfen",
"Bibel-Verweis": "Ps. 34:17-19",
"Bibeltext": "Der HERR ist nahe denen, die zerbrochenen Herzens sind … Er erlöst sie aus allen ihren Nöten.",
"Schluesselwoerter": ["nah", "helfen"]
},
{
"Thema": "Leid",
"Kommentar": "Gott wird allem Leid bald ein Ende machen",
"Bibel-Verweis": "Jes. 65:17",
"Bibeltext": "Denn siehe, ich schaffe einen neuen Himmel und eine neue Erde …",
"Schluesselwoerter": ["neuer Himmel", "Ende"]
},
{
"Thema": "Tod",
"Kommentar": "Die Toten sind ohne jedes Bewusstsein und leiden auch nicht",
"Bibel-Verweis": "Pred. 9:5",
"Bibeltext": "Denn die Lebenden wissen, dass sie sterben; die Toten aber wissen nichts …",
"Schluesselwoerter": ["Toten", "Bewusstsein"]
},
{
"Thema": "Tod",
"Kommentar": "Die Toten können uns weder helfen noch uns schaden",
"Bibel-Verweis": "Ps. 146:4",
"Bibeltext": "Wenn ein Mensch stirbt, kehrt sein Geist zurück zur Erde; an demselben Tag sind alle seine Pläne zunichte.",
"Schluesselwoerter": ["helfen", "schaden"]
},
{
"Thema": "Tod",
"Kommentar": "Unsere geliebten Verstorbenen werden auferweckt",
"Bibel-Verweis": "Hiob 14:13-15",
"Bibeltext": "Wenn du mich nur im Totenreich verwahrtest … du würdest rufen, und ich würde dir antworten.",
"Schluesselwoerter": ["Auferweckung", "Hoffnung"]
},
{
"Thema": "Tod",
"Kommentar": "Den Tod wird es nicht mehr geben",
"Bibel-Verweis": "Offb. 21:3-4",
"Bibeltext": "Gott wird abwischen alle Tränen von ihren Augen; der Tod wird nicht mehr sein …",
"Schluesselwoerter": ["Tod", "nicht mehr"]
},
{
"Thema": "Religion",
"Kommentar": "Gott ist nicht mit allen Religionen einverstanden",
"Bibel-Verweis": "Jer. 7:11",
"Bibeltext": "Ist denn dieses Haus, das nach meinem Namen genannt ist, eine Räuberhöhle geworden in euren Augen?",
"Schluesselwoerter": ["Religion", "Räuberhöhle"]
},
{
"Thema": "Religion",
"Kommentar": "Gott hasst Heuchelei",
"Bibel-Verweis": "Jes. 29:13",
"Bibeltext": "Dieses Volk naht mir mit seinem Mund … aber ihr Herz ist fern von mir.",
"Schluesselwoerter": ["Heuchelei", "Herz"]
},
{
"Thema": "Religion",
"Kommentar": "Die wahre Religion zeichnet sich durch echte Liebe aus",
"Bibel-Verweis": "Joh. 13:34-35",
"Bibeltext": "Ein neues Gebot gebe ich euch: dass ihr einander liebt … Daran werden alle erkennen, dass ihr meine Jünger seid.",
"Schluesselwoerter": ["Liebe", "Gebot"]
}
];
const modeSelect = document.getElementById('mode-select');
const topicSelect = document.getElementById('topic-select');
const bookSelect = document.getElementById('book-select');
const commentHint = document.getElementById('comment-hint');
const keywordHint = document.getElementById('keyword-hint');
const themeHint = document.getElementById('theme-hint');
const cardEl = document.querySelector('.card');
const cardFrontSymbol = document.querySelector('.card-symbol');
const cardFrontRef = document.querySelector('.card-ref');
const cardFrontComment = document.querySelector('.card-comment');
const cardBackText = document.querySelector('.card-back .card-text');
const cardFrontKeywords = document.querySelector('.card-front .card-keywords');
const cardBackCounter = document.querySelector('.card-back .card-counter');
const correctBtn = document.getElementById('correct-btn');
const wrongBtn = document.getElementById('wrong-btn');
const counterDisplay = document.getElementById('counter');
const darkToggle = document.getElementById('dark-mode-toggle');
const splashScreen = document.getElementById('splash-screen');
const installBtn = document.getElementById('install-btn');
const continueBtn = document.getElementById('continue-btn');
// Mapping von Themen zu Symbolen und Farben
const topicMapping = {
'Zukunft': { color: '#B2E0F1', symbol: '⏳' },
'Familie': { color: '#FFEFA1', symbol: '👨‍👩‍👧‍👦' },
'Gott': { color: '#C3EACE', symbol: '🕊️' },
'Gebet': { color: '#F9B5C8', symbol: '🙏' },
'Jesus': { color: '#FFD0B5', symbol: '✝️' },
'Reich Gottes': { color: '#ADD7F6', symbol: '👑' },
'Leid': { color: '#D3C0E6', symbol: '😢' },
'Tod': { color: '#B7D4E7', symbol: '⚰️' },
'Religion': { color: '#FFC8BF', symbol: '⛪️' },
};
// Daten werden nach dem Laden der Seite geladen
let data = [];
let topics = {};
let uniqueBooks = [];
let deck = [];
let currentIndex = 0;
// Zähler für aktuelle Session
let correctCount = 0;
// Fortlaufende Statistik über alle Sessions hinweg nach Thema
let progressData = {};
// Statistik pro Karte (richtig/falsch)
let cardStats = {};
let deferredPrompt = null;
// Gruppiert Daten nach Thema und sammelt Buchlisten
function groupData() {
topics = {};
const booksSet = new Set();
data.forEach(item => {
const theme = item['Thema'];
if (!topics[theme]) {
topics[theme] = {
color: (topicMapping[theme] && topicMapping[theme].color) || '#CCCCCC',
symbol: (topicMapping[theme] && topicMapping[theme].symbol) || '📖',
items: [],
};
}
topics[theme].items.push(item);
// Extrahiere Buch zur Liste
const book = extractBook(item['Bibel-Verweis']);
booksSet.add(book);
});
uniqueBooks = Array.from(booksSet).sort((a, b) => a.localeCompare(b, 'de')); // sortiert nach deutschem Collation
}
// Extrahiert das Buch aus einem Verweis (z.B. "2. Tim. 3:1-5" -> "2. Tim.")
function extractBook(ref) {
const beforeColon = ref.split(':')[0].trim();
const parts = beforeColon.split(' ');
// Entferne die letzte Komponente (Kapitel)
if (parts.length > 1) parts.pop();
return parts.join(' ');
}
// Generiert einen eindeutigen Schlüssel für eine Karte. Wir verwenden Thema,
// den BibelVerweis und den Kommentar, um Karten eindeutig zu identifizieren.
function getCardKey(item) {
const theme = item['Thema'] || '';
const ref = item['Bibel-Verweis'] || '';
const comment = item['Kommentar'] || '';
return `${theme}|${ref}|${comment}`;
}
// Füllt die Auswahlfelder für Thema und Buch
function populateSelects() {
// Themenauswahl
topicSelect.innerHTML = '';
Object.keys(topics).forEach(name => {
const option = document.createElement('option');
option.value = name;
option.textContent = name;
topicSelect.appendChild(option);
});
// Buchauswahl
bookSelect.innerHTML = '';
uniqueBooks.forEach(name => {
const option = document.createElement('option');
option.value = name;
option.textContent = name;
bookSelect.appendChild(option);
});
}
// Mischt ein Array (FisherYates)
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
// Bereitet das KartenDeck entsprechend dem aktuellen Modus vor
function prepareDeck() {
const mode = modeSelect.value;
let items = [];
if (mode === 'random') {
// Alle Elemente
items = [...data];
} else if (mode === 'topic') {
const selectedTheme = topicSelect.value;
items = topics[selectedTheme] ? [...topics[selectedTheme].items] : [];
} else if (mode === 'book') {
const selectedBook = bookSelect.value;
items = data.filter(item => extractBook(item['Bibel-Verweis']) === selectedBook);
}
deck = shuffle(items);
currentIndex = 0;
correctCount = 0;
updateCounter();
}
// Aktualisiert die Anzeige der aktuellen Karte
function updateCard() {
if (deck.length === 0) {
cardFrontRef.textContent = 'Keine Karten';
cardBackText.textContent = '';
cardFrontSymbol.textContent = '';
cardEl.classList.remove('flipped');
return;
}
const item = deck[currentIndex];
const theme = item['Thema'];
const mapping = topicMapping[theme] || { color: '#CCCCCC', symbol: '📖' };
// Setze die Akzentfarbe über CSSVariable
cardFrontRef.parentElement.style.setProperty('--accent-color', mapping.color);
cardBackText.parentElement.style.setProperty('--accent-color', mapping.color);
// Thema als Text oder leer je nach Hint
if (themeHint && themeHint.checked) {
cardFrontSymbol.textContent = theme;
} else {
cardFrontSymbol.textContent = '';
}
// Referenz immer ohne Keywords anzeigen
cardFrontRef.textContent = item['Bibel-Verweis'];
// Kommentar sichtbar machen, wenn aktiviert
if (commentHint.checked) {
cardFrontComment.textContent = item['Kommentar'];
} else {
cardFrontComment.textContent = '';
}
// Setze Text der Rückseite
cardBackText.textContent = item['Bibeltext'];
// Aktualisiere die PerKartenZähleranzeige
if (cardBackCounter) {
const key = getCardKey(item);
const stats = cardStats[key] || { correct: 0, wrong: 0 };
const correctVal = stats.correct || 0;
const wrongVal = stats.wrong || 0;
cardBackCounter.textContent = `Richtig: ${correctVal} | Falsch: ${wrongVal}`;
}
// Schlüsselwörter auf der Vorderseite, falls aktiviert
if (keywordHint && keywordHint.checked) {
const keywords = item['Schluesselwoerter'] || [];
cardFrontKeywords.textContent = keywords.join(', ');
} else {
cardFrontKeywords.textContent = '';
}
// Stellen Sie sicher, dass die Karte initial nicht umgedreht ist
cardEl.classList.remove('flipped');
}
// Aktualisiert den Counter oben rechts
function updateCounter() {
const total = deck.length;
counterDisplay.textContent = `${correctCount}/${total}`;
}
// Wechselt zur nächsten Karte im Stapel
function nextCard() {
if (deck.length === 0) return;
currentIndex = (currentIndex + 1) % deck.length;
updateCard();
updateCounter();
}
// EreignisListener für DarkMode
function handleDarkModeChange() {
const dark = darkToggle.checked;
document.body.classList.toggle('dark', dark);
localStorage.setItem('darkMode', dark);
}
// Initialisiert die SplashScreenLogik
function initSplash() {
// Zeige Splash nur, wenn noch nicht gesehen
const dismissed = localStorage.getItem('splashDismissed');
if (dismissed) return;
splashScreen.classList.remove('hidden');
}
// Registriert Service Worker
function registerSW() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('service-worker.js')
.catch(err => console.error('Service Worker registration failed:', err));
}
}
// HauptInitialisierung
document.addEventListener('DOMContentLoaded', async () => {
// Lade Daten
try {
if (location.protocol === 'file:') {
// Beim direkten Öffnen über das Dateisystem schlägt fetch typischerweise fehl.
// Verwenden Sie in diesem Fall FallbackDaten aus dieser Datei.
data = fallbackData;
} else {
const res = await fetch('data.json');
if (!res.ok) throw new Error('Network response was not ok');
data = await res.json();
}
} catch (err) {
console.warn('Fehler beim Laden der Daten, verwende FallbackDaten:', err);
data = fallbackData;
}
// Lade gespeicherte Zähler aus localStorage
try {
const storedProgress = localStorage.getItem('progressData');
if (storedProgress) progressData = JSON.parse(storedProgress);
} catch (e) {
progressData = {};
}
try {
const storedStats = localStorage.getItem('cardStats');
if (storedStats) cardStats = JSON.parse(storedStats);
} catch (e) {
cardStats = {};
}
// Gruppiere Daten und fülle Auswahlfelder
groupData();
populateSelects();
// Auswahllisten je nach Modus initial ausblenden
topicSelect.classList.toggle('hidden', modeSelect.value !== 'topic');
bookSelect.classList.toggle('hidden', modeSelect.value !== 'book');
prepareDeck();
updateCard();
// Dark mode initial
const darkPref = localStorage.getItem('darkMode') === 'true';
darkToggle.checked = darkPref;
document.body.classList.toggle('dark', darkPref);
// Splash init
initSplash();
// Service Worker
registerSW();
});
// EventListener für ModeÄnderungen
modeSelect.addEventListener('change', () => {
const mode = modeSelect.value;
topicSelect.classList.toggle('hidden', mode !== 'topic');
bookSelect.classList.toggle('hidden', mode !== 'book');
prepareDeck();
updateCard();
});
topicSelect.addEventListener('change', () => {
prepareDeck();
updateCard();
});
bookSelect.addEventListener('change', () => {
prepareDeck();
updateCard();
});
// Hint toggles
commentHint.addEventListener('change', () => {
updateCard();
});
keywordHint.addEventListener('change', () => {
updateCard();
});
if (themeHint) {
themeHint.addEventListener('change', () => {
updateCard();
});
}
// Card click flip
cardEl.addEventListener('click', () => {
if (deck.length === 0) return;
cardEl.classList.toggle('flipped');
});
// Korrekt/Wrong Buttons
correctBtn.addEventListener('click', () => {
if (deck.length === 0) return;
// Aktuelle Karte
const item = deck[currentIndex];
const theme = item['Thema'];
const key = getCardKey(item);
// SessionCounter erhöhen
correctCount++;
// Fortschrittsdaten pro Thema aktualisieren
if (!progressData[theme]) progressData[theme] = { correct: 0, wrong: 0 };
progressData[theme].correct++;
// PerKartenStatistik aktualisieren
if (!cardStats[key]) cardStats[key] = { correct: 0, wrong: 0 };
cardStats[key].correct++;
// Speichern in localStorage
try {
localStorage.setItem('progressData', JSON.stringify(progressData));
localStorage.setItem('cardStats', JSON.stringify(cardStats));
} catch (e) {
console.warn('Speichern der Zählerdaten fehlgeschlagen:', e);
}
nextCard();
});
wrongBtn.addEventListener('click', () => {
if (deck.length === 0) return;
// Aktuelle Karte
const item = deck[currentIndex];
const theme = item['Thema'];
const key = getCardKey(item);
// Fortschrittsdaten pro Thema aktualisieren
if (!progressData[theme]) progressData[theme] = { correct: 0, wrong: 0 };
progressData[theme].wrong++;
// PerKartenStatistik aktualisieren
if (!cardStats[key]) cardStats[key] = { correct: 0, wrong: 0 };
cardStats[key].wrong++;
// Speichern in localStorage
try {
localStorage.setItem('progressData', JSON.stringify(progressData));
localStorage.setItem('cardStats', JSON.stringify(cardStats));
} catch (e) {
console.warn('Speichern der Zählerdaten fehlgeschlagen:', e);
}
nextCard();
});
// Dark mode toggle
darkToggle.addEventListener('change', handleDarkModeChange);
// SplashScreen Buttons
continueBtn.addEventListener('click', () => {
splashScreen.classList.add('hidden');
localStorage.setItem('splashDismissed', 'true');
});
installBtn.addEventListener('click', async () => {
if (deferredPrompt) {
deferredPrompt.prompt();
const result = await deferredPrompt.userChoice;
console.log('Install result:', result);
deferredPrompt = null;
}
splashScreen.classList.add('hidden');
localStorage.setItem('splashDismissed', 'true');
});
// beforeinstallprompt event
window.addEventListener('beforeinstallprompt', e => {
// Verhindere die StandardBanneranzeige
e.preventDefault();
deferredPrompt = e;
// Falls der Splash noch sichtbar ist, zeige InstallButton
installBtn.style.display = 'inline-block';
});
})();