Commit Graph

908 Commits

Author SHA1 Message Date
Maxim Dolgolyov ac618b3fb1 feat(pet): кастомизация вынесена в модалку-«гардеробную» с живым превью
Кнопка «Нарядить» на сцене открывает модалку: слева крупное живое превью
питомца (обновляется мгновенно при любой смене — аксессуар/цвет/узор/фон),
справа вкладки Аксессуары/Цвет/Узор/Фон. Превью-сцена отражает выбранный
фон. Закрытие крестиком, кликом по фону, Esc. Инлайн-карточка убрана со
страницы; все рендереры идут через общий paintPet (сцена + превью).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 14:15:59 +03:00
Maxim Dolgolyov cac352b355 fix(pet): аккуратная раскладка гардероба (зоны — строки, не слипаются)
Контейнер #pet-accessories наследовал старый .pet-accessories
(display:flex center) → панель действий и зоны сваливались в один поток.
Снял класс + #pet-accessories{display:block}: тулбар с разделителем сверху,
каждая зона — отдельная строка (подпись справа фикс-ширины + плитки),
тонкие разделители, иконки на кнопках «Случайный образ»/«Снять всё».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 14:08:19 +03:00
Maxim Dolgolyov 7db337eccd style(pet): полностью переработан вид блока «Кастомизация»
Премиальная карточка с градиентом и заголовком-иконкой; сегментные вкладки
с иконками и подсветкой активной; аксессуары — тайлы по зонам с галочкой
вместо текстовых чипов; узор — крупные превью-плитки с подписью; фон —
увеличенные карточки; плавное появление панелей.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 14:05:23 +03:00
Maxim Dolgolyov 6880e1a55a feat(pet): прокачанный блок кастомизации + много контента
Контент:
- Узор тела (новая ось): пятнышки, полоски, градиент, галактика (клип по
  силуэту, рендер в обоих рендерерах) + миграция pet_pattern + /api/pet/pattern.
- +4 аксессуара: колпак, тёмные очки, шарф, цветок (все бесплатные).
- +3 фона: Сияние, Леденец, Сакура (CSS-градиенты + частицы: звёзды/пузыри/лепестки).

UI кастомизации:
- Вкладка «Узор» со свотчами-превью.
- Гардероб по зонам (Голова/Лицо/Шея/Уши/Акцент) + счётчик надетого,
  кнопки «Случайный образ» и «Снять всё».
- Фон — инлайн-сетка с превью/ценой/балансом (как раньше).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:58:12 +03:00
Maxim Dolgolyov 152291aec8 feat(pet): единый UI кастомизации (аксессуары/цвет/фон) + пояснение эволюции
Вынес кастомизацию из тесного блока сцены в отдельную карточку с вкладками
«Аксессуары · Цвет · Фон». Фон теперь выбирается инлайн (сетка превью с
ценой/статусом, покупка/выбор за монеты) вместо незаметной кнопки-модалки.
Добавил легенду эволюции: облик (уши/антенны/крылья/аура…) растёт с XP по
уровням — объясняет «откуда крылья». Рендереры цвета/гардероба не тронуты
(те же id), бэкенд без изменений.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:44:09 +03:00
Maxim Dolgolyov 7bf1da94e4 feat(pet): гардероб — выбор аксессуаров + новые украшения
Аксессуары больше не навешиваются авто по уровню — теперь разблокируются
и НАДЕВАЮТСЯ по выбору (один на слот). Новые: шапочка выпускника, наушники,
бабочка (бесплатные — доступны даже при 0 XP). Сохранены цилиндр/корона/очки/
звезда с прежними порогами; дефолт повторяет старый вид (без сюрпризов).

