fix: add subscription tab to desktop nav, fix device dots overflow, show available referral balance

- Add Subscription tab to desktop header navigation (was only in mobile)
- Fix device dots overflow for large limits (>10) by using progress bar
- Show available referral balance on dashboard instead of total earnings
- Add available_balance and withdrawn fields to ReferralInfo type
This commit is contained in:
Fringg
2026-02-27 04:53:37 +03:00
parent 82987fd49a
commit 27f85a1db1
5 changed files with 39 additions and 15 deletions

View File

@@ -42,7 +42,7 @@ export default function StatsGrid({
refLoading, refLoading,
}: StatsGridProps) { }: StatsGridProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { formatAmount, currencySymbol, formatPositive } = useCurrency(); const { formatAmount, currencySymbol } = useCurrency();
const { isDark } = useTheme(); const { isDark } = useTheme();
const g = getGlassColors(isDark); const g = getGlassColors(isDark);
@@ -83,7 +83,7 @@ export default function StatsGrid({
label: t('dashboard.stats.referrals'), label: t('dashboard.stats.referrals'),
value: `${referralCount}`, value: `${referralCount}`,
valueColor: g.text, valueColor: g.text,
subtitle: `${formatPositive(earningsRubles)} ${currencySymbol}`, subtitle: `${formatAmount(earningsRubles)} ${currencySymbol}`,
subtitleColor: zone.mainHex, subtitleColor: zone.mainHex,
to: '/referral', to: '/referral',
icon: (color: string) => ( icon: (color: string) => (

View File

@@ -240,19 +240,38 @@ export default function SubscriptionCardActive({
</div> </div>
</div> </div>
{/* Device dots */} {/* Device indicator */}
<div className="flex flex-shrink-0 gap-1.5" aria-hidden="true"> {subscription.device_limit <= 10 ? (
{Array.from({ length: subscription.device_limit }, (_, i) => ( <div className="flex flex-shrink-0 gap-1.5" aria-hidden="true">
{Array.from({ length: subscription.device_limit }, (_, i) => (
<div
key={i}
className="h-[7px] w-[7px] rounded-full transition-all duration-300"
style={{
background: i < connectedDevices ? zone.mainHex : g.textGhost,
boxShadow: i < connectedDevices ? `0 0 6px ${zone.mainHex}50` : 'none',
}}
/>
))}
</div>
) : (
<div className="flex w-16 flex-shrink-0 items-center" aria-hidden="true">
<div <div
key={i} className="h-[6px] w-full overflow-hidden rounded-full"
className="h-[7px] w-[7px] rounded-full transition-all duration-300" style={{ background: g.textGhost }}
style={{ >
background: i < connectedDevices ? zone.mainHex : g.textGhost, <div
boxShadow: i < connectedDevices ? `0 0 6px ${zone.mainHex}50` : 'none', className="h-full rounded-full transition-all duration-500"
}} style={{
/> width: `${Math.round((connectedDevices / subscription.device_limit) * 100)}%`,
))} background: zone.mainHex,
</div> boxShadow: `0 0 8px ${zone.mainHex}40`,
minWidth: connectedDevices > 0 ? '4px' : '0px',
}}
/>
</div>
</div>
)}
</HoverBorderGradient> </HoverBorderGradient>
)} )}

View File

@@ -20,6 +20,7 @@ import CampaignBonusNotifier from '@/components/CampaignBonusNotifier';
import SuccessNotificationModal from '@/components/SuccessNotificationModal'; import SuccessNotificationModal from '@/components/SuccessNotificationModal';
import LanguageSwitcher from '@/components/LanguageSwitcher'; import LanguageSwitcher from '@/components/LanguageSwitcher';
import TicketNotificationBell from '@/components/TicketNotificationBell'; import TicketNotificationBell from '@/components/TicketNotificationBell';
import { SubscriptionIcon } from '@/components/icons';
import { MobileBottomNav } from './MobileBottomNav'; import { MobileBottomNav } from './MobileBottomNav';
import { AppHeader } from './AppHeader'; import { AppHeader } from './AppHeader';
@@ -252,6 +253,7 @@ export function AppShell({ children }: AppShellProps) {
// Desktop navigation items // Desktop navigation items
const desktopNavItems = [ const desktopNavItems = [
{ path: '/', label: t('nav.dashboard'), icon: HomeIcon }, { path: '/', label: t('nav.dashboard'), icon: HomeIcon },
{ path: '/subscription', label: t('nav.subscription'), icon: SubscriptionIcon },
{ path: '/balance', label: t('nav.balance'), icon: CreditCardIcon }, { path: '/balance', label: t('nav.balance'), icon: CreditCardIcon },
{ path: '/support', label: t('nav.support'), icon: ChatIcon }, { path: '/support', label: t('nav.support'), icon: ChatIcon },
{ path: '/info', label: t('nav.info'), icon: InfoIcon }, { path: '/info', label: t('nav.info'), icon: InfoIcon },

View File

@@ -265,7 +265,7 @@ export default function Dashboard() {
balanceRubles={balanceData?.balance_rubles || 0} balanceRubles={balanceData?.balance_rubles || 0}
subscription={subscription} subscription={subscription}
referralCount={referralInfo?.total_referrals || 0} referralCount={referralInfo?.total_referrals || 0}
earningsRubles={referralInfo?.total_earnings_rubles || 0} earningsRubles={referralInfo?.available_balance_rubles || 0}
refLoading={refLoading} refLoading={refLoading}
/> />

View File

@@ -423,6 +423,9 @@ export interface ReferralInfo {
total_earnings_kopeks: number; total_earnings_kopeks: number;
total_earnings_rubles: number; total_earnings_rubles: number;
commission_percent: number; commission_percent: number;
available_balance_kopeks: number;
available_balance_rubles: number;
withdrawn_kopeks: number;
} }
export interface ReferralTerms { export interface ReferralTerms {