Feat: adjustable superscript index, loyalty badges, centered unit price, global badge apply, brevo url fix
This commit is contained in:
1 parent
245e3f8471
commit
4e4e5e5af3
10 files changed
+539
-290
No files matched your search
+13
-158
@@ -1,159 +1,7 @@
|
||||
import { BadgeTemplate, BadgeLayer } from '@/types/newsletter';
|
||||
|
||||
export const DEFAULT_BADGE_TEMPLATES: BadgeTemplate[] = [
|
||||
{
|
||||
id: 'badge-preset-yellow-akcia',
|
||||
name: 'COOP Akcia (Žltá)',
|
||||
svgRaw: `<svg width="140" height="95" viewBox="0 0 140 95" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="140" height="95" rx="14" fill="#ffd100"/>
|
||||
<rect x="15" y="8" width="110" height="24" rx="6" fill="#e2001a"/>
|
||||
</svg>`,
|
||||
width: 110,
|
||||
align: 'center',
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
layersConfig: [
|
||||
{
|
||||
id: 'l-akcia-1',
|
||||
type: 'text',
|
||||
text: 'AKCIA',
|
||||
x: 70,
|
||||
y: 20,
|
||||
fontSize: 14,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Poppins',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
id: 'l-akcia-2',
|
||||
type: 'text',
|
||||
text: '{cena}',
|
||||
x: 70,
|
||||
y: 62,
|
||||
fontSize: 42,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Arial Narrow',
|
||||
fill: '#001a33',
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'badge-preset-red-zlava',
|
||||
name: 'COOP Zľava (Červená)',
|
||||
svgRaw: `<svg width="140" height="95" viewBox="0 0 140 95" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="140" height="95" rx="14" fill="#e2001a"/>
|
||||
<rect x="12" y="8" width="116" height="22" rx="5" fill="#ffffff" fill-opacity="0.2"/>
|
||||
</svg>`,
|
||||
width: 110,
|
||||
align: 'center',
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
layersConfig: [
|
||||
{
|
||||
id: 'l-zlava-1',
|
||||
type: 'text',
|
||||
text: 'ZĽAVA -{zlava}',
|
||||
x: 70,
|
||||
y: 19,
|
||||
fontSize: 13,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Poppins',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
id: 'l-zlava-2',
|
||||
type: 'text',
|
||||
text: '{cena}',
|
||||
x: 70,
|
||||
y: 62,
|
||||
fontSize: 42,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Arial Narrow',
|
||||
fill: '#ffd100',
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'badge-preset-blue-supercena',
|
||||
name: 'Super Cena (Tmavomodrá)',
|
||||
svgRaw: `<svg width="140" height="95" viewBox="0 0 140 95" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="140" height="95" rx="14" fill="#001a33"/>
|
||||
<rect x="0" y="0" width="140" height="30" rx="14" fill="#003399"/>
|
||||
</svg>`,
|
||||
width: 110,
|
||||
align: 'center',
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
layersConfig: [
|
||||
{
|
||||
id: 'l-super-1',
|
||||
type: 'text',
|
||||
text: 'SUPER CENA',
|
||||
x: 70,
|
||||
y: 16,
|
||||
fontSize: 13,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Poppins',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
id: 'l-super-2',
|
||||
type: 'text',
|
||||
text: '{cena}',
|
||||
x: 70,
|
||||
y: 62,
|
||||
fontSize: 42,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Arial Narrow',
|
||||
fill: '#ffd100',
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'badge-preset-green-cerstve',
|
||||
name: 'Bio & Čerstvé (Zelená)',
|
||||
svgRaw: `<svg width="140" height="95" viewBox="0 0 140 95" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="140" height="95" rx="14" fill="#005239"/>
|
||||
<rect x="15" y="8" width="110" height="22" rx="6" fill="#003d2b"/>
|
||||
</svg>`,
|
||||
width: 110,
|
||||
align: 'center',
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
layersConfig: [
|
||||
{
|
||||
id: 'l-green-1',
|
||||
type: 'text',
|
||||
text: 'ČERSTVÉ',
|
||||
x: 70,
|
||||
y: 19,
|
||||
fontSize: 13,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Poppins',
|
||||
fill: '#a3e635',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
id: 'l-green-2',
|
||||
type: 'text',
|
||||
text: '{cena}',
|
||||
x: 70,
|
||||
y: 62,
|
||||
fontSize: 42,
|
||||
fontWeight: '900',
|
||||
fontFamily: 'Arial Narrow',
|
||||
fill: '#ffffff',
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
// Vymazané všetky preddefinované šablóny — v systéme sú výhradne vlastné cenovky vytvorené používateľom
|
||||
export const DEFAULT_BADGE_TEMPLATES: BadgeTemplate[] = [];
|
||||
|
||||
export interface BadgeProductData {
|
||||
priceMain: string;
|
||||
@@ -224,7 +72,10 @@ export function renderCleanBadgeSvg(
|
||||
const textLayersSvg = (template.layersConfig || []).map((layer) => {
|
||||
const rawText = layer.text || '';
|
||||
const fontSize = layer.fontSize || 16;
|
||||
const subFontSize = Math.max(10, Math.round(fontSize * 0.55));
|
||||
const subFontSize = layer.indexFontSize || Math.max(10, Math.round(fontSize * 0.55));
|
||||
const subDy = layer.indexOffsetY !== undefined ? `${layer.indexOffsetY}px` : '-0.45em';
|
||||
const subDx = layer.indexOffsetX !== undefined ? `${layer.indexOffsetX}px` : '1px';
|
||||
const revertDy = layer.indexOffsetY !== undefined ? `${-layer.indexOffsetY}px` : '0.45em';
|
||||
const fontWeight = layer.fontWeight || '700';
|
||||
const fill = layer.fill || '#ffffff';
|
||||
const fontFamily = layer.fontFamily
|
||||
@@ -235,17 +86,21 @@ export function renderCleanBadgeSvg(
|
||||
if (layer.align === 'left') anchor = 'start';
|
||||
if (layer.align === 'right') anchor = 'end';
|
||||
|
||||
// Formátovanie textu: ak obsahuje {cena}, centy vložíme do <tspan> ako horný index
|
||||
// Formátovanie textu: ak obsahuje {cena} alebo {centy}, centy vložíme do <tspan> ako horný index
|
||||
let contentSvg = '';
|
||||
if (rawText.includes('{cena}')) {
|
||||
const parts = rawText.split('{cena}');
|
||||
const before = escapeXml(parts[0] || '');
|
||||
const after = escapeXml(parts[1] || '');
|
||||
contentSvg = `${before}${escapeXml(pMain)}<tspan font-size="${subFontSize}px" dy="-0.45em" font-weight="${fontWeight}">${escapeXml(pSub)}</tspan><tspan dy="0.45em">${after}</tspan>`;
|
||||
contentSvg = `${before}${escapeXml(pMain)}<tspan font-size="${subFontSize}px" dx="${subDx}" dy="${subDy}" font-weight="${fontWeight}">${escapeXml(pSub)}</tspan>${after ? `<tspan dy="${revertDy}">${after}</tspan>` : ''}`;
|
||||
} else if (rawText.includes('{centy}')) {
|
||||
const parts = rawText.split('{centy}');
|
||||
const before = escapeXml(parts[0] || '');
|
||||
const after = escapeXml(parts[1] || '');
|
||||
contentSvg = `${before}<tspan font-size="${subFontSize}px" dx="${subDx}" dy="${subDy}" font-weight="${fontWeight}">${escapeXml(pSub)}</tspan>${after ? `<tspan dy="${revertDy}">${after}</tspan>` : ''}`;
|
||||
} else {
|
||||
let replaced = rawText
|
||||
.replace(/{cela_suma}/g, pMain)
|
||||
.replace(/{centy}/g, pSub)
|
||||
.replace(/{zlava}/g, discount)
|
||||
.replace(/{jednotkova_cena}/g, unitPrice)
|
||||
.replace(/{mena}/g, '€');
|
||||
|
||||
Reference in new issue
Block a user