Бэкенд: миграция pet_equipped, каталог ACCESSORY_CATALOG + /api/pet/equip
(валидация разблокировки и слотов). Рендер аксессуаров строго по equipped —
в обеих копиях (pet.html и pet-sprite.js для дашборда). UI гардероба на /pet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:37:45 +03:00
Maxim Dolgolyov 8c961cd082 docs: SETUP.md — перенос проекта на другую машину
Чеклист: предустановки, npm install, .env, что переносить вне git
(БД/uploads/.env), миграции/seed, запуск, восстановление памяти,
ast-index/vex. Данные (с ключами) переносятся отдельным пакетом, не в git.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 08:41:07 +03:00
Maxim Dolgolyov 8a7091ddec chore(memory): снимок файлов памяти Claude в репозиторий для переноса
Копия пользовательской автопамяти (29 фактов + индекс MEMORY.md) в
.claude/memory/, чтобы переносить между машинами через git.
README.md — как восстановить в пользовательскую папку на другой машине.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 08:32:16 +03:00
Maxim Dolgolyov 13d91714d4 docs(teacher-guide): актуализация под текущее состояние системы
- Учебники (11.1): вместо 2 курсов — полный каталог (Матем 5-6, Алгебра/
  Геометрия 7-11, Физика 7-11, Химия 7-9).
- Новые главы: 18 Квантик-ассистент, 19 Флэшкарты, 20 Ещё модули
  (Карта знаний, Теория, Кроссворд, Виселица, Красная книга, Коллекция,
  Мои материалы, Магазин, Родители) + админ-глава A7 Провайдеры ИИ.
- Экзамен (12.3): хаб «Подготовка к экзамену 9» (Темы/Варианты/Практика/
  Пробник) + Квантик-подсказки; ссылка на /exam-prep/math9.
- Фикс сломанных ссылок навигации (s-14-4, s-16-3) + полные списки feature-flags.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 21:53:54 +03:00
Maxim Dolgolyov b9d63b0776 fix(assistant): не обрезать пошаговые решения посреди формулы
Лимит ответа был 420 токенов — длинное решение обрывалось внутри $$…$$,
незакрытый блок показывался сырым LaTeX. Теперь лимит по режиму
(ответ 1200, проверка 900, подсказка 320), а рендер отбрасывает
незакрытый хвост $$ (ставит «…») вместо сырого кода.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 21:33:07 +03:00
Maxim Dolgolyov 6e0a00fd8b feat(assistant): авто-получение лимитов моделей для любого провайдера
Новый GET /admin/assistant/models: тянет список моделей провайдера с лимитами
(OpenAI-совместимый /models: context_length+max_completion_tokens+pricing;
нативный Google generativelanguage: inputTokenLimit/outputTokenLimit) и кэширует
лимиты текущей модели на провайдере. Карточка показывает лимиты у ВСЕХ провайдеров
(не только Kilo), для отсутствующих — фоновая авто-подгрузка. В форме — кнопка
«Загрузить модели провайдера» с выбором модели и её лимитами. Так Gemini и любые
новые модели получают лимиты автоматически.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 21:28:34 +03:00
Maxim Dolgolyov f1f79335ec fix(assistant): длинные формулы не обрезаются + лимиты моделей в админке
Рендер ответа: display-формулы KaTeX прокручиваются по горизонтали
(overflow-x:auto), пузырь ассистента во всю ширину, панель шире (380px) —
длинные выражения больше не режутся по правому краю.

