Spaces:
Paused
Paused
| import { useState, useEffect, useCallback } from 'react'; | |
| import { DashboardWidget } from '@/pages/Dashboard'; | |
| const PAGES_STORAGE_KEY = 'cyber-custom-pages'; | |
| export type PageType = 'dashboard' | 'static' | 'report'; | |
| export interface PageBlock { | |
| id: string; | |
| type: 'heading' | 'text' | 'image' | 'divider' | 'metric' | 'chart' | 'table'; | |
| content: any; | |
| } | |
| export interface CustomPage { | |
| id: string; | |
| slug: string; | |
| title: string; | |
| description?: string; | |
| type: PageType; | |
| icon?: string; | |
| widgets?: DashboardWidget[]; | |
| blocks?: PageBlock[]; | |
| createdAt: number; | |
| updatedAt: number; | |
| } | |
| const generateSlug = (title: string): string => { | |
| return title | |
| .toLowerCase() | |
| .replace(/[æ]/g, 'ae') | |
| .replace(/[ø]/g, 'oe') | |
| .replace(/[å]/g, 'aa') | |
| .replace(/[^a-z0-9]+/g, '-') | |
| .replace(/^-|-$/g, ''); | |
| }; | |
| export function useCustomPages() { | |
| const [pages, setPages] = useState<CustomPage[]>([]); | |
| useEffect(() => { | |
| const saved = localStorage.getItem(PAGES_STORAGE_KEY); | |
| if (saved) { | |
| try { | |
| setPages(JSON.parse(saved)); | |
| } catch (e) { | |
| console.error('Failed to load pages:', e); | |
| } | |
| } | |
| }, []); | |
| const savePages = useCallback((newPages: CustomPage[]) => { | |
| localStorage.setItem(PAGES_STORAGE_KEY, JSON.stringify(newPages)); | |
| setPages(newPages); | |
| }, []); | |
| const createPage = useCallback(( | |
| title: string, | |
| type: PageType, | |
| description?: string, | |
| icon?: string | |
| ): CustomPage => { | |
| const baseSlug = generateSlug(title); | |
| let slug = baseSlug; | |
| let counter = 1; | |
| // Ensure unique slug | |
| while (pages.some(p => p.slug === slug)) { | |
| slug = `${baseSlug}-${counter}`; | |
| counter++; | |
| } | |
| const newPage: CustomPage = { | |
| id: `page-${Date.now()}`, | |
| slug, | |
| title, | |
| description, | |
| type, | |
| icon, | |
| widgets: type === 'dashboard' ? [] : undefined, | |
| blocks: type !== 'dashboard' ? [] : undefined, | |
| createdAt: Date.now(), | |
| updatedAt: Date.now(), | |
| }; | |
| savePages([...pages, newPage]); | |
| return newPage; | |
| }, [pages, savePages]); | |
| const updatePage = useCallback((pageId: string, updates: Partial<CustomPage>) => { | |
| const updatedPages = pages.map(p => { | |
| if (p.id === pageId) { | |
| return { ...p, ...updates, updatedAt: Date.now() }; | |
| } | |
| return p; | |
| }); | |
| savePages(updatedPages); | |
| }, [pages, savePages]); | |
| const deletePage = useCallback((pageId: string) => { | |
| savePages(pages.filter(p => p.id !== pageId)); | |
| }, [pages, savePages]); | |
| const getPageBySlug = useCallback((slug: string): CustomPage | undefined => { | |
| return pages.find(p => p.slug === slug); | |
| }, [pages]); | |
| const getPageById = useCallback((id: string): CustomPage | undefined => { | |
| return pages.find(p => p.id === id); | |
| }, [pages]); | |
| return { | |
| pages, | |
| createPage, | |
| updatePage, | |
| deletePage, | |
| getPageBySlug, | |
| getPageById, | |
| }; | |
| } | |