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:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lageplan",
|
"name": "lageplan",
|
||||||
"version": "1.4.14",
|
"version": "1.4.15",
|
||||||
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
|
DropdownMenuLabel,
|
||||||
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu'
|
} from '@/components/ui/dropdown-menu'
|
||||||
import {
|
import {
|
||||||
@@ -184,7 +186,7 @@ export function Topbar({
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant={presentationLocked ? 'default' : 'outline'}
|
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}
|
onClick={onTogglePresentationLock}
|
||||||
title={presentationLocked ? 'Präsentationsmodus deaktivieren' : 'Präsentationsmodus aktivieren'}
|
title={presentationLocked ? 'Präsentationsmodus deaktivieren' : 'Präsentationsmodus aktivieren'}
|
||||||
>
|
>
|
||||||
@@ -205,7 +207,7 @@ export function Topbar({
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => onNewProject('UEBUNG')}
|
onClick={() => onNewProject('UEBUNG')}
|
||||||
variant="outline"
|
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"
|
title="Neue Übung erstellen"
|
||||||
>
|
>
|
||||||
<GraduationCap className="w-5 h-5 md:mr-1" />
|
<GraduationCap className="w-5 h-5 md:mr-1" />
|
||||||
@@ -214,7 +216,7 @@ export function Topbar({
|
|||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<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" />
|
<MoreVertical className="w-5 h-5 md:mr-1" />
|
||||||
<span className="hidden lg:inline">Menü</span>
|
<span className="hidden lg:inline">Menü</span>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -347,36 +349,102 @@ export function Topbar({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Mobile: overflow menu with all secondary actions */}
|
{/* Mobile: EIN Menü mit allen Aktionen (ersetzt die früheren zwei getrennten Menüs) */}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<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" />
|
<MoreVertical className="w-5 h-5" />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</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 && (
|
{project && onEndProject && (
|
||||||
<DropdownMenuItem onClick={onEndProject} className="text-red-600 focus:text-red-700">
|
<DropdownMenuItem onClick={onEndProject} className="text-red-600 focus:text-red-700">
|
||||||
<CheckCircle2 className="w-4 h-4 mr-2" />
|
<CheckCircle2 className="w-4 h-4 mr-2" />
|
||||||
{project.mode === 'UEBUNG' ? 'Übung beenden' : 'Einsatz beenden'}
|
{project.mode === 'UEBUNG' ? 'Übung beenden' : 'Einsatz beenden'}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
<DropdownMenuItem onClick={onToggleTheme}>
|
<DropdownMenuItem onClick={() => onNewProject('UEBUNG')}>
|
||||||
{isDarkMode ? <Sun className="w-4 h-4 mr-2" /> : <Moon className="w-4 h-4 mr-2" />}
|
<GraduationCap className="w-4 h-4 mr-2" />
|
||||||
{isDarkMode ? 'Tagmodus' : 'Nachtmodus'}
|
Neue Übung
|
||||||
</DropdownMenuItem>
|
</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}>
|
<DropdownMenuItem onClick={onToggleFullscreen}>
|
||||||
{isFullscreen ? <Minimize className="w-4 h-4 mr-2" /> : <Maximize className="w-4 h-4 mr-2" />}
|
{isFullscreen ? <Minimize className="w-4 h-4 mr-2" /> : <Maximize className="w-4 h-4 mr-2" />}
|
||||||
{isFullscreen ? 'Vollbild verlassen' : 'Vollbild'}
|
{isFullscreen ? 'Vollbild verlassen' : 'Vollbild'}
|
||||||
</DropdownMenuItem>
|
</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)}>
|
<DropdownMenuItem onClick={() => setIsHoseSettingsOpen(true)}>
|
||||||
<Settings className="w-4 h-4 mr-2" />
|
<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>
|
</DropdownMenuItem>
|
||||||
{onLogout && (
|
{onLogout && (
|
||||||
<DropdownMenuItem onClick={onLogout} className="text-destructive">
|
<DropdownMenuItem onClick={onLogout} className="text-destructive focus:text-destructive">
|
||||||
<LogOut className="w-4 h-4 mr-2" />
|
<LogOut className="w-4 h-4 mr-2" />
|
||||||
Abmelden {userName && `(${userName})`}
|
Abmelden
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user