Files
Pickup-Config/src/components/NavigationTabs.js
Meik bc0c4c750c feat: combine mobile navigation and account menu
Replace the mobile profile card with a compact page header, account menu, and
contextual dashboard toolbar while preserving desktop behavior.
2026-08-05 19:30:10 +02:00

110 lines
3.4 KiB
JavaScript

import { useEffect, useMemo, useState } from 'react';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import './NavigationTabs.css';
const NavigationTabs = ({ isAdmin, onProtectedNavigate, profileName, onLogout }) => {
const location = useLocation();
const navigate = useNavigate();
const [mobileOpen, setMobileOpen] = useState(false);
const tabs = useMemo(() => {
const items = [
{ to: '/', label: 'Slots buchen' },
{ to: '/store-watch', label: 'Betriebs-Monitoring' },
{ to: '/journal', label: 'Abhol-Journal' }
];
if (isAdmin) {
items.push({ to: '/debug', label: 'Debug' });
items.push({ to: '/admin', label: 'Admin' });
}
return items;
}, [isAdmin]);
const activeTab = tabs.find((tab) => tab.to === location.pathname) || tabs[0];
const handleClick = (event, to) => {
event.preventDefault();
if (to === location.pathname) {
return;
}
const label = tabs.find((tab) => tab.to === to)?.label || '';
const proceed = () => navigate(to);
if (onProtectedNavigate) {
onProtectedNavigate(`zur Seite "${label}" zu wechseln`, proceed);
return;
}
proceed();
};
useEffect(() => {
setMobileOpen(false);
}, [location.pathname]);
const renderLink = (tab, className) => {
const isActive = location.pathname === tab.to;
return (
<Link
key={tab.to}
to={tab.to}
onClick={(event) => handleClick(event, tab.to)}
className={`${className}${isActive ? ' is-active' : ''}`}
aria-current={isActive ? 'page' : undefined}
>
{tab.label}
</Link>
);
};
return (
<nav className="app-navigation" aria-label="Navigation">
<div className="app-navigation__mobile-header">
<span className="app-navigation__current-page">{activeTab.label}</span>
<button
type="button"
className="app-navigation__menu-toggle"
aria-label={mobileOpen ? 'Navigation schließen' : 'Navigation öffnen'}
aria-expanded={mobileOpen}
aria-controls="mobile-navigation"
onClick={() => setMobileOpen((open) => !open)}
>
<svg viewBox="0 0 24 24" stroke="currentColor" fill="none" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
{mobileOpen ? (
<>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</>
) : (
<>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="3" y1="12" x2="21" y2="12" />
<line x1="3" y1="18" x2="21" y2="18" />
</>
)}
</svg>
</button>
</div>
{mobileOpen && (
<div id="mobile-navigation" className="app-navigation__mobile-menu">
<div className="app-navigation__mobile-links">
{tabs.map((tab) => renderLink(tab, 'app-navigation__mobile-link'))}
</div>
<div className="app-navigation__account">
<div>
<span>Angemeldet</span>
<strong>{profileName || 'Profil'}</strong>
</div>
<button type="button" onClick={onLogout}>Logout</button>
</div>
</div>
)}
<div className="app-navigation__desktop">
{tabs.map((tab) => renderLink(tab, 'app-navigation__desktop-link'))}
</div>
</nav>
);
};
export default NavigationTabs;