deckhearth/src/components/ResponsiveLayout.tsx

520 lines
No EOL
28 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import { useTheme } from '../contexts/ThemeContext';
const ResponsiveLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { user, logout, isAdmin } = useAuth();
const { toggleTheme, effectiveTheme } = useTheme();
const location = useLocation();
const navigate = useNavigate();
const [showUserMenu, setShowUserMenu] = useState(false);
const [sidebarOpen, setSidebarOpen] = useState(false);
const handleLogout = () => {
logout();
setShowUserMenu(false);
setSidebarOpen(false);
navigate('/login');
};
const isActive = (path: string) => location.pathname === path;
const navigation = [
{ name: 'Dashboard', href: '/dashboard', icon: '📊', mobileIcon: '🏠' },
{ name: 'Cards', href: '/cards', icon: '🃏', mobileIcon: '🃏' },
{ name: 'Collections', href: '/collections', icon: '📚', mobileIcon: '📚' },
{ name: 'Decks', href: '/decks', icon: '🎯', mobileIcon: '🎯' },
{ name: 'Scanner', href: '/scanner', icon: '📷', mobileIcon: '📷' },
];
return (
<div className="min-h-screen bg-surface-50 dark:bg-surface-900 transition-colors">
{/* Desktop Layout */}
<div className="hidden lg:flex h-screen">
{/* Sidebar */}
<div className="w-64 bg-white dark:bg-surface-800 border-r border-surface-200 dark:border-surface-700 flex flex-col">
{/* Logo */}
<div className="p-6 border-b border-surface-200 dark:border-surface-700">
<Link to="/dashboard" className="flex items-center space-x-3">
<div className="bg-gradient-to-r from-primary-500 to-accent-500 text-white p-3 rounded-xl">
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
<path d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<div>
<h1 className="text-xl font-bold text-surface-900 dark:text-white">TCG Vault</h1>
<p className="text-sm text-surface-600 dark:text-surface-400">
Hi, {user?.firstName || user?.username}
</p>
</div>
</Link>
</div>
{/* Navigation */}
<nav className="flex-1 p-4 space-y-2">
{navigation.map((item) => (
<Link
key={item.name}
to={item.href}
className={`flex items-center space-x-3 px-4 py-3 rounded-xl text-sm font-medium transition-all duration-200 ${
isActive(item.href)
? 'bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300'
: 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-white hover:bg-surface-100 dark:hover:bg-surface-700'
}`}
>
<span className="text-lg">{item.icon}</span>
<span>{item.name}</span>
</Link>
))}
</nav>
{/* User Section */}
<div className="p-4 border-t border-surface-200 dark:border-surface-700">
<div className="flex items-center space-x-3 p-3 rounded-xl bg-surface-50 dark:bg-surface-700">
<div className="w-10 h-10 bg-gradient-to-r from-primary-500 to-accent-500 rounded-xl flex items-center justify-center text-white font-semibold">
{user?.firstName?.[0] || user?.username?.[0]?.toUpperCase() || 'U'}
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-surface-900 dark:text-white truncate">
{user?.firstName && user?.lastName
? `${user.firstName} ${user.lastName}`
: user?.username}
</p>
<p className="text-xs text-surface-600 dark:text-surface-400 truncate">{user?.email}</p>
</div>
<button
onClick={() => setShowUserMenu(!showUserMenu)}
className="p-1 rounded-lg hover:bg-surface-200 dark:hover:bg-surface-600 transition-colors"
>
<svg className="w-4 h-4 text-surface-600 dark:text-surface-400" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" />
</svg>
</button>
</div>
{/* User Menu Dropdown */}
{showUserMenu && (
<div className="absolute bottom-20 left-4 w-56 bg-white dark:bg-surface-800 rounded-xl shadow-lg ring-1 ring-black ring-opacity-5 border border-surface-200 dark:border-surface-700">
<div className="py-2">
<Link
to="/settings"
onClick={() => setShowUserMenu(false)}
className="flex items-center space-x-3 px-4 py-2 text-sm text-surface-700 dark:text-surface-300 hover:bg-surface-100 dark:hover:bg-surface-700"
>
<span></span>
<span>Settings</span>
</Link>
{isAdmin() && (
<Link
to="/admin"
onClick={() => setShowUserMenu(false)}
className="flex items-center space-x-3 px-4 py-2 text-sm text-yellow-700 dark:text-yellow-300 hover:bg-yellow-50 dark:hover:bg-yellow-900/20"
>
<span>👑</span>
<span>Admin Panel</span>
</Link>
)}
<div className="border-t border-surface-200 dark:border-surface-700 my-1"></div>
<button
onClick={handleLogout}
className="flex items-center space-x-3 px-4 py-2 text-sm text-red-700 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 w-full text-left"
>
<span>🚪</span>
<span>Sign Out</span>
</button>
</div>
</div>
)}
</div>
</div>
{/* Main Content */}
<div className="flex-1 flex flex-col overflow-hidden">
{/* Top Header */}
<header className="bg-white dark:bg-surface-800 border-b border-surface-200 dark:border-surface-700 px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<h2 className="text-2xl font-bold text-surface-900 dark:text-white">
{navigation.find(item => isActive(item.href))?.name || 'TCG Vault'}
</h2>
{isAdmin() && (
<span className="px-3 py-1 bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-200 text-xs font-medium rounded-full">
Admin
</span>
)}
</div>
<div className="flex items-center space-x-3">
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="p-2 rounded-xl bg-surface-100 dark:bg-surface-700 text-surface-600 dark:text-surface-300 hover:bg-surface-200 dark:hover:bg-surface-600 transition-colors"
>
{effectiveTheme === 'dark' ? (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clipRule="evenodd" />
</svg>
) : (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>
)}
</button>
</div>
</div>
</header>
{/* Page Content */}
<main className="flex-1 overflow-auto p-6">
<div className="max-w-7xl mx-auto">
{children}
</div>
</main>
</div>
</div>
{/* Mobile Layout */}
<div className="lg:hidden">
{/* Top Header */}
<header className="fixed top-0 left-0 right-0 z-40 bg-white dark:bg-surface-900 border-b border-surface-200 dark:border-surface-700 px-4 py-3 safe-area-inset-top">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<button
onClick={() => setSidebarOpen(!sidebarOpen)}
className="p-2 rounded-xl bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-300 hover:bg-surface-200 dark:hover:bg-surface-700 transition-colors"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
<div className="bg-gradient-to-r from-primary-500 to-accent-500 text-white p-2 rounded-xl">
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<div>
<h1 className="text-lg font-bold text-surface-900 dark:text-white">TCG Vault</h1>
<p className="text-xs text-surface-600 dark:text-surface-400">
Hi, {user?.firstName || user?.username}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="p-2 rounded-xl bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-300 hover:bg-surface-200 dark:hover:bg-surface-700 transition-colors"
>
{effectiveTheme === 'dark' ? (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clipRule="evenodd" />
</svg>
) : (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>
)}
</button>
{/* User Avatar */}
<button
onClick={() => setShowUserMenu(true)}
className="relative p-1"
>
<div className="w-8 h-8 bg-gradient-to-r from-primary-500 to-accent-500 rounded-xl flex items-center justify-center text-white font-semibold text-sm">
{user?.firstName?.[0] || user?.username?.[0]?.toUpperCase() || 'U'}
</div>
{isAdmin() && (
<div className="absolute -top-1 -right-1 w-3 h-3 bg-yellow-400 rounded-full border border-white dark:border-surface-900"></div>
)}
</button>
</div>
</div>
</header>
{/* Mobile Sidebar */}
{sidebarOpen && (
<div className="fixed inset-0 z-50 lg:hidden">
<div className="fixed inset-0 bg-black/50" onClick={() => setSidebarOpen(false)}></div>
<div className="fixed left-0 top-0 bottom-0 w-64 bg-white dark:bg-surface-800 border-r border-surface-200 dark:border-surface-700 transform transition-transform duration-300 ease-in-out">
<div className="p-6 border-b border-surface-200 dark:border-surface-700">
<div className="flex items-center justify-between">
<Link to="/dashboard" className="flex items-center space-x-3" onClick={() => setSidebarOpen(false)}>
<div className="bg-gradient-to-r from-primary-500 to-accent-500 text-white p-3 rounded-xl">
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
<path d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<div>
<h1 className="text-xl font-bold text-surface-900 dark:text-white">TCG Vault</h1>
<p className="text-sm text-surface-600 dark:text-surface-400">
Hi, {user?.firstName || user?.username}
</p>
</div>
</Link>
<button
onClick={() => setSidebarOpen(false)}
className="p-2 rounded-xl bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-300 hover:bg-surface-200 dark:hover:bg-surface-700 transition-colors"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<nav className="flex-1 p-4 space-y-2">
{navigation.map((item) => (
<Link
key={item.name}
to={item.href}
onClick={() => setSidebarOpen(false)}
className={`flex items-center space-x-3 px-4 py-3 rounded-xl text-sm font-medium transition-all duration-200 ${
isActive(item.href)
? 'bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300'
: 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-white hover:bg-surface-100 dark:hover:bg-surface-700'
}`}
>
<span className="text-lg">{item.icon}</span>
<span>{item.name}</span>
</Link>
))}
</nav>
<div className="p-4 border-t border-surface-200 dark:border-surface-700">
<div className="flex items-center space-x-3 p-3 rounded-xl bg-surface-50 dark:bg-surface-700">
<div className="w-10 h-10 bg-gradient-to-r from-primary-500 to-accent-500 rounded-xl flex items-center justify-center text-white font-semibold">
{user?.firstName?.[0] || user?.username?.[0]?.toUpperCase() || 'U'}
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-surface-900 dark:text-white truncate">
{user?.firstName && user?.lastName
? `${user.firstName} ${user.lastName}`
: user?.username}
</p>
<p className="text-xs text-surface-600 dark:text-surface-400 truncate">{user?.email}</p>
</div>
</div>
</div>
</div>
</div>
)}
{/* Bottom Navigation */}
<nav className="fixed bottom-0 left-0 right-0 z-50 bg-white dark:bg-surface-900 border-t border-surface-200 dark:border-surface-700 safe-area-inset-bottom">
<div className="relative flex items-end justify-around px-4 py-2">
{/* Home */}
<Link
to="/dashboard"
className={`flex flex-col items-center justify-center p-2 rounded-xl transition-all duration-200 ${
isActive('/dashboard')
? 'text-primary-600 dark:text-primary-400'
: 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-white'
}`}
>
<div className="mb-1">
{isActive('/dashboard') ? (
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</svg>
) : (
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
)}
</div>
<span className="text-xs font-medium">Home</span>
</Link>
{/* Cards */}
<Link
to="/cards"
className={`flex flex-col items-center justify-center p-2 rounded-xl transition-all duration-200 ${
isActive('/cards')
? 'text-primary-600 dark:text-primary-400'
: 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-white'
}`}
>
<div className="mb-1">
{isActive('/cards') ? (
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
) : (
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
)}
</div>
<span className="text-xs font-medium">Cards</span>
</Link>
{/* Scanner - Special Raised Button */}
<Link
to="/scanner"
className="relative flex flex-col items-center justify-center -mt-6 mb-2"
>
<div className={`w-14 h-14 rounded-full shadow-lg transition-all duration-200 flex items-center justify-center ${
isActive('/scanner')
? 'bg-gradient-to-r from-primary-600 to-accent-600 shadow-primary-500/25 shadow-xl'
: 'bg-gradient-to-r from-primary-500 to-accent-500 hover:from-primary-600 hover:to-accent-600 shadow-primary-500/20 hover:shadow-xl'
}`}>
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 13a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<span className="text-xs font-medium text-primary-600 dark:text-primary-400 mt-1">Scanner</span>
</Link>
{/* Collections */}
<Link
to="/collections"
className={`flex flex-col items-center justify-center p-2 rounded-xl transition-all duration-200 ${
isActive('/collections')
? 'text-primary-600 dark:text-primary-400'
: 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-white'
}`}
>
<div className="mb-1">
{isActive('/collections') ? (
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M7 4V2a1 1 0 011-1h8a1 1 0 011 1v2h3a1 1 0 110 2h-1v10a2 2 0 01-2 2H7a2 2 0 01-2-2V6H4a1 1 0 010-2h3zM9 4h6V3H9v1zm8 2H7v10h10V6z"/>
</svg>
) : (
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
)}
</div>
<span className="text-xs font-medium">Collections</span>
</Link>
{/* More */}
<button
onClick={() => setShowUserMenu(true)}
className="flex flex-col items-center justify-center p-2 rounded-xl transition-all duration-200 text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-white"
>
<div className="mb-1">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
</svg>
</div>
<span className="text-xs font-medium">More</span>
</button>
</div>
</nav>
{/* Page Content */}
<main className="pt-16 pb-20 px-4 max-w-md mx-auto">
<div className="animate-fade-in">
{children}
</div>
</main>
{/* User Menu Modal */}
{showUserMenu && (
<div className="fixed inset-0 z-50 bg-black/50" onClick={() => setShowUserMenu(false)}>
<div className="fixed bottom-0 left-0 right-0 bg-white dark:bg-surface-900 rounded-t-3xl p-6 safe-area-inset-bottom animate-slide-up">
<div className="w-12 h-1.5 bg-surface-300 dark:bg-surface-600 rounded-full mx-auto mb-6"></div>
<div className="flex items-center space-x-4 mb-6 p-4 bg-surface-50 dark:bg-surface-800 rounded-2xl">
<div className="w-12 h-12 bg-gradient-to-r from-primary-500 to-accent-500 rounded-xl flex items-center justify-center text-white font-semibold text-lg">
{user?.firstName?.[0] || user?.username?.[0]?.toUpperCase() || 'U'}
</div>
<div>
<p className="font-semibold text-surface-900 dark:text-white">
{user?.firstName && user?.lastName
? `${user.firstName} ${user.lastName}`
: user?.username}
</p>
<p className="text-sm text-surface-600 dark:text-surface-400">{user?.email}</p>
<div className="flex gap-1 mt-1">
{user?.roles.map((role) => (
<span
key={role}
className={`px-2 py-0.5 rounded-full text-xs font-medium ${
role === 'admin'
? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200'
: 'bg-primary-100 text-primary-800 dark:bg-primary-900 dark:text-primary-200'
}`}
>
{role}
</span>
))}
</div>
</div>
</div>
<div className="space-y-2 mb-6">
<Link
to="/decks"
onClick={() => setShowUserMenu(false)}
className="flex items-center space-x-3 p-3 rounded-xl hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors"
>
<svg className="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
<span className="text-surface-900 dark:text-white font-medium">Decks</span>
</Link>
<Link
to="/settings"
onClick={() => setShowUserMenu(false)}
className="flex items-center space-x-3 p-3 rounded-xl hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors"
>
<svg className="w-5 h-5 text-surface-600 dark:text-surface-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span className="text-surface-900 dark:text-white font-medium">Settings</span>
</Link>
{isAdmin() && (
<Link
to="/admin"
onClick={() => setShowUserMenu(false)}
className="flex items-center space-x-3 p-3 rounded-xl hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors"
>
<svg className="w-5 h-5 text-yellow-600 dark:text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
<span className="text-yellow-700 dark:text-yellow-300 font-medium">Admin Panel</span>
</Link>
)}
</div>
<button
onClick={handleLogout}
className="w-full flex items-center justify-center space-x-2 p-3 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-xl hover:bg-red-100 dark:hover:bg-red-900/30 transition-colors font-medium"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
<span>Sign Out</span>
</button>
</div>
</div>
)}
</div>
{/* Click outside to close menus */}
{(showUserMenu || sidebarOpen) && (
<div
className="fixed inset-0 z-40"
onClick={() => {
setShowUserMenu(false);
setSidebarOpen(false);
}}
/>
)}
</div>
);
};
export default ResponsiveLayout;