mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
fix(cabinet): show trial offer in multi-tariff mode
Two cabinet routes never showed TrialOfferCard for users without any subscription when MULTI_TARIFF was enabled: 1. Dashboard (/) hasNoSubscription was derived from subscriptionResponse, but the /cabinet/subscription query is disabled in multi-tariff mode (`enabled: !isMultiTariff`). subscriptionResponse stayed undefined forever, so `has_subscription === false` was never true and the trial card never rendered. Fix: branch on isMultiTariff — use multiSubData.subscriptions.length when in multi-tariff, keep the single-tariff path unchanged. 2. /subscriptions list When the array came back empty the page rendered EmptyState directly, bypassing trial eligibility entirely. Users who navigated to 'Подписки' from the menu before opening the dashboard saw the empty placeholder and nothing about the trial. Fix: fetch trial-info on empty state, render TrialOfferCard if trialInfo.is_available, fall back to EmptyState otherwise. Also wired the activate mutation locally (mirrors Dashboard) so the button works without bouncing through the home screen first. Single-tariff behavior is unchanged. After the fix both entry points agree: if you have no subscriptions and trial is available, you see the offer regardless of which page you opened first.
This commit is contained in:
@@ -195,7 +195,12 @@ export default function Dashboard() {
|
||||
refreshTrafficMutation.mutate();
|
||||
}, [subscription, refreshTrafficMutation]);
|
||||
|
||||
const hasNoSubscription = subscriptionResponse?.has_subscription === false && !subLoading;
|
||||
// В multi-tariff /cabinet/subscription отключён, поэтому subscriptionResponse=undefined.
|
||||
// Используем список из /cabinet/subscriptions/list — пустой массив означает «нет подписок»,
|
||||
// и тогда показываем TrialOfferCard. Без этой ветки multi-tariff юзер никогда не видел триал.
|
||||
const hasNoSubscription = isMultiTariff
|
||||
? multiSubData !== undefined && (multiSubData.subscriptions?.length ?? 0) === 0
|
||||
: subscriptionResponse?.has_subscription === false && !subLoading;
|
||||
|
||||
// Show onboarding for new users after data loads
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useState } from 'react';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { Navigate, useNavigate } from 'react-router';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { subscriptionApi } from '../api/subscription';
|
||||
import { balanceApi } from '../api/balance';
|
||||
import { useTheme } from '../hooks/useTheme';
|
||||
import { getGlassColors } from '../utils/glassTheme';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
import SubscriptionListCard from '../components/subscription/SubscriptionListCard';
|
||||
import TrialOfferCard from '../components/dashboard/TrialOfferCard';
|
||||
|
||||
function EmptyState({ onBuy }: { onBuy: () => void }) {
|
||||
const { t } = useTranslation();
|
||||
@@ -55,6 +59,9 @@ export default function Subscriptions() {
|
||||
const navigate = useNavigate();
|
||||
const { isDark } = useTheme();
|
||||
const g = getGlassColors(isDark);
|
||||
const queryClient = useQueryClient();
|
||||
const refreshUser = useAuthStore((state) => state.refreshUser);
|
||||
const [trialError, setTrialError] = useState<string | null>(null);
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['subscriptions-list'],
|
||||
@@ -65,6 +72,39 @@ export default function Subscriptions() {
|
||||
|
||||
const subscriptions = data?.subscriptions ?? [];
|
||||
const isMultiTariff = data?.multi_tariff_enabled ?? false;
|
||||
const hasNoSubscriptions = !isLoading && subscriptions.length === 0;
|
||||
|
||||
// Если у юзера нет подписок — проверяем доступность триала, иначе
|
||||
// (в multi-tariff) ему вообще негде увидеть оффер.
|
||||
const { data: trialInfo, isLoading: trialLoading } = useQuery({
|
||||
queryKey: ['trial-info'],
|
||||
queryFn: () => subscriptionApi.getTrialInfo(),
|
||||
enabled: hasNoSubscriptions,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
|
||||
const { data: balanceData } = useQuery({
|
||||
queryKey: ['balance'],
|
||||
queryFn: balanceApi.getBalance,
|
||||
enabled: hasNoSubscriptions && !!trialInfo?.is_available,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
|
||||
const activateTrialMutation = useMutation({
|
||||
mutationFn: () => subscriptionApi.activateTrial(),
|
||||
onSuccess: () => {
|
||||
setTrialError(null);
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['subscriptions-list'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['trial-info'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['balance'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['purchase-options'] });
|
||||
refreshUser();
|
||||
},
|
||||
onError: (error: { response?: { data?: { detail?: string } } }) => {
|
||||
setTrialError(error.response?.data?.detail || t('common.error'));
|
||||
},
|
||||
});
|
||||
|
||||
// Single-tariff mode with one subscription: skip list, go directly to detail
|
||||
if (data && !isMultiTariff && subscriptions.length === 1) {
|
||||
@@ -115,8 +155,17 @@ export default function Subscriptions() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Empty state */}
|
||||
{!isLoading && subscriptions.length === 0 && (
|
||||
{/* Empty state: показываем триал, если доступен; иначе — обычный empty */}
|
||||
{hasNoSubscriptions && !trialLoading && trialInfo?.is_available && (
|
||||
<TrialOfferCard
|
||||
trialInfo={trialInfo}
|
||||
balanceKopeks={balanceData?.balance_kopeks ?? 0}
|
||||
balanceRubles={balanceData?.balance_rubles ?? 0}
|
||||
activateTrialMutation={activateTrialMutation}
|
||||
trialError={trialError}
|
||||
/>
|
||||
)}
|
||||
{hasNoSubscriptions && !trialLoading && !trialInfo?.is_available && (
|
||||
<EmptyState onBuy={() => navigate('/subscription/purchase')} />
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user