v1.3.0: Refactoring Phase 3+4, Symbol-Verwaltung Redesign, Schlauch-Labels Fix

- Refactoring: Error Boundaries, apiFetch Wrapper, Socket Status-Tracking
- Refactoring: UI Kontrast (theme-aware colors), unused imports bereinigt
- Symbol-Verwaltung: Neues Split-Panel (Meine Symbole + Bibliothek)
- Symbol-Verwaltung: Umbenennen (TLF rot/blau), Duplikate erlaubt
- Symbol-Verwaltung: Karten-Sidebar zeigt eigene Symbole bevorzugt
- Schlauch-Labels: Groessere Schrift (13px/10px), verschiebbar (Drag)
- Schema: TenantSymbol customName, sortOrder, unique constraint entfernt
- Open Source Referenz entfernt (kostenloses Projekt)
This commit is contained in:
Pepe Ziberi
2026-02-25 00:06:39 +01:00
parent 8ddeb7b377
commit 5917fa88ad
30 changed files with 3110 additions and 2120 deletions

View File

@@ -0,0 +1,74 @@
import { useEffect, useCallback } from 'react'
import type { DrawMode, DrawFeature } from '@/types'
interface UseKeyboardShortcutsOptions {
featuresRef: React.MutableRefObject<DrawFeature[]>
onUndo: () => void
onRedo: () => void
onSave: () => void
onDelete: (newFeatures: DrawFeature[]) => void
onToolChange: (mode: DrawMode) => void
onHelpOpen: () => void
}
const TOOL_SHORTCUTS: Record<string, DrawMode> = {
'v': 'select', 's': 'select',
'p': 'point',
'l': 'linestring',
'g': 'polygon',
'r': 'rectangle',
'c': 'circle',
'f': 'freehand',
'a': 'arrow',
't': 'text',
'e': 'eraser',
'm': 'measure',
'd': 'dangerzone',
}
export function useKeyboardShortcuts({
featuresRef,
onUndo,
onRedo,
onSave,
onDelete,
onToolChange,
onHelpOpen,
}: UseKeyboardShortcutsOptions) {
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
// Ignore when typing in inputs/textareas
const tag = (e.target as HTMLElement)?.tagName
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || (e.target as HTMLElement)?.isContentEditable) return
// ? or F1 → help
if (e.key === '?' || e.key === 'F1') { e.preventDefault(); onHelpOpen(); return }
// DEL / Backspace → delete selected feature(s)
if (e.key === 'Delete' || e.key === 'Backspace') {
e.preventDefault()
const current = featuresRef.current
const selected = current.filter(f => f.properties?._selected)
if (selected.length > 0) {
onDelete(current.filter(f => !f.properties?._selected))
}
return
}
// Ctrl/Cmd shortcuts
if (e.ctrlKey || e.metaKey) {
if (e.key === 'z' && e.shiftKey) { e.preventDefault(); onRedo(); return }
if (e.key === 'z') { e.preventDefault(); onUndo(); return }
if (e.key === 'y') { e.preventDefault(); onRedo(); return }
if (e.key === 's') { e.preventDefault(); onSave(); return }
return
}
// Tool shortcuts (single key, no modifier)
const mode = TOOL_SHORTCUTS[e.key.toLowerCase()]
if (mode) { e.preventDefault(); onToolChange(mode); return }
}
window.addEventListener('keydown', handleKeyDown)
return () => window.removeEventListener('keydown', handleKeyDown)
}, [featuresRef, onUndo, onRedo, onSave, onDelete, onToolChange, onHelpOpen])
}