mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
200 lines
6.8 KiB
TypeScript
200 lines
6.8 KiB
TypeScript
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<string>(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<Record<string, string>>({});
|
|
const [visibility, setVisibility] = useState<Record<string, boolean>>({});
|
|
const [styles, setStyles] = useState<Record<string, Record<string, any>>>({});
|
|
const [elementOrder, setElementOrder] = useState<string[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [refreshKey, setRefreshKey] = useState<number>(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<string, HTMLElement>();
|
|
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<string, string> = {};
|
|
const visMap: Record<string, boolean> = {};
|
|
|
|
// 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<string, any> | undefined => {
|
|
return styles[elementName];
|
|
};
|
|
|
|
return { configs, visibility, styles, elementOrder, getVariant, isVisible, getStyles, loading, refreshKey };
|
|
};
|