// Страница «Колоды»: плоский список — только название + количество states. // Раскрытия по нажатию нет: тап переходит на страницу колоды, где все данные. import { getDecks, getDeckStateCounts } from './db-types.ts'; import type { Deck } from './db-types.ts'; import { hasDatabaseFile } from './opfs.ts'; export type DecksNav = { goDeck: (deckId: number) => void; goReview: (deckId: number) => void; }; function escapeHtml(s: string): string { return s .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function plural(n: number): string { const m10 = n % 10; const m100 = n % 100; if (m10 === 1 && m100 !== 11) return 'запись'; if (m10 >= 2 && m10 <= 4 && (m100 < 12 || m100 > 14)) return 'записи'; return 'записей'; } // Одна колода — плоская строка: имя + количество слева, «▶» справа. // Тап по имени — на страницу колоды, тап по «▶» — сразу в повторение. function deckRowHtml(d: Deck, count: number): string { const name = escapeHtml(d.name) || `Колода #${d.id}`; return `
` + `` + `` + `
`; } export function renderDecksPage(root: HTMLElement, nav: DecksNav): void { root.innerHTML = `

🗂️ Колоды

Проверка локальной базы…
`; const countEl = root.querySelector('#decks-count')!; const statusEl = root.querySelector('#decks-status')!; const listEl = root.querySelector('#decks-list')!; function setStatus(msg: string): void { statusEl.textContent = msg; statusEl.hidden = msg === ''; } listEl.addEventListener('click', (e) => { const btn = (e.target as HTMLElement).closest('[data-act]'); if (!btn) return; const id = Number(btn.dataset.deckId); if (!Number.isFinite(id)) return; if (btn.dataset.act === 'review') nav.goReview(id); else nav.goDeck(id); }); void (async () => { const has = await hasDatabaseFile(); if (!has) { setStatus('Нет локальной базы — скачай сохранение на странице «Синхронизация».'); countEl.textContent = ''; return; } setStatus('Загрузка колод…'); try { const [decks, counts] = await Promise.all([getDecks(), getDeckStateCounts()]); if (decks.length === 0) { countEl.textContent = 'Колоды пока отсутствуют.'; setStatus(''); listEl.innerHTML = ''; return; } countEl.textContent = `Всего: ${decks.length}`; setStatus(''); listEl.innerHTML = decks .map((d) => deckRowHtml(d, counts.get(d.id) ?? 0)) .join(''); } catch (err) { setStatus(`Не удалось загрузить колоды: ${err instanceof Error ? err.message : String(err)}`); } })(); }