Files
schichtplanung/frontend/src/components/Navbar.jsx
T
2026-07-31 10:08:13 +02:00

227 lines
9.2 KiB
React

/* Hallmark · pre-emit critique: P5 H5 E5 S5 R5 V5 */
/* Hallmark · redesign: Navbar · studied-DNA: https://inihaus.de · nav: N1b Architectural Masthead */
import React from 'react';
import { Calendar, User, LogOut, Sparkles, Plus, Layers, Settings, Edit3, Home, CalendarDays, TableProperties, Sun, Moon, Monitor } from 'lucide-react';
export default function Navbar({
branding,
user,
activeTab,
onChangeTab,
themeMode,
onChangeThemeMode,
onLogout,
onOpenAuth,
onOpenCreateEvent,
onOpenTemplates,
onOpenProfile,
onOpenAdmin,
pwaInstallPrompt,
onInstallPwa
}) {
const primaryColor = branding?.primary_color || 'var(--brand-primary)';
const cycleTheme = () => {
if (themeMode === 'dark') onChangeThemeMode('light');
else if (themeMode === 'light') onChangeThemeMode('auto');
else onChangeThemeMode('dark');
};
return (
<header className="bg-surface border-b border-grid sticky top-0 z-40">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between gap-4">
{/* Brand Section */}
<div className="flex items-center space-x-3 shrink-0">
<div
onClick={() => onChangeTab('home')}
style={{ backgroundColor: primaryColor }}
className="w-8 h-8 rounded-sm flex items-center justify-center text-white font-bold cursor-pointer shadow-sm"
>
{branding?.logo_url ? (
<img src={branding.logo_url} alt="Logo" className="w-4 h-4 object-contain" />
) : (
<Calendar className="w-4 h-4" />
)}
</div>
<div onClick={() => onChangeTab('home')} className="cursor-pointer">
<h1 className="font-serif text-base font-bold tracking-tight text-main leading-none">
{branding?.app_name || "Schichtplaner"}
</h1>
<div className="text-[10px] font-mono text-muted mt-1 uppercase tracking-wider flex items-center gap-1.5">
{user ? (
<span className="text-emerald-500 font-semibold">[ {user.display_name || user.username} ]</span>
) : (
<span className="text-amber-500 font-semibold">[ GAST-MODUS ]</span>
)}
</div>
</div>
</div>
{/* Center Navigation Tabs (Clean Hallmark N1b Style) */}
<nav className="hidden md:flex items-center gap-2">
<button
onClick={() => onChangeTab('home')}
className={`px-3 py-1.5 rounded-sm text-xs font-mono transition flex items-center gap-1.5 border ${
activeTab === 'home'
? 'bg-surface-hover text-main font-bold border-grid'
: 'text-muted hover:text-main border-transparent'
}`}
>
<Home className="w-3.5 h-3.5" /> Startseite
</button>
<button
onClick={() => onChangeTab('calendar')}
className={`px-3 py-1.5 rounded-sm text-xs font-mono transition flex items-center gap-1.5 border ${
activeTab === 'calendar'
? 'bg-surface-hover text-main font-bold border-grid'
: 'text-muted hover:text-main border-transparent'
}`}
>
<CalendarDays className="w-3.5 h-3.5" /> Kalender
</button>
{(user?.is_admin_user || user?.is_staff || user?.is_superuser) && (
<button
onClick={() => onChangeTab('admin')}
className={`px-3 py-1.5 rounded-sm text-xs font-mono transition flex items-center gap-1.5 border ${
activeTab === 'admin'
? 'bg-surface-hover text-main font-bold border-grid'
: 'text-muted hover:text-main border-transparent'
}`}
>
<Settings className="w-3.5 h-3.5 text-indigo-400" /> Admin
</button>
)}
</nav>
{/* Right Action Controls */}
<div className="flex items-center space-x-2">
{/* Theme Mode Button */}
<button
onClick={cycleTheme}
className="h-8 px-2.5 rounded-sm text-xs font-mono bg-subtle hover:bg-surface-hover text-main border border-grid transition flex items-center gap-1.5"
title={`Design-Modus: ${themeMode.toUpperCase()}`}
>
{themeMode === 'dark' ? (
<>
<Moon className="w-3.5 h-3.5 text-indigo-400" />
<span className="hidden lg:inline text-[11px] font-bold">DARK</span>
</>
) : themeMode === 'light' ? (
<>
<Sun className="w-3.5 h-3.5 text-amber-500" />
<span className="hidden lg:inline text-[11px] font-bold">LIGHT</span>
</>
) : (
<>
<Monitor className="w-3.5 h-3.5 text-blue-500" />
<span className="hidden lg:inline text-[11px] font-bold">AUTO</span>
</>
)}
</button>
{pwaInstallPrompt && (
<button
onClick={onInstallPwa}
className="h-8 px-2.5 rounded-sm text-xs font-mono bg-emerald-500/10 text-emerald-500 border border-emerald-500/20 hover:bg-emerald-500/20 transition flex items-center gap-1"
>
<Sparkles className="w-3 h-3" /> PWA
</button>
)}
{user ? (
<>
<button
onClick={onOpenCreateEvent}
style={{ backgroundColor: primaryColor }}
className="h-8 px-3 rounded-sm text-xs font-mono font-bold text-white transition flex items-center gap-1 shadow-sm hover:brightness-110"
>
<Plus className="w-3.5 h-3.5" /> Event
</button>
<button
onClick={onOpenTemplates}
className="h-8 px-2.5 rounded-sm text-xs font-mono bg-subtle hover:bg-surface-hover text-main border border-grid transition hidden sm:flex items-center gap-1"
title="Vorlagen"
>
<Layers className="w-3.5 h-3.5 text-muted" /> Vorlagen
</button>
<button
onClick={onOpenProfile}
className="h-8 px-2.5 rounded-sm text-xs font-mono bg-subtle hover:bg-surface-hover text-main border border-grid transition flex items-center gap-1"
title="Profil & Namen ändern"
>
<Edit3 className="w-3.5 h-3.5 text-amber-500" /> Profil
</button>
{(user.is_admin_user || user.is_staff || user.is_superuser) && (
<button
onClick={() => onChangeTab('admin')}
className={`h-8 px-2.5 rounded-sm text-xs font-mono transition flex items-center gap-1 border ${
activeTab === 'admin'
? 'bg-indigo-500/20 text-indigo-300 border-indigo-500/40 font-bold'
: 'bg-indigo-500/10 hover:bg-indigo-500/20 text-indigo-400 border-indigo-500/30'
}`}
title="Admin-Zentrale"
>
<Settings className="w-3.5 h-3.5" /> Admin
</button>
)}
<div className="h-4 w-px bg-grid mx-1"></div>
<button
onClick={onLogout}
className="h-8 w-8 rounded-sm text-muted hover:text-red-500 hover:bg-red-500/10 border border-transparent hover:border-red-500/20 transition flex items-center justify-center"
title="Abmelden"
>
<LogOut className="w-3.5 h-3.5" />
</button>
</>
) : (
<button
onClick={onOpenAuth}
style={{ backgroundColor: primaryColor }}
className="h-8 px-3.5 rounded-sm text-xs font-mono font-bold text-white transition hover:brightness-110 flex items-center gap-1.5 shadow-sm"
>
<User className="w-3.5 h-3.5" /> Anmelden
</button>
)}
</div>
</div>
{/* Mobile Navigation */}
<div className="flex md:hidden items-center justify-around border-t border-grid py-2 bg-subtle text-xs font-mono">
<button
onClick={() => onChangeTab('home')}
className={`flex items-center gap-1 px-3 py-1.5 rounded-sm border ${
activeTab === 'home' ? 'text-main font-bold bg-surface border-grid' : 'text-muted border-transparent'
}`}
>
<Home className="w-3.5 h-3.5" /> Start
</button>
<button
onClick={() => onChangeTab('calendar')}
className={`flex items-center gap-1 px-3 py-1.5 rounded-sm border ${
activeTab === 'calendar' ? 'text-main font-bold bg-surface border-grid' : 'text-muted border-transparent'
}`}
>
<CalendarDays className="w-3.5 h-3.5" /> Termine
</button>
<button
onClick={() => onChangeTab('schedule')}
className={`flex items-center gap-1 px-3 py-1.5 rounded-sm border ${
activeTab === 'schedule' ? 'text-main font-bold bg-surface border-grid' : 'text-muted border-transparent'
}`}
>
<TableProperties className="w-3.5 h-3.5" /> Schichtplan
</button>
</div>
</header>
);
}