diff --git a/assets/js/offline-engine.js b/assets/js/offline-engine.js index 8147688..7142043 100644 --- a/assets/js/offline-engine.js +++ b/assets/js/offline-engine.js @@ -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); } \ No newline at end of file