Redesign p1
This commit is contained in:
@@ -1,42 +1,88 @@
|
||||
import { Outlet, Link, useNavigate } from 'react-router-dom'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Outlet, Link, useNavigate, useLocation } from 'react-router-dom'
|
||||
import { useAuthStore } from '@/store/auth'
|
||||
import { Gamepad2, LogOut, Trophy, User } from 'lucide-react'
|
||||
import { Gamepad2, LogOut, Trophy, User, Menu, X } from 'lucide-react'
|
||||
import { TelegramLink } from '@/components/TelegramLink'
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
export function Layout() {
|
||||
const { user, isAuthenticated, logout } = useAuthStore()
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const [isScrolled, setIsScrolled] = useState(false)
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setIsScrolled(window.scrollY > 10)
|
||||
}
|
||||
window.addEventListener('scroll', handleScroll)
|
||||
return () => window.removeEventListener('scroll', handleScroll)
|
||||
}, [])
|
||||
|
||||
// Close mobile menu on route change
|
||||
useEffect(() => {
|
||||
setIsMobileMenuOpen(false)
|
||||
}, [location])
|
||||
|
||||
const handleLogout = () => {
|
||||
logout()
|
||||
navigate('/login')
|
||||
}
|
||||
|
||||
const isActiveLink = (path: string) => location.pathname === path
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
{/* Header */}
|
||||
<header className="bg-gray-800 border-b border-gray-700">
|
||||
<header
|
||||
className={clsx(
|
||||
'fixed top-0 left-0 right-0 z-50 transition-all duration-300',
|
||||
isScrolled
|
||||
? 'bg-dark-900/80 backdrop-blur-lg border-b border-dark-600/50 shadow-lg'
|
||||
: 'bg-transparent'
|
||||
)}
|
||||
>
|
||||
<div className="container mx-auto px-4 py-4 flex items-center justify-between">
|
||||
<Link to="/" className="flex items-center gap-2 text-xl font-bold text-white">
|
||||
<Gamepad2 className="w-8 h-8 text-primary-500" />
|
||||
<span>Игровой Марафон</span>
|
||||
{/* Logo */}
|
||||
<Link
|
||||
to="/"
|
||||
className="flex items-center gap-3 group"
|
||||
>
|
||||
<div className="relative">
|
||||
<Gamepad2 className="w-8 h-8 text-neon-500 transition-all duration-300 group-hover:text-neon-400 group-hover:drop-shadow-[0_0_8px_rgba(0,240,255,0.8)]" />
|
||||
</div>
|
||||
<span className="text-xl font-bold text-white font-display tracking-wider glitch-hover">
|
||||
МАРАФОН
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<nav className="flex items-center gap-4">
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden md:flex items-center gap-6">
|
||||
{isAuthenticated ? (
|
||||
<>
|
||||
<Link
|
||||
to="/marathons"
|
||||
className="flex items-center gap-2 text-gray-300 hover:text-white transition-colors"
|
||||
className={clsx(
|
||||
'flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200',
|
||||
isActiveLink('/marathons')
|
||||
? 'text-neon-400 bg-neon-500/10'
|
||||
: 'text-gray-300 hover:text-white hover:bg-dark-700'
|
||||
)}
|
||||
>
|
||||
<Trophy className="w-5 h-5" />
|
||||
<span>Марафоны</span>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3 ml-4 pl-4 border-l border-gray-700">
|
||||
<div className="flex items-center gap-3 ml-2 pl-4 border-l border-dark-600">
|
||||
<Link
|
||||
to="/profile"
|
||||
className="flex items-center gap-2 text-gray-300 hover:text-white transition-colors"
|
||||
className={clsx(
|
||||
'flex items-center gap-2 px-3 py-2 rounded-lg transition-all duration-200',
|
||||
isActiveLink('/profile')
|
||||
? 'text-neon-400 bg-neon-500/10'
|
||||
: 'text-gray-300 hover:text-white hover:bg-dark-700'
|
||||
)}
|
||||
>
|
||||
<User className="w-5 h-5" />
|
||||
<span>{user?.nickname}</span>
|
||||
@@ -46,7 +92,7 @@ export function Layout() {
|
||||
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="p-2 text-gray-400 hover:text-white transition-colors"
|
||||
className="p-2 text-gray-400 hover:text-red-400 hover:bg-red-500/10 rounded-lg transition-all duration-200"
|
||||
title="Выйти"
|
||||
>
|
||||
<LogOut className="w-5 h-5" />
|
||||
@@ -55,27 +101,114 @@ export function Layout() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link to="/login" className="text-gray-300 hover:text-white transition-colors">
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-gray-300 hover:text-white transition-colors px-4 py-2"
|
||||
>
|
||||
Войти
|
||||
</Link>
|
||||
<Link to="/register" className="btn btn-primary">
|
||||
<Link
|
||||
to="/register"
|
||||
className="px-4 py-2 bg-neon-500 hover:bg-neon-400 text-dark-900 font-semibold rounded-lg transition-all duration-200 shadow-[0_0_15px_rgba(0,240,255,0.3)] hover:shadow-[0_0_25px_rgba(0,240,255,0.5)]"
|
||||
>
|
||||
Регистрация
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className="md:hidden p-2 text-gray-300 hover:text-white rounded-lg hover:bg-dark-700 transition-colors"
|
||||
>
|
||||
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
{isMobileMenuOpen && (
|
||||
<div className="md:hidden bg-dark-800/95 backdrop-blur-lg border-t border-dark-600 animate-slide-in-down">
|
||||
<div className="container mx-auto px-4 py-4 space-y-2">
|
||||
{isAuthenticated ? (
|
||||
<>
|
||||
<Link
|
||||
to="/marathons"
|
||||
className={clsx(
|
||||
'flex items-center gap-3 px-4 py-3 rounded-lg transition-all',
|
||||
isActiveLink('/marathons')
|
||||
? 'text-neon-400 bg-neon-500/10'
|
||||
: 'text-gray-300 hover:text-white hover:bg-dark-700'
|
||||
)}
|
||||
>
|
||||
<Trophy className="w-5 h-5" />
|
||||
<span>Марафоны</span>
|
||||
</Link>
|
||||
<Link
|
||||
to="/profile"
|
||||
className={clsx(
|
||||
'flex items-center gap-3 px-4 py-3 rounded-lg transition-all',
|
||||
isActiveLink('/profile')
|
||||
? 'text-neon-400 bg-neon-500/10'
|
||||
: 'text-gray-300 hover:text-white hover:bg-dark-700'
|
||||
)}
|
||||
>
|
||||
<User className="w-5 h-5" />
|
||||
<span>{user?.nickname}</span>
|
||||
</Link>
|
||||
<div className="pt-2 border-t border-dark-600">
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="flex items-center gap-3 w-full px-4 py-3 text-red-400 hover:bg-red-500/10 rounded-lg transition-all"
|
||||
>
|
||||
<LogOut className="w-5 h-5" />
|
||||
<span>Выйти</span>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link
|
||||
to="/login"
|
||||
className="block px-4 py-3 text-gray-300 hover:text-white hover:bg-dark-700 rounded-lg transition-all"
|
||||
>
|
||||
Войти
|
||||
</Link>
|
||||
<Link
|
||||
to="/register"
|
||||
className="block px-4 py-3 text-center bg-neon-500 hover:bg-neon-400 text-dark-900 font-semibold rounded-lg transition-all"
|
||||
>
|
||||
Регистрация
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
{/* Spacer for fixed header */}
|
||||
<div className="h-[72px]" />
|
||||
|
||||
{/* Main content */}
|
||||
<main className="flex-1 container mx-auto px-4 py-8">
|
||||
<Outlet />
|
||||
</main>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className="bg-gray-800 border-t border-gray-700 py-4">
|
||||
<div className="container mx-auto px-4 text-center text-gray-500 text-sm">
|
||||
Игровой Марафон © {new Date().getFullYear()}
|
||||
<footer className="bg-dark-800/50 border-t border-dark-600/50 py-6">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-2 text-gray-500">
|
||||
<Gamepad2 className="w-5 h-5 text-neon-500/50" />
|
||||
<span className="text-sm">
|
||||
Игровой Марафон © {new Date().getFullYear()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm text-gray-500">
|
||||
<span className="text-neon-500/50">v1.0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user