mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-30 10:27:49 +00:00
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:
@@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import { promoApi, PromoOffer } from '../api/promo';
|
import { promoApi, PromoOffer } from '../api/promo';
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
@@ -148,22 +149,26 @@ export default function PromoOffersSection({ className = '' }: PromoOffersSectio
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`space-y-4 ${className}`}>
|
<div className={`space-y-4 ${className}`}>
|
||||||
{/* Active Discount Banner */}
|
{/* Active Discount Banner - clickable, navigates to subscription */}
|
||||||
{activeDiscount && activeDiscount.is_active && activeDiscount.discount_percent > 0 && (
|
{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 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">
|
<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">
|
||||||
<CheckIcon />
|
<span className="text-2xl">🏷️</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="mb-1 flex items-center gap-2">
|
<div className="mb-1 flex items-center gap-2">
|
||||||
<h3 className="font-semibold text-dark-100">
|
<h3 className="font-semibold text-dark-100">
|
||||||
{t('promo.offers.discountActiveTitle', {
|
{t('promo.offers.discountActiveTitle', {
|
||||||
percent: activeDiscount.discount_percent,
|
percent: activeDiscount.discount_percent,
|
||||||
})}
|
})}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="rounded bg-accent-500/20 px-2 py-0.5 text-xs text-accent-400">
|
<span className="rounded bg-success-500/20 px-2 py-0.5 text-xs font-bold text-success-400">
|
||||||
{t('promo.offers.statusActive')}
|
-{activeDiscount.discount_percent}%
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4 text-sm text-dark-400">
|
<div className="flex items-center gap-4 text-sm text-dark-400">
|
||||||
@@ -179,8 +184,20 @@ export default function PromoOffersSection({ className = '' }: PromoOffersSectio
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
</div>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Success/Error Messages */}
|
{/* Success/Error Messages */}
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ import {
|
|||||||
isLogoPreloaded,
|
isLogoPreloaded,
|
||||||
} from '@/api/branding';
|
} from '@/api/branding';
|
||||||
import { themeColorsApi } from '@/api/themeColors';
|
import { themeColorsApi } from '@/api/themeColors';
|
||||||
import { promoApi } from '@/api/promo';
|
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
import LanguageSwitcher from '@/components/LanguageSwitcher';
|
import LanguageSwitcher from '@/components/LanguageSwitcher';
|
||||||
import PromoDiscountBadge from '@/components/PromoDiscountBadge';
|
|
||||||
import TicketNotificationBell from '@/components/TicketNotificationBell';
|
import TicketNotificationBell from '@/components/TicketNotificationBell';
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
@@ -78,7 +76,7 @@ export function AppHeader({
|
|||||||
}: AppHeaderProps) {
|
}: AppHeaderProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { user, logout, isAdmin, isAuthenticated } = useAuthStore();
|
const { user, logout, isAdmin } = useAuthStore();
|
||||||
const { toggleTheme, isDark } = useTheme();
|
const { toggleTheme, isDark } = useTheme();
|
||||||
const { haptic, platform } = usePlatform();
|
const { haptic, platform } = usePlatform();
|
||||||
const [userPhotoUrl, setUserPhotoUrl] = useState<string | null>(null);
|
const [userPhotoUrl, setUserPhotoUrl] = useState<string | null>(null);
|
||||||
@@ -112,15 +110,6 @@ export function AppHeader({
|
|||||||
});
|
});
|
||||||
const canToggle = enabledThemes?.dark && enabledThemes?.light;
|
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
|
// Get user photo from Telegram
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
@@ -273,16 +262,10 @@ export function AppHeader({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div onClick={() => setMobileMenuOpen(false)}>
|
|
||||||
<PromoDiscountBadge />
|
|
||||||
</div>
|
|
||||||
<div onClick={() => setMobileMenuOpen(false)}>
|
<div onClick={() => setMobileMenuOpen(false)}>
|
||||||
<TicketNotificationBell isAdmin={isAdminActive()} />
|
<TicketNotificationBell isAdmin={isAdminActive()} />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div onClick={() => setMobileMenuOpen(false)}>
|
||||||
className={isPromoActive ? 'hidden sm:block' : ''}
|
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
|
||||||
>
|
|
||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -358,7 +341,6 @@ export function AppHeader({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isPromoActive && <LanguageSwitcher />}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Nav items */}
|
{/* Nav items */}
|
||||||
|
|||||||
Reference in New Issue
Block a user