// Dynamic SPA menu tree (reads from backend via window.WNW_NAV_TREE) export const NAV_TREE_VERSION = 'navTree-2025-10-28-dynamic'; export type NodeMode = 'spa' | 'bridge'; export type SubItem = { label: string; mode: NodeMode; path?: string; // for SPA routes href?: string; // for classic admin URLs exact?: boolean; }; export type MainKey = string; // Changed from union to string to support dynamic keys export type MainNode = { key: MainKey; label: string; path: string; // main path icon?: string; // lucide icon name children: SubItem[]; // will be frozen at runtime }; /** * Get navigation tree from backend (dynamic) * Falls back to static tree if backend data not available */ function getNavTreeFromBackend(): MainNode[] { const backendTree = (window as any).WNW_NAV_TREE; if (Array.isArray(backendTree) && backendTree.length > 0) { return backendTree; } // Fallback to static tree (for development/safety) return getStaticFallbackTree(); } /** * Static fallback tree (used if backend data not available) */ function getStaticFallbackTree(): MainNode[] { const admin = (window as any).wnw?.adminUrl ?? (window as any).woonoow?.adminUrl ?? '/wp-admin/admin.php'; return [ { key: 'dashboard', label: 'Dashboard', path: '/dashboard', icon: 'layout-dashboard', children: [ { label: 'Overview', mode: 'spa', path: '/dashboard', exact: true }, { label: 'Revenue', mode: 'spa', path: '/dashboard/revenue' }, { label: 'Orders', mode: 'spa', path: '/dashboard/orders' }, { label: 'Products', mode: 'spa', path: '/dashboard/products' }, { label: 'Customers', mode: 'spa', path: '/dashboard/customers' }, { label: 'Coupons', mode: 'spa', path: '/dashboard/coupons' }, { label: 'Taxes', mode: 'spa', path: '/dashboard/taxes' }, ], }, { key: 'orders', label: 'Orders', path: '/orders', icon: 'receipt-text', children: [], }, { key: 'products', label: 'Products', path: '/products', icon: 'package', children: [ { label: 'All products', mode: 'spa', path: '/products' }, { label: 'New', mode: 'spa', path: '/products/new' }, { label: 'Categories', mode: 'spa', path: '/products/categories' }, { label: 'Tags', mode: 'spa', path: '/products/tags' }, { label: 'Attributes', mode: 'spa', path: '/products/attributes' }, ], }, { key: 'coupons', label: 'Coupons', path: '/coupons', icon: 'tag', children: [ { label: 'All coupons', mode: 'spa', path: '/coupons' }, { label: 'New', mode: 'spa', path: '/coupons/new' }, ], }, { key: 'customers', label: 'Customers', path: '/customers', icon: 'users', children: [ { label: 'All customers', mode: 'spa', path: '/customers' }, ], }, { key: 'settings', label: 'Settings', path: '/settings', icon: 'settings', // Settings submenu available in all modes for consistent experience children: [ // WooNooW Settings { label: 'WooNooW', mode: 'spa' as const, path: '/settings' }, // Core Settings (Shopify-inspired) { label: 'Store Details', mode: 'spa' as const, path: '/settings/store' }, { label: 'Payments', mode: 'spa' as const, path: '/settings/payments' }, { label: 'Shipping & Delivery', mode: 'spa' as const, path: '/settings/shipping' }, { label: 'Taxes', mode: 'spa' as const, path: '/settings/taxes' }, { label: 'Checkout', mode: 'spa' as const, path: '/settings/checkout' }, { label: 'Customer Accounts', mode: 'spa' as const, path: '/settings/customers' }, { label: 'Notifications', mode: 'spa' as const, path: '/settings/notifications' }, { label: 'Brand & Appearance', mode: 'spa' as const, path: '/settings/brand' }, // Advanced (Bridge to WP Admin) { label: 'Advanced', mode: 'bridge' as const, href: `${admin}?page=wc-settings&tab=advanced` }, { label: 'Integrations', mode: 'bridge' as const, href: `${admin}?page=wc-settings&tab=integration` }, { label: 'System Status', mode: 'bridge' as const, href: `${admin}?page=wc-status` }, { label: 'Extensions', mode: 'bridge' as const, href: `${admin}?page=wc-addons` }, ], }, ]; } /** * Deep freeze tree for immutability */ function deepFreezeTree(src: MainNode[]): MainNode[] { return src.map((n) => Object.freeze({ ...n, children: Object.freeze([...(n.children ?? [])]), }) as MainNode ) as unknown as MainNode[]; } /** * Export the navigation tree (reads from backend, falls back to static) */ export const navTree: MainNode[] = Object.freeze( deepFreezeTree(getNavTreeFromBackend()) ) as unknown as MainNode[];