Commit Graph

1996 Commits

Author SHA1 Message Date
kewldan
ce13792f96 fix(referral): показывать секцию вывода средств всем реферерам 2026-07-23 03:36:30 +03:00
Fringg
f04675b249 fix(support): не склеивать t.me со ссылкой на внешний хелпдеск
SUPPORT_USERNAME на бэке принимает и @username, и произвольный URL. Кабинет
же во всех трёх ветках клеил `https://t.me/${support_username}`, из-за чего
внешний хелпдеск превращался в https://t.me/https://help.example.com и не
открывался. Бэк теперь отдаёт контакт разрезолвленным (support_url +
contact_is_telegram) — клеить на клиенте нечего.

Логика вынесена в resolveSupportContact: три копии склейки (profile, fallback
и карточка режима both) заменены одним вызовом. Старый бэк не шлёт support_url,
для него сохранено прежнее поведение — новый фронт не ломается на неподнятом
бэкенде.

Заодно ушли три non-null assertion на support_username.
2026-07-20 21:41:08 +03:00
Fringg
b97c3dc2f2 Merge branch 'fix/payment-methods-locale-duplicate' into dev: дубликат ключа admin.paymentMethods.description 2026-07-19 17:44:27 +03:00
Fringg
46c1bc79a4 fix(admin): дубликат ключа admin.paymentMethods.description
Ключ был объявлен дважды: как подзаголовок страницы списка методов
и как подпись поля формы. Побеждало последнее определение, поэтому
на странице «Платёжные методы» вместо «Настройка порядка и условий
отображения» показывалось «Описание».

Подзаголовок переименован в subtitle, пара description/descriptionHint
осталась за полем формы. В zh/fa подписи поля не было вовсе — там под
description лежал текст подзаголовка, поэтому форма показывала не то;
добавлены недостающие переводы вместо русского фолбэка.

Заодно форматирование AdminPaymentMethodEdit.tsx: шаг format:check
в CI не доходил до выполнения, пока падал lint.

Чинит красный lint в CI ветки dev.
2026-07-19 17:44:22 +03:00
Fringg
da74d03596 Merge branch 'feat/cispay-payment-method' into dev: способ оплаты cisPay 2026-07-19 17:38:36 +03:00
Fringg
4b982175d7 feat(payments): способ оплаты cisPay
Регистрация нового провайдера пополнения (api.cispay.app, карта и СБП)
во фронтенде: метка в METHOD_LABELS, иконка, узел настроек
payments_cispay и локали ru/en/zh/fa.

Бэкенд отдаёт метод динамически, поэтому страницы статистики и транзакций
подхватывают его автоматически через METHOD_LABELS и PaymentMethodIcon.
2026-07-19 17:38:32 +03:00
Egor
6d1513092b Merge PR #496: кнопка построения полной реферальной сети 2026-07-19 16:36:28 +03:00
Egor
0b53e0e35f Merge PR #495: приоритет админского display_name/description над локалью на балансе 2026-07-19 16:34:40 +03:00
Egor
424d77455e Merge PR #493: состав промокода чекбоксами — баланс / дни / промогруппа 2026-07-19 16:29:08 +03:00
Egor
10b58cdc1f Merge PR #492: кнопка «Отправить сообщение» в карточке пользователя 2026-07-19 16:26:15 +03:00
Egor
812f73dd07 Merge pull request #498 from BEDOLAGA-DEV/main
w
2026-07-19 16:24:28 +03:00
Fringg
61d3169e7d Merge PR #491: vitest-чек синхронности en/ru локалей + запуск тестов в CI 2026-07-19 16:23:26 +03:00
Fringg
1fddd9473c test(i18n): опустошить allowlist после мержа #489 + перевод realtimeTitle
Поверх #491: #489 уже в dev — записи resetPassword.*/expiredDate_trial и
placeholder-исключение serverAccess из allowlist удалены (по инструкции
самого теста); последняя дыра admin.remnawave.traffic.realtimeTitle закрыта
переводом — проверка синхронности теперь строгая, без известных исключений
2026-07-19 16:23:17 +03:00
Fringg
b771152bb2 Merge branch 'test/locale-sync' into test-merge-491 2026-07-19 16:22:02 +03:00
Egor
e84ef0553e Merge PR #490: форматирование дат и чисел локалью выбранного языка 2026-07-19 16:18:50 +03:00
Egor
80ff53a036 Merge PR #489: недостающие английские переводы resetPassword и expiredDate_trial 2026-07-19 16:16:36 +03:00
kewldan
19facf2ba9 feat(referral-network): кнопка построения полной реферальной сети
Со времён редизайна со скоуп-селектором граф строится только для
выбранных кампаний, партнёров или пользователей, и посмотреть сеть
целиком стало нечем. Бэкенд для этого уже есть — GET /cabinet/admin/
referral-network/ отдаёт полный граф и остался неиспользуемым после
того, как фронт перешёл на /scoped.