Админка: к моделям Kilo добавлены ctx/out (из /models); на карточке Kilo
показывается «контекст N · ответ до M токенов · бесплатно».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 21:18:50 +03:00
Maxim Dolgolyov 78a9eca9c0 fix(assistant): снятие устаревшего флага failover + чистый sample в тесте
Баннер «провайдеры недоступны» висел из старой записи assistant_failover.
Теперь успешный тест активного провайдера и смена активного снимают флаг,
плюс кнопка «Снять» на баннере (PUT /assistant {dismissFailover}).
Тест провайдера: system-инструкция + 64 токена + fallback на reasoning →
sample не показывает «мысли вслух» reasoning-моделей.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 21:06:31 +03:00
Maxim Dolgolyov f748e074fd feat(assistant): форма добавления провайдера свёрнута по умолчанию
Раскрывается кнопкой «+ Добавить провайдера» (и автоматически при «Изм.»),
сворачивается после сохранения/отмены. Окно компактнее в обычном режиме.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:58:14 +03:00
Maxim Dolgolyov 4172569ff7 feat(assistant): +4 бесплатные модели Kilo (8 всего, проверены на русском)
Опросил шлюз Kilo (342 модели, 13 free), протестировал текстовые на русском.
Добавил рабочие: Nemotron 120B, Qwen3.7 Plus, Laguna M.1, Free Router.
Исключил пустые (step-3.7-flash, kilo-auto/free) и нечатовые (content-safety, lyria).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:53:54 +03:00
Maxim Dolgolyov 0e08e5775d feat(assistant): красивый интерактивный модуль провайдеров + модели Kilo
Админ-раздел переделан: провайдеры — карточки (активный подсвечен, бейджи
ключ/активен, кнопки Сделать активным/Тест/Изменить/Удалить, hover-подъём).
Форма с лейблами и пресетами. Для Kilo — выпадающий список проверенных бесплатных
моделей (Nemotron 550B / Owl Alpha / Nemotron Nano 30B / Laguna XS) и инлайн-
переключатель модели прямо на карточке. Бэкенд: пресет Kilo + kiloModels в /admin/assistant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:47:28 +03:00
Maxim Dolgolyov d1be2c1a62 chore(assistant): не выводить рассуждения вслух (для reasoning-моделей)
Подключён Kilo Code (kilocode.ai/api/openrouter) как провайдер с бесплатной
моделью nvidia/nemotron-3-ultra-550b-a55b:free — активный; Gemini в failover.
Промпт дополнен запретом «думать вслух», т.к. nemotron — reasoning-модель.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:40:18 +03:00
Maxim Dolgolyov aac1240658 feat(assistant): уведомление о failover в админке
callLLMFailover пишет состояние в app_settings.assistant_failover: какой провайдер
исчерпан и каким подхвачено (или «все недоступны»); при успехе активного флаг
снимается. Админ-раздел показывает баннер «Провайдер X недоступен — работаю на Y».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:27:29 +03:00
Maxim Dolgolyov e2bff24b5b feat(assistant): несколько провайдеров ИИ + выбор активного + авто-перехват при лимите
Конфиг стал списком провайдеров (assistant_providers) + активный (assistant_active).
llmConfig берёт активного; providersOrdered — активный первым, затем остальные с
ключом; callLLMFailover перебирает их при 429/сетевой ошибке (второй ключ подхватывает
при исчерпании квоты). Legacy мигрируется в список. Админ-раздел: список провайдеров
(радио-активный, Тест/Изменить/Удалить) + форма с пресетами. Эндпоинты
POST/DELETE /admin/assistant/provider(/:id), POST /admin/assistant/active.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:21:06 +03:00
Maxim Dolgolyov 78300845ed feat(assistant): чёткий ответ при лимите ИИ (память не теряется), напоминание о памяти, отдельный раздел в админке
- Баг «не помнит»: на самом деле free-лимит Gemini (429). callLLM теперь
  возвращает ошибку; при 429 показываем «много запросов, подожди минутку —
  память не потеряется» и НЕ ломаем историю (убираем неудачный вопрос); при
  сбое — «не получилось, попробуй позже». Раньше показывалось «не нашёл ответ».
- В окне «Спроси» — пояснение, сколько помнит Квантик (≈6 реплик, рабочая память).
- Окна красивее: шире, аватар Квантика в шапке, мягкая анимация.
- Управление помощником вынесено в отдельный раздел админки «Помощник Квантик»
  (системный вкл/выкл + модель/ключ/тест/RAG/кнопки экзамена/статистика/качество);
  из раздела «Игры» конфиг убран.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:03:02 +03:00
Maxim Dolgolyov 961504b256 fix(assistant): мета-фильтр требует саморефренцию — не блокирует «модель атома/газа»
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 19:49:22 +03:00
Maxim Dolgolyov 3ecf488e83 feat(assistant): не отвечает «какая ты модель» + тумблер кнопок на экзамене
- Идентичность: вопросы про модель/нейросеть/провайдера/системный промпт
  отбиваются шаблонно (META_RE, без вызова LLM) + запрет в системном промпте.
