From 6de864ac434236425e9a3aa69d106794334b65c2 Mon Sep 17 00:00:00 2001 From: c0mrade Date: Thu, 26 Mar 2026 19:43:42 +0300 Subject: [PATCH] fix: promocode multi-tariff support in cabinet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Balance page: handle select_subscription response — show subscription picker when promo code adds days and user has multiple tariffs - API: activatePromocode now accepts optional subscriptionId - AdminPromocodeCreate: show trial tariff info when creating trial_subscription promo code, warn if no trial tariff configured --- src/api/balance.ts | 17 +++++--- src/pages/AdminPromocodeCreate.tsx | 35 +++++++++++++++++ src/pages/Balance.tsx | 62 +++++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 10 deletions(-) diff --git a/src/api/balance.ts b/src/api/balance.ts index 49f97f7..9e5ab91 100644 --- a/src/api/balance.ts +++ b/src/api/balance.ts @@ -68,14 +68,21 @@ export const balanceApi = { // Activate promo code activatePromocode: async ( code: string, + subscriptionId?: number, ): Promise<{ success: boolean; - message: string; - balance_before: number; - balance_after: number; - bonus_description: string | null; + message?: string; + balance_before?: number; + balance_after?: number; + bonus_description?: string | null; + error?: string; + eligible_subscriptions?: Array<{ id: number; tariff_name: string; days_left: number }>; + code?: string; }> => { - const response = await apiClient.post('/cabinet/promocode/activate', { code }); + const response = await apiClient.post('/cabinet/promocode/activate', { + code, + ...(subscriptionId ? { subscription_id: subscriptionId } : {}), + }); return response.data; }, diff --git a/src/pages/AdminPromocodeCreate.tsx b/src/pages/AdminPromocodeCreate.tsx index 280b67b..c83ee49 100644 --- a/src/pages/AdminPromocodeCreate.tsx +++ b/src/pages/AdminPromocodeCreate.tsx @@ -11,6 +11,7 @@ import { PromoCodeUpdateRequest, PromoGroup, } from '../api/promocodes'; +import { tariffsApi } from '../api/tariffs'; import { usePlatform } from '../platform/hooks/usePlatform'; // Icons @@ -69,6 +70,15 @@ export default function AdminPromocodeCreate() { const promoGroups: PromoGroup[] = promoGroupsData?.items || []; + // Fetch tariffs to show trial tariff info + const { data: tariffsData } = useQuery({ + queryKey: ['admin-tariffs-for-promo'], + queryFn: () => tariffsApi.getTariffs(true), + enabled: type === 'trial_subscription', + }); + + const trialTariff = tariffsData?.tariffs?.find((t) => t.is_trial_available) || null; + // Fetch promocode for editing const { isLoading: isLoadingPromocode } = useQuery({ queryKey: ['admin-promocode', id], @@ -301,6 +311,31 @@ export default function AdminPromocodeCreate() { )} + {type === 'trial_subscription' && ( +
+ {trialTariff ? ( +
+ + {t('admin.promocodes.form.trialTariffInfo', 'Будет выдан тариф:')} + {' '} + {trialTariff.name} + + {' '} + ({trialTariff.traffic_limit_gb} GB, {trialTariff.device_limit}{' '} + {t('admin.promocodes.form.devices', 'устр.')}) + +
+ ) : ( +
+ {t( + 'admin.promocodes.form.noTrialTariff', + '⚠️ Триальный тариф не настроен. Отметьте тариф как «доступен для триала» в настройках тарифов.', + )} +
+ )} +
+ )} + {type === 'promo_group' && (