feat(coupons): лимит на пользователя и удаление партии в кабинете

Парная фронтовая часть к бэкенду (бот: 82609441).

- Поле «Лимит на пользователя» в форме создания партии: 0 — без
  ограничения, для раздач и конкурсов ставится 1. Значение показывается в
  карточке партии, если задано.
- Кнопка «Удалить партию» с подтверждением: отдельно от отзыва, который
  лишь гасит ссылки. Если в партии есть погашенные купоны, подтверждение
  предупреждает о потере истории активаций (выданные подписки не
  отзываются). После удаления — возврат к списку.
- API: max_per_user в типах партии и запросе создания, deleteBatch.

Локали ru/en — раздел admin.coupons в zh/fa отсутствует целиком (купоны там
никогда не переводились), поэтому новые ключи добавлены в том же объёме.
This commit is contained in:
Fringg
2026-07-29 22:02:07 +03:00
parent c9afea7a50
commit 390da33914
5 changed files with 129 additions and 7 deletions

View File

@@ -10,6 +10,8 @@ export interface CouponBatch {
period_days: number;
coupons_total: number;
wholesale_price_kopeks: number;
/** Сколько купонов партии может активировать один пользователь; 0 — без ограничения */
max_per_user: number;
valid_until: string | null;
is_revoked: boolean;
created_at: string;
@@ -31,6 +33,7 @@ export interface CouponBatchCreateRequest {
period_days: number;
coupons_count: number;
wholesale_price_kopeks?: number;
max_per_user?: number;
valid_days?: number;
}
@@ -99,6 +102,12 @@ export const couponsApi = {
},
// User: redeem a coupon for the current cabinet user
/** Полное удаление партии (в отличие от revoke, который гасит ссылки) */
deleteBatch: async (id: number): Promise<{ batch_id: number; deleted_coupons: number }> => {
const response = await apiClient.delete(`/cabinet/admin/coupons/${id}`);
return response.data;
},
redeemCoupon: async (token: string): Promise<CouponRedeemResponse> => {
const response = await apiClient.post('/cabinet/coupon/redeem', { token });
return response.data;