Spaces:
Paused
Paused
| import { useState, useEffect, useCallback } from 'react'; | |
| import { DashboardWidget } from '@/pages/Dashboard'; | |
| const PRESETS_STORAGE_KEY = 'cyber-dashboard-presets'; | |
| const ACTIVE_PRESET_KEY = 'cyber-dashboard-active-preset'; | |
| export interface DashboardPreset { | |
| id: string; | |
| name: string; | |
| description?: string; | |
| widgets: DashboardWidget[]; | |
| createdAt: number; | |
| updatedAt: number; | |
| isBuiltIn?: boolean; | |
| } | |
| // Built-in presets | |
| const BUILT_IN_PRESETS: DashboardPreset[] = [ | |
| { | |
| id: 'default', | |
| name: 'Standard', | |
| description: 'Grundlæggende dashboard layout', | |
| widgets: [ | |
| { id: '1', type: 'news', name: 'News Feed', icon: 'Rss', size: 'medium' }, | |
| { id: '2', type: 'alerts', name: 'Active Alerts', icon: 'AlertTriangle', size: 'medium' }, | |
| { id: '3', type: 'metrics', name: 'Threat Metrics', icon: 'TrendingUp', size: 'small' }, | |
| { id: '4', type: 'radar', name: 'Threat Radar', icon: 'Radar', size: 'small' }, | |
| ], | |
| createdAt: 0, | |
| updatedAt: 0, | |
| isBuiltIn: true, | |
| }, | |
| { | |
| id: 'soc-analyst', | |
| name: 'SOC Analyst', | |
| description: 'Optimeret til sikkerhedsanalytikere', | |
| widgets: [ | |
| { id: '1', type: 'alerts', name: 'Active Alerts', icon: 'AlertTriangle', size: 'large' }, | |
| { id: '2', type: 'events', name: 'Real-Time Events', icon: 'Zap', size: 'medium' }, | |
| { id: '3', type: 'threatmap', name: 'Threat Map', icon: 'Map', size: 'medium' }, | |
| { id: '4', type: 'statistics', name: 'Statistics', icon: 'BarChart3', size: 'small' }, | |
| { id: '5', type: 'radar', name: 'Threat Radar', icon: 'Radar', size: 'small' }, | |
| ], | |
| createdAt: 0, | |
| updatedAt: 0, | |
| isBuiltIn: true, | |
| }, | |
| { | |
| id: 'executive', | |
| name: 'Executive', | |
| description: 'Overblik for ledelsen', | |
| widgets: [ | |
| { id: '1', type: 'metrics', name: 'Threat Metrics', icon: 'TrendingUp', size: 'large' }, | |
| { id: '2', type: 'global', name: 'Global Threats', icon: 'Globe', size: 'medium' }, | |
| { id: '3', type: 'statistics', name: 'Statistics', icon: 'BarChart3', size: 'medium' }, | |
| { id: '4', type: 'trends', name: 'Trend Analysis', icon: 'LineChart', size: 'medium' }, | |
| ], | |
| createdAt: 0, | |
| updatedAt: 0, | |
| isBuiltIn: true, | |
| }, | |
| { | |
| id: 'minimal', | |
| name: 'Minimal', | |
| description: 'Kun det vigtigste', | |
| widgets: [ | |
| { id: '1', type: 'alerts', name: 'Active Alerts', icon: 'AlertTriangle', size: 'large' }, | |
| { id: '2', type: 'metrics', name: 'Threat Metrics', icon: 'TrendingUp', size: 'medium' }, | |
| ], | |
| createdAt: 0, | |
| updatedAt: 0, | |
| isBuiltIn: true, | |
| }, | |
| ]; | |
| export function useDashboardPresets() { | |
| const [presets, setPresets] = useState<DashboardPreset[]>([]); | |
| const [activePresetId, setActivePresetId] = useState<string | null>(null); | |
| // Load presets from localStorage | |
| useEffect(() => { | |
| const savedPresets = localStorage.getItem(PRESETS_STORAGE_KEY); | |
| const savedActiveId = localStorage.getItem(ACTIVE_PRESET_KEY); | |
| let userPresets: DashboardPreset[] = []; | |
| if (savedPresets) { | |
| try { | |
| userPresets = JSON.parse(savedPresets); | |
| } catch (e) { | |
| console.error('Failed to load presets:', e); | |
| } | |
| } | |
| // Combine built-in and user presets | |
| setPresets([...BUILT_IN_PRESETS, ...userPresets]); | |
| setActivePresetId(savedActiveId || null); | |
| }, []); | |
| // Save user presets to localStorage | |
| const savePresets = useCallback((allPresets: DashboardPreset[]) => { | |
| const userPresets = allPresets.filter(p => !p.isBuiltIn); | |
| localStorage.setItem(PRESETS_STORAGE_KEY, JSON.stringify(userPresets)); | |
| setPresets(allPresets); | |
| }, []); | |
| const setActivePreset = useCallback((presetId: string | null) => { | |
| setActivePresetId(presetId); | |
| if (presetId) { | |
| localStorage.setItem(ACTIVE_PRESET_KEY, presetId); | |
| } else { | |
| localStorage.removeItem(ACTIVE_PRESET_KEY); | |
| } | |
| }, []); | |
| const createPreset = useCallback((name: string, widgets: DashboardWidget[], description?: string): DashboardPreset => { | |
| const newPreset: DashboardPreset = { | |
| id: `preset-${Date.now()}`, | |
| name, | |
| description, | |
| widgets: widgets.map((w, i) => ({ ...w, id: `${w.type}-${i}` })), | |
| createdAt: Date.now(), | |
| updatedAt: Date.now(), | |
| isBuiltIn: false, | |
| }; | |
| const updatedPresets = [...presets, newPreset]; | |
| savePresets(updatedPresets); | |
| return newPreset; | |
| }, [presets, savePresets]); | |
| const updatePreset = useCallback((presetId: string, widgets: DashboardWidget[], name?: string, description?: string) => { | |
| const updatedPresets = presets.map(p => { | |
| if (p.id === presetId && !p.isBuiltIn) { | |
| return { | |
| ...p, | |
| name: name ?? p.name, | |
| description: description ?? p.description, | |
| widgets: widgets.map((w, i) => ({ ...w, id: `${w.type}-${i}` })), | |
| updatedAt: Date.now(), | |
| }; | |
| } | |
| return p; | |
| }); | |
| savePresets(updatedPresets); | |
| }, [presets, savePresets]); | |
| const deletePreset = useCallback((presetId: string) => { | |
| const preset = presets.find(p => p.id === presetId); | |
| if (preset?.isBuiltIn) return false; | |
| const updatedPresets = presets.filter(p => p.id !== presetId); | |
| savePresets(updatedPresets); | |
| if (activePresetId === presetId) { | |
| setActivePreset(null); | |
| } | |
| return true; | |
| }, [presets, activePresetId, savePresets, setActivePreset]); | |
| const getPreset = useCallback((presetId: string): DashboardPreset | undefined => { | |
| return presets.find(p => p.id === presetId); | |
| }, [presets]); | |
| const loadPreset = useCallback((presetId: string): DashboardWidget[] | null => { | |
| const preset = getPreset(presetId); | |
| if (!preset) return null; | |
| setActivePreset(presetId); | |
| // Return new widget instances with fresh IDs | |
| return preset.widgets.map((w, i) => ({ ...w, id: `${w.type}-${Date.now()}-${i}` })); | |
| }, [getPreset, setActivePreset]); | |
| const activePreset = activePresetId ? getPreset(activePresetId) : null; | |
| return { | |
| presets, | |
| activePreset, | |
| activePresetId, | |
| createPreset, | |
| updatePreset, | |
| deletePreset, | |
| loadPreset, | |
| getPreset, | |
| setActivePreset, | |
| }; | |
| } | |