From 07745ea4ed5fe66e5eed56f61074dfa8b08ec90f Mon Sep 17 00:00:00 2001 From: Oronemu Date: Sat, 20 Dec 2025 01:07:24 +0700 Subject: [PATCH] Add TG banner --- frontend/src/components/TelegramBotBanner.tsx | 80 +++++++++++++++++++ frontend/src/pages/MarathonPage.tsx | 4 + frontend/src/pages/MarathonsPage.tsx | 6 ++ frontend/src/store/auth.ts | 1 + 4 files changed, 91 insertions(+) create mode 100644 frontend/src/components/TelegramBotBanner.tsx diff --git a/frontend/src/components/TelegramBotBanner.tsx b/frontend/src/components/TelegramBotBanner.tsx new file mode 100644 index 0000000..a39a94b --- /dev/null +++ b/frontend/src/components/TelegramBotBanner.tsx @@ -0,0 +1,80 @@ +import { Link } from 'react-router-dom' +import { useAuthStore } from '@/store/auth' +import { NeonButton } from '@/components/ui' +import { Bot, Bell, X } from 'lucide-react' +import { useState } from 'react' + +const STORAGE_KEY = 'telegram_banner_dismissed' + +export function TelegramBotBanner() { + const user = useAuthStore((state) => state.user) + const [dismissed, setDismissed] = useState(() => { + return sessionStorage.getItem(STORAGE_KEY) === 'true' + }) + + const handleDismiss = () => { + sessionStorage.setItem(STORAGE_KEY, 'true') + setDismissed(true) + } + + // Don't show if user already has Telegram linked or dismissed + if (user?.telegram_id || dismissed) { + return null + } + + return ( +
+ {/* Background image */} +
+ {/* Overlay */} +
+ + {/* Close button */} + + + {/* Content */} +
+
+
+ +
+
+

+ Привяжите Telegram-бота +

+

+ Получайте уведомления о событиях марафона, новых заданиях и результатах прямо в Telegram +

+
+ + + Мгновенные уведомления + + + + Удобное управление + +
+
+
+ +
+ + + Привязать + + +
+
+
+ ) +} diff --git a/frontend/src/pages/MarathonPage.tsx b/frontend/src/pages/MarathonPage.tsx index 16af9f6..0670ae6 100644 --- a/frontend/src/pages/MarathonPage.tsx +++ b/frontend/src/pages/MarathonPage.tsx @@ -16,6 +16,7 @@ import { } from 'lucide-react' import { format } from 'date-fns' import { ru } from 'date-fns/locale' +import { TelegramBotBanner } from '@/components/TelegramBotBanner' export function MarathonPage() { const { id } = useParams<{ id: string }>() @@ -316,6 +317,9 @@ export function MarathonPage() { />
+ {/* Telegram Bot Banner */} + + {/* Active event banner */} {marathon.status === 'active' && activeEvent?.event && ( diff --git a/frontend/src/pages/MarathonsPage.tsx b/frontend/src/pages/MarathonsPage.tsx index d074369..50170ae 100644 --- a/frontend/src/pages/MarathonsPage.tsx +++ b/frontend/src/pages/MarathonsPage.tsx @@ -4,6 +4,7 @@ import { marathonsApi } from '@/api' import type { MarathonListItem } from '@/types' import { NeonButton, GlassCard, StatsCard } from '@/components/ui' import { Plus, Users, Calendar, Loader2, Trophy, Gamepad2, ChevronRight, Hash, Sparkles } from 'lucide-react' +import { TelegramBotBanner } from '@/components/TelegramBotBanner' import { format } from 'date-fns' import { ru } from 'date-fns/locale' @@ -145,6 +146,11 @@ export function MarathonsPage() {
)} + {/* Telegram Bot Banner */} +
+ +
+ {/* Join marathon */} {showJoinSection && ( diff --git a/frontend/src/store/auth.ts b/frontend/src/store/auth.ts index de86341..06cd4e2 100644 --- a/frontend/src/store/auth.ts +++ b/frontend/src/store/auth.ts @@ -148,6 +148,7 @@ export const useAuthStore = create()( logout: () => { localStorage.removeItem('token') + sessionStorage.removeItem('telegram_banner_dismissed') set({ user: null, token: null,