mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
fix: block wheel spin without active subscription
- Add has_subscription to WheelConfig type - Disable spin button when user has no subscription - Add noSubscription guard in handleUnifiedSpin handler - Show warning banner directing user to activate subscription - Prevent banner stacking (noSubscription takes priority over daily limit) - Add noSubscription i18n keys for ru, en, zh, fa
This commit is contained in:
@@ -26,6 +26,7 @@ export interface WheelConfig {
|
|||||||
can_pay_days: boolean;
|
can_pay_days: boolean;
|
||||||
user_balance_kopeks: number;
|
user_balance_kopeks: number;
|
||||||
required_balance_kopeks: number;
|
required_balance_kopeks: number;
|
||||||
|
has_subscription: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SpinAvailability {
|
export interface SpinAvailability {
|
||||||
|
|||||||
@@ -858,7 +858,8 @@
|
|||||||
"cannotSpin": "Cannot spin right now",
|
"cannotSpin": "Cannot spin right now",
|
||||||
"insufficientBalance": "Insufficient balance",
|
"insufficientBalance": "Insufficient balance",
|
||||||
"topUpRequired": "Top up your balance to pay for spin",
|
"topUpRequired": "Top up your balance to pay for spin",
|
||||||
"starsNotAvailable": "Stars payment not available. Open the app via Telegram."
|
"starsNotAvailable": "Stars payment not available. Open the app via Telegram.",
|
||||||
|
"noSubscription": "An active subscription is required to spin the wheel. Activate your subscription first."
|
||||||
},
|
},
|
||||||
"payWithStars": "Pay with Stars",
|
"payWithStars": "Pay with Stars",
|
||||||
"payWithDays": "Pay with days",
|
"payWithDays": "Pay with days",
|
||||||
|
|||||||
@@ -694,7 +694,8 @@
|
|||||||
"cannotSpin": "فعلاً امکان چرخش نیست",
|
"cannotSpin": "فعلاً امکان چرخش نیست",
|
||||||
"insufficientBalance": "موجودی کافی نیست",
|
"insufficientBalance": "موجودی کافی نیست",
|
||||||
"topUpRequired": "برای پرداخت شارژ کنید",
|
"topUpRequired": "برای پرداخت شارژ کنید",
|
||||||
"starsNotAvailable": "پرداخت Stars در دسترس نیست. برنامه را از طریق تلگرام باز کنید."
|
"starsNotAvailable": "پرداخت Stars در دسترس نیست. برنامه را از طریق تلگرام باز کنید.",
|
||||||
|
"noSubscription": "برای چرخاندن گردونه نیاز به اشتراک فعال دارید. ابتدا اشتراک خود را فعال کنید."
|
||||||
},
|
},
|
||||||
"payWithStars": "پرداخت {stars} Stars",
|
"payWithStars": "پرداخت {stars} Stars",
|
||||||
"processingPayment": "در حال پردازش...",
|
"processingPayment": "در حال پردازش...",
|
||||||
|
|||||||
@@ -887,7 +887,8 @@
|
|||||||
"cannotSpin": "Сейчас нельзя крутить",
|
"cannotSpin": "Сейчас нельзя крутить",
|
||||||
"insufficientBalance": "Недостаточно средств на балансе",
|
"insufficientBalance": "Недостаточно средств на балансе",
|
||||||
"topUpRequired": "Пополните баланс для оплаты спина",
|
"topUpRequired": "Пополните баланс для оплаты спина",
|
||||||
"starsNotAvailable": "Оплата Stars недоступна. Откройте приложение через Telegram."
|
"starsNotAvailable": "Оплата Stars недоступна. Откройте приложение через Telegram.",
|
||||||
|
"noSubscription": "Для вращения колеса необходима активная подписка. Активируйте подписку в разделе «Подписка»."
|
||||||
},
|
},
|
||||||
"payWithStars": "Оплатить Stars",
|
"payWithStars": "Оплатить Stars",
|
||||||
"payWithDays": "Оплатить днями",
|
"payWithDays": "Оплатить днями",
|
||||||
|
|||||||
@@ -698,7 +698,8 @@
|
|||||||
"cannotSpin": "当前无法抽奖",
|
"cannotSpin": "当前无法抽奖",
|
||||||
"insufficientBalance": "余额不足",
|
"insufficientBalance": "余额不足",
|
||||||
"topUpRequired": "请充值以支付抽奖费用",
|
"topUpRequired": "请充值以支付抽奖费用",
|
||||||
"starsNotAvailable": "Stars支付不可用。请通过Telegram打开应用。"
|
"starsNotAvailable": "Stars支付不可用。请通过Telegram打开应用。",
|
||||||
|
"noSubscription": "需要有效订阅才能转动轮盘。请先激活订阅。"
|
||||||
},
|
},
|
||||||
"payWithStars": "支付 {stars} Stars",
|
"payWithStars": "支付 {stars} Stars",
|
||||||
"processingPayment": "处理中...",
|
"processingPayment": "处理中...",
|
||||||
|
|||||||
@@ -403,6 +403,7 @@ export default function Wheel() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleUnifiedSpin = () => {
|
const handleUnifiedSpin = () => {
|
||||||
|
if (noSubscription) return;
|
||||||
if (paymentType === 'telegram_stars') {
|
if (paymentType === 'telegram_stars') {
|
||||||
if (!config?.spin_cost_stars_enabled || !config?.spin_cost_stars) {
|
if (!config?.spin_cost_stars_enabled || !config?.spin_cost_stars) {
|
||||||
notify.warning(t('wheel.starsNotAvailable'));
|
notify.warning(t('wheel.starsNotAvailable'));
|
||||||
@@ -505,10 +506,12 @@ export default function Wheel() {
|
|||||||
|
|
||||||
// Stars via Telegram invoice don't require ruble balance, so only check daily limit
|
// Stars via Telegram invoice don't require ruble balance, so only check daily limit
|
||||||
const dailyLimitReached = config.daily_limit > 0 && config.user_spins_today >= config.daily_limit;
|
const dailyLimitReached = config.daily_limit > 0 && config.user_spins_today >= config.daily_limit;
|
||||||
|
const noSubscription = !config.has_subscription;
|
||||||
const spinDisabled =
|
const spinDisabled =
|
||||||
isSpinning ||
|
isSpinning ||
|
||||||
isPayingStars ||
|
isPayingStars ||
|
||||||
dailyLimitReached ||
|
dailyLimitReached ||
|
||||||
|
noSubscription ||
|
||||||
(paymentType === 'telegram_stars' ? !starsEnabled : !config.can_spin);
|
(paymentType === 'telegram_stars' ? !starsEnabled : !config.can_spin);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -614,22 +617,34 @@ export default function Wheel() {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* No subscription hint */}
|
||||||
|
{!isSpinning && noSubscription && (
|
||||||
|
<div className="rounded-linear border border-warning-500/30 bg-warning-500/5 p-4 text-center">
|
||||||
|
<p className="text-warning-400">{t('wheel.errors.noSubscription')}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{/* Cannot spin hint — only show for days payment (Stars via invoice always works) */}
|
{/* Cannot spin hint — only show for days payment (Stars via invoice always works) */}
|
||||||
{!isSpinning && paymentType !== 'telegram_stars' && !config.can_spin && (
|
{!isSpinning &&
|
||||||
<div className="rounded-linear border border-dark-700/30 bg-dark-800/30 p-4 text-center">
|
!noSubscription &&
|
||||||
<p className="text-dark-400">
|
paymentType !== 'telegram_stars' &&
|
||||||
{config.can_spin_reason === 'daily_limit_reached'
|
!config.can_spin && (
|
||||||
? t('wheel.errors.dailyLimitReached')
|
<div className="rounded-linear border border-dark-700/30 bg-dark-800/30 p-4 text-center">
|
||||||
: t('wheel.errors.cannotSpin')}
|
<p className="text-dark-400">
|
||||||
</p>
|
{config.can_spin_reason === 'daily_limit_reached'
|
||||||
</div>
|
? t('wheel.errors.dailyLimitReached')
|
||||||
)}
|
: t('wheel.errors.cannotSpin')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{/* Daily limit hint for Stars payment (not covered by can_spin check) */}
|
{/* Daily limit hint for Stars payment (not covered by can_spin check) */}
|
||||||
{!isSpinning && paymentType === 'telegram_stars' && dailyLimitReached && (
|
{!isSpinning &&
|
||||||
<div className="rounded-linear border border-dark-700/30 bg-dark-800/30 p-4 text-center">
|
!noSubscription &&
|
||||||
<p className="text-dark-400">{t('wheel.errors.dailyLimitReached')}</p>
|
paymentType === 'telegram_stars' &&
|
||||||
</div>
|
dailyLimitReached && (
|
||||||
)}
|
<div className="rounded-linear border border-dark-700/30 bg-dark-800/30 p-4 text-center">
|
||||||
|
<p className="text-dark-400">{t('wheel.errors.dailyLimitReached')}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Inline Result Card */}
|
{/* Inline Result Card */}
|
||||||
{spinResult && !isSpinning && (
|
{spinResult && !isSpinning && (
|
||||||
|
|||||||
Reference in New Issue
Block a user