feat: prevent duplicate cards, merge contexts, and display star badge when word is in library

This commit is contained in:
2026-10-05 15:15:06 +03:00
parent f52820fff6
commit a73bdc29fd
7 changed files with 355 additions and 24 deletions
+11 -11
View File
@@ -48,17 +48,17 @@
---
### 3. 🛡️ Дедупликация слов и защита от повторного добавления (Reader + API)
- [ ] **Проверка дубликатов на бэкенде (`POST /api/cards`)**:
- Проверять наличие слова для пользователя без учёта регистра: `lower(trim(term))`.
- При попытке повторного добавления: не создавать дубликат-клон, а дополнять контекстное предложение (если в новой цитате другой контекст) и объединять теги книги (`tags`), возвращая существующую карточку со статусом `already_exists`.
- [ ] **Индикация в читалке (Reader Popup)**:
- При клике на слово проверять, есть ли уже `cleanTerm` в словаре пользователя.
- Если слово уже сохранено: показывать зелёный бейдж `✓ В словаре` вместо активной кнопки `+ В словарь` (предотвращая случайные повторные клики).
- Предоставить кнопку «Добавить контекст» для привязки новой цитаты к существующей карточке.
- [ ] **Индекс целостности в SQLite**:
- Добавить `CREATE INDEX IF NOT EXISTS idx_vocab_user_term_nocase ON vocabulary_cards(user_id, term COLLATE NOCASE);` для мгновенного поиска за $O(\log N)$.
- [ ] **Слияние существующих дубликатов в базе**:
- Написать безопасную миграцию/скрипт, объединяющий накопившиеся дубликаты (например, `admired`, `suddenly`/`Suddenly` у пользователя `kopri`), объединяя контексты предложений и сохраняя историю повторений SRS.
- [x] **Проверка дубликатов на бэкенде (`POST /api/cards`)**:
- Проверка слова без учёта регистра `lower(trim(term))`.
- При повторном добавлении не создаётся дубликат, а дополняется контекстное предложение и объединяются теги, возвращается `already_exists: True`.
- [x] **Индикация в читалке и карточке поиска**:
- В читалке при клике на слово и в карточке поиска выводится бейдж `⭐ В библиотеке`.
- Кнопка «+ В словарь» заменяется на бейдж `⭐ Слово уже в библиотеке` с опциональной кнопкой `+ Добавить эту цитату к карточке`.
- [x] **Индекс целостности в SQLite**:
- Создан `UNIQUE INDEX idx_vocab_user_term_nocase ON vocabulary_cards(user_id, term COLLATE NOCASE);` гарантирующий отсутствие дубликатов на уровне движка БД за $O(\log N)$.
- [x] **Слияние существующих дубликатов в базе**:
- Объединены дубликаты `admired` (ID 5 и ID 7) и `suddenly`/`Suddenly` (ID 2 и ID 9) с объединением контекстных предложений, слиянием тегов и сохранением прогресса SRS.
---