- Кнопки «Подсказка»/«Спросить Квантика» на карточках экзамена скрыты по
  умолчанию; включаются тумблером в админке (assistant_exam_buttons →
  examButtons в /context → класс html.asst-exam-on открывает кнопки).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 19:46:38 +03:00
Maxim Dolgolyov 4224a22092 feat(assistant): источники в ответах, режим-наставник, оценки, утренний бриф
- Источники: RAG возвращает sources (slug/§/ref), под ответом ссылка «по учебнику
  X, §N» на параграф (миграция 064: section_ref в textbook_chunks; headless-индексатор
  его заполняет). Статический индексатор теперь не затирает headless-данные.
- Режим-наставник: переключатель Ответ/Подсказка/Проверить решение в «Спроси»
  (mode в ask + промпт); на карточке экзамена кнопка «Подсказка» (mode hint).
- Оценка ответов: лайк/дизлайк под ответом (assistant_feedback) + сводка в админке.
- Утренний бриф на дашборде: «занимался N из 5 дн + план на сегодня».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 19:38:47 +03:00
Maxim Dolgolyov 0119ea0f15 feat(assistant): headless-RAG — индексация JS-рендеримых учебников
scripts/index-textbooks-headless.js: puppeteer-core + системный Chrome/Edge
рендерит каждый учебник через локальный сервер (служебный JWT в localStorage,
т.к. /textbook требует логина), кликает по параграфам и забирает рендерный
текст движков (математика/физика и т.п.) в textbook_chunks. Дополняет
статический индексатор. npm: index:textbooks / index:textbooks:full (headless).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 18:27:52 +03:00
Maxim Dolgolyov 2252bbd666 feat(assistant): RAG по учебникам, кэш+счётчик, режим учителя
- RAG: индексатор scripts/index-textbooks.js → textbook_chunks (миграция 063);
  ask() подмешивает релевантные куски учебников (LIKE-скоринг). Покрывает
  учебники со статическим текстом; JS-рендеримые — через контекст страницы.
  Админка: тумблер RAG + кнопка «Переиндексировать» + число фрагментов.
- Кэш ответов (assistant_cache, 7 дней, только «чистые» вопросы без контекста/
  истории) + суточный счётчик (assistant_usage: ИИ/кэш/FAQ) в админке.
- Режим учителя: роль в /context, системный промпт для учителей (задания,
  план урока, учительские инструменты), подсказки-чипы для учителей.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 18:16:53 +03:00
Maxim Dolgolyov dc073e2114 feat(assistant): админ-панель LLM (ключ/URL/модель/тест) + многоходовой чат
Админка (Управление → игры/фичи): карточка «Помощник Квантик — модель» —
пресеты провайдеров, URL/модель, поле ключа, кнопки Сохранить/Проверить/
Очистить ключ, индикатор статуса. Конфиг в app_settings (без рестарта),
откат на ENV/дефолты; нет ключа → автоматически FAQ-режим. Эндпоинты
GET/PUT/POST /api/admin/assistant(/test), admin-only.

«Спроси Квантика» теперь многоходовой чат: история диалога (последние 6
реплик) уходит модели, ответы рендерятся как чат-лента, кнопка «Очистить».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 18:04:42 +03:00
Maxim Dolgolyov 479c621e2e feat(assistant): markdown+KaTeX, «Объясни это», репетитор на экзамене, флешкарты
- Ответы модели рендерятся как markdown + формулы KaTeX (ленивая загрузка),
  модель просим оформлять формулы в LaTeX $...$.
- «Объясни это»: ask принимает context; кнопки «Объяснить выделенное» (запоминаем
  выделение) и «Объяснить/Конспект параграфа» на учебнике.
- Репетитор на экзамене: кнопка «Спросить Квантика» на карточке задания →
  Assistant.ask с условием/ответом/решением как контекстом.
- Быстрые действия: «Флешкарты из параграфа» → POST /api/assistant/flashcards
  (модель → JSON, починка обрезанного) → колода через существующий API флешкарт.
