101 lines
3.5 KiB
TypeScript
101 lines
3.5 KiB
TypeScript
import { Link } from 'react-router-dom'
|
||
import { useAuthStore } from '@/store/auth'
|
||
import { contentApi } from '@/api/admin'
|
||
import { NeonButton } from '@/components/ui'
|
||
import { Bot, Bell, X } from 'lucide-react'
|
||
import { useState, useEffect } from 'react'
|
||
|
||
const STORAGE_KEY = 'telegram_banner_dismissed'
|
||
|
||
// Default content if not configured in admin
|
||
const DEFAULT_TITLE = 'Привяжите Telegram-бота'
|
||
const DEFAULT_DESCRIPTION = 'Получайте уведомления о событиях марафона, новых заданиях и результатах прямо в Telegram'
|
||
|
||
export function TelegramBotBanner() {
|
||
const user = useAuthStore((state) => state.user)
|
||
const [dismissed, setDismissed] = useState(() => {
|
||
return sessionStorage.getItem(STORAGE_KEY) === 'true'
|
||
})
|
||
const [title, setTitle] = useState(DEFAULT_TITLE)
|
||
const [description, setDescription] = useState(DEFAULT_DESCRIPTION)
|
||
|
||
useEffect(() => {
|
||
const loadContent = async () => {
|
||
try {
|
||
const data = await contentApi.getPublicContent('telegram_bot_info')
|
||
if (data.title) setTitle(data.title)
|
||
if (data.content) setDescription(data.content)
|
||
} catch {
|
||
// Use defaults if content not found
|
||
}
|
||
}
|
||
loadContent()
|
||
}, [])
|
||
|
||
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 (
|
||
<div className="relative rounded-2xl overflow-hidden">
|
||
{/* Background image */}
|
||
<div
|
||
className="absolute inset-0 bg-cover bg-center"
|
||
style={{ backgroundImage: 'url(/telegram_bot_banner.png)' }}
|
||
/>
|
||
{/* Overlay */}
|
||
<div className="absolute inset-0 bg-gradient-to-r from-dark-900/95 via-dark-900/80 to-dark-900/60" />
|
||
|
||
{/* Close button */}
|
||
<button
|
||
onClick={handleDismiss}
|
||
className="absolute top-3 right-3 p-1.5 text-white bg-dark-700/70 hover:bg-dark-600 rounded-lg transition-colors z-10"
|
||
title="Скрыть"
|
||
>
|
||
<X className="w-4 h-4" />
|
||
</button>
|
||
|
||
{/* Content */}
|
||
<div className="relative p-6 pr-12 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 rounded-xl bg-[#2AABEE]/20 border border-[#2AABEE]/30 flex items-center justify-center flex-shrink-0">
|
||
<Bot className="w-6 h-6 text-[#2AABEE]" />
|
||
</div>
|
||
<div>
|
||
<h3 className="text-lg font-semibold text-white mb-1">
|
||
{title}
|
||
</h3>
|
||
<p className="text-gray-400 text-sm max-w-md">
|
||
{description}
|
||
</p>
|
||
<div className="flex items-center gap-4 mt-2 text-xs text-gray-500">
|
||
<span className="flex items-center gap-1">
|
||
<Bell className="w-3 h-3" />
|
||
Мгновенные уведомления
|
||
</span>
|
||
<span className="flex items-center gap-1">
|
||
<Bot className="w-3 h-3" />
|
||
Удобное управление
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="ml-16 sm:ml-0">
|
||
<Link to="/profile">
|
||
<NeonButton color="neon" size="sm">
|
||
Привязать
|
||
</NeonButton>
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|