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,69 @@
import { create } from 'zustand'
import type { Project, Feature, JournalEntry } from '@/types'
interface ProjectStore {
// Projekt-Daten
project: Project | null
features: Feature[] // Karten-Elemente (Symbole, Linien, Polygone)
journalEntries: JournalEntry[]
// Actions
setProject: (project: Project | null) => void
setFeatures: (features: Feature[]) => void
addFeature: (feature: Feature) => void
updateFeature: (id: string, updates: Partial<Feature>) => void
removeFeature: (id: string) => void
setJournalEntries: (entries: JournalEntry[]) => void
addJournalEntry: (entry: JournalEntry) => void
// Realtime-Sync Actions (werden von Socket.io getriggert)
syncFeatures: (features: Feature[]) => void
syncJournalEntry: (entry: JournalEntry) => void
}
export const useProjectStore = create<ProjectStore>((set) => ({
project: null,
features: [],
journalEntries: [],
setProject: (project) => set({ project }),
setFeatures: (features) => set({ features }),
addFeature: (feature) => set((state) => ({
features: [...state.features, feature]
})),
updateFeature: (id, updates) => set((state) => ({
features: state.features.map(f =>
f.id === id || f.properties?.id === id
? { ...f, properties: { ...f.properties, ...updates } }
: f
)
})),
removeFeature: (id) => set((state) => ({
features: state.features.filter(f => f.id !== id && f.properties?.id !== id)
})),
setJournalEntries: (entries) => set({ journalEntries: entries }),
addJournalEntry: (entry) => set((state) => ({
journalEntries: [...state.journalEntries, entry]
})),
syncFeatures: (features) => set({ features }),
syncJournalEntry: (entry) => set((state) => {
// Avoid duplicates
if (state.journalEntries.some(e => e.id === entry.id)) {
return {
journalEntries: state.journalEntries.map(e => e.id === entry.id ? entry : e)
}
}
return {
journalEntries: [...state.journalEntries, entry]
}
}),
}))

39
src/stores/tool-store.ts Normal file
View File

@@ -0,0 +1,39 @@
import { create } from 'zustand'
import type { DrawMode } from '@/types'
export type LineType = 'solid' | 'dashed' | 'dotted'
interface ToolStore {
activeTool: DrawMode | null
activeColor: string
lineType: LineType
lineWidth: number
selectedFeatureId: string | null
// Actions
setActiveTool: (tool: ToolStore['activeTool']) => void
setActiveColor: (color: string) => void
setLineType: (type: ToolStore['lineType']) => void
setLineWidth: (width: number) => void
selectFeature: (id: string | null) => void
resetTool: () => void
}
export const useToolStore = create<ToolStore>((set) => ({
activeTool: 'select',
activeColor: '#ff0000', // Default Rot
lineType: 'solid',
lineWidth: 3,
selectedFeatureId: null,
setActiveTool: (tool) => set({ activeTool: tool }),
setActiveColor: (color) => set({ activeColor: color }),
setLineType: (type) => set({ lineType: type }),
setLineWidth: (width) => set({ lineWidth: width }),
selectFeature: (id) => set({ selectedFeatureId: id }),
resetTool: () => set({
activeTool: 'select',
selectedFeatureId: null
}),
}))

39
src/stores/ui-store.ts Normal file
View File

@@ -0,0 +1,39 @@
import { create } from 'zustand'
export type SidebarTab = 'map' | 'journal'
export type ConnectionStatus = 'connected' | 'reconnecting' | 'offline'
interface UIStore {
sidebarOpen: boolean
sidebarTab: SidebarTab
activeModal: string | null
isEditing: boolean
connectionStatus: ConnectionStatus
// Actions
toggleSidebar: () => void
setSidebarOpen: (open: boolean) => void
setSidebarTab: (tab: SidebarTab) => void
openModal: (modal: string) => void
closeModal: () => void
setIsEditing: (editing: boolean) => void
setConnectionStatus: (status: ConnectionStatus) => void
}
export const useUIStore = create<UIStore>((set) => ({
sidebarOpen: true,
sidebarTab: 'map',
activeModal: null,
isEditing: false,
connectionStatus: 'offline',
toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
setSidebarOpen: (open) => set({ sidebarOpen: open }),
setSidebarTab: (tab) => set({ sidebarTab: tab }),
openModal: (modal) => set({ activeModal: modal }),
closeModal: () => set({ activeModal: null }),
setIsEditing: (editing) => set({ isEditing: editing }),
setConnectionStatus: (status) => set({ connectionStatus: status }),
}))