import { useState, useEffect } from 'react'; import { PageElementConfig, getPageElementConfigs } from '../services/pageElements'; export const usePageElementConfig = (pageType: string, elementName: string, defaultVariant: string = 'unified') => { const [variant, setVariant] = useState(defaultVariant); const [loading, setLoading] = useState(true); useEffect(() => { let active = true; const loadConfig = async () => { try { const configs = await getPageElementConfigs(pageType); if (active) { const config = configs.find(c => c.element_name === elementName); if (config) { setVariant(config.variant); } } } catch (error) { console.error(`Failed to load config for ${elementName}:`, error); } finally { if (active) { setLoading(false); } } }; loadConfig(); return () => { active = false; }; }, [pageType, elementName, defaultVariant]); return { variant, loading }; }; export const useAllPageElementConfigs = (pageType: string) => { const [configs, setConfigs] = useState>({}); const [visibility, setVisibility] = useState>({}); const [styles, setStyles] = useState>>({}); const [elementOrder, setElementOrder] = useState([]); const [loading, setLoading] = useState(true); const [refreshKey, setRefreshKey] = useState(0); useEffect(() => { let active = true; // Helper function to apply DOM order const applyDOMOrder = (order: string[]) => { // Check if MyUIbrix viewport wrapper is active const viewportWrapper = document.querySelector('.myuibrix-viewport-wrapper'); const container = viewportWrapper || document.querySelector('.container'); if (!container) return; const sections = Array.from(container.querySelectorAll('[data-element]')) as HTMLElement[]; const elementMap = new Map(); sections.forEach(section => { const elementName = section.getAttribute('data-element'); if (elementName) { elementMap.set(elementName, section); } }); order.forEach((elementName) => { const element = elementMap.get(elementName); if (element && element.parentElement === container) { container.appendChild(element); } }); }; const loadConfigs = async () => { try { const data = await getPageElementConfigs(pageType); if (active) { const configMap: Record = {}; const visMap: Record = {}; // Sort by display_order to get correct element order const sorted = [...data].sort((a, b) => (a.display_order || 0) - (b.display_order || 0)); const order = sorted.map(config => config.element_name); sorted.forEach(config => { configMap[config.element_name] = config.variant; visMap[config.element_name] = config.visible !== false; }); setConfigs(configMap); setVisibility(visMap); setElementOrder(order); // Apply initial order to DOM only in editor/preview mode const isEditingMode = (() => { try { if (typeof document !== 'undefined' && (document.body?.classList?.contains('myuibrix-edit-mode'))) return true; const params = new URLSearchParams(window.location.search); return params.get('myuibrix') === 'edit'; } catch { return false; } })(); if (order.length > 0 && isEditingMode) { requestAnimationFrame(() => { applyDOMOrder(order); }); } } } catch (error) { console.error('Failed to load page element configs:', error); } finally { if (active) { setLoading(false); } } }; loadConfigs(); // Listen for live updates from MyUIbrix editor (ONLY in preview mode) const handleMyUIbrixChange = ((event: CustomEvent) => { const { elementName, variant, visible, previewMode, timestamp } = event.detail; // Only apply changes if in preview mode (editing) // This prevents production users from seeing draft changes if (previewMode) { console.log(`[usePageElementConfig] Variant change: ${elementName} -> ${variant}`); setConfigs(prev => ({ ...prev, [elementName]: variant })); setVisibility(prev => ({ ...prev, [elementName]: visible })); // Force React to re-render by incrementing refresh key setRefreshKey(prev => prev + 1); } }) as EventListener; // Listen for reorder events const handleMyUIbrixReorder = ((event: CustomEvent) => { const { order } = event.detail; setElementOrder(order); try { const inEdit = document.body?.classList?.contains('myuibrix-edit-mode') || false; if (inEdit) { applyDOMOrder(order); } } catch { // no-op } }) as EventListener; // Listen for style changes from VisualStylePanel const handleMyUIbrixStyleChange = ((event: CustomEvent) => { const { elementName, styles: newStyles, previewMode } = event.detail; if (previewMode) { // Only update state - let React apply the styles through component rendering // This prevents conflicts with React's virtual DOM setStyles(prev => ({ ...prev, [elementName]: newStyles })); } }) as EventListener; window.addEventListener('myuibrix-change', handleMyUIbrixChange); window.addEventListener('myuibrix-reorder', handleMyUIbrixReorder); window.addEventListener('myuibrix-style-change', handleMyUIbrixStyleChange); return () => { active = false; window.removeEventListener('myuibrix-change', handleMyUIbrixChange); window.removeEventListener('myuibrix-reorder', handleMyUIbrixReorder); window.removeEventListener('myuibrix-style-change', handleMyUIbrixStyleChange); }; }, [pageType]); const getVariant = (elementName: string, defaultVariant: string = 'unified'): string => { return configs[elementName] || defaultVariant; }; const isVisible = (elementName: string, defaultVisible: boolean = true): boolean => { return visibility[elementName] !== undefined ? visibility[elementName] : defaultVisible; }; const getStyles = (elementName: string): Record | undefined => { return styles[elementName]; }; return { configs, visibility, styles, elementOrder, getVariant, isVisible, getStyles, loading, refreshKey }; };