2026-05-29 14:04:42 +02:00

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: '',
},
}
);
};