Возвращаем к нему доступ: в дропдауне селектора появляется закреплённый
пункт «Вся сеть», который грузит граф целиком. Режим взаимоисключающий
с выбором чипов — полный граф и так содержит все сущности.
2026-07-16 15:32:17 +03:00
smediainfo
112e09bc6d fix(payment-methods): admin display_name/description override locale on balance
White-label (per-method display_name + description in admin) was defeated on
balance/top-up pages: render used `translatedName || method.name` and
`translatedDesc || method.description`, so the bundled locale always won and
the admin override was ignored.

- Flip priority: admin-configured value first, locale as fallback
  (TopUpMethodSelect, Balance)
- Add missing Description field to payment-method edit page
  (mirrors Display name: description / reset_description)
- Add description to admin PaymentMethodConfig type
- Add description/descriptionHint i18n keys (ru, en)
2026-07-16 09:55:08 +03:00
Case211
9ce838bade feat(promocodes): состав промокода чекбоксами — баланс / дни / промогруппа
Форма создания промокода переведена с жёсткого выбора одного типа на режим
«Набор бонусов»: галочками выбирается, что входит в промокод — бонус на
баланс, дни подписки, промогруппа — в любой комбинации. Тип для бэкенда
выводится из выбора (balance / subscription_days / balance_and_days /
promo_group), промогруппа едет через promo_group_id при любом типе (бэкенд
назначает её при активации независимо от типа).

Триал и процентная скидка остаются отдельными режимами: скидка
переиспользует те же колонки с другой семантикой (процент/часы) и не
комбинируется без миграции.

- список и статистика: лейбл/цвет нового типа balance_and_days, у составных
  кодов видны оба значения (+руб и +дни)
- edit-режим восстанавливает чекбоксы из типа и promo_group_id
- унифицирована валидация формы (isValid = список ошибок пуст; для скидки
  0 часов = «до первой покупки» — разрешено, как и было в isValid)
- локали ru/en/fa/zh

Парный PR бэкенда: remnawave-bedolaga-telegram-bot (тип BALANCE_AND_DAYS,
порядок эффектов дни→баланс, валидации, бот-визард).
2026-07-14 08:52:06 +05:00
Case211
2f743d82db feat(users): кнопка «Отправить сообщение» в карточке пользователя
Паритет с бот-кнопкой «✉️ Отправить сообщение»: в блоке действий карточки
юзера появляется кнопка (RBAC users:send_message), открывающая модалку с
текстом (HTML, лимит 4096) — бот отправляет юзеру прямое сообщение через
POST /admin/users/{id}/send-message.

Для email-only юзеров без telegram_id кнопка задизейблена с подсказкой;
коды ошибок бэкенда (no_telegram_id / forbidden / bad_request) маппятся
в честные локализованные сообщения. Локали ru/en/fa/zh.
2026-07-14 07:28:33 +05:00
kewldan
2b5152608c test(i18n): vitest-чек синхронности en/ru локалей + запуск тестов в CI 2026-07-14 00:10:59 +03:00
kewldan
81fd96c2a7 fix(i18n): форматировать даты и числа локалью выбранного языка, а не браузера 2026-07-14 00:04:45 +03:00
kewldan
dd50d648d0 fix(i18n): добавить недостающие английские переводы resetPassword и expiredDate_trial 2026-07-13 23:37:07 +03:00
Egor
d7ea3c0635 Merge pull request #488 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.61.0
2026-07-13 21:55:21 +03:00
github-actions[bot]
c234100a4b chore(main): release 1.61.0 2026-07-13 18:54:59 +00:00
Egor
44369510bf Merge pull request #487 from BEDOLAGA-DEV/dev
Dev
2026-07-13 21:54:28 +03:00
Egor
9f909b0f2c Merge PR #486: fallback на покупку при переключении с бесплатного тарифа
fix(subscription): fall back to purchase flow for free-tariff switches
2026-07-13 15:36:37 +03:00
Egor
a47e9ab699 Merge PR #485: слушать IPv6 в nginx — фикс ложного unhealthy
fix(docker): слушать IPv6 в nginx — healthcheck на localhost уводил контейнер в unhealthy
2026-07-13 15:35:01 +03:00
Egor
eeb715c095 Merge PR #484: поле icon_custom_emoji_id у кастомных кнопок рассылки
feat(broadcasts): поле icon_custom_emoji_id у кастомных кнопок рассылки
2026-07-13 15:13:22 +03:00
Egor
478a693019 Merge PR #483: сдвиг страницы, мигание переключателя языка и перезапуск фона при SPA-навигации
fix(ui): сдвиг страницы, мигание переключателя языка и перезапуск фона при SPA-навигации
2026-07-13 15:01:12 +03:00
Egor
28ce17cd99 Merge PR #482: подключить vitest и покрыть утилиты юнит-тестами
test: подключить vitest и покрыть утилиты юнит-тестами
2026-07-13 14:45:40 +03:00
Chara-Freedom
255777e7d1 fix(subscription): fall back to purchase flow for free-tariff switches
The bot backend now rejects prorated tariff switches from a free (0RUB)
tariff with 400 free_tariff_cannot_switch + use_purchase_flow=true
(TARIFF_SWITCH_RESET_FREE_DAYS: the free remainder must reset, not be
prorated over hundreds of accumulated days and carried to a paid
tariff). Handle it like the existing trial_cannot_switch contract:

