Filtering bad

This commit is contained in:
2026-07-05 13:34:23 +03:00
parent c184945e95
commit 064c39924b
3 changed files with 119 additions and 52 deletions
+1 -1
View File
@@ -23,4 +23,4 @@ dist-ssr
*.sln
*.sw?
jwl.tar.gz
/.jwl
/jwl
+67 -19
View File
@@ -5,6 +5,11 @@ export interface HistoryViewCallbacks {
onBack: () => void;
}
let allRecords: any[] = [];
let showBadOnly = false;
const BAD_MODES = new Set(['hard', 'none']);
/**
* Показывает страницу истории повторений для указанной колоды.
*/
@@ -13,46 +18,97 @@ export async function renderHistoryView(
setId: number,
callbacks: HistoryViewCallbacks,
): Promise<void> {
showBadOnly = false;
container.innerHTML = `
<div class="history-header">
<button id="btnHistoryBack" class="btn" style="flex:none; padding:0.4rem 0.8rem;">← Назад</button>
<span style="font-size:0.85rem;color:var(--text);">Загрузка...</span>
</div>
<div class="history-filters">
<button id="btnFilterAll" class="btn btn-filter active">📊 Все записи</button>
<button id="btnFilterBad" class="btn btn-filter">🔴 Только плохие</button>
</div>
<div class="history-card">
<div id="history-content" style="text-align:center;padding:2rem;opacity:0.6;">Загрузка истории...</div>
</div>
`;
console.log('[History] Загрузка истории для set_id:', setId);
document.getElementById('btnHistoryBack')?.addEventListener('click', () => {
callbacks.onBack();
});
try {
const records = await getHistory(setId, 2000);
console.log('[History] Получено записей:', records.length, records);
document.getElementById('btnFilterAll')?.addEventListener('click', () => {
showBadOnly = false;
updateFilterButtons();
renderRows(container);
});
// Получаем слова для отображения
const wordIds = [...new Set(records.map((r) => r.word_id))];
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 = `записей: ${records.length}`;
headerSpan.textContent = `всего записей: ${allRecords.length}`;
}
renderRows(container);
} catch (err) {
console.error('[History] Ошибка загрузки:', err);
const contentEl = document.getElementById('history-content');
if (contentEl) {
contentEl.innerHTML = '<div style="text-align:center;padding:2rem;color:var(--error);">Ошибка загрузки истории</div>';
}
}
}
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;
if (records.length === 0) {
contentEl.innerHTML = '<div style="text-align:center;padding:2rem;opacity:0.6;">История пуста</div>';
const wordMap = (window as any).__wordMap as Map<number, string> || 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 = '<div style="text-align:center;padding:2rem;opacity:0.6;">Нет записей</div>';
return;
}
contentEl.innerHTML = '';
for (const record of records) {
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);
@@ -84,13 +140,6 @@ export async function renderHistoryView(
`;
contentEl.appendChild(row);
}
} catch (err) {
console.error('[History] Ошибка загрузки:', err);
const contentEl = document.getElementById('history-content');
if (contentEl) {
contentEl.innerHTML = '<div style="text-align:center;padding:2rem;color:var(--error);">Ошибка загрузки истории</div>';
}
}
}
async function getWordMap(wordIds: number[]): Promise<Map<number, string>> {
@@ -104,7 +153,6 @@ async function getWordMap(wordIds: number[]): Promise<Map<number, string>> {
wordIds,
);
for (const row of rows) {
// rows — массив массивов [id, key]
map.set(row[0], row[1]);
}
} catch {
+19
View File
@@ -426,6 +426,25 @@ body {
padding: 0.5rem 0;
}
.history-filters {
display: flex;
gap: 0.5rem;
padding: 0.25rem 0;
}
.btn-filter {
flex: 1;
font-size: 0.8rem;
padding: 0.5rem 0.75rem;
min-height: 40px;
}
.btn-filter.active {
background: var(--accent-light);
border-color: var(--accent);
color: var(--accent);
}
.history-card {
flex: 1;
background: var(--card-bg);