- Экспорт Assistant.ask(q,context) / explainSelection().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:53:45 +03:00
Maxim Dolgolyov 638b684f77 fix(assistant): «Спроси» отвечает и на учебные вопросы, без эмодзи
Промпт был слишком узким (только навигация по справке) — на «1+1» и учебные
вопросы Квантик отказывался. Расширил: платформенные вопросы — по справке,
учебные/общие (математика, физика, объяснения) — по существу. Запрет эмодзи.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:34:55 +03:00
Maxim Dolgolyov 9dbc0443af feat(assistant): «Спроси» через бесплатную LLM (Groq по умолчанию), грунтовка по FAQ
ask() умеет вызывать OpenAI-совместимую модель: топ-FAQ как контекст, краткий
ответ на русском (source:'model'), таймаут 12с, при ошибке/без ключа — мягкий
откат на FAQ. Конфиг через ENV (ASSISTANT_LLM_URL/KEY/MODEL): дефолт — Groq
(бесплатный ключ), поддержан и локальный Ollama без ключа. Фронт показывает
ответ модели сверху, FAQ и поиск по платформе — ниже. .env.example дополнен.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:22:32 +03:00
Maxim Dolgolyov e1cde834d0 feat(assistant): админ-тумблер, расширенный FAQ, подсказки «что спросить»
- Отдельный фича-флаг 'assistant' (вместо reuse 'pet'): админ может включать/
  выключать помощника в Управление → фичи, независимо от питомца. Дефолт ON.
- FAQ расширен (~50 -> ~60): профиль/пароль, колоды/массовый импорт/SRS,
  прогресс по предмету, поиск, экзамен9, питомец, «без класса», «о чём спросить».
- В «Спроси Квантика» — чипы с примерами вопросов (что можно спросить).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:13:52 +03:00
Maxim Dolgolyov c33295e975 feat(assistant): контент по всем разделам, FAQ x5, поиск по платформе, умный проактив
Контент: контекстные подсказки на ВСЕ разделы (PAGE_HINTS), «Совет дня» (ротация),
FAQ расширен ~10 -> ~50 записей по всем фичам. «Спроси Квантика» теперь ищет и по
платформе (LS.globalSearch) рядом с FAQ. Умный проактив: weakSubject (слабый предмет
по тестам, /api/assistant/context) -> «потренируемся» и daily-plan (план на сегодня из
квестов и карточек к повторению).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 17:07:57 +03:00
Maxim Dolgolyov 2f3fd7475b fix(assistant): тур не залипает на нижних шагах
Подсказка тура уезжала за край на нижних пунктах сайдбара (Питомец), а оверлей
ловил клики → «ничего не сделать». Теперь: scrollIntoView ДО замера позиции,
подсказка жёстко клампится в пределах экрана (меряем реальный размер), и клик
по затемнённому фону закрывает тур (escape-hatch вдобавок к Esc).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 16:53:33 +03:00
Maxim Dolgolyov aff07647ec fix(assistant): помощник не перекрывает сайдбар — сдвиг в контентную область
Компаньон стоял на left:18px, поверх профиля внизу сайдбара (230/62px).
Теперь сдвигается правее сайдбара (.app-layout ~ .asst-root: 248px, collapsed
80px), на мобиле — к левому краю (шторка). Плавный transition при сворачивании.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 16:42:45 +03:00
Maxim Dolgolyov 9baaca7f68 feat(assistant): Ф2 онбординг-тур + проактив «продолжи урок»
Ф2: коачмарк-тур новичка по разделам (сайдбар + сам помощник), офер на
дашборде пока не пройден/не закрыт, повтор из приветствия и Assistant.tour().
activeLesson: контекст-эндпоинт отдаёт начатый незавершённый урок (как
«продолжить чтение»), добавлено проактивное правило «Продолжи …» → /course.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 16:30:34 +03:00
Maxim Dolgolyov 3f8009c59d feat(assistant): Квантик-ассистент — Ф0/Ф1 + «Спроси» (правиловый движок)
Плавающий помощник на всех страницах (через sidebar.js + inject в учебник):
контекстные подсказки по странице, проактивные напоминания из реальных данных
(домашка с дедлайном, карточки к повторению, серия под угрозой, квест дня),
поздравления (левелап/серия) и панель «Спроси Квантика» (поиск по FAQ + точка
расширения под локальную модель). Консервативно: дневной лимит, кулдауны,
«не показывать», выключатель в профиле. Лицо — pet-sprite, данные — /api/pet.

