import { getHistory } from './history.ts'; import { execute } from './sqlite-manager.ts'; export interface HistoryViewCallbacks { onBack: () => void; } let allRecords: any[] = []; let showBadOnly = false; const BAD_MODES = new Set(['hard', 'none']); /** * Показывает страницу истории повторений для указанной колоды. */ export async function renderHistoryView( container: HTMLElement, setId: number, callbacks: HistoryViewCallbacks, ): Promise { showBadOnly = false; container.innerHTML = `
Загрузка...
Загрузка истории...
`; document.getElementById('btnHistoryBack')?.addEventListener('click', () => { callbacks.onBack(); }); document.getElementById('btnFilterAll')?.addEventListener('click', () => { showBadOnly = false; updateFilterButtons(); renderRows(container); }); document.getElementById('btnFilterBad')?.addEventListener('click', () => { showBadOnly = true; updateFilterButtons(); renderRows(container); }); try { allRecords = await getHistory(setId, 2000); const wordIds = [...new Set(allRecords.map((r) => r.word_id))]; const wordMap = await getWordMap(wordIds); // Сохраняем wordMap для renderRows (window as any).__wordMap = wordMap; const headerSpan = container.querySelector('.history-header span'); if (headerSpan) { headerSpan.textContent = `всего записей: ${allRecords.length}`; } renderRows(container); } catch (err) { console.error('[History] Ошибка загрузки:', err); const contentEl = document.getElementById('history-content'); if (contentEl) { contentEl.innerHTML = '
Ошибка загрузки истории
'; } } } function updateFilterButtons() { const btnAll = document.getElementById('btnFilterAll'); const btnBad = document.getElementById('btnFilterBad'); if (btnAll && btnBad) { btnAll.classList.toggle('active', !showBadOnly); btnBad.classList.toggle('active', showBadOnly); } } function renderRows(container: HTMLElement) { const contentEl = document.getElementById('history-content'); if (!contentEl) return; const wordMap = (window as any).__wordMap as Map || new Map(); const headerSpan = container.querySelector('.history-header span'); let filtered = allRecords; if (showBadOnly) { filtered = allRecords.filter((r) => BAD_MODES.has(r.mode)); } if (headerSpan) { headerSpan.textContent = showBadOnly ? `плохих: ${filtered.length} / ${allRecords.length}` : `всего записей: ${allRecords.length}`; } if (filtered.length === 0) { contentEl.innerHTML = '
Нет записей
'; return; } contentEl.innerHTML = ''; for (const record of filtered) { const word = wordMap.get(record.word_id); const wordText = word ? word : `#${record.word_id}`; const date = new Date(record.timestamp); const dateStr = date.toLocaleString('ru-RU', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit', }); const modeLabels: Record = { easy: '🟢 Легко', ok: '🟡 Нормально', hard: '🟠 Тяжело', none: '🔴 Не знаю', }; const row = document.createElement('div'); row.className = 'history-row'; row.innerHTML = `
${escapeHtml(wordText)}
${modeLabels[record.mode] || record.mode}
${record.score_before.toFixed(1)} ${record.score_after.toFixed(1)}
${dateStr}
`; contentEl.appendChild(row); } } async function getWordMap(wordIds: number[]): Promise> { const map = new Map(); if (wordIds.length === 0) return map; try { const placeholders = wordIds.map(() => '?').join(','); const rows: any[] = await execute( `SELECT id, key FROM words WHERE id IN (${placeholders})`, wordIds, ); for (const row of rows) { map.set(row[0], row[1]); } } catch { // ignore } return map; } function escapeHtml(text: string): string { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; }