- SwitchTariffSheet: accept free_tariff_cannot_switch in
  shouldUsePurchaseFlow so the sheet hands off to the purchase form
- TariffPickerGrid: new subscription_on_free_tariff purchase-options
  flag disables the switch CTA up front and shows purchase instead

Companion to BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot#3056.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 05:36:12 +03:00
Fringg
f9ee16a2e6 feat(admin): бейдж «Команда» для команд бота в таймлайне активности
Команды (/start и др.) приходят типом button_click с подтипом command —
добавлен перевод бейджа во всех 4 локалях.
2026-07-13 04:19:32 +03:00
Fringg
5fc8e7f97a feat(admin): клики кнопок бота и действия в кабинете во вкладке «Активность»
Два новых типа записей таймлайна: button_click (нажатия кнопок в боте,
с текстом кнопки) и cabinet_action (мутационные действия юзера в
кабинете, метод + нормализованный путь). Чип-фильтр «Клики», иконки
BotIcon/BoltIcon, переводы во всех 4 локалях.

biome check, type-check и build проходят (pre-commit пропущен: biome
не установлен локально).
2026-07-13 03:46:53 +03:00
Fringg
7547b49d7a feat(admin): вкладка «Активность» в карточке пользователя
Единый таймлайн действий юзера в боте и кабинете
(GET /cabinet/admin/users/{id}/activity): вертикальная лента с
иконками-кружками по типу записи, бейджи подтипов, суммы со знаком
(+зелёный / −красный), относительное время (абсолютное — в title),
чипы-фильтры по категориям (платежи, события, промо, тикеты, подарки,
рефералы, входы), счётчик StatCard и постраничная догрузка по house
load-more паттерну. Компонент самодостаточный (ActivityTab), как
TicketsTab. Переводы во всех 4 локалях; время переиспользует
admin.auditLog.time.*.

biome check, type-check и build проходят (pre-commit пропущен: biome
не установлен локально — бинарь есть только в CI).
2026-07-13 03:34:07 +03:00
kewldan
ce4ce046ba fix(docker): слушать IPv6 в nginx — healthcheck на localhost уводил контейнер в unhealthy 2026-07-13 03:01:55 +03:00
Fringg
c920330fa6 feat(navigation): startapp=trial → дашборд (оплата платного триала из rich-меню)
Кнопка «Активировать триал» в rich-меню бота при платном триале ведёт в
миниапп: startapp=trial открывает дашборд, где TrialOfferCard показывает
цену и flow оплаты с баланса.

biome check, type-check и build проходят (pre-commit пропущен: biome не
установлен локально — бинарь есть только в CI).
2026-07-13 02:40:12 +03:00
kewldan
b4b4bca2cb feat(broadcasts): поле icon_custom_emoji_id для кастомных кнопок рассылки 2026-07-13 02:34:46 +03:00
Fringg
2eaea75fd9 feat(navigation): роутинг startapp-диплинков rich-меню бота
StartParamNavigator обобщён до таблицы маршрутов: помимо admin_ticket_<id>
теперь разбираются renew_<id> → /subscriptions/<id>/renew и subscriptions →
/subscriptions — их шлют ссылки «Продлить» у истёкших подписок в rich-меню
бота (t.me/<bot>/<app>?startapp=…). Доступ по-прежнему ограничен гвардами
самих маршрутов.