Бэкенд: миграция 062 (assistant_enabled + assistant_seen, cross-device «видел»),
GET /api/assistant/context, POST seen/dismiss/ask, PATCH settings — гейт фичи 'pet'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 16:17:37 +03:00
Maxim Dolgolyov 26c0ac0e58 docs(assistant): дизайн-документ «Квантик-ассистент» (правиловый, без кода)
План сквозного ассистента поверх существующего питомца: контекстные подсказки,
проактивные напоминания из реальных данных, поздравления, онбординг-тур.
Архитектура (assistant.js через sidebar.js, правиловый движок, анти-назойливость),
каталог правил, фазы Ф0–Ф4, открытые вопросы.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 15:59:56 +03:00
Maxim Dolgolyov 423c1001e4 fix(materials): аннотация фото перезаписывает материал, а не плодит копии
Рисование поверх существующего материала (annotate) теперь обновляет ту же
запись (LS.updateMaterial url), а не создаёт новую. На бэкенде PATCH
/api/materials/:id разрешает менять поле url. Кнопка «Рисунок» (новый с нуля)
по-прежнему создаёт новый материал.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 14:45:01 +03:00
Maxim Dolgolyov ed50cb49e5 style(materials): подтверждение удаления через LS.confirm вместо нативного confirm()
Удаление материала и папки теперь показывает стилизованную модалку
(LS.confirm, danger) вместо браузерного диалога «Сообщение с localhost».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 14:39:21 +03:00
Maxim Dolgolyov bdc8075c3d feat(materials): просмотр материала в модалке-лайтбоксе
Клик по картинке/доске больше не открывает новую вкладку, а показывает
материал в окне на странице (LS.modal size lg): изображение, кнопки
«Скачать» и «В новой вкладке». Кнопка действия «Открыть» заменена на
«Просмотр» (иконка eye). Ссылки по-прежнему открываются внешне.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 14:37:50 +03:00
Maxim Dolgolyov 53e996e2e0 fix(materials): картинки материалов отдаются публично (рендер/открытие/скачивание)
/api/files/:id/download требует Bearer-заголовок, поэтому <img>, переход по
ссылке и «Скачать» для сохранённых картинок ломались (битое изображение,
клик не открывал). Теперь личные картинки складываются в uploads/materials и
отдаются статикой (как flashcards): POST /api/files/personal возвращает
{ url:'/uploads/materials/<file>' }. board-clip, material-save, textbook-clip
и рисовалка в my-materials сохраняют этот публичный url.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 14:30:47 +03:00
Maxim Dolgolyov 55c8c5fa51 fix(materials): личная загрузка картинок без права library.upload
POST /api/files требует teacher/admin + library.upload — поэтому сохранение
картинок в «Мои материалы» (вырезка области учебника, обрезка доски,
рисунок, аннотация) падало с 403 у учеников и учителей без этого права.

Добавлен auth-only эндпоинт POST /api/files/personal (только картинки,
is_public=1) + LS.uploadMaterialFile. На него переключены board-clip,
material-save, textbook-clip (вырезка области) и рисовалка в my-materials.
Загрузка в учительскую библиотеку (library/lesson-editor) не тронута.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 14:21:18 +03:00
Maxim Dolgolyov ac1857c931 feat(textbook): вырезание области страницы в «Мои материалы»
Плавающая кнопка «Вырезать область» на странице учебника: выделяешь
прямоугольник прямо на живой странице → регион растеризуется в PNG
(html2canvas, грузится лениво только при первом использовании) →
превью с редактируемым названием → сохраняется как материал-картинка.
Рядом сохранена прежняя кнопка «В мои материалы» (ссылка).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 14:11:05 +03:00
Maxim Dolgolyov 0be62d5156 style(materials): переработана карточка материала
- карточка-ссылка: превью-баннер (иконка + человекочитаемая метка + url),
  заголовок снова главный, кнопка «Открыть» вместо сырого URL в теле
