From c184945e95111edefa42b76a7f24b556044ae851 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Fri, 3 Jul 2026 21:02:40 +0300 Subject: [PATCH] history page works --- lang.rs | 4 +-- src/algorithm.ts | 2 -- src/history-view.ts | 4 ++- src/main.ts | 27 +++++++++++++++ src/style.css | 80 +++++++++++++++++++++++++++++++++++++++++++++ src/training.ts | 9 +++-- 6 files changed, 117 insertions(+), 9 deletions(-) diff --git a/lang.rs b/lang.rs index e3eb572..621be80 100644 --- a/lang.rs +++ b/lang.rs @@ -79,9 +79,7 @@ impl CardStatistics { self.score = MAX_SCORE } self.last_open = Utc::now(); - updateCardStat(self.id, self.score, last_open).catch((err) => - console.error('[Training] Ошибка сохранения last_opened:', err), - ); } + } pub fn calculated_score(&self) -> f32 { let time = Utc::now() - self.last_open; diff --git a/src/algorithm.ts b/src/algorithm.ts index 7f45235..95b2055 100644 --- a/src/algorithm.ts +++ b/src/algorithm.ts @@ -55,9 +55,7 @@ export function calculatedScore(stat: CardStatistics): number { const now = Date.now(); const diffMs = now - stat.last_open; const days = diffMs / (1000 * 60 * 60 * 24); - console.log(`Days ${days}`) const multiplier = Math.pow(FADE_PER_DAY, Math.max(0, days)); - console.log(`multiplier ${multiplier}`) const v = stat.score * multiplier; return v; } diff --git a/src/history-view.ts b/src/history-view.ts index 4212cb6..bab98d8 100644 --- a/src/history-view.ts +++ b/src/history-view.ts @@ -1,5 +1,4 @@ import { getHistory } from './history.ts'; -import type { RepetitionRecord } from './history.ts'; import { execute } from './sqlite-manager.ts'; export interface HistoryViewCallbacks { @@ -24,12 +23,15 @@ export async function renderHistoryView( `; + 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); // Получаем слова для отображения const wordIds = [...new Set(records.map((r) => r.word_id))]; diff --git a/src/main.ts b/src/main.ts index d8201d9..2c588da 100644 --- a/src/main.ts +++ b/src/main.ts @@ -237,6 +237,8 @@ function showSetDetail(set: CardSetRecord, listItem: HTMLLIElement) { + + `; } @@ -258,6 +260,24 @@ function showWordView(word: Word) { ); } +// ----- История ----- + +async function showHistory(setId: number) { + hideNav(); + currentPage = 'history'; + + await renderHistoryView( + container, + setId, + { + onBack: () => { + showNav(); + switchPage('sets'); + }, + }, + ); +} + // ----- Тренировка ----- async function startTraining(setId: number) { @@ -453,6 +473,13 @@ async function main() { const setId = Number((trainingBtn as HTMLElement).dataset.setId); await startTraining(setId); } + + const historyBtn = target.closest('.btn-history'); + if (historyBtn) { + const setId = Number((historyBtn as HTMLElement).dataset.setId); + console.log('[App] История для set_id:', setId); + await showHistory(setId); + } }); } catch (err) { diff --git a/src/style.css b/src/style.css index d36bcbb..51cfe21 100644 --- a/src/style.css +++ b/src/style.css @@ -417,6 +417,86 @@ body { margin-bottom: 0; } +/* ──── История ──── */ + +.history-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 0; +} + +.history-card { + flex: 1; + background: var(--card-bg); + border: 1px solid var(--border); + border-radius: 16px; + padding: 0; + box-shadow: var(--shadow); + overflow-y: auto; +} + +#history-content { + padding: 0; +} + +.history-row { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 14px; + border-bottom: 1px solid var(--border); + font-size: 0.85rem; +} + +.history-row:last-child { + border-bottom: none; +} + +.history-row-word { + flex: 1; + font-weight: 600; + color: var(--text-h); + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.history-row-mode { + font-size: 0.8rem; + flex-shrink: 0; +} + +.history-row-scores { + display: flex; + align-items: center; + gap: 4px; + flex-shrink: 0; + font-size: 0.8rem; +} + +.history-score-before { + color: var(--text); +} + +.history-score-arrow { + color: var(--text); + opacity: 0.5; +} + +.history-score-after { + color: var(--accent); + font-weight: 600; +} + +.history-row-date { + font-size: 0.75rem; + color: var(--text); + opacity: 0.7; + flex-shrink: 0; +} + /* ──── Навигация ──── */ .app-nav { diff --git a/src/training.ts b/src/training.ts index d7386ec..d0fd190 100644 --- a/src/training.ts +++ b/src/training.ts @@ -244,15 +244,18 @@ export class TrainingPage { if (stat) { const scoreAfter = Math.round(calculatedScore(stat) * 10) / 10; const word = this.words[current]; + console.log('[Training] vote debug:', { stat, word, current, scoreBefore, scoreAfter }); if (word) { - addRepetition({ - set_id: stat.set_id, + const record = { + set_id: Number(stat.set_id), word_id: word.id, timestamp: Date.now(), mode, score_before: scoreBefore, score_after: scoreAfter, - }).catch((err) => console.error('[Training] Ошибка сохранения истории:', err)); + }; + console.log('[Training] Сохраняем историю:', record); + addRepetition(record).catch((err) => console.error('[Training] Ошибка сохранения истории:', err)); } }