Init v1.0.0
Some checks failed
Build & Push Docker Image / build (push) Failing after 53s

This commit is contained in:
2026-02-24 18:14:16 +01:00
commit 54d6ee553a
49 changed files with 10410 additions and 0 deletions

108
src/components/Sidebar.jsx Normal file
View File

@@ -0,0 +1,108 @@
import { NavLink } from 'react-router-dom';
import { LayoutDashboard, Settings, Shield, Video, X, Palette } from 'lucide-react';
import { useAuth } from '../contexts/AuthContext';
import { useLanguage } from '../contexts/LanguageContext';
import ThemeSelector from './ThemeSelector';
import { useState } from 'react';
export default function Sidebar({ open, onClose }) {
const { user } = useAuth();
const { t } = useLanguage();
const [themeOpen, setThemeOpen] = useState(false);
const navItems = [
{ to: '/dashboard', icon: LayoutDashboard, label: t('nav.dashboard') },
{ to: '/settings', icon: Settings, label: t('nav.settings') },
];
if (user?.role === 'admin') {
navItems.push({ to: '/admin', icon: Shield, label: t('nav.admin') });
}
const linkClasses = ({ isActive }) =>
`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${
isActive
? 'bg-th-accent text-th-accent-t shadow-sm'
: 'text-th-text-s hover:text-th-text hover:bg-th-hover'
}`;
return (
<>
<aside
className={`fixed top-0 left-0 z-40 h-full w-64 bg-th-side border-r border-th-border
transition-transform duration-300 ease-in-out
${open ? 'translate-x-0' : '-translate-x-full'} lg:translate-x-0`}
>
<div className="flex flex-col h-full">
{/* Logo */}
<div className="flex items-center justify-between h-16 px-4 border-b border-th-border">
<div className="flex items-center gap-2.5">
<div className="w-8 h-8 gradient-bg rounded-lg flex items-center justify-center">
<Video size={18} className="text-white" />
</div>
<div>
<h1 className="text-lg font-bold gradient-text">Redlight</h1>
</div>
</div>
<button
onClick={onClose}
className="lg:hidden p-1.5 rounded-lg hover:bg-th-hover text-th-text-s transition-colors"
>
<X size={18} />
</button>
</div>
{/* Navigation */}
<nav className="flex-1 px-3 py-4 space-y-1 overflow-y-auto">
<p className="px-3 mb-2 text-xs font-semibold text-th-text-s uppercase tracking-wider">
{t('nav.navigation')}
</p>
{navItems.map(item => (
<NavLink
key={item.to}
to={item.to}
className={linkClasses}
onClick={onClose}
>
<item.icon size={18} />
{item.label}
</NavLink>
))}
<div className="pt-4">
<p className="px-3 mb-2 text-xs font-semibold text-th-text-s uppercase tracking-wider">
{t('nav.appearance')}
</p>
<button
onClick={() => setThemeOpen(!themeOpen)}
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-th-text-s hover:text-th-text hover:bg-th-hover transition-all duration-200"
>
<Palette size={18} />
{t('nav.changeTheme')}
</button>
</div>
</nav>
{/* User info */}
<div className="p-4 border-t border-th-border">
<div className="flex items-center gap-3">
<div
className="w-9 h-9 rounded-full flex items-center justify-center text-white text-sm font-bold flex-shrink-0"
style={{ backgroundColor: user?.avatar_color || '#6366f1' }}
>
{user?.name?.[0]?.toUpperCase() || '?'}
</div>
<div className="min-w-0">
<p className="text-sm font-medium text-th-text truncate">{user?.name}</p>
<p className="text-xs text-th-text-s truncate">{user?.email}</p>
</div>
</div>
</div>
</div>
</aside>
{/* Theme Selector Modal */}
{themeOpen && <ThemeSelector onClose={() => setThemeOpen(false)} />}
</>
);
}