- бейдж типа теперь inline-чип в теле (с иконкой) — больше не наезжает на контент
- hover-подъём карточки
- fix: кнопка «В флешкарты» перенесена на карточку-заметку (раньше висела
  на ссылке и не отображалась), заметки теперь можно и раздавать

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:55:27 +03:00
Maxim Dolgolyov aee8597499 style(dashboard): визуальная полировка блока «Активность»
- hero-строка: крупное число занятий + тренд-пилюля со стрелкой
- сегментированный контрол масштаба (6н/12н/6м)
- ячейки тепловой карты: скруглённые квадраты, интенсивность через alpha, glow при наведении
- легенда типов — чипы-пилюли
- календарь «Месяц»: оттенок активных дней по нагрузке, пилюля стрика, мягкий ring сегодня
- паритет тёмной темы

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:22:01 +03:00
Maxim Dolgolyov 8e8f54b41b feat(dashboard): блок активности — все виды учёбы, тренд, разбивка по типам, empty-state
- Бэкенд /api/dashboard/activity: per-day агрегация активности по типам (тест/экзамен/карты/уроки/
  онлайн/домашка) из 6 таблиц за ~182 дня (раньше карта считала только тесты).
- Карта раскрашивается по доминирующему типу активности + легенда типов; интенсивность/размер по числу.
- Недельный тренд в футере («эта неделя N · +K к прошлой»).
- Тултип и попап по клику показывают разбивку дня по типам.
- Empty-state для новичков (вместо пустой сетки — призыв + CTA). Календарь «Месяц» тоже от всех активностей.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:06:46 +03:00
Maxim Dolgolyov 7a2a07c96e feat(nav): пункт «Домашние задания» в сайдбаре
Страница homework.html была доступна только через виджет дашборда. Добавил пункт
в группу «Учебный процесс» (видно всем — ученик выполняет, учитель задаёт).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:41:30 +03:00
Maxim Dolgolyov 7b653d92c2 fix(pet): человекочитаемые подписи в ленте XP питомца
Лента «последних начислений» печатала сырые коды причин из xp_log
(achievement:cr_5_lessons, tb:math-6-ch1-ach-start, lesson_complete).
Добавлен резолвер _xpReasonLabel: achievement:<slug> -> «Достижение
«<title>»» через ACHIEVEMENT_DEFS, tb:* -> «Учебник», недостающие
фиксированные причины (lesson_complete/daily_goal/daily_activity/
lab_experiment), сохранение уже-читаемых фраз, фолбэк «Награда».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:39:43 +03:00
Maxim Dolgolyov 785f85e1ef fix(materials): не падать из-за глобального esc (api.js) — обернул inline-скрипт в IIFE
js/api.js объявляет глобальный `const esc`, а инлайн-скрипт my-materials объявлял `function esc`
→ «Identifier esc has already been declared», из-за чего весь скрипт страницы не выполнялся.
Обернул инлайн-скрипт в IIFE (esc и прочее локальны; обработчики экспортируются через window.*).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:33:19 +03:00
Maxim Dolgolyov f7357adf1e feat(materials): Фаза 6b — раздатка материала ученикам/классу
- POST /api/materials/:id/share {classId|userId} (teacher/admin): создаёт независимую КОПИЮ
  материала каждому ученику класса (source_title «Раздатка: <учитель>») + уведомление через SSE.
- /my-materials: кнопка «Раздать» на карточках (видна учителю/админу) → выбор класса.
- Хелпер LS.shareMaterial. На этом план «Мои материалы» (6 фаз) завершён.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:26:46 +03:00
Maxim Dolgolyov e793b4ec09 feat(materials): Фаза 5 — заметка в флешкарты
Кнопка «В флешкарты» на карточке-заметке: выбор колоды (или новая «Из материалов») →
создание карточки (front=заголовок, back=текст) через существующий API флешкард.
Хелперы fcListDecks/fcCreateDeck/fcAddCard в js/api.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:23:19 +03:00