biome check, type-check и build проходят (pre-commit пропущен: biome не
установлен локально как зависимость — бинарь есть только в CI).
2026-07-13 02:12:57 +03:00
kewldan
1ea9b99ab5 fix(ui): не перезапускать анимированный фон при смене страницы 2026-07-13 01:52:36 +03:00
kewldan
a7ff8a6b09 fix(header): кэшировать список языков — переключатель не мигает при смене страницы 2026-07-13 01:46:24 +03:00
kewldan
b40f939e91 fix(ui): фиксированная ширина 100vw — страницы не сдвигаются при появлении скроллбара 2026-07-13 01:46:22 +03:00
kewldan
42788e842d test: подключить vitest и покрыть утилиты юнит-тестами 2026-07-13 01:09:33 +03:00
Egor
b7b103e6e2 Merge pull request #481 from BEDOLAGA-DEV/release-please--branches--main--components--cabinet-frontend
chore(main): release 1.60.0
2026-07-13 00:06:07 +03:00
github-actions[bot]
5df992c587 chore(main): release 1.60.0 2026-07-12 21:05:10 +00:00
Egor
cad7214207 Merge pull request #480 from BEDOLAGA-DEV/dev
Dev
2026-07-13 00:04:41 +03:00
Fringg
758a645dff Merge PR #479: счётчик символов и предупреждение о разбивке длинных текстов
Парный к боту #3049. В /admin/legal-pages под полем политики/оферты/правил:
постоянный счётчик символов + предупреждение с оценкой числа сообщений бота
(estimateTelegramParts зеркалит split_telegram_text, порог 3500). Скрыто там,
где документ в боте не показывается (recurrent-payments, web-only); счётчик
остаётся. Переводы ru/en с плюральными формами, прочие локали — en fallback.

Валидация: JSON-ключи, tsc, biome lint/format, build — чисто.
2026-07-12 23:57:05 +03:00
Fringg
63b19645e6 Merge PR #478: stagger-анимация скрывала контент, пришедший из API после mount
framer-motion stagger раздаёт детям команду показаться один раз при монтировании
родителя; дети, смонтированные позже (когда resolve-ится react-query), оставались
в initial (opacity:0) — пустые страницы после F5/прямого захода.

- ConnectedAccounts, SavedCards: key={isLoading?...} перемонтирует контейнер
  после загрузки → stagger проигрывается со всеми детьми;
- Balance (2), Profile, Support: явные initial/animate на условных staggerItem —
  элемент самоанимируется при mount, вне оркестрации родителя;
- Wheel: исправлены несуществующие варианты hidden/show → initial/animate
  (stagger истории спинов молча не работал).

Валидация на смердженном дереве: tsc, biome lint/format, build — чисто.
Правки #477 и #478 в общих файлах (ConnectedAccounts/Profile) сосуществуют.
2026-07-12 23:45:08 +03:00
Fringg
0e6f80c090 Merge PR #477: нормализовать detail из ответов API перед рендером (краш на 422)
FastAPI/Pydantic на 422 кладёт в detail массив объектов {type,loc,msg,...};
компоненты рендерили его в JSX как есть → React падал в ErrorBoundary
(Objects are not valid as a React child), пользователь не видел причину.

Все такие обработчики (Login, Profile, ConnectedAccounts, admin AnalyticsTab
и MenuEditorTab) переведены на существующий getApiErrorMessage — строковый
detail возвращается как есть (ветки .includes работают), Pydantic-массив
разворачивается в строку field: msg; ..., любой формат безопасен для рендера.

Валидация на смердженном дереве: tsc, biome lint/format, build — чисто.
2026-07-12 23:22:26 +03:00
kewldan
93cfca46dc feat(admin): предупреждение о разбивке длинных текстов системных страниц в боте
Кабинет, в отличие от админки бота (лимит 4000 символов), позволяет
сохранять юридические тексты любой длины — и до парного фикса в боте
(BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot#3049) текст длиннее
~4096 символов ронял показ правил и политики при /start
(MESSAGE_TOO_LONG).

Теперь под текстовым полем политики, оферты и правил постоянно
показывается счётчик символов, а для текстов длиннее одного сообщения —
предупреждение с оценкой, на сколько сообщений бот разобьёт текст.
Оценка зеркалит жадную упаковку абзацев из split_telegram_text бота
(порог 3500 символов на кусок).

Предупреждение не показывается там, где оно неуместно:
- «Рекуррентные платежи» — документ не отображается в боте вовсе;
- режим отображения «Только веб» — бот документ не показывает.

Переводы добавлены в ru/en (с плюральными формами); остальные локали
используют английский fallback через defaultValue.
2026-07-12 19:41:03 +03:00