diff --git a/src/api/branding.ts b/src/api/branding.ts index e948691..b61f2e5 100644 --- a/src/api/branding.ts +++ b/src/api/branding.ts @@ -7,6 +7,10 @@ export interface BrandingInfo { has_custom_logo: boolean } +export interface AnimationEnabled { + enabled: boolean +} + export const brandingApi = { // Get current branding (public, no auth required) getBranding: async (): Promise => { @@ -45,4 +49,16 @@ export const brandingApi = { } return `${import.meta.env.VITE_API_URL || ''}${branding.logo_url}` }, + + // Get animation enabled (public, no auth required) + getAnimationEnabled: async (): Promise => { + const response = await apiClient.get('/cabinet/branding/animation') + return response.data + }, + + // Update animation enabled (admin only) + updateAnimationEnabled: async (enabled: boolean): Promise => { + const response = await apiClient.patch('/cabinet/branding/animation', { enabled }) + return response.data + }, } diff --git a/src/components/AnimatedBackground.tsx b/src/components/AnimatedBackground.tsx new file mode 100644 index 0000000..4695887 --- /dev/null +++ b/src/components/AnimatedBackground.tsx @@ -0,0 +1,190 @@ +import { useQuery } from '@tanstack/react-query' +import { brandingApi } from '../api/branding' + +export default function AnimatedBackground() { + const { data: animationSettings } = useQuery({ + queryKey: ['animation-enabled'], + queryFn: brandingApi.getAnimationEnabled, + staleTime: 1000 * 60 * 5, // 5 minutes + retry: false, + }) + + // Don't render if animation is disabled + if (animationSettings && !animationSettings.enabled) { + return null + } + + return ( + <> + {/* SVG Filter for glow effect */} + + + + + + + + + + + {/* Animated wave gradients */} +
+
+
+
+
+
+ + + + ) +} diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index a6263e9..8ab2c62 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -6,6 +6,7 @@ import { useAuthStore } from '../../store/auth' import LanguageSwitcher from '../LanguageSwitcher' import PromoDiscountBadge from '../PromoDiscountBadge' import TicketNotificationBell from '../TicketNotificationBell' +import AnimatedBackground from '../AnimatedBackground' import { contestsApi } from '../../api/contests' import { pollsApi } from '../../api/polls' import { brandingApi } from '../../api/branding' @@ -270,6 +271,9 @@ export default function Layout({ children }: LayoutProps) { return (
+ {/* Animated Background */} + + {/* Header */}
diff --git a/src/pages/AdminSettings.tsx b/src/pages/AdminSettings.tsx index e8cfa56..c3bc9de 100644 --- a/src/pages/AdminSettings.tsx +++ b/src/pages/AdminSettings.tsx @@ -864,6 +864,19 @@ export default function AdminSettings() { queryFn: brandingApi.getBranding, }) + // Animation toggle query and mutation + const { data: animationSettings } = useQuery({ + queryKey: ['animation-enabled'], + queryFn: brandingApi.getAnimationEnabled, + }) + + const updateAnimationMutation = useMutation({ + mutationFn: (enabled: boolean) => brandingApi.updateAnimationEnabled(enabled), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['animation-enabled'] }) + }, + }) + const updateNameMutation = useMutation({ mutationFn: (name: string) => brandingApi.updateName(name), onSuccess: () => { @@ -1187,6 +1200,29 @@ export default function AdminSettings() {

+ + {/* Animation Toggle */} +
+
+
+

Анимированный фон

+

+ Волновая анимация на фоне для всех пользователей +

+
+ +
+
{/* Theme Colors Card */}