Многие тосты повторяли то, что пользователь и так видит сразу после действия:
новую фракцию или аватар в профиле, переход на страницу партии, исчезнувшую
карточку приглашения, закрывшийся редактор. Такой шум приучает не читать
всплывашки, в том числе ошибки. Убраны 19 таких тостов в профиле, группах,
партиях и админке.
Остались ошибки, предупреждения (лимит фото, повторы фракций, конфликт правок,
«вы не в группе») и сообщения о действиях без видимого следа: приглашение
отправлено, дополнения сохранены, вступление в группу, пароль задан. Сохранение
текстового поля, где заметна только погасшая кнопка, тоже осталось.
По просьбе владельца оставшиеся тосты показываются не нижней «таблеткой», а
всплывашкой сверху, как входящие уведомления. ToastProvider держит одну стопку
на всё приложение: show — обычное сообщение, error — ошибка с красной полосой
(держится 5 с), notify — уведомление с переходом по клику. Одинаковое сообщение
не копится, а заменяет прежнее; клик по карточке закрывает её.
NotificationToaster больше не рисует свою стопку, а отдаёт новые уведомления в
общую, поэтому они не наезжают на сообщения. Все вызовы с ApiError и отказы
(лимит фото, партия изменилась на другом устройстве) переведены на toast.error.
Нижний класс .toast удалён.
#41
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
Страница входа начинается с карточки «Вход» (ник и пароль), в ней же
переключатель на регистрацию с повтором пароля. Telegram стоит ниже вторым
способом. Под ним подсказка: аккаунт, созданный по паролю, сначала привязывают к
Telegram в профиле, иначе вход через Telegram заведёт новый аккаунт. Поле логина
без автозаглавной буквы и автоисправления, у полей правильный autocomplete для
менеджеров паролей.
SetPasswordDialog показывается в AppShell всем, у кого has_password=false:
аккаунтам из Telegram и созданным до паролей. Закрыть окно нельзя, только задать
пароль или выйти. Успешный ответ кладёт в кэш профиль с has_password=true, и окно
исчезает само. Кнопка «Позже (dev)» есть лишь под import.meta.env.DEV: в
прод-бандле её строки нет, это проверено по dist.
В профиле появилась карточка «Вход в аккаунт»: смена пароля (текущий, если он
задан, новый и повтор) и привязка Telegram тем же виджетом, что при входе. У
смены ника подсказка, что ник — это и логин. В админке у игрока появилась кнопка
«Задать пароль» с вводом в той же строке, как у переименования, а в строке
игрока — пометка «без пароля».
schema.d.ts перегенерирован с живого бэкенда.
#24
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
Находки прохода /code-review high по frontend/src:
- CreateMatchPage: барабан рандома, таймеры и строки адресовались по индексу,
а удаление строки индексы сдвигает — фракция могла записаться соседу или
потеряться. Строки получили стабильный id.
- AdminAccountsPage: переключение «активен» глотало ошибку и всё равно
показывало «Сохранено».
- useServerEvents/useFinishMatch: завершение чужой партии не инвалидировало
историю игр и публичные профили — открытый профиль показывал состав до
завершения.
- guards/useMe: обрыв связи не отличался от «нет сессии», и мигание сети
выкидывало авторизованного пользователя на /login. Транспортные ошибки
повторяем, гварды показывают сообщение вместо редиректа.
- format: fallback на нераспознанную дату не работал (new Date не бросает
исключение), и в интерфейс попадало «NaN.NaN NaN:NaN».
- PlaceEditor: без onPointerCancel прерванный перенос оставлял блок с классом
dragging и сдвигом, которые React не снимает — они выставлены в обход него.
- AdminFactionsPage: refetch после сохранения одной фракции затирал
несохранённый ввод в остальных.
- MatchDetailPage: nav(-1) после удаления уводил из приложения при открытии
партии по прямой ссылке; id из URL мог быть NaN и уходил в запрос.
#8
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186Fk74jkkszahEHSjBzTjD
Единое правило: название страницы показывает верхняя панель (или активная
вкладка админки), тело страницы его не повторяет. Убраны дубли на общей
статистике, в справке и в админ-разделах (аккаунты, фракции, журнал);
пояснительные абзацы сохранены. Заголовки-сущности (имя группы, дата
партии) остаются h2 в теле.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- «Winrate» -> «Винрейт» в карточке статистики; в справке добавлена
расшифровка «Винрейт (WR)» — WR остаётся в компактных таблицах;
- кнопки сохранения: «ОК» -> «Сохранить» (аккаунт, фракции, аккаунты
в админке); отмена в модалках/формах — везде «Отмена», не «Назад»;
- пустые состояния приведены к шаблону «X пока нет.»;
- роли участников группы переведены: owner/member -> владелец/участник,
бейдж admin -> «админ»; «Имя обновлено» -> «Ник обновлён»;
- «N игр.» в значении числа игроков -> «N игроков» со склонением
(новый хелпер plural в domain/format.ts);
- «минимум 2 участника» -> «минимум 2 игрока» (в партии — игроки,
в группе — участники).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>