fix(promocodes): чекбоксы набора по значениям, трафик в списке

Дополнения к PR #543 при мерже.

С появлением трафика тип balance_and_days перестал означать «есть и баланс, и
дни»: теперь он стоит у любого набора с трафиком, в том числе с нулевым
балансом и нулём дней. Две поверхности этого не учитывали.

Форма редактирования поднимала галочки «Баланс» и «Дни» по ТИПУ. Код с одним
трафиком открывался с двумя чужими галочками на нулях, валидация требовала
«больше 0», и Сохранить не работало — админ не мог поправить даже число
активаций, ничего не меняя по сути. Хуже того, подсказка прямо предлагает
вписать сумму: сделав это, админ молча превращал код на 50 ГБ в код на 50 ГБ
плюс 100 рублей. Галочки теперь выводятся по значениям — ровно так, как сам
автор уже сделал для трафика строкой ниже.

Список промокодов печатал составляющие тоже по типу, поэтому код с одним
трафиком показывался как «+0 ₽ +0 дн.» и ни слова про гигабайты: админ при
разборе списка видел код, который якобы не даёт ничего. Теперь каждая
составляющая показывается по своему значению, и добавлена строка трафика —
ключ form.gb автор уже завёл во всех четырёх локалях.

Дробный ввод не трогал: поведение общее с полями баланса и дней и от этого PR
не зависит.
This commit is contained in:
Fringg
2026-08-06 02:53:02 +03:00
parent 1883ec9340
commit 29c9ed1a40
2 changed files with 27 additions and 9 deletions

View File

@@ -87,8 +87,15 @@ export default function AdminPromocodeCreate() {
setMode(data.type); setMode(data.type);
} else { } else {
setMode('bonus_set'); setMode('bonus_set');
setIncludeBalance(data.type === 'balance' || data.type === 'balance_and_days'); // Галочки поднимаем по ЗНАЧЕНИЯМ, а не по типу. С появлением трафика
setIncludeDays(data.type === 'subscription_days' || data.type === 'balance_and_days'); // balance_and_days перестал означать «есть и баланс, и дни»: этот тип
// теперь у любого набора с трафиком, в том числе с нулевым балансом и
// нулём дней. По типу такой код открывался бы с двумя чужими галочками
// на нулях, валидация требовала бы «больше 0», и Сохранить не работало
// бы, пока админ их не снимет, — а подсказка толкает вместо этого
// вписать сумму и молча добавить коду бонус, которого в нём не было.
setIncludeBalance(data.type === 'balance' || (data.balance_bonus_rubles || 0) > 0);
setIncludeDays(data.type === 'subscription_days' || (data.subscription_days || 0) > 0);
// Промогруппа комбинируется с любым составом (bэкенд назначает её // Промогруппа комбинируется с любым составом (bэкенд назначает её
// независимо от типа), поэтому чекбокс — по факту наличия группы // независимо от типа), поэтому чекбокс — по факту наличия группы
setIncludeGroup(data.type === 'promo_group' || !!data.promo_group_id); setIncludeGroup(data.type === 'promo_group' || !!data.promo_group_id);

View File

@@ -196,18 +196,29 @@ export default function AdminPromocodes() {
</div> </div>
{/* Info line */} {/* Info line */}
<div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-dark-400"> <div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-dark-400">
{(promo.type === 'balance' || promo.type === 'balance_and_days') && ( {/* Составляющие показываем по значению, а не по типу:
balance_and_days теперь стоит и у набора, где баланса
или дней нет вовсе, — иначе в списке висело бы «+0 ₽
+0 дн.» у кода, который на самом деле раздаёт трафик. */}
{(promo.type === 'balance' || promo.type === 'balance_and_days') &&
promo.balance_bonus_rubles > 0 && (
<span className="text-success-400"> <span className="text-success-400">
+{promo.balance_bonus_rubles} {t('admin.promocodes.form.rub')} +{promo.balance_bonus_rubles} {t('admin.promocodes.form.rub')}
</span> </span>
)} )}
{(promo.type === 'subscription_days' || {(promo.type === 'subscription_days' ||
promo.type === 'trial_subscription' || promo.type === 'trial_subscription' ||
promo.type === 'balance_and_days') && ( promo.type === 'balance_and_days') &&
promo.subscription_days > 0 && (
<span className="text-accent-400"> <span className="text-accent-400">
+{promo.subscription_days} {t('admin.promocodes.form.days')} +{promo.subscription_days} {t('admin.promocodes.form.days')}
</span> </span>
)} )}
{promo.type === 'balance_and_days' && (promo.traffic_gb || 0) > 0 && (
<span className="text-accent-400">
+{promo.traffic_gb} {t('admin.promocodes.form.gb')}
</span>
)}
{promo.type === 'discount' && ( {promo.type === 'discount' && (
<span className="text-pink-400"> <span className="text-pink-400">
{t('admin.promocodes.discountForHours', { {t('admin.promocodes.discountForHours', {