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.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
fix: clarify mobile slot card hierarchy
|
feat: combine mobile navigation and account menu
|
||||||
|
|
||||||
Prioritize store identity over booking controls and make card boundaries and
|
Replace the mobile profile card with a compact page header, account menu, and
|
||||||
booking states easier to scan on mobile.
|
contextual dashboard toolbar while preserving desktop behavior.
|
||||||
|
|||||||
@@ -868,7 +868,12 @@ function App() {
|
|||||||
<>
|
<>
|
||||||
<div className="min-h-screen bg-gray-100 py-6">
|
<div className="min-h-screen bg-gray-100 py-6">
|
||||||
<div className="max-w-6xl mx-auto px-4">
|
<div className="max-w-6xl mx-auto px-4">
|
||||||
<NavigationTabs isAdmin={session?.isAdmin} onProtectedNavigate={requestNavigation} />
|
<NavigationTabs
|
||||||
|
isAdmin={session?.isAdmin}
|
||||||
|
onProtectedNavigate={requestNavigation}
|
||||||
|
profileName={session?.profile?.name}
|
||||||
|
onLogout={handleLogout}
|
||||||
|
/>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={dashboardContent} />
|
<Route path="/" element={dashboardContent} />
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
@@ -760,7 +760,7 @@ const DashboardView = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 max-w-6xl mx-auto bg-white shadow-lg rounded-lg mt-4">
|
<div className="p-4 max-w-6xl mx-auto bg-white shadow-lg rounded-lg mt-4">
|
||||||
<h1 className="text-2xl font-bold mb-4 text-center text-gray-800">Foodsharing Pickup Manager</h1>
|
<h1 className="dashboard-page-title text-2xl font-bold mb-4 text-center text-gray-800">Foodsharing Pickup Manager</h1>
|
||||||
<div className="dashboard-summary-card dashboard-session bg-blue-50 border border-blue-100 rounded-lg p-4 mb-4 shadow">
|
<div className="dashboard-summary-card dashboard-session bg-blue-50 border border-blue-100 rounded-lg p-4 mb-4 shadow">
|
||||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
||||||
<div className="dashboard-session__identity">
|
<div className="dashboard-session__identity">
|
||||||
@@ -803,6 +803,25 @@ const DashboardView = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="dashboard-mobile-toolbar" aria-label="Slot-Werkzeuge">
|
||||||
|
<button type="button" className="dashboard-mobile-toolbar__refresh" onClick={() => onRefresh({ block: false })}>
|
||||||
|
Betriebe aktualisieren
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`dashboard-mobile-toolbar__notifications ${notificationPanelOpen ? 'is-active' : ''}`}
|
||||||
|
onClick={onToggleNotificationPanel}
|
||||||
|
title="Benachrichtigungen konfigurieren"
|
||||||
|
aria-label="Benachrichtigungen konfigurieren"
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
|
||||||
|
<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 0 0 2.573 1.066c1.543-.89 3.31.877 2.42 2.42a1.724 1.724 0 0 0 1.065 2.572c1.757.426 1.757 2.924 0 3.35a1.724 1.724 0 0 0-1.066 2.573c.89 1.543-.877 3.31-2.42 2.42a1.724 1.724 0 0 0-2.572 1.065c-.426 1.757-2.924 1.757-3.35 0a1.724 1.724 0 0 0-2.573-1.066c-1.543.89-3.31-.877-2.42-2.42a1.724 1.724 0 0 0-1.065-2.572c-1.757-.426-1.757-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.89-1.543.877-3.31 2.42-2.42.996.575 2.273.155 2.573-1.065z" />
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
{notificationLoading && <span className="dashboard-mobile-toolbar__loading">Lade...</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
{notificationPanelOpen && (
|
{notificationPanelOpen && (
|
||||||
<NotificationPanel
|
<NotificationPanel
|
||||||
error={notificationError}
|
error={notificationError}
|
||||||
|
|||||||
@@ -2,81 +2,43 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-mobile-toolbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.dashboard-session {
|
.dashboard-session {
|
||||||
margin: 0.75rem 0 1rem;
|
display: none;
|
||||||
padding: 0.75rem;
|
|
||||||
border: 1px solid #dbe4ee;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: #f8fafc;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-session > div {
|
.dashboard-page-title {
|
||||||
display: grid;
|
display: none;
|
||||||
gap: 0.65rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-session__identity {
|
.dashboard-mobile-toolbar {
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: 0.4rem;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-session__label,
|
|
||||||
.dashboard-session__name {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-session__label {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
letter-spacing: 0;
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-session__name {
|
|
||||||
overflow: hidden;
|
|
||||||
color: #1f2937;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-session__actions {
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||||
gap: 0.45rem;
|
gap: 0.45rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin: 0.75rem 0 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-session__refresh,
|
.dashboard-mobile-toolbar__refresh,
|
||||||
.dashboard-session__logout,
|
.dashboard-mobile-toolbar__notifications {
|
||||||
.dashboard-session__notifications {
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-height: 2.35rem;
|
min-height: 2.35rem;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-session__refresh {
|
.dashboard-mobile-toolbar__refresh {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid #2563eb;
|
border: 1px solid #2563eb;
|
||||||
background: #2563eb;
|
background: #2563eb;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-session__logout {
|
.dashboard-mobile-toolbar__notifications {
|
||||||
width: auto;
|
|
||||||
border: 1px solid #cbd5e1;
|
|
||||||
padding: 0.45rem 0.65rem;
|
|
||||||
background: #fff;
|
|
||||||
color: #475569;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-session__notifications {
|
|
||||||
width: 2.35rem;
|
width: 2.35rem;
|
||||||
height: 2.35rem;
|
height: 2.35rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -85,11 +47,22 @@
|
|||||||
color: #475569;
|
color: #475569;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-session__notifications svg {
|
.dashboard-mobile-toolbar__notifications svg {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-mobile-toolbar__notifications.is-active {
|
||||||
|
border-color: #2563eb;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-mobile-toolbar__loading {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mobile-config-list {
|
.mobile-config-list {
|
||||||
display: block;
|
display: block;
|
||||||
padding-bottom: 5.5rem;
|
padding-bottom: 5.5rem;
|
||||||
|
|||||||
150
src/components/NavigationTabs.css
Normal file
150
src/components/NavigationTabs.css
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
.app-navigation {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__mobile-header,
|
||||||
|
.app-navigation__mobile-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__desktop {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border: 1px solid #dbe4ee;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__desktop-link {
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.45rem 0.65rem;
|
||||||
|
color: #475569;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__desktop-link:hover,
|
||||||
|
.app-navigation__desktop-link.is-active {
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.app-navigation {
|
||||||
|
margin: 0 -0.25rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__desktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__mobile-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: 2.9rem;
|
||||||
|
padding: 0 0.25rem 0 0.5rem;
|
||||||
|
border-bottom: 1px solid #cbd5e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__current-page {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #1f2937;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 650;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__menu-toggle {
|
||||||
|
display: grid;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
place-items: center;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #fff;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__menu-toggle svg {
|
||||||
|
width: 1.2rem;
|
||||||
|
height: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__mobile-menu {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__mobile-links {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__mobile-link {
|
||||||
|
padding: 0.7rem 0.75rem;
|
||||||
|
border: 1px solid #dbe4ee;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__mobile-link.is-active {
|
||||||
|
border-color: #2563eb;
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #1d4ed8;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__account {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
border-top: 1px solid #dbe4ee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__account div {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__account span {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__account strong {
|
||||||
|
overflow: hidden;
|
||||||
|
color: #1f2937;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-navigation__account button {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-height: 2.25rem;
|
||||||
|
border: 1px solid #cbd5e1;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 0.4rem 0.65rem;
|
||||||
|
background: #fff;
|
||||||
|
color: #475569;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
import './NavigationTabs.css';
|
||||||
|
|
||||||
const NavigationTabs = ({ isAdmin, onProtectedNavigate }) => {
|
const NavigationTabs = ({ isAdmin, onProtectedNavigate, profileName, onLogout }) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
|
|
||||||
const tabs = [
|
const tabs = useMemo(() => {
|
||||||
{ to: '/', label: 'Slots buchen' },
|
const items = [
|
||||||
{ to: '/store-watch', label: 'Betriebs-Monitoring' },
|
{ to: '/', label: 'Slots buchen' },
|
||||||
{ to: '/journal', label: 'Abhol-Journal' }
|
{ to: '/store-watch', label: 'Betriebs-Monitoring' },
|
||||||
];
|
{ to: '/journal', label: 'Abhol-Journal' }
|
||||||
if (isAdmin) {
|
];
|
||||||
tabs.push({ to: '/debug', label: 'Debug' });
|
if (isAdmin) {
|
||||||
tabs.push({ to: '/admin', label: 'Admin' });
|
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) => {
|
const handleClick = (event, to) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -34,50 +40,34 @@ const NavigationTabs = ({ isAdmin, onProtectedNavigate }) => {
|
|||||||
setMobileOpen(false);
|
setMobileOpen(false);
|
||||||
}, [location.pathname]);
|
}, [location.pathname]);
|
||||||
|
|
||||||
const renderLink = (tab, className, options = {}) => {
|
const renderLink = (tab, className) => {
|
||||||
const isActive = location.pathname === tab.to;
|
const isActive = location.pathname === tab.to;
|
||||||
const combinedClassName = typeof className === 'function' ? className(isActive) : className;
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
key={tab.to}
|
key={tab.to}
|
||||||
to={tab.to}
|
to={tab.to}
|
||||||
onClick={(event) => handleClick(event, tab.to)}
|
onClick={(event) => handleClick(event, tab.to)}
|
||||||
className={combinedClassName}
|
className={`${className}${isActive ? ' is-active' : ''}`}
|
||||||
aria-current={isActive ? 'page' : undefined}
|
aria-current={isActive ? 'page' : undefined}
|
||||||
>
|
>
|
||||||
<span className="relative z-10">{tab.label}</span>
|
{tab.label}
|
||||||
{options.showUnderline ? (
|
|
||||||
<span
|
|
||||||
className={`absolute inset-x-3 -bottom-1 h-0.5 rounded-full transition-all ${
|
|
||||||
isActive ? 'bg-blue-500 opacity-100' : 'bg-blue-200 opacity-0 group-hover:opacity-60'
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="mb-4" aria-label="Navigation">
|
<nav className="app-navigation" aria-label="Navigation">
|
||||||
<div className="flex items-center justify-between sm:hidden">
|
<div className="app-navigation__mobile-header">
|
||||||
<span className="text-sm font-semibold text-gray-600">Navigation</span>
|
<span className="app-navigation__current-page">{activeTab.label}</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-3 py-2 text-gray-700 shadow-sm"
|
className="app-navigation__menu-toggle"
|
||||||
|
aria-label={mobileOpen ? 'Navigation schließen' : 'Navigation öffnen'}
|
||||||
aria-expanded={mobileOpen}
|
aria-expanded={mobileOpen}
|
||||||
aria-controls="mobile-navigation"
|
aria-controls="mobile-navigation"
|
||||||
onClick={() => setMobileOpen((open) => !open)}
|
onClick={() => setMobileOpen((open) => !open)}
|
||||||
>
|
>
|
||||||
<svg
|
<svg viewBox="0 0 24 24" stroke="currentColor" fill="none" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||||
className="h-5 w-5"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="none"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
{mobileOpen ? (
|
{mobileOpen ? (
|
||||||
<>
|
<>
|
||||||
<line x1="18" y1="6" x2="6" y2="18" />
|
<line x1="18" y1="6" x2="6" y2="18" />
|
||||||
@@ -93,35 +83,24 @@ const NavigationTabs = ({ isAdmin, onProtectedNavigate }) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
id="mobile-navigation"
|
{mobileOpen && (
|
||||||
className={`mt-3 flex flex-col gap-2 sm:hidden ${mobileOpen ? '' : 'hidden'}`}
|
<div id="mobile-navigation" className="app-navigation__mobile-menu">
|
||||||
>
|
<div className="app-navigation__mobile-links">
|
||||||
{tabs.map((tab) =>
|
{tabs.map((tab) => renderLink(tab, 'app-navigation__mobile-link'))}
|
||||||
renderLink(
|
</div>
|
||||||
tab,
|
<div className="app-navigation__account">
|
||||||
(isActive) =>
|
<div>
|
||||||
`px-4 py-3 rounded-md border text-left transition-colors ${
|
<span>Angemeldet</span>
|
||||||
isActive
|
<strong>{profileName || 'Profil'}</strong>
|
||||||
? 'bg-blue-500 text-white border-blue-600'
|
</div>
|
||||||
: 'bg-white text-gray-700 border-gray-300 hover:border-blue-400'
|
<button type="button" onClick={onLogout}>Logout</button>
|
||||||
}`
|
</div>
|
||||||
)
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
<div className="hidden items-center gap-6 rounded-xl border border-gray-200 bg-white/80 px-3 py-2 shadow-sm sm:flex">
|
<div className="app-navigation__desktop">
|
||||||
{tabs.map((tab) =>
|
{tabs.map((tab) => renderLink(tab, 'app-navigation__desktop-link'))}
|
||||||
renderLink(
|
|
||||||
tab,
|
|
||||||
(isActive) =>
|
|
||||||
`group relative rounded-md px-2 pb-2 pt-1 text-sm font-semibold tracking-tight transition-colors ${
|
|
||||||
isActive
|
|
||||||
? 'text-blue-600 bg-blue-50/70'
|
|
||||||
: 'text-gray-600 hover:bg-gray-100/80 hover:text-gray-900'
|
|
||||||
}`,
|
|
||||||
{ showUnderline: true }
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
|
|||||||
28
src/components/NavigationTabs.test.js
Normal file
28
src/components/NavigationTabs.test.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import NavigationTabs from './NavigationTabs';
|
||||||
|
|
||||||
|
describe('NavigationTabs', () => {
|
||||||
|
it('opens the mobile menu with account actions', () => {
|
||||||
|
const onLogout = jest.fn();
|
||||||
|
render(<NavigationTabs profileName="Meik" onLogout={onLogout} />);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Navigation öffnen' }));
|
||||||
|
|
||||||
|
expect(screen.getByText('Meik')).toBeInTheDocument();
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Logout' }));
|
||||||
|
expect(onLogout).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses the existing protected navigation callback', () => {
|
||||||
|
const onProtectedNavigate = jest.fn();
|
||||||
|
render(<NavigationTabs onProtectedNavigate={onProtectedNavigate} />);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: 'Navigation öffnen' }));
|
||||||
|
fireEvent.click(screen.getAllByText('Betriebs-Monitoring')[0]);
|
||||||
|
|
||||||
|
expect(onProtectedNavigate).toHaveBeenCalledWith(
|
||||||
|
'zur Seite "Betriebs-Monitoring" zu wechseln',
|
||||||
|
expect.any(Function)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user