diff --git a/src/pages/AdminPromocodes.tsx b/src/pages/AdminPromocodes.tsx index ab7122d..3d5255b 100644 --- a/src/pages/AdminPromocodes.tsx +++ b/src/pages/AdminPromocodes.tsx @@ -87,6 +87,7 @@ const getTypeLabel = (type: PromoCodeType): string => { subscription_days: 'Дни подписки', trial_subscription: 'Тестовая подписка', promo_group: 'Группа скидок', + discount: 'Скидка %', } return labels[type] || type } @@ -97,6 +98,7 @@ const getTypeColor = (type: PromoCodeType): string => { subscription_days: 'bg-blue-500/20 text-blue-400', trial_subscription: 'bg-purple-500/20 text-purple-400', promo_group: 'bg-amber-500/20 text-amber-400', + discount: 'bg-pink-500/20 text-pink-400', } return colors[type] || 'bg-dark-600 text-dark-300' } @@ -146,10 +148,14 @@ function PromocodeModal({ promocode, promoGroups, onSave, onClose, isLoading }: const [promoGroupId, setPromoGroupId] = useState(promocode?.promo_group_id || null) const handleSubmit = () => { + // Для discount: balance_bonus_kopeks = процент (целое число), subscription_days = часы + // Для balance: balance_bonus_kopeks = рубли * 100 const data: PromoCodeCreateRequest | PromoCodeUpdateRequest = { code: code.trim().toUpperCase(), type, - balance_bonus_kopeks: Math.round(balanceBonusRubles * 100), + balance_bonus_kopeks: type === 'discount' + ? Math.round(balanceBonusRubles) // процент как целое число + : Math.round(balanceBonusRubles * 100), // рубли в копейки subscription_days: subscriptionDays, max_uses: maxUses, is_active: isActive, @@ -165,6 +171,7 @@ function PromocodeModal({ promocode, promoGroups, onSave, onClose, isLoading }: if (type === 'balance' && balanceBonusRubles <= 0) return false if ((type === 'subscription_days' || type === 'trial_subscription') && subscriptionDays <= 0) return false if (type === 'promo_group' && !promoGroupId) return false + if (type === 'discount' && (balanceBonusRubles <= 0 || balanceBonusRubles > 100 || subscriptionDays <= 0)) return false return true } @@ -207,6 +214,7 @@ function PromocodeModal({ promocode, promoGroups, onSave, onClose, isLoading }: + @@ -262,6 +270,40 @@ function PromocodeModal({ promocode, promoGroups, onSave, onClose, isLoading }: )} + {type === 'discount' && ( + <> +
+ +
+ setBalanceBonusRubles(Math.min(100, Math.max(0, parseFloat(e.target.value) || 0)))} + className="w-32 px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-dark-100 focus:outline-none focus:border-accent-500" + min={1} + max={100} + /> + % +
+

Скидка применяется один раз при оплате

+
+
+ +
+ setSubscriptionDays(Math.max(0, parseInt(e.target.value) || 0))} + className="w-32 px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-dark-100 focus:outline-none focus:border-accent-500" + min={1} + /> + часов +
+

Сколько часов после активации скидка действует

+
+ + )} + {/* Max Uses */}
@@ -578,6 +620,18 @@ function PromocodeStatsModal({ promocode, onClose, onEdit }: PromocodeStatsModal +{promocode.subscription_days}
)} + {promocode.type === 'discount' && ( + <> +
+ Скидка: + -{promocode.balance_bonus_kopeks}% +
+
+ Действует: + {promocode.subscription_days} часов +
+ + )}
Лимит: @@ -936,6 +990,9 @@ export default function AdminPromocodes() { {(promo.type === 'subscription_days' || promo.type === 'trial_subscription') && ( +{promo.subscription_days} дней )} + {promo.type === 'discount' && ( + -{promo.balance_bonus_kopeks}% на {promo.subscription_days}ч + )} Использовано: {promo.current_uses}/{promo.max_uses === 0 ? '∞' : promo.max_uses}