270 lines
5.4 KiB
TypeScript
270 lines
5.4 KiB
TypeScript
import {
|
|
ElementSettings,
|
|
ElementType,
|
|
UiElementItem,
|
|
UiElementRow,
|
|
} from './types';
|
|
|
|
export const UI_ELEMENT_TYPES: ElementType[] = [
|
|
'nav_button',
|
|
'spot',
|
|
'description',
|
|
'gallery',
|
|
'carousel',
|
|
'logo',
|
|
'video_player',
|
|
'popup',
|
|
];
|
|
|
|
export const toElementLabel = (value: string) =>
|
|
value
|
|
.split('_')
|
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
.join(' ');
|
|
|
|
const defaultSettingsByType: Record<string, ElementSettings> = {
|
|
nav_button: {
|
|
style: {
|
|
color: '#ffffff',
|
|
backgroundColor: '#2563eb',
|
|
border: '1px solid #1d4ed8',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 16,
|
|
heightPercent: 8,
|
|
xPercent: 10,
|
|
yPercent: 10,
|
|
},
|
|
content: {
|
|
icon: 'mdiArrowRight',
|
|
title: 'Action',
|
|
placeholder: '',
|
|
text: 'Open',
|
|
},
|
|
},
|
|
spot: {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#fde68a',
|
|
border: '1px solid #f59e0b',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 14,
|
|
heightPercent: 8,
|
|
xPercent: 20,
|
|
yPercent: 20,
|
|
},
|
|
content: {
|
|
icon: 'mdiMapMarker',
|
|
title: 'Spot',
|
|
placeholder: '',
|
|
text: 'Important point',
|
|
},
|
|
},
|
|
description: {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#f3f4f6',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 28,
|
|
heightPercent: 16,
|
|
xPercent: 30,
|
|
yPercent: 22,
|
|
},
|
|
content: {
|
|
icon: 'mdiText',
|
|
title: 'Description',
|
|
placeholder: 'Enter description',
|
|
text: 'Description text',
|
|
},
|
|
},
|
|
gallery: {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#ffffff',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 32,
|
|
heightPercent: 20,
|
|
xPercent: 12,
|
|
yPercent: 40,
|
|
},
|
|
content: {
|
|
icon: 'mdiImageMultiple',
|
|
title: 'Gallery',
|
|
placeholder: 'Image URL',
|
|
text: '3 images',
|
|
},
|
|
},
|
|
carousel: {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#ffffff',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 34,
|
|
heightPercent: 20,
|
|
xPercent: 24,
|
|
yPercent: 46,
|
|
},
|
|
content: {
|
|
icon: 'mdiViewCarousel',
|
|
title: 'Carousel',
|
|
placeholder: 'Slide title',
|
|
text: 'Slide 1',
|
|
},
|
|
},
|
|
logo: {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#ffffff',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 14,
|
|
heightPercent: 10,
|
|
xPercent: 72,
|
|
yPercent: 10,
|
|
},
|
|
content: {
|
|
icon: 'mdiImage',
|
|
title: 'Logo',
|
|
placeholder: 'Brand name',
|
|
text: 'Brand',
|
|
},
|
|
},
|
|
video_player: {
|
|
style: {
|
|
color: '#ffffff',
|
|
backgroundColor: '#111827',
|
|
border: '1px solid #111827',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 42,
|
|
heightPercent: 28,
|
|
xPercent: 12,
|
|
yPercent: 58,
|
|
},
|
|
content: {
|
|
icon: 'mdiPlayCircle',
|
|
title: 'Video',
|
|
placeholder: 'Video URL',
|
|
text: 'Play video',
|
|
},
|
|
},
|
|
popup: {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#ffffff',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 30,
|
|
heightPercent: 18,
|
|
xPercent: 52,
|
|
yPercent: 34,
|
|
},
|
|
content: {
|
|
icon: 'mdiOpenInNew',
|
|
title: 'Popup',
|
|
placeholder: 'Popup title',
|
|
text: 'Popup content',
|
|
},
|
|
},
|
|
};
|
|
|
|
const parseJsonObject = (value?: string): Record<string, any> => {
|
|
if (!value) return {};
|
|
|
|
try {
|
|
const parsed = JSON.parse(value);
|
|
return typeof parsed === 'object' && parsed !== null ? parsed : {};
|
|
} catch {
|
|
return {};
|
|
}
|
|
};
|
|
|
|
export const normalizeUiElement = (row: UiElementRow): UiElementItem => {
|
|
const defaults = defaultSettingsByType[row.element_type] || {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#ffffff',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 20,
|
|
heightPercent: 10,
|
|
xPercent: 0,
|
|
yPercent: 0,
|
|
},
|
|
content: {
|
|
icon: 'mdiShape',
|
|
title: toElementLabel(row.element_type),
|
|
placeholder: '',
|
|
text: row.name || '',
|
|
},
|
|
};
|
|
const parsedSettings = parseJsonObject(row.settings_json);
|
|
|
|
return {
|
|
id: row.id,
|
|
elementType: row.element_type,
|
|
name: row.name || toElementLabel(row.element_type),
|
|
sortOrder: Number(row.sort_order ?? 0),
|
|
settings: {
|
|
style: {
|
|
...defaults.style,
|
|
...(parsedSettings.style || {}),
|
|
},
|
|
layout: {
|
|
...defaults.layout,
|
|
...(parsedSettings.layout || {}),
|
|
},
|
|
content: {
|
|
...defaults.content,
|
|
...(parsedSettings.content || {}),
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
export const getDefaultSettings = (
|
|
elementType: ElementType,
|
|
): ElementSettings => {
|
|
return (
|
|
defaultSettingsByType[elementType] || {
|
|
style: {
|
|
color: '#111827',
|
|
backgroundColor: '#ffffff',
|
|
border: '1px solid #d1d5db',
|
|
},
|
|
layout: {
|
|
position: 'absolute',
|
|
widthPercent: 20,
|
|
heightPercent: 10,
|
|
xPercent: 0,
|
|
yPercent: 0,
|
|
},
|
|
content: {
|
|
icon: 'mdiShape',
|
|
title: toElementLabel(elementType),
|
|
placeholder: '',
|
|
text: '',
|
|
},
|
|
}
|
|
);
|
|
};
|