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:
69
src/stores/project-store.ts
Normal file
69
src/stores/project-store.ts
Normal 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
39
src/stores/tool-store.ts
Normal 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
39
src/stores/ui-store.ts
Normal 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 }),
|
||||
}))
|
||||
Reference in New Issue
Block a user