fix: unify wheel Stars payment across desktop and mobile

- Use Telegram Stars invoice on all platforms instead of balance
  payment on desktop
- Show star cost in toggle and subtitle everywhere
- Show popup/toast when Stars are not enabled and user tries to spin
- Remove platform-specific payment type auto-select logic
- Add starsNotAvailable translation key (ru, en, zh, fa)
This commit is contained in:
c0mrade
2026-02-04 16:26:07 +03:00
parent 4499c9ad57
commit 02640d1c38
5 changed files with 20 additions and 36 deletions

View File

@@ -713,6 +713,7 @@
"starsPaymentSuccessCheckHistory": "Payment successful! Check history or Telegram for the result.",
"starsPaymentFailed": "Payment failed. Please try again.",
"starsPaymentRedirected": "Telegram will open for payment. Refresh the page after payment.",
"starsNotAvailable": "Star payments are currently unavailable. Contact support.",
"youWon": "You won",
"noPrize": "No luck this time...",
"noHistory": "No spin history yet",

View File

@@ -599,6 +599,7 @@
"starsPaymentSuccess": "پرداخت موفق! نتیجه به تلگرام ارسال شد.",
"starsPaymentFailed": "پرداخت ناموفق. دوباره تلاش کنید.",
"starsPaymentRedirected": "تلگرام برای پرداخت باز می‌شود. پس از پرداخت صفحه را بازخوانی کنید.",
"starsNotAvailable": "پرداخت با ستاره در حال حاضر در دسترس نیست. با پشتیبانی تماس بگیرید.",
"noHistory": "هنوز تاریخچه‌ای نیست",
"banner": {
"title": "شانس خود را امتحان کنید!",

View File

@@ -741,6 +741,7 @@
"starsPaymentSuccessCheckHistory": "Оплата прошла! Проверьте историю или Telegram для результата.",
"starsPaymentFailed": "Ошибка оплаты. Попробуйте еще раз.",
"starsPaymentRedirected": "Откроется Telegram для оплаты. После оплаты обновите страницу.",
"starsNotAvailable": "Оплата звёздами сейчас недоступна. Обратитесь в поддержку.",
"youWon": "Вы выиграли",
"noPrize": "В этот раз не повезло...",
"noHistory": "История вращений пуста",

View File

@@ -603,6 +603,7 @@
"starsPaymentSuccess": "支付成功抽奖结果已发送到Telegram。",
"starsPaymentFailed": "支付失败。请重试。",
"starsPaymentRedirected": "将打开Telegram进行支付。支付后请刷新页面。",
"starsNotAvailable": "星星支付暂不可用。请联系客服。",
"noHistory": "暂无抽奖记录",
"banner": {
"title": "试试运气!",

View File

@@ -5,8 +5,8 @@ import { wheelApi, type SpinResult, type SpinHistoryItem } from '../api/wheel';
import FortuneWheel from '../components/wheel/FortuneWheel';
import WheelLegend from '../components/wheel/WheelLegend';
import InsufficientBalancePrompt from '../components/InsufficientBalancePrompt';
import { useCurrency } from '../hooks/useCurrency';
import { usePlatform, useHaptic } from '@/platform';
import { useNotify } from '@/platform/hooks/useNotify';
import { Card } from '@/components/data-display/Card/Card';
import { Button } from '@/components/primitives/Button/Button';
import { motion, AnimatePresence } from 'framer-motion';
@@ -60,9 +60,9 @@ const ChevronIcon = ({ expanded }: { expanded: boolean }) => (
export default function Wheel() {
const { t } = useTranslation();
const queryClient = useQueryClient();
const { formatAmount, currencySymbol } = useCurrency();
const { platform, openInvoice, capabilities } = usePlatform();
const { openInvoice, capabilities } = usePlatform();
const haptic = useHaptic();
const notify = useNotify();
const [isSpinning, setIsSpinning] = useState(false);
const [targetRotation, setTargetRotation] = useState<number | null>(null);
@@ -74,9 +74,6 @@ export default function Wheel() {
const [historyExpanded, setHistoryExpanded] = useState(false);
const paymentTypeInitialized = useRef(false);
// Check if we're in Telegram Mini App environment
const isTelegramMiniApp = platform === 'telegram';
const {
data: config,
isLoading,
@@ -98,25 +95,13 @@ export default function Wheel() {
const starsEnabled = config.spin_cost_stars_enabled && config.spin_cost_stars;
const daysEnabled = config.spin_cost_days_enabled && config.spin_cost_days;
const canPayBalance = starsEnabled && config.can_pay_stars;
const canPayDays = daysEnabled && config.can_pay_days;
if (isTelegramMiniApp) {
// In Mini App: prefer stars if available
if (starsEnabled) {
setPaymentType('telegram_stars');
} else if (canPayDays) {
setPaymentType('subscription_days');
}
} else {
// In Web: prefer balance (Stars converted to rubles), fallback to days
if (canPayBalance) {
setPaymentType('telegram_stars');
} else if (canPayDays) {
setPaymentType('subscription_days');
}
if (starsEnabled) {
setPaymentType('telegram_stars');
} else if (daysEnabled) {
setPaymentType('subscription_days');
}
}, [config, isTelegramMiniApp]);
}, [config]);
// Function to poll for new spin result after Stars payment
const pollForSpinResult = useCallback(
@@ -362,7 +347,11 @@ export default function Wheel() {
};
const handleUnifiedSpin = () => {
if (isTelegramMiniApp && paymentType === 'telegram_stars') {
if (paymentType === 'telegram_stars') {
if (!config?.spin_cost_stars_enabled || !config?.spin_cost_stars) {
notify.warning(t('wheel.starsNotAvailable'));
return;
}
handleDirectStarsPay();
} else {
handleSpin();
@@ -456,11 +445,7 @@ export default function Wheel() {
const starsEnabled = config.spin_cost_stars_enabled && config.spin_cost_stars;
const daysEnabled = config.spin_cost_days_enabled && config.spin_cost_days;
const canPayBalance = starsEnabled && config.can_pay_stars; // For web: pay with internal balance
const canPayDays = daysEnabled && config.can_pay_days;
const bothMethodsAvailable = isTelegramMiniApp
? starsEnabled && daysEnabled && canPayDays
: starsEnabled && daysEnabled && canPayBalance && canPayDays;
const bothMethodsAvailable = !!(starsEnabled && daysEnabled);
const spinDisabled =
!config.can_spin ||
@@ -472,10 +457,7 @@ export default function Wheel() {
const getCostSubtitle = () => {
if (bothMethodsAvailable) return null; // toggle handles it
if (paymentType === 'telegram_stars' && starsEnabled) {
if (isTelegramMiniApp) {
return `${config.spin_cost_stars}`;
}
return `${formatAmount(config.required_balance_kopeks / 100)} ${currencySymbol} (${config.spin_cost_stars} ⭐)`;
return `${config.spin_cost_stars}`;
}
if (paymentType === 'subscription_days' && daysEnabled) {
return t('wheel.days', { count: config.spin_cost_days ?? 0 });
@@ -529,9 +511,7 @@ export default function Wheel() {
}`}
>
<StarIcon />
{isTelegramMiniApp
? `${config.spin_cost_stars}`
: `${formatAmount(config.required_balance_kopeks / 100)} ${currencySymbol}`}
{`${config.spin_cost_stars}`}
</button>
<button
onClick={() => setPaymentType('subscription_days')}