Update assets/js/offline-engine.js

This commit is contained in:
2026-06-16 10:56:29 +02:00
parent 1c5cd257b7
commit 939de60914
+80 -94
View File
@@ -1,91 +1,113 @@
import { getDB } from './db.js';
function getStore(storeName, mode = 'readonly') {
/**
* HELPERS
*/
function store(storeName, mode = 'readonly') {
const db = getDB();
const tx = db.transaction(storeName, mode);
return tx.objectStore(storeName);
}
export async function saveWords(lang, list, words) {
/**
* IMPORT WORD LIST FROM SERVER → INDEXEDDB
*/
export async function importList(lang, list) {
const store = getStore('words', 'readwrite');
const res = await fetch(`/api/list.php?lang=${lang}&list=${list}`);
const data = await res.json();
for (const word of words) {
if (!data.words || !Array.isArray(data.words)) {
console.error("Import failed:", data);
return;
}
store.put({
const s = store('words', 'readwrite');
data.words.forEach(word => {
s.put({
key: `${lang}:${list}:${word.id}`,
id: word.id,
lang,
list,
...word
question: word.question,
answer: word.answer,
correct: word.correct || 0,
wrong: word.wrong || 0,
nextReview: word.nextReview || null,
interval: word.interval || 1
});
}
});
console.log(`Imported ${data.words.length} words`);
}
/**
* GET WORDS
*/
export async function getWords(lang, list) {
return new Promise((resolve) => {
const store = getStore('words');
const s = store('words');
const req = store.getAll();
const req = s.getAll();
req.onsuccess = () => {
const result = req.result.filter(
const filtered = req.result.filter(
w => w.lang === lang && w.list === list
);
resolve(result);
resolve(filtered);
};
});
}
/**
* GET NEXT WORD (SRS SIMPLE)
*/
export async function getNextWord(lang, list) {
const words = await getWords(lang, list);
if (!words.length) {
console.warn("No words in IndexedDB");
return null;
}
const today = new Date().toISOString().split('T')[0];
let due = words.filter(word => {
return !word.nextReview ||
word.nextReview <= today;
});
let due = words.filter(w =>
!w.nextReview || w.nextReview <= today
);
if (!due.length) {
due = words;
}
const random =
Math.floor(Math.random() * due.length);
return due[random];
return due[Math.floor(Math.random() * due.length)];
}
export async function answerWord(word, answer) {
/**
* ANSWER WORD
*/
export async function answerWord(word, input) {
const correct =
word.answer.trim().toLowerCase() ===
answer.trim().toLowerCase();
input.trim().toLowerCase();
const store =
getStore('words', 'readwrite');
const s = store('words', 'readwrite');
const updated = { ...word };
if (correct) {
const days =
updated.interval
? updated.interval * 2
: 1;
updated.correct++;
const days = updated.interval * 2;
updated.interval = days;
const d = new Date();
@@ -96,6 +118,8 @@ export async function answerWord(word, answer) {
} else {
updated.wrong++;
updated.interval = 1;
const d = new Date();
@@ -105,38 +129,29 @@ export async function answerWord(word, answer) {
d.toISOString().split('T')[0];
}
store.put(updated);
s.put(updated);
await updateSessionStats(correct);
updateSessionStats(correct);
await queueSync({
queueSync({
wordId: word.id,
lang: word.lang,
list: word.list,
correct,
timestamp: Date.now()
ts: Date.now()
});
return {
correct
};
return { correct };
}
async function queueSync(item) {
/**
* SESSION STATS
*/
export function updateSessionStats(correct) {
const store =
getStore('sync_queue', 'readwrite');
const s = store('session', 'readwrite');
store.add(item);
}
export async function updateSessionStats(correct) {
const store =
getStore('session', 'readwrite');
const req =
store.get('stats');
const req = s.get('stats');
req.onsuccess = () => {
@@ -150,13 +165,10 @@ export async function updateSessionStats(correct) {
};
}
if (correct) {
stats.correct++;
} else {
stats.wrong++;
}
if (correct) stats.correct++;
else stats.wrong++;
store.put(stats);
s.put(stats);
};
}
@@ -164,51 +176,25 @@ export async function getSessionStats() {
return new Promise(resolve => {
const store =
getStore('session');
const s = store('session');
const req =
store.get('stats');
const req = s.get('stats');
req.onsuccess = () => {
resolve(
req.result || {
correct: 0,
wrong: 0
}
);
resolve(req.result || {
correct: 0,
wrong: 0
});
};
});
}
export async function resetSessionStats() {
/**
* SYNC QUEUE
*/
function queueSync(item) {
const store =
getStore('session', 'readwrite');
store.put({
key: 'stats',
correct: 0,
wrong: 0
});
}
import { saveWords } from './offline-engine.js';
export async function importList(lang, list) {
const res = await fetch(
`/api/list.php?lang=${lang}&list=${list}`
);
const data = await res.json();
if (!data.words) {
throw new Error('No words');
}
await saveWords(lang, list, data.words);
return data.words.length;
const s = store('sync_queue', 'readwrite');
s.add(item);
}