refactor(topbar): Handy-Menü entwirrt – ein einziges Menü statt zwei (v1.4.15)
- Mobil nur noch EIN ⋮-Menü (früher ☰ links + ⋮ rechts → verwirrend) - Topbar mobil reduziert auf: Logo · Speichern · Neuer Einsatz · Menü - Selten gebrauchte Buttons (Neue Übung, Präsentationsmodus) wandern ins Menü - Menü gruppiert mit Trennern: Einsatz/Übung · Export/Karte · Ansicht · System/Konto - Voller Funktionsumfang mobil erreichbar (Einsätze verwalten, Export, Admin, Schlaucheinstellungen, Tour, Kennwort, Abmelden) - Desktop-Layout unverändert Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import {
|
||||
@@ -184,7 +186,7 @@ export function Topbar({
|
||||
|
||||
<Button
|
||||
variant={presentationLocked ? 'default' : 'outline'}
|
||||
className={`h-9 md:h-10 px-2 md:px-3 text-sm ${presentationLocked ? 'bg-amber-600 hover:bg-amber-700 text-white border-amber-600' : ''}`}
|
||||
className={`hidden md:flex h-9 md:h-10 px-2 md:px-3 text-sm ${presentationLocked ? 'bg-amber-600 hover:bg-amber-700 text-white border-amber-600' : ''}`}
|
||||
onClick={onTogglePresentationLock}
|
||||
title={presentationLocked ? 'Präsentationsmodus deaktivieren' : 'Präsentationsmodus aktivieren'}
|
||||
>
|
||||
@@ -205,7 +207,7 @@ export function Topbar({
|
||||
<Button
|
||||
onClick={() => onNewProject('UEBUNG')}
|
||||
variant="outline"
|
||||
className="h-9 md:h-10 px-2 md:px-3 text-sm border-blue-500 text-blue-600 hover:bg-blue-50 dark:text-blue-400 dark:hover:bg-blue-950/40"
|
||||
className="hidden md:flex h-9 md:h-10 px-2 md:px-3 text-sm border-blue-500 text-blue-600 hover:bg-blue-50 dark:text-blue-400 dark:hover:bg-blue-950/40"
|
||||
title="Neue Übung erstellen"
|
||||
>
|
||||
<GraduationCap className="w-5 h-5 md:mr-1" />
|
||||
@@ -214,7 +216,7 @@ export function Topbar({
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" className="h-9 md:h-10 px-2 md:px-3 text-sm" title="Menü">
|
||||
<Button variant="outline" className="hidden md:flex h-9 md:h-10 px-2 md:px-3 text-sm" title="Menü">
|
||||
<MoreVertical className="w-5 h-5 md:mr-1" />
|
||||
<span className="hidden lg:inline">Menü</span>
|
||||
</Button>
|
||||
@@ -347,36 +349,102 @@ export function Topbar({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Mobile: overflow menu with all secondary actions */}
|
||||
{/* Mobile: EIN Menü mit allen Aktionen (ersetzt die früheren zwei getrennten Menüs) */}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" className="md:hidden h-9 px-2">
|
||||
<Button variant="outline" className="md:hidden h-9 px-2" title="Menü">
|
||||
<MoreVertical className="w-5 h-5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-48">
|
||||
<DropdownMenuContent align="end" className="w-56 max-h-[80vh] overflow-y-auto">
|
||||
{userName && (
|
||||
<>
|
||||
<DropdownMenuLabel className="text-xs text-muted-foreground font-normal">
|
||||
{userName}{userRole ? ` · ${userRole}` : ''}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Einsatz / Übung */}
|
||||
{project && onEndProject && (
|
||||
<DropdownMenuItem onClick={onEndProject} className="text-red-600 focus:text-red-700">
|
||||
<CheckCircle2 className="w-4 h-4 mr-2" />
|
||||
{project.mode === 'UEBUNG' ? 'Übung beenden' : 'Einsatz beenden'}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={onToggleTheme}>
|
||||
{isDarkMode ? <Sun className="w-4 h-4 mr-2" /> : <Moon className="w-4 h-4 mr-2" />}
|
||||
{isDarkMode ? 'Tagmodus' : 'Nachtmodus'}
|
||||
<DropdownMenuItem onClick={() => onNewProject('UEBUNG')}>
|
||||
<GraduationCap className="w-4 h-4 mr-2" />
|
||||
Neue Übung
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={handleOpenLoadDialog}>
|
||||
<List className="w-4 h-4 mr-2" />
|
||||
Einsätze verwalten
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
{/* Karte / Export */}
|
||||
<DropdownMenuItem onClick={() => handleExport('png')}>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Als PNG exportieren
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleExport('pdf')}>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Als PDF exportieren
|
||||
</DropdownMenuItem>
|
||||
{onClearAll && (
|
||||
<DropdownMenuItem onClick={onClearAll} className="text-destructive focus:text-destructive">
|
||||
<Eraser className="w-4 h-4 mr-2" />
|
||||
Zeichnung leeren
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{onTogglePresentationLock && (
|
||||
<DropdownMenuItem onClick={onTogglePresentationLock}>
|
||||
{presentationLocked ? <Lock className="w-4 h-4 mr-2" /> : <Unlock className="w-4 h-4 mr-2" />}
|
||||
{presentationLocked ? 'Präsentation: gesperrt' : 'Präsentationsmodus'}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
{/* Ansicht */}
|
||||
<DropdownMenuItem onClick={onToggleFullscreen}>
|
||||
{isFullscreen ? <Minimize className="w-4 h-4 mr-2" /> : <Maximize className="w-4 h-4 mr-2" />}
|
||||
{isFullscreen ? 'Vollbild verlassen' : 'Vollbild'}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={onToggleTheme}>
|
||||
{isDarkMode ? <Sun className="w-4 h-4 mr-2" /> : <Moon className="w-4 h-4 mr-2" />}
|
||||
{isDarkMode ? 'Tagmodus' : 'Nachtmodus'}
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
{/* System / Konto */}
|
||||
{(userRole === 'SERVER_ADMIN' || userRole === 'TENANT_ADMIN') && (
|
||||
<DropdownMenuItem onClick={() => window.location.href = '/admin'}>
|
||||
<Shield className="w-4 h-4 mr-2" />
|
||||
Administration
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={() => setIsHoseSettingsOpen(true)}>
|
||||
<Settings className="w-4 h-4 mr-2" />
|
||||
Einstellungen
|
||||
Schlaucheinstellungen
|
||||
</DropdownMenuItem>
|
||||
{onStartTour && (
|
||||
<DropdownMenuItem onClick={onStartTour}>
|
||||
<HelpCircle className="w-4 h-4 mr-2" />
|
||||
Tour starten
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={() => setShowPasswordDialog(true)}>
|
||||
<Key className="w-4 h-4 mr-2" />
|
||||
Kennwort ändern
|
||||
</DropdownMenuItem>
|
||||
{onLogout && (
|
||||
<DropdownMenuItem onClick={onLogout} className="text-destructive">
|
||||
<DropdownMenuItem onClick={onLogout} className="text-destructive focus:text-destructive">
|
||||
<LogOut className="w-4 h-4 mr-2" />
|
||||
Abmelden {userName && `(${userName})`}
|
||||
Abmelden
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
|
||||
Reference in New Issue
Block a user