fix: remove small discount badge and improve large badge UX

- Remove unused PromoDiscountBadge component
- Fix undefined isPromoActive variable in AppHeader
- Restore language switcher visibility on mobile
- Enhance active discount banner with better hover effects
- Add arrow indicator and scale animation on hover
This commit is contained in:
c0mrade
2026-02-02 07:20:37 +03:00
parent c815ac29ea
commit 822b9a6265
3 changed files with 27 additions and 62 deletions

View File

@@ -1,34 +0,0 @@
import { useQuery } from '@tanstack/react-query';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { promoApi } from '../api/promo';
export default function PromoDiscountBadge() {
const { t } = useTranslation();
const { data: activeDiscount } = useQuery({
queryKey: ['active-discount'],
queryFn: promoApi.getActiveDiscount,
staleTime: 30000,
refetchInterval: 60000,
});
// Don't render if no active discount
if (!activeDiscount || !activeDiscount.is_active || !activeDiscount.discount_percent) {
return null;
}
return (
<Link
to="/subscription"
state={{ scrollToExtend: true }}
className="group relative flex items-center gap-1.5 rounded-lg bg-gradient-to-r from-success-500/20 to-accent-500/15 px-2.5 py-1.5 transition-all hover:from-success-500/30 hover:to-accent-500/25"
title={t('promo.activeDiscount', 'Active discount')}
>
<span className="text-base">🏷</span>
<span className="text-sm font-bold text-success-400">
-{activeDiscount.discount_percent}%
</span>
</Link>
);
}

View File

@@ -1,6 +1,7 @@
import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { promoApi, PromoOffer } from '../api/promo';
// Icons
@@ -148,22 +149,26 @@ export default function PromoOffersSection({ className = '' }: PromoOffersSectio
return (
<div className={`space-y-4 ${className}`}>
{/* Active Discount Banner */}
{/* Active Discount Banner - clickable, navigates to subscription */}
{activeDiscount && activeDiscount.is_active && activeDiscount.discount_percent > 0 && (
<div className="card border-accent-500/30 bg-gradient-to-br from-accent-500/10 to-transparent">
<Link
to="/subscription"
state={{ scrollToExtend: true }}
className="card group block cursor-pointer border-success-500/30 bg-gradient-to-br from-success-500/10 to-accent-500/5 transition-all duration-200 hover:scale-[1.01] hover:border-success-500/50 hover:from-success-500/20 hover:to-accent-500/10 hover:shadow-lg hover:shadow-success-500/10 active:scale-[0.99]"
>
<div className="flex items-center gap-4">
<div className="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-xl bg-accent-500/20 text-accent-400">
<CheckIcon />
<div className="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-xl bg-success-500/20 text-success-400 transition-transform duration-200 group-hover:scale-110">
<span className="text-2xl">🏷</span>
</div>
<div className="flex-1">
<div className="min-w-0 flex-1">
<div className="mb-1 flex items-center gap-2">
<h3 className="font-semibold text-dark-100">
{t('promo.offers.discountActiveTitle', {
percent: activeDiscount.discount_percent,
})}
</h3>
<span className="rounded bg-accent-500/20 px-2 py-0.5 text-xs text-accent-400">
{t('promo.offers.statusActive')}
<span className="rounded bg-success-500/20 px-2 py-0.5 text-xs font-bold text-success-400">
-{activeDiscount.discount_percent}%
</span>
</div>
<div className="flex items-center gap-4 text-sm text-dark-400">
@@ -179,8 +184,20 @@ export default function PromoOffersSection({ className = '' }: PromoOffersSectio
)}
</div>
</div>
{/* Arrow indicator */}
<div className="flex-shrink-0 text-dark-500 transition-all duration-200 group-hover:translate-x-1 group-hover:text-success-400">
<svg
className="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
</div>
</div>
</div>
</Link>
)}
{/* Success/Error Messages */}

View File

@@ -14,11 +14,9 @@ import {
isLogoPreloaded,
} from '@/api/branding';
import { themeColorsApi } from '@/api/themeColors';
import { promoApi } from '@/api/promo';
import { cn } from '@/lib/utils';
import LanguageSwitcher from '@/components/LanguageSwitcher';
import PromoDiscountBadge from '@/components/PromoDiscountBadge';
import TicketNotificationBell from '@/components/TicketNotificationBell';
// Icons
@@ -78,7 +76,7 @@ export function AppHeader({
}: AppHeaderProps) {
const { t } = useTranslation();
const location = useLocation();
const { user, logout, isAdmin, isAuthenticated } = useAuthStore();
const { user, logout, isAdmin } = useAuthStore();
const { toggleTheme, isDark } = useTheme();
const { haptic, platform } = usePlatform();
const [userPhotoUrl, setUserPhotoUrl] = useState<string | null>(null);
@@ -112,15 +110,6 @@ export function AppHeader({
});
const canToggle = enabledThemes?.dark && enabledThemes?.light;
// Promo active check
const { data: activeDiscount } = useQuery({
queryKey: ['active-discount'],
queryFn: promoApi.getActiveDiscount,
enabled: isAuthenticated,
staleTime: 30000,
});
const isPromoActive = activeDiscount?.is_active && activeDiscount?.discount_percent;
// Get user photo from Telegram
useEffect(() => {
try {
@@ -273,16 +262,10 @@ export function AppHeader({
</button>
)}
<div onClick={() => setMobileMenuOpen(false)}>
<PromoDiscountBadge />
</div>
<div onClick={() => setMobileMenuOpen(false)}>
<TicketNotificationBell isAdmin={isAdminActive()} />
</div>
<div
className={isPromoActive ? 'hidden sm:block' : ''}
onClick={() => setMobileMenuOpen(false)}
>
<div onClick={() => setMobileMenuOpen(false)}>
<LanguageSwitcher />
</div>
@@ -358,7 +341,6 @@ export function AppHeader({
</div>
</div>
</div>
{isPromoActive && <LanguageSwitcher />}
</div>
{/